diff options
author | Michael Still <mikal@stillhq.com> | 2013-05-06 16:45:09 +1000 |
---|---|---|
committer | Michael Still <mikal@stillhq.com> | 2013-05-07 08:36:33 +1000 |
commit | 3893ef8c807457e54ecaf02c001f4b31a5a58b14 (patch) | |
tree | 6ea0b322750ea7d65fc7fcc04af36a4405385e5a /openstack/common/processutils.py | |
parent | f9d502228752bcb909e58cafacd1cd948d9a8206 (diff) | |
download | oslo-3893ef8c807457e54ecaf02c001f4b31a5a58b14.tar.gz oslo-3893ef8c807457e54ecaf02c001f4b31a5a58b14.tar.xz oslo-3893ef8c807457e54ecaf02c001f4b31a5a58b14.zip |
Import trycmd and ssh_execute from nova.
This change required adding basic unit tests as well as these were
both untested in nova.
Change-Id: If6843e57810198aab3c61f9eb3c3a6f42f710f7c
Diffstat (limited to 'openstack/common/processutils.py')
-rw-r--r-- | openstack/common/processutils.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/openstack/common/processutils.py b/openstack/common/processutils.py index 560055e..09baea3 100644 --- a/openstack/common/processutils.py +++ b/openstack/common/processutils.py @@ -34,6 +34,11 @@ from openstack.common import log as logging LOG = logging.getLogger(__name__) +class InvalidArgumentError(Exception): + def __init__(self, message=None): + super(InvalidArgumentError, self).__init__(message) + + class UnknownArgumentError(Exception): def __init__(self, message=None): super(UnknownArgumentError, self).__init__(message) @@ -179,3 +184,64 @@ def execute(*cmd, **kwargs): # call clean something up in between calls, without # it two execute calls in a row hangs the second one greenthread.sleep(0) + + +def trycmd(*args, **kwargs): + """ + A wrapper around execute() to more easily handle warnings and errors. + + Returns an (out, err) tuple of strings containing the output of + the command's stdout and stderr. If 'err' is not empty then the + command can be considered to have failed. + + :discard_warnings True | False. Defaults to False. If set to True, + then for succeeding commands, stderr is cleared + + """ + discard_warnings = kwargs.pop('discard_warnings', False) + + try: + out, err = execute(*args, **kwargs) + failed = False + except ProcessExecutionError, exn: + out, err = '', str(exn) + failed = True + + if not failed and discard_warnings and err: + # Handle commands that output to stderr but otherwise succeed + err = '' + + return out, err + + +def ssh_execute(ssh, cmd, process_input=None, + addl_env=None, check_exit_code=True): + LOG.debug(_('Running cmd (SSH): %s'), cmd) + if addl_env: + raise InvalidArgumentError(_('Environment not supported over SSH')) + + if process_input: + # This is (probably) fixable if we need it... + raise InvalidArgumentError(_('process_input not supported over SSH')) + + stdin_stream, stdout_stream, stderr_stream = ssh.exec_command(cmd) + channel = stdout_stream.channel + + # NOTE(justinsb): This seems suspicious... + # ...other SSH clients have buffering issues with this approach + stdout = stdout_stream.read() + stderr = stderr_stream.read() + stdin_stream.close() + + exit_status = channel.recv_exit_status() + + # exit_status == -1 if no exit code was returned + if exit_status != -1: + LOG.debug(_('Result was %s') % exit_status) + if check_exit_code and exit_status != 0: + raise ProcessExecutionError(exit_code=exit_status, + stdout=stdout, + stderr=stderr, + cmd=cmd) + + return (stdout, stderr) |