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:
         if self.verbose:
             print("[XX] handling new config:")
             print("[XX] handling new config:")
             print(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
         return answer
         # TODO
         # TODO
 
 

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

@@ -50,6 +50,26 @@ using isc::data::ParseError;
 namespace isc {
 namespace isc {
 namespace config {
 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
 void
 ModuleCCSession::read_module_specification(const std::string& filename) {
 ModuleCCSession::read_module_specification(const std::string& filename) {
     std::ifstream file;
     std::ifstream file;
@@ -136,11 +156,14 @@ ModuleCCSession::check_command()
         cout << "[XX] got something!" << endl << data->str() << endl;
         cout << "[XX] got something!" << endl << data->str() << endl;
         ElementPtr answer;
         ElementPtr answer;
         if (data->contains("config_update")) {
         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 {
             } else {
-                answer = Element::createFromString("{ \"result\": [0] }");
+                // handle config update
+                answer = config_handler_(new_config);
             }
             }
         }
         }
         if (data->contains("command")) {
         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);
     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
 #endif // __CCSESSION_H

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

@@ -209,7 +209,7 @@ ModuleSpec::getModuleName()
 }
 }
 
 
 bool
 bool
-ModuleSpec::validate(const ElementPtr data)
+ModuleSpec::validate_config(const ElementPtr data)
 {
 {
     ElementPtr spec = module_specification->find("module_spec/config_data");
     ElementPtr spec = module_specification->find("module_spec/config_data");
     return validate_spec_list(spec, 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
         /// \param data The base \c Element of the data to check
         /// \return true if the data conforms to the specification,
         /// \return true if the data conforms to the specification,
         /// false otherwise.
         /// false otherwise.
-        bool validate(const ElementPtr data);
+        bool validate_config(const ElementPtr data);
 
 
     private:
     private:
         bool validate_item(const ElementPtr spec, const ElementPtr data);
         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);
     ElementPtr data = Element::createFromString(data_file, data_file_name);
     data_file.close();
     data_file.close();
 
 
-    return dd.validate(data);
+    return dd.validate_config(data);
 }
 }
 
 
 TEST(ModuleSpec, DataValidation) {
 TEST(ModuleSpec, DataValidation) {

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

@@ -135,8 +135,15 @@ class ModuleCCSession(ConfigData):
         if msg:
         if msg:
             answer = None
             answer = None
             try:
             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:
                 if "command" in msg and self._command_handler:
                     answer = self._command_handler(msg["command"])
                     answer = self._command_handler(msg["command"])
             except Exception as exc:
             except Exception as exc:
@@ -168,7 +175,7 @@ class ModuleCCSession(ConfigData):
         answer, env = self._session.group_recvmsg(False)
         answer, env = self._session.group_recvmsg(False)
         rcode, value = parse_answer(answer)
         rcode, value = parse_answer(answer)
         if rcode == 0:
         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);
                 self.set_local_config(value);
                 if self._config_handler:
                 if self._config_handler:
                     self._config_handler(value)
                     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):
 def check_type(spec_part, value):
     """Returns true if the value is of the correct type given the
     """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:
     if type(spec_part) == list:
         data_type = "list"
         data_type = "list"
     else:
     else:

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

@@ -64,7 +64,7 @@ class ModuleSpec:
             _check(module_spec)
             _check(module_spec)
         self._module_spec = 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
         """Check whether the given piece of data conforms to this
            data definition. If so, it returns True. If not, it will
            data definition. If so, it returns True. If not, it will
            return false. If errors is given, and is an array, a string
            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_file = open(self.spec_file(datafile_name))
         data_str = data_file.read()
         data_str = data_file.read()
         data = isc.cc.data.parse_value_str(data_str)
         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):
     def test_data_validation(self):
         self.assertEqual(True, self.validate_data("spec22.spec", "data22_1.data"))
         self.assertEqual(True, self.validate_data("spec22.spec", "data22_1.data"))