Example #1
0
 def _process_sm_exc(self, db_session, exc, msg, new_state=None):
     """
     Process a state machine exception.  For putting as much code as
     possible on a common call path.
     """
     delay_factor = 1 + random()
     delay_period = timedelta(minutes=delay_factor *
                              float(settings['master_hold_timeout']))
     old_state = self.state
     if new_state:
         self.state = new_state
     log_msg = str(exc)
     log_info(log_msg)
     self.retry_msg = log_msg
     create_event(ServerSMConfigure,
                  db_session=db_session,
                  sm_id=self.id_,
                  server_id=self.id_,
                  delay=delay_period,
                  server_name=self.name)
     state_str = ''
     if old_state != self.state:
         state_str = ("old state %s, new state %s - " %
                      (old_state, self.state))
     return (RCODE_OK, "Server '%s': %s%s" % (self.name, state_str, msg))
Example #2
0
 def _ready_all_reconfig(self, event):
     """
     Process an all reconfig
     """
     # Update server address info
     recalc_machine_dns_server_info(event.db_session)
     # Update master server configuration
     rcode, msg = self._master_rndc(event, 'reconfig')
     if rcode != RCODE_OK:
         return (rcode, msg)
     
     # Issue all reconfig event to all servers
     delay_time = timedelta(
             seconds=float(settings['master_rndc_settle_delay']))
     db_session = event.db_session
     ServerGroup = sql_types['ServerGroup']
     for sg in db_session.query(ServerGroup):
         try:
             sg.write_config(db_session, ServerConfigFileError)
         except ServerConfigFileError as exc:
             log_error(str(exc))
             continue
         for server_sm in sg.servers:
             if server_sm.is_disabled():
                 continue
             create_event(sql_events['ServerSMConfigChange'],
                         db_session=event.db_session,
                         sm_id=server_sm.id_, server_id=server_sm.id_,
                         delay=delay_time,
                         server_name=server_sm.name)
     
     self._hold_enter(db_session)
     return (RCODE_OK, 
             "Master named reconfig done and reconfig queued for all SGs")
Example #3
0
def reset_master_sm(db_session):
    """
    Reset the Configuration state machine
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMReset, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_)
Example #4
0
def reconfig_all(db_session):
    """
    Reconfigure all DNS servers - helper
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMAllReconfig, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_)
Example #5
0
    def _ready_all_reconfig(self, event):
        """
        Process an all reconfig
        """
        # Update server address info
        recalc_machine_dns_server_info(event.db_session)
        # Update master server configuration
        rcode, msg = self._master_rndc(event, 'reconfig')
        if rcode != RCODE_OK:
            return (rcode, msg)

        # Issue all reconfig event to all servers
        delay_time = timedelta(
            seconds=float(settings['master_rndc_settle_delay']))
        db_session = event.db_session
        ServerGroup = sql_types['ServerGroup']
        for sg in db_session.query(ServerGroup):
            try:
                sg.write_config(db_session, ServerConfigFileError)
            except ServerConfigFileError as exc:
                log_error(str(exc))
                continue
            for server_sm in sg.servers:
                if server_sm.is_disabled():
                    continue
                create_event(sql_events['ServerSMConfigChange'],
                             db_session=event.db_session,
                             sm_id=server_sm.id_,
                             server_id=server_sm.id_,
                             delay=delay_time,
                             server_name=server_sm.name)

        self._hold_enter(db_session)
        return (RCODE_OK,
                "Master named reconfig done and reconfig queued for all SGs")
