blob: 03f79838f7be96d2379d9cbabbdbccf9b14ee1ab [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
George Keishinge635ddc2022-12-08 07:38:02 -06004import logging
Patrick Williams20f38712022-12-08 06:18:26 -06005import socket
George Keishinge635ddc2022-12-08 07:38:02 -06006import telnetlib
Patrick Williams20f38712022-12-08 06:18:26 -06007import time
Peter D Phane732f772021-07-01 10:16:35 -05008from collections import deque
9
10
11class TelnetRemoteclient:
Peter D Phane732f772021-07-01 10:16:35 -050012 r"""
13 Class to create telnet connection to remote host for command execution.
14 """
15
Patrick Williams20f38712022-12-08 06:18:26 -060016 def __init__(
17 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):
Peter D Phane732f772021-07-01 10:16:35 -050036 is_telnet = True
37 try:
Patrick Williams20f38712022-12-08 06:18:26 -060038 self.tnclient = telnetlib.Telnet(
39 self.hostname, self.port, timeout=15
40 )
41 if b"login:" in self.tnclient.read_until(
42 b"login:", timeout=self.read_timeout
43 ):
44 self.tnclient.write(self.username.encode("utf-8") + b"\n")
Peter D Phane732f772021-07-01 10:16:35 -050045
Patrick Williams20f38712022-12-08 06:18:26 -060046 if b"Password:" in self.tnclient.read_until(
47 b"Password:", timeout=self.read_timeout
48 ):
49 self.tnclient.write(self.password.encode("utf-8") + b"\n")
Peter D Phane732f772021-07-01 10:16:35 -050050
Patrick Williams20f38712022-12-08 06:18:26 -060051 n, match, pre_match = self.tnclient.expect(
52 [
53 b"Login incorrect",
54 b"invalid login name or password.",
55 rb"\#",
56 rb"\$",
57 ],
58 timeout=self.read_timeout,
59 )
Peter D Phane732f772021-07-01 10:16:35 -050060 if n == 0 or n == 1:
Peter D Phane86d9a52021-07-15 10:42:25 -050061 logging.error(
Patrick Williams20f38712022-12-08 06:18:26 -060062 "\n\tERROR: Telnet Authentication Failed. Check"
63 " userid and password.\n\n"
64 )
Peter D Phane732f772021-07-01 10:16:35 -050065 is_telnet = False
66 else:
67 # login successful
68 self.fifo = deque()
69 else:
70 # Anything else, telnet server is not running
George Keishing7bf55092021-07-22 12:33:34 -050071 logging.error("\n\tERROR: Telnet Connection Refused.\n\n")
Peter D Phane732f772021-07-01 10:16:35 -050072 is_telnet = False
73 else:
74 is_telnet = False
75 except Exception:
76 # Any kind of exception, skip telnet protocol
77 is_telnet = False
78
79 return is_telnet
80
81 def __del__(self):
82 self.tn_remoteclient_disconnect()
83
84 def tn_remoteclient_disconnect(self):
85 try:
86 self.tnclient.close()
87 except Exception:
88 # the telnet object might not exist yet, so ignore this one
89 pass
90
Patrick Williams20f38712022-12-08 06:18:26 -060091 def execute_command(self, cmd, i_timeout=120):
92 r"""
93 Executes commands on the remote host
Peter D Phane732f772021-07-01 10:16:35 -050094
Patrick Williams20f38712022-12-08 06:18:26 -060095 Description of argument(s):
96 cmd Command to run on remote host
97 i_timeout Timeout for command output
98 default is 120 seconds
99 """
Peter D Phane732f772021-07-01 10:16:35 -0500100
Peter D Phan1627d962021-08-09 11:06:04 -0500101 # Wait time for command execution before reading the output.
102 # Use user input wait time for command execution if one exists.
103 # Else use the default 120 sec,
104 if i_timeout != 120:
105 execution_time = i_timeout
106 else:
107 execution_time = 120
108
109 # Execute the command and read the command output.
Patrick Williams20f38712022-12-08 06:18:26 -0600110 return_buffer = b""
Peter D Phane732f772021-07-01 10:16:35 -0500111 try:
Peter D Phan1627d962021-08-09 11:06:04 -0500112 # Do at least one non-blocking read.
Peter D Phane86d9a52021-07-15 10:42:25 -0500113 # to flush whatever data is in the read buffer.
114 while self.tnclient.read_very_eager():
115 continue
Peter D Phane732f772021-07-01 10:16:35 -0500116
117 # Execute the command
Patrick Williams20f38712022-12-08 06:18:26 -0600118 self.tnclient.write(cmd.encode("utf-8") + b"\n")
Peter D Phan1627d962021-08-09 11:06:04 -0500119 time.sleep(execution_time)
Peter D Phane732f772021-07-01 10:16:35 -0500120
Patrick Williams20f38712022-12-08 06:18:26 -0600121 local_buffer = b""
Peter D Phane86d9a52021-07-15 10:42:25 -0500122 # Read the command output one block at a time.
Peter D Phan5963d632021-07-12 09:58:55 -0500123 return_buffer = self.tnclient.read_very_eager()
Peter D Phane86d9a52021-07-15 10:42:25 -0500124 while return_buffer:
Patrick Williams20f38712022-12-08 06:18:26 -0600125 local_buffer = b"".join([local_buffer, return_buffer])
Peter D Phane86d9a52021-07-15 10:42:25 -0500126 time.sleep(3) # let the buffer fill up a bit
127 return_buffer = self.tnclient.read_very_eager()
Peter D Phane732f772021-07-01 10:16:35 -0500128 except (socket.error, EOFError) as e:
129 self.tn_remoteclient_disconnect()
130
131 if str(e).__contains__("Connection reset by peer"):
132 msg = e
133 elif str(e).__contains__("telnet connection closed"):
134 msg = "Telnet connection closed."
135 else:
Peter D Phan5963d632021-07-12 09:58:55 -0500136 msg = "Some other issue.%s %s %s\n\n" % (cmd, e.__class__, e)
Peter D Phane732f772021-07-01 10:16:35 -0500137
Peter D Phane86d9a52021-07-15 10:42:25 -0500138 logging.error("\t\t ERROR %s " % msg)
Peter D Phane732f772021-07-01 10:16:35 -0500139
Peter D Phanb76e1752021-08-03 12:50:05 -0500140 # Return ASCII string data with ending PROMPT stripped
Patrick Williams20f38712022-12-08 06:18:26 -0600141 return local_buffer.decode("ascii", "ignore").replace("$ ", "\n")