diff options
Diffstat (limited to 'nova/utils.py')
-rw-r--r-- | nova/utils.py | 123 |
1 files changed, 14 insertions, 109 deletions
diff --git a/nova/utils.py b/nova/utils.py index bb002b9e7..64606f4f8 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -30,7 +30,6 @@ import pyclbr import random import re import shutil -import signal import socket import struct import sys @@ -38,8 +37,6 @@ import tempfile import time from xml.sax import saxutils -from eventlet.green import subprocess -from eventlet import greenthread import netaddr from oslo.config import cfg @@ -48,6 +45,7 @@ from nova import exception from nova.openstack.common import excutils from nova.openstack.common import importutils from nova.openstack.common import log as logging +from nova.openstack.common import processutils from nova.openstack.common.rpc import common as rpc_common from nova.openstack.common import timeutils @@ -149,107 +147,11 @@ def vpn_ping(address, port, timeout=0.05, session_id=None): return server_sess -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/nova/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 run with rootwrap. - - :raises exception.NovaException: 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.NovaException(_('Got unknown keyword args ' - 'to utils.execute: %r') % kwargs) - - if run_as_root and os.geteuid() != 0: - cmd = ['sudo', 'nova-rootwrap', CONF.rootwrap_config] + 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 - - if os.name == 'nt': - preexec_fn = None - close_fds = False - else: - preexec_fn = _subprocess_setup - close_fds = True - - obj = subprocess.Popen(cmd, - stdin=_PIPE, - stdout=_PIPE, - stderr=_PIPE, - close_fds=close_fds, - preexec_fn=preexec_fn, - 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 - 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 nova-rootwrap %s' % CONF.rootwrap_config + return processutils.execute(*cmd, **kwargs) def trycmd(*args, **kwargs): @@ -269,7 +171,7 @@ def trycmd(*args, **kwargs): try: out, err = execute(*args, **kwargs) failed = False - except exception.ProcessExecutionError, exn: + except processutils.ProcessExecutionError, exn: out, err = '', str(exn) failed = True @@ -309,10 +211,13 @@ def ssh_execute(ssh, cmd, process_input=None, if exit_status != -1: LOG.debug(_('Result was %s') % exit_status) if check_exit_code and exit_status != 0: - raise exception.ProcessExecutionError(exit_code=exit_status, - stdout=stdout, - stderr=stderr, - cmd=cmd) + # TODO(mikal): I know this is a bit odd, but its needed for + # consistency. I will move this method into processutils in a + # later change. + raise processutils.ProcessExecutionError(exit_code=exit_status, + stdout=stdout, + stderr=stderr, + cmd=cmd) return (stdout, stderr) @@ -1066,7 +971,7 @@ def read_file_as_root(file_path): try: out, _err = execute('cat', file_path, run_as_root=True) return out - except exception.ProcessExecutionError: + except processutils.ProcessExecutionError: raise exception.FileNotFound(file_path=file_path) |