blob: f363e820b8a8c2611cba7fa2ca9719188380ac8b [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:
93 if stdout.channel.exit_status_ready():
94 break
95 time.sleep(1)
Peter D Phan2b6cb3a2021-07-19 06:55:42 -050096 cmd_exit_code = stdout.channel.recv_exit_status()
97 return cmd_exit_code, stderr.readlines(), stdout.readlines()
Peter D Phanbabf2962021-07-07 11:24:40 -050098
Peter D Phan72ce6b82021-06-03 06:18:26 -050099 except (paramiko.AuthenticationException, paramiko.SSHException,
Peter D Phanbabf2962021-07-07 11:24:40 -0500100 paramiko.ChannelException, SocketTimeout) as e:
Peter D Phan8462faf2021-06-16 12:24:15 -0500101 # Log command with error. Return to caller for next command, if any.
Peter D Phane86d9a52021-07-15 10:42:25 -0500102 logging.error("\n>>>>>\tERROR: Fail remote command %s %s" % (e.__class__, e))
103 logging.error(">>>>>\tCommand '%s' Elapsed Time %s" %
104 (command, time.strftime("%H:%M:%S", time.gmtime(time.time() - cmd_start))))
Peter D Phan2b6cb3a2021-07-19 06:55:42 -0500105 return 0, empty, empty
Peter D Phan72ce6b82021-06-03 06:18:26 -0500106
107 def scp_connection(self):
108
109 r"""
110 Create a scp connection for file transfer.
111 """
Peter D Phan733df632021-06-17 13:13:36 -0500112 try:
Peter D Phan56429a62021-06-23 08:38:29 -0500113 self.scpclient = SCPClient(self.sshclient.get_transport(), sanitize=lambda x: x)
Peter D Phane86d9a52021-07-15 10:42:25 -0500114 logging.info("\n\t[Check] %s SCP transport established.\t [OK]" % self.hostname)
Peter D Phan733df632021-06-17 13:13:36 -0500115 except (SCPException, SocketTimeout, PipeTimeout) as e:
116 self.scpclient = None
Peter D Phane86d9a52021-07-15 10:42:25 -0500117 logging.error("\n>>>>>\tERROR: SCP get_transport has failed. %s %s" % (e.__class__, e))
118 logging.info(">>>>>\tScript continues generating FFDC on %s." % self.hostname)
119 logging.info(">>>>>\tCollected data will need to be manually offloaded.")
Peter D Phan72ce6b82021-06-03 06:18:26 -0500120
121 def scp_file_from_remote(self, remote_file, local_file):
122
123 r"""
124 scp file in remote system to local with date-prefixed filename.
125
126 Description of argument(s):
127 remote_file Full path filename on the remote host
128
129 local_file Full path filename on the local host
130 local filename = date-time_remote filename
131
132 """
133
134 try:
Peter D Phan56429a62021-06-23 08:38:29 -0500135 self.scpclient.get(remote_file, local_file, recursive=True)
Peter D Phan733df632021-06-17 13:13:36 -0500136 except (SCPException, SocketTimeout, PipeTimeout) as e:
Peter D Phan8462faf2021-06-16 12:24:15 -0500137 # Log command with error. Return to caller for next file, if any.
Peter D Phane86d9a52021-07-15 10:42:25 -0500138 logging.error(
139 "\n>>>>>\tERROR: Fail scp %s from remotehost %s %s\n\n" % (remote_file, e.__class__, e))
Peter D Phan72ce6b82021-06-03 06:18:26 -0500140 return False
141
142 # Return True for file accounting
143 return True