Browse Source

moduleccsession now validates config updates before calling the provided config_handler
renamed validate() to validate_config() (plan on adding validate_command() as well)
added createAnswer function in cpp version


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jelte-configuration@880 e5f2f494-b856-4b98-b285-d166d9295462

Jelte Jansen 15 years ago
parent
commit
da8e6967bd

+ 1 - 9
src/bin/bind10/bind10.py.in

@@ -115,15 +115,7 @@ class BoB:
         if self.verbose:
             print("[XX] handling new config:")
             print(new_config)
-        errors = []
-        if self.ccs.get_module_spec().validate(False, new_config, errors):
-            self.ccs.set_local_config(new_config)
-            answer = isc.config.ccsession.create_answer(0)
-        else:
-            if len(errors) > 0:
-                answer = isc.config.ccsession.create_answer(1, " ".join(errors))
-            else:
-                answer = isc.config.ccsession.create_answer(1, "Unknown error in validation")
+        answer = isc.config.ccsession.create_answer(0)
         return answer
         # TODO
 

+ 27 - 4
src/lib/config/cpp/ccsession.cc

@@ -50,6 +50,26 @@ using isc::data::ParseError;
 namespace isc {
 namespace config {
 
+ElementPtr
+create_answer(const int rcode, const ElementPtr arg)
+{
+    ElementPtr answer = Element::createFromString("{\"result\": []");
+    ElementPtr answer_content = answer->get("result");
+    answer_content->add(Element::create(rcode));
+    answer_content->add(arg);
+    return answer;
+}
+
+ElementPtr
+create_answer(const int rcode, const std::string& arg)
+{
+    ElementPtr answer = Element::createFromString("{\"result\": []");
+    ElementPtr answer_content = answer->get("result");
+    answer_content->add(Element::create(rcode));
+    answer_content->add(Element::create(arg));
+    return answer;
+}
+
 void
 ModuleCCSession::read_module_specification(const std::string& filename) {
     std::ifstream file;
@@ -136,11 +156,14 @@ ModuleCCSession::check_command()
         cout << "[XX] got something!" << endl << data->str() << endl;
         ElementPtr answer;
         if (data->contains("config_update")) {
-            if (config_handler_) {
-                // handle config update
-                answer = config_handler_(data->get("config_update"));
+            ElementPtr new_config = data->get("config_update");
+            if (!config_handler_) {
+                answer = create_answer(1, module_name_ + " does not have a config handler");
+            } else if (!module_specification_.validate_config(new_config)) {
+                answer = create_answer(2, "Error in config validation");
             } else {
-                answer = Element::createFromString("{ \"result\": [0] }");
+                // handle config update
+                answer = config_handler_(new_config);
             }
         }
         if (data->contains("command")) {

+ 3 - 0
src/lib/config/cpp/ccsession.h

@@ -85,6 +85,9 @@ private:
     isc::data::ElementPtr(*command_handler_)(isc::data::ElementPtr command);
 };
 
+ElementPtr createAnswer(const int rcode, const ElementPtr arg);
+ElementPtr createAnswer(const int rcode, const std::string arg);
+
 }
 }
 #endif // __CCSESSION_H

+ 1 - 1
src/lib/config/cpp/module_spec.cc

@@ -209,7 +209,7 @@ ModuleSpec::getModuleName()
 }
 
 bool
-ModuleSpec::validate(const ElementPtr data)
+ModuleSpec::validate_config(const ElementPtr data)
 {
     ElementPtr spec = module_specification->find("module_spec/config_data");
     return validate_spec_list(spec, data);

+ 1 - 1
src/lib/config/cpp/module_spec.h

@@ -83,7 +83,7 @@ namespace isc { namespace config {
         /// \param data The base \c Element of the data to check
         /// \return true if the data conforms to the specification,
         /// false otherwise.
-        bool validate(const ElementPtr data);
+        bool validate_config(const ElementPtr data);
 
     private:
         bool validate_item(const ElementPtr spec, const ElementPtr data);

+ 1 - 1
src/lib/config/cpp/module_spec_unittests.cc

@@ -129,7 +129,7 @@ data_test(ModuleSpec dd, const std::string& data_file_name)
     ElementPtr data = Element::createFromString(data_file, data_file_name);
     data_file.close();
 
-    return dd.validate(data);
+    return dd.validate_config(data);
 }
 
 TEST(ModuleSpec, DataValidation) {

+ 10 - 3
src/lib/config/python/isc/config/ccsession.py

@@ -135,8 +135,15 @@ class ModuleCCSession(ConfigData):
         if msg:
             answer = None
             try:
-                if "config_update" in msg and self._config_handler:
-                    answer = self._config_handler(msg["config_update"])
+                if "config_update" in msg:
+                    new_config = msg["config_update"]
+                    errors = []
+                    if not self._config_handler:
+                        answer = create_answer(2, self._module_name + " has no config handler")
+                    elif not self.get_module_spec().validate_config(False, new_config, errors):
+                        answer = create_answer(1, " ".join(errors))
+                    else:
+                        answer = self._config_handler(msg["config_update"])
                 if "command" in msg and self._command_handler:
                     answer = self._command_handler(msg["command"])
             except Exception as exc:
@@ -168,7 +175,7 @@ class ModuleCCSession(ConfigData):
         answer, env = self._session.group_recvmsg(False)
         rcode, value = parse_answer(answer)
         if rcode == 0:
-            if value != None and self.get_module_spec().validate(False, value):
+            if value != None and self.get_module_spec().validate_config(False, value):
                 self.set_local_config(value);
                 if self._config_handler:
                     self._config_handler(value)

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

@@ -27,7 +27,8 @@ class ConfigDataError(Exception): pass
 
 def check_type(spec_part, value):
     """Returns true if the value is of the correct type given the
-       specification part relevant for the value"""
+       specification part relevant for the value. spec_part can be
+       retrieved with find_spec()"""
     if type(spec_part) == list:
         data_type = "list"
     else:

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

@@ -64,7 +64,7 @@ class ModuleSpec:
             _check(module_spec)
         self._module_spec = module_spec
 
-    def validate(self, full, data, errors = None):
+    def validate_config(self, full, data, errors = None):
         """Check whether the given piece of data conforms to this
            data definition. If so, it returns True. If not, it will
            return false. If errors is given, and is an array, a string

+ 1 - 1
src/lib/config/python/isc/config/module_spec_test.py

@@ -76,7 +76,7 @@ class TestModuleSpec(unittest.TestCase):
         data_file = open(self.spec_file(datafile_name))
         data_str = data_file.read()
         data = isc.cc.data.parse_value_str(data_str)
-        return dd.validate(True, data)
+        return dd.validate_config(True, data)
         
     def test_data_validation(self):
         self.assertEqual(True, self.validate_data("spec22.spec", "data22_1.data"))