Пример #1
0
def config_transition(statemachine, spawn, context):
    # Config may be locked, retry until max attempts or config state reached
    wait_time = spawn.settings.CONFIG_LOCK_RETRY_SLEEP
    max_attempts = spawn.settings.CONFIG_LOCK_RETRIES
    dialog = Dialog([
        Statement(pattern=patterns.config_locked,
                  action=update_context,
                  args={'config_locked': True},
                  loop_continue=False,
                  trim_buffer=True),
        Statement(pattern=statemachine.get_state('enable').pattern,
                  action=update_context,
                  args={'config_locked': False},
                  loop_continue=False,
                  trim_buffer=False),
        Statement(pattern=statemachine.get_state('config').pattern,
                  action=update_context,
                  args={'config_locked': False},
                  loop_continue=False,
                  trim_buffer=False)
    ])

    for attempts in range(max_attempts + 1):
        spawn.sendline(statemachine.config_command)
        try:
            dialog.process(spawn,
                           timeout=spawn.settings.CONFIG_TIMEOUT,
                           context=context)
        except UniconTimeoutError:
            pass
        if context.get('config_locked'):
            if attempts < max_attempts:
                spawn.log.warning(
                    '*** Config lock detected, waiting {} seconds. Retry attempt {}/{} ***'
                    .format(wait_time, attempts + 1, max_attempts))
                sleep(wait_time)
        else:
            statemachine.detect_state(spawn)
            if statemachine.current_state == 'config':
                return
            else:
                spawn.log.warning(
                    "Could not enter config mode, sending clear line command and trying again.."
                )
                spawn.send(spawn.settings.CLEAR_LINE_CMD)

    if context.get('config_locked'):
        raise StateMachineError('Config locked, unable to configure device')
    else:
        raise StateMachineError('Unable to transition to config mode')
Пример #2
0
def config_transition(statemachine, spawn, context):
    # Config may be locked, retry until max attempts or config state reached
    wait_time = spawn.settings.CONFIG_LOCK_RETRY_SLEEP
    max_attempts = spawn.settings.CONFIG_LOCK_RETRIES
    dialog = Dialog([Statement(pattern=statemachine.get_state('enable').pattern,
                               loop_continue=False,
                               trim_buffer=True),
                     Statement(pattern=statemachine.get_state('config').pattern,
                               loop_continue=False,
                               trim_buffer=False),
                     ])
    if hasattr(statemachine, 'config_transition_statement_list'):
        dialog += Dialog(statemachine.config_transition_statement_list)

    for attempt in range(max_attempts + 1):
        spawn.sendline(statemachine.config_command)
        dialog.process(spawn, timeout=spawn.settings.CONFIG_TIMEOUT, context=context)

        statemachine.detect_state(spawn)
        if statemachine.current_state == 'config':
            return

        if attempt < max_attempts:
            spawn.log.warning('*** Could not enter config mode, waiting {} seconds. Retry attempt {}/{} ***'.format(
                              wait_time, attempt + 1, max_attempts))
            sleep(wait_time)

    raise StateMachineError('Unable to transition to config mode')
Пример #3
0
    def call_service(self, style, *args, **kwargs):
        # Get current state of the state machine and determine end state
        sm = self.get_sm()
        con = self.connection

        con.log.debug('+++ cli_style current state %s +++' % sm.current_state)
        current_state = sm.current_state
        self.start_state = current_state

        if sm.current_cli_style == 'cisco':
            if style[0].lower() == 'j':
                self.start_state = "juniper_" + sm.current_cli_mode
        elif sm.current_cli_style == 'juniper':
            if style[0].lower() == 'c':
                self.start_state = "cisco_" + sm.current_cli_mode
        else:
            raise StateMachineError('Invalid state when calling cli_style')

        self.end_state = self.start_state
        spawn = self.get_spawn()
        try:
            sm.go_to(self.start_state, spawn, context=self.context)
        except Exception as err:
            raise SubCommandFailure(
                "Failed to bring device to requested CLI state", err)

        con.log.debug('+++ cli_style new state %s +++' % sm.current_state)
        self.result = True
Пример #4
0
 def test_stage_apply_configuration2(self):
     self.device.configure = Mock(side_effect=StateMachineError('negative test'))
     self.device.destroy = Mock(return_value="")
     self.device.connect = Mock(return_value=self.raw_output.connect)
     self.device.execute = Mock(return_value="")
     
     # Execute stage: apply_configuration
     with self.assertRaises(TerminateStepSignal):
         apply_configuration(self.section, self.steps, self.device,
                             **self.device.clean.apply_configuration)
