]> scripts.mit.edu Git - wizard.git/blobdiff - wizard/shell.py
Implement web verification for pre-upgrade and post-upgrade.
[wizard.git] / wizard / shell.py
index c66147a0f9d876fe9fe10b2249d4cfd7f6771a49..8660d1ade198840e5c15d79ee1abb8fcdf30ff14 100644 (file)
@@ -25,12 +25,14 @@ def is_python(args):
     """Detects whether or not an argument list invokes a Python program."""
     return args[0] == "python" or args[0] == "wizard"
 
-def drop_priviledges(dir, options):
+def drop_priviledges(dir, log_file):
     """
     Checks if we are running as root.  If we are, attempt to drop
     priviledges to the user who owns ``dir``, by re-calling
     itself using sudo with exec, such that the new process subsumes our
-    current one.
+    current one.  If ``log_file`` is passed, the file is chown'ed
+    to the user we are dropping priviledges to, so the subprocess
+    can write to it.
     """
     if os.getuid():
         return
@@ -43,7 +45,7 @@ def drop_priviledges(dir, options):
             args.append("%s=%s" % (k,v))
     args += sys.argv
     logging.debug("Dropping priviledges")
-    if options.log_file: os.chown(options.log_file, uid, -1)
+    if log_file: os.chown(log_file, uid, -1)
     os.execlp('sudo', 'sudo', '-u', '#' + str(uid), *args)
 
 class Shell(object):
@@ -73,6 +75,9 @@ class Shell(object):
             specify this if you are using another wrapper around this function).
         :param log: if True, we log the call as INFO, if False, we log the call
             as DEBUG, otherwise, we detect based on ``strip``.
+        :param stdout:
+        :param stderr:
+        :param stdin: a file-type object that will be written to or read from as a pipe.
         :returns: a tuple of strings ``(stdout, stderr)``, or a string ``stdout``
             if ``strip`` is specified.
 
@@ -88,6 +93,9 @@ class Shell(object):
         kwargs.setdefault("strip", False)
         kwargs.setdefault("python", None)
         kwargs.setdefault("log", None)
+        kwargs.setdefault("stdout", subprocess.PIPE)
+        kwargs.setdefault("stdin", subprocess.PIPE)
+        kwargs.setdefault("stderr", subprocess.PIPE)
         msg = "Running `" + ' '.join(args) + "`"
         if kwargs["strip"] and not kwargs["log"] is True or kwargs["log"] is False:
             logging.debug(msg)
@@ -108,9 +116,9 @@ class Shell(object):
             stdin=sys.stdin
             stderr=sys.stderr
         else:
-            stdout=subprocess.PIPE
-            stdin=subprocess.PIPE
-            stderr=subprocess.PIPE
+            stdout=kwargs["stdout"]
+            stdin=kwargs["stdin"]
+            stderr=kwargs["stderr"]
         # XXX: There is a possible problem here where we can fill up
         # the kernel buffer if we have 64KB of data.  This shouldn't
         # be a problem, and the fix for such case would be to write to
@@ -244,6 +252,13 @@ class ParallelShell(Shell):
         super(ParallelShell, self).__init__(dry=dry)
         self.running = {}
         self.max = max # maximum of commands to run in parallel
+    @staticmethod
+    def make(no_parallelize, max):
+        """Convenience method oriented towards command modules."""
+        if no_parallelize:
+            return DummyParallelShell()
+        else:
+            return ParallelShell(max=max)
     def _async(self, proc, args, python, on_success, on_error, **kwargs):
         """
         Gets handed a :class:`subprocess.Proc` object from our deferred