blob: 08e4071d778a5670b380af4428eaab6517b449aa [file] [log] [blame]
George Keishinge7e91712021-09-03 11:28:44 -05001#!/usr/bin/env python3
Peter D Phane732f772021-07-01 10:16:35 -05002
Peter D Phan5963d632021-07-12 09:58:55 -05003
Patrick Williams57318182022-12-08 06:18:26 -06004import time
George Keishinge635ddc2022-12-08 07:38:02 -06005import socket
6import logging
7import telnetlib
Peter D Phane732f772021-07-01 10:16:35 -05008from collections import deque
9
10
11class TelnetRemoteclient:
George Keishinge635ddc2022-12-08 07:38:02 -060012
Peter D Phane732f772021-07-01 10:16:35 -050013 r"""
14 Class to create telnet connection to remote host for command execution.
15 """
16
George Keishinge635ddc2022-12-08 07:38:02 -060017 def __init__(self, hostname, username, password, port=23, read_timeout=None):
18
Peter D Phane732f772021-07-01 10:16:35 -050019 r"""
20 Description of argument(s):
21
22 hostname Name/IP of the remote (targeting) host
23 username User on the remote host with access to FFCD files
24 password Password for user on remote host
25 read_timeout New read timeout value to override default one
26 """
27
28 self.hostname = hostname
29 self.username = username
30 self.password = password
31 self.tnclient = None
32 self.port = port
33 self.read_timeout = read_timeout
34
35 def tn_remoteclient_login(self):
George Keishinge635ddc2022-12-08 07:38:02 -060036
Peter D Phane732f772021-07-01 10:16:35 -050037 is_telnet = True
38 try:
George Keishinge635ddc2022-12-08 07:38:02 -060039 self.tnclient = telnetlib.Telnet(self.hostname, self.port, timeout=15)
40 if b'login:' in self.tnclient.read_until(b'login:', timeout=self.read_timeout):
41 self.tnclient.write(self.username.encode('utf-8') + b"\n")
Peter D Phane732f772021-07-01 10:16:35 -050042
George Keishinge635ddc2022-12-08 07:38:02 -060043 if b'Password:' in self.tnclient.read_until(b'Password:', timeout=self.read_timeout):
44 self.tnclient.write(self.password.encode('utf-8') + b"\n")
Peter D Phane732f772021-07-01 10:16:35 -050045
George Keishinge635ddc2022-12-08 07:38:02 -060046 n, match, pre_match = \
47 self.tnclient.expect(
48 [b'Login incorrect', b'invalid login name or password.', br'\#', br'\$'],
49 timeout=self.read_timeout)
Peter D Phane732f772021-07-01 10:16:35 -050050 if n == 0 or n == 1:
Peter D Phane86d9a52021-07-15 10:42:25 -050051 logging.error(
George Keishinge635ddc2022-12-08 07:38:02 -060052 "\n\tERROR: Telnet Authentication Failed. Check userid and password.\n\n")
Peter D Phane732f772021-07-01 10:16:35 -050053 is_telnet = False
54 else:
55 # login successful
56 self.fifo = deque()
57 else:
58 # Anything else, telnet server is not running
George Keishing7bf55092021-07-22 12:33:34 -050059 logging.error("\n\tERROR: Telnet Connection Refused.\n\n")
Peter D Phane732f772021-07-01 10:16:35 -050060 is_telnet = False
61 else:
62 is_telnet = False
63 except Exception:
64 # Any kind of exception, skip telnet protocol
65 is_telnet = False
66
67 return is_telnet
68
69 def __del__(self):
70 self.tn_remoteclient_disconnect()
71
72 def tn_remoteclient_disconnect(self):
73 try:
74 self.tnclient.close()
75 except Exception:
76 # the telnet object might not exist yet, so ignore this one
77 pass
78
George Keishinge635ddc2022-12-08 07:38:02 -060079 def execute_command(self, cmd,
80 i_timeout=120):
Peter D Phane732f772021-07-01 10:16:35 -050081
George Keishinge635ddc2022-12-08 07:38:02 -060082 r'''
83 Executes commands on the remote host
84
85 Description of argument(s):
86 cmd Command to run on remote host
87 i_timeout Timeout for command output
88 default is 120 seconds
89 '''
Peter D Phane732f772021-07-01 10:16:35 -050090
Peter D Phan1627d962021-08-09 11:06:04 -050091 # Wait time for command execution before reading the output.
92 # Use user input wait time for command execution if one exists.
93 # Else use the default 120 sec,
94 if i_timeout != 120:
95 execution_time = i_timeout
96 else:
97 execution_time = 120
98
99 # Execute the command and read the command output.
George Keishinge635ddc2022-12-08 07:38:02 -0600100 return_buffer = b''
Peter D Phane732f772021-07-01 10:16:35 -0500101 try:
George Keishinge635ddc2022-12-08 07:38:02 -0600102
Peter D Phan1627d962021-08-09 11:06:04 -0500103 # Do at least one non-blocking read.
Peter D Phane86d9a52021-07-15 10:42:25 -0500104 # to flush whatever data is in the read buffer.
105 while self.tnclient.read_very_eager():
106 continue
Peter D Phane732f772021-07-01 10:16:35 -0500107
108 # Execute the command
George Keishinge635ddc2022-12-08 07:38:02 -0600109 self.tnclient.write(cmd.encode('utf-8') + b'\n')
Peter D Phan1627d962021-08-09 11:06:04 -0500110 time.sleep(execution_time)
Peter D Phane732f772021-07-01 10:16:35 -0500111
George Keishinge635ddc2022-12-08 07:38:02 -0600112 local_buffer = b''
Peter D Phane86d9a52021-07-15 10:42:25 -0500113 # Read the command output one block at a time.
Peter D Phan5963d632021-07-12 09:58:55 -0500114 return_buffer = self.tnclient.read_very_eager()
Peter D Phane86d9a52021-07-15 10:42:25 -0500115 while return_buffer:
George Keishinge635ddc2022-12-08 07:38:02 -0600116 local_buffer = b''.join([local_buffer, return_buffer])
Peter D Phane86d9a52021-07-15 10:42:25 -0500117 time.sleep(3) # let the buffer fill up a bit
118 return_buffer = self.tnclient.read_very_eager()
Peter D Phane732f772021-07-01 10:16:35 -0500119 except (socket.error, EOFError) as e:
120 self.tn_remoteclient_disconnect()
121
122 if str(e).__contains__("Connection reset by peer"):
123 msg = e
124 elif str(e).__contains__("telnet connection closed"):
125 msg = "Telnet connection closed."
126 else:
Peter D Phan5963d632021-07-12 09:58:55 -0500127 msg = "Some other issue.%s %s %s\n\n" % (cmd, e.__class__, e)
Peter D Phane732f772021-07-01 10:16:35 -0500128
Peter D Phane86d9a52021-07-15 10:42:25 -0500129 logging.error("\t\t ERROR %s " % msg)
Peter D Phane732f772021-07-01 10:16:35 -0500130
Peter D Phanb76e1752021-08-03 12:50:05 -0500131 # Return ASCII string data with ending PROMPT stripped
George Keishinge635ddc2022-12-08 07:38:02 -0600132 return local_buffer.decode('ascii', 'ignore').replace('$ ', '\n')