Пример #5
0
 def test_stage_apply_configuration(self):
     self.device.configure = Mock(side_effect=StateMachineError('device hostname changed'))
     self.device.destroy = Mock(return_value="")
     self.device.connect = Mock(return_value=self.raw_output.connect)
     self.device.execute = Mock(side_effect=pos_execute)
     
     # Execute stage: apply_configuration
     with self.assertRaises(AEtestPassedSignal):
         apply_configuration(self.section, self.steps, self.device,
                             **self.device.clean.apply_configuration)
Пример #6
0
def switch_console(statemachine, spawn, context):
    sm = statemachine
    # switch between XR and BMC console
    if sm.current_state == 'enable':
        target_state = 'bmc'
    elif sm.current_state == 'bmc':
        target_state = 'enable'
    else:
        raise StateMachineError('Unsupported state transition from {}'.format(
            sm.current_state))

    # Try ctrl-o (\x0f) and then ctrl-w (\x17)
    for cmd in ['\x0f', '\x17']:
        spawn.send(cmd)
        sm.go_to('any', spawn, timeout=spawn.timeout)
        if sm.current_state == target_state:
            spawn.sendline()
            return

    raise StateMachineError('Unable to switch console state')
Пример #7
0
    def glean_state(self, spawn, possible_states):
        """ Try to figure out the state by sending commands and verifying the matches against known output.
        """
        # Create list of commands to execute
        glean_command_map = {}
        state_patterns = []
        for state in possible_states:
            state_patterns.append(state.pattern)
            glean_data = self.STATE_GLEAN.get(state.name, None)
            if glean_data:
                if glean_data.command in glean_command_map:
                    glean_command_map[glean_data.command][
                        glean_data.pattern] = state
                else:
                    glean_command_map[glean_data.command] = {}
                    glean_command_map[glean_data.command][
                        glean_data.pattern] = state

        if not glean_command_map:
            raise StateMachineError(
                'Unable to detect state, multiple states possible and no glean data available'
            )

        # Execute each glean commnd and check for pattern match
        for glean_cmd in glean_command_map:
            glean_pattern_map = glean_command_map[glean_cmd]
            dialog = Dialog(default_statement_list +
                            [Statement(p) for p in state_patterns])

            spawn.sendline(glean_cmd)
            result = dialog.process(spawn)
            if result:
                output = result.match_output
                for glean_pattern in glean_pattern_map:
                    if re.search(glean_pattern, output):
                        self.update_cur_state(glean_pattern_map[glean_pattern])
                        return
Пример #8
0
def ftd_to_module_transition(statemachine, spawn, context):
    if context.get('console'):
        spawn.sendline('exit')
    else:
        raise StateMachineError('Not on console, cannot transition')
Пример #9
0
def raise_ftd_not_running():
    raise StateMachineError('FTD is not running')