Example #6
0
    def _create_check(self, event):
        """
        Process a state machine exception.  For putting as much code as
        possible on a common call path.
        """
        db_session = event.db_session

        # Check every half to full holdout time
        master_hold_timeout = float(settings['master_hold_timeout'])
        delay_factor = (1 + random()) * 0.5
        delay_period = timedelta(minutes=delay_factor * master_hold_timeout)
        hold_period = timedelta(minutes=master_hold_timeout)

        # See if a check event already exists for this ServerSM
        current_checks = find_events(ServerSMCheckServer,
                                     db_session,
                                     server_id=self.id_)
        current_checks = [e for e in current_checks if e.id_ != event.id_]
        if len(current_checks):
            return

        create_event(ServerSMCheckServer,
                     db_session=db_session,
                     sm_id=self.id_,
                     server_id=self.id_,
                     delay=delay_period,
                     server_name=self.name)
Example #7
0
def reconfig_master(db_session):
    """
    Reconfigure Master DNS server
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMMasterReconfig, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_)
Example #8
0
 def _reset(self, event):
     """
     Reset mastersm
     """
     self._init()
     # Queue all reconfig
     create_event(MasterSMAllReconfig, db_session=event.db_session, sm_id=self.id_, master_id=self.id_)
     return (RCODE_OK, "MasterSM - SM reinitialised and MasterSMAllReconfig")
Example #9
0
def reconfig_sg(db_session, sg_id, sg_name):
    """
    Reconfigure An SGs DNS servers - helper
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMPartialReconfig, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_,
                        sg_id=sg_id, sg_name=sg_name)
Example #10
0
def reconfig_master(db_session):
    """
    Reconfigure Master DNS server
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMMasterReconfig,
                 db_session=db_session,
                 sm_id=master_sm.id_,
                 master_id=master_sm.id_)
Example #11
0
def reconfig_all(db_session):
    """
    Reconfigure all DNS servers - helper
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMAllReconfig,
                 db_session=db_session,
                 sm_id=master_sm.id_,
                 master_id=master_sm.id_)
