Browse Source

[213] High level reconfigure and shutdown

With tests. Includes a bugfix, the _build_plan did not include the name
when asking to shut down a component.
Michal 'vorner' Vaner 13 years ago
parent
commit
a730ddd17c

+ 20 - 6
src/lib/python/isc/bind10/component.py

@@ -182,6 +182,13 @@ class Configurator:
         self._old_config = {}
         self._old_config = {}
         self._running = False
         self._running = False
 
 
+    def __reconfigure_internal(self, old, new):
+        """
+        Does a switch from one configuration to another.
+        """
+        self._run_plan(self._build_plan(old, new))
+        self._old_config = new
+
     def startup(self, configuration):
     def startup(self, configuration):
         """
         """
         Starts the first set of processes. This configuration is expected
         Starts the first set of processes. This configuration is expected
@@ -191,22 +198,28 @@ class Configurator:
         if self._running:
         if self._running:
             raise ValueError("Trying to start the component configurator " +
             raise ValueError("Trying to start the component configurator " +
                              "twice")
                              "twice")
-        self._run_plan(self._build_plan({}, configuration))
-        self._old_config = configuration
+        self.__reconfigure_internal({}, configuration)
         self._running = True
         self._running = True
 
 
     def shutdown(self):
     def shutdown(self):
         """
         """
         Shuts everything down.
         Shuts everything down.
         """
         """
-        pass
+        if not self._running:
+            raise ValueError("Trying to shutdown the component " +
+                             "configurator while it's not yet running")
+        self.__reconfigure_internal(self._old_config, {})
+        self._running = False
 
 
-    def reconfigure(configuration):
+    def reconfigure(self, configuration):
         """
         """
         Changes configuration from the current one to the provided. It
         Changes configuration from the current one to the provided. It
         starts and stops all the components as needed.
         starts and stops all the components as needed.
         """
         """
-        pass
+        if not self._running:
+            raise ValueError("Trying to reconfigure the component " +
+                             "configurator while it's not yet running")
+        self.__reconfigure_internal(self._old_config, configuration)
 
 
     def _build_plan(self, old, new):
     def _build_plan(self, old, new):
         """
         """
@@ -227,7 +240,8 @@ class Configurator:
                 if component.running():
                 if component.running():
                     plan.append({
                     plan.append({
                         'command': 'stop',
                         'command': 'stop',
-                        'component': component
+                        'component': component,
+                        'name': cname
                     })
                     })
         # Handle transitions of configuration of what is here
         # Handle transitions of configuration of what is here
         for cname in new.keys():
         for cname in new.keys():

+ 52 - 2
src/lib/python/isc/bind10/tests/component_test.py

@@ -566,6 +566,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         self.assertEqual([], self.log)
         self.assertEqual([], self.log)
         self.assertEqual([{
         self.assertEqual([{
             'command': 'stop',
             'command': 'stop',
+            'name': 'additional',
             'component': component
             'component': component
         }], plan)
         }], plan)
 
 
@@ -585,6 +586,7 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
                          self.log)
                          self.log)
         self.assertEqual(2, len(plan))
         self.assertEqual(2, len(plan))
         self.assertEqual('stop', plan[0]['command'])
         self.assertEqual('stop', plan[0]['command'])
+        self.assertEqual('additional', plan[0]['name'])
         self.assertTrue('component' in plan[0])
         self.assertTrue('component' in plan[0])
         self.assertEqual('start', plan[1]['command'])
         self.assertEqual('start', plan[1]['command'])
         self.assertEqual('another', plan[1]['name'])
         self.assertEqual('another', plan[1]['name'])
@@ -625,14 +627,34 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         # instance
         # instance
         self.assertEqual([], self.__do_switch('special', 'test'))
         self.assertEqual([], self.__do_switch('special', 'test'))
 
 
-    def test_startup(self):
+    def __check_shutdown_log(self):
+        """
+        Checks the log for shutting down from the core configuration.
+        """
+        # We know everything must be stopped, we know what it is.
+        # But we don't know the order, so we check everything is exactly
+        # once in the log
+        components = set(self.__core.keys())
+        for (name, command) in self.log:
+            self.assertEqual('stop', command)
+            self.assertTrue(name in components)
+            components.remove(name)
+        self.assertEqual(set([]), components, "Some component wasn't stopped")
+
+    def test_run(self):
         """
         """
         Passes some configuration to the startup method and sees if
         Passes some configuration to the startup method and sees if
-        the components are started up.
+        the components are started up. Then it reconfigures it with
+        empty configuration, the original configuration again and shuts
+        down.
 
 
         It also checks the components are kept inside the configurator.
         It also checks the components are kept inside the configurator.
         """
         """
         configurator = Configurator(self)
         configurator = Configurator(self)
+        # Can't reconfigure nor stop yet
+        self.assertRaises(ValueError, configurator.reconfigure, self.__core)
+        self.assertRaises(ValueError, configurator.shutdown)
+        # Start it
         configurator.startup(self.__core)
         configurator.startup(self.__core)
         self.assertEqual(self.__core_log, self.log)
         self.assertEqual(self.__core_log, self.log)
         for core in self.__core.keys():
         for core in self.__core.keys():
@@ -642,6 +664,34 @@ class ConfiguratorTest(BossUtils, unittest.TestCase):
         # It can't be started twice
         # It can't be started twice
         self.assertRaises(ValueError, configurator.startup, self.__core)
         self.assertRaises(ValueError, configurator.startup, self.__core)
 
 
+        self.log = []
+        # Reconfigure - stop everything
+        configurator.reconfigure({})
+        self.assertEqual({}, configurator._components)
+        self.assertEqual({}, configurator._old_config)
+        self.assertTrue(configurator._running)
+        self.__check_shutdown_log()
+
+        # Start it again
+        self.log = []
+        configurator.reconfigure(self.__core)
+        self.assertEqual(self.__core_log, self.log)
+        for core in self.__core.keys():
+            self.assertTrue(core in configurator._components)
+        self.assertEqual(self.__core, configurator._old_config)
+        self.assertTrue(configurator._running)
+
+        # Do a shutdown
+        self.log = []
+        configurator.shutdown()
+        self.assertEqual({}, configurator._components)
+        self.assertEqual({}, configurator._old_config)
+        self.assertFalse(configurator._running)
+        self.__check_shutdown_log()
+
+        # It can't be stopped twice
+        self.assertRaises(ValueError, configurator.shutdown)
+
 if __name__ == '__main__':
 if __name__ == '__main__':
     isc.log.init("bind10") # FIXME Should this be needed?
     isc.log.init("bind10") # FIXME Should this be needed?
     isc.log.resetUnitTestRootLogger()
     isc.log.resetUnitTestRootLogger()