Пример #10
0
    def call_service(self,
                     command=[],
                     reply=Dialog([]),
                     timeout=None,
                     error_pattern=None,
                     *args,
                     **kwargs):

        # Get current state of the state machine and determine end state
        sm = self.get_sm()
        con = self.connection

        con.log.debug('+++ configure state %s +++' % sm.current_state)

        if sm.current_cli_style == 'cisco':
            self.start_state = 'cisco_config'
            self.end_state = 'cisco_exec'
            PROMPT_PREFIX = None
        elif sm.current_cli_style == 'juniper':
            self.start_state = 'juniper_config'
            self.end_state = 'juniper_exec'
            PROMPT_PREFIX = con.settings.JUNIPER_PROMPT_PREFIX
        else:
            raise StateMachineError(
                'Invalid state (%s) when calling configure' %
                sm.current_cli_style())

        spawn = self.get_spawn()
        sm.go_to(self.start_state, spawn, context=self.context)

        timeout = timeout or self.timeout
        if isinstance(command, str):
            command = command.splitlines()
        self.command_list_is_empty = False
        if not isinstance(reply, Dialog):
            raise SubCommandFailure(
                "dialog passed via 'reply' must be an instance of Dialog")

        # No command passed, just move to config mode
        if len(command) == 0:
            self.result = None
            self.command_list_is_empty = True
            return

        if con.settings.IGNORE_CHATTY_TERM_OUTPUT:
            # clear buffer of 'System message at ...' messages
            chatty_term_wait(con.spawn, trim_buffer=True)

        command_output = {}
        # if commands is a list
        if not isinstance(command, collections.abc.Sequence):
            raise SubCommandFailure('Invalid command passed %s' %
                                    repr(command))

        if 'commit' not in command:
            command.append('commit')

        try:
            for cmd in command:
                self.result = con.command(cmd,
                                          reply=reply,
                                          error_pattern=error_pattern,
                                          timeout=timeout)
                if self.result:
                    output = utils.truncate_trailing_prompt(
                        sm.get_state(sm.current_state), self.result,
                        self.connection.hostname)
                    output = output.replace(cmd, "", 1)
                    output = re.sub(r"^\r\n", "", output, 1)
                    if PROMPT_PREFIX:
                        output = re.sub(PROMPT_PREFIX, "", output)
                    command_output[cmd] = output.rstrip()
        except SubCommandFailure as e:
            # Go to exec state after command failure,
            # do not commit changes (handled by state transition)
            sm.go_to(self.end_state, spawn, context=self.context)
            raise

        if len(command_output) == 1:
            self.result = list(command_output.values())[0]
        else:
            self.result = command_output
    def go_to(self, to_state, spawn,
              context=AttributeDict(),
              dialog=None,
              timeout=None,
              hop_wise=False,
              prompt_recovery=False):
        # get the composed full (slot_<slot>_<app>) state name
        to_state = self.get_full_state_name(to_state)

        # when a connection is made to the device and the device
        # is left in a random state we need to try to detect the
        # state or signal failure because going to 'any' state
        # can lead to circular transitions which go on in a loop
        # indefinetely
        if self.current_state == 'generic' and to_state is 'any':
            # try to detect in which state we are right now or fail
            # send a newline to initialize the prompt
            spawn.sendline('')
            # wait 10 seconds for the prompt to populate
            time.sleep(10)
            # match everything in the output buffer
            output = spawn.expect('.*', timeout=30).match_output
            for state_name, state_data in self.states_dict.items():
                pattern = state_data.pattern
                if isinstance(pattern, str):
                    if re.match(pattern, output.split('\r\n')[-1]):
                        self.update_cur_state(state_name)
                        return output
                if isinstance(pattern, list):
                    for pat in pattern:
                        if re.match(pat, output.split('\r\n')[-1]):
                            self.update_cur_state(state_name)
                            return output
            raise RuntimeError('Could not detect current state. Please ' +
                               'connect to the chassis and bring it to ' +
                               'the mio state prompt. Output is:' + output)
        elif (self.current_state != 'generic' and to_state is 'any') or \
                isinstance(to_state, list):
            expected_state = to_state
            transition = AnyStateTransition(state_machine=self,
                                            to_state=to_state,
                                            spawn=spawn,
                                            dialog=dialog,
                                            timeout=timeout,
                                            context=context,
                                            prompt_recovery=prompt_recovery)
        else:
            if not isinstance(to_state, State):
                to_state = self.get_state(to_state)
            expected_state = to_state.name

            # Get the current state from SM
            current_state = self.get_state(self.current_state)

            # If the current and to_state state are same
            # we are already there so just return
            if to_state == current_state:
                return

            # If hop_wise is enabled then do step by step state transition
            if hop_wise:
                transition = HopWiseStateTransition(state_machine=self,
                                                    to_state=to_state,
                                                    spawn=spawn,
                                                    dialog=dialog,
                                                    timeout=timeout,
                                                    context=context,
                                                    prompt_recovery=prompt_recovery)
            else:
                transition = StateTransition(state_machine=self,
                                             to_state=to_state,
                                             spawn=spawn,
                                             dialog=dialog,
                                             timeout=timeout,
                                             context=context,
                                             prompt_recovery=prompt_recovery)
        # Start the state transition
        try:
            output = transition.do_transitions()

        except Exception as err:
            raise StateMachineError('Failed while bringing device to ' +
                                    '"%s" state' % \
                                    str(expected_state)) from err
        finally:
            if transition.current_state is not 'generic':
                self.update_cur_state(transition.current_state)

        # If the current_state and to_state are not matching
        # the probably whe landed somewhere wrong, so raise exception
        if expected_state is not 'any' \
                and self.current_state not in expected_state:
            raise StateMachineError(
                'Changing state to %s failed\n'
                'current_state: %s\n'
                'last command: %s\n'
                'buffer: %s\n'
                'last match: %s' %
                (
                    expected_state,
                    self.current_state,
                    repr(spawn.last_sent),
                    repr(spawn.buffer),
                    repr(spawn.match.match_output)
                )
            )

        return output
Пример #12
0
 def current_cli_mode(self):
     self.current_state_tokens = self.current_state.split('_')
     if len(self.current_state_tokens) < 1:
         raise StateMachineError('Invalid state')
     mode = self.current_state_tokens[1]
     return mode
Пример #13
0
 def current_cli_style(self):
     self.current_state_tokens = self.current_state.split('_')
     if len(self.current_state_tokens) < 1:
         raise StateMachineError('Invalid state')
     style = self.current_state_tokens[0]
     return style