Ejemplo n.º 1
0
def auth_loadzone_command(module_cc, zone_name, zone_class):
    '''Create a 'loadzone' command with a given zone for Auth server.

    This function generates an inter-module command for Auth
    to force it to reload the zone.

    Parameters:
    module_cc (CCSession): a CC session that can get access to auth module
      configuration as a remote configuration
    zone_name (bundy.dns.Name): the zone name to be possibly reloaded
    zone_class (bundy.dns.RRClass): the RR class of the zone to be possibly
      reloaded.

    Return: a CC command message for the reload.
    '''
    # Note: this function was originally a dedicated subroutine of xfrin,
    # but was moved here so it can be shared by some other modules
    # (specifically, by ddns).  It's expected that we'll soon fundamentally
    # revisit the whole data source related configuration, at which point
    # this function should be substantially modified if not completely
    # deprecated (which is a more likely scenario).  For this reason, the
    # corresponding tests were still kept in xfrin.

    # Note: The function got very simplified by #1976. There's plan to move
    # to notification-driven approach, at which point the function would
    # be changed a lot.

    return create_command(AUTH_LOADZONE_COMMAND,
                          auth_loadzone_params(zone_name, zone_class))
Ejemplo n.º 2
0
 def _send_module_spec_to_cmdctl(self, module_name, spec):
     """Sends the given module spec for the given module name to Cmdctl.
        Parameters:
        module_name: A string with the name of the module
        spec: dict containing full module specification, as returned by
              ModuleSpec.get_full_spec(). This argument may also be None,
              in which case it signals Cmdctl to remove said module from
              its list.
        No response from Cmdctl is expected."""
     spec_update = ccsession.create_command(ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE,
                                            [ module_name, spec ])
     self.cc.group_sendmsg(spec_update, "Cmdctl")
Ejemplo n.º 3
0
 def _send_module_spec_to_cmdctl(self, module_name, spec):
     """Sends the given module spec for the given module name to Cmdctl.
        Parameters:
        module_name: A string with the name of the module
        spec: dict containing full module specification, as returned by
              ModuleSpec.get_full_spec(). This argument may also be None,
              in which case it signals Cmdctl to remove said module from
              its list.
        No response from Cmdctl is expected."""
     spec_update = ccsession.create_command(
         ccsession.COMMAND_MODULE_SPECIFICATION_UPDATE, [module_name, spec])
     self.cc.group_sendmsg(spec_update, "Cmdctl")
Ejemplo n.º 4
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.º 5
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