def safe_mode_toggle(self): if self.ssh_shell.channel.send(chr(0x18)) != 1: raise base.ClientError('Failed to send ^D') hijack_safe_mode = \ "Hijacking Safe Mode from someone - unroll/release/don't take it [u/r/d]: " self.ssh_shell.shell_prompts.add_prompt(hijack_safe_mode) shell_output, _ = self.ssh_shell.read_until_prompt(10) if self.ssh_shell.last_prompt == hijack_safe_mode: self.ssh_shell.channel.send('r') shell_output, _ = self.ssh_shell.read_until_prompt(10) first_line = shell_output.pop(0) if first_line == '114': pass if len(shell_output) < 2: raise base.ClientError(shell_output[0]) if shell_output[1] == '[Safe Mode taken]': if self.in_safe_mode: raise base.ClientError('Mismatch with in_safe_mode') self.in_safe_mode = True elif shell_output[1] == '[Safe Mode released]': if not self.in_safe_mode: raise base.ClientError('Mismatch with in_safe_mode') self.in_safe_mode = False else: raise base.ClientError(shell_output[1]) return self.in_safe_mode
def configure_via_cli(self, new_config): if self.can_ssh(): try: cli_output = self.ssh_command('configure terminal') if not cli_output[0].startswith("'Enter configuration commands, one per line."): self._in_configure_mode = True else: raise base.ClientError(cli_output[0]) for config_line in new_config: stripped_line = config_line.strip() if stripped_line in ['end', 'exit']: continue cli_output = self.ssh_command(stripped_line) if cli_output != []: raise base.ClientError(cli_output[0]) finally: cli_output = self.ssh_command('end') if cli_output == []: self._in_configure_mode = False return True else: raise base.ClientError(cli_output[0]) return False
def ssh_command(self, *args, **kwargs): if not self.can_ssh(): raise base.ClientError('No SSH client') if not hasattr(self, 'ssh_shell'): raise base.ClientError('No shell channel') shell_output = self.ssh_shell.command(*args, **kwargs) if self.ssh_shell.last_prompt.endswith(' <SAFE> '): if not self.in_safe_mode: raise base.ClientError('Mismatch between in_safe_mode and prompt') return shell_output
def persist_configuration(self): if self.in_configure_mode: pass cli_output = self.ssh_command('write memory') if cli_output[0] != 'Building configuration...' and cli_output[-1] != '[OK]': raise base.ClientError(cli_output[0]) return True
def __init__(self, *args, **kwargs): super(Client, self).__init__(*args, **kwargs) grouped_kwargs = base.Utils.group_kwargs('snmp_', 'ssh_', **kwargs) if 'snmp_' in grouped_kwargs: snmp_client = snmp.Client(kwargs['host'], **grouped_kwargs['snmp_']) try: sys_object_id = snmp_client.sysObjectID() except snmp.SNMP_Exception: pass else: if not self.is_cumulus(sys_object_id): raise base.ClientError('Not a Cumulus device') self.snmp_client = snmp_client if 'ssh_' in grouped_kwargs: if 'username' not in grouped_kwargs['ssh_'] and 'username' in kwargs: grouped_kwargs['ssh_']['username'] = kwargs['username'] if 'password' not in grouped_kwargs['ssh_'] and 'password' in kwargs: grouped_kwargs['ssh_']['password'] = kwargs['password'] self.ssh_client = ssh.Client(kwargs['host'], **grouped_kwargs['ssh_']) shell_prompt = ssh.ShellPrompt(ssh.ShellPrompt.regexp_prompt(r'[^@]+@[^\$]+\$ ')) if self.can_snmp() and 'username' in grouped_kwargs['ssh_']: shell_prompt.add_prompt( grouped_kwargs['ssh_']['username'] + '@' + self.snmp_client.sysName() + '$ ' ) self.ssh_shell = ssh.Shell(self.ssh_client, shell_prompt)
def configure_via_cli(self, config_commands): if not self.in_safe_mode: self.safe_mode_toggle() for config_line in config_commands: cli_output = self.cli_command(config_line, use_cache=False) if cli_output != []: raise base.ClientError(cli_output[0]) self.safe_mode_toggle()
def persist_configuration(self): # if self.in_configure_mode: # pass cli_output = self.cli_command('copy running-config startup-config') if cli_output[0] != 'Copy completed successfully.': raise base.ClientError(cli_output[0]) return True
def __init__(self, *args, **kwargs): super(Client, self).__init__(*args, **kwargs) grouped_kwargs = base.Utils.group_kwargs('snmp_', 'ssh_', 'rosapi_', **kwargs) if HAVE_SNMP and 'snmp_' in grouped_kwargs: snmp_client = SNMP_Client(kwargs['host'], **grouped_kwargs['snmp_']) try: sys_object_id = snmp_client.sysObjectID() except SNMP_Exception: pass else: if not self.is_mikrotik(sys_object_id): raise base.ClientError('Not a Mikrotik device') self.snmp_client = snmp_client self.in_safe_mode = False self._cli_output_cache = {} if HAVE_APILIB and 'rosapi_' in grouped_kwargs: pass if not self.can_rosapi(): if 'ssh_' not in grouped_kwargs: grouped_kwargs['ssh_'] = {} if 'username' not in grouped_kwargs['ssh_'] and 'username' in kwargs: grouped_kwargs['ssh_']['username'] = kwargs['username'] if 'password' not in grouped_kwargs['ssh_'] and 'password' in kwargs: grouped_kwargs['ssh_']['password'] = kwargs['password'] shell_prompts = ssh.ShellPrompt( ssh.ShellPrompt.regexp_prompt(r'\[[^\@]+\@[^\]]+\] > $') ) shell_prompts.add_prompt( ssh.ShellPrompt.regexp_prompt(r'\[[^\@]+\@[^\]]+\] <SAFE> $') ) if 'username' in grouped_kwargs['ssh_']: original_username = grouped_kwargs['ssh_']['username'] grouped_kwargs['ssh_']['username'] += '+ct0h160w' if self.can_snmp(): shell_prompts.add_prompt( '[' + original_username + '@' + self.snmp_client.sysName() + '] > ' ) shell_prompts.add_prompt( '[' + original_username + '@' + self.snmp_client.sysName() + '] <SAFE> ' ) self.ssh_client = ssh.Client(kwargs['host'], **grouped_kwargs['ssh_']) shell_args = { 'combine_stderr': True, } self.ssh_shell = Shell(self.ssh_client, shell_prompts, optional_args=shell_args) self._datetime_offset = datetime.datetime.now() - self.ros_datetime()
def ssh_command(self, *args, **kwargs): if not self.can_ssh(): raise base.ClientError('No SSH client') if not hasattr(self, 'ssh_shell'): raise base.ClientError('No shell channel') shell_output = self.ssh_shell.command(*args, **kwargs) # config_prompt = self.ssh_shell.last_prompt.endswith('(config)#') # mode_mismatch = False # if self.in_configure_mode: # if not config_prompt: # mode_mismatch = True # else: # if config_prompt: # mode_mismatch = True # if mode_mismatch: # raise base.ClientError( # 'Mistmatch between in_configure_mode [{}] and prompt [{}]'.format( # self.in_configure_mode, # self.ssh_shell.last_prompt # ) # ) return shell_output
def in_configure_mode(self): mode_mismatch = False config_prompt = self.ssh_shell.last_prompt.endswith('(config)#') if self._in_configure_mode: if not config_prompt: mode_mismatch = True else: if config_prompt: mode_mismatch = True if mode_mismatch: raise base.ClientError( 'Mistmatch between in_configure_mode [{}] and prompt [{}]'. format(self._in_configure_mode, self.ssh_shell.last_prompt)) return self._in_configure_mode
def configure_via_cli(self, new_config): configured_okay = True if self.can_eapi(): try: config_output = self._pyeapi_node.config(new_config) except BaseException as error: configured_okay = False print error else: for output_line in config_output: if output_line != {}: configured_okay = False return configured_okay elif self.can_ssh(): try: cli_output = self.ssh_command('configure terminal') if cli_output == []: self.in_configure_mode = True else: raise base.ClientError(cli_output[0]) for config_line in new_config: stripped_line = config_line.strip() if stripped_line in ['end', 'exit']: continue cli_output = self.ssh_command(stripped_line) if cli_output != []: configured_okay = False # raise base.ClientError(cli_output[0]) except BaseException as error: configured_okay = False finally: cli_output = self.ssh_command('end') if cli_output == []: self.in_configure_mode = False else: configured_okay = False # raise base.ClientError(cli_output[0]) return configured_okay
def cli_command(self, *args, **kwargs): if self.can_ssh(): return self.ssh_command(*args, **kwargs) raise base.ClientError('No valid CLI handlers')
def ssh_command(self, *args, **kwargs): if not self.can_ssh(): raise base.ClientError('No SSH client') if not hasattr(self, 'ssh_shell'): raise base.ClientError('No shell channel') return self.ssh_shell.command(*args, **kwargs)
def privilege_level(self): cli_output = self.ssh_command('show privilege') partial_output = 'Current privilege level is ' if not cli_output[0].startswith(partial_output): raise base.ClientError(cli_output) return int(cli_output[0][len(partial_output):])
def safe_mode_exit(self): if self.ssh_shell.channel.send(chr(0x04)) != 1: raise base.ClientError('Failed to send ^X') self.in_safe_mode = False