Code Review
/
yardstick.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
Merge "add missing test suite files for new scenarios"
[yardstick.git]
/
yardstick
/
ssh.py
diff --git
a/yardstick/ssh.py
b/yardstick/ssh.py
index
46d53b7
..
cfbc3ca
100644
(file)
--- a/
yardstick/ssh.py
+++ b/
yardstick/ssh.py
@@
-25,7
+25,7
@@
Execute command and get output:
status, stdout, stderr = ssh.execute("ps ax")
if status:
raise Exception("Command failed with non-zero status.")
status, stdout, stderr = ssh.execute("ps ax")
if status:
raise Exception("Command failed with non-zero status.")
- print
stdout.splitlines(
)
+ print
(stdout.splitlines()
)
Execute command with huge output:
Execute command with huge output:
@@
-62,13
+62,16
@@
Eventlet:
sshclient = eventlet.import_patched("yardstick.ssh")
"""
sshclient = eventlet.import_patched("yardstick.ssh")
"""
+from __future__ import absolute_import
import os
import select
import socket
import time
import os
import select
import socket
import time
+import re
import logging
import paramiko
import logging
import paramiko
+from oslo_utils import encodeutils
from scp import SCPClient
import six
from scp import SCPClient
import six
@@
-157,7
+160,7
@@
class SSH(object):
def run(self, cmd, stdin=None, stdout=None, stderr=None,
raise_on_error=True, timeout=3600,
def run(self, cmd, stdin=None, stdout=None, stderr=None,
raise_on_error=True, timeout=3600,
- keep_stdin_open=False):
+ keep_stdin_open=False
, pty=False
):
"""Execute specified command on the server.
:param cmd: Command to be executed.
"""Execute specified command on the server.
:param cmd: Command to be executed.
@@
-171,6
+174,10
@@
class SSH(object):
Default 1 hour. No timeout if set to 0.
:param keep_stdin_open: don't close stdin on empty reads
:type keep_stdin_open: bool
Default 1 hour. No timeout if set to 0.
:param keep_stdin_open: don't close stdin on empty reads
:type keep_stdin_open: bool
+ :param pty: Request a pseudo terminal for this connection.
+ This allows passing control characters.
+ Default False.
+ :type pty: bool
"""
client = self._get_client()
"""
client = self._get_client()
@@
-181,18
+188,21
@@
class SSH(object):
return self._run(client, cmd, stdin=stdin, stdout=stdout,
stderr=stderr, raise_on_error=raise_on_error,
timeout=timeout,
return self._run(client, cmd, stdin=stdin, stdout=stdout,
stderr=stderr, raise_on_error=raise_on_error,
timeout=timeout,
- keep_stdin_open=keep_stdin_open)
+ keep_stdin_open=keep_stdin_open
, pty=pty
)
def _run(self, client, cmd, stdin=None, stdout=None, stderr=None,
raise_on_error=True, timeout=3600,
def _run(self, client, cmd, stdin=None, stdout=None, stderr=None,
raise_on_error=True, timeout=3600,
- keep_stdin_open=False):
+ keep_stdin_open=False
, pty=False
):
transport = client.get_transport()
session = transport.open_session()
transport = client.get_transport()
session = transport.open_session()
+ if pty:
+ session.get_pty()
session.exec_command(cmd)
start_time = time.time()
session.exec_command(cmd)
start_time = time.time()
- data_to_send = ""
+ # encode on transmit, decode on receive
+ data_to_send = encodeutils.safe_encode("", incoming='utf-8')
stderr_data = None
# If we have data to be sent to stdin then `select' should also
stderr_data = None
# If we have data to be sent to stdin then `select' should also
@@
-207,14
+217,15
@@
class SSH(object):
r, w, e = select.select([session], writes, [session], 1)
if session.recv_ready():
r, w, e = select.select([session], writes, [session], 1)
if session.recv_ready():
- data =
session.recv(4096
)
+ data =
encodeutils.safe_decode(session.recv(4096), 'utf-8'
)
self.log.debug("stdout: %r", data)
if stdout is not None:
stdout.write(data)
continue
if session.recv_stderr_ready():
self.log.debug("stdout: %r", data)
if stdout is not None:
stdout.write(data)
continue
if session.recv_stderr_ready():
- stderr_data = session.recv_stderr(4096)
+ stderr_data = encodeutils.safe_decode(
+ session.recv_stderr(4096), 'utf-8')
self.log.debug("stderr: %r", stderr_data)
if stderr is not None:
stderr.write(stderr_data)
self.log.debug("stderr: %r", stderr_data)
if stderr is not None:
stderr.write(stderr_data)
@@
-223,7
+234,11
@@
class SSH(object):
if session.send_ready():
if stdin is not None and not stdin.closed:
if not data_to_send:
if session.send_ready():
if stdin is not None and not stdin.closed:
if not data_to_send:
- data_to_send = stdin.read(4096)
+ stdin_txt = stdin.read(4096)
+ if stdin_txt is None:
+ stdin_txt = ''
+ data_to_send = encodeutils.safe_encode(
+ stdin_txt, incoming='utf-8')
if not data_to_send:
# we may need to keep stdin open
if not keep_stdin_open:
if not data_to_send:
# we may need to keep stdin open
if not keep_stdin_open:
@@
-246,7
+261,7
@@
class SSH(object):
raise SSHError("Socket error.")
exit_status = session.recv_exit_status()
raise SSHError("Socket error.")
exit_status = session.recv_exit_status()
- if
0 != exit_status
and raise_on_error:
+ if
exit_status != 0
and raise_on_error:
fmt = "Command '%(cmd)s' failed with exit_status %(status)d."
details = fmt % {"cmd": cmd, "status": exit_status}
if stderr_data:
fmt = "Command '%(cmd)s' failed with exit_status %(status)d."
details = fmt % {"cmd": cmd, "status": exit_status}
if stderr_data:
@@
-305,17
+320,21
@@
class SSH(object):
mode = 0o777 & os.stat(localpath).st_mode
sftp.chmod(remotepath, mode)
mode = 0o777 & os.stat(localpath).st_mode
sftp.chmod(remotepath, mode)
+ TILDE_EXPANSIONS_RE = re.compile("(^~[^/]*/)?(.*)")
+
def _put_file_shell(self, localpath, remotepath, mode=None):
# quote to stop wordpslit
def _put_file_shell(self, localpath, remotepath, mode=None):
# quote to stop wordpslit
- cmd = ['cat > "%s"' % remotepath]
+ tilde, remotepath = self.TILDE_EXPANSIONS_RE.match(remotepath).groups()
+ if not tilde:
+ tilde = ''
+ cmd = ['cat > %s"%s"' % (tilde, remotepath)]
if mode is not None:
# use -- so no options
if mode is not None:
# use -- so no options
- cmd.append('chmod -- 0%o
"%s"' % (mo
de, remotepath))
+ cmd.append('chmod -- 0%o
%s"%s"' % (mode, til
de, remotepath))
with open(localpath, "rb") as localfile:
# only chmod on successful cat
with open(localpath, "rb") as localfile:
# only chmod on successful cat
- cmd = "&& ".join(cmd)
- self.run(cmd, stdin=localfile)
+ self.run("&& ".join(cmd), stdin=localfile)
def put_file(self, localpath, remotepath, mode=None):
"""Copy specified local file to the server.
def put_file(self, localpath, remotepath, mode=None):
"""Copy specified local file to the server.
@@
-324,7
+343,6
@@
class SSH(object):
:param remotepath: Remote filename.
:param mode: Permissions to set after upload
"""
:param remotepath: Remote filename.
:param mode: Permissions to set after upload
"""
- import socket
try:
self._put_file_sftp(localpath, remotepath, mode=mode)
except (paramiko.SSHException, socket.error):
try:
self._put_file_sftp(localpath, remotepath, mode=mode)
except (paramiko.SSHException, socket.error):