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)
def a_send_username(username, ctx): """Sent the username text.""" if username: ctx.ctrl.sendline(username) return True else: ctx.ctrl.disconnect() raise ConnectionAuthenticationError("Username not provided", ctx.ctrl.hostname)
def a_send_password(password, ctx): """Send the password text. Before sending the password local echo is disabled. If password not provided it disconnects from the device and raises ConnectionAuthenticationError exception. """ if password: ctx.ctrl.send_command(password, password=True) return True else: ctx.ctrl.disconnect() raise ConnectionAuthenticationError("Password not provided", ctx.ctrl.hostname)
def a_authentication_error(ctx): """Raise ConnectionAuthenticationError exception and disconnect.""" ctx.ctrl.disconnect() raise ConnectionAuthenticationError("Authentication failed", ctx.ctrl.hostname)
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()
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()