def _enter_key_value(self,value): configuration_dialog = Dialog([ ['Enter a key', 'sendline({})'.format(value), None, True, True], ['Confirm the key:', 'sendline({})'.format(value), None, False, False], ]) target_state = self.handle.sm.current_state self.handle.run_cmd_dialog('set key', configuration_dialog, target_state=target_state)
def install_remove_inactive(section, steps, device, timeout=180): """ This stage removes partially installed packages/images left on the device. If a super package is left partially installed, we cannot attempt to install another until it is removed. Stage Schema ------------ install_image: timeout (int, optional): Maximum time to wait for remove process to finish. Defaults to 180. Example ------- install_remove_inactive: timeout: 180 """ with steps.start("Removing inactive packages") as step: install_remove_inactive_dialog = Dialog([ Statement(pattern=r".*Do you want to remove the above files\? \[y\/n\]", action='sendline(y)', loop_continue=False, continue_timer=False), ]) try: device.execute('install remove inactive', reply=install_remove_inactive_dialog, timeout=timeout) except Exception as e: step.failed("Remove inactive packages failed. Error: {e}".format(e=str(e)))
def clear_cores(device, core_list, crashreport_list, **kwargs): # Create dialog for response dialog = Dialog([ Statement(pattern=r'Delete.*', action='sendline()', loop_continue=True, continue_timer=False), ]) # preparing the full list to iterate over full_list = core_list + crashreport_list # Delete cores from the device for item in full_list: try: # Execute delete command for this core cmd = 'delete {location}/{core}'.format(core=item['core'], location=item['location']) output = device.execute(cmd, timeout=300, reply=dialog) # Log to user meta_info = 'Successfully deleted {location}/{core}'.format( core=item['core'], location=item['location']) logger.info(meta_info) return OK(meta_info) except Exception as e: # Handle exception logger.warning(e) meta_info = 'Unable to delete {location}/{core}'.format( core=item['core'], location=item['location']) logger.error(meta_info) return ERRORED(meta_info)
def rommon_boot(self, timeout=600): """Perform TFTP Boot from ROMMON. :return: None """ time.sleep(10) logger.info('=== Performing TFTP Boot from ROMMON') logger.info('=== Wait for installation to complete, timeout = {}' ' seconds ...'.format(str(timeout))) self.spawn_id.sendline('tftpdnld') d1 = Dialog([ ['rommon.*> ', 'sendline(tftpdnld)', None, True, False], ['Overwrite \(y/n\)', 'sendline(y)', None, True, False], ['login:'******'sendline()', None, False, False], ]) try: d1.process(self.spawn_id, timeout=timeout) self.spawn_id.sendline() except: logger.info("=== Rommon file download failed, raise runtime error. ") raise RuntimeError( ">>>>>> Download failed. Please check details - " "tftp_server: {}, image file: {}".format(self.rommon_tftp_server, self.rommon_image)) logger.info("=== Rommon file was installed successfully.")
def default_interface(device, interfaces): """ Reset junos interface configuration Args: device (`obj`): Device object interfaces (`list`): List of interfaces to be defaulted Returns: None """ dialog = Dialog( [ Statement( pattern=r"Delete everything under this level?.*", action="sendline(yes)", loop_continue=True, continue_timer=False, ) ] ) for intf in interfaces: config_cmd = ["edit interfaces {}".format(intf), "delete"] try: device.configure(config_cmd, reply=dialog) log.info("Successfully defaulted {}".format(intf)) except SubCommandFailure as e: raise SubCommandFailure( "Couldn't default {interface}. Error:\n{error}".format( interface=intf, error=e ) )
def __init__(self, connection, context, **kwargs): self.connection = connection self.context = context self.timeout_pattern = ['Timeout occurred', ] self.error_pattern = [] self.start_state = 'enable' self.end_state = 'enable' self.result = None self.service_name = 'copy' self.dialog = Dialog([ [pr.are_you_sure, lambda spawn: spawn.sendline('y'), None, True, False], [pc.tftp_starting, None, None, True, False], [pc.tftp_complete, None, None, True, False], [pc.restart_system, None, None, False, False], # Sometime, when AP Images are missing TSIM needs a little prod [pc.reboot_to_complete, lambda spawn: spawn.sendline('reset system forced'), None, True, False]]) # add the keyword arguments to the object self.__dict__.update(kwargs)
def unconfigure_pki_trustpoint(device, label_name): """ Unconfigures Trustpoint related config on device Args: device ('obj'): device to use label_name ('str'): Label name Returns: None Raises: SubCommandFailure """ log.debug("Unconfigure Trustpoint on device") dialog = Dialog([ Statement(pattern=r'.*\% Removing an enrolled trustpoint will destroy all certificates\n' 'received from the related Certificate Authority\.\n' 'Are you sure you want to do this\? \[yes\/no\]\:', action='sendline(y)', loop_continue=True, continue_timer=False) ]) try: device.configure("no crypto pki trustpoint {label_name}".format(label_name=label_name), reply=dialog) except SubCommandFailure as e: raise SubCommandFailure( "Could not unconfigure Trustpoint related config from device " "Error: {error}".format(error=e) )
def execute_write_erase(device, timeout=300): ''' Execute 'write erase' on the device Args: device ('obj'): Device object timeout ('int'): Max time to for write erase to complete in seconds ''' log.info("Executing 'write erase' on the device") # Unicon Statement/Dialog write_erase = Statement( pattern=r".*remove all configuration files\! Continue\? \[confirm\]", action='sendline()', loop_continue=True, continue_timer=False) try: output = device.execute("write erase", reply=Dialog([write_erase]), timeout=timeout) except Exception as err: log.error("Failed to write erase: {err}".format(err=err)) raise Exception(err) if "[OK]" in output: log.info("Successfully executed 'write erase'") else: raise Exception("Failed to execute 'write erase'")
def fxos_ftd_transition(statemachine, spawn, context): sm = statemachine console = context.get('console', False) if console: spawn.sendline('connect ftd') else: dialog = Dialog([ generic_statements.login_stmt, generic_statements.password_stmt, Statement(pattern=patterns.you_came_from_fxos, action=update_context, args={'console': True}, loop_continue=True) ]) spawn.sendline('exit') # Wait a bit using expect, login prompt could appear spawn.expect('.+', trim_buffer=False) sm.go_to(['ftd', 'disable', 'fxos'], spawn, context=context, timeout=spawn.timeout, dialog=dialog) if sm.current_state == 'fxos': spawn.sendline('connect ftd') context.update({'console': True}) else: spawn.sendline()
def configure_replace(device, file_location, timeout=60, file_name=None): """Configure replace on device Args: device (`obj`): Device object file_location (`str`): File location timeout (`int`): Timeout value in seconds file_name (`str`): File name Returns: None Raises: pyATS Results """ if file_name: file_location = '{}{}'.format(file_location, file_name) try: # check if file exist device.execute.error_pattern.append('.*Path does not exist.*') device.execute("dir {}".format(file_location)) except Exception: raise Exception("File {} does not exist".format(file_location)) dialog = Dialog([ Statement(pattern=r'\[no\]', action='sendline(y)', loop_continue=True, continue_timer=False) ]) device.configure("load {}\ncommit replace".format(file_location), timeout=timeout, reply=dialog)
def _reload_expect_prompt(self, timeout=300): """Wait for ASA to be back online after reload :param timeout: timeout for reload :return: None """ if 'telnet' in self.type: disable_prompt = self.sm.patterns.prompt.disable_prompt dialog = Dialog([ ['Process shutdown finished', None, None, True, False], ['The system is restarting', None, None, True, False], ['Configuring network interfaces... done', None, None, True, False], ['Compiled on', None, None, True, False], ['The digital signature of the running image verified successfully', \ None, None, True, False], ['Compiled on', None, None, True, False], ['Cisco Adaptive Security Appliance Software Version', None, None, True, False], [disable_prompt, 'sendline()', None, False, False], ]) dialog.process(self.spawn_id, timeout=timeout) self.go_to('any') elif 'ssh' in self.type: pass
def save_device_information(device, **kwargs): """Save running-configuration to startup-config. This is for general IOSXE devices. Args: Mandatory: device (`obj`) : Device object. Raises: None Example: >>> save_device_information(device=Device()) """ # configure config-register device.configure('config-register 0x2102') # save all configuration to startup for all slots dialog = Dialog([ Statement(pattern=r'Destination +filename +\[.*\].*', action='sendline()', loop_continue=True, continue_timer=False) ]) device.execute('copy running-config nvram:startup-config', reply=dialog) device.execute('write memory')
def enter_shell(device, timeout=60): """Enter shell prompt on IOSXE deivces by using command "request platform software system shell switch active R0" Args: Mandatory: device (`obj`) : Device object. Optional: timeout (`int`) : Command execution timeout. Returns: None Raises: None Example: >>> enter_shell(device=Device()) """ # Run workon.sh on the RP shell dialog = Dialog([ Statement(pattern=r'continue\? +\[y\/n\]', action='sendline(y)', loop_continue=True, continue_timer=False) ]) # store original pattern enable_state = device.state_machine.get_state('enable') device.origin_pattern = enable_state._pattern # Completely remove the enable state pattern and update it with new pattern. enable_state._pattern = [r'(.*)\:\/]\$'] # enter shell device.execute('request platform software system shell switch active R0', reply=dialog)
def call_service(self, target, timeout=None, *args, **kwargs): if not self.connection.connected: return con = self.connection sm = self.get_sm() dialog = Dialog([ftd_statements.command_not_completed_stmt]) timeout = timeout if timeout is not None else self.timeout if isinstance(target, str): target_list = [target] elif isinstance(target, list): target_list = target else: raise Exception('Invalid switchto target type: %s' % repr(target)) for target_state in target_list: m1 = re.match('module\s+(\d+)\s+console', target_state) m2 = re.match('cimc\s+(\S+)', target_state) m3 = re.match('chassis scope (.*)', target_state) if m1: mod = m1.group(1) self.context._module = mod target_state = 'module_console' elif m2: mod = m2.group(1) self.context._cimc_module = mod target_state = 'cimc' con.state_machine.go_to('chassis', con.spawn, context=self.context, hop_wise=True, timeout=timeout) elif m3: scope = m3.group(1) self.context._scope = scope target_state = 'chassis_scope' con.state_machine.go_to('chassis', con.spawn, context=self.context, hop_wise=True, timeout=timeout) else: target_state = target.replace(' ', '_') valid_states = [x.name for x in sm.states] if target_state not in valid_states: con.log.warning('%s is not a valid state, ignoring switchto' % target_state) return con.state_machine.go_to(target_state, con.spawn, context=self.context, hop_wise=True, timeout=timeout, dialog=dialog) self.end_state = sm.current_state
def _cli(device, cmd, timeout, prompt): """ Send command to device and get the output Args: device (`obj`): Device object cmd (`str`): Command timeout (`int`): Timeout in second prompt (`obj`): Unicon statement Returns: output (`obj`): Output """ # Create a dialog state = device.state_machine.current_state pattern = device.state_machine.get_state(state).pattern device.send(cmd) statements = [] statements.append(prompt) statements.append(Statement(pattern=pattern)) statements.extend(device.state_machine.default_dialog) statements.extend(default_statement_list) dialog = Dialog(statements) output = dialog.process(device.spawn, timeout=timeout) return output
def create(self): super().create() self.remove_path('enable', 'rommon') self.remove_path('rommon', 'disable') self.remove_state('rommon') rommon = State('rommon', patterns.rommon_prompt) enable_to_rommon = Path(self.get_state('enable'), rommon, 'reload', Dialog(reload_statement_list)) rommon_to_disable = Path(rommon, self.get_state('disable'), boot_from_rommon, Dialog(connection_statement_list)) self.add_state(rommon) self.add_path(enable_to_rommon) self.add_path(rommon_to_disable)
def execute_clean_controller_fabric(device, max_time=90): """ Cleans the controller part of the ACI fabric Args: device (obj): Device to execute on max_time (int, optional): Max time in seconds allowed for 'acidiag touch clean'. Defaults to 90. Returns: True if successful False if failed Raises: N/A """ clean_dialog = Dialog([ Statement( pattern=r".*This command will wipe out this device\, Proceed\? \[y\/N\].*", action='sendline(y)' ) ]) try: device.execute( 'acidiag touch clean', timeout=max_time, reply=clean_dialog, error_pattern=[r".*Cant find image.*"]) except Exception as e: log.error("Failed to execute the command. Error: {}".format(str(e))) return False else: return True
def ssh_vty(self, ip, port='22'): """Setup ssh connection to the server. :param ip: ssh host/ip :param port: ssh port :return: ssh_line """ from .constants import WebserverConstants spawn = Spawn( 'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ' '-l {} -p {} {} \n'.format(WebserverConstants.username, port, ip)) d1 = Dialog([ [ 'continue connecting (yes/no)?', 'sendline(yes)', None, True, False ], [ '(p|P)assword:', 'sendline({})'.format(WebserverConstants.login_password), None, False, False ], ]) try: d1.process(spawn, timeout=60) spawn.sendline() except TimeoutError: pass ssh_line = WebserverLine(spawn, self.sm, 'ssh_ftd') return ssh_line
def call_service(self, reload_command='reset system forced', dialog=Dialog([]), timeout=None, **kwargs): con = self.connection timeout = timeout or self.timeout con.log.debug('+++ reloading %s with reload_command %s and timeout is %s +++' % (self.connection.hostname, reload_command, timeout)) dialog += self.dialog_reload try: con.spawn.sendline(reload_command) self.result = dialog.process(con.spawn, timeout=timeout, prompt_recovery=self.prompt_recovery) con.state_machine.go_to('any', con.spawn, context=self.context, prompt_recovery=self.prompt_recovery, timeout=con.connection_timeout, dialog=con.connection_provider.get_connection_dialog()) con.connection_provider.init_handle() except Exception as err: raise SubCommandFailure('Reload failed %s' % err)
def execute_write_erase(device, timeout=300): ''' Execute write erase on the device Args: device ('obj'): Device object ''' log.info("Executing Write Erase") write_erase = Statement( pattern=r'.*Do you wish to proceed anyway\? \(y\/n\)\s*\[n\]', action='sendline(y)', loop_continue=True, continue_timer=False) # Add permisson denied to error pattern origin = list(device.execute.error_pattern) error_pattern = ['.*[Pp]ermission denied.*'] error_pattern.extend(origin) try: device.execute("write erase", reply=Dialog([write_erase]), timeout=timeout, error_pattern=error_pattern) except Exception as err: log.error("Failed to write erase: {err}".format(err=err)) raise Exception(err) finally: # restore original error pattern device.execute.error_pattern = origin
def install_activate(self, steps, device, install_timeout=INSTALL_TIMEOUT): with steps.start("Activating operation ID {}".format( self.operation_id)) as step: cmd = 'install activate id {id}'.format(id=self.operation_id) install_activate_dialog = Dialog([ Statement(pattern='.*This install operation will reload the ' 'system\, continue\?.*\[yes[:\/]no\]\:\[yes\].*', action='sendline(yes)', loop_continue=False, continue_timer=False) ]) try: # send the install cmd device.sendline(cmd) # Process the dialog that appears install_activate_dialog.process(device.spawn, timeout=install_timeout) # Wait for successful output device.expect([self.successful_operation_string], timeout=install_timeout) except Exception as e: step.failed("Attempting to activate install id '{id}' " "failed. Error: {e}".format(id=self.operation_id, e=str(e)))
def create(self): # Create States disable_state = State(AsaSmStates.DISABLE_STATE.value, self.patterns.prompt.disable_prompt) enable_state = State(AsaSmStates.ENABLE_STATE.value, self.patterns.prompt.enable_prompt) config_state = State(AsaSmStates.CONFIG_STATE.value, self.patterns.prompt.config_prompt) # Add states self.add_state(disable_state) self.add_state(enable_state) self.add_state(config_state) # Create paths enable_dialog = Dialog( [self.statements.disable_to_enable_statement, self.statements.set_enable_pwd_statement, self.statements.repeat_enable_pwd_statement, ] ) disable_to_enable_path = Path(disable_state, enable_state, 'enable', enable_dialog) enable_to_disable_path = Path(enable_state, disable_state, 'disable', None) enable_to_config_path = Path(enable_state, config_state, 'config t', None) config_to_enable_path = Path(config_state, enable_state, 'end', None) # Add paths self.add_path(disable_to_enable_path) self.add_path(enable_to_disable_path) self.add_path(enable_to_config_path) self.add_path(config_to_enable_path)
def copy_file_to_running_config(device, path, file, timeout=60): """ Restore config from local file using copy function Args: device (`obj`): Device object path (`str`): directory file (`str`): file name timeout (`str`): timeout Returns: None """ dialog = Dialog( [ Statement( pattern=r".*Destination filename.*", action="sendline()", loop_continue=True, continue_timer=False, ) ] ) try: device.execute( "copy {path}{file} running-config".format(path=path, file=file), reply=dialog, timeout=timeout ) except SubCommandFailure as e: raise SubCommandFailure( "Could not copy saved configuration on " "device {device}.\nError: {e}".format(device=device.name, e=str(e)) )
def _reloadLc(self, lc): """Do the reload LC action for asr1k devices. Args: Mandatory: lc (`str`) : LC slot number need to reload. Raises: Unicon errors Example: >>> _reloadLc(lc='27') """ # unicon dialog = Dialog([ Statement(pattern=r'Proceed\[y\/n\]\?.*', action='sendline(y)', loop_continue=True, continue_timer=False), Statement(pattern=r'\(y\/n\)\?.*', action='sendline(y)', loop_continue=True, continue_timer=False) ]) # Execute command to reload LC self.device.execute('admin reload location {}'.format(lc), reply=dialog) time.sleep(5)
def restore_running_config(device, path, file, timeout=60): """ Restore config from local file Args: device (`obj`): Device object path (`str`): directory file (`str`): file name timeout (`int`): Timeout for applying config Returns: None """ dialog = Dialog([ Statement( pattern=r".*Enter Y.*", action="sendline(y)", loop_continue=True, continue_timer=False, ) ]) try: device.execute("configure replace {path}{file}".format(path=path, file=file), reply=dialog, timeout=timeout) except SubCommandFailure as e: raise SubCommandFailure("Could not replace saved configuration on " "device {device}\nError: {e}".format( device=device.name, e=str(e)))
def create(self): cisco_exec = State('cisco_exec', patterns.cisco_prompt) cisco_config = State('cisco_config', patterns.cisco_config_prompt) self.add_state(cisco_exec) self.add_state(cisco_config) cisco_exec_to_config = Path(cisco_exec, cisco_config, 'config term', None) # Ignore config changes on state change # config commits are done as part of the configure method cisco_config_dialog = Dialog([ # Uncommitted changes found, commit them? [yes/no/CANCEL] no [ patterns.cisco_commit_changes_prompt, 'sendline(no)', None, True, False ], ]) cisco_config_to_exec = Path(cisco_config, cisco_exec, 'end', cisco_config_dialog) self.add_path(cisco_exec_to_config) self.add_path(cisco_config_to_exec) self.add_default_statements(default_statement_list)
def rollback_checkpoint(self, device, name): ''' Rollback configuration by checkpoint Args: device ('obj'): Device Object. name ('str'): Checkpoint name. Returns: None Raises: SyntaxError example: >>> rollback_checkpoint(device=device, name='bgp-001') ''' log.info('rollback configuration by checkpoint {n}'.format(n=name)) # rollback checkpoint try: dialog = Dialog([ Statement(pattern=r'you want to proceed.*', action='sendline(y)', loop_continue=True, continue_timer=False) ]) device.execute('configure replace {}'.format(name), reply=dialog) except Exception as e: raise SyntaxError('Error when running rollback running-config ' 'checkpoint {}'.format(name)) from e
def create(self): """creates the junos state machine""" ########################################################## # State Definition ########################################################## shell = State('shell', patterns.shell_prompt) enable = State('enable', patterns.enable_prompt) config = State('config', patterns.config_prompt) ########################################################## # Path Definition ########################################################## config_dialog = Dialog([ [patterns.commit_changes_prompt, 'sendline(yes)', None, True, False], ]) enable_to_shell = Path(enable, shell, 'exit', None) shell_to_enable = Path(shell, enable, 'cli', None) enable_to_config = Path(enable, config, 'configure', None) config_to_enable = Path(config, enable, 'commit\nexit', config_dialog) # Add State and Path to State Machine self.add_state(shell) self.add_state(enable) self.add_state(config) self.add_path(enable_to_shell) self.add_path(shell_to_enable) self.add_path(enable_to_config) self.add_path(config_to_enable)
def __init__(self, connection, context, **kwargs): super().__init__(connection, context, **kwargs) self.start_state = 'enable' self.end_state = 'enable' self.service_name = 'switchover' self.timeout = connection.settings.SWITCHOVER_TIMEOUT self.dialog = Dialog(switchover_statement_list)
def scp(self, cmd, pwd, target_state=None, timeout=None): """perform the scp action (based on user cmd), and follow up with all prompts in scp. :param cmd: scp command, such as "scp [email protected]://abc.log ." :param pwd: password for scp :param target_state: move to this state before issuing the command :param timeout: in seconds :return: None """ if not target_state: target_state = 'sudo_state' if not timeout: timeout = self.default_timeout logger.debug("scp command: {}".format(cmd)) d = Dialog([[ 'continue connecting (yes/no)?', 'sendline(yes)', None, True, False ], ['.*(P|p)assword:', 'sendline({})'.format(pwd), None, True, False], [ '100%.*?' + self.sm.get_state('{}'.format(target_state)).pattern, None, None, False, False ]]) self.run_cmd_dialog(cmd, d, target_state, timeout)