def __enter__(self): # NOTE(ft): Iperf doesn't close stdout in server mode # but standard exec_command waits for it # so instead of use it we waits for some string in output ssh = remote_client.RemoteClient(self.instance.ip_address, self.ssh_user, pkey=self.ssh_keypair.material) ssh_conn = ssh.ssh_client._get_ssh_connection() chan = ssh_conn.get_transport().open_session() chan.get_pty() # NOTE(ft): to stop iperf with session end chan.fileno() chan.exec_command(self.cmd) started = False out_data = [] err_data = [] select_params = [chan], [], [], ssh.ssh_client.channel_timeout while True: ready = select.select(*select_params) if not any(ready): raise exceptions.TimeoutException( "Cannot start iperf server on host '{1}'.".format( self.host)) if not ready[0]: continue out_chunk = err_chunk = None if chan.recv_ready(): out_chunk = chan.recv(ssh.ssh_client.buf_size) out_data += out_chunk, if chan.recv_stderr_ready(): err_chunk = chan.recv_stderr(ssh.ssh_client.buf_size) err_data += err_chunk, if chan.exit_status_ready(): exit_status = chan.recv_exit_status() if 0 != exit_status or len(err_data) > 0: raise exceptions.SSHExecCommandFailed( command=self.cmd, exit_status=exit_status, strerror=''.join(err_data)) lines = ''.join(out_data).splitlines() for line in lines: if line.startswith("Server listening"): started = True break if (started or chan.closed and not err_chunk and not out_chunk): break self.ssh = ssh self.ssh_conn = ssh_conn self.chan = chan
def exec_command(self, cmd): """ Execute the specified command on the server. Note that this method is reading whole command outputs to memory, thus shouldn't be used for large outputs. :returns: data read from standard output of the command. :raises: SSHExecCommandFailed if command returns nonzero status. The exception contains command status stderr content. """ ssh = self._get_ssh_connection() transport = ssh.get_transport() channel = transport.open_session() channel.fileno() # Register event pipe channel.exec_command(cmd) channel.shutdown_write() out_data = [] err_data = [] poll = select.poll() poll.register(channel, select.POLLIN) start_time = time.time() while True: ready = poll.poll(self.channel_timeout) if not any(ready): if not self._is_timed_out(start_time): continue raise exceptions.TimeoutException( "Command: '{0}' executed on host '{1}'.".format( cmd, self.host)) if not ready[0]: # If there is nothing to read. continue out_chunk = err_chunk = None if channel.recv_ready(): out_chunk = channel.recv(self.buf_size) out_data += out_chunk, if channel.recv_stderr_ready(): err_chunk = channel.recv_stderr(self.buf_size) err_data += err_chunk, if channel.closed and not err_chunk and not out_chunk: break exit_status = channel.recv_exit_status() if 0 != exit_status: raise exceptions.SSHExecCommandFailed(command=cmd, exit_status=exit_status, strerror=''.join(err_data)) return ''.join(out_data)
def scp_file_to_instance_using_fip(self, src_file, dst_folder, dst_host, username, pkey): dst_folder = "%s@%s:%s" % (username, dst_host, dst_folder) cmd = "scp -v -o UserKnownHostsFile=/dev/null " \ "-o StrictHostKeyChecking=no " \ "-i %(pkey)s %(file1)s %(dst_folder)s" % {'pkey': pkey, 'file1': src_file, 'dst_folder': dst_folder} args = shlex.split(cmd.encode('utf-8')) subprocess_args = { 'stdout': subprocess.PIPE, 'stderr': subprocess.STDOUT } proc = subprocess.Popen(args, **subprocess_args) stdout, stderr = proc.communicate() if proc.returncode != 0: raise exceptions.SSHExecCommandFailed(cmd, proc.returncode, stdout, stderr) return stdout