This allows us to only remote-execute the actual calls, not whole functions.
"""
-from ceph_deploy.util.decorators import remote_compile
from ceph_deploy.util import context
"""
command = ' '.join(args)
patch = kw.pop('patch', True) # Always patch unless explicitly told to
+ mangle = kw.pop('mangle_exc', False) # Default to not mangle exceptions
+ stop_on_error = kw.pop('stop_on_error', True) # Halt on remote exceptions
logger.info('Running command: %s' % command)
def remote_call(args, *a, **kw):
**kw
)
+ with context.remote(conn, logger, remote_call, mangle_exc=mangle, patch=patch) as call:
+ try:
+ return call(args, *a, **kw)
+ except Exception as err:
+ import inspect
+ stack = inspect.getframeinfo(inspect.currentframe().f_back)
+ if hasattr(err, 'remote_traceback'):
+ logger.error('Traceback (most recent call last):')
+ logger.error(' File "%s", line %s, in %s' % (
+ stack[0],
+ stack[1],
+ stack[2])
+ )
+ err.remote_traceback.pop(0)
+ for line in err.remote_traceback:
+ if line:
+ logger.error(line)
+ if stop_on_error:
+ raise RuntimeError(
+ 'Failed to execute command: %s' % ' '.join(args)
+ )
+ else:
+ if stop_on_error:
+ raise err
+
+
+def Popen(conn, logger, args, *a, **kw):
+ """
+ Wraps ``subprocess.Popen`` for a remote call via ``pushy``
+ doing all the capturing and logging nicely upon failure/success
+
+ The mangling of the traceback when an exception ocurrs, is because the
+ caller gets eating up by not being executed in the actual function of
+ a given module (e.g. ``centos/install.py``) but rather here, where the
+ stack trace is no longer relevant.
+
+ :param args: The args to be passed onto ``Popen``
+ """
+ command = ' '.join(args)
+ patch = kw.pop('patch', True) # Always patch unless explicitly told to
+ logger.info('Running command: %s' % command)
+
+ def remote_call(args, *a, **kw):
+ import subprocess
+ process = subprocess.Popen(
+ args,
+ *a,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ **kw
+ )
+ stdout, stderr = process.communicate()
+ return stdout, stderr, process.wait()
+
with context.remote(conn, logger, remote_call, mangle_exc=False, patch=patch) as call:
try:
return call(args, *a, **kw)