summaryrefslogtreecommitdiffstats
path: root/openstack
diff options
context:
space:
mode:
authorMichael Still <mikal@stillhq.com>2012-11-01 13:41:32 +0100
committerMichael Still <mikal@stillhq.com>2012-11-01 15:00:55 +0100
commit4c00615aad0a21d81924586a7265f31a51801b30 (patch)
treee05423f106b0b6dc21e033c53d8e0749d4e215e4 /openstack
parent3d6c2368a5de16d875341426db8ddc9888213264 (diff)
downloadoslo-4c00615aad0a21d81924586a7265f31a51801b30.tar.gz
oslo-4c00615aad0a21d81924586a7265f31a51801b30.tar.xz
oslo-4c00615aad0a21d81924586a7265f31a51801b30.zip
Move utils.execute to its own module.
Also move the exceptions raised to being local to the executils module. Change-Id: Ibb2445f92840b9ce4b52373b0b09adb3d6a4a897
Diffstat (limited to 'openstack')
-rw-r--r--openstack/common/exception.py12
-rw-r--r--openstack/common/processutils.py124
-rw-r--r--openstack/common/utils.py76
3 files changed, 124 insertions, 88 deletions
diff --git a/openstack/common/exception.py b/openstack/common/exception.py
index ba32da5..4866de2 100644
--- a/openstack/common/exception.py
+++ b/openstack/common/exception.py
@@ -22,18 +22,6 @@ Exceptions common to OpenStack projects
import logging
-class ProcessExecutionError(IOError):
- def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
- description=None):
- if description is None:
- description = "Unexpected error while running command."
- if exit_code is None:
- exit_code = '-'
- message = "%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r" % (
- description, cmd, exit_code, stdout, stderr)
- IOError.__init__(self, message)
-
-
class Error(Exception):
def __init__(self, message=None):
super(Error, self).__init__(message)
diff --git a/openstack/common/processutils.py b/openstack/common/processutils.py
new file mode 100644
index 0000000..a21db01
--- /dev/null
+++ b/openstack/common/processutils.py
@@ -0,0 +1,124 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 OpenStack LLC.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+System-level utilities and helper functions.
+"""
+
+import logging
+import random
+import shlex
+
+from eventlet.green import subprocess
+from eventlet import greenthread
+
+from openstack.common.gettextutils import _
+
+
+LOG = logging.getLogger(__name__)
+
+
+class UnknownArgumentError(Exception):
+ def __init__(self, message=None):
+ super(UnknownArgumentError, self).__init__(message)
+
+
+class ProcessExecutionError(Exception):
+ def __init__(self, stdout=None, stderr=None, exit_code=None, cmd=None,
+ description=None):
+ if description is None:
+ description = "Unexpected error while running command."
+ if exit_code is None:
+ exit_code = '-'
+ message = ("%s\nCommand: %s\nExit code: %s\nStdout: %r\nStderr: %r"
+ % (description, cmd, exit_code, stdout, stderr))
+ super(ProcessExecutionError, self).__init__(message)
+
+
+def execute(*cmd, **kwargs):
+ """
+ Helper method to execute command with optional retry.
+
+ :cmd Passed to subprocess.Popen.
+ :process_input Send to opened process.
+ :check_exit_code Defaults to 0. Raise executils.ProcessExecutionError
+ unless program exits with this code.
+ :delay_on_retry True | False. Defaults to True. If set to True, wait a
+ short amount of time before retrying.
+ :attempts How many times to retry cmd.
+ :run_as_root True | False. Defaults to False. If set to True,
+ the command is prefixed by the command specified
+ in the root_helper kwarg.
+ :root_helper command to prefix all cmd's with
+
+ :raises executils.UnknownArgumentError on receiving unknown arguments
+ :raises executils.ProcessExecutionError
+ """
+
+ process_input = kwargs.pop('process_input', None)
+ check_exit_code = kwargs.pop('check_exit_code', 0)
+ delay_on_retry = kwargs.pop('delay_on_retry', True)
+ attempts = kwargs.pop('attempts', 1)
+ run_as_root = kwargs.pop('run_as_root', False)
+ root_helper = kwargs.pop('root_helper', '')
+ if len(kwargs):
+ raise UnknownArgumentError(_('Got unknown keyword args '
+ 'to utils.execute: %r') % kwargs)
+ if run_as_root:
+ cmd = shlex.split(root_helper) + list(cmd)
+ cmd = map(str, cmd)
+
+ while attempts > 0:
+ attempts -= 1
+ try:
+ LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd))
+ _PIPE = subprocess.PIPE # pylint: disable=E1101
+ obj = subprocess.Popen(cmd,
+ stdin=_PIPE,
+ stdout=_PIPE,
+ stderr=_PIPE,
+ close_fds=True)
+ result = None
+ if process_input is not None:
+ result = obj.communicate(process_input)
+ else:
+ result = obj.communicate()
+ obj.stdin.close() # pylint: disable=E1101
+ _returncode = obj.returncode # pylint: disable=E1101
+ if _returncode:
+ LOG.debug(_('Result was %s') % _returncode)
+ if (isinstance(check_exit_code, int) and
+ not isinstance(check_exit_code, bool) and
+ _returncode != check_exit_code):
+ (stdout, stderr) = result
+ raise ProcessExecutionError(exit_code=_returncode,
+ stdout=stdout,
+ stderr=stderr,
+ cmd=' '.join(cmd))
+ return result
+ except ProcessExecutionError:
+ if not attempts:
+ raise
+ else:
+ LOG.debug(_('%r failed. Retrying.'), cmd)
+ if delay_on_retry:
+ greenthread.sleep(random.randint(20, 200) / 100.0)
+ finally:
+ # NOTE(termie): this appears to be necessary to let the subprocess
+ # call clean something up in between calls, without
+ # it two execute calls in a row hangs the second one
+ greenthread.sleep(0)
diff --git a/openstack/common/utils.py b/openstack/common/utils.py
index 220b49e..dce62c1 100644
--- a/openstack/common/utils.py
+++ b/openstack/common/utils.py
@@ -62,79 +62,3 @@ def bool_from_string(subject):
if subject.strip().lower() in ('true', 'on', 'yes', '1'):
return True
return False
-
-
-def execute(*cmd, **kwargs):
- """
- Helper method to execute command with optional retry.
-
- :cmd Passed to subprocess.Popen.
- :process_input Send to opened process.
- :check_exit_code Defaults to 0. Raise exception.ProcessExecutionError
- unless program exits with this code.
- :delay_on_retry True | False. Defaults to True. If set to True, wait a
- short amount of time before retrying.
- :attempts How many times to retry cmd.
- :run_as_root True | False. Defaults to False. If set to True,
- the command is prefixed by the command specified
- in the root_helper kwarg.
- :root_helper command to prefix all cmd's with
-
- :raises exception.Error on receiving unknown arguments
- :raises exception.ProcessExecutionError
- """
-
- process_input = kwargs.pop('process_input', None)
- check_exit_code = kwargs.pop('check_exit_code', 0)
- delay_on_retry = kwargs.pop('delay_on_retry', True)
- attempts = kwargs.pop('attempts', 1)
- run_as_root = kwargs.pop('run_as_root', False)
- root_helper = kwargs.pop('root_helper', '')
- if len(kwargs):
- raise exception.Error(_('Got unknown keyword args '
- 'to utils.execute: %r') % kwargs)
- if run_as_root:
- cmd = shlex.split(root_helper) + list(cmd)
- cmd = map(str, cmd)
-
- while attempts > 0:
- attempts -= 1
- try:
- LOG.debug(_('Running cmd (subprocess): %s'), ' '.join(cmd))
- _PIPE = subprocess.PIPE # pylint: disable=E1101
- obj = subprocess.Popen(cmd,
- stdin=_PIPE,
- stdout=_PIPE,
- stderr=_PIPE,
- close_fds=True)
- result = None
- if process_input is not None:
- result = obj.communicate(process_input)
- else:
- result = obj.communicate()
- obj.stdin.close() # pylint: disable=E1101
- _returncode = obj.returncode # pylint: disable=E1101
- if _returncode:
- LOG.debug(_('Result was %s') % _returncode)
- if (isinstance(check_exit_code, int) and
- not isinstance(check_exit_code, bool) and
- _returncode != check_exit_code):
- (stdout, stderr) = result
- raise exception.ProcessExecutionError(
- exit_code=_returncode,
- stdout=stdout,
- stderr=stderr,
- cmd=' '.join(cmd))
- return result
- except exception.ProcessExecutionError:
- if not attempts:
- raise
- else:
- LOG.debug(_('%r failed. Retrying.'), cmd)
- if delay_on_retry:
- greenthread.sleep(random.randint(20, 200) / 100.0)
- finally:
- # NOTE(termie): this appears to be necessary to let the subprocess
- # call clean something up in between calls, without
- # it two execute calls in a row hangs the second one
- greenthread.sleep(0)