import contextlib
import datetime
-import errno
import functools
import hashlib
import inspect
import pyclbr
import random
import re
-import shlex
import shutil
-import signal
import sys
import tempfile
import time
from xml.sax import saxutils
from eventlet import event
-from eventlet.green import subprocess
from eventlet import greenthread
from eventlet import pools
from cinder.openstack.common import importutils
from cinder.openstack.common import lockutils
from cinder.openstack.common import log as logging
+from cinder.openstack.common import processutils
from cinder.openstack.common import timeutils
execute('curl', '--fail', url, '-o', target)
-def _subprocess_setup():
- # Python installs a SIGPIPE handler by default. This is usually not what
- # non-Python subprocesses expect.
- signal.signal(signal.SIGPIPE, signal.SIG_DFL)
-
-
def execute(*cmd, **kwargs):
- """Helper method to execute command with optional retry.
-
- If you add a run_as_root=True command, don't forget to add the
- corresponding filter to etc/cinder/rootwrap.d !
-
- :param cmd: Passed to subprocess.Popen.
- :param process_input: Send to opened process.
- :param check_exit_code: Single bool, int, or list of allowed exit
- codes. Defaults to [0]. Raise
- exception.ProcessExecutionError unless
- program exits with one of these code.
- :param delay_on_retry: True | False. Defaults to True. If set to
- True, wait a short amount of time
- before retrying.
- :param attempts: How many times to retry cmd.
- :param run_as_root: True | False. Defaults to False. If set to True,
- the command is prefixed by the command specified
- in the root_helper CONF.
-
- :raises exception.Error: on receiving unknown arguments
- :raises exception.ProcessExecutionError:
-
- :returns: a tuple, (stdout, stderr) from the spawned process, or None if
- the command fails.
- """
-
- process_input = kwargs.pop('process_input', None)
- check_exit_code = kwargs.pop('check_exit_code', [0])
- ignore_exit_code = False
- if isinstance(check_exit_code, bool):
- ignore_exit_code = not check_exit_code
- check_exit_code = [0]
- elif isinstance(check_exit_code, int):
- check_exit_code = [check_exit_code]
- delay_on_retry = kwargs.pop('delay_on_retry', True)
- attempts = kwargs.pop('attempts', 1)
- run_as_root = kwargs.pop('run_as_root', False)
- shell = kwargs.pop('shell', False)
-
- if len(kwargs):
- raise exception.Error(_('Got unknown keyword args '
- 'to utils.execute: %r') % kwargs)
-
- if run_as_root:
-
- if CONF.rootwrap_config is None or CONF.root_helper != 'sudo':
- LOG.deprecated(_('The root_helper option (which lets you specify '
- 'a root wrapper different from cinder-rootwrap, '
- 'and defaults to using sudo) is now deprecated. '
- 'You should use the rootwrap_config option '
- 'instead.'))
-
- if (CONF.rootwrap_config is not None):
- cmd = ['sudo', 'cinder-rootwrap',
- CONF.rootwrap_config] + list(cmd)
- else:
- cmd = shlex.split(CONF.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,
- preexec_fn=_subprocess_setup,
- shell=shell)
- 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 not ignore_exit_code and _returncode not in 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)
+ """Convenience wrapper around oslo's execute() method."""
+ if 'run_as_root' in kwargs and not 'root_helper' in kwargs:
+ kwargs['root_helper'] =\
+ 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
+ try:
+ (stdout, stderr) = processutils.execute(*cmd, **kwargs)
+ except processutils.ProcessExecutionError as ex:
+ raise exception.ProcessExecutionError(
+ exit_code=ex.exit_code,
+ stderr=ex.stderr,
+ stdout=ex.stdout,
+ cmd=ex.cmd,
+ description=ex.description)
+ except processutils.UnknownArgumentError as ex:
+ raise exception.Error(ex.message)
+ return (stdout, stderr)
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)
-
+ """Convenience wrapper around oslo's trycmd() method."""
+ if 'run_as_root' in kwargs and not 'root_helper' in kwargs:
+ kwargs['root_helper'] =\
+ 'sudo cinder-rootwrap %s' % CONF.rootwrap_config
try:
- out, err = execute(*args, **kwargs)
- failed = False
- except exception.ProcessExecutionError as exn:
- out, err = '', str(exn)
- LOG.debug(err)
- failed = True
-
- if not failed and discard_warnings and err:
- # Handle commands that output to stderr but otherwise succeed
- LOG.debug(err)
- err = ''
-
- return out, err
+ (stdout, stderr) = processutils.trycmd(*args, **kwargs)
+ except processutils.ProcessExecutionError as ex:
+ raise exception.ProcessExecutionError(
+ exit_code=ex.exit_code,
+ stderr=ex.stderr,
+ stdout=ex.stdout,
+ cmd=ex.cmd,
+ description=ex.description)
+ except processutils.UnknownArgumentError as ex:
+ raise exception.Error(ex.message)
+ return (stdout, stderr)
def ssh_execute(ssh, cmd, process_input=None,