]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-deploy.git/commitdiff
create a Popen wrapper that can do remote stuff for us
authorAlfredo Deza <alfredo.deza@inktank.com>
Mon, 19 Aug 2013 20:56:11 +0000 (16:56 -0400)
committerAlfredo Deza <alfredo@deza.pe>
Tue, 20 Aug 2013 15:46:10 +0000 (11:46 -0400)
Signed-off-by: Alfredo Deza <alfredo.deza@inktank.com>
ceph_deploy/util/wrappers.py

index 4bff77b5657b6ea0ac484359fb93d3a804362451..fe41856d1f7f773bc36648761084ef1185685453 100644 (file)
@@ -5,7 +5,6 @@ logging and remote execution.
 
 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
 
 
@@ -23,6 +22,8 @@ def check_call(conn, logger, args, *a, **kw):
     """
     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):
@@ -33,6 +34,60 @@ def check_call(conn, logger, 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)