command = ' '.join(command)
return "Can't execute command %s: %s" % (command, self.error)
+class ParameterError(Error, KeyError):
+ r"""
+ ParameterError(paramname) -> ParameterError instance
+
+ This is the base exception for all DhcpHandler parameters related errors.
+ """
+
+ def __init__(self, paramname):
+ r"Initialize the object. See class documentation for more info."
+ self.message = 'Parameter error: "%s"' % paramname
+
+class ParameterNotFoundError(ParameterError):
+ r"""
+ ParameterNotFoundError(hostname) -> ParameterNotFoundError instance
+
+ This exception is raised when trying to operate on a parameter that doesn't
+ exists.
+ """
+
+ def __init__(self, paramname):
+ r"Initialize the object. See class documentation for more info."
+ self.message = 'Parameter not found: "%s"' % paramname
+
def call(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=True, universal_newlines=True,
**kw):
if r is not 0:
raise ExecutionError(command, ReturnNot0Error(r))
-class ServiceHandler(Handler):
- r"""ServiceHandler([start[, stop[, restart[, reload]]]]) -> ServiceHandler.
-
- This is a helper class to inherit from to automatically handle services
- with start, stop, restart, reload actions.
-
- The actions can be defined by calling the constructor with all the
- parameters or in a more declarative way as class attributes, like:
-
- class TestHandler(ServiceHandler):
- _service_start = ('command', 'start')
- _service_stop = ('command', 'stop')
- _service_restart = ('command', 'restart')
- _service_reload = 'reload-command'
-
- Commands are executed without using the shell, that's why they are specified
- as tuples (where the first element is the command and the others are the
- command arguments). If only a command is needed (without arguments) a single
- string can be specified.
-
- All commands must be specified.
- """
- # TODO implement it using metaclasses to add the handlers method by demand
- # (only for specifieds commands).
-
- def __init__(self, start=None, stop=None, restart=None, reload=None):
- r"Initialize the object, see the class documentation for details."
- for (name, action) in dict(start=start, stop=stop, restart=restart,
- reload=reload).items():
- if action is not None:
- setattr(self, '_service_%s' % name, action)
-
- @handler(u'Start the service.')
- def start(self):
- r"start() -> None :: Start the service."
- call(self._service_start)
-
- @handler(u'Stop the service.')
- def stop(self):
- r"stop() -> None :: Stop the service."
- call(self._service_stop)
-
- @handler(u'Restart the service.')
- def restart(self):
- r"restart() -> None :: Restart the service."
- call(self._service_restart)
-
- @handler(u'Reload the service config (without restarting, if possible).')
- def reload(self):
- r"reload() -> None :: Reload the configuration of the service."
- call(self._service_reload)
-
-class InitdHandler(Handler):
- r"""InitdHandler([initd_name[, initd_dir]]) -> InitdHandler.
-
- This is a helper class to inherit from to automatically handle services
- with start, stop, restart, reload actions using a /etc/init.d like script.
-
- The name and directory of the script can be defined by calling the
- constructor or in a more declarative way as class attributes, like:
-
- class TestHandler(ServiceHandler):
- _initd_name = 'some-service'
- _initd_dir = '/usr/local/etc/init.d'
-
- The default _initd_dir is '/etc/init.d', _initd_name has no default and
- must be specified in either way.
-
- Commands are executed without using the shell.
- """
- # TODO implement it using metaclasses to add the handlers method by demand
- # (only for specifieds commands).
-
- _initd_dir = '/etc/init.d'
-
- def __init__(self, initd_name=None, initd_dir=None):
- r"Initialize the object, see the class documentation for details."
- if initd_name is not None:
- self._initd_name = initd_name
- if initd_dir is not None:
- self._initd_dir = initd_dir
-
- @handler(u'Start the service.')
- def start(self):
- r"start() -> None :: Start the service."
- call((path.join(self._initd_dir, self._initd_name), 'start'))
-
- @handler(u'Stop the service.')
- def stop(self):
- r"stop() -> None :: Stop the service."
- call((path.join(self._initd_dir, self._initd_name), 'stop'))
-
- @handler(u'Restart the service.')
- def restart(self):
- r"restart() -> None :: Restart the service."
- call((path.join(self._initd_dir, self._initd_name), 'restart'))
-
- @handler(u'Reload the service config (without restarting, if possible).')
- def reload(self):
- r"reload() -> None :: Reload the configuration of the service."
- call((path.join(self._initd_dir, self._initd_name), 'reload'))
-
class Persistent:
- r"""Persistent([vars[, dir[, ext]]]) -> Persistent.
+ r"""Persistent([attrs[, dir[, ext]]]) -> Persistent.
This is a helper class to inherit from to automatically handle data
persistence using pickle.
- The variables attributes to persist (vars), and the pickle directory (dir)
+ The variables attributes to persist (attrs), and the pickle directory (dir)
and file extension (ext) can be defined by calling the constructor or in a
more declarative way as class attributes, like:
class TestHandler(Persistent):
- _persistent_vars = ('some_var', 'other_var')
+ _persistent_attrs = ('some_attr', 'other_attr')
_persistent_dir = 'persistent-data'
_persistent_ext = '.pickle'
# TODO implement it using metaclasses to add the handlers method by demand
# (only for specifieds commands).
- _persistent_vars = ()
+ _persistent_attrs = ()
_persistent_dir = '.'
_persistent_ext = '.pkl'
- def __init__(self, vars=None, dir=None, ext=None):
+ def __init__(self, attrs=None, dir=None, ext=None):
r"Initialize the object, see the class documentation for details."
- if vars is not None:
- self._persistent_vars = vars
+ if attrs is not None:
+ self._persistent_attrs = attrs
if dir is not None:
self._persistent_dir = dir
if ext is not None:
def _dump(self):
r"_dump() -> None :: Dump all persistent data to pickle files."
- if isinstance(self._persistent_vars, basestring):
- self._persistent_vars = (self._persistent_vars,)
- for varname in self._persistent_vars:
- self._dump_var(varname)
+ if isinstance(self._persistent_attrs, basestring):
+ self._persistent_attrs = (self._persistent_attrs,)
+ for attrname in self._persistent_attrs:
+ self._dump_attr(attrname)
def _load(self):
r"_load() -> None :: Load all persistent data from pickle files."
- if isinstance(self._persistent_vars, basestring):
- self._persistent_vars = (self._persistent_vars,)
- for varname in self._persistent_vars:
- self._load_var(varname)
-
- def _dump_var(self, varname):
- r"_dump_var() -> None :: Dump a especific variable to a pickle file."
- f = file(self._pickle_filename(varname), 'wb')
- pickle.dump(getattr(self, varname), f, 2)
+ if isinstance(self._persistent_attrs, basestring):
+ self._persistent_attrs = (self._persistent_attrs,)
+ for attrname in self._persistent_attrs:
+ self._load_attr(attrname)
+
+ def _dump_attr(self, attrname):
+ r"_dump_attr() -> None :: Dump a specific variable to a pickle file."
+ f = file(self._pickle_filename(attrname), 'wb')
+ pickle.dump(getattr(self, attrname), f, 2)
f.close()
- def _load_var(self, varname):
- r"_load_var() -> object :: Load a especific pickle file."
- f = file(self._pickle_filename(varname))
- setattr(self, varname, pickle.load(f))
+ def _load_attr(self, attrname):
+ r"_load_attr() -> object :: Load a specific pickle file."
+ f = file(self._pickle_filename(attrname))
+ setattr(self, attrname, pickle.load(f))
f.close()
def _pickle_filename(self, name):
declarative way as class attributes, like:
class TestHandler(Restorable):
- _persistent_vars = ('some_var', 'other_var')
+ _persistent_attrs = ('some_attr', 'other_attr')
_restorable_defaults = dict(
- some_var = 'some_default',
- other_var = 'other_default')
+ some_attr = 'some_default',
+ other_attr = 'other_default')
- The defaults is a dictionary, very coupled with the _persistent_vars
+ The defaults is a dictionary, very coupled with the _persistent_attrs
attribute inherited from Persistent. The defaults keys should be the
- values from _persistent_vars, and the values the default values.
+ values from _persistent_attrs, and the values the default values.
The _restore() method returns True if the data was restored successfully
or False if the defaults were loaded (in case you want to take further
for t in self._config_writer_files:
self._write_single_config(t)
+class ServiceHandler(Handler):
+ r"""ServiceHandler([start[, stop[, restart[, reload]]]]) -> ServiceHandler.
+
+ This is a helper class to inherit from to automatically handle services
+ with start, stop, restart, reload actions.
+
+ The actions can be defined by calling the constructor with all the
+ parameters or in a more declarative way as class attributes, like:
+
+ class TestHandler(ServiceHandler):
+ _service_start = ('command', 'start')
+ _service_stop = ('command', 'stop')
+ _service_restart = ('command', 'restart')
+ _service_reload = 'reload-command'
+
+ Commands are executed without using the shell, that's why they are specified
+ as tuples (where the first element is the command and the others are the
+ command arguments). If only a command is needed (without arguments) a single
+ string can be specified.
+
+ All commands must be specified.
+ """
+ # TODO implement it using metaclasses to add the handlers method by demand
+ # (only for specifieds commands).
+
+ def __init__(self, start=None, stop=None, restart=None, reload=None):
+ r"Initialize the object, see the class documentation for details."
+ for (name, action) in dict(start=start, stop=stop, restart=restart,
+ reload=reload).items():
+ if action is not None:
+ setattr(self, '_service_%s' % name, action)
+
+ @handler(u'Start the service.')
+ def start(self):
+ r"start() -> None :: Start the service."
+ call(self._service_start)
+
+ @handler(u'Stop the service.')
+ def stop(self):
+ r"stop() -> None :: Stop the service."
+ call(self._service_stop)
+
+ @handler(u'Restart the service.')
+ def restart(self):
+ r"restart() -> None :: Restart the service."
+ call(self._service_restart)
+
+ @handler(u'Reload the service config (without restarting, if possible).')
+ def reload(self):
+ r"reload() -> None :: Reload the configuration of the service."
+ call(self._service_reload)
+
+class InitdHandler(Handler):
+ r"""InitdHandler([initd_name[, initd_dir]]) -> InitdHandler.
+
+ This is a helper class to inherit from to automatically handle services
+ with start, stop, restart, reload actions using a /etc/init.d like script.
+
+ The name and directory of the script can be defined by calling the
+ constructor or in a more declarative way as class attributes, like:
+
+ class TestHandler(ServiceHandler):
+ _initd_name = 'some-service'
+ _initd_dir = '/usr/local/etc/init.d'
+
+ The default _initd_dir is '/etc/init.d', _initd_name has no default and
+ must be specified in either way.
+
+ Commands are executed without using the shell.
+ """
+ # TODO implement it using metaclasses to add the handlers method by demand
+ # (only for specifieds commands).
+
+ _initd_dir = '/etc/init.d'
+
+ def __init__(self, initd_name=None, initd_dir=None):
+ r"Initialize the object, see the class documentation for details."
+ if initd_name is not None:
+ self._initd_name = initd_name
+ if initd_dir is not None:
+ self._initd_dir = initd_dir
+
+ @handler(u'Start the service.')
+ def start(self):
+ r"start() -> None :: Start the service."
+ call((path.join(self._initd_dir, self._initd_name), 'start'))
+
+ @handler(u'Stop the service.')
+ def stop(self):
+ r"stop() -> None :: Stop the service."
+ call((path.join(self._initd_dir, self._initd_name), 'stop'))
+
+ @handler(u'Restart the service.')
+ def restart(self):
+ r"restart() -> None :: Restart the service."
+ call((path.join(self._initd_dir, self._initd_name), 'restart'))
+
+ @handler(u'Reload the service config (without restarting, if possible).')
+ def reload(self):
+ r"reload() -> None :: Reload the configuration of the service."
+ call((path.join(self._initd_dir, self._initd_name), 'reload'))
+
class TransactionalHandler(Handler):
- r"""TransactionalHandler([initd_name[, initd_dir]]) -> TransactionalHandler.
+ r"""Handle command transactions providing a commit and rollback commands.
This is a helper class to inherit from to automatically handle
transactional handlers, which have commit and rollback commands.
if hasattr(self, '_load'):
self._load()
+class ParametersHandler(Handler):
+ r"""ParametersHandler([attr]) -> ParametersHandler.
+
+ This is a helper class to inherit from to automatically handle
+ service parameters, providing set, get, list and show commands.
+
+ The attribute that holds the parameters can be defined by calling the
+ constructor or in a more declarative way as class attributes, like:
+
+ class TestHandler(ServiceHandler):
+ _parameters_attr = 'some_attr'
+
+ The default is 'params' and it should be a dictionary.
+ """
+ # TODO implement it using metaclasses to add the handlers method by demand
+ # (only for specifieds commands).
+
+ _parameters_attr = 'params'
+
+ def __init__(self, attr=None):
+ r"Initialize the object, see the class documentation for details."
+ if attr is not None:
+ self._parameters_attr = attr
+
+ @handler(u'Set a service parameter.')
+ def set(self, param, value):
+ r"set(param, value) -> None :: Set a service parameter."
+ if not param in self.params:
+ raise ParameterNotFoundError(param)
+ self.params[param] = value
+
+ @handler(u'Get a service parameter.')
+ def get(self, param):
+ r"get(param) -> None :: Get a service parameter."
+ if not param in self.params:
+ raise ParameterNotFoundError(param)
+ return self.params[param]
+
+ @handler(u'List all available service parameters.')
+ def list(self):
+ r"list() -> tuple :: List all the parameter names."
+ return self.params.keys()
+
+ @handler(u'Get all service parameters, with their values.')
+ def show(self):
+ r"show() -> (key, value) tuples :: List all the parameters."
+ return self.params.items()
+
if __name__ == '__main__':
# Persistent test
print 'PTestHandler'
class PTestHandler(Persistent):
- _persistent_vars = 'vars'
+ _persistent_attrs = 'vars'
def __init__(self):
self.vars = dict(a=1, b=2)
h = PTestHandler()
# Restorable test
print 'RTestHandler'
class RTestHandler(Restorable):
- _persistent_vars = 'vars'
+ _persistent_attrs = 'vars'
_restorable_defaults = dict(vars=dict(a=1, b=2))
def __init__(self):
self._restore()