bin/pvl.backup-snapshot
changeset 55 95c86df4807a
parent 53 f17c2733417a
child 57 52a4be76e85a
equal deleted inserted replaced
54:12fbf099be99 55:95c86df4807a
    13 from pvl.backup import __version__
    13 from pvl.backup import __version__
    14 from pvl.backup import rsync, invoke
    14 from pvl.backup import rsync, invoke
    15 
    15 
    16 import optparse, ConfigParser
    16 import optparse, ConfigParser
    17 import os, os.path, stat
    17 import os, os.path, stat
    18 import shutil
    18 import shutil, glob
    19 import datetime
    19 import datetime
    20 import logging
    20 import logging
    21 
    21 
    22 log = logging.getLogger()
    22 log = logging.getLogger()
    23 
    23 
    71 
    71 
    72     parser.add_option('-n', '--dry-run',    action='store_true',
    72     parser.add_option('-n', '--dry-run',    action='store_true',
    73         help="Don't actually clean anything")
    73         help="Don't actually clean anything")
    74 
    74 
    75     #
    75     #
    76     parser.add_option('-c', '--config',     metavar='FILE',
    76     parser.add_option('-c', '--config',     metavar='FILE/DIR', action='append',    # multi
    77         help="Load configuration file")
    77         help="Load configuration file(s)")
    78 
    78 
    79     parser.add_option('-r', '--run',        metavar='NAME',
    79     parser.add_option('-r', '--run',        metavar='NAME',
    80         help="Run given set of targets, per config [run/...]")
    80         help="Run given set of targets, per config [run/...]")
    81 
    81 
    82     #
    82     #
    91 
    91 
    92 
    92 
    93     # defaults
    93     # defaults
    94     parser.set_defaults(
    94     parser.set_defaults(
    95         loglevel            = logging.INFO,
    95         loglevel            = logging.INFO,
    96 
    96         
       
    97         config              = [],
    97         target_intervals    = [],
    98         target_intervals    = [],
    98     )
    99     )
    99     parser.set_defaults(**defaults)
   100     parser.set_defaults(**defaults)
   100 
   101 
   101     
   102     
   130 
   131 
   131     return name.replace('-', '_')
   132     return name.replace('-', '_')
   132 
   133 
   133 def parse_config (path, defaults) :
   134 def parse_config (path, defaults) :
   134     """
   135     """
   135         Parse given config file
   136         Parse given config file, returning updated set of configs based on given defaults.
   136     """
   137     """
   137 
   138 
   138     log.debug("loading config: %s", path)
   139     log.debug("loading config: %s", path)
   139 
   140 
   140     config = dict(defaults)
   141     config = dict(defaults)
   699         if target not in options.targets :
   700         if target not in options.targets :
   700             raise ConfigError("Unknown [target/{target}] in [run/{run}]".format(target=target, run=run))
   701             raise ConfigError("Unknown [target/{target}] in [run/{run}]".format(target=target, run=run))
   701 
   702 
   702         yield target
   703         yield target
   703 
   704 
       
   705 def load_configs (configs, confglob='*.conf') :
       
   706     """
       
   707         Load configuration files from given list of config paths; supports loading a conf.d
       
   708     """
       
   709 
       
   710     for path in configs :
       
   711         log.debug("%s", path)
       
   712 
       
   713         if os.path.isdir(path) :
       
   714             # glob dir: $path/$glob
       
   715             for globpath in glob.glob(os.path.join(path, confglob)) :
       
   716                 if os.path.exists(globpath) :
       
   717                     yield globpath
       
   718                 else :
       
   719                     raise Exception("Globbed file does not exist: {0}".format(globpath))
       
   720 
       
   721         elif os.path.isfile(path) :
       
   722             # normal file
       
   723             yield path
       
   724 
       
   725         elif os.path.exists(path) :
       
   726             raise Exception("Unrecognized config file type: {0}".format(path))
       
   727 
       
   728         else :
       
   729             raise Exception("Given config file does not exist: {0}".format(path))
       
   730 
   704 def run (options, run_targets) :
   731 def run (options, run_targets) :
   705     # default config
   732     # default config
   706     config = dict(
   733     config = dict(
   707         rsync_options   = {},
   734         rsync_options   = {},
   708         intervals       = {},
   735         intervals       = {},
   709         targets         = {},
   736         targets         = {},
   710     )
   737     )
   711 
   738     
   712     if options.config :
   739     # config?
       
   740     for path in load_configs(options.config) :
   713         # load
   741         # load
   714         try :
   742         try :
   715             config = parse_config(options.config, config)
   743             config = parse_config(path, config)
   716         except ConfigError as e:
   744         except ConfigError as e:
   717             log.error("Configuration error: %s: %s", options.config, e)
   745             log.error("Configuration error: %s: %s", path, e)
   718             return 2
   746             return 2
   719 
   747 
   720     # targets to run
   748     # targets to run
   721     options.targets = {}
   749     options.targets = {}
   722  
   750