Example #12
0
def reset_master_sm(db_session):
    """
    Reset the Configuration state machine
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMReset,
                 db_session=db_session,
                 sm_id=master_sm.id_,
                 master_id=master_sm.id_)
Example #13
0
def reconfig_sg(db_session, sg_id, sg_name):
    """
    Reconfigure An SGs DNS servers - helper
    """
    master_sm = get_master_sm(db_session)
    create_event(MasterSMPartialReconfig,
                 db_session=db_session,
                 sm_id=master_sm.id_,
                 master_id=master_sm.id_,
                 sg_id=sg_id,
                 sg_name=sg_name)
Example #14
0
 def _config_change(self, event):
     """
     Start the reconfiguration process
     """
     self.state = SSTATE_CONFIG
     self.retry_msg = None
     create_event(ServerSMConfigure,
                  db_session=event.db_session,
                  sm_id=self.id_,
                  server_id=self.id_,
                  server_name=self.name)
     return (RCODE_OK, "Server '%s': reconfiguring" % self.name)
Example #15
0
 def _reset(self, event):
     """
     Reset mastersm
     """
     self._init()
     # Queue all reconfig
     create_event(MasterSMAllReconfig,
                  db_session=event.db_session,
                  sm_id=self.id_,
                  master_id=self.id_)
     return (RCODE_OK,
             "MasterSM - SM reinitialised and MasterSMAllReconfig")
Example #16
0
    def _hold_enter(self, db_session, all_reconfig=False):
        """
        Enter hold state

        Set fields as needed.
        """
        if self.state == MSTATE_HOLD:
            return
        self.hold_sg = HOLD_SG_ALL if all_reconfig else HOLD_SG_NONE
        self.state = MSTATE_HOLD
        self.hold_start = db_time(db_session)
        delay = timedelta(minutes=float(settings["master_hold_timeout"]))
        self.hold_stop = self.hold_start + delay
        # Queue hold timeout
        create_event(MasterSMHoldTimeout, db_session=db_session, sm_id=self.id_, master_id=self.id_, delay=delay)
Example #17
0
def zone_sm_dnssec_schedule(db_session, zone_sm, operation):
    """
    Schedule a DNSSEC rndc sign/loadkeys operation for a zone_sm
    """
    master_sm = get_master_sm(db_session)
    if operation == 'loadkeys':
        create_event(MasterSMLoadKeys, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_,
                        zone_name=zone_sm.name)
    elif operation in ('sign', 'signzone'):
        create_event(MasterSMSignZone, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_,
                        zone_name=zone_sm.name)
    else:
        log_error("MasterSM - zone '%s', invalid dnssec operation"
                % zone_sm.name)
Example #18
0
def zone_sm_reconfig_schedule(db_session, zone_sm, zone_sm_event=None,
                            randomize=False, master_reconfig=False, **kwargs):
    """
    Schedule MasterSM zone creation/update events

    Zone SM helper function
    """
    master_sm = get_master_sm(db_session)
    # According to sampling theorem, twice tick rate, add 1 to account for
    # safety
    coalesce_time = timedelta(seconds=3*float(settings['sleep_time']))
    # Make delay_secs 2 * coalesce time
    delay_secs = 6*float(settings['sleep_time'])
    if randomize:
        delay_secs += 60*float(settings['master_hold_timeout']) * random()
    delay_time = timedelta(seconds=delay_secs)
    sg_id = zone_sm.sg.id_
    # Queue config event
    if master_reconfig:
        if (master_sm.state != MSTATE_HOLD
            or (master_sm.state == MSTATE_HOLD
                and master_sm.hold_sg == HOLD_SG_NONE)):
            create_event(MasterSMMasterReconfig, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_)
    # Only create MasterSMPartialEvents when needed, as they clog the 
    # event queue
    elif (master_sm.state != MSTATE_HOLD
            or (master_sm.state == MSTATE_HOLD 
                and (master_sm.hold_sg != sg_id 
                    and master_sm.hold_sg != HOLD_SG_ALL))):
        create_event(MasterSMPartialReconfig, db_session=db_session,
                        sm_id=master_sm.id_, master_id=master_sm.id_,
                        sg_id=sg_id, sg_name=zone_sm.sg.name)
    # Queue zone_sm event
    if not zone_sm_event:
        return
    if master_sm.state == MSTATE_READY:
        create_event(zone_sm_event, db_session=db_session,
                        sm_id=zone_sm.id_, zone_id=zone_sm.id_,
                        name=zone_sm.name,
                        delay=delay_time, coalesce_period=coalesce_time,
                        **kwargs)
        return
    elif master_sm.state == MSTATE_HOLD:
        schedule_time = master_sm.hold_stop + delay_time
        create_event(zone_sm_event, db_session=db_session,
                        time=schedule_time, coalesce_period=coalesce_time,
                        sm_id=zone_sm.id_, zone_id=zone_sm.id_,
                        name=zone_sm.name, **kwargs)
        return
    else:
        log_critical('MasterSM - unrecognized state, exiting')
        systemd_exit(os.EX_SOFTWARE, SDEX_GENERIC)
    return
Example #19
0
    def _hold_enter(self, db_session, all_reconfig=False):
        """
        Enter hold state

        Set fields as needed.
        """
        if self.state == MSTATE_HOLD:
            return
        self.hold_sg = HOLD_SG_ALL if all_reconfig else HOLD_SG_NONE
        self.state = MSTATE_HOLD
        self.hold_start = db_time(db_session)
        delay = timedelta(minutes=float(settings['master_hold_timeout']))
        self.hold_stop = self.hold_start + delay
        # Queue hold timeout
        create_event(MasterSMHoldTimeout,
                     db_session=db_session,
                     sm_id=self.id_,
                     master_id=self.id_,
                     delay=delay)
Example #20
0
def zone_sm_dnssec_schedule(db_session, zone_sm, operation):
    """
    Schedule a DNSSEC rndc sign/loadkeys operation for a zone_sm
    """
    master_sm = get_master_sm(db_session)
    if operation == 'loadkeys':
        create_event(MasterSMLoadKeys,
                     db_session=db_session,
                     sm_id=master_sm.id_,
                     master_id=master_sm.id_,
                     zone_name=zone_sm.name)
    elif operation in ('sign', 'signzone'):
        create_event(MasterSMSignZone,
                     db_session=db_session,
                     sm_id=master_sm.id_,
                     master_id=master_sm.id_,
                     zone_name=zone_sm.name)
    else:
        log_error("MasterSM - zone '%s', invalid dnssec operation" %
                  zone_sm.name)
Example #21
0
 def _enable(self, event):
     """
     Enable the Server
     """
     try:
         query = event.db_session.query(ServerSM)\
                 .filter(ServerSM.address == self.address)\
                 .filter(ServerSM.state != SSTATE_DISABLED)
         result = query.all()
         if result:
             raise ServerEnableFailure(
                 "Server '%s' - server '%s' with same address enabled" %
                 (self.name, result[0].name))
     except NoResultFound:
         pass
     self.state = SSTATE_CONFIG
     create_event(ServerSMConfigure,
                  db_session=event.db_session,
                  sm_id=self.id_,
                  server_id=self.id_,
                  server_name=self.name)
     return (RCODE_OK, "Server '%s': enabling" % self.name)
Example #22
0
    def _hold_time_out(self, event):
        """
        Process a hold time out.

        This the event runs the associated SM backend routine depending on 
        value of self.hold_sg
       """
        db_session = event.db_session
        sm_id = event.py_parameters["sm_id"]
        old_hold_sg = self.hold_sg
        old_hold_sg_name = self.hold_sg_name
        # Reset All SM fields
        self._init()
        if old_hold_sg == HOLD_SG_ALL:
            create_event(MasterSMAllReconfig, sm_id=self.id_, master_id=self.id_)
            return (
                RCODE_OK,
                "MasterSM - %s, %s created and queued" % (MasterSMHoldTimeout.__name__, MasterSMAllReconfig.__name__),
            )
        if old_hold_sg == HOLD_SG_MASTER:
            create_event(MasterSMMasterReconfig, sm_id=self.id_, master_id=self.id_)
            return (
                RCODE_OK,
                "MasterSM - %s, %s created and queued"
                % (MasterSMHoldTimeout.__name__, MasterSMMasterReconfig.__name__),
            )
        elif old_hold_sg:
            create_event(
                MasterSMPartialReconfig, sm_id=self.id_, master_id=self.id_, sg_id=old_hold_sg, sg_name=old_hold_sg_name
            )
            return (
                RCODE_OK,
                "MasterSM - %s, %s for SG %s(%s) created and queued"
                % (
                    MasterSMHoldTimeout.__name__,
                    MasterSMPartialReconfig.__name__,
                    old_hold_sg_name,
                    self._display_hold_sg(old_hold_sg),
                ),
            )

        return (RCODE_NOCHANGE, "MasterSM - no reconfigure event during hold")
Example #23
0
    def _hold_time_out(self, event):
        """
        Process a hold time out.

        This the event runs the associated SM backend routine depending on 
        value of self.hold_sg
       """
        db_session = event.db_session
        sm_id = event.py_parameters['sm_id']
        old_hold_sg = self.hold_sg
        old_hold_sg_name = self.hold_sg_name
        # Reset All SM fields
        self._init()
        if old_hold_sg == HOLD_SG_ALL:
            create_event(MasterSMAllReconfig,
                         sm_id=self.id_,
                         master_id=self.id_)
            return (
                RCODE_OK, "MasterSM - %s, %s created and queued" %
                (MasterSMHoldTimeout.__name__, MasterSMAllReconfig.__name__))
        if old_hold_sg == HOLD_SG_MASTER:
            create_event(MasterSMMasterReconfig,
                         sm_id=self.id_,
                         master_id=self.id_)
            return (RCODE_OK, "MasterSM - %s, %s created and queued" %
                    (MasterSMHoldTimeout.__name__,
                     MasterSMMasterReconfig.__name__))
        elif old_hold_sg:
            create_event(MasterSMPartialReconfig,
                         sm_id=self.id_,
                         master_id=self.id_,
                         sg_id=old_hold_sg,
                         sg_name=old_hold_sg_name)
            return (RCODE_OK,
                    "MasterSM - %s, %s for SG %s(%s) created and queued" %
                    (MasterSMHoldTimeout.__name__,
                     MasterSMPartialReconfig.__name__, old_hold_sg_name,
                     self._display_hold_sg(old_hold_sg)))

        return (RCODE_NOCHANGE, "MasterSM - no reconfigure event during hold")
Example #24
0
    def _ready_partial_reconfig(self, event):
        """
        Process a partial reconfig event
        """
        # Update server address info
        recalc_machine_dns_server_info(event.db_session)
        # Update master server configuration
        rcode, msg = self._master_rndc(event, 'reconfig')
        if rcode != RCODE_OK:
            return (rcode, msg)

        # Issue reconfig event to SG
        db_session = event.db_session
        ServerGroup = sql_types['ServerGroup']
        # sg_id found in zone_sm and sent here as event parameter
        sg_id = event.py_parameters['sg_id']
        sg_name = event.py_parameters['sg_name']
        try:
            sg = db_session.query(ServerGroup)\
                    .filter(ServerGroup.id_ == sg_id).one()
        except NoResultFound as exc:
            msg = ("MasterSM: can't find SG %s by id '%s'" % (sg_name, sg_id))
            raise CantFindSg(msg)

        self.hold_sg_name = sg.name

        delay_time = timedelta(
            seconds=float(settings['master_rndc_settle_delay']))
        # Replica SG reconfigure
        replica_sg = self.replica_sg
        if (replica_sg and replica_sg is not sg):
            try:
                replica_sg.write_config(db_session, ServerConfigFileError)
            except ServerConfigFileError as exc:
                log_error(str(exc))
            else:
                for server_sm in replica_sg.servers:
                    if server_sm.is_disabled():
                        continue
                    create_event(sql_events['ServerSMConfigChange'],
                                 db_session=event.db_session,
                                 sm_id=server_sm.id_,
                                 server_id=server_sm.id_,
                                 delay=delay_time,
                                 server_name=server_sm.name)

        # SG reconfigure
        try:
            sg.write_config(db_session, ServerConfigFileError)
        except ServerConfigFileError as exc:
            log_error(str(exc))
        else:
            # Reconfigure servers in this group
            for server_sm in sg.servers:
                if server_sm.is_disabled():
                    continue
                create_event(sql_events['ServerSMConfigChange'],
                             db_session=event.db_session,
                             sm_id=server_sm.id_,
                             server_id=server_sm.id_,
                             delay=delay_time,
                             server_name=server_sm.name)

        self._hold_enter(db_session)
        return (
            RCODE_OK,
            "MasterSM: SG '%s' - master named reconfig done and SG reconfig queued"
            % self.hold_sg_name)
Example #25
0
def zone_sm_reconfig_schedule(db_session,
                              zone_sm,
                              zone_sm_event=None,
                              randomize=False,
                              master_reconfig=False,
                              **kwargs):
    """
    Schedule MasterSM zone creation/update events

    Zone SM helper function
    """
    master_sm = get_master_sm(db_session)
    # According to sampling theorem, twice tick rate, add 1 to account for
    # safety
    coalesce_time = timedelta(seconds=3 * float(settings['sleep_time']))
    # Make delay_secs 2 * coalesce time
    delay_secs = 6 * float(settings['sleep_time'])
    if randomize:
        delay_secs += 60 * float(settings['master_hold_timeout']) * random()
    delay_time = timedelta(seconds=delay_secs)
    sg_id = zone_sm.sg.id_
    # Queue config event
    if master_reconfig:
        if (master_sm.state != MSTATE_HOLD
                or (master_sm.state == MSTATE_HOLD
                    and master_sm.hold_sg == HOLD_SG_NONE)):
            create_event(MasterSMMasterReconfig,
                         db_session=db_session,
                         sm_id=master_sm.id_,
                         master_id=master_sm.id_)
    # Only create MasterSMPartialEvents when needed, as they clog the
    # event queue
    elif (master_sm.state != MSTATE_HOLD or
          (master_sm.state == MSTATE_HOLD and
           (master_sm.hold_sg != sg_id and master_sm.hold_sg != HOLD_SG_ALL))):
        create_event(MasterSMPartialReconfig,
                     db_session=db_session,
                     sm_id=master_sm.id_,
                     master_id=master_sm.id_,
                     sg_id=sg_id,
                     sg_name=zone_sm.sg.name)
    # Queue zone_sm event
    if not zone_sm_event:
        return
    if master_sm.state == MSTATE_READY:
        create_event(zone_sm_event,
                     db_session=db_session,
                     sm_id=zone_sm.id_,
                     zone_id=zone_sm.id_,
                     name=zone_sm.name,
                     delay=delay_time,
                     coalesce_period=coalesce_time,
                     **kwargs)
        return
    elif master_sm.state == MSTATE_HOLD:
        schedule_time = master_sm.hold_stop + delay_time
        create_event(zone_sm_event,
                     db_session=db_session,
                     time=schedule_time,
                     coalesce_period=coalesce_time,
                     sm_id=zone_sm.id_,
                     zone_id=zone_sm.id_,
                     name=zone_sm.name,
                     **kwargs)
        return
    else:
        log_critical('MasterSM - unrecognized state, exiting')
        systemd_exit(os.EX_SOFTWARE, SDEX_GENERIC)
    return
Example #26
0
    def _ready_partial_reconfig(self, event):
        """
        Process a partial reconfig event
        """
        # Update server address info
        recalc_machine_dns_server_info(event.db_session)
        # Update master server configuration
        rcode, msg = self._master_rndc(event, 'reconfig')
        if rcode != RCODE_OK:
            return (rcode, msg)

        # Issue reconfig event to SG
        db_session = event.db_session
        ServerGroup = sql_types['ServerGroup']
        # sg_id found in zone_sm and sent here as event parameter
        sg_id = event.py_parameters['sg_id']
        sg_name = event.py_parameters['sg_name']
        try:
            sg = db_session.query(ServerGroup)\
                    .filter(ServerGroup.id_ == sg_id).one()
        except NoResultFound as exc:
            msg = ("MasterSM: can't find SG %s by id '%s'" 
                % (sg_name, sg_id))
            raise CantFindSg(msg)
        
        self.hold_sg_name = sg.name
        
        delay_time = timedelta(
                seconds=float(settings['master_rndc_settle_delay']))
        # Replica SG reconfigure
        replica_sg = self.replica_sg
        if (replica_sg and replica_sg is not sg):
            try:
                replica_sg.write_config(db_session, ServerConfigFileError)
            except ServerConfigFileError as exc:
                log_error(str(exc))
            else:
                for server_sm in replica_sg.servers:
                    if server_sm.is_disabled():
                        continue
                    create_event(sql_events['ServerSMConfigChange'],
                                db_session=event.db_session,
                                sm_id=server_sm.id_, server_id=server_sm.id_,
                                delay=delay_time,
                                server_name=server_sm.name)

        # SG reconfigure
        try:
            sg.write_config(db_session, ServerConfigFileError)
        except ServerConfigFileError as exc:
            log_error(str(exc))
        else:
            # Reconfigure servers in this group
            for server_sm in sg.servers:
                if server_sm.is_disabled():
                    continue
                create_event(sql_events['ServerSMConfigChange'],
                            db_session=event.db_session,
                            sm_id=server_sm.id_, server_id=server_sm.id_,
                            delay=delay_time,
                            server_name=server_sm.name)

        self._hold_enter(db_session)
        return (RCODE_OK, "MasterSM: SG '%s' - master named reconfig done and SG reconfig queued"
                            % self.hold_sg_name)