24 'Importing Paramiko library failed. '
25 'Make sure you have Paramiko installed.'
32 'Importing SCP library failed. '
33 'Make sure you have SCP installed.'
36 from .abstractclient
import (AbstractShell, AbstractSFTPClient,
37 AbstractSSHClient, AbstractCommand,
38 SSHClientException, SFTPFileInfo)
39 from .pythonforward
import LocalPortForwarding
40 from .utils
import is_bytes, is_list_like, is_unicode, is_truthy
41 from robot.api
import logger
46 self.banner_timeout = 45
47 self._orig_start_client(*args, **kwargs)
50 paramiko.transport.Transport._orig_start_client = \
51 paramiko.transport.Transport.start_client
52 paramiko.transport.Transport.start_client = _custom_start_client
56 escape =
lambda s: s.replace(
'%',
'%%')
58 msg = [escape(m)
for m
in msg]
61 return self._orig_log(level, msg, *args)
64 paramiko.sftp_client.SFTPClient._orig_log = paramiko.sftp_client.SFTPClient._log
65 paramiko.sftp_client.SFTPClient._log = _custom_log
72 client = paramiko.SSHClient()
73 client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
78 paramiko.util.log_to_file(path)
83 ssh_config_file = os.path.expanduser(
"~/.ssh/config")
84 if os.path.exists(ssh_config_file):
85 conf = paramiko.SSHConfig()
86 with open(ssh_config_file)
as f:
88 port = int(PythonSSHClient._get_ssh_config_port(conf, host, port_number))
89 user = PythonSSHClient._get_ssh_config_user(conf, host, username)
90 proxy_command = PythonSSHClient._get_ssh_config_proxy_cmd(conf, host, proxy_cmd)
91 host = PythonSSHClient._get_ssh_config_host(conf, host)
92 return host, user, port, proxy_command
93 return host, username, port_number, proxy_cmd
97 ssh_config_file = os.path.expanduser(
"~/.ssh/config")
98 if os.path.exists(ssh_config_file):
99 conf = paramiko.SSHConfig()
100 with open(ssh_config_file)
as f:
102 port = int(PythonSSHClient._get_ssh_config_port(conf, host, port_number))
103 id_file = PythonSSHClient._get_ssh_config_identity_file(conf, host, identity_file)
104 user = PythonSSHClient._get_ssh_config_user(conf, host, username)
105 proxy_command = PythonSSHClient._get_ssh_config_proxy_cmd(conf, host, proxy_cmd)
106 host = PythonSSHClient._get_ssh_config_host(conf, host)
107 return host, user, port, id_file, proxy_command
108 return host, username, port_number, identity_file, proxy_cmd
113 return conf.lookup(host)[
'user']
if not None else user
120 return conf.lookup(host)[
'proxycommand']
if not None else proxy_cmd
127 return conf.lookup(host)[
'identityfile'][0]
if not None else id_file
134 return conf.lookup(host)[
'port']
if not None else port_number
141 return conf.lookup(host)[
'hostname']
if not None else host
146 dest_addr = (self.
configconfig.host, self.
configconfig.port)
147 jump_addr = (jumphost_connection.config.host, jumphost_connection.config.port)
148 jumphost_transport = jumphost_connection.client.get_transport()
149 if not jumphost_transport:
150 raise RuntimeError(
"Could not get transport for {}:{}. Have you logged in?".format(*jump_addr))
151 return jumphost_transport.open_channel(
"direct-tcpip", dest_addr, jump_addr)
153 def _login(self, username, password, allow_agent=False, look_for_keys=False, proxy_cmd=None,
154 read_config=False, jumphost_connection=None, keep_alive_interval=None):
156 hostname = self.
configconfig.host
157 self.
configconfig.host, username, self.
configconfig.port, proxy_cmd = \
162 if proxy_cmd
and jumphost_connection:
163 raise ValueError(
"`proxy_cmd` and `jumphost_connection` are mutually exclusive SSH features.")
165 sock_tunnel = paramiko.ProxyCommand(proxy_cmd)
166 elif jumphost_connection:
169 if not password
and not allow_agent:
173 password, look_for_keys=look_for_keys,
174 allow_agent=allow_agent,
175 timeout=float(self.
configconfig.timeout), sock=sock_tunnel)
176 except paramiko.SSHException:
178 transport = self.
clientclient.get_transport()
179 transport.set_keepalive(keep_alive_interval)
180 transport.auth_none(username)
184 password, look_for_keys=look_for_keys,
185 allow_agent=allow_agent,
186 timeout=float(self.
configconfig.timeout), sock=sock_tunnel)
187 transport = self.
clientclient.get_transport()
188 transport.set_keepalive(keep_alive_interval)
189 except paramiko.AuthenticationException:
191 transport = self.
clientclient.get_transport()
192 transport.set_keepalive(keep_alive_interval)
194 transport.auth_none(username)
197 transport.auth_password(username, password)
199 raise SSHClientException
200 except paramiko.AuthenticationException:
201 raise SSHClientException
204 jumphost_connection=None, read_config=False, keep_alive_interval=None):
206 hostname = self.
configconfig.host
207 self.
configconfig.host, username, self.
configconfig.port, key_file, proxy_cmd = \
211 if key_file
is not None:
212 if not os.path.exists(key_file):
216 open(key_file).
close()
220 raise RuntimeError(
"Keyfile must be specified as keyword argument or in config file.")
221 if proxy_cmd
and jumphost_connection:
222 raise ValueError(
"`proxy_cmd` and `jumphost_connection` are mutually exclusive SSH features.")
224 sock_tunnel = paramiko.ProxyCommand(proxy_cmd)
225 elif jumphost_connection:
230 password, key_filename=key_file,
231 allow_agent=allow_agent,
232 look_for_keys=look_for_keys,
233 timeout=float(self.
configconfig.timeout),
235 transport = self.
clientclient.get_transport()
236 transport.set_keepalive(keep_alive_interval)
237 except paramiko.AuthenticationException:
239 transport = self.
clientclient.get_transport()
240 transport.set_keepalive(keep_alive_interval)
242 transport.auth_none(username)
245 transport.auth_publickey(username,
None)
246 except Exception
as err:
247 raise SSHClientException
254 client = paramiko.SSHClient()
255 client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
257 client.connect(str(host), int(port), username=
"bad-username")
258 except paramiko.AuthenticationException:
263 def _start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False):
265 transport = self.
clientclient.get_transport()
267 raise AssertionError(
"Connection not open")
268 new_shell = transport.open_session(timeout=float(self.
configconfig.timeout))
271 paramiko.agent.AgentRequestHandler(new_shell)
273 cmd.run_in(new_shell, sudo, sudo_password, invoke_subsystem)
293 transport = self.
clientclient.get_transport()
295 raise AssertionError(
"Connection not open")
297 self.
tunneltunnel.forward(int(local_port))
302 return super(PythonSSHClient, self).
close()
307 def __init__(self, client, term_type, term_width, term_height):
309 self.
_shell_shell = client.invoke_shell(term_type, term_width, term_height)
310 except AttributeError:
311 raise RuntimeError(
'Cannot open session, you need to establish a connection first.')
316 data += self.
_shell_shell.recv(4096)
321 return self.
_shell_shell.recv(1)
325 self.
_shell_shell.resize_pty(width=width, height=height)
328 return self.
_shell_shell.recv_ready()
331 self.
_shell_shell.sendall(text)
339 super(SFTPClient, self).
__init__(encoding)
342 path = path.encode(self.
_encoding_encoding)
343 for item
in self.
_client_client.listdir_attr(path):
344 filename = item.filename
345 if is_bytes(filename):
346 filename = filename.decode(self.
_encoding_encoding)
350 path = path.encode(self.
_encoding_encoding)
351 attributes = self.
_client_client.stat(path)
356 path = path.encode(self.
_encoding_encoding)
360 file_exists = self.
is_fileis_file(destination)
361 destination = destination.encode(self.
_encoding_encoding)
362 remote_file = self.
_client_client.file(destination,
'wb')
363 remote_file.set_pipelined(
True)
364 if not file_exists
and mode:
365 self.
_client_client.chmod(destination, mode)
369 remote_file.write(data)
374 def _get_file(self, remote_path, local_path, scp_preserve_times):
375 remote_path = remote_path.encode(self.
_encoding_encoding)
376 self.
_client_client.get(remote_path, local_path)
380 path = self.
_client_client.normalize(path)
382 path = path.decode(self.
_encoding_encoding)
386 return bool(ntpath.splitdrive(path)[0])
389 return self.
_client_client.readlink(path)
394 self.
_scp_client_scp_client = scp.SCPClient(ssh_client.get_transport())
396 def put_file(self, source, destination, scp_preserve_times, *args):
398 self.
_scp_client_scp_client.put(sources, destination, preserve_times=is_truthy(scp_preserve_times))
400 def get_file(self, source, destination, scp_preserve_times, *args):
401 self.
_scp_client_scp_client.get(source, destination, preserve_times=is_truthy(scp_preserve_times))
404 self.
_scp_client_scp_client.put(source, destination,
True, preserve_times=is_truthy(scp_preserve_times))
407 self.
_scp_client_scp_client.get(source, destination,
True, preserve_times=is_truthy(scp_preserve_times))
410 source = source.replace(
'/', os.sep)
411 if not os.path.exists(source):
412 sources = [f
for f
in glob.glob(source)]
414 sources = [f
for f
in [source]]
416 msg =
"There are no source files matching '%s'." % source
424 self.
_scp_client_scp_client = scp.SCPClient(ssh_client.get_transport())
425 super(SCPTransferClient, self).
__init__(ssh_client, encoding)
427 def _put_file(self, source, destination, mode, newline, path_separator, scp_preserve_times=False):
429 self.
_scp_client_scp_client.put(source, destination, preserve_times=is_truthy(scp_preserve_times))
431 def _get_file(self, remote_path, local_path, scp_preserve_times=False):
432 self.
_scp_client_scp_client.get(remote_path, local_path, preserve_times=is_truthy(scp_preserve_times))
437 def read_outputs(self, timeout=None, output_during_execution=False, output_if_timeout=False):
438 stderr, stdout = self.
_receive_stdout_and_stderr_receive_stdout_and_stderr(timeout, output_during_execution, output_if_timeout)
439 rc = self.
_shell_shell.recv_exit_status()
441 return stdout, stderr, rc
444 stdout_filebuffer = self.
_shell_shell.makefile(
'rb', -1)
445 stderr_filebuffer = self.
_shell_shell.makefile_stderr(
'rb', -1)
449 self.
_flush_stdout_and_stderr_flush_stdout_and_stderr(stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, timeout,
450 output_during_execution, output_if_timeout)
452 stdout = (b
''.join(stdouts) + stdout_filebuffer.read()).decode(self.
_encoding_encoding)
453 stderr = (b
''.join(stderrs) + stderr_filebuffer.read()).decode(self.
_encoding_encoding)
454 return stderr, stdout
457 output_during_execution=False, output_if_timeout=False):
459 end_time = time.time() + timeout
460 while time.time() < end_time:
461 if self.
_shell_shell.status_event.wait(0):
463 self.
_output_logging_output_logging(stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, output_during_execution)
464 if not self.
_shell_shell.status_event.isSet():
465 if is_truthy(output_if_timeout):
470 self.
_output_logging_output_logging(stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, output_during_execution)
472 def _output_logging(self, stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, output_during_execution=False):
473 if self.
_shell_shell.recv_ready():
474 stdout_output = stdout_filebuffer.read(len(self.
_shell_shell.in_buffer))
475 if is_truthy(output_during_execution):
476 logger.console(stdout_output)
477 stdouts.append(stdout_output)
478 if self.
_shell_shell.recv_stderr_ready():
479 stderr_output = stderr_filebuffer.read(len(self.
_shell_shell.in_stderr_buffer))
480 if is_truthy(output_during_execution):
481 logger.console(stderr_output)
482 stderrs.append(stderr_output)
485 return not (self.
_shell_shell.closed
or
486 self.
_shell_shell.eof_received
or
487 self.
_shell_shell.eof_sent
or
488 not self.
_shell_shell.active)
495 if sudo_password
is None:
496 self.
_shell_shell.exec_command(command)
498 self.
_shell_shell.exec_command(
'echo %s | sudo --stdin --prompt "" %s' % (sudo_password, command))
Base class for the remote command.
Base class for the SFTP implementation.
def _create_remote_file(self, destination, mode)
def is_file(self, path)
Checks if the path points to a regular file on the remote host.
Base class for the SSH client implementation.
Base class for the shell implementation.
Wrapper class for the language specific file information objects.
def close(self)
Closes the connection.
def _get_ssh_config_port(conf, host, port_number)
def _create_sftp_client(self)
def _read_public_key_ssh_config(host, username, port_number, proxy_cmd, identity_file)
def _login(self, username, password, allow_agent=False, look_for_keys=False, proxy_cmd=None, read_config=False, jumphost_connection=None, keep_alive_interval=None)
def _get_ssh_config_user(conf, host, user)
def _read_login_ssh_config(host, username, port_number, proxy_cmd)
def _start_command(self, command, sudo=False, sudo_password=None, invoke_subsystem=False, forward_agent=False)
def _get_ssh_config_host(conf, host)
def enable_logging(path)
Enables logging of SSH events to a file.
def _create_scp_all_client(self)
def _get_ssh_config_identity_file(conf, host, id_file)
def get_banner_without_login(host, port=22)
def _login_with_public_key(self, username, key_file, password, allow_agent, look_for_keys, proxy_cmd=None, jumphost_connection=None, read_config=False, keep_alive_interval=None)
def _create_local_port_forwarder(self, local_port, remote_host, remote_port, bind_address)
def _get_jumphost_tunnel(self, jumphost_connection)
def create_local_ssh_tunnel(self, local_port, remote_host, remote_port, bind_address)
def _get_ssh_config_proxy_cmd(conf, host, proxy_cmd)
def _create_scp_transfer_client(self)
def read_outputs(self, timeout=None, output_during_execution=False, output_if_timeout=False)
def _flush_stdout_and_stderr(self, stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, timeout=None, output_during_execution=False, output_if_timeout=False)
def _execute_with_sudo(self, sudo_password=None)
def _receive_stdout_and_stderr(self, timeout=None, output_during_execution=False, output_if_timeout=False)
def _output_logging(self, stderr_filebuffer, stderrs, stdout_filebuffer, stdouts, output_during_execution=False)
def __init__(self, ssh_client)
def _get_put_file_sources(self, source)
def get_directory(self, source, destination, scp_preserve_times, *args)
def get_file(self, source, destination, scp_preserve_times, *args)
def put_file(self, source, destination, scp_preserve_times, *args)
def put_directory(self, source, destination, scp_preserve_times, *args)
def _get_file(self, remote_path, local_path, scp_preserve_times=False)
def __init__(self, ssh_client, encoding)
def _put_file(self, source, destination, mode, newline, path_separator, scp_preserve_times=False)
def __init__(self, ssh_client, encoding)
def _create_remote_file(self, destination, mode)
def _create_missing_remote_path(self, path, mode)
def _close_remote_file(self, remote_file)
def _absolute_path(self, path)
def _write_to_remote_file(self, remote_file, data, position)
def _get_file(self, remote_path, local_path, scp_preserve_times)
def _readlink(self, path)
def _is_windows_path(self, path)
def write(self, text)
Writes the text in the current shell.
def resize(self, width, height)
def read(self)
Reads all the output from the shell.
def __init__(self, client, term_type, term_width, term_height)
def _output_available(self)
def read_byte(self)
Reads a single byte from the shell.
def _custom_start_client(self, *args, **kwargs)
def _custom_log(self, level, msg, *args)