Ejemplo n.º 1
0
 def __handle_set_config_all(self, cmd):
     old_data = copy.deepcopy(self.config.data)
     got_error = False
     err_list = []
     # The format of the command is a dict with module->newconfig
     # sets, so we simply call set_config_module for each of those
     for module in cmd:
         if module != "version":
             answer = self.__handle_set_config_module(module, cmd[module])
             if answer == None:
                 got_error = True
                 err_list.append("No answer message from " + module)
             else:
                 rcode, val = ccsession.parse_answer(answer)
                 if rcode != 0:
                     got_error = True
                     err_list.append(val)
     if not got_error:
         # if Logging config is in there, update our config as well
         self.check_logging_config(cmd);
         self.write_config()
         return ccsession.create_answer(0)
     else:
         # TODO rollback changes that did get through, should we re-send update?
         self.config.data = old_data
         return ccsession.create_answer(1, " ".join(err_list))
Ejemplo n.º 2
0
 def __handle_set_config_all(self, cmd):
     old_data = copy.deepcopy(self.config.data)
     got_error = False
     err_list = []
     # The format of the command is a dict with module->newconfig
     # sets, so we simply call set_config_module for each of those
     for module in cmd:
         if module != "version":
             answer = self.__handle_set_config_module(module, cmd[module])
             if answer == None:
                 got_error = True
                 err_list.append("No answer message from " + module)
             else:
                 rcode, val = ccsession.parse_answer(answer)
                 if rcode != 0:
                     got_error = True
                     err_list.append(val)
     if not got_error:
         # if Logging config is in there, update our config as well
         self.check_logging_config(cmd)
         self.write_config()
         return ccsession.create_answer(0)
     else:
         # TODO rollback changes that did get through, should we re-send update?
         self.config.data = old_data
         return ccsession.create_answer(1, " ".join(err_list))
Ejemplo n.º 3
0
    def __handle_set_config_module(self, module_name, cmd):
        # the answer comes (or does not come) from the relevant module
        # so we need a variable to see if we got it
        answer = None
        # todo: use api (and check the data against the definition?)
        old_data = copy.deepcopy(self.config.data)
        conf_part = data.find_no_exc(self.config.data, module_name)
        update_cmd = None
        use_part = None
        if conf_part:
            data.merge(conf_part, cmd)
            use_part = conf_part
        else:
            conf_part = data.set(self.config.data, module_name, {})
            data.merge(conf_part[module_name], cmd)
            use_part = conf_part[module_name]

        # The command to send
        update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE,
                                              use_part)

        # TODO: This design might need some revisiting. We might want some
        # polymorphism instead of branching. But it just might turn out it
        # will get solved by itself when we move everything to virtual modules
        # (which is possible solution to the offline configuration problem)
        # or when we solve the incorrect behaviour here when a config is
        # rejected (spying modules don't know it was rejected and some modules
        # might have been committed already).
        if module_name in self.virtual_modules:
            # The module is virtual, so call it to get the answer
            try:
                error = self.virtual_modules[module_name](use_part)
                if error is None:
                    answer = ccsession.create_answer(0)
                    # OK, it is successful, send the notify, but don't wait
                    # for answer
                    seq = self.cc.group_sendmsg(update_cmd, module_name)
                else:
                    answer = ccsession.create_answer(1, error)
            # Make sure just a validating plugin don't kill the whole manager
            except Exception as excp:
                # Provide answer
                answer = ccsession.create_answer(1, "Exception: " + str(excp))
        else:
            # Real module, send it over the wire to it
            # send out changed info and wait for answer
            seq = self.cc.group_sendmsg(update_cmd, module_name)
            try:
                # replace 'our' answer with that of the module
                answer, env = self.cc.group_recvmsg(False, seq)
            except bundy.cc.SessionTimeout:
                answer = ccsession.create_answer(1, "Timeout waiting for answer from " + module_name)
            except bundy.cc.SessionError as se:
                logger.error(CFGMGR_BAD_UPDATE_RESPONSE_FROM_MODULE, module_name, se)
                answer = ccsession.create_answer(1, "Unable to parse response from " + module_name + ": " + str(se))
        if answer:
            rcode, val = ccsession.parse_answer(answer)
            if rcode == 0:
                self.write_config()
            else:
                self.config.data = old_data
        return answer
Ejemplo n.º 4
0
    def __handle_set_config_module(self, module_name, new_conf):
        # Reject attempts of overridding system reserved items.
        reserved_items = [
            item for item in new_conf.keys() if item and item[0] == '_'
        ]
        if reserved_items:
            return ccsession.create_answer(
                1, 'system reserved items cannot be set manually: ' +
                ' '.join(reserved_items))

        # the answer comes (or does not come) from the relevant module
        # so we need a variable to see if we got it
        answer = None
        # todo: use api (and check the data against the definition?)
        old_data = copy.deepcopy(self.config.data)
        conf_part = data.find_no_exc(self.config.data, module_name)
        update_cmd = None
        use_part = None
        if conf_part:
            data.merge(conf_part, new_conf)
            use_part = conf_part
        else:
            conf_part = data.set(self.config.data, module_name, {})
            data.merge(conf_part[module_name], new_conf)
            use_part = conf_part[module_name]

        # set/increment the generation ID of the module config
        old_genid = use_part.get('_generation_id')
        use_part['_generation_id'] = 1 if old_genid is None else old_genid + 1

        # The command to send
        update_cmd = ccsession.create_command(ccsession.COMMAND_CONFIG_UPDATE,
                                              use_part)

        # TODO: This design might need some revisiting. We might want some
        # polymorphism instead of branching. But it just might turn out it
        # will get solved by itself when we move everything to virtual modules
        # (which is possible solution to the offline configuration problem)
        # or when we solve the incorrect behaviour here when a config is
        # rejected (spying modules don't know it was rejected and some modules
        # might have been committed already).
        if module_name in self.virtual_modules:
            # The module is virtual, so call it to get the answer
            try:
                error = self.virtual_modules[module_name](use_part)
                if error is None:
                    answer = ccsession.create_answer(0)
                    # OK, it is successful, send the notify, but don't wait
                    # for answer
                    seq = self.cc.group_sendmsg(update_cmd, module_name)
                else:
                    answer = ccsession.create_answer(1, error)
            # Make sure just a validating plugin don't kill the whole manager
            except Exception as excp:
                # Provide answer
                answer = ccsession.create_answer(1, "Exception: " + str(excp))
        else:
            # Real module, send it over the wire to it
            # send out changed info and wait for answer
            seq = self.cc.group_sendmsg(update_cmd, module_name)
            try:
                # replace 'our' answer with that of the module
                answer, env = self.cc.group_recvmsg(False, seq)
            except bundy.cc.SessionTimeout:
                answer = ccsession.create_answer(
                    1, "Timeout waiting for answer from " + module_name)
            except bundy.cc.SessionError as se:
                logger.error(CFGMGR_BAD_UPDATE_RESPONSE_FROM_MODULE,
                             module_name, se)
                answer = ccsession.create_answer(
                    1, "Unable to parse response from " + module_name + ": " +
                    str(se))
        if answer:
            rcode, val = ccsession.parse_answer(answer)
            if rcode == 0:
                self.write_config()
            else:
                self.config.data = old_data
        return answer