""" Running backup actions """
+import os
import logging as log
from backupninja import config
"""
log.info('Running all actions')
try:
- actions = config.list_actions(opts)
+ action_configs = config.list_actions(opts)
except OSError, e:
log.critical('Unable to list actions: %s', e)
return
- actions.sort()
+ action_configs.sort()
- for action in actions:
- run_action(action, opts, global_config)
+ for action_config in action_configs:
+ run_action(action_config, opts, global_config)
-def run_action(action, opts, global_config):
+def run_action(action_config, opts, global_config):
"""
- Run a single action. opts are the parsed commandline options,
+ Run a single action. action_config is the full path to its
+ configuration file. opts are the parsed commandline options,
global_config is the parsed global configuration.
"""
- log.info('Running action "%s"', action)
# Split the action filename
- parts = action.split('.')
+ parts = os.path.basename(action_config).split('.')
if (len(parts) != 2):
- log.error('Invalid action filename: "%s". Should be in the form name.type, where type is a valid handler.' % action)
+ log.error('Invalid action filename: "%s". Should be in the form name.type, where type is a valid handler.' % action_config)
return
(action_name, action_ty) = parts
-
- # Get the config for this action
- action_config = config.get_action_config(opts, action)
+ log.info('Running action "%s.%s"', action_name, action_ty)
try:
# Create a handler for this action
- handler = handlers.create_handler(action_ty, action_config)
+ handler = handlers.create_handler(action_ty)
+ # Let the handler load its configuration file
+ handler.load_config(action_config)
# Run it
handler.run(test=opts.test)
handler.finish(test=opts.test)
except Exception, e:
- log.error('Running action "%s" failed: %s', action, e)
+ log.error('Running action "%s.%s" failed: %s', action_name, action_ty, e)
import traceback
log.debug(traceback.format_exc())
import os, ConfigParser
+# Defaults for global configuration values
+default_global_config = {}
import logging as log
opts are the parsed commandline options.
"""
global_config = os.path.join(opts.config_dir, opts.global_config)
- return _load_config(global_config)
-
-def get_action_config(opts, action):
- """
- Returns the configuration for the named action, in a
- SafeConfigParser object. If the configuration file can not be found,
- logs an error and returns None.
-
- opts are the parsed commandline options.
- """
- actions_dir = os.path.join(opts.config_dir, opts.actions_dir)
- return _load_config(os.path.join(actions_dir, action))
+ return load_config(global_config, default_global_config)
def list_actions(opts):
"""
Lists all actions defined in the configuration directory. Returns a
- list of action names that can be passed to get_action_config.
+ list of full paths to action configuration files.
+
opts are the parsed commandline options.
"""
actions_dir = os.path.join(opts.config_dir, opts.actions_dir)
- return [f for f in os.listdir(actions_dir) if not f.startswith('.')]
+ return [os.path.join(actions_dir, f)
+ for f in os.listdir(actions_dir)
+ if not f.startswith('.')]
-def _load_config(filename):
+def load_config(filename, defaults):
+ """
+ Load a configuration file, using the given default values.
+
+ The defaults argument contains a dictionary of sections. Each key is
+ a section name, each value is a dictionary of values (where the key
+ is the value name and the value is the actual value).
+ """
# Open a file and read it
config = ConfigParser.SafeConfigParser()
+ _set_default_config(config, defaults)
log.debug('Reading config file "%s"', filename)
try:
file = open(filename, 'r')
config.readfp(file)
return config
+
+def _set_default_config(parser, values):
+ """
+ Saves the values given to the ConfigParser given. This can be used
+ to store a set of default values to a ConfigParser before loading a
+ file (The defaults argument to the ConfigParser constructor only
+ sets the values of the "DEFAULT" section).
+
+ The values argument contains a dictionary of sections. Each key is a
+ section name, each value is a dictionary of values (where the key is
+ the value name and the value is the actual value).
+ """
+ for section, options in values.items():
+ if not parser.has_section(section):
+ parser.add_section(section)
+ for option, value in options.items():
+ parser.set(section, option, value)
import sys
import logging as log
+from backupninja import config
+
class Handler(object):
- def __init__(self, conf):
- self.conf = conf
+ def __init__(self):
+ # Subclasses should overwrite this with their default config
+ # See backupninja.config.load_config for the structure of this
+ # value.
+ self.default_config = {}
def run(self, **kwargs):
"""
"""
pass
-def create_handler(ty, conf):
+ def load_config(self, filename):
+ """
+ Load the configuration for this action from the given filename.
+ """
+ self.conf = config.load_config(filename, self.default_config)
+
+
+
+def create_handler(ty):
"""
Create a new (subclass of) Handler object for an action with the
- given type. conf is the configuration to pass to the handler.
+ given type.
If the handler cannot be loaded, an exception is thrown.
"""
% (module.__file__))
# Call the "handler" function to create the actual handler
- handler = module.handler(conf)
+ handler = module.handler()
# Check if the handler returned is really a subclass of Handler
if not isinstance(handler, Handler):