Ejemplo n.º 1
0
    def test_fsm_action_is_class(self):
        """FSM: Test action is class"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = "STATE1"

        class action1:
            pass

        transitions = [
            ("STATE1", [0], -1, action1, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        with self.assertRaises(RuntimeWarning):
            sm.run()
Ejemplo n.º 2
0
    def test_fsm_action_is_class(self):
        """FSM: Test action is class"""
        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = "STATE1"

        class action1:
            pass

        transitions = [
            ("STATE1", [0], -1, action1, 1),
        ]

        sm = FSM("FSM",
                 device,
                 events=events,
                 transitions=transitions,
                 init_pattern=None,
                 timeout=1,
                 max_transitions=5)

        with self.assertRaises(RuntimeWarning):
            sm.run()
Ejemplo n.º 3
0
    def config(self, config_text, plane):
        """Apply config."""
        nol = config_text.count('\n')
        config_lines = iter(config_text.splitlines())
        events = [self.prompt_re, self.syntax_error_re]
        transitions = [(self.prompt_re, [0], 0,
                        partial(a_send_line, config_lines), 10),
                       (self.syntax_error_re, [0], -1,
                        CommandSyntaxError("Configuration syntax error."), 0)]
        self.device.ctrl.send_command(self.config_cmd)
        fsm = FSM("CONFIG",
                  self.device,
                  events,
                  transitions,
                  timeout=10,
                  max_transitions=nol + 5)
        fsm.run()

        # after the configuration the hostname may change. Need to detect it again
        try:
            self.device.send("", timeout=2)
        except CommandTimeoutError:
            prompt = self.device.ctrl.detect_prompt()
            self.device.prompt_re = self.make_dynamic_prompt(prompt)
            self.device.update_config_mode(prompt)

        if self.device.mode == "config":
            self.device.send("end")

        self.device.send("write memory")

        return "NO-COMMIT-ID"
Ejemplo n.º 4
0
    def reload(self, reload_timeout=300, save_config=True):
        """Reload the device.

        CSM_DUT#reload

        System configuration has been modified. Save? [yes/no]: yes
        Building configuration...
        [OK]
        Proceed with reload? [confirm]
        """
        response = "yes" if save_config else "no"

        events = [SAVE_CONFIG, PROCEED, pexpect.TIMEOUT, pexpect.EOF]

        transitions = [
            (SAVE_CONFIG, [0], 1, partial(a_send_line, response), 60),
            (PROCEED, [0, 1], 2, partial(a_send, "\r"), 10),
            # if timeout try to send the reload command again
            (pexpect.TIMEOUT, [0], 0, partial(a_send_line,
                                              self.reload_cmd), 10),
            (pexpect.TIMEOUT, [2], -1, a_disconnect, 0),
            (pexpect.EOF, [0, 1, 2], -1, a_disconnect, 0)
        ]
        fsm = FSM("IOS-RELOAD",
                  self.device,
                  events,
                  transitions,
                  timeout=10,
                  max_transitions=5)
        fsm.run()
Ejemplo n.º 5
0
    def enable(self, enable_password):
        """Change to the privilege mode."""
        if self.device.prompt[-1] == '#':
            self.log("Device is already in privileged mode")
            return

        events = [
            self.password_re, self.device.prompt_re, pexpect.TIMEOUT,
            pexpect.EOF
        ]
        transitions = [
            (self.password_re, [0], 1, partial(a_send_password,
                                               enable_password), 10),
            (self.password_re, [1], -1,
             ConnectionAuthenticationError("Incorrect enable password",
                                           self.device.hostname), 0),
            (self.device.prompt_re, [0, 1, 2, 3], -1, a_expected_prompt, 0),
            (pexpect.TIMEOUT, [0, 1, 2], -1,
             ConnectionAuthenticationError("Unable to get privileged mode",
                                           self.device.hostname), 0),
            (pexpect.EOF, [0, 1,
                           2], -1, ConnectionError("Device disconnected"), 0)
        ]
        self.device.ctrl.send_command(self.enable_cmd)
        fsm = FSM("IOS-ENABLE",
                  self.device,
                  events,
                  transitions,
                  timeout=10,
                  max_transitions=5)
        fsm.run()
        if self.device.prompt[-1] != '#':
            raise ConnectionAuthenticationError("Privileged mode not set",
                                                self.device.hostname)
Ejemplo n.º 6
0
    def test_fsm_action(self):
        """FSM: Test different actions"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        @action
        def action1(ctx):
            ctx.ctrl.expect.return_value = 1
            self.assertEqual(str(ctx), "FSM Context:E=0,S=0,FI=False,M=''")
            return True

        @action
        def action2(ctx):
            """Action 2"""
            ctx.ctrl.expect.return_value = 2
            self.assertEqual(str(ctx), "FSM Context:E=1,S=1,FI=False,M=''")
            return True

        events = ["STATE1", "STATE2", "STATE3"]

        transitions = [
            ("STATE1", [0], 1, action1, 1),
            ("STATE2", [1], 2, action2, 1),
            ("STATE3", [2], 3, None, 1),
            ("STATE3", [3], -1, condoor.ConnectionTimeoutError("Error"), 0),
            ("UNKNOWN", [4], -1, None, 0)
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        with self.assertRaises(condoor.ConnectionTimeoutError):
            sm.run()
Ejemplo n.º 7
0
    def config(self, config_text, plane):
        """Apply config."""
        NO_CONFIGURATION_CHANGE = re.compile(
            "No configuration changes to commit")
        CONFIGURATION_FAILED = re.compile("show configuration failed")
        CONFIGURATION_INCONSITENCY = re.compile(
            "No configuration commits for this SDR will be allowed until "
            "a 'clear configuration inconsistency' command is performed.")

        self.enter_plane(plane)

        nol = config_text.count('\n')
        config_lines = iter(config_text.splitlines())
        events = [self.prompt_re, self.syntax_error_re]
        transitions = [(self.prompt_re, [0], 0,
                        partial(a_send_line, config_lines), 10),
                       (self.syntax_error_re, [0], -1,
                        CommandSyntaxError("Configuration syntax error."), 0)]
        self.device.ctrl.send_command(self.config_cmd)
        fsm = FSM("CONFIG",
                  self.device,
                  events,
                  transitions,
                  timeout=10,
                  max_transitions=nol + 5)
        fsm.run()

        events = [
            self.prompt_re, NO_CONFIGURATION_CHANGE, CONFIGURATION_FAILED
        ]
        transitions = [
            (NO_CONFIGURATION_CHANGE, [0], -1,
             ConfigurationErrors("No configuration changes to commit."), 0),
            (CONFIGURATION_FAILED, [0], 2, a_capture_show_configuration_failed,
             10),
            (CONFIGURATION_INCONSITENCY, [0], 2, a_configuration_inconsistency,
             10), (self.prompt_re, [0], 1, partial(a_send_line, 'end'), 60),
            (self.prompt_re, [1], -1, None, 0)
        ]

        label = 'condoor-{}'.format(int(time.time()))
        self.device.ctrl.send_command(self.commit_cmd.format(label))
        fsm = FSM("COMMIT",
                  self.device,
                  events,
                  transitions,
                  timeout=120,
                  max_transitions=5)
        fsm.run()
        self.exit_plane()
        return label
Ejemplo n.º 8
0
    def test_fsm_unknown_state(self):
        """FSM: Test unknown state transition"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        @action
        def action1(value, ctx):
            """Action 1"""
            return True

        events = "STATE2"

        transitions = [
            ("STATE1", [0], -1, action1, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertFalse(result)
Ejemplo n.º 9
0
    def test_fsm_action_is_partial(self):
        """FSM: Test action is partial"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = ["STATE1"]

        @action
        def action1(value, ctx):
            """Action 1"""
            self.assertEqual(value, "test_value")
            return True

        transitions = [
            ("STATE1", [0], -1, partial(action1, "test_value"), 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertTrue(result)
Ejemplo n.º 10
0
    def test_fsm_event_not_list(self):
        """FSM: Test single event"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = "STATE1"

        transitions = [
            ("STATE1", [0], -1, None, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertEqual(True, result)
Ejemplo n.º 11
0
    def connect(self, driver):
        """Connect using the SSH protocol specific FSM."""
        #                      0                    1                 2
        events = [driver.password_re, self.device.prompt_re, driver.unable_to_connect_re,
                  #   3          4              5               6                   7
                  NEWSSHKEY, KNOWN_HOSTS, HOST_KEY_FAILED, MODULUS_TOO_SMALL, PROTOCOL_DIFFER,
                  #      8              9
                  driver.timeout_re, pexpect.TIMEOUT]

        transitions = [
            (driver.password_re, [0, 1, 4, 5], -1, partial(a_save_last_pattern, self), 0),
            (self.device.prompt_re, [0], -1, partial(a_save_last_pattern, self), 0),
            #  cover all messages indicating that connection was not set up
            (driver.unable_to_connect_re, [0], -1, a_unable_to_connect, 0),
            (NEWSSHKEY, [0], 1, partial(a_send_line, "yes"), 10),
            (KNOWN_HOSTS, [0, 1], 0, None, 0),
            (HOST_KEY_FAILED, [0], -1, ConnectionError("Host key failed", self.hostname), 0),
            (MODULUS_TOO_SMALL, [0], 0, self.fallback_to_sshv1, 0),
            (PROTOCOL_DIFFER, [0], 4, self.fallback_to_sshv1, 0),
            (PROTOCOL_DIFFER, [4], -1, ConnectionError("Protocol version differs", self.hostname), 0),
            (pexpect.TIMEOUT, [0], 5, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [5], -1, ConnectionTimeoutError("Connection timeout", self.hostname), 0),
            (driver.timeout_re, [0], -1, ConnectionTimeoutError("Connection timeout", self.hostname), 0),
        ]

        self.log("EXPECTED_PROMPT={}".format(pattern_to_str(self.device.prompt_re)))
        fsm = FSM("SSH-CONNECT", self.device, events, transitions, timeout=_C['connect_timeout'],
                  searchwindowsize=160)
        return fsm.run()
Ejemplo n.º 12
0
    def wait_for_string(self, expected_string, timeout=60):
        """Wait for string FSM."""
        #                    0                         1                        2                        3
        events = [self.syntax_error_re, self.connection_closed_re, expected_string, self.press_return_re,
                  #        4           5                 6                7
                  self.more_re, pexpect.TIMEOUT, pexpect.EOF, self.buffer_overflow_re]

        # add detected prompts chain
        events += self.device.get_previous_prompts()  # without target prompt

        logger.debug("Expecting: {}".format(pattern_to_str(expected_string)))

        transitions = [
            (self.syntax_error_re, [0], -1, CommandSyntaxError("Command unknown", self.device.hostname), 0),
            (self.connection_closed_re, [0], 1, a_connection_closed, 10),
            (pexpect.TIMEOUT, [0], -1, CommandTimeoutError("Timeout waiting for prompt", self.device.hostname), 0),
            (pexpect.EOF, [0, 1], -1, ConnectionError("Unexpected device disconnect", self.device.hostname), 0),
            (self.more_re, [0], 0, partial(a_send, " "), 10),
            (expected_string, [0, 1], -1, a_expected_prompt, 0),
            (self.press_return_re, [0], -1, a_stays_connected, 0),
            # TODO: Customize in XR driver
            (self.buffer_overflow_re, [0], -1, CommandSyntaxError("Command too long", self.device.hostname), 0)
        ]

        for prompt in self.device.get_previous_prompts():
            transitions.append((prompt, [0, 1], 0, a_unexpected_prompt, 0))

        fsm = FSM("WAIT-4-STRING", self.device, events, transitions, timeout=timeout)
        return fsm.run()
Ejemplo n.º 13
0
    def authenticate(self, driver):
        """Authenticate using the SSH protocol specific FSM."""
        #              0                     1                    2                  3
        events = [
            driver.press_return_re, driver.password_re, self.device.prompt_re,
            pexpect.TIMEOUT
        ]

        transitions = [
            (driver.press_return_re, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (driver.password_re, [0], 1,
             partial(a_send_password,
                     self._acquire_password()), _C['first_prompt_timeout']),
            (driver.password_re, [1], -1, a_authentication_error, 0),
            (self.device.prompt_re, [0, 1], -1, None, 0),
            (pexpect.TIMEOUT, [1], -1,
             ConnectionError("Error getting device prompt")
             if self.device.is_target else partial(a_send, "\r\n"), 0)
        ]

        self.log("EXPECTED_PROMPT={}".format(
            pattern_to_str(self.device.prompt_re)))
        fsm = FSM("SSH-AUTH",
                  self.device,
                  events,
                  transitions,
                  init_pattern=self.last_pattern,
                  timeout=30)
        return fsm.run()
Ejemplo n.º 14
0
    def test_fsm_event_not_list(self):
        """FSM: Test single event"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = "STATE1"

        transitions = [
            ("STATE1", [0], -1, None, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertEqual(True, result)
Ejemplo n.º 15
0
    def connect(self, driver):
        """Connect using the SSH protocol specific FSM."""
        #                      0                    1                 2
        events = [driver.password_re, self.device.prompt_re, driver.unable_to_connect_re,
                  #   3          4              5               6                   7
                  NEWSSHKEY, KNOWN_HOSTS, HOST_KEY_FAILED, MODULUS_TOO_SMALL, PROTOCOL_DIFFER,
                  #      8              9
                  driver.timeout_re, pexpect.TIMEOUT]

        transitions = [
            (driver.password_re, [0, 1, 4, 5], -1, partial(a_save_last_pattern, self), 0),
            (self.device.prompt_re, [0], -1, partial(a_save_last_pattern, self), 0),
            #  cover all messages indicating that connection was not set up
            (driver.unable_to_connect_re, [0], -1, a_unable_to_connect, 0),
            (NEWSSHKEY, [0], 1, partial(a_send_line, "yes"), 10),
            (KNOWN_HOSTS, [0, 1], 0, None, 0),
            (HOST_KEY_FAILED, [0], -1, ConnectionError("Host key failed", self.hostname), 0),
            (MODULUS_TOO_SMALL, [0], 0, self.fallback_to_sshv1, 0),
            (PROTOCOL_DIFFER, [0], 4, self.fallback_to_sshv1, 0),
            (PROTOCOL_DIFFER, [4], -1, ConnectionError("Protocol version differs", self.hostname), 0),
            (pexpect.TIMEOUT, [0], 5, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [5], -1, ConnectionTimeoutError("Connection timeout", self.hostname), 0),
            (driver.timeout_re, [0], -1, ConnectionTimeoutError("Connection timeout", self.hostname), 0),
        ]

        logger.debug("EXPECTED_PROMPT={}".format(pattern_to_str(self.device.prompt_re)))
        fsm = FSM("SSH-CONNECT", self.device, events, transitions, timeout=_C['connect_timeout'],
                  searchwindowsize=160)
        return fsm.run()
Ejemplo n.º 16
0
    def connect(self, driver):
        """Connect using the Telnet protocol specific FSM."""
        #              0            1                              2                      3
        events = [ESCAPE_CHAR, driver.press_return_re, driver.standby_re, driver.username_re,
                  #            4                   5                  6                     7
                  driver.password_re, driver.more_re, self.device.prompt_re, driver.rommon_re,
                  #       8                              9              10            11
                  driver.unable_to_connect_re, driver.timeout_re, pexpect.TIMEOUT, PASSWORD_OK]

        transitions = [
            (ESCAPE_CHAR, [0], 1, None, _C['esc_char_timeout']),
            (driver.press_return_re, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (PASSWORD_OK, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (driver.standby_re, [0, 5], -1, partial(a_standby_console), 0),
            (driver.username_re, [0, 1, 5, 6], -1, partial(a_save_last_pattern, self), 0),
            (driver.password_re, [0, 1, 5], -1, partial(a_save_last_pattern, self), 0),
            (driver.more_re, [0, 5], 7, partial(a_send, "q"), 10),
            # router sends it again to delete
            (driver.more_re, [7], 8, None, 10),
            # (prompt, [0, 1, 5], 6, partial(a_send, "\r\n"), 10),
            (self.device.prompt_re, [0, 1, 5], 0, None, 10),
            (self.device.prompt_re, [6, 8, 5], -1, partial(a_save_last_pattern, self), 0),
            (driver.rommon_re, [0, 1, 5], -1, partial(a_save_last_pattern, self), 0),
            (driver.unable_to_connect_re, [0, 1], -1, a_unable_to_connect, 0),
            (driver.timeout_re, [0, 1], -1, ConnectionTimeoutError("Connection Timeout", self.hostname), 0),
            (pexpect.TIMEOUT, [0, 1], 5, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [5], -1, ConnectionTimeoutError("Connection timeout", self.hostname), 0)
        ]

        logger.debug("EXPECTED_PROMPT={}".format(pattern_to_str(self.device.prompt_re)))
        fsm = FSM("TELNET-CONNECT", self.device, events, transitions, timeout=_C['connect_timeout'],
                  init_pattern=self.last_pattern)
        return fsm.run()
Ejemplo n.º 17
0
    def authenticate(self, driver):
        """Authenticate using the SSH protocol specific FSM."""
        #                      0                      1                    2                    3
        events = [driver.username_re, driver.password_re, self.device.prompt_re, driver.rommon_re,
                  #       4                              5                              6           7
                  driver.unable_to_connect_re, driver.authentication_error_re, pexpect.TIMEOUT, pexpect.EOF]

        transitions = [
            (driver.username_re, [0], 1, partial(a_send_username, self.username), 10),
            (driver.username_re, [1], 1, None, 10),
            (driver.password_re, [0, 1], 2, partial(a_send_password, self._acquire_password()),
             _C['first_prompt_timeout']),
            (driver.username_re, [2], -1, a_authentication_error, 0),
            (driver.password_re, [2], -1, a_authentication_error, 0),
            (driver.authentication_error_re, [1, 2], -1, a_authentication_error, 0),
            (self.device.prompt_re, [0, 1, 2], -1, None, 0),
            (driver.rommon_re, [0], -1, partial(a_send, "\r\n"), 0),
            (pexpect.TIMEOUT, [0], 1, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [2], -1, None, 0),
            (pexpect.TIMEOUT, [3, 7], -1, ConnectionTimeoutError("Connection Timeout", self.hostname), 0),
            (driver.unable_to_connect_re, [0, 1, 2], -1, a_unable_to_connect, 0),
        ]
        logger.debug("EXPECTED_PROMPT={}".format(pattern_to_str(self.device.prompt_re)))
        fsm = FSM("TELNET-AUTH", self.device, events, transitions, timeout=_C['connect_timeout'],
                  init_pattern=self.last_pattern)
        return fsm.run()
Ejemplo n.º 18
0
    def connect(self, driver):
        """Connect using console specific FSM."""
        #              0            1                    2                      3
        events = [
            ESCAPE_CHAR,
            driver.press_return_re,
            driver.standby_re,
            driver.username_re,
            #            4                   5            6                     7
            driver.password_re,
            driver.more_re,
            self.device.prompt_re,
            driver.rommon_re,
            #       8                           9              10             11
            driver.unable_to_connect_re,
            driver.timeout_re,
            pexpect.TIMEOUT,
            PASSWORD_OK
        ]

        transitions = [
            (ESCAPE_CHAR, [0], 1, partial(a_send,
                                          "\r\n"), _C['esc_char_timeout']),
            (driver.press_return_re, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (PASSWORD_OK, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (driver.standby_re, [0, 5], -1,
             ConnectionError("Standby console", self.hostname), 0),
            (driver.username_re, [0, 1, 5,
                                  6], -1, partial(a_save_last_pattern,
                                                  self), 0),
            (driver.password_re, [0, 1,
                                  5], -1, partial(a_save_last_pattern,
                                                  self), 0),
            (driver.more_re, [0, 5], 7, partial(a_send, "q"), 10),
            # router sends it again to delete
            (driver.more_re, [7], 8, None, 10),
            # (prompt, [0, 1, 5], 6, partial(a_send, "\r\n"), 10),
            (self.device.prompt_re, [0, 5], 0, None, 10),
            (self.device.prompt_re, [1, 6, 8,
                                     5], -1, partial(a_save_last_pattern,
                                                     self), 0),
            (driver.rommon_re, [0, 1, 5], -1, partial(a_save_last_pattern,
                                                      self), 0),
            (driver.unable_to_connect_re, [0, 1], -1, a_unable_to_connect, 0),
            (driver.timeout_re, [0, 1], -1,
             ConnectionTimeoutError("Connection Timeout", self.hostname), 0),
            (pexpect.TIMEOUT, [0, 1], 5, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [5], -1,
             ConnectionTimeoutError("Connection timeout", self.hostname), 0)
        ]
        logger.debug("EXPECTED_PROMPT={}".format(
            pattern_to_str(self.device.prompt_re)))
        fsm = FSM("CONSOLE-SERVER-CONNECT",
                  self.device,
                  events,
                  transitions,
                  timeout=_C['connect_timeout'],
                  init_pattern=self.last_pattern)
        return fsm.run()
Ejemplo n.º 19
0
    def test_fsm_action(self):
        """FSM: Test different actions"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        @action
        def action1(ctx):
            ctx.ctrl.expect.return_value = 1
            self.assertEqual(str(ctx), "FSM Context:E=0,S=0,FI=False,M=''")
            return True

        @action
        def action2(ctx):
            """Action 2"""
            ctx.ctrl.expect.return_value = 2
            self.assertEqual(str(ctx), "FSM Context:E=1,S=1,FI=False,M=''")
            return True

        events = ["STATE1", "STATE2", "STATE3"]

        transitions = [
            ("STATE1", [0], 1, action1, 1),
            ("STATE2", [1], 2, action2, 1),
            ("STATE3", [2], 3, None, 1),
            ("STATE3", [3], -1, condoor.ConnectionTimeoutError("Error"), 0),
            ("UNKNOWN", [4], -1, None, 0)
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        with self.assertRaises(condoor.ConnectionTimeoutError):
            sm.run()
Ejemplo n.º 20
0
    def reload(self, reload_timeout, save_config):
        """Reload the device."""
        RELOAD_PROMPT = re.compile(re.escape("Reload hardware module ? [no,yes]"))
        START_TO_BACKUP = re.compile("Status report.*START TO BACKUP")
        BACKUP_HAS_COMPLETED_SUCCESSFULLY = re.compile("Status report.*BACKUP HAS COMPLETED SUCCESSFULLY")
        DONE = re.compile(re.escape("[Done]"))
        CONSOLE = re.compile("ios con[0|1]/(?:RS?P)?[0-1]/CPU0 is now available")
        CONFIGURATION_COMPLETED = re.compile("SYSTEM CONFIGURATION COMPLETED")
        CONFIGURATION_IN_PROCESS = re.compile("SYSTEM CONFIGURATION IN PROCESS")
        BOOTING = re.compile("Booting IOS-XR 64 bit Boot previously installed image")

        # events = [RELOAD_NA, DONE, PROCEED, CONFIGURATION_IN_PROCESS, self.rommon_re, self.press_return_re,
        #           #   6               7                       8                     9      10        11
        #           CONSOLE, CONFIGURATION_COMPLETED, RECONFIGURE_USERNAME_PROMPT, TIMEOUT, EOF, self.reload_cmd,
        #           #    12                    13                     14
        #           ROOT_USERNAME_PROMPT, ROOT_PASSWORD_PROMPT, CANDIDATE_BOOT_IMAGE]

        events = [self.reload_cmd, RELOAD_PROMPT, START_TO_BACKUP, BACKUP_HAS_COMPLETED_SUCCESSFULLY, DONE, BOOTING,
                  CONSOLE, self.press_return_re, CONFIGURATION_COMPLETED, CONFIGURATION_IN_PROCESS, EOF]

        transitions = [
            # do I really need to clean the cmd
            (RELOAD_PROMPT, [0], 1, partial(a_send_line, "yes"), 30),
            (START_TO_BACKUP, [1], 2, a_message_callback, 60),
            (BACKUP_HAS_COMPLETED_SUCCESSFULLY, [2], 3, a_message_callback, 10),
            (DONE, [3], 4, None, 600),
            (self.rommon_re, [0, 4], 5, partial(a_send_boot, "boot"), 600),
            (BOOTING, [0, 4], 5, a_message_callback, 600),
            (CONSOLE, [0, 5], 6, None, 600),
            (self.press_return_re, [6], 7, partial(a_send, "\r"), 300),
            (CONFIGURATION_IN_PROCESS, [7], 8, None, 180),
            (CONFIGURATION_COMPLETED, [8], -1, a_reconnect, 0),
            (EOF, [0, 1, 2, 3, 4, 5], -1, ConnectionError("Device disconnected"), 0),

            # (RELOAD_NA, [1], -1, a_reload_na, 0),
            # (DONE, [1], 2, None, 120),
            # (PROCEED, [2], 3, partial(a_send, "\r"), reload_timeout),
            # (self.rommon_re, [0, 3], 4, partial(a_send_boot, "boot"), 600),
            # (CANDIDATE_BOOT_IMAGE, [0, 3], 4, a_message_callback, 600),
            # (CONSOLE, [0, 1, 3, 4], 5, None, 600),
            # (self.press_return_re, [5], 6, partial(a_send, "\r"), 300),
            # # configure root username and password the same as used for device connection.
            # (RECONFIGURE_USERNAME_PROMPT, [6, 7], 8, None, 10),
            # (ROOT_USERNAME_PROMPT, [8], 9, partial(a_send_username, self.device.node_info.username), 1),
            # (ROOT_PASSWORD_PROMPT, [9], 9, partial(a_send_password, self.device.node_info.password), 1),
            # (CONFIGURATION_IN_PROCESS, [6, 9], 7, None, 180),
            # (CONFIGURATION_COMPLETED, [7], -1, a_reconnect, 0),
            # (TIMEOUT, [0, 1, 2], -1, ConnectionAuthenticationError("Unable to reload"), 0),
            # (EOF, [0, 1, 2, 3, 4, 5], -1, ConnectionError("Device disconnected"), 0),
            # (TIMEOUT, [6], 7, partial(a_send, "\r"), 180),
            # (TIMEOUT, [7], -1, ConnectionAuthenticationError("Unable to reconnect after reloading"), 0),
        ]

        fsm = FSM("RELOAD", self.device, events, transitions, timeout=600)
        return fsm.run()
Ejemplo n.º 21
0
    def enable(self, enable_password):
        """Change to the privilege mode."""
        if self.device.prompt[-1] == '#':
            logger.debug("Device is already in privileged mode")
            return

        events = [self.password_re, self.device.prompt_re, pexpect.TIMEOUT, pexpect.EOF]
        transitions = [
            (self.password_re, [0], 1, partial(a_send_password, enable_password), 10),
            (self.password_re, [1], -1, ConnectionAuthenticationError("Incorrect enable password",
                                                                      self.device.hostname), 0),
            (self.device.prompt_re, [0, 1, 2, 3], -1, a_expected_prompt, 0),
            (pexpect.TIMEOUT, [0, 1, 2], -1, ConnectionAuthenticationError("Unable to get privileged mode",
                                                                           self.device.hostname), 0),
            (pexpect.EOF, [0, 1, 2], -1, ConnectionError("Device disconnected"), 0)
        ]
        self.device.ctrl.send_command(self.enable_cmd)
        fsm = FSM("IOS-ENABLE", self.device, events, transitions, timeout=10, max_transitions=5)
        fsm.run()
        if self.device.prompt[-1] != '#':
            raise ConnectionAuthenticationError("Privileged mode not set", self.device.hostname)
Ejemplo n.º 22
0
    def test_fsm_action_is_string(self):
        """FSM: Test action is string"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = "STATE1"

        action1 = "not callable string"

        transitions = [
            ("STATE1", [0], -1, action1, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        with self.assertRaises(RuntimeWarning):
            sm.run()
Ejemplo n.º 23
0
    def test_fsm_max_transitions(self):
        """FSM: Test the maximum transitions sentil"""

        class Ctrl(object):
            logger = None
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0
        device.chain.connection.log.return_value = None

        @action
        def action1(ctx):
            self.assertEqual(ctx.event, 0)
            self.assertEqual(ctx.finished, False)
            self.assertEqual(ctx.fsm_name, "MAX-TR")
            self.assertEqual(ctx.msg, "")
            self.assertEqual(ctx.pattern, pexpect.TIMEOUT)
            self.assertEqual(ctx.state, 0)
            ctx.device.counter += 1
            return True

        events = [pexpect.TIMEOUT]

        transitions = [
            (pexpect.TIMEOUT, [0], 0, action1, 1)
        ]

        sm = FSM("MAX-TR", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)
        result = sm.run()

        self.assertEqual(device.counter, 5)
        self.assertFalse(result)
Ejemplo n.º 24
0
    def reload(self, reload_timeout=300, save_config=True):
        """Reload the device.

        CSM_DUT#reload

        System configuration has been modified. Save? [yes/no]: yes
        Building configuration...
        [OK]
        Proceed with reload? [confirm]
        """
        response = "yes" if save_config else "no"

        events = [SAVE_CONFIG, PROCEED, pexpect.TIMEOUT, pexpect.EOF]

        transitions = [
            (SAVE_CONFIG, [0], 1, partial(a_send_line, response), 60),
            (PROCEED, [0, 1], 2, partial(a_send, "\r"), 10),
            # if timeout try to send the reload command again
            (pexpect.TIMEOUT, [0], 0, partial(a_send_line, self.reload_cmd), 10),
            (pexpect.TIMEOUT, [2], -1, a_disconnect, 0),
            (pexpect.EOF, [0, 1, 2], -1, a_disconnect, 0)
        ]
        fsm = FSM("IOS-RELOAD", self.device, events, transitions, timeout=10, max_transitions=5)
        fsm.run()
Ejemplo n.º 25
0
    def authenticate(self, driver):
        """Authenticate using the SSH protocol specific FSM."""
        #              0                     1                    2                  3
        events = [driver.press_return_re, driver.password_re, self.device.prompt_re, pexpect.TIMEOUT]

        transitions = [
            (driver.press_return_re, [0, 1], 1, partial(a_send, "\r\n"), 10),
            (driver.password_re, [0], 1, partial(a_send_password, self._acquire_password()),
             _C['first_prompt_timeout']),
            (driver.password_re, [1], -1, a_authentication_error, 0),
            (self.device.prompt_re, [0, 1], -1, None, 0),
            (pexpect.TIMEOUT, [1], -1,
             ConnectionError("Error getting device prompt") if self.device.is_target else partial(a_send, "\r\n"), 0)
        ]

        logger.debug("EXPECTED_PROMPT={}".format(pattern_to_str(self.device.prompt_re)))
        fsm = FSM("SSH-AUTH", self.device, events, transitions, init_pattern=self.last_pattern, timeout=30)
        return fsm.run()
Ejemplo n.º 26
0
    def reload(self, reload_timeout=300, save_config=True):
        """Reload the device.

        CSM_DUT#reload

        System configuration has been modified. Save? [yes/no]: yes
        Building configuration...
        [OK]
        Proceed with reload? [confirm]
        """
        SAVE_CONFIG = re.compile(
            re.escape(
                "System configuration has been modified. Save? [yes/no]: "))
        PROCEED = re.compile(re.escape("Proceed with reload? [confirm]"))
        IMAGE = re.compile("Passing control to the main image")
        BOOTSTRAP = re.compile("System Bootstrap")
        LOCATED = re.compile("Located .*")
        RETURN = re.compile(re.escape("Press RETURN to get started!"))

        response = "yes" if save_config else "no"

        #              0          1       2       3         4
        events = [
            SAVE_CONFIG, PROCEED, LOCATED, RETURN, self.username_re,
            self.password_re, BOOTSTRAP, IMAGE, TIMEOUT, EOF
        ]
        #              5              6          7       8      9

        transitions = [
            (SAVE_CONFIG, [0], 1, partial(a_send_line, response), 60),
            (PROCEED, [0, 1], 2, partial(a_send, "\r"), reload_timeout),
            (LOCATED, [2], 2, a_message_callback, reload_timeout),
            # if timeout try to send the reload command again
            (TIMEOUT, [0], 0, partial(a_send_line, self.reload_cmd), 10),
            (BOOTSTRAP, [2], -1, a_disconnect, reload_timeout),
            (IMAGE, [2], 3, a_message_callback, reload_timeout),
            (self.username_re, [3], -1, a_return_and_reconnect, 0),
            (self.password_re, [3], -1, a_return_and_reconnect, 0),
            (RETURN, [3], -1, a_return_and_reconnect, 0),
            (TIMEOUT, [2], -1, a_disconnect, 0),
            (EOF, [0, 1, 2, 3], -1, a_disconnect, 0)
        ]
        fsm = FSM("IOS-RELOAD", self.device, events, transitions, timeout=10)
        return fsm.run()
Ejemplo n.º 27
0
    def authenticate(self, driver):
        """Authenticate using the Console Server protocol specific FSM."""
        #                      0                      1                    2                    3
        events = [
            driver.username_re,
            driver.password_re,
            self.device.prompt_re,
            driver.rommon_re,
            #       4             5                   6                       7                8
            driver.unable_to_connect_re,
            driver.authentication_error_re,
            pexpect.TIMEOUT,
            pexpect.EOF
        ]

        transitions = [
            (driver.username_re, [0], 1, partial(a_send_username,
                                                 self.username), 10),
            (driver.username_re, [1], 1, None, 10),
            (driver.password_re, [0, 1], 2,
             partial(a_send_password,
                     self._acquire_password()), _C['first_prompt_timeout']),
            (driver.username_re, [2], -1, a_authentication_error, 0),
            (driver.password_re, [2], -1, a_authentication_error, 0),
            (driver.authentication_error_re, [1, 2], -1,
             a_authentication_error, 0),
            (self.device.prompt_re, [0, 1, 2], -1, None, 0),
            (driver.rommon_re, [0], -1, partial(a_send, "\r\n"), 0),
            (pexpect.TIMEOUT, [0], 1, partial(a_send, "\r\n"), 10),
            (pexpect.TIMEOUT, [2], -1, None, 0),
            (pexpect.TIMEOUT, [3, 7], -1,
             ConnectionTimeoutError("Connection Timeout", self.hostname), 0),
            (driver.unable_to_connect_re, [0, 1,
                                           2], -1, a_unable_to_connect, 0),
        ]
        logger.debug("EXPECTED_PROMPT={}".format(
            pattern_to_str(self.device.prompt_re)))
        fsm = FSM("CONSOLE-SERVER-AUTH",
                  self.device,
                  events,
                  transitions,
                  timeout=_C['connect_timeout'],
                  init_pattern=self.last_pattern)
        return fsm.run()
Ejemplo n.º 28
0
    def wait_for_string(self, expected_string, timeout=60):
        """Wait for string FSM for XR 64 bit."""
        # Big thanks to calvados developers for make this FSM such complex ;-)
        #                    0                         1                        2                        3
        events = [self.syntax_error_re, self.connection_closed_re, expected_string, self.press_return_re,
                  #        4           5                 6                7               8
                  self.more_re, pexpect.TIMEOUT, pexpect.EOF, self.calvados_re, self.calvados_connect_re,
                  #     9
                  self.calvados_term_length]

        # add detected prompts chain
        events += self.device.get_previous_prompts()  # without target prompt

        logger.debug("Expecting: {}".format(pattern_to_str(expected_string)))
        logger.debug("Calvados prompt: {}".format(pattern_to_str(self.calvados_re)))

        transitions = [
            (self.syntax_error_re, [0], -1, CommandSyntaxError("Command unknown", self.device.hostname), 0),
            (self.connection_closed_re, [0], 1, a_connection_closed, 10),
            (pexpect.TIMEOUT, [0, 2], -1, CommandTimeoutError("Timeout waiting for prompt", self.device.hostname), 0),
            (pexpect.EOF, [0, 1], -1, ConnectionError("Unexpected device disconnect", self.device.hostname), 0),
            (self.more_re, [0], 0, partial(a_send, " "), 10),
            (expected_string, [0, 1], -1, a_expected_prompt, 0),
            (self.calvados_re, [0], -1, a_expected_prompt, 0),
            (self.press_return_re, [0], -1, a_stays_connected, 0),
            (self.calvados_connect_re, [0], 2, None, 0),
            # admin command to switch to calvados
            (self.calvados_re, [2], 3, None, _C['calvados_term_wait_time']),
            # getting the prompt only
            (pexpect.TIMEOUT, [3], 0, partial(a_send, "\r"), 0),
            # term len
            (self.calvados_term_length, [3], 4, None, 0),
            # ignore for command start
            (self.calvados_re, [4], 5, None, 0),
            # ignore for command start
            (self.calvados_re, [5], 0, a_store_cmd_result, 0),
        ]

        for prompt in self.device.get_previous_prompts():
            transitions.append((prompt, [0, 1], 0, a_unexpected_prompt, 0))

        fsm = FSM("WAIT-4-STRING", self.device, events, transitions, timeout=timeout)
        return fsm.run()
Ejemplo n.º 29
0
    def test_fsm_action_is_partial(self):
        """FSM: Test action is partial"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        events = ["STATE1"]

        @action
        def action1(value, ctx):
            """Action 1"""
            self.assertEqual(value, "test_value")
            return True

        transitions = [
            ("STATE1", [0], -1, partial(action1, "test_value"), 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertTrue(result)
Ejemplo n.º 30
0
    def test_fsm_max_transitions(self):
        """FSM: Test the maximum transitions sentil"""

        class Ctrl(object):
            logger = None
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Device(object):
            ctrl = Mock(spec=Ctrl)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        @action
        def action1(ctx):
            self.assertEqual(ctx.event, 0)
            self.assertEqual(ctx.finished, False)
            self.assertEqual(ctx.fsm_name, "MAX-TR")
            self.assertEqual(ctx.msg, "")
            self.assertEqual(ctx.pattern, pexpect.TIMEOUT)
            self.assertEqual(ctx.state, 0)
            ctx.device.counter += 1
            return True

        events = [pexpect.TIMEOUT]

        transitions = [
            (pexpect.TIMEOUT, [0], 0, action1, 1)
        ]

        sm = FSM("MAX-TR", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)
        result = sm.run()

        self.assertEqual(device.counter, 5)
        self.assertFalse(result)
Ejemplo n.º 31
0
    def test_fsm_unknown_state(self):
        """FSM: Test unknown state transition"""

        class Ctrl(object):
            hostname = "hostname"

            def expect(self, events, searchwindowsize, timeout):
                pass

        class Connection(object):
            def log(self, msg):
                print(msg)

        class Chain(object):
            connection = Mock(spec=Connection)

        class Device(object):
            ctrl = Mock(spec=Ctrl)
            chain = Mock(spec=Chain)

        device = Mock(spec=Device)
        device.ctrl.expect.return_value = 0
        device.counter = 0

        @action
        def action1(value, ctx):
            """Action 1"""
            return True

        events = "STATE2"

        transitions = [
            ("STATE1", [0], -1, action1, 1),
        ]

        sm = FSM("FSM", device, events=events, transitions=transitions, init_pattern=None,
                 timeout=1, max_transitions=5)

        result = sm.run()
        self.assertFalse(result)
Ejemplo n.º 32
0
    def reload(self, reload_timeout, save_config):
        """Reload the device."""
        PROCEED = re.compile(re.escape("Proceed with reload? [confirm]"))
        DONE = re.compile(re.escape("[Done]"))
        CONFIGURATION_COMPLETED = re.compile("SYSTEM CONFIGURATION COMPLETED")
        CONFIGURATION_IN_PROCESS = re.compile(
            "SYSTEM CONFIGURATION IN PROCESS")

        # CONSOLE = re.compile("ios con[0|1]/RS?P[0-1]/CPU0 is now available")
        CONSOLE = re.compile(
            "ios con[0|1]/(?:RS?P)?[0-1]/CPU0 is now available")
        RECONFIGURE_USERNAME_PROMPT = "[Nn][Oo] root-system username is configured"
        ROOT_USERNAME_PROMPT = "Enter root-system username\: "
        ROOT_PASSWORD_PROMPT = "Enter secret( again)?\: "

        # BOOT=disk0:asr9k-os-mbi-6.1.1/0x100305/mbiasr9k-rsp3.vm,1; \
        # disk0:asr9k-os-mbi-5.3.4/0x100305/mbiasr9k-rsp3.vm,2;
        # Candidate Boot Image num 0 is disk0:asr9k-os-mbi-6.1.1/0x100305/mbiasr9k-rsp3.vm
        # Candidate Boot Image num 1 is disk0:asr9k-os-mbi-5.3.4/0x100305/mbiasr9k-rsp3.vm
        CANDIDATE_BOOT_IMAGE = "Candidate Boot Image num 0 is .*vm"
        NOT_COMMITTED = re.compile(
            re.escape(
                "Some active software packages are not yet committed. Proceed?[confirm]"
            ))
        RELOAD_NA = re.compile(
            "Reload to the ROM monitor disallowed from a telnet line")
        #           0          1      2                3                   4                  5
        events = [
            RELOAD_NA,
            DONE,
            PROCEED,
            CONFIGURATION_IN_PROCESS,
            self.rommon_re,
            self.press_return_re,
            #   6               7                   8                           9
            CONSOLE,
            CONFIGURATION_COMPLETED,
            RECONFIGURE_USERNAME_PROMPT,
            ROOT_USERNAME_PROMPT,
            #    10                    11              12     13          14           15
            ROOT_PASSWORD_PROMPT,
            self.username_re,
            TIMEOUT,
            EOF,
            self.reload_cmd,
            CANDIDATE_BOOT_IMAGE,
            #   16
            NOT_COMMITTED
        ]

        transitions = [
            (RELOAD_NA, [0], -1, a_reload_na, 0),
            # temp for testing
            (NOT_COMMITTED, [0], -1, a_not_committed, 10),
            (DONE, [0], 2, None, 120),
            (PROCEED, [2], 3, partial(a_send, "\r"), reload_timeout),
            # this needs to be verified
            (self.rommon_re, [0, 3], 3, partial(a_send_boot, "boot"), 600),
            (CANDIDATE_BOOT_IMAGE, [0, 3], 4, a_message_callback, 600),
            (CONSOLE, [0, 1, 3, 4], 5, None, 600),
            # This is required. Otherwise nothing more is displayed on the console
            (self.press_return_re, [5], 6, partial(a_send, "\r"), 300),
            # configure root username and password the same as used for device connection.
            (RECONFIGURE_USERNAME_PROMPT, [6, 7, 10], 8, None, 10),
            (ROOT_USERNAME_PROMPT, [8], 9,
             partial(a_send_username, self.device.node_info.username), 1),
            (ROOT_PASSWORD_PROMPT, [9], 9,
             partial(a_send_password, self.device.node_info.password), 1),
            (CONFIGURATION_IN_PROCESS, [6, 9], 10, None, 1200),
            (CONFIGURATION_COMPLETED, [10], -1, a_reconnect, 0),
            (self.username_re, [7, 9], -1, a_return_and_reconnect, 0),
            (TIMEOUT, [0, 1, 2], -1,
             ConnectionAuthenticationError("Unable to reload"), 0),
            (EOF, [0, 1, 2, 3, 4,
                   5], -1, ConnectionError("Device disconnected"), 0),
            (TIMEOUT, [6], 7, partial(a_send, "\r"), 180),
            (TIMEOUT, [7], -1,
             ConnectionAuthenticationError(
                 "Unable to reconnect after reloading"), 0),
            (TIMEOUT, [10], -1, a_reconnect, 0),
        ]

        fsm = FSM("RELOAD", self.device, events, transitions, timeout=600)
        return fsm.run()
Ejemplo n.º 33
0
    def wait_for_string(self, expected_string, timeout=60):
        """Wait for string FSM for XR 64 bit."""
        # Big thanks to calvados developers for make this FSM such complex ;-)
        #                    0                         1                        2                        3
        events = [
            self.syntax_error_re,
            self.connection_closed_re,
            expected_string,
            self.press_return_re,
            #        4           5                 6                7               8
            self.more_re,
            pexpect.TIMEOUT,
            pexpect.EOF,
            self.calvados_re,
            self.calvados_connect_re,
            #     9
            self.calvados_term_length
        ]

        # add detected prompts chain
        events += self.device.get_previous_prompts()  # without target prompt

        logger.debug("Expecting: {}".format(pattern_to_str(expected_string)))
        logger.debug("Calvados prompt: {}".format(
            pattern_to_str(self.calvados_re)))

        transitions = [
            (self.syntax_error_re, [0], -1,
             CommandSyntaxError("Command unknown", self.device.hostname), 0),
            (self.connection_closed_re, [0], 1, a_connection_closed, 10),
            (pexpect.TIMEOUT, [0, 2], -1,
             CommandTimeoutError("Timeout waiting for prompt",
                                 self.device.hostname), 0),
            (pexpect.EOF, [0, 1], -1,
             ConnectionError("Unexpected device disconnect",
                             self.device.hostname), 0),
            (self.more_re, [0], 0, partial(a_send, " "), 10),
            (expected_string, [0, 1], -1, a_expected_prompt, 0),
            (self.calvados_re, [0], -1, a_expected_prompt, 0),
            (self.press_return_re, [0], -1, a_stays_connected, 0),
            (self.calvados_connect_re, [0], 2, None, 0),
            # admin command to switch to calvados
            (self.calvados_re, [2], 3, None, _C['calvados_term_wait_time']),
            # getting the prompt only
            (pexpect.TIMEOUT, [3], 0, partial(a_send, "\r"), 0),
            # term len
            (self.calvados_term_length, [3], 4, None, 0),
            # ignore for command start
            (self.calvados_re, [4], 5, None, 0),
            # ignore for command start
            (self.calvados_re, [5], 0, a_store_cmd_result, 0),
        ]

        for prompt in self.device.get_previous_prompts():
            transitions.append((prompt, [0, 1], 0, a_unexpected_prompt, 0))

        fsm = FSM("WAIT-4-STRING",
                  self.device,
                  events,
                  transitions,
                  timeout=timeout)
        return fsm.run()
Ejemplo n.º 34
0
    def reload(self, reload_timeout, save_config):
        """Reload the device."""
        RELOAD_PROMPT = re.compile(
            re.escape("Reload hardware module ? [no,yes]"))
        START_TO_BACKUP = re.compile("Status report.*START TO BACKUP")
        BACKUP_HAS_COMPLETED_SUCCESSFULLY = re.compile(
            "Status report.*BACKUP HAS COMPLETED SUCCESSFULLY")
        DONE = re.compile(re.escape("[Done]"))
        CONSOLE = re.compile(
            "ios con[0|1]/(?:RS?P)?[0-1]/CPU0 is now available")
        CONFIGURATION_COMPLETED = re.compile("SYSTEM CONFIGURATION COMPLETED")
        CONFIGURATION_IN_PROCESS = re.compile(
            "SYSTEM CONFIGURATION IN PROCESS")
        BOOTING = re.compile(
            "Booting IOS-XR 64 bit Boot previously installed image")

        # events = [RELOAD_NA, DONE, PROCEED, CONFIGURATION_IN_PROCESS, self.rommon_re, self.press_return_re,
        #           #   6               7                       8                     9      10        11
        #           CONSOLE, CONFIGURATION_COMPLETED, RECONFIGURE_USERNAME_PROMPT, TIMEOUT, EOF, self.reload_cmd,
        #           #    12                    13                     14
        #           ROOT_USERNAME_PROMPT, ROOT_PASSWORD_PROMPT, CANDIDATE_BOOT_IMAGE]

        events = [
            self.reload_cmd, RELOAD_PROMPT, START_TO_BACKUP,
            BACKUP_HAS_COMPLETED_SUCCESSFULLY, DONE, BOOTING, CONSOLE,
            self.press_return_re, CONFIGURATION_COMPLETED,
            CONFIGURATION_IN_PROCESS, EOF
        ]

        transitions = [
            # do I really need to clean the cmd
            (RELOAD_PROMPT, [0], 1, partial(a_send_line, "yes"), 30),
            (START_TO_BACKUP, [1], 2, a_message_callback, 60),
            (BACKUP_HAS_COMPLETED_SUCCESSFULLY, [2], 3, a_message_callback,
             10),
            (DONE, [3], 4, None, 600),
            (self.rommon_re, [0, 4], 5, partial(a_send_boot, "boot"), 600),
            (BOOTING, [0, 4], 5, a_message_callback, 600),
            (CONSOLE, [0, 5], 6, None, 600),
            (self.press_return_re, [6], 7, partial(a_send, "\r"), 300),
            (CONFIGURATION_IN_PROCESS, [7], 8, None, 180),
            (CONFIGURATION_COMPLETED, [8], -1, a_reconnect, 0),
            (EOF, [0, 1, 2, 3, 4,
                   5], -1, ConnectionError("Device disconnected"), 0),

            # (RELOAD_NA, [1], -1, a_reload_na, 0),
            # (DONE, [1], 2, None, 120),
            # (PROCEED, [2], 3, partial(a_send, "\r"), reload_timeout),
            # (self.rommon_re, [0, 3], 4, partial(a_send_boot, "boot"), 600),
            # (CANDIDATE_BOOT_IMAGE, [0, 3], 4, a_message_callback, 600),
            # (CONSOLE, [0, 1, 3, 4], 5, None, 600),
            # (self.press_return_re, [5], 6, partial(a_send, "\r"), 300),
            # # configure root username and password the same as used for device connection.
            # (RECONFIGURE_USERNAME_PROMPT, [6, 7], 8, None, 10),
            # (ROOT_USERNAME_PROMPT, [8], 9, partial(a_send_username, self.device.node_info.username), 1),
            # (ROOT_PASSWORD_PROMPT, [9], 9, partial(a_send_password, self.device.node_info.password), 1),
            # (CONFIGURATION_IN_PROCESS, [6, 9], 7, None, 180),
            # (CONFIGURATION_COMPLETED, [7], -1, a_reconnect, 0),
            # (TIMEOUT, [0, 1, 2], -1, ConnectionAuthenticationError("Unable to reload"), 0),
            # (EOF, [0, 1, 2, 3, 4, 5], -1, ConnectionError("Device disconnected"), 0),
            # (TIMEOUT, [6], 7, partial(a_send, "\r"), 180),
            # (TIMEOUT, [7], -1, ConnectionAuthenticationError("Unable to reconnect after reloading"), 0),
        ]

        fsm = FSM("RELOAD", self.device, events, transitions, timeout=600)
        return fsm.run()
Ejemplo n.º 35
0
    def reload(self, reload_timeout, save_config):
        """Reload the device."""
        MAX_BOOT_TIME = 1800  # 30 minutes - TODO(klstanie): move to config
        RELOAD_PROMPT = re.compile(
            re.escape("Reload hardware module ? [no,yes]"))

        START_TO_BACKUP = re.compile("Status report.*START TO BACKUP")
        BACKUP_IN_PROGRESS = re.compile("Status report.*BACKUP INPROGRESS")

        BACKUP_HAS_COMPLETED_SUCCESSFULLY = re.compile(
            "Status report.*BACKUP HAS COMPLETED SUCCESSFULLY")
        DONE = re.compile(re.escape("[Done]"))

        STAND_BY = re.compile("Please stand by while rebooting the system")
        CONSOLE = re.compile(
            "ios con[0|1]/(?:RS?P)?[0-1]/CPU0 is now available")
        CONFIGURATION_COMPLETED = re.compile("SYSTEM CONFIGURATION COMPLETED")
        CONFIGURATION_IN_PROCESS = re.compile(
            "SYSTEM CONFIGURATION IN PROCESS")
        BOOTING = re.compile(
            "Booting IOS-XR 64 bit Boot previously installed image")

        #           0                 1              2                         3                          4     5
        events = [
            RELOAD_PROMPT,
            START_TO_BACKUP,
            BACKUP_IN_PROGRESS,
            BACKUP_HAS_COMPLETED_SUCCESSFULLY,
            DONE,
            BOOTING,
            #   6                  7               8                     9                         10
            CONSOLE,
            self.press_return_re,
            CONFIGURATION_COMPLETED,
            CONFIGURATION_IN_PROCESS,
            self.username_re,
            # 11          12           13           14
            EOF,
            pexpect.TIMEOUT,
            self.rommon_re,
            STAND_BY
        ]

        transitions = [
            # do I really need to clean the cmd
            (RELOAD_PROMPT, [0], 1, partial(a_send_line,
                                            "yes"), MAX_BOOT_TIME),
            (START_TO_BACKUP, [0, 1], 2, a_message_callback, 60),
            (BACKUP_IN_PROGRESS, [0, 1, 2], 2, a_message_callback, 60),
            (BACKUP_HAS_COMPLETED_SUCCESSFULLY, [0, 1, 2], 3,
             a_message_callback, 10),
            (DONE, [1, 2, 3], 4, None, MAX_BOOT_TIME),
            (STAND_BY, [2, 3, 4], 5, a_message_callback, MAX_BOOT_TIME),
            (self.rommon_re, [0, 4], 5, partial(a_send_boot,
                                                "boot"), MAX_BOOT_TIME),
            (BOOTING, [0, 1, 2, 3, 4], 5, a_message_callback, MAX_BOOT_TIME),
            (CONSOLE, [0, 1, 2, 3, 4, 5], 6, None, 600),
            (self.press_return_re, [6], 7, partial(a_send, "\r"), 300),
            (CONFIGURATION_IN_PROCESS, [7], 8, None, 180),
            (CONFIGURATION_COMPLETED, [8], -1, a_reconnect, 0),
            (self.username_re, [9], -1, a_return_and_reconnect, 0),
            (EOF, [0, 1, 2, 3, 4,
                   5], -1, ConnectionError("Device disconnected"), 0),
            (pexpect.TIMEOUT, [7], 9, partial(a_send, "\r"), 180),
            (pexpect.TIMEOUT, [1, 5, 8], -1,
             ConnectionError(
                 "Boot process took more than {}s".format(MAX_BOOT_TIME)), 0),
            (pexpect.TIMEOUT, [9], -1,
             ConnectionAuthenticationError(
                 "Unable to reconnect after reloading"), 0)
        ]

        fsm = FSM("RELOAD", self.device, events, transitions, timeout=600)
        return fsm.run()
Ejemplo n.º 36
0
    def wait_for_string(self, expected_string, timeout=60):
        """Wait for string FSM for XR 64 bit."""
        ADMIN_USERNAME_PROMPT = re.compile("Admin Username:"******"Password:"******"Expecting: {}".format(pattern_to_str(expected_string)))
        self.log("Calvados prompt: {}".format(pattern_to_str(
            self.calvados_re)))

        transitions = [
            (ADMIN_USERNAME_PROMPT, [0], 6,
             partial(a_send_username, self.device.node_info.username), 5),
            (ADMIN_PASSWORD_PROMPT, [0, 6], 0,
             partial(a_send_password, self.device.node_info.password), 5),
            (self.authentication_error_re, [0], -1,
             ConnectionAuthenticationError("Admin plane authentication failed",
                                           self.device.hostname), 0),
            (self.syntax_error_re, [0], -1,
             CommandSyntaxError("Command unknown", self.device.hostname), 0),
            (self.connection_closed_re, [0], 1, a_connection_closed, 10),
            (pexpect.TIMEOUT, [0, 2], -1,
             CommandTimeoutError("Timeout waiting for prompt",
                                 self.device.hostname), 0),
            (pexpect.EOF, [0, 1], -1,
             ConnectionError("Unexpected device disconnect",
                             self.device.hostname), 0),
            (self.more_re, [0], 0, partial(a_send, " "), 10),
            (expected_string, [0, 1], -1, a_expected_prompt, 0),
            (self.calvados_re, [0], -1, a_expected_prompt, 0),
            (self.press_return_re, [0], -1, a_stays_connected, 0),
            (self.calvados_connect_re, [0], 2, None, 0),
            # admin command to switch to calvados
            (self.calvados_re, [2], 3, None, _C['calvados_term_wait_time']),
            # getting the prompt only
            (pexpect.TIMEOUT, [3], 0, partial(a_send, "\r\r"), timeout),
            # term len
            (self.calvados_term_length, [3], 4, None, 0),
            # ignore for command start
            (self.calvados_re, [4], 5, None, 0),
            # ignore for command start
            (self.calvados_re, [5], 0, a_store_cmd_result, 0),
        ]

        for prompt in self.device.get_previous_prompts():
            transitions.append((prompt, [0, 1], 0, a_unexpected_prompt, 0))

        fsm = FSM("WAIT-4-STRING",
                  self.device,
                  events,
                  transitions,
                  timeout=timeout)
        return fsm.run()
Ejemplo n.º 37
0
    def connect(self, driver):
        """Connect using the Telnet protocol specific FSM."""
        #              0            1                              2                      3
        events = [
            ESCAPE_CHAR,
            driver.press_return_re,
            driver.standby_re,
            driver.username_re,
            #            4                   5                  6                     7
            driver.password_re,
            driver.more_re,
            self.device.prompt_re,
            driver.rommon_re,
            #       8                              9              10            11              12
            driver.unable_to_connect_re,
            driver.timeout_re,
            pexpect.TIMEOUT,
            PASSWORD_OK,
            driver.syntax_error_re
        ]

        transitions = [
            (ESCAPE_CHAR, [0], 1, None, _C['esc_char_timeout']),
            (driver.syntax_error_re, [0], -1,
             CommandSyntaxError("Command syntax error"), 0),
            (driver.press_return_re, [0, 1], 1, a_send_newline, 10),
            (PASSWORD_OK, [0, 1], 1, a_send_newline, 10),
            (driver.standby_re, [0, 5], -1, partial(a_standby_console), 0),
            (driver.username_re, [0, 1, 5,
                                  6], -1, partial(a_save_last_pattern,
                                                  self), 0),
            (driver.password_re, [0, 1,
                                  5], -1, partial(a_save_last_pattern,
                                                  self), 0),
            (driver.more_re, [0, 5], 7, partial(a_send, "q"), 10),
            # router sends it again to delete
            (driver.more_re, [7], 8, None, 10),
            # (prompt, [0, 1, 5], 6, a_send_newline, 10),
            (self.device.prompt_re, [0, 1, 5], 0, None, 10),
            (self.device.prompt_re, [6, 8,
                                     5], -1, partial(a_save_last_pattern,
                                                     self), 0),
            (driver.rommon_re, [0, 1, 5], -1, partial(a_save_last_pattern,
                                                      self), 0),
            (driver.unable_to_connect_re, [0, 1,
                                           5], -1, a_unable_to_connect, 0),
            (driver.timeout_re, [0, 1, 5], -1,
             ConnectionTimeoutError("Connection Timeout", self.hostname), 0),
            (pexpect.TIMEOUT, [0, 1], 5, a_send_newline, 10),
            (pexpect.TIMEOUT, [5], -1,
             ConnectionTimeoutError("Connection timeout", self.hostname), 0)
        ]

        self.log("EXPECTED_PROMPT={}".format(
            pattern_to_str(self.device.prompt_re)))
        # setting max_transitions to large number to swallow prompt like strings from prompt
        fsm = FSM("TELNET-CONNECT",
                  self.device,
                  events,
                  transitions,
                  timeout=_C['connect_timeout'],
                  init_pattern=self.last_pattern,
                  max_transitions=500)
        return fsm.run()