def test_sshconn2(self, sleep_patch, patch1, patch2, patch3, patch4, patch5): handle = SshConn(host='dummy', user='******', password='******') self.assertIsInstance(handle, SshConn) handle = SshConn(host='dummy', user='******', password='******', ssh_key_file="file") self.assertIsInstance(handle, SshConn) handle = SshConn(host='dummy', user='******', password='******', ssh_key_file="file", port="22") self.assertIsInstance(handle, SshConn) with patch('jnpr.toby.hldcl.connectors.sshconn.select', side_effect=[(0, '', ''), (1, '', ''), (1, '', '')]) as select_patch: patch2.return_value = Shellmock1() handle = SshConn(host='dummy', user='******', password='******', ssh_key_file="file", port="22") self.assertIsInstance(handle, SshConn)
def prepend_remote_file(host_name: str, string_to_write: str, file_name: str): """Prepends a string to an existing remote file. :param host_name: **REQUIRED** Full host name of remote host. Example input: '*****@*****.**' :param string_to_write: **REQUIRED** The string you want written to the remote file. :param file_name: **REQUIRED** The full path of the file as it is stored on the remote host. Example input: '/usr/local/etc/raddb/sample.txt' :return: True if file operation is successful. In the event of failure, an exception is thrown. """ # Prepend operation is heavier than overwrite/append. Must read in file beforehand, then regenerate. ssh_connection = SshConn(host=host_name, user='******', password='******') sftp_client = ssh_connection.open_sftp() # Read in the previous contents of the file with sftp_client.open(file_name, mode='r') as file_handle: previous_contents = file_handle.read() with sftp_client.open(file_name, mode='w') as handle: handle.write(string_to_write) handle.write(previous_contents) return True
def clobber_remote_file(host_name: str, string_to_write: str, file_name: str): """ This function clobbers an existing file stored on a remote host with a user supplied string. If the file does not exist, it will be created and populated with said string. :param host_name: **REQUIRED** Full host name of remote host. Example input: '*****@*****.**' :param string_to_write: **REQUIRED** The string you want written to the remote file. :param file_name: **REQUIRED** The full path of the file as it is stored on the remote host. Example input: '/usr/local/etc/raddb/sample.txt' :return: True if file operation is successful. In the event of failure, an exception is thrown. """ # Establish SshConn for remote file operations. Write config to specified file ssh_connection = SshConn(host=host_name, user='******', password='******') sftp_client = ssh_connection.open_sftp() file_handle = sftp_client.open(file_name, mode='w') # Write to file try: file_handle.write(string_to_write) finally: file_handle.close() return True
def test_sshconn_execute(self, sleep_patch): sobject = MagicMock(spec=SshConn) sobject.client = MagicMock() dhandle = MagicMock() self.assertEqual(SshConn.execute(sobject, cmd="show version", pattern="os",\ device=dhandle, no_response='no_response'), 1) delattr(dhandle, "shelltype") sobject.wait_for.return_value = (False, "test") #self.assertRaises(SshConn.execute(sobject, cmd="show version", pattern=["os"],\ # device=dhandle), -1) sobject.wait_for.return_value = (True, "test") self.assertEqual(SshConn.execute(sobject, cmd="show version", pattern="String",\ device=dhandle), 1) sobject.wait_for.side_effect = [(True, "---(more)---"), (True, "test")] self.assertEqual(SshConn.execute(sobject, cmd="show version", pattern=["os"],\ device=dhandle), 1) sobject.wait_for.side_effect = [(True, "---(more)---"), (True, "test")] self.assertEqual(SshConn.execute(sobject, cmd="show version", pattern="String",\ device=dhandle, raw_output=True), 1) sobject.wait_for.side_effect = [(True, """test abc"""), (True, """test abc""")] self.assertEqual(SshConn.execute(sobject, cmd="show version", pattern="String",\ device=dhandle, raw_output=False), 1)
def test_sshconn(self, sleep_patch, patch1, patch2, patch3, patch4, patch5): handle = SshConn(host='dummy', user='******', password='******') self.assertIsInstance(handle, SshConn) handle = SshConn(host='dummy', user='******', password='******', port='555') self.assertIsInstance(handle, SshConn)
def test_sshconn_waitfor1(self, patch1, patch2): sshhandle = MagicMock(spec=SshConn) sshhandle.client = MagicMock() sshhandle.client.recv = MagicMock() sshhandle.client.recv.return_value = b'FreeBSD $' self.assertEqual( SshConn.wait_for(sshhandle, expected=['$', '#'], shell='sh'), (True, 'FreeBSD $')) self.assertEqual(SshConn.wait_for(sshhandle, shell='csh'), (True, 'FreeBSD $')) with patch('jnpr.toby.hldcl.connectors.sshconn.select', side_effect=[(0, '', ''), (1, '', ''), (1, '', '')]) as select_patch: patch2.return_value = Shellmock1() self.assertEqual(SshConn.wait_for(sshhandle, shell='csh'), (True, 'FreeBSD $'))
def __init__(self, **kwargs): """ :param host: **REQUIRED** hostname or IP address of device to telnet to :param user: *OPTIONAL* Login user name. If not provided will be derived from Toby framework defaults. :param password: *OPTIONAL* Login Password. If not provided will be derived from Toby framework defaults. :param connect_mode: *OPTIONAL* Connection mode to device. Default is telnet. Supported value is telnet. """ if 'host' not in kwargs: raise TobyException("Mandatory Parameter host missing") # if username and password are not specified by caller kwargs['os'] = kwargs.get('osname', 'WINDOWS') if not kwargs.get('user', None): kwargs['user'], kwargs['password'] = credentials.get_credentials( os=kwargs.get('osname', 'WINDOWS')) host = kwargs.get('host') connect_mode = kwargs.get('connect_mode', 'telnet') super(Windows, self).__init__(**kwargs) self.log(message='Trying to connect to device ' + host + ' via ' + connect_mode + ' ...') self.prompt = 'Toby-%s-%s' % (os.getpid(), host) self.prompt += '%' self.port = kwargs.get('text_port') try: if connect_mode == 'ssh': self.prompt = '>\s?' handle = SshConn(host=host, user=kwargs['user'], password=kwargs['password'], initialize_command='cd') else: handle = TelnetConn(host=host, user=kwargs['user'], password=kwargs['password'], port=self.port) self.handle = handle self.log(message='Connection to ' + host + ' via ' + connect_mode + ' is successful.') except: raise TobyException( "Cannot connect text channel via %s to %s Device %s" % (connect_mode, kwargs['os'], host), host_obj=self) if self.port == 23: self.set_shell_prompt(prompt=self.prompt) else: self.prompt = '>\s?' self.connected = 1 self.response = '' self.mode = 'shell'
def _get_version(self): """ Get Chassis OS Version of Spirent TC : :return: spirent TC version """ self.log(level="DEBUG", message="Entering '_get_version'\n"+__file__) version = None try: self.telnet_handle = telnetlib.Telnet(self.landslide_manager) # self.telnet_handle.set_debuglevel(10) # self.telnet_handle.write(b"\n") time.sleep(self.wait) self.telnet_handle.read_until(b'login: '******'ascii') self.telnet_handle.write(uname) time.sleep(self.wait) self.telnet_handle.read_until(b"Password: "******"\n" pwd = pwd.encode('ascii') self.telnet_handle.write(pwd) time.sleep(self.wait) time.sleep(self.wait) self.telnet_handle.read_until(b"##>") cmd = "cat /usr/sms/data/tasoutput.txt | grep 'TAS started'\n" cmd = cmd.encode('ascii') self.telnet_handle.write(cmd) time.sleep(self.wait) match_results = self.telnet_handle.expect([br"\d+.\d+.\d+.\d+"]) full_version = match_results[1].group(0).decode('ascii') version = full_version ver_re = re.compile(r'\d+.\d+.\d+(\.\d+)?') if ver_re.search(full_version): version = ver_re.search(full_version).group() except Exception as ex: # pylint: disable=bare-except #if telnet isn't listening, try ssh self.log(level="WARN", message="Unable to detect Landslide Chassis version use telnet due to: %s" % ex.__str__()) try: ssh_handle = SshConn(host=self.landslide_manager, user=self.telnetuser, password=self.telnetpwd) paramiko_handle = ssh_handle.client paramiko_handle.send('cat /usr/sms/data/tasoutput.txt | grep "TAS started"\n') time.sleep(self.wait) response = paramiko_handle.recv(1024) ver_re = re.compile(r'\d+.\d+.\d+(\.\d+)?') if ver_re.search(str(response)): version = ver_re.search(str(response)).group() except Exception as ex: self.log(level="ERROR", message="Unable to detect Landslide Chassis version using ssh connection due to: %s" % ex.__str__()) if not version: self.log(level="DEBUG", message="Unable to detect Landslide Chassis version") raise TobyException("Unable to detect Landslide Chassis version") self.log('CHASSIS VERSION: ' + version) self.log(level="DEBUG", message="Exiting '_get_version' with return value/code :\n"+str(version)) return version
def test_sshconn_waitfor4(self, patch1, patch2): sshhandle = MagicMock(spec=SshConn) sshhandle.client = MagicMock() sshhandle.client.recv = MagicMock() sshhandle.client.recv.return_value = b'\xC4abc' self.assertEqual( SshConn.wait_for(sshhandle, expected=['ab', 'c'], timeout=True, shell='csh'), (True, 'Äabc'))
def read_remote_file_to_string(host_name: str, file_name: str): """Reads a remote file and returns a string containing the contents of that remote file. :param host_name: **REQUIRED** Full host name of remote host. Example input: '*****@*****.**' :param file_name: **REQUIRED** The full path of the file as it is stored on the remote host. Example input: '/usr/local/etc/raddb/sample.txt' :return: String containing the current contents of the file """ # Prepend operation is heavier than overwrite/append. Must read in file beforehand, then regenerate. ssh_connection = SshConn(host=host_name, user='******', password='******') sftp_client = ssh_connection.open_sftp() # Read in the previous contents of the file with sftp_client.open(file_name, mode='r') as file_handle: current_contents = file_handle.read() # Return the byte string as a decoded string return current_contents.decode("utf-8")
def test_sshconn_waitfor3(self, search_patch, patch1, patch2): sshhandle = MagicMock(spec=SshConn) sshhandle.client = MagicMock() data_obj = MagicMock() decode_obj = MagicMock() data_obj.decode.return_value = decode_obj sshhandle.client.recv = data_obj data_obj.decode = MagicMock(return_value='Test') self.assertNotEqual( SshConn.wait_for(sshhandle, expected=['ab', 'c'], timeout=1, shell='csh'), (True, decode_obj))
def reconnect(self, timeout=30, interval=10): """ Method called by user to reconnect to Host :param timeout: *OPTIONAL* Time by which device need to reconnect. Default is 30 seconds :param interval: *OPTIONAL* Interval at which reconnect need to be attempted. Default is 10 seconds :return: True if device reconnection is successful. In all other cases Exception is raised """ try: self.log(level='INFO', message="Now checking %s's %s server.." % (self.host, self.connect_mode)) if check_socket(host=self.host, socket_type=self.connect_mode, timeout=timeout, interval=interval): self.log(level='DEBUG', message='Successfully created %s socket to %s' % (self.connect_mode, self.host)) else: raise TobyException('Failed to create %s socket to %s' % (self.host, self.connect_mode), host_obj=self) if self.connect_mode == 'ssh': if self.handle.client.get_transport().isAlive(): self.handle.client.close() self.handle = SshConn(host=self.host, user=self.user, password=self.password, port=22, initialize_command='cd') else: self.handle = TelnetConn(host=self.host, user=self.user, password=self.password) if self.port == 23: self.prompt = 'Toby-%s-%s' % (os.getpid(), self.host) self.prompt += '%' self.set_shell_prompt(prompt=self.prompt) else: self.prompt = '>\s?' except: raise TobyException("Error reconnecting to Device", host_obj=self) return True
def _get_version(self): """ Get Chassis OS Version of Breakingpoint TC : :return: breakingpoint chassisversion """ version = None try: ssh_handle = SshConn(host=self.chassis, user=self.username, password=self.password) paramiko_handle = ssh_handle.client # this is for version 8.40 and above, for lower versions the command is harmless paramiko_handle.send('enter bps\n') time.sleep(4) paramiko_handle.send('version\n') ## increase waiting time from 1s to 4s, otherwise it cannot get the output time.sleep(4) response = paramiko_handle.recv(1024) ver_re = re.compile(r'version:(\d+\.\d+\.\d+)') if ver_re.search(str(response)): version = ver_re.search(str(response)).group(1) except Exception as ex: self.log( level="ERROR", message= "Toby was not able to detect Breakingpoint version info using ssh connection due to: %s" % ex.__str__()) if not version: raise TobyException("Unable to detect Breakingpoint version", host_obj=self) self.log('CHASSIS VERSION: ' + version) self.major_version = re.search(r'^\d+', version).group(0) if not self.major_version: raise TobyException( "Unable to derive major and minor version from " + version, host_obj=self) if float(self.major_version) < 8.0: raise TobyException("Unsupported version " + self.major_version + ". Minimum version supported: 8.0", host_obj=self) return version
def _connect_unix(kvargs): """ _connect_unix function Used to connect to Unix device """ if kvargs.get('connect_targets') == "console": host = kvargs.get('con-ip') else: host = kvargs.get('host') connect_mode = kvargs.get('connect_mode', 'ssh') osname = kvargs.get('osname', 'unix') connect_timeout = kvargs.get('timeout', '30') try: if connect_mode == 'ssh': if 'proxy_host' in kvargs or 'proxy_hosts' in kvargs: proxy = True hosts = _build_proxy_hosts_stack(kvargs) # build SshConn to proxy instead of final target resource t.log(level="INFO", message='Trying to connect to device ' + hosts[0]['host'] + ' via SSH ...') handle = SshConn(host=hosts[0]['host'], user=hosts[0]['user'], password=hosts[0]['password'], port=int(hosts[0].get('port', 22)), ssh_key_file=hosts[0].get( 'ssh_key_file', None)) tnh = handle.client # now hop from host to host to get to final target for i in range(1, len(hosts)): t.log(level="INFO", message='Proxy connection - ' + hosts[i]['connect_command']) res = tnh.send(hosts[i]['connect_command'] + '\r') # if user has specified a password key as 'None', it indicates a password-less # login to the host. Below condition is executed when password is not None if hosts[i]['password'] and hosts[i][ 'password'] != "None" and not hosts[i][ 'ssh_key_file']: t.log(level="INFO", message="PASSWORD: "******"DEBUG", message="waiting for password prompt") while True: read, write, err = select([tnh], [], [], 10) if read: data = tnh.recv(1024) data = data.decode("utf-8") got = got + data t.log(level="DEBUG", message="Read Data:\n---\n%s\n---" % data) # in case the connect command is 'ssh' and we are prompted with a # key update, go ahead and pass 'yes' and continue waiting on the # until password prompt appears if re.search( r"Are you sure you want to continue connecting \(yes/no\)", data): tnh.send("yes\r") # if password prompt appears, send password and break this loop if re.search(r'assword', data): res = tnh.send(hosts[i]['password'] + '\r') break pattern = hosts[i]['expected_prompt_substr'] pattern = "(" + ")|(".join(pattern) + ")" got = '' while True: read, write, err = select([tnh], [], [], 10) if read: data = tnh.recv(1024) data = data.decode("utf-8") got = got + data if re.search(re.compile(pattern), data): break else: text_port = kvargs.get('text_port', None) if text_port is not None: text_port = int(text_port) t.log(level='info', message="using text port: " + str(text_port)) t.log(level="INFO", message='Trying to connect to device ' + str(host) + ' via SSH ...') handle = SshConn(host=host, user=kvargs['user'], port=text_port, \ password=kvargs['password'], ssh_key_file=kvargs.get('ssh_key_file', None)) else: t.log(level="INFO", message='Trying to connect to device ' + host + ' via Telnet ...') handle = TelnetConn(host=host, user=kvargs['user'], password=kvargs['password'], connect_timeout=connect_timeout) except: raise TobyException("Cannot connect to %s Device %s" % (osname, host)) return handle
def _get_version(self): """ Get Chassis OS Version of Avalanche TC : :return: avalanche TC version """ version = None try: if self.model == 'C100': raise TobyException("Default to ssh for C100", host_obj=self) self.telnet_handle = telnetlib.Telnet(self.chassis) # self.telnet_handle.set_debuglevel(10) # self.telnet_handle.write(b"\n") time.sleep(self.wait) time.sleep(self.wait) self.telnet_handle.read_until(b'login: '******'ascii') self.telnet_handle.write(uname) time.sleep(self.wait) self.telnet_handle.read_until(b"Password: "******"\n" pwd = pwd.encode('ascii') self.telnet_handle.write(pwd) time.sleep(self.wait) time.sleep(self.wait) self.telnet_handle.read_until(b"admin>") cmd = "version\n" cmd = cmd.encode('ascii') self.telnet_handle.write(cmd) time.sleep(self.wait) match_results = self.telnet_handle.expect([br"\d+.\d+"]) full_version = match_results[1].group(0).decode('ascii') version = full_version ver_re = re.compile(r'\d.\d\d+') if ver_re.search(full_version): version = ver_re.search(full_version).group() except Exception as ex: # pylint: disable=bare-except #if telnet isn't listening, try ssh self.log( level="WARN", message= "Unable to detect Avalanche Chassis version use telnet due to: %s" % ex.__str__()) try: ssh_handle = SshConn(host=self.chassis, user=self.username, password=self.password) paramiko_handle = ssh_handle.client if self.model == 'C100' or re.search('3100', self.model, re.I): paramiko_handle.send('/swat/bin/wawr -#\n') else: paramiko_handle.send('version\n') time.sleep(self.wait) response = paramiko_handle.recv(1024) ver_re = re.compile(r'\d.\d\d+') if ver_re.search(str(response)): version = ver_re.search(str(response)).group() else: version = '4.58' except Exception as ex: self.log( level="ERROR", message= "Unable to detect Avalanche Chassis version using ssh connection due to: %s" % ex.__str__()) if not version: raise TobyException("Unable to detect Avalanche Chassis version", host_obj=self) return version
def _get_version(self): """ Get Chassis OS Version of Spirent TC : :return: spirent TC version """ version = None try: self.telnet_handle = telnetlib.Telnet(self.chassis) # self.telnet_handle.set_debuglevel(10) # self.telnet_handle.write(b"\n") time.sleep(self.wait) self.telnet_handle.read_until(b'login: '******'ascii') self.telnet_handle.write(uname) time.sleep(self.wait) self.telnet_handle.read_until(b"Password: "******"\n" pwd = pwd.encode('ascii') self.telnet_handle.write(pwd) time.sleep(self.wait) time.sleep(self.wait) self.telnet_handle.read_until(b"admin>", timeout=self.read_timeout) cmd = "version\n" cmd = cmd.encode('ascii') self.telnet_handle.write(cmd) time.sleep(self.wait) match_results = self.telnet_handle.expect( [br"\d+.\d+"], timeout=self.read_timeout) full_version = match_results[1].group(0).decode('ascii') version = full_version ver_re = re.compile(r'\d.\d\d+') if ver_re.search(full_version): version = ver_re.search(full_version).group() except Exception as ex: self.log( level="WARN", message= "Toby was not able to find version use telnet due to: %s" % ex.__str__()) #if telnet isn't listening, try ssh try: ssh_handle = SshConn(host=self.chassis, user=self.username, password=self.password) paramiko_handle = ssh_handle.client paramiko_handle.send('version\n') time.sleep(self.wait) response = paramiko_handle.recv(1024) ver_re = re.compile(r'\d.\d\d+') if ver_re.search(str(response)): version = ver_re.search(str(response)).group() except Exception as ex: self.log( level="ERROR", message= "Toby was not able to find version info using ssh connection due to: %s" % ex.__str__()) if not version: if not check_device_reachability(self, self.chassis): raise SpirentConnectError("Spirent chassis is not pingable") elif not check_port_status(self, self.chassis, 23, 5, "telnet"): raise SpirentConnectError("Spirent telnet port is down") elif not check_port_status(self, self.chassis, 22, 5, "SSH"): raise SpirentConnectError("Spirent ssh port is down") else: raise TobyException("Unable to detect Spirent Chassis version", host_obj=self) self.log('CHASSIS VERSION: ' + version) return version
def test_sshconn_exception(self, sleep_patch, patch1, patch2, patch3): self.assertRaises( Exception, lambda: SshConn(host='dummy', user='******', password='******'))