Commit da8e6967 authored by Jelte Jansen's avatar Jelte Jansen

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
parent f3a53f55
......@@ -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
......
......@@ -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")) {
......
......@@ -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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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)
......
......@@ -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:
......
......@@ -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
......
......@@ -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"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment