Browse Source

made config-specific commands also of the form of 'normal' commands, so they can be made with the same functions
updated cfgmgr to use these functions


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

Jelte Jansen 15 years ago
parent
commit
4b1e0bab42

+ 37 - 5
src/lib/config/cpp/ccsession.cc

@@ -103,6 +103,42 @@ parseAnswer(int &rcode, const ElementPtr msg)
     }
 }
 
+ElementPtr
+createCommand(const std::string& command, ElementPtr arg)
+{
+    ElementPtr cmd = Element::createFromString("{}");
+    ElementPtr cmd_parts = Element::createFromString("[]");
+    cmd_parts->add(Element::create(command));
+    if (arg) {
+        cmd_parts->add(arg);
+    }
+    cmd->set("command", cmd_parts);
+    return cmd;
+}
+
+/// Returns "" and empty ElementPtr() if this does not
+/// look like a command
+const std::string
+parseCommand(ElementPtr& arg, const ElementPtr command)
+{
+    if (command->getType() == Element::map &&
+        command->contains("command")) {
+        ElementPtr cmd = command->get("command");
+        if (cmd->getType() == Element::list &&
+            cmd->size() > 0 &&
+            cmd->get(0)->getType() == Element::string) {
+            if (cmd->size() > 1) {
+                arg = cmd->get(1);
+            } else {
+                arg = ElementPtr();
+            }
+            return cmd->get(0)->stringValue();
+        }
+    }
+    arg = ElementPtr();
+    return "";
+}
+
 void
 ModuleCCSession::read_module_specification(const std::string& filename) {
     std::ifstream file;
@@ -150,8 +186,7 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
     //session_.subscribe("Boss", "*");
     //session_.subscribe("statistics", "*");
     // send the data specification
-    ElementPtr spec_msg = Element::createFromString("{}");
-    spec_msg->set("module_spec", module_specification_.getFullSpec());
+    ElementPtr spec_msg = createCommand("module_spec", module_specification_.getFullSpec());
     session_.group_sendmsg(spec_msg, "ConfigManager");
     session_.group_recvmsg(env, answer, false);
     
@@ -160,7 +195,6 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
         ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
         session_.group_sendmsg(cmd, "ConfigManager");
         session_.group_recvmsg(env, answer, false);
-        cout << "[XX] got config: " << endl << answer->str() << endl;
         int rcode;
         ElementPtr new_config = parseAnswer(rcode, answer);
         handleConfigUpdate(new_config);
@@ -208,7 +242,6 @@ ModuleCCSession::getSocket()
 int
 ModuleCCSession::check_command()
 {
-    cout << "[XX] check for command" << endl;
     ElementPtr cmd, routing, data;
     if (session_.group_recvmsg(routing, data, true)) {
         /* ignore result messages (in case we're out of sync, to prevent
@@ -216,7 +249,6 @@ ModuleCCSession::check_command()
         if (!data->getType() == Element::map || data->contains("result")) {
             return 0;
         }
-        cout << "[XX] got something!" << endl << data->str() << endl;
         ElementPtr answer;
         if (data->contains("config_update")) {
             ElementPtr new_config = data->get("config_update");

+ 9 - 4
src/lib/config/python/isc/config/ccsession.py

@@ -83,6 +83,7 @@ COMMAND_GET_COMMANDS_SPEC = "get_commands_spec"
 COMMAND_GET_CONFIG = "get_config"
 COMMAND_SET_CONFIG = "set_config"
 COMMAND_GET_MODULE_SPEC = "get_module_spec"
+COMMAND_MODULE_SPEC = "module_spec"
 
 def parse_command(msg):
     """Parses what may be a command message. If it looks like one,
@@ -90,8 +91,11 @@ def parse_command(msg):
        string. If it is not, this function returns None, None"""
     if type(msg) == dict and len(msg.items()) == 1:
         cmd, value = msg.popitem()
-        if type(cmd) == str:
-            return cmd, value
+        if cmd == "command" and type(value) == list:
+            if len(value) == 1:
+                return value[0], None
+            elif len(value) > 1:
+                return value[0], value[1]
     return None, None
 
 def create_command(command_name, params = None):
@@ -197,7 +201,8 @@ class ModuleCCSession(ConfigData):
 
     def __send_spec(self):
         """Sends the data specification to the configuration manager"""
-        self._session.group_sendmsg({ "module_spec": self.get_module_spec().get_full_spec() }, "ConfigManager")
+        msg = create_command(COMMAND_MODULE_SPEC, self.get_module_spec().get_full_spec())
+        self._session.group_sendmsg(msg, "ConfigManager")
         answer, env = self._session.group_recvmsg(False)
         
     def __request_config(self):
@@ -289,7 +294,7 @@ class UIModuleCCSession(MultiConfigData):
         """Commit all local changes, send them through b10-cmdctl to
            the configuration manager"""
         if self.get_local_changes():
-            self._conn.send_POST('/ConfigManager/set_config', self.get_local_changes())
+            self._conn.send_POST('/ConfigManager/set_config', [ self.get_local_changes() ])
             # todo: check result
             self.request_current_config()
             self.clear_local_changes()

+ 47 - 46
src/lib/config/python/isc/config/cfgmgr.py

@@ -189,10 +189,10 @@ class ConfigManager:
     def _handle_get_module_spec(self, cmd):
         """Private function that handles the 'get_module_spec' command"""
         answer = {}
-        if len(cmd) > 1:
-            if type(cmd[1]) == dict:
-                if 'module_name' in cmd[1] and cmd[1]['module_name'] != '':
-                    module_name = cmd[1]['module_name']
+        if cmd != None:
+            if type(cmd) == dict:
+                if 'module_name' in cmd and cmd['module_name'] != '':
+                    module_name = cmd['module_name']
                     answer = isc.config.ccsession.create_answer(0, self.get_config_spec(module_name))
                 else:
                     answer = isc.config.ccsession.create_answer(1, "Bad module_name in get_module_spec command")
@@ -205,10 +205,10 @@ class ConfigManager:
     def _handle_get_config(self, cmd):
         """Private function that handles the 'get_config' command"""
         answer = {}
-        if len(cmd) > 1:
-            if type(cmd[1]) == dict:
-                if 'module_name' in cmd[1] and cmd[1]['module_name'] != '':
-                    module_name = cmd[1]['module_name']
+        if cmd != None:
+            if type(cmd) == dict:
+                if 'module_name' in cmd and cmd['module_name'] != '':
+                    module_name = cmd['module_name']
                     try:
                         answer = isc.config.ccsession.create_answer(0, data.find(self.config.data, module_name))
                     except data.DataNotFoundError as dnfe:
@@ -226,19 +226,19 @@ class ConfigManager:
     def _handle_set_config(self, cmd):
         """Private function that handles the 'set_config' command"""
         answer = None
-        if len(cmd) == 3:
+        if cmd == None:
+            return isc.config.ccsession.create_answer(1, "Wrong number of arguments")
+        if len(cmd) == 2:
             # todo: use api (and check the data against the definition?)
-            module_name = cmd[1]
+            module_name = cmd[0]
             conf_part = data.find_no_exc(self.config.data, module_name)
-            print("[XX] cfgmgr conf part:")
-            print(conf_part)
             if conf_part:
-                data.merge(conf_part, cmd[2])
+                data.merge(conf_part, cmd[1])
                 self.cc.group_sendmsg({ "config_update": conf_part }, module_name)
                 answer, env = self.cc.group_recvmsg(False)
             else:
                 conf_part = data.set(self.config.data, module_name, {})
-                data.merge(conf_part[module_name], cmd[2])
+                data.merge(conf_part[module_name], cmd[1])
                 # send out changed info
                 self.cc.group_sendmsg({ "config_update": conf_part[module_name] }, module_name)
                 # replace 'our' answer with that of the module
@@ -246,10 +246,10 @@ class ConfigManager:
             rcode, val = isc.config.ccsession.parse_answer(answer)
             if rcode == 0:
                 self.write_config()
-        elif len(cmd) == 2:
+        elif len(cmd) == 1:
             # todo: use api (and check the data against the definition?)
             old_data = self.config.data.copy()
-            data.merge(self.config.data, cmd[1])
+            data.merge(self.config.data, cmd[0])
             # send out changed info
             got_error = False
             err_list = []
@@ -269,6 +269,7 @@ class ConfigManager:
                 self.config.data = old_data
                 answer = isc.config.ccsession.create_answer(1, " ".join(err_list))
         else:
+            print(cmd)
             answer = isc.config.ccsession.create_answer(1, "Wrong number of arguments")
         if not answer:
             answer = isc.config.ccsession.create_answer(1, "Error handling set_config command")
@@ -285,42 +286,42 @@ class ConfigManager:
         
         # We should make one general 'spec update for module' that
         # passes both specification and commands at once
-        self.cc.group_sendmsg({ "specification_update": [ spec.get_module_name(), spec.get_config_spec() ] }, "Cmd-Ctrld")
-        self.cc.group_sendmsg({ "commands_update": [ spec.get_module_name(), spec.get_commands_spec() ] }, "Cmd-Ctrld")
+        spec_update = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_SPECIFICATION_UPDATE,
+                                                          [ spec.get_module_name(), spec.get_config_spec() ])
+        self.cc.group_sendmsg(spec_update, "Cmd-Ctrld")
+        cmds_update = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_COMMANDS_UPDATE,
+                                                          [ spec.get_module_name(), spec.get_commands_spec() ])
+        self.cc.group_sendmsg(cmds_update, "Cmd-Ctrld")
         answer = isc.config.ccsession.create_answer(0)
         return answer
 
     def handle_msg(self, msg):
         """Handle a command from the cc channel to the configuration manager"""
         answer = {}
-        if "command" in msg:
-            cmd = msg["command"]
-            try:
-                if cmd[0] == "get_commands_spec":
-                    answer = isc.config.ccsession.create_answer(0, self.get_commands_spec())
-                elif cmd[0] == "get_module_spec":
-                    answer = self._handle_get_module_spec(cmd)
-                elif cmd[0] == "get_config":
-                    answer = self._handle_get_config(cmd)
-                elif cmd[0] == "set_config":
-                    answer = self._handle_set_config(cmd)
-                elif cmd[0] == "shutdown":
-                    print("[bind-cfgd] Received shutdown command")
-                    self.running = False
-                    answer = isc.config.ccsession.create_answer(0)
-                else:
-                    answer = isc.config.ccsession.create_answer(1, "Unknown command: " + str(cmd))
-            except IndexError as ie:
-                answer = isc.config.ccsession.create_answer(1, "Missing argument in command: " + str(ie))
-                raise ie
-        elif "module_spec" in msg:
-            try:
-                answer = self._handle_module_spec(isc.config.ModuleSpec(msg["module_spec"]))
-            except isc.config.ModuleSpecError as dde:
-                answer = isc.config.ccsession.create_answer(1, "Error in data definition: " + str(dde))
-        elif 'result' in msg:
-            # this seems wrong, might start pingpong
-            answer = isc.config.ccsession.create_answer(0)
+        #print("[XX] got msg:")
+        #print(msg)
+        cmd, arg = isc.config.ccsession.parse_command(msg)
+        if cmd:
+            #print("[XX] cmd: " + cmd)
+            if cmd == isc.config.ccsession.COMMAND_GET_COMMANDS_SPEC:
+                answer = isc.config.ccsession.create_answer(0, self.get_commands_spec())
+            elif cmd == isc.config.ccsession.COMMAND_GET_MODULE_SPEC:
+                answer = self._handle_get_module_spec(arg)
+            elif cmd == isc.config.ccsession.COMMAND_GET_CONFIG:
+                answer = self._handle_get_config(arg)
+            elif cmd == isc.config.ccsession.COMMAND_SET_CONFIG:
+                answer = self._handle_set_config(arg)
+            elif cmd == "shutdown":
+                print("[b10-cfgmgr] Received shutdown command")
+                self.running = False
+                answer = isc.config.ccsession.create_answer(0)
+            elif cmd == isc.config.ccsession.COMMAND_MODULE_SPEC:
+                try:
+                    answer = self._handle_module_spec(isc.config.ModuleSpec(arg))
+                except isc.config.ModuleSpecError as dde:
+                    answer = isc.config.ccsession.create_answer(1, "Error in data definition: " + str(dde))
+            else:
+                answer = isc.config.ccsession.create_answer(1, "Unknown command: " + str(cmd))
         else:
             answer = isc.config.ccsession.create_answer(1, "Unknown message format: " + str(msg))
         return answer

+ 7 - 9
src/lib/config/python/isc/config/cfgmgr_test.py

@@ -210,7 +210,7 @@ class TestConfigManager(unittest.TestCase):
     def test_handle_msg(self):
         self._handle_msg_helper({}, { 'result': [ 1, 'Unknown message format: {}']})
         self._handle_msg_helper("", { 'result': [ 1, 'Unknown message format: ']})
-        self._handle_msg_helper({ "command": [ "badcommand" ] }, { 'result': [ 1, "Unknown command: ['badcommand']"]})
+        self._handle_msg_helper({ "command": [ "badcommand" ] }, { 'result': [ 1, "Unknown command: badcommand"]})
         self._handle_msg_helper({ "command": [ "get_commands_spec" ] }, { 'result': [ 0, {} ]})
         self._handle_msg_helper({ "command": [ "get_module_spec" ] }, { 'result': [ 0, {} ]})
         #self._handle_msg_helper({ "command": [ "get_module_spec", { "module_name": "nosuchmodule" } ] },
@@ -228,7 +228,7 @@ class TestConfigManager(unittest.TestCase):
                                 {'result': [1, 'Bad module_name in get_config command']})
         self._handle_msg_helper({ "command": [ "set_config" ] },
                                 {'result': [1, 'Wrong number of arguments']})
-        self._handle_msg_helper({ "command": [ "set_config", {} ] },
+        self._handle_msg_helper({ "command": [ "set_config", [{}]] },
                                 {'result': [0]})
         self.assertEqual(len(self.fake_session.message_queue), 0)
 
@@ -237,13 +237,13 @@ class TestConfigManager(unittest.TestCase):
         my_ok_answer = { 'result': [ 0 ] }
 
         self.fake_session.group_sendmsg(my_ok_answer, "ConfigManager")
-        self._handle_msg_helper({ "command": [ "set_config", self.name, { "test": 123 } ] },
+        self._handle_msg_helper({ "command": [ "set_config", [self.name, { "test": 123 }] ] },
                                 my_ok_answer)
         self.assertEqual(len(self.fake_session.message_queue), 1)
         self.fake_session.group_sendmsg(my_ok_answer, "ConfigManager")
         self.assertEqual({'config_update': {'test': 123}},
                          self.fake_session.get_message(self.name, None))
-        self._handle_msg_helper({ "command": [ "set_config", self.name, { "test": 124 } ] },
+        self._handle_msg_helper({ "command": [ "set_config", [self.name, { "test": 124 }] ] },
                                 {'result': [0]})
 
         #print(self.fake_session.message_queue)
@@ -251,13 +251,11 @@ class TestConfigManager(unittest.TestCase):
         self.assertEqual({'config_update': {'test': 124}},
                          self.fake_session.get_message(self.name, None))
         self.assertEqual({'version': 1, 'TestModule': {'test': 124}}, self.cm.config.data)
-        self._handle_msg_helper({ "module_spec": 
-                                  self.spec.get_full_spec()
+        self._handle_msg_helper({ "command": 
+                                  ["module_spec", self.spec.get_full_spec()]
                                 },
                                 {'result': [0]})
-        self._handle_msg_helper({ "module_spec": 
-                                  { 'foo': 1 }
-                                },
+        self._handle_msg_helper({ "command": [ "module_spec", { 'foo': 1 } ] },
                                 {'result': [1, 'Error in data definition: no module_name in module_spec']})
         self._handle_msg_helper({ "command": [ "get_module_spec" ] }, { 'result': [ 0, { self.spec.get_module_name(): self.spec.get_config_spec() } ]})
         self._handle_msg_helper({ "command": [ "get_commands_spec" ] }, { 'result': [ 0, { self.spec.get_module_name(): self.spec.get_commands_spec() } ]})

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

@@ -103,7 +103,6 @@ def spec_name_list(spec, prefix="", recurse=False):
             for name in spec:
                 result.append(prefix + name + "/")
                 if recurse:
-                    print("[XX] recurse1")
                     result.extend(spec_name_list(spec[name],name, recurse))
     elif type(spec) == list:
         for list_el in spec:

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

@@ -29,7 +29,6 @@ class TestConfigData(unittest.TestCase):
         else:
             self.data_path = "../../../testdata"
         spec = isc.config.module_spec_from_file(self.data_path + os.sep + "spec2.spec")
-        print("SPEC: " + str(type(spec)))
         self.cd = ConfigData(spec)
 
     #def test_module_spec_from_file(self):

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

@@ -51,7 +51,6 @@ def module_spec_from_file(spec_file, check = True):
         raise ModuleSpecError("Data definition has no module_spec element")
         
     result = ModuleSpec(module_spec['module_spec'], check)
-    print("RETURNING: " + str(type(result)))
     return result
 
 class ModuleSpec: