Browse Source

added support for access to the configuration settings of other modules
(on the python side)

ModuleCCSession.add_remote_config(specfile) sets this up; you provide it the spec file of the module you want a setting from. Config updates will be caught so the get function below should always give you the latest error.
(there is no rollback yet, so if the other module does not accept the new value for any reason this is currently missed here)

ModuleCCSession.get_remote_config_value(module name, identifier) returns the same value,default tuple as ConfigData::get_value(identifier), but obviously for the remote module

ModuleCCSession.remove_remote_config(module_name) removes the remote config settings again.


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1205 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
06da514e02

+ 59 - 1
src/lib/python/isc/config/ccsession.py

@@ -148,6 +148,8 @@ class ModuleCCSession(ConfigData):
             self._session = cc_session
         self._session.group_subscribe(self._module_name, "*")
 
+        self._remote_module_configs = {}
+
     def start(self):
         """Send the specification for this module to the configuration
            manager, and request the current non-default configuration.
@@ -183,6 +185,21 @@ class ModuleCCSession(ConfigData):
                 cmd, arg = isc.config.ccsession.parse_command(msg)
                 if cmd == COMMAND_CONFIG_UPDATE:
                     new_config = arg
+                    module_name = env['group']
+                    # If the target channel was not this module
+                    # it might be in the remote_module_configs
+                    if module_name != self._module_name:
+                        if module_name in self._remote_module_configs:
+                            # no checking for validity, that's up to the
+                            # module itself.
+                            newc = self._remote_module_configs[module_name].get_local_config()
+                            isc.cc.data.merge(newc, new_config)
+                            self._remote_module_configs[module_name].set_local_config(newc)
+                            print("[XX] updated remote config value: ")
+                            print(newc)
+                            return
+
+                    # ok, so apparently this update is for us.
                     errors = []
                     if not self._config_handler:
                         answer = create_answer(2, self._module_name + " has no config handler")
@@ -202,7 +219,6 @@ class ModuleCCSession(ConfigData):
                     else:
                         answer = create_answer(2, self._module_name + " has no command handler")
             except Exception as exc:
-                print("error! " + str(exc))
                 answer = create_answer(1, str(exc))
                 raise exc
             if answer:
@@ -221,6 +237,47 @@ class ModuleCCSession(ConfigData):
            and return an answer created with create_answer()"""
         self._command_handler = command_handler
 
+    def add_remote_config(self, spec_file_name):
+        """Gives access to the configuration of a different module.
+           These remote module options can at this moment only be
+           accessed through get_remote_config_value(). This function
+           also subscribes to the channel of the remote module name
+           to receive the relevant updates. It is not possible to
+           specify your own handler for this right now.
+           Returns the name of the module."""
+        module_spec = isc.config.module_spec_from_file(spec_file_name)
+        module_cfg = ConfigData(module_spec)
+        module_name = module_spec.get_module_name()
+        self._session.group_subscribe(module_name);
+
+        # Get the current config for that module now
+        self._session.group_sendmsg({ "command": [ "get_config", { "module_name": module_name } ] }, "ConfigManager")
+        answer, env = self._session.group_recvmsg(False)
+        if answer:
+            rcode, value = parse_answer(answer)
+            if rcode == 0:
+                if value != None and self.get_module_spec().validate_config(False, value):
+                    module_cfg.set_local_config(value);
+
+        # all done, add it
+        self._remote_module_configs[module_name] = module_cfg
+        return module_name
+        
+    def remove_remote_config(self, module_name):
+        """Removes the remote configuration access for this module"""
+        if module_name in self._remote_module_configs:
+            del self._remote_module_configs[module_name]
+
+    def get_remote_config_value(self, module_name, identifier):
+        """Returns the current setting for the given identifier at the
+           given module. If the module has not been added with
+           add_remote_config, a ModuleCCSessionError is raised"""
+        if module_name in self._remote_module_configs:
+            return self._remote_module_configs[module_name].get_value(identifier)
+        else:
+            raise ModuleCCSessionError("Remote module " + module_name +
+                                       " not found")
+
     def __send_spec(self):
         """Sends the data specification to the configuration manager"""
         msg = create_command(COMMAND_MODULE_SPEC, self.get_module_spec().get_full_spec())
@@ -245,6 +302,7 @@ class ModuleCCSession(ConfigData):
         else:
             raise ModuleCCSessionError("No answer from configuration manager")
 
+
 class UIModuleCCSession(MultiConfigData):
     """This class is used in a configuration user interface. It contains
        specific functions for getting, displaying, and sending

+ 0 - 1
src/lib/python/isc/config/cfgmgr.py

@@ -316,7 +316,6 @@ class ConfigManager:
         """Handle a command from the cc channel to the configuration manager"""
         answer = {}
         cmd, arg = isc.config.ccsession.parse_command(msg)
-        print("[b10-cfgmgr] got message: " + str(msg))
         if cmd:
             if cmd == isc.config.ccsession.COMMAND_GET_COMMANDS_SPEC:
                 answer = isc.config.ccsession.create_answer(0, self.get_commands_spec())

+ 17 - 0
src/lib/python/isc/config/unittests/ccsession_test.py

@@ -343,6 +343,23 @@ class TestModuleCCSession(unittest.TestCase):
         mccs.check_command()
         self.assertEqual(len(fake_session.message_queue), 0)
 
+    def test_remote_module(self):
+        fake_session = FakeModuleCCSession()
+        mccs = self.create_session("spec1.spec", None, None, fake_session)
+        mccs.remove_remote_config("Spec2")
+
+        self.assertRaises(ModuleCCSessionError, mccs.get_remote_config_value, "Spec2", "item1")
+
+        rmodname = mccs.add_remote_config(self.spec_file("spec2.spec"))
+        self.assertEqual("Spec2", rmodname)
+        self.assertRaises(isc.cc.data.DataNotFoundError, mccs.get_remote_config_value, rmodname, "asdf")
+        value, default = mccs.get_remote_config_value(rmodname, "item1")
+        self.assertEqual(1, value)
+        self.assertEqual(True, default)
+
+        mccs.remove_remote_config(rmodname)
+        self.assertRaises(ModuleCCSessionError, mccs.get_remote_config_value, "Spec2", "item1")
+    
 class fakeUIConn():
     def __init__(self):
         self.get_answers = {}