Browse Source

[213] Move special components out

Michal 'vorner' Vaner 13 years ago
parent
commit
27f88f2ed0

+ 3 - 1
src/bin/bind10/bind10_src.py.in

@@ -68,6 +68,7 @@ import isc.net.parse
 import isc.log
 from isc.log_messages.bind10_messages import *
 import isc.bind10.component
+import isc.bind10.special_component
 
 isc.log.init("b10-boss")
 logger = isc.log.Logger("boss")
@@ -242,7 +243,8 @@ class BoB:
         self.config_filename = config_filename
         self.cmdctl_port = cmdctl_port
         self.brittle = brittle
-        self._component_configurator = isc.bind10.component.Configurator(self)
+        self._component_configurator = isc.bind10.component.Configurator(self,
+            isc.bind10.special_component.get_specials())
         self.__core_components = {
             'sockcreator': {
                 'kind': 'core',

+ 1 - 1
src/lib/python/isc/bind10/Makefile.am

@@ -1,4 +1,4 @@
 SUBDIRS = . tests
 
-python_PYTHON = __init__.py sockcreator.py component.py
+python_PYTHON = __init__.py sockcreator.py component.py special_component.py
 pythondir = $(pyexecdir)/isc/bind10

+ 8 - 89
src/lib/python/isc/bind10/component.py

@@ -13,12 +13,9 @@
 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-import isc.bind10.sockcreator
 import isc.log
 from isc.log_messages.bind10_messages import *
 import time
-from bind10_config import LIBEXECDIR
-import os
 
 logger = isc.log.Logger("boss")
 DBG_TRACE_DATA = 20
@@ -210,90 +207,6 @@ class Component:
         """
         return self._procinfo.pid if self._procinfo else None
 
-# These are specialized components. Some of them are components which need
-# special care (like the message queue or socket creator) or they need
-# some parameters constructed from Boss's command line. They are not tested
-# currently, because it is not clear what to test on them anyway and they just
-# delegate the work for the boss
-class SockCreator(Component):
-    """
-    The socket creator component. Will start and stop the socket creator
-    accordingly.
-    """
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self.__creator = None
-
-    def start_internal(self):
-        self._boss.curproc = 'b10-sockcreator'
-        self.__creator = isc.bind10.sockcreator.Creator(LIBEXECDIR + ':' +
-                                                        os.environ['PATH'])
-        self._boss.register_process(self.pid(), self)
-
-    def stop_internal(self):
-        if self.__creator is None:
-            return
-        self.__creator.terminate()
-        self.__creator = None
-
-    def pid(self):
-        """
-        Pid of the socket creator. It is provided differently from a usual
-        component.
-        """
-        return self.__creator.pid() if self.__creator else None
-
-class Msgq(Component):
-    """
-    The message queue. Starting is passed to boss, stopping is not supported
-    and we leave the boss kill it by signal.
-    """
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self._start_func = boss.start_msgq
-
-    def stop_internal(self):
-        pass # Wait for the boss to actually kill it. There's no stop command.
-
-class CfgMgr(Component):
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self._start_func = boss.start_cfgmgr
-        self._address = 'ConfigManager'
-
-class Auth(Component):
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self._start_func = boss.start_auth
-        self._address = 'Auth'
-
-class Resolver(Component):
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self._start_func = boss.start_resolver
-        self._address = 'Resolver'
-
-class CmdCtl(Component):
-    def __init__(self, process, boss, kind, address=None, params=None):
-        Component.__init__(self, process, boss, kind)
-        self._start_func = boss.start_cmdctl
-        self._address = 'Cmdctl'
-
-specials = {
-    'sockcreator': SockCreator,
-    'msgq': Msgq,
-    'cfgmgr': CfgMgr,
-    # TODO: Should these be replaced by configuration in config manager only?
-    # They should not have any parameters anyway
-    'auth': Auth,
-    'resolver': Resolver,
-    'cmdctl': CmdCtl
-}
-"""
-List of specially started components. Each one should be the class than can
-be created for that component.
-"""
-
 class Configurator:
     """
     This thing keeps track of configuration changes and starts and stops
@@ -304,8 +217,13 @@ class Configurator:
     component. There should be some kind of layer protecting users from ever
     doing so (users must not stop the config manager, message queue and stuff
     like that or the system won't start again).
+
+    The parameters are:
+    * `boss`: The boss we are managing for.
+    * `specials`: Dict of specially started components. Each item is a class
+      representing the component.
     """
-    def __init__(self, boss):
+    def __init__(self, boss, specials = {}):
         """
         Initializes the configurator, but nothing is started yet.
 
@@ -317,6 +235,7 @@ class Configurator:
         self._components = {}
         self._old_config = {}
         self._running = False
+        self.__specials = specials
 
     def __reconfigure_internal(self, old, new):
         """
@@ -401,7 +320,7 @@ class Configurator:
                 creator = Component
                 if 'special' in params:
                     # TODO: Better error handling
-                    creator = specials[params['special']]
+                    creator = self.__specials[params['special']]
                 component = creator(params.get('process', cname), self.__boss,
                                     params.get('kind', 'dispensable'),
                                     params.get('address'),

+ 99 - 0
src/lib/python/isc/bind10/special_component.py

@@ -0,0 +1,99 @@
+# Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+from isc.bind10.component import Component
+import isc.bind10.sockcreator
+from bind10_config import LIBEXECDIR
+import os
+
+class SockCreator(Component):
+    """
+    The socket creator component. Will start and stop the socket creator
+    accordingly.
+    """
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self.__creator = None
+
+    def start_internal(self):
+        self._boss.curproc = 'b10-sockcreator'
+        self.__creator = isc.bind10.sockcreator.Creator(LIBEXECDIR + ':' +
+                                                        os.environ['PATH'])
+        self._boss.register_process(self.pid(), self)
+
+    def stop_internal(self):
+        if self.__creator is None:
+            return
+        self.__creator.terminate()
+        self.__creator = None
+
+    def pid(self):
+        """
+        Pid of the socket creator. It is provided differently from a usual
+        component.
+        """
+        return self.__creator.pid() if self.__creator else None
+
+class Msgq(Component):
+    """
+    The message queue. Starting is passed to boss, stopping is not supported
+    and we leave the boss kill it by signal.
+    """
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self._start_func = boss.start_msgq
+
+    def stop_internal(self):
+        pass # Wait for the boss to actually kill it. There's no stop command.
+
+class CfgMgr(Component):
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self._start_func = boss.start_cfgmgr
+        self._address = 'ConfigManager'
+
+class Auth(Component):
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self._start_func = boss.start_auth
+        self._address = 'Auth'
+
+class Resolver(Component):
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self._start_func = boss.start_resolver
+        self._address = 'Resolver'
+
+class CmdCtl(Component):
+    def __init__(self, process, boss, kind, address=None, params=None):
+        Component.__init__(self, process, boss, kind)
+        self._start_func = boss.start_cmdctl
+        self._address = 'Cmdctl'
+
+def get_specials():
+    """
+    List of specially started components. Each one should be the class than can
+    be created for that component.
+    """
+    return {
+        'sockcreator': SockCreator,
+        'msgq': Msgq,
+        'cfgmgr': CfgMgr,
+        # TODO: Should these be replaced by configuration in config manager only?
+        # They should not have any parameters anyway
+        'auth': Auth,
+        'resolver': Resolver,
+        'cmdctl': CmdCtl
+    }

+ 19 - 28
src/lib/python/isc/bind10/tests/component_test.py

@@ -14,14 +14,16 @@
 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 """
-Tests for the bind10.component module
+Tests for the isc.bind10.component module and the
+isc.bind10.special_component module.
 """
 
 import unittest
 import isc.log
 import time
 import copy
-from isc.bind10.component import Component, Configurator, specials
+from isc.bind10.component import Component, Configurator
+import isc.bind10.special_component
 
 class TestError(Exception):
     """
@@ -410,12 +412,13 @@ class ComponentTests(BossUtils, unittest.TestCase):
         Test that a componet that is not yet started doesn't have a PID.
         But it won't failed if asked for and returns None.
         """
-        for component_type in [Component, isc.bind10.component.SockCreator,
-                               isc.bind10.component.Msgq,
-                               isc.bind10.component.CfgMgr,
-                               isc.bind10.component.Auth,
-                               isc.bind10.component.Resolver,
-                               isc.bind10.component.CmdCtl]:
+        for component_type in [Component,
+                               isc.bind10.special_component.SockCreator,
+                               isc.bind10.special_component.Msgq,
+                               isc.bind10.special_component.CfgMgr,
+                               isc.bind10.special_component.Auth,
+                               isc.bind10.special_component.Resolver,
+                               isc.bind10.special_component.CmdCtl]:
             component = component_type('none', self, 'needed')
             self.assertIsNone(component.pid())
 
@@ -466,15 +469,9 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
     """
     def setUp(self):
         """
-        Insert the special evaluated test components we use and prepare the
-        log. Also provide some data for the tests and prepare us to pretend
-        we're boss.
+        Prepare some test data for the tests.
         """
         BossUtils.setUp(self)
-        # We put our functions inside instead of class constructors,
-        # so we can look into what is happening more easily
-        self.__orig_specials = copy.copy(specials)
-        specials['test'] = self.__component_test
         self.log = []
         # The core "hardcoded" configuration
         self.__core = {
@@ -507,13 +504,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         self.__core_log_start = [('core1', 'start'), ('core3', 'start'),
                                  ('core2', 'start')]
         self.__core_log = self.__core_log_create + self.__core_log_start
-
-    def tearDown(self):
-        """
-        Clean up the special evaluated test components and other stuff.
-        """
-        BossUtils.tearDown(self)
-        specials = self.__orig_specials
+        self.__specials = { 'test': self.__component_test }
 
     def __component_test(self, process, boss, kind, address=None, params=None):
         """
@@ -527,7 +518,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         Tests the configurator can be created and it does not create
         any components yet, nor does it remember anything.
         """
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         self.assertEqual([], self.log)
         self.assertEqual({}, configurator._components)
         self.assertEqual({}, configurator._old_config)
@@ -541,7 +532,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         Also includes one that raises, so we see it just stops there.
         """
         # Prepare the configurator and the plan
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         started = self.__component_test('second', self, 'dispensable')
         started.start()
         stopped = self.__component_test('first', self, 'core')
@@ -581,7 +572,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         Test building the plan correctly. Not complete yet, this grows as we
         add more ways of changing the plan.
         """
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         plan = configurator._build_plan({}, self.__core)
         # This should have created the components
         self.assertEqual(self.__core_log_create, self.log)
@@ -682,7 +673,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         Start it with some component and then switch the configuration of the
         component. This will probably raise, as it is not yet supported.
         """
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         compconfig = {
             'special': 'test',
             'process': 'process',
@@ -735,7 +726,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
 
         It also checks the components are kept inside the configurator.
         """
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         # Can't reconfigure nor stop yet
         self.assertRaises(ValueError, configurator.reconfigure, self.__core)
         self.assertRaises(ValueError, configurator.shutdown)
@@ -786,7 +777,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         (or without priority), it failed as it couldn't compare the dicts
         there. This tests it doesn't crash.
         """
-        configurator = Configurator(self)
+        configurator = Configurator(self, self.__specials)
         configurator._build_plan({}, {"c1": {}, "c2": {}})
 
 if __name__ == '__main__':