Parcourir la source

same remote config stuff for the c++ side of modulesessions

git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1218 e5f2f494-b856-4b98-b285-d166d9295462
Jelte Jansen il y a 15 ans
Parent
commit
af72796acf

+ 81 - 6
src/lib/config/ccsession.cc

@@ -38,7 +38,6 @@
 #include <cc/session.h>
 #include <exceptions/exceptions.h>
 
-//#include "common.h"
 #include "ccsession.h"
 #include "config.h"
 
@@ -139,10 +138,11 @@ parseCommand(ElementPtr& arg, const ElementPtr command)
     return "";
 }
 
-void
+ModuleSpec
 ModuleCCSession::read_module_specification(const std::string& filename) {
     std::ifstream file;
-
+    ModuleSpec module_spec;
+    
     // this file should be declared in a @something@ directive
     file.open(filename.c_str());
     if (!file) {
@@ -151,7 +151,7 @@ ModuleCCSession::read_module_specification(const std::string& filename) {
     }
 
     try {
-        module_specification_ = moduleSpecFromFile(file, true);
+        module_spec = moduleSpecFromFile(file, true);
     } catch (ParseError pe) {
         cout << "Error parsing module specification file: " << pe.what() << endl;
         exit(1);
@@ -160,6 +160,7 @@ ModuleCCSession::read_module_specification(const std::string& filename) {
         exit(1);
     }
     file.close();
+    return module_spec;
 }
 
 ModuleCCSession::ModuleCCSession(std::string spec_file_name,
@@ -167,7 +168,7 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
                                isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)
                               ) throw (isc::cc::SessionError)
 {
-    read_module_specification(spec_file_name);
+    module_specification_ = read_module_specification(spec_file_name);
     sleep(1);
 
     module_name_ = module_specification_.getFullSpec()->get("module_name")->stringValue();
@@ -251,6 +252,7 @@ ModuleCCSession::check_command()
 {
     ElementPtr cmd, routing, data;
     if (session_.group_recvmsg(routing, data, true)) {
+        
         /* ignore result messages (in case we're out of sync, to prevent
          * pingpongs */
         if (!data->getType() == Element::map || data->contains("result")) {
@@ -260,7 +262,16 @@ ModuleCCSession::check_command()
         std::string cmd_str = parseCommand(arg, data);
         ElementPtr answer;
         if (cmd_str == "config_update") {
-            answer = handleConfigUpdate(arg);
+            std::string target_module = routing->get("group")->stringValue();
+            if (target_module == module_name_) {
+                answer = handleConfigUpdate(arg);
+            } else {
+                // ok this update is not for us, if we have this module
+                // in our remote config list, update that
+                updateRemoteConfig(target_module, arg);
+                // we're not supposed to answer to this, so return
+                return 0;
+            }
         } else {
             if (command_handler_) {
                 answer = command_handler_(cmd_str, arg);
@@ -274,5 +285,69 @@ ModuleCCSession::check_command()
     return 0;
 }
 
+std::string
+ModuleCCSession::addRemoteConfig(const std::string& spec_file_name)
+{
+    ModuleSpec rmod_spec = read_module_specification(spec_file_name);
+    std::string module_name = rmod_spec.getFullSpec()->get("module_name")->stringValue();
+    ConfigData rmod_config = ConfigData(rmod_spec);
+    session_.subscribe(module_name);
+
+    // Get the current configuration values for that module
+    ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name + "\"} ] }");
+    ElementPtr env, answer;
+    int rcode;
+    
+    session_.group_sendmsg(cmd, "ConfigManager");
+    session_.group_recvmsg(env, answer, false);
+    ElementPtr new_config = parseAnswer(rcode, answer);
+    if (rcode == 0) {
+        rmod_config.setLocalConfig(new_config);
+    } else {
+        isc_throw(CCSessionError, "Error getting config for " + module_name + ": " + answer->str());
+    }
+
+    // all ok, add it
+    remote_module_configs_[module_name] = rmod_config;
+    return module_name;
+}
+
+void
+ModuleCCSession::removeRemoteConfig(const std::string& module_name)
+{
+    std::map<std::string, ConfigData>::iterator it;
+
+    it = remote_module_configs_.find(module_name);
+    if (it != remote_module_configs_.end()) {
+        remote_module_configs_.erase(it);
+        session_.unsubscribe(module_name);
+    }
+}
+
+ElementPtr
+ModuleCCSession::getRemoteConfigValue(const std::string& module_name, const std::string& identifier)
+{
+    std::map<std::string, ConfigData>::iterator it;
+
+    it = remote_module_configs_.find(module_name);
+    if (it != remote_module_configs_.end()) {
+        return remote_module_configs_[module_name].getValue(identifier);
+    } else {
+        isc_throw(CCSessionError, "Remote module " + module_name + " not found.");
+    }
+}
+
+void
+ModuleCCSession::updateRemoteConfig(const std::string& module_name, ElementPtr new_config)
+{
+    std::map<std::string, ConfigData>::iterator it;
+
+    it = remote_module_configs_.find(module_name);
+    if (it != remote_module_configs_.end()) {
+        ElementPtr rconf = (*it).second.getLocalConfig();
+        isc::data::merge(rconf, new_config);
+    }
+}
+
 }
 }

+ 42 - 1
src/lib/config/ccsession.h

@@ -90,8 +90,46 @@ public:
      */
     void set_command_handler(isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args)) { command_handler_ = command_handler; };
 
+    /**
+     * Gives access to the configuration values of a different module
+     * Once this function has been called with the name of the specification
+     * file of the module you want the configuration of, you can use
+     * \c getRemoteConfigValue() to get a specific setting.
+     * Changes are automatically updated, but you cannot specify handlers
+     * for those changes, must use \c getRemoteConfigValue() to get a value
+     * This function will subscribe to the relevant module channel.
+     *
+     * \param spec_file_name The path to the specification file of
+     *                       the module we want to have configuration
+     *                       values from
+     * \return The name of the module specified in the given specification
+     *         file
+     */
+    std::string addRemoteConfig(const std::string& spec_file_name);
+
+    /**
+     * Removes the module with the given name from the remote config
+     * settings. If the module was not added with \c addRemoteConfig(),
+     * nothing happens.
+     */
+    void removeRemoteConfig(const std::string& module_name);
+
+    /**
+     * Returns the current configuration value for the given module
+     * name at the given identifier. See \c ConfigData::getValue() for
+     * more details.
+     * Raises a ModuleCCSessionError if the module name is unknown
+     * Raises a DataNotFoundError if the identifier does not exist
+     * in the specification.
+     *
+     * \param module_name The name of the module to get a config value for
+     * \param identifier The identifier of the config value
+     * \return The configuration setting at the given identifier
+     */
+    ElementPtr getRemoteConfigValue(const std::string& module_name, const std::string& identifier);
+    
 private:
-    void read_module_specification(const std::string& filename);
+    ModuleSpec read_module_specification(const std::string& filename);
     
     std::string module_name_;
     isc::cc::Session session_;
@@ -101,6 +139,9 @@ private:
 
     isc::data::ElementPtr(*config_handler_)(isc::data::ElementPtr new_config);
     isc::data::ElementPtr(*command_handler_)(const std::string& command, const isc::data::ElementPtr args);
+
+    std::map<std::string, ConfigData> remote_module_configs_;
+    void updateRemoteConfig(const std::string& module_name, ElementPtr new_config);
 };
 
 ElementPtr createAnswer(const int rcode);

+ 0 - 2
src/lib/python/isc/config/ccsession.py

@@ -195,8 +195,6 @@ class ModuleCCSession(ConfigData):
                             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.

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

@@ -267,8 +267,10 @@ class ConfigManager:
             got_error = False
             err_list = []
             for module in self.config.data:
-                if module != "version":
+                if module != "version" and self.config.data[module] != old_data[module]:
                     update_cmd = isc.config.ccsession.create_command(isc.config.ccsession.COMMAND_CONFIG_UPDATE, self.config.data[module])
+                    print("[XX] send update: " + str(update_cmd))
+                    print("[XX] to: " + str(module))
                     self.cc.group_sendmsg(update_cmd, module)
                     answer, env = self.cc.group_recvmsg(False)
                     if answer == None: