def connect(self): self.client = paramiko.SSHClient() self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: self.client.connect(self.host, self.port, username=self.username, password=self.password, look_for_keys=False) transport = self.client.get_transport() transport.default_window_size = paramiko.common.MAX_WINDOW_SIZE # transport.packetizer.REKEY_BYTES = pow(2, 40) # 1TB max, this is a security degradation! # transport.packetizer.REKEY_PACKETS = pow(2, 40) # 1TB max, this is a security degradation! except paramiko.AuthenticationException as ex: raise AuthenticationFailure() except paramiko.SSHException as ex: raise paramiko.SSHException(ex) except NoValidConnectionsError as ex: raise ConnectionFailure(ex) except socket.gaierror as ex: raise ConnectionFailure(ex) try: self.sftp = self.client.open_sftp() self.channel = self.sftp.get_channel() self.channel.settimeout(10.0) except paramiko.SSHException as ex: raise paramiko.SSHException(ex)
def run_command(self, cmd): """Execute command on remote host. :param cmd: command to execute on remote :raise: ValueError: no VM with specified IP address found :raise subprocess.CalledProcessError: command failed on remote host :raise paramiko.SSHException: connection failed :return: command output """ if self.ip_addresses[0] is None: self.ip_addresses = (self.get_ip_address(), self.ip_addresses[1]) print self.ip_addresses[0], self.ip_addresses[1] ip_addr = self.ip_addresses[0] if ip_addr is None: raise paramiko.SSHException("Failed to IP address for SSH") self.logger.info( "remote IP '%s' - command for execution: '%s'", ip_addr, cmd) try: client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(ip_addr, username=SSH_INFO[0], password=SSH_INFO[1], timeout=SSH_INFO[2]) stdin, stdout, stderr = client.exec_command(cmd) except paramiko.SSHException: # self.logger.error("Failed to execute remote cmd: %s", # exception.message) raise except paramiko.ssh_exception.NoValidConnectionsError as exception: raise paramiko.SSHException("Failed to execute remote cmd: %s", exception.strerror) output_stdout_rc = stdout.channel.recv_exit_status() output_stdout = stdout.readlines() output_stderr = stderr.readlines() self.logger.debug("Stdout rc[%d]:\n%s", output_stdout_rc, ''.join(output_stdout)) self.logger.debug("Stderr:\n%s", ''.join(output_stderr)) client.close() if 0 != output_stdout_rc: raise subprocess.CalledProcessError( output_stdout_rc, cmd, "Command on remote host failed: %s" % output_stderr) self.state = VMState.Ready return output_stdout
def save_to_eeprom(iio_uri, coarse, fine): full_uri = iio_uri.split(":", 2) if full_uri[0] != "ip": pytest.skip("Tuning currently supported only for ip URIs") ip = full_uri[1] ssh_client = paramiko.SSHClient() ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh_client.connect(ip, username="******", password="******") ssh_stdin, ssh_stdout, ssh_stderr = ssh_client.exec_command( "find /sys/ -name eeprom" ) eeprom_path = ssh_stdout.readline().rstrip("\n") if ssh_stderr.channel.recv_exit_status() != 0: raise paramiko.SSHException("find_eeprom command did not execute properly") this_day = date.today() if this_day.year <= 1995: pytest.skip( "System date and time not in order. Please connect the device to internet to update." ) sn = popup_txt() hc = hex(coarse).lstrip("0x").rstrip("L") if coarse <= 16: hc = "0" + hc hf = hex(fine).lstrip("0x").rstrip("L") h = hc + hf cmd = ( "fru-dump -i " + eeprom_path + " -o " + eeprom_path + " -s " + sn + " -d " + datetime.now().strftime("%Y-%m-%dT%H:%M:%S-05:00") + " -t " + str(h) + " 2>&1" ) sshin, sshout, ssherr = ssh_client.exec_command(cmd) if ssherr.channel.recv_exit_status() != 0: raise paramiko.SSHException("fru-dump command did not execute properly") ssh_client.close()
def create(self): try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) if self.privatekey: pkfile = os.path.expanduser(self.privatekey) self.privatekey = paramiko.RSAKey.from_private_key_file(pkfile) elif not self.password: msg = _("Specify a password or private_key") raise exception.ManilaException(msg) ssh.connect(self.ip, port=self.port, username=self.login, password=self.password, pkey=self.privatekey, timeout=self.conn_timeout) # Paramiko by default sets the socket timeout to 0.1 seconds, # ignoring what we set thru the sshclient. This doesn't help for # keeping long lived connections. Hence we have to bypass it, by # overriding it after the transport is initialized. We are setting # the sockettimeout to None and setting a keepalive packet so that, # the server will keep the connection open. All that does is send # a keepalive packet every ssh_conn_timeout seconds. if self.conn_timeout: transport = ssh.get_transport() transport.sock.settimeout(None) transport.set_keepalive(self.conn_timeout) return ssh except Exception as e: msg = _("Error connecting via ssh: %s") % e LOG.error(msg) raise paramiko.SSHException(msg)
def exec_ssh_cmd(p_cfg, p_cmd): stdout_lines = [] stderr_lines = [] cmd_exec_status = True try: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(hostname=p_cfg['msg']['server_ip'], port=int(p_cfg['msg']['server_port']), username=p_cfg['msg']['server_user'], password=p_cfg['msg']['server_pass']) stdin, stdout, stderr = ssh.exec_command(p_cmd, timeout=6) stdout_lines = stdout.readlines() stderr_lines = stderr.readlines() if stdout.channel.recv_exit_status() != 0: raise paramiko.SSHException() ssh.close() except paramiko.SSHException as e: print("Failed to execute the command on '{}': {}".format( p_cfg['msg']['server_ip'], str(e))) if len(stderr_lines) > 0: print("Error reported by {}: {}".format(p_cfg['msg']['server_ip'], "\n".join(stderr_lines))) cmd_exec_status = False return {'status': cmd_exec_status, 'stdout': stdout_lines}
def paste_remote_file(machine_ip, user_name, remotepath, localpath, password=None, ret_list=False): """ Executes command on remote machine using paramiko SSHClient """ #logger.debug("executing remote command %s on %s with %s:" %(command, machine_ip, user_name)) if machine_ip == 'localhost': logger.debug("TODO") else: #logger.debug("executing remote command %s on %s with %s:" %(command, machine_ip, user_name)) try: sftp = None ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.connect(machine_ip, username=user_name, password=password) #logger.debug("Connected to host %s " % machine_ip) sftp = ssh.open_sftp() if not os.path.exists(localpath): raise paramiko.SSHException('filepath: ' + localpath + 'not found') sftp.put(localpath, remotepath) except paramiko.SSHException as e: #log_exception() print(e) finally: if sftp: sftp.close() if ssh: ssh.close()
def rmdir(self, path: str): """ Removes the directory at the given path """ if self.session is None: raise paramiko.SSHException("Transport is not connected") self.session.rmdir(path)
def run_add_to_python_dot_org(db: DbfilenameShelf) -> None: client = paramiko.SSHClient() client.load_system_host_keys() client.set_missing_host_key_policy(paramiko.WarningPolicy) client.connect(DOWNLOADS_SERVER, port=22, username=db["ssh_user"]) # Ensure the file is there source = pathlib.Path(__file__).parent / "add-to-pydotorg.py" destination = pathlib.Path( f"/home/psf-users/{db['ssh_user']}/add-to-pydotorg.py") ftp_client = MySFTPClient.from_transport(client.get_transport()) ftp_client.put(str(source), str(destination)) ftp_client.close() auth_info = db["auth_info"] assert auth_info is not None stdin, stdout, stderr = client.exec_command( f"AUTH_INFO={auth_info} python add-to-pydotorg.py {db['release']}") stderr_text = stderr.read().decode() if stderr_text: raise paramiko.SSHException( f"Failed to execute the command: {stderr_text}") stdout_text = stdout.read().decode() print("-- Command output --") print(stdout_text) print("-- End of command output --")
def stat(self, path: str) -> typing.Any: """ Returns stat information """ if self.session is None: raise paramiko.SSHException("Transport is not connected") return self.session.stat(path)
def _run_ssh(self, cmd_list, check_exit=True, attempts=1): utils.check_ssh_injection(cmd_list) command = ' '.join(cmd_list) if not self.sshpool: self.sshpool = utils.SSHPool( self.config.san_ip, self.config.san_ssh_port, self.config.ssh_conn_timeout, self.config.san_login, password=self.config.san_password, privatekey=self.config.san_private_key, min_size=self.config.ssh_min_pool_conn, max_size=self.config.ssh_max_pool_conn) try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return self._ssh_execute(ssh, command, check_exit_code=check_exit) except Exception as e: LOG.error(e) greenthread.sleep(randint(20, 500) / 100.0) msg = (_("SSH Command failed after '%(total_attempts)r' " "attempts : '%(command)s'") % { 'total_attempts': total_attempts, 'command': command }) raise paramiko.SSHException(msg) except Exception: with excutils.save_and_reraise_exception(): LOG.error(_("Error running ssh command: %s") % command)
def chmod(self, path: str, mode: int): """ Change file permissions """ if self.session is None: raise paramiko.SSHException("Transport is not connected") self.session.chmod(path, mode)
def exec_command(self, command, verbose=True): try: stdout_data = [] stderr_data = [] session = self.ssh.get_transport().open_session() session.exec_command(command) nbytes = 4096 # TODO add a timeout here, don't wait for commands forever. while True: if session.recv_ready(): msg = session.recv(nbytes) stdout_data.append(msg) if session.recv_stderr_ready(): msg = session.recv_stderr(nbytes) stderr_data.append(msg) if session.exit_status_ready(): break time.sleep(0.1) # Sleep briefly to prevent over-polling status = session.recv_exit_status() str_return = ''.join(stdout_data).splitlines() stderr_str = ''.join(stderr_data) session.close() if status != 0: raise paramiko.SSHException( "Exit Code: {0}\tSTDOUT: {1}\tSTDERR: {2}\n\n".format( status, "\n".join(str_return), stderr_str)) if verbose: print "EXECUTING...\t{0}".format(command) return str_return except paramiko.SSHException as e: if verbose: print "FAILED......\t{0}\t{1}".format(command, e) raise SSHException("{0}\t{1}".format(command, e))
def mklink(self, src: str, dest: str): """ Creates a symlink from dest->src """ if self.session is None: raise paramiko.SSHException("Transport is not connected") self.session.symlink(src, dest)
def execute_ssh_command(self, cmd): cmd_exec_status = True stdout_lines = [] stderr_lines = [] try: print("Executing command on '%s': %s" % (self._host, cmd)) stdin, stdout, stderr = self._ssh_client.exec_command( cmd, get_pty=True, timeout=SSHHelper.SSH_CMD_TIMEOUT) stdout_lines = stdout.readlines() stderr_lines = stderr.readlines() if stdout.channel.recv_exit_status() != 0: raise paramiko.SSHException() except paramiko.SSHException as e: print("Failed to execute the command on '%s': %s" % (self._host, str(e))) if len(stderr_lines) > 0: print("Error reported by %s: %s" % (self._host, "\n".join(stderr_lines))) cmd_exec_status = False return cmd_exec_status, stdout_lines
def _invoke( self, command: str, pty: typing.Optional[bool] = False ) -> typing.Tuple[paramiko.ChannelFile, paramiko.ChannelFile, paramiko.ChannelFile]: """ Raw handle to exec_command """ if self.client._transport is None: raise paramiko.SSHException("Client is not connected") try: return self.client.exec_command(command, get_pty=pty) except paramiko.ssh_exception.SSHException as e: if e.args == ( 'Key-exchange timed out waiting for key negotiation', ): print( "Rekey timeout. Restarting client. Open transports may be interrupted" ) reinit = [] for t in self.__transports: if t.session is not None: t.__exit__() reinit.append(t) self.__exit__() self.__enter__() for t in reinit: t.__enter__() return self.client.exec_command(command, get_pty=pty) else: raise
def exec_command(self, cmd, error_expected=False): """ General command to execute remote commands on the configured host. :param cmd: The command to execute on the remote host :type cmd: unicode :param error_expected: Whether a non-zero error code is expected from the command execution. :type error_expected: bool :returns: a tuple containing the exitstatus and output of command """ tp = self._open_transport() try: # TODO: if we're on a recent version of paramiko, let's use the # timeout parameter when opening the session session = _open_session_with_timeout(tp) session.set_combine_stderr(True) session.exec_command(cmd) chunks_read = [] while True: data = session.recv(4096) if not data: break chunks_read.append(unicode(data, "utf-8", "replace")) status = session.recv_exit_status() if not error_expected and status != 0: raise paramiko.SSHException("Non-zero exit status {} from " "command `{}`".format(status, cmd)) session.close() output = ''.join(chunks_read) return status, output finally: tp.close()
def test_logging_when_reraising_other_exc(self, mock_LOG): self.client.password = "******" exc = paramiko.SSHException() self.mock_connect.side_effect = exc self.assertRaises(paramiko.SSHException, self.client.connect) mock_LOG.info.assert_any_call('ssh://%s@%s:%d failed. %s', 'test-user', '123.456.789.0', 22, exc)
def _run_ssh(self, command, check_exit=True, attempts=1): if not self.sshpool: self.sshpool = utils.SSHPool( self.config.san_ip, self.config.san_ssh_port, self.config.ssh_conn_timeout, self.config.san_login, password=self.config.san_password, privatekey=self.config.san_private_key, min_size=self.config.ssh_min_pool_conn, max_size=self.config.ssh_max_pool_conn) try: total_attempts = attempts with self.sshpool.item() as ssh: while attempts > 0: attempts -= 1 try: return self._ssh_execute(ssh, command, check_exit_code=check_exit) except Exception as e: LOG.error(e) greenthread.sleep(randint(20, 500) / 100.0) raise paramiko.SSHException( _("SSH Command failed after " "'%(total_attempts)r' attempts" ": '%(command)s'"), locals()) except Exception as e: LOG.error(_("Error running ssh command: %s") % command) raise e
def mkdir(self, path: str): """ Creates the requested directory """ if self.session is None: raise paramiko.SSHException("Transport is not connected") return self.session.mkdir(path)
def listdir(self, path: str) -> typing.List[str]: """ Lists the contents of the requested path """ if self.session is None: raise paramiko.SSHException("Transport is not connected") return self.session.listdir(path)
def client(logger=None): if logger is None: logger = logging.getLogger("sftp_client") logger.setLevel(logging.DEBUG) if not available(): raise ValueError( "environmental variable $SFTP_SERVER, $SFTP_USER, and $SFTP_PASSWORD is required" ) sftp_server, sftp_user, sftp_password = os.environ[ "SFTP_SERVER"], os.environ["SFTP_USER"], os.environ["SFTP_PASSWORD"] try: sftp_port = int(os.environ.get("SFTP_PORT", 22)) except ValueError: raise ValueError("SFTP_PORT is not an integer: {0}".format( os.environ.get("SFTP_PORT"))) try: connected = False e = None for i in range(0, SSH_PROTOCOL_ERROR_RETRIES): logger.info( "trying to connect to {0}@{1} (port {2}) attempt {3}".format( sftp_user, sftp_server, sftp_port, i)) transport = paramiko.Transport((sftp_server, sftp_port)) try: transport.connect(username=sftp_user, password=sftp_password) except paramiko.SSHException as e: if str(e) == "Error reading SSH protocol banner": transport.close() logger.warning( "failed to connect with {0}, retrying...".format( str(e))) continue raise e else: logger.info("connected to {0}@{1} (port {2})".format( sftp_user, sftp_server, sftp_port)) connected = True break if not connected: raise paramiko.SSHException( "cannot connect to SSH even after {0} retries: {1}".format( SSH_PROTOCOL_ERROR_RETRIES, str(e))) sftp = paramiko.SFTPClient.from_transport(transport) logger.debug("Can see the following directory listings: {0}".format( " ".join(sftp.listdir()))) yield sftp finally: sftp.close() transport.close() logger.info("disconnected from {0}@{1} (port {2})".format( sftp_user, sftp_server, sftp_port))
def handler(title, instructions, fields): global password if len(fields) > 1: raise sftp.SSHException("Expecting one field only.") return [password]
def _sftp(self): if self.__sftp is not None: return self.__sftp logger.warning('SFTP is not connected, try to reconnect') self._connect_sftp() if self.__sftp is not None: return self.__sftp raise paramiko.SSHException('SFTP connection failed')
def __enter__(self): """ Starts a connection to the remote server """ if self.client._transport is None: raise paramiko.SSHException("Client is not connected") self.session = self.client.open_sftp() return self
def missing_host_key(self, client, hostname, key): print "Target has ssh host key fingerprint ", print binascii.hexlify(key.get_fingerprint()) response = raw_input("Is this correct? y/N: ") if response.lower() == "y": super(AskAddPolicy, self).missing_host_key(client, hostname, key) else: raise paramiko.SSHException("Incorrect host key for %s" % hostname)
def connect_to_server(self): if not self.__host or not self.__user or not self.__password: raise paramiko.SSHException( "host, user or password field is empty") self.ssh_conn = paramiko.SSHClient() self.ssh_conn.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh_conn.connect(self.__host, username=self.__user, password=self.__password)
def wait_for_completion(self, poll_timeout=POLL_TIMEOUT, exec_timeout=EXEC_TIMEOUT): tx = time.time() + float(exec_timeout) n = 0L while not self.exit_status_ready(): n += 1L if time.time() > tx: raise paramiko.SSHException('Execution timeout exceeded', n) time.sleep(poll_timeout) return self.channel.recv_exit_status()
def test_execute_read_exception(self): ssh = mock.Mock(paramiko.SSHClient) exec_command = self.mock_object(ssh, 'exec_command') exec_command.side_effect = paramiko.SSHException('Failure') wait_on_stdout = self.mock_object(self.sshutil, '_wait_on_stdout') self.assertRaises(paramiko.SSHException, self.sshutil.execute_command, ssh, 'ls') wait_on_stdout.assert_not_called()
def handle( self, ): peer_name = self.request.getpeername() try: self.ssh_channel = self.server.paramiko_session.get_transport().open_channel( kind='direct-tcpip', dest_addr=( self.server.remote_host, self.server.remote_port, ), src_addr=peer_name, ) except Exception as error: logger.error( msg='Incoming request to {host}:{port} failed.'.format( host=self.server.remote_host, port=self.server.remote_port, ), ) raise paramiko.SSHException( error, ) else: self.selector.register( fileobj=self.ssh_channel, events=selectors.EVENT_READ, data=self._read_from_channel, ) self.selector.register( fileobj=self.request, events=selectors.EVENT_READ, data=self._read_from_client, ) if self.ssh_channel is None: logger.warning( msg='Incoming request to {host}:{port} was rejected by the SSH server.'.format( host=self.server.remote_host, port=self.server.remote_port, ), ) self.finish() while True: events = self.selector.select() for key, mask in events: callback = key.data callback( socket_obj=key.fileobj, mask=mask, ) if self.server._BaseServer__is_shut_down.is_set(): self.finish() time.sleep(0)
def _invoke( self, command: str ) -> typing.Tuple[paramiko.ChannelFile, paramiko.ChannelFile, paramiko.ChannelFile]: """ Raw handle to exec_command """ if self.client._transport is None: raise paramiko.SSHException("Client is not connected") return self.client.exec_command(command)