From: Leandro Lucarella Date: Mon, 16 Jun 2008 18:43:45 +0000 (-0300) Subject: Use a plug-in architecture for services (refs #27). X-Git-Url: https://git.llucax.com/software/pymin.git/commitdiff_plain/fac20bd5c930ab027e9c097f34bf50714f8a53d5 Use a plug-in architecture for services (refs #27). Service modules are loaded dinamically using the imp module. The config.py file is simplified to avoid the need of defining pymind command handlers "tree" in the configuration file. --- diff --git a/config.py b/config.py index aae79c1..aa3e5eb 100644 --- a/config.py +++ b/config.py @@ -8,7 +8,6 @@ logging.basicConfig( datefmt = '%a, %d %b %Y %H:%M:%S', ) -from pymin.services import * from pymin.dispatcher import Handler from os.path import join @@ -17,67 +16,64 @@ pickle_path = join(base_path, 'pickle') # FIXME, this should be specific for each service config_path = join(base_path, 'config') -class Root(Handler): - - def __init__(self): - try: - f = file("/proc/sys/net/ipv4/ip_forward","w") - f.write("1") - f.close() - except (IOError, OSError), e: - print "Can't set ip_forward:", e - #self.ip.device_up_hook(self.dns) - - firewall = FirewallHandler( - pickle_dir = join(pickle_path, 'firewall'), - config_dir = join(config_path, 'firewall')) - - nat = NatHandler(pickle_dir = join(pickle_path, 'nat')) - - ppp = PppHandler( - pickle_dir = join(pickle_path, 'ppp'), - config_dir = { - 'pap-secrets': join(config_path, 'ppp'), - 'chap-secrets': join(config_path, 'ppp'), - 'options.X': join(config_path, 'ppp'), - 'nameX': join(config_path, 'ppp', 'peers'), - }) - - vpn = VpnHandler( - pickle_dir = join(pickle_path, 'vpn'), - config_dir = join(config_path, 'vpn')) - - ip = IpHandler( - pickle_dir = join(pickle_path, 'ip'), - config_dir = join(config_path, 'ip')) - - dns = DnsHandler( - pickle_dir = join(pickle_path, 'dns'), - config_dir = { - 'named.conf': join(config_path, 'dns'), - 'zoneX.zone': join(config_path, 'dns', 'zones'), - }) - - dhcp = DhcpHandler( - pickle_dir = join(pickle_path, 'dhcp'), - config_dir = join(config_path, 'dhcp')) - - proxy = ProxyHandler( - pickle_dir = join(pickle_path, 'proxy'), - config_dir = join(config_path, 'proxy')) - - vrrp = VrrpHandler( - pickle_dir = join(pickle_path, 'vrrp'), - config_dir = join(config_path, 'vrrp'), - pid_dir = join(config_path, 'vrrp', 'run')) - - vpn = VpnHandler( - pickle_dir = join(pickle_path, 'vpn'), - config_dir = join(config_path, 'vpn')) - - #qos = QoSHandler( - # pickle_dir = join(pickle_path, 'qos'), - # config_dir = join(config_path, 'qos')) +try: + f = file("/proc/sys/net/ipv4/ip_forward","w") + f.write("1") + f.close() +except (IOError, OSError), e: + print "Can't set ip_forward:", e + +class firewall: + pickle_dir = join(pickle_path, 'firewall') + config_dir = join(config_path, 'firewall') + +class nat: + pickle_dir = join(pickle_path, 'nat') + +class ppp: + pickle_dir = join(pickle_path, 'ppp') + config_dir = { + 'pap-secrets': join(config_path, 'ppp'), + 'chap-secrets': join(config_path, 'ppp'), + 'options.X': join(config_path, 'ppp'), + 'nameX': join(config_path, 'ppp', 'peers'), + } + +class vpn: + pickle_dir = join(pickle_path, 'vpn') + config_dir = join(config_path, 'vpn') + +class ip: + pickle_dir = join(pickle_path, 'ip') + config_dir = join(config_path, 'ip') + +class dns: + pickle_dir = join(pickle_path, 'dns') + config_dir = { + 'named.conf': join(config_path, 'dns'), + 'zoneX.zone': join(config_path, 'dns', 'zones'), + } + +class dhcp: + pickle_dir = join(pickle_path, 'dhcp') + config_dir = join(config_path, 'dhcp') + +class proxy: + pickle_dir = join(pickle_path, 'proxy') + config_dir = join(config_path, 'proxy') + +class vrrp: + pickle_dir = join(pickle_path, 'vrrp') + config_dir = join(config_path, 'vrrp') + pid_dir = join(config_path, 'vrrp', 'run') + +class vpn: + pickle_dir = join(pickle_path, 'vpn') + config_dir = join(config_path, 'vpn') + +class qos: + pickle_dir = join(pickle_path, 'qos') + config_dir = join(config_path, 'qos') bind_addr = \ ( @@ -85,3 +81,7 @@ bind_addr = \ 9999, # Port ) +services = 'firewall nat ppp vpn ip dns dhcp proxy vrrp qos'.split() + +services_dirs = ['pymin/services'] + diff --git a/pymin/services/__init__.py b/pymin/services/__init__.py index 7620197..1828fb4 100644 --- a/pymin/services/__init__.py +++ b/pymin/services/__init__.py @@ -1,12 +1,19 @@ # vim: set encoding=utf-8 et sw=4 sts=4 : -from pymin.services.dhcp import DhcpHandler -from pymin.services.dns import DnsHandler -from pymin.services.firewall import FirewallHandler -from pymin.services.nat import NatHandler -from pymin.services.ip import IpHandler -from pymin.services.proxy import ProxyHandler -from pymin.services.vrrp import VrrpHandler -from pymin.services.ppp import PppHandler -from pymin.services.qos import QoSHandler -from pymin.services.vpn import VpnHandler +import imp + +class LoadError(ImportError): + pass + +def load_service(name, search_paths): + try: + (fp, path, desc) = imp.find_module(name, search_paths) + except ImportError: + raise LoadError('module "%s" not found' % name) + + try: + return imp.load_module(name, fp, path, desc) + finally: + if fp: + fp.close() + diff --git a/pymin/services/dhcp/__init__.py b/pymin/services/dhcp/__init__.py index b5bf6f3..1c6a919 100644 --- a/pymin/services/dhcp/__init__.py +++ b/pymin/services/dhcp/__init__.py @@ -9,7 +9,12 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ TransactionalHandler, ParametersHandler, \ DictSubHandler, ReloadHandler -__all__ = ('DhcpHandler',) +__all__ = ('DhcpHandler', 'get_service') + + +def get_service(config): + return DhcpHandler(config.dhcp.pickle_dir, config.dhcp.config_dir) + class Host(Sequence): r"""Host(name, ip, mac) -> Host instance :: Class representing a host. diff --git a/pymin/services/dns/__init__.py b/pymin/services/dns/__init__.py index 0576cd0..c3cf03e 100644 --- a/pymin/services/dns/__init__.py +++ b/pymin/services/dns/__init__.py @@ -11,7 +11,12 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ TransactionalHandler, ParametersHandler, \ DictComposedSubHandler, DictSubHandler, call -__all__ = ('DnsHandler',) +__all__ = ('DnsHandler', 'get_service') + + +def get_service(config): + return DnsHandler(config.dns.pickle_dir, config.dns.config_dir) + class Host(Sequence): def __init__(self, name, ip): diff --git a/pymin/services/firewall/__init__.py b/pymin/services/firewall/__init__.py index 0ab2b4c..7b17c23 100644 --- a/pymin/services/firewall/__init__.py +++ b/pymin/services/firewall/__init__.py @@ -14,7 +14,12 @@ from pymin.dispatcher import Handler, handler, HandlerError from pymin.services.util import Restorable, ConfigWriter, ServiceHandler, \ TransactionalHandler, ListSubHandler -__all__ = ('FirewallHandler',) +__all__ = ('FirewallHandler', 'get_service') + + +def get_service(config): + return FirewallHandler(config.firewall.pickle_dir, config.firewall.config_dir) + class UpOneOf(OneOf): def validate_python(self, value, state): diff --git a/pymin/services/ip/__init__.py b/pymin/services/ip/__init__.py index 86551f4..54ee30b 100644 --- a/pymin/services/ip/__init__.py +++ b/pymin/services/ip/__init__.py @@ -12,7 +12,11 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ DictComposedSubHandler, ListSubHandler, \ Device, Address, ExecutionError -__all__ = ('IpHandler',) +__all__ = ('IpHandler', 'get_service') + + +def get_service(config): + return IpHandler(config.ip.pickle_dir, config.ip.config_dir) class Hop(Sequence): diff --git a/pymin/services/nat/__init__.py b/pymin/services/nat/__init__.py index 34d5b0d..3afc997 100644 --- a/pymin/services/nat/__init__.py +++ b/pymin/services/nat/__init__.py @@ -9,7 +9,12 @@ from pymin.services.util import Restorable, ConfigWriter, RestartHandler, \ ReloadHandler, TransactionalHandler, \ ServiceHandler, ListSubHandler, call -__all__ = ('NatHandler',) +__all__ = ('NatHandler', 'get_service') + + +def get_service(config): + return NatHandler(config.nat.pickle_dir) + class PortForward(Sequence): r"""PortForward(dev, protocol, port, dst[, dst_port[, ...]]) -> PortForward. diff --git a/pymin/services/ppp/__init__.py b/pymin/services/ppp/__init__.py index 6ee9f5a..7f5a143 100644 --- a/pymin/services/ppp/__init__.py +++ b/pymin/services/ppp/__init__.py @@ -11,7 +11,12 @@ from pymin.dispatcher import Handler, handler, HandlerError from pymin.services.util import Restorable, ConfigWriter, ReloadHandler, \ TransactionalHandler, DictSubHandler, call -__all__ = ('PppHandler',) +__all__ = ('PppHandler', 'get_service') + + +def get_service(config): + return PppHandler(config.ppp.pickle_dir, config.ppp.config_dir) + class ConnectionError(HandlerError, KeyError): r""" diff --git a/pymin/services/proxy/__init__.py b/pymin/services/proxy/__init__.py index 5ab624b..448f568 100644 --- a/pymin/services/proxy/__init__.py +++ b/pymin/services/proxy/__init__.py @@ -11,7 +11,13 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ import crypt -__all__ = ('ProxyHandler',) + +__all__ = ('ProxyHandler', 'get_service') + + +def get_service(config): + return ProxyHandler(config.proxy.pickle_dir, config.proxy.config_dir) + class Host(Sequence): def __init__(self,ip): diff --git a/pymin/services/qos/__init__.py b/pymin/services/qos/__init__.py index b583d4d..d021d68 100644 --- a/pymin/services/qos/__init__.py +++ b/pymin/services/qos/__init__.py @@ -10,7 +10,12 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ get_network_devices, ListComposedSubHandler, \ DictComposedSubHandler, ExecutionError -__all__ = ('QoSHandler',) +__all__ = ('QoSHandler', 'get_service') + + +def get_service(config): + return QoSHandler(config.qos.pickle_dir, config.qos.config_dir) + class DeviceError(HandlerError): diff --git a/pymin/services/vpn/__init__.py b/pymin/services/vpn/__init__.py index f3b9f95..066e8fc 100644 --- a/pymin/services/vpn/__init__.py +++ b/pymin/services/vpn/__init__.py @@ -13,6 +13,13 @@ from pymin.services.util import Restorable, ConfigWriter, InitdHandler, \ TransactionalHandler, DictSubHandler, DictComposedSubHandler, call, ExecutionError +__all__ = ('VpnHandler', 'get_service') + + +def get_service(config): + return VpnHandler(config.vpn.pickle_dir, config.vpn.config_dir) + + class Host(Sequence): def __init__(self, vpn_src, ip, vpn_src_net, key): self.name = vpn_src diff --git a/pymin/services/vrrp/__init__.py b/pymin/services/vrrp/__init__.py index f957bb4..9b4c0e6 100644 --- a/pymin/services/vrrp/__init__.py +++ b/pymin/services/vrrp/__init__.py @@ -8,7 +8,12 @@ from pymin.services.util import Restorable, TransactionalHandler, \ # Logger import logging ; log = logging.getLogger('pymin.services.vrrp') -__all__ = ('VrrpHandler',) +__all__ = ('VrrpHandler', 'get_service') + + +def get_service(config): + return VrrpHandler(config.vrrp.pickle_dir, config.vrrp.config_dir) + # FIXME the the command should not use new parameters unless commit where called # i.e. integrate commit with procman to update internal procman parameters. diff --git a/pymind b/pymind index a04307d..2f428b5 100755 --- a/pymind +++ b/pymind @@ -1,8 +1,29 @@ #!/usr/bin/env python # vim: set encoding=utf-8 et sw=4 sts=4 : +import sys from pymin.pymindaemon import PyminDaemon +from pymin.dispatcher import Handler +from pymin.services import load_service, LoadError import config -PyminDaemon(config.Root(), config.bind_addr).run() +class Root(Handler): + pass + +def build_root(config): + # TODO check services dependencies + services = dict() + for service in config.services: + try: + s = load_service(service, config.services_dirs) + except LoadError, e: + sys.stderr.write("Can't find service called '%s'\n" % service) + sys.exit(1) + services[service] = s + root = Root() + for name, service in services.items(): + setattr(root, name, service.get_service(config)) + return root + +PyminDaemon(build_root(config), config.bind_addr).run()