blob: ea5cf4fa9ccb0be45332e0fe66abb1bffea6a820 [file] [log] [blame]
Peter D Phan72ce6b82021-06-03 06:18:26 -05001#!/usr/bin/env python
2
3import paramiko
Peter D Phan8462faf2021-06-16 12:24:15 -05004from paramiko.ssh_exception import AuthenticationException
5from paramiko.ssh_exception import NoValidConnectionsError
6from paramiko.ssh_exception import SSHException
7from paramiko.ssh_exception import BadHostKeyException
Peter D Phan72ce6b82021-06-03 06:18:26 -05008from paramiko.buffered_pipe import PipeTimeout as PipeTimeout
Peter D Phan733df632021-06-17 13:13:36 -05009from scp import SCPClient, SCPException
Peter D Phanbabf2962021-07-07 11:24:40 -050010import time
Peter D Phan72ce6b82021-06-03 06:18:26 -050011import socket
Peter D Phane86d9a52021-07-15 10:42:25 -050012import logging
Peter D Phan72ce6b82021-06-03 06:18:26 -050013from 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
Peter D Phan8462faf2021-06-16 12:24:15 -050027 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
Peter D Phan72ce6b82021-06-03 06:18:26 -050030 """
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
Peter D Phan5963d632021-07-12 09:58:55 -050046 is_ssh_login = True
Peter D Phan72ce6b82021-06-03 06:18:26 -050047 try:
48 # SSHClient to make connections to the remote server
49 self.sshclient = paramiko.SSHClient()
Peter D Phan8462faf2021-06-16 12:24:15 -050050 # setting set_missing_host_key_policy() to allow any host
Peter D Phan72ce6b82021-06-03 06:18:26 -050051 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,
George Keishing1c3d86b2021-06-16 22:29:30 -050055 password=self.password,
56 look_for_keys=False)
Peter D Phan72ce6b82021-06-03 06:18:26 -050057
Peter D Phan8462faf2021-06-16 12:24:15 -050058 except (BadHostKeyException, AuthenticationException,
59 SSHException, NoValidConnectionsError, socket.error) as e:
Peter D Phan5963d632021-07-12 09:58:55 -050060 is_ssh_login = False
61
62 return is_ssh_login
Peter D Phan72ce6b82021-06-03 06:18:26 -050063
64 def ssh_remoteclient_disconnect(self):
65
66 r"""
67 Clean up.
68 """
69
70 if self.sshclient:
71 self.sshclient.close()
72
73 if self.scpclient:
74 self.scpclient.close()
75
Peter D Phan2b6cb3a2021-07-19 06:55:42 -050076 def execute_command(self, command,
77 default_timeout=60):
Peter D Phan72ce6b82021-06-03 06:18:26 -050078 """
79 Execute command on the remote host.
80
81 Description of argument(s):
82 command Command string sent to remote host
83
84 """
85
Peter D Phanbabf2962021-07-07 11:24:40 -050086 empty = ''
87 cmd_start = time.time()
Peter D Phan72ce6b82021-06-03 06:18:26 -050088 try:
Peter D Phanbabf2962021-07-07 11:24:40 -050089 stdin, stdout, stderr = \
90 self.sshclient.exec_command(command, timeout=default_timeout)
91 start = time.time()
92 while time.time() < start + default_timeout:
Peter D Phanba48e9b2021-08-12 11:35:50 -050093 # Need to do read/write operation to trigger
94 # paramiko exec_command timeout mechanism.
95 xresults = stdout.readlines()
96 results = ''.join(xresults)
Peter D Phanbabf2962021-07-07 11:24:40 -050097 if stdout.channel.exit_status_ready():
98 break
99 time.sleep(1)
Peter D Phan2b6cb3a2021-07-19 06:55:42 -0500100 cmd_exit_code = stdout.channel.recv_exit_status()
Peter D Phan8a7ec172021-08-03 13:20:26 -0500101
102 # Convert list of string to one string
103 err = ''
104 out = ''
105 for item in stderr.readlines():
106 err += item
Peter D Phanba48e9b2021-08-12 11:35:50 -0500107 for item in results:
Peter D Phan8a7ec172021-08-03 13:20:26 -0500108 out += item
109
110 return cmd_exit_code, err, out
Peter D Phanbabf2962021-07-07 11:24:40 -0500111
Peter D Phan72ce6b82021-06-03 06:18:26 -0500112 except (paramiko.AuthenticationException, paramiko.SSHException,
Peter D Phanbabf2962021-07-07 11:24:40 -0500113 paramiko.ChannelException, SocketTimeout) as e:
Peter D Phan8462faf2021-06-16 12:24:15 -0500114 # Log command with error. Return to caller for next command, if any.
George Keishing7bf55092021-07-22 12:33:34 -0500115 logging.error("\n\tERROR: Fail remote command %s %s" % (e.__class__, e))
116 logging.error("\tCommand '%s' Elapsed Time %s" %
Peter D Phane86d9a52021-07-15 10:42:25 -0500117 (command, time.strftime("%H:%M:%S", time.gmtime(time.time() - cmd_start))))
Peter D Phan2b6cb3a2021-07-19 06:55:42 -0500118 return 0, empty, empty
Peter D Phan72ce6b82021-06-03 06:18:26 -0500119
120 def scp_connection(self):
121
122 r"""
123 Create a scp connection for file transfer.
124 """
Peter D Phan733df632021-06-17 13:13:36 -0500125 try:
Peter D Phan56429a62021-06-23 08:38:29 -0500126 self.scpclient = SCPClient(self.sshclient.get_transport(), sanitize=lambda x: x)
Peter D Phane86d9a52021-07-15 10:42:25 -0500127 logging.info("\n\t[Check] %s SCP transport established.\t [OK]" % self.hostname)
Peter D Phan733df632021-06-17 13:13:36 -0500128 except (SCPException, SocketTimeout, PipeTimeout) as e:
129 self.scpclient = None
George Keishing7bf55092021-07-22 12:33:34 -0500130 logging.error("\n\tERROR: SCP get_transport has failed. %s %s" % (e.__class__, e))
131 logging.info("\tScript continues generating FFDC on %s." % self.hostname)
132 logging.info("\tCollected data will need to be manually offloaded.")
Peter D Phan72ce6b82021-06-03 06:18:26 -0500133
134 def scp_file_from_remote(self, remote_file, local_file):
135
136 r"""
137 scp file in remote system to local with date-prefixed filename.
138
139 Description of argument(s):
140 remote_file Full path filename on the remote host
141
142 local_file Full path filename on the local host
143 local filename = date-time_remote filename
144
145 """
146
147 try:
Peter D Phan56429a62021-06-23 08:38:29 -0500148 self.scpclient.get(remote_file, local_file, recursive=True)
Peter D Phan733df632021-06-17 13:13:36 -0500149 except (SCPException, SocketTimeout, PipeTimeout) as e:
Peter D Phan8462faf2021-06-16 12:24:15 -0500150 # Log command with error. Return to caller for next file, if any.
Peter D Phane86d9a52021-07-15 10:42:25 -0500151 logging.error(
George Keishing7bf55092021-07-22 12:33:34 -0500152 "\n\tERROR: Fail scp %s from remotehost %s %s\n\n" % (remote_file, e.__class__, e))
Peter D Phan72ce6b82021-06-03 06:18:26 -0500153 return False
154
155 # Return True for file accounting
156 return True