1#!/usr/bin/env python 2 3import paramiko 4from paramiko.ssh_exception import AuthenticationException 5from paramiko.ssh_exception import NoValidConnectionsError 6from paramiko.ssh_exception import SSHException 7from paramiko.ssh_exception import BadHostKeyException 8from paramiko.buffered_pipe import PipeTimeout as PipeTimeout 9from scp import SCPClient, SCPException 10import time 11import socket 12import logging 13from socket import timeout as SocketTimeout 14 15 16class SSHRemoteclient: 17 r""" 18 Class to create ssh connection to remote host 19 for remote host command execution and scp. 20 """ 21 22 def __init__(self, hostname, username, password): 23 24 r""" 25 Description of argument(s): 26 27 hostname Name/IP of the remote (targeting) host 28 username User on the remote host with access to FFCD files 29 password Password for user on remote host 30 """ 31 32 self.ssh_output = None 33 self.ssh_error = None 34 self.sshclient = None 35 self.scpclient = None 36 self.hostname = hostname 37 self.username = username 38 self.password = password 39 40 def ssh_remoteclient_login(self): 41 42 r""" 43 Method to create a ssh connection to remote host. 44 """ 45 46 is_ssh_login = True 47 try: 48 # SSHClient to make connections to the remote server 49 self.sshclient = paramiko.SSHClient() 50 # setting set_missing_host_key_policy() to allow any host 51 self.sshclient.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 52 # Connect to the server 53 self.sshclient.connect(hostname=self.hostname, 54 username=self.username, 55 password=self.password, 56 banner_timeout=120, 57 timeout=60, 58 look_for_keys=False) 59 60 except (BadHostKeyException, AuthenticationException, 61 SSHException, NoValidConnectionsError, socket.error) as e: 62 is_ssh_login = False 63 64 return is_ssh_login 65 66 def ssh_remoteclient_disconnect(self): 67 68 r""" 69 Clean up. 70 """ 71 72 if self.sshclient: 73 self.sshclient.close() 74 75 if self.scpclient: 76 self.scpclient.close() 77 78 def execute_command(self, command, 79 default_timeout=60): 80 """ 81 Execute command on the remote host. 82 83 Description of argument(s): 84 command Command string sent to remote host 85 86 """ 87 88 empty = '' 89 cmd_start = time.time() 90 try: 91 stdin, stdout, stderr = \ 92 self.sshclient.exec_command(command, timeout=default_timeout) 93 start = time.time() 94 while time.time() < start + default_timeout: 95 # Need to do read/write operation to trigger 96 # paramiko exec_command timeout mechanism. 97 xresults = stderr.readlines() 98 results = ''.join(xresults) 99 time.sleep(1) 100 if stdout.channel.exit_status_ready(): 101 break 102 cmd_exit_code = stdout.channel.recv_exit_status() 103 104 # Convert list of string to one string 105 err = '' 106 out = '' 107 for item in results: 108 err += item 109 for item in stdout.readlines(): 110 out += item 111 112 return cmd_exit_code, err, out 113 114 except (paramiko.AuthenticationException, paramiko.SSHException, 115 paramiko.ChannelException, SocketTimeout) as e: 116 # Log command with error. Return to caller for next command, if any. 117 logging.error("\n\tERROR: Fail remote command %s %s" % (e.__class__, e)) 118 logging.error("\tCommand '%s' Elapsed Time %s" % 119 (command, time.strftime("%H:%M:%S", time.gmtime(time.time() - cmd_start)))) 120 return 0, empty, empty 121 122 def scp_connection(self): 123 124 r""" 125 Create a scp connection for file transfer. 126 """ 127 try: 128 self.scpclient = SCPClient(self.sshclient.get_transport(), sanitize=lambda x: x) 129 logging.info("\n\t[Check] %s SCP transport established.\t [OK]" % self.hostname) 130 except (SCPException, SocketTimeout, PipeTimeout) as e: 131 self.scpclient = None 132 logging.error("\n\tERROR: SCP get_transport has failed. %s %s" % (e.__class__, e)) 133 logging.info("\tScript continues generating FFDC on %s." % self.hostname) 134 logging.info("\tCollected data will need to be manually offloaded.") 135 136 def scp_file_from_remote(self, remote_file, local_file): 137 138 r""" 139 scp file in remote system to local with date-prefixed filename. 140 141 Description of argument(s): 142 remote_file Full path filename on the remote host 143 144 local_file Full path filename on the local host 145 local filename = date-time_remote filename 146 147 """ 148 149 try: 150 self.scpclient.get(remote_file, local_file, recursive=True) 151 except (SCPException, SocketTimeout, PipeTimeout) as e: 152 # Log command with error. Return to caller for next file, if any. 153 logging.error( 154 "\n\tERROR: Fail scp %s from remotehost %s %s\n\n" % (remote_file, e.__class__, e)) 155 return False 156 157 # Return True for file accounting 158 return True 159