From: Leandro Lucarella Date: Thu, 4 Oct 2007 14:35:40 +0000 (-0300) Subject: Add a ParametersHandler to services.util. X-Git-Url: https://git.llucax.com/software/pymin.git/commitdiff_plain/70ec9c970b451ee166087a3327a6b906a4777500?ds=sidebyside;hp=--cc Add a ParametersHandler to services.util. This class is a helper to provide common service parameters commands: get, set, list and show. All service handlers that use parameters were update to inherit from this class. --- 70ec9c970b451ee166087a3327a6b906a4777500 diff --git a/services/dhcp/__init__.py b/services/dhcp/__init__.py index 7ffadcf..8bed883 100644 --- a/services/dhcp/__init__.py +++ b/services/dhcp/__init__.py @@ -5,10 +5,10 @@ from os import path from seqtools import Sequence from dispatcher import Handler, handler, HandlerError from services.util import Restorable, ConfigWriter -from services.util import InitdHandler, TransactionalHandler +from services.util import InitdHandler, TransactionalHandler, ParametersHandler __ALL__ = ('DhcpHandler', 'Error', 'HostError', 'HostAlreadyExistsError', - 'HostNotFoundError', 'ParameterError', 'ParameterNotFoundError') + 'HostNotFoundError') class Error(HandlerError): r""" @@ -61,29 +61,6 @@ class HostNotFoundError(HostError): r"Initialize the object. See class documentation for more info." self.message = 'Host not found: "%s"' % hostname -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 - class Host(Sequence): r"""Host(name, ip, mac) -> Host instance :: Class representing a host. @@ -157,7 +134,8 @@ class HostHandler(Handler): r"show() -> list of Hosts :: List all the complete hosts information." return self.hosts.values() -class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): +class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler, + ParametersHandler): r"""DhcpHandler([pickle_dir[, config_dir]]) -> DhcpHandler instance. Handles DHCP service commands for the dhcpd program. @@ -171,11 +149,11 @@ class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): _initd_name = 'dhcpd' - _persistent_vars = ('vars', 'hosts') + _persistent_vars = ('params', 'hosts') _restorable_defaults = dict( hosts = dict(), - vars = dict( + params = dict( domain_name = 'example.com', dns_1 = 'ns1.example.com', dns_2 = 'ns2.example.com', @@ -199,31 +177,7 @@ class DhcpHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): self.host = HostHandler(self.hosts) def _get_config_vars(self, config_file): - return dict(hosts=self.hosts.values(), **self.vars) - - @handler(u'Set a DHCP parameter.') - def set(self, param, value): - r"set(param, value) -> None :: Set a DHCP parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - self.vars[param] = value - - @handler(u'Get a DHCP parameter.') - def get(self, param): - r"get(param) -> None :: Get a DHCP parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - return self.vars[param] - - @handler(u'List all available DHCP parameters.') - def list(self): - r"list() -> tuple :: List all the parameter names." - return self.vars.keys() - - @handler(u'Get all DHCP parameters, with their values.') - def show(self): - r"show() -> (key, value) tuples :: List all the parameters." - return self.vars.items() + return dict(hosts=self.hosts.values(), **self.params) if __name__ == '__main__': diff --git a/services/dns/__init__.py b/services/dns/__init__.py index e3739e3..ce21e97 100644 --- a/services/dns/__init__.py +++ b/services/dns/__init__.py @@ -8,15 +8,14 @@ from new import instancemethod from seqtools import Sequence from dispatcher import handler, HandlerError, Handler from services.util import Restorable, ConfigWriter, call -from services.util import InitdHandler, TransactionalHandler +from services.util import InitdHandler, TransactionalHandler, ParametersHandler __ALL__ = ('DnsHandler', 'Error', 'ZoneError', 'ZoneNotFoundError', 'ZoneAlreadyExistsError', 'HostError', 'HostAlreadyExistsError', 'HostNotFoundError', 'MailExchangeError', 'MailExchangeAlreadyExistsError', 'MailExchangeNotFoundError', 'NameServerError', - 'NameServerAlreadyExistsError', 'NameServerNotFoundError', - 'ParameterError', 'ParameterNotFoundError') + 'NameServerAlreadyExistsError', 'NameServerNotFoundError') template_dir = path.join(path.dirname(__file__), 'templates') @@ -396,7 +395,8 @@ class ZoneHandler(Handler): def show(self): return self.zones.values() -class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): +class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler, + ParametersHandler): r"""DnsHandler([pickle_dir[, config_dir]]) -> DnsHandler instance. Handles DNS service commands for the dns program. @@ -410,11 +410,11 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): _initd_name = 'bind' - _persistent_vars = ('vars', 'zones') + _persistent_vars = ('params', 'zones') _restorable_defaults = dict( zones = dict(), - vars = dict( + params = dict( isp_dns1 = '', isp_dns2 = '', bind_addr1 = '', @@ -437,34 +437,11 @@ class DnsHandler(Restorable, ConfigWriter, InitdHandler, TransactionalHandler): self.mx = MailExchangeHandler(self.zones) self.ns = NameServerHandler(self.zones) - @handler(u'Set a DNS parameter') - def set(self, param, value): - r"set(param, value) -> None :: Set a DNS parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - self.vars[param] = value - self.mod = True - - @handler(u'Get a DNS parameter') - def get(self, param): - r"get(param) -> None :: Get a DNS parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - return self.vars[param] - - @handler(u'List DNS parameters') - def list(self): - return self.vars.keys() - - @handler(u'Get all DNS parameters, with their values.') - def show(self): - return self.vars.values() - def _zone_filename(self, zone): return zone.name + '.zone' def _get_config_vars(self, config_file): - return dict(zones=self.zones.values(), **self.vars) + return dict(zones=self.zones.values(), **self.params) def _write_config(self): r"_write_config() -> None :: Generate all the configuration files." diff --git a/services/firewall/__init__.py b/services/firewall/__init__.py index bbdb3fd..738bf67 100644 --- a/services/firewall/__init__.py +++ b/services/firewall/__init__.py @@ -7,8 +7,8 @@ from os import path from seqtools import Sequence from dispatcher import Handler, handler, HandlerError -from services.util import ServiceHandler, TransactionalHandler from services.util import Restorable, ConfigWriter +from services.util import ServiceHandler, TransactionalHandler __ALL__ = ('FirewallHandler', 'Error', 'RuleError', 'RuleAlreadyExistsError', 'RuleNotFoundError') @@ -174,7 +174,7 @@ class RuleHandler(Handler): return self.rules class FirewallHandler(Restorable, ConfigWriter, ServiceHandler, - TransactionalHandler): + TransactionalHandler): r"""FirewallHandler([pickle_dir[, config_dir]]) -> FirewallHandler instance. Handles firewall commands using iptables. diff --git a/services/proxy/__init__.py b/services/proxy/__init__.py index 195125c..6054887 100644 --- a/services/proxy/__init__.py +++ b/services/proxy/__init__.py @@ -5,7 +5,7 @@ from os import path from seqtools import Sequence from dispatcher import Handler, handler, HandlerError from services.util import Restorable, ConfigWriter -from services.util import InitdHandler, TransactionalHandler +from services.util import InitdHandler, TransactionalHandler, ParametersHandler __ALL__ = ('ProxyHandler', 'Error', 'HostError', 'HostAlreadyExistsError', 'HostNotFoundError', 'ParameterError', 'ParameterNotFoundError') @@ -119,15 +119,15 @@ class HostHandler(Handler): class ProxyHandler(Restorable, ConfigWriter, InitdHandler, - TransactionalHandler): + TransactionalHandler, ParametersHandler): _initd_name = 'squid' - _persistent_vars = ('vars', 'hosts') + _persistent_vars = ('params', 'hosts') _restorable_defaults = dict( hosts = dict(), - vars = dict( + params = dict( ip = '192.168.0.1', port = '8080', ), @@ -145,29 +145,7 @@ class ProxyHandler(Restorable, ConfigWriter, InitdHandler, self.host = HostHandler(self.hosts) def _get_config_vars(self, config_file): - return dict(hosts=self.hosts.values(), **self.vars) - - @handler(u'Set a Proxy parameter') - def set(self, param, value): - r"set(param, value) -> None :: Set a Proxy parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - self.vars[param] = value - - @handler(u'Get a DNS parameter') - def get(self, param): - r"get(param) -> None :: Get a Proxy parameter." - if not param in self.vars: - raise ParameterNotFoundError(param) - return self.vars[param] - - @handler(u'List Proxy parameters') - def list(self): - return self.vars.keys() - - @handler(u'Get all Proxy parameters, with their values.') - def show(self): - return self.vars.values() + return dict(hosts=self.hosts.values(), **self.params) if __name__ == '__main__': diff --git a/services/util.py b/services/util.py index cbfc091..4468384 100644 --- a/services/util.py +++ b/services/util.py @@ -72,6 +72,29 @@ class ExecutionError(Error): 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): @@ -89,108 +112,6 @@ def call(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, 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. @@ -419,8 +340,110 @@ class ConfigWriter: 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. @@ -451,6 +474,54 @@ class TransactionalHandler(Handler): 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__':