Move custom exception classes to catalyst.error and all spawn-related functions to...
authorAndrew Gaffney <agaffney@gentoo.org>
Sun, 11 Jan 2009 22:59:14 +0000 (16:59 -0600)
committerAndrew Gaffney <agaffney@gentoo.org>
Sun, 11 Jan 2009 22:59:14 +0000 (16:59 -0600)
17 files changed:
ChangeLog
catalyst
modules/catalyst/arch/powerpc.py
modules/catalyst/arch/sparc.py
modules/catalyst/arch/x86.py
modules/catalyst/config.py
modules/catalyst/error.py [new file with mode: 0644]
modules/catalyst/hash.py
modules/catalyst/spawn.py [new file with mode: 0644]
modules/catalyst/support.py
modules/catalyst/target/generic_stage.py
modules/catalyst/target/grp.py
modules/catalyst/target/livecd_stage2.py
modules/catalyst/target/netboot.py
modules/catalyst/target/netboot2.py
modules/catalyst/target/tinderbox.py
modules/catalyst/util.py

index dfd9f24cb781356c38f372ff1ca08f72b404e93a..a0ff5b87212ea86a318bf04af423646014ee8ea6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,18 @@
 # Copyright 2002-2009 Gentoo Foundation; 2008-2009 Various authors (see AUTHORS)
 # Distributed under the GPL v2
 
+  11 Jan 2009; Andrew Gaffney <agaffney@gentoo.org> catalyst,
+  modules/catalyst/arch/powerpc.py, modules/catalyst/arch/sparc.py,
+  modules/catalyst/arch/x86.py, modules/catalyst/config.py,
+  +modules/catalyst/error.py, modules/catalyst/hash.py,
+  +modules/catalyst/spawn.py, modules/catalyst/support.py,
+  modules/catalyst/target/generic_stage.py, modules/catalyst/target/grp.py,
+  modules/catalyst/target/livecd_stage2.py,
+  modules/catalyst/target/netboot.py, modules/catalyst/target/netboot2.py,
+  modules/catalyst/target/tinderbox.py, modules/catalyst/util.py:
+  Move custom exception classes to catalyst.error and all spawn-related
+  functions to catalyst.spawn
+
   11 Jan 2009; Andrew Gaffney <agaffney@gentoo.org>
   +modules/catalyst/hash.py, modules/catalyst/support.py,
   modules/catalyst/target/generic_stage.py,
index ee8eb83e8c1089ec8ac42613629a545ac68eb3bf..35da3446915eda0973b49a6552e94d3079ea1e29 100755 (executable)
--- a/catalyst
+++ b/catalyst
@@ -14,8 +14,9 @@ sys.path.append(__selfpath__ + "/modules")
 import catalyst.config
 import catalyst.util
 import catalyst.target
-from catalyst.support import hash_map, CatalystError
 from catalyst.output import *
+from catalyst.error import *
+from catalyst.hash import hash_map
 
 __maintainer__="Chris Gianelloni <wolf31o2@gentoo.org>"
 __version__="2.99"
index 50c848dc0f0273367d7840e8b5f99a897183bc3d..ea28b04c664ed4a8a9d6bff8b8643312e97df660 100644 (file)
@@ -1,6 +1,7 @@
 
 import os,catalyst.arch
 from catalyst.support import *
+from catalyst.error import *
 
 class generic_ppc(catalyst.arch.generic_arch):
        "abstract base class for all 32-bit powerpc builders"
index 9404caf31ceead8a1bea008cdc871204a08cf6d9..30c932404e888fb4ec08eb42ef0ff9d4e22f4453 100644 (file)
@@ -1,6 +1,7 @@
 
 import catalyst.arch,os
 from catalyst.support import *
+from catalyst.error import *
 
 class generic_sparc(catalyst.arch.generic_arch):
        "abstract base class for all sparc builders"
index 960c6e1d8ba5ecaf40a79c4e579e91ee374704a1..6c45b34319a70ff9ba949896d0c7f1443b39f06e 100644 (file)
@@ -1,6 +1,7 @@
 
 import catalyst.arch,os
 from catalyst.support import *
+from catalyst.error import *
 
 class generic_x86(catalyst.arch.generic_arch):
        "abstract base class for all x86 builders"
index 6f53bdd2a40f1fe8799efbc29c18da48e09f1f7f..746a2c6846c7df80f42ae127b647f429896e459d 100644 (file)
@@ -1,4 +1,5 @@
 import re
+from catalyst.error import *
 
 class ParserBase:
 
diff --git a/modules/catalyst/error.py b/modules/catalyst/error.py
new file mode 100644 (file)
index 0000000..cc22e9b
--- /dev/null
@@ -0,0 +1,29 @@
+"""
+This module contains the custom exception classes used by catalyst
+"""
+
+import sys, traceback
+import catalyst.output
+
+class CatalystError(Exception):
+       def __init__(self, message):
+               if message:
+                       (type,value)=sys.exc_info()[:2]
+                       if value!=None:
+                               print
+                               print traceback.print_exc(file=sys.stdout)
+                       print
+                       catalyst.output.warn(message)
+                       print
+
+class LockInUse(Exception):
+       def __init__(self, message):
+               if message:
+                       #(type,value)=sys.exc_info()[:2]
+                       #if value!=None:
+                           #print
+                           #kprint traceback.print_exc(file=sys.stdout)
+                       print
+                       catalyst.output.warn("lock file in use: " + message)
+                       print
+
index 44c272de007855a16bada4d8a79d35354b1a8d69..7392010e5402703f1db9997425768c7738022d7d 100644 (file)
@@ -3,6 +3,7 @@ This module contains functions for generating the CONTENTS and hash files
 """
 
 import os
+from catalyst.error import *
 
 def generate_contents(file, contents_function="auto", verbose=False):
        try:
diff --git a/modules/catalyst/spawn.py b/modules/catalyst/spawn.py
new file mode 100644 (file)
index 0000000..a6d3715
--- /dev/null
@@ -0,0 +1,304 @@
+"""
+This module contains all the functions related to spawning external commands
+"""
+
+import sys, os, types
+import catalyst.util
+from catalyst.error import *
+
+# pids this process knows of.
+spawned_pids = []
+
+def cleanup(pids,block_exceptions=True):
+        """function to go through and reap the list of pids passed to it"""
+        global spawned_pids
+        if type(pids) == int:
+                pids = [pids]
+        for x in pids:
+                try:
+                        os.kill(x,signal.SIGTERM)
+                        if os.waitpid(x,os.WNOHANG)[1] == 0:
+                                # feisty bugger, still alive.
+                                os.kill(x,signal.SIGKILL)
+                                os.waitpid(x,0)
+
+                except OSError, oe:
+                        if block_exceptions:
+                                pass
+                        if oe.errno not in (10,3):
+                                raise oe
+                except SystemExit:
+                        raise
+                except Exception:
+                        if block_exceptions:
+                                pass
+                try:                    spawned_pids.remove(x)
+                except IndexError:      pass
+
+
+def spawn_bash(mycommand,env={},debug=False,opt_name=None,**keywords):
+       """spawn mycommand as an arguement to bash"""
+       args=[BASH_BINARY]
+       if not opt_name:
+           opt_name=mycommand.split()[0]
+       if not "BASH_ENV" in env:
+           env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
+       if debug:
+           args.append("-x")
+       args.append("-c")
+       args.append(mycommand)
+       return spawn(args,env=env,opt_name=opt_name,**keywords)
+
+#def spawn_get_output(mycommand,spawn_type=spawn,raw_exit_code=False,emulate_gso=True, \
+#        collect_fds=[1],fd_pipes=None,**keywords):
+def spawn_get_output(mycommand,raw_exit_code=False,emulate_gso=True, \
+        collect_fds=[1],fd_pipes=None,**keywords):
+        """call spawn, collecting the output to fd's specified in collect_fds list
+        emulate_gso is a compatability hack to emulate commands.getstatusoutput's return, minus the
+        requirement it always be a bash call (spawn_type controls the actual spawn call), and minus the
+        'lets let log only stdin and let stderr slide by'.
+
+        emulate_gso was deprecated from the day it was added, so convert your code over.
+        spawn_type is the passed in function to call- typically spawn_bash, spawn, spawn_sandbox, or spawn_fakeroot"""
+        global selinux_capable
+        pr,pw=os.pipe()
+
+        #if type(spawn_type) not in [types.FunctionType, types.MethodType]:
+        #        s="spawn_type must be passed a function, not",type(spawn_type),spawn_type
+        #        raise Exception,s
+
+        if fd_pipes==None:
+                fd_pipes={}
+                fd_pipes[0] = 0
+
+        for x in collect_fds:
+                fd_pipes[x] = pw
+        keywords["returnpid"]=True
+
+        mypid=spawn_bash(mycommand,fd_pipes=fd_pipes,**keywords)
+        os.close(pw)
+        if type(mypid) != types.ListType:
+                os.close(pr)
+                return [mypid, "%s: No such file or directory" % mycommand.split()[0]]
+
+        fd=os.fdopen(pr,"r")
+        mydata=fd.readlines()
+        fd.close()
+        if emulate_gso:
+                mydata="".join(mydata)
+                if len(mydata) and mydata[-1] == "\n":
+                        mydata=mydata[:-1]
+        retval=os.waitpid(mypid[0],0)[1]
+        cleanup(mypid)
+        if raw_exit_code:
+                return [retval,mydata]
+        retval=process_exit_code(retval)
+        return [retval, mydata]
+
+
+# base spawn function
+def spawn(mycommand,env={},raw_exit_code=False,opt_name=None,fd_pipes=None,returnpid=False,\
+        uid=None,gid=None,groups=None,umask=None,logfile=None,path_lookup=True,\
+        selinux_context=None, raise_signals=False, func_call=False):
+        """base fork/execve function.
+       mycommand is the desired command- if you need a command to execute in a bash/sandbox/fakeroot
+       environment, use the appropriate spawn call.  This is a straight fork/exec code path.
+       Can either have a tuple, or a string passed in.  If uid/gid/groups/umask specified, it changes
+       the forked process to said value.  If path_lookup is on, a non-absolute command will be converted
+       to an absolute command, otherwise it returns None.
+
+       selinux_context is the desired context, dependant on selinux being available.
+       opt_name controls the name the processor goes by.
+       fd_pipes controls which file descriptor numbers are left open in the forked process- it's a dict of
+       current fd's raw fd #, desired #.
+
+       func_call is a boolean for specifying to execute a python function- use spawn_func instead.
+       raise_signals is questionable.  Basically throw an exception if signal'd.  No exception is thrown
+       if raw_input is on.
+
+       logfile overloads the specified fd's to write to a tee process which logs to logfile
+       returnpid returns the relevant pids (a list, including the logging process if logfile is on).
+
+       non-returnpid calls to spawn will block till the process has exited, returning the exitcode/signal
+       raw_exit_code controls whether the actual waitpid result is returned, or intrepretted."""
+
+
+       myc=''
+       if not func_call:
+               if type(mycommand)==types.StringType:
+                       mycommand=mycommand.split()
+               myc = mycommand[0]
+               if not os.access(myc, os.X_OK):
+                       if not path_lookup:
+                               return None
+                       myc = catalyst.util.find_binary(myc)
+                       if myc == None:
+                           return None
+        mypid=[]
+       if logfile:
+               pr,pw=os.pipe()
+               mypid.extend(spawn(('tee','-i','-a',logfile),returnpid=True,fd_pipes={0:pr,1:1,2:2}))
+               retval=os.waitpid(mypid[-1],os.WNOHANG)[1]
+               if retval != 0:
+                       # he's dead jim.
+                       if raw_exit_code:
+                               return retval
+                       return process_exit_code(retval)
+
+               if fd_pipes == None:
+                       fd_pipes={}
+                       fd_pipes[0] = 0
+               fd_pipes[1]=pw
+               fd_pipes[2]=pw
+
+       if not opt_name:
+               opt_name = mycommand[0]
+       myargs=[opt_name]
+       myargs.extend(mycommand[1:])
+       global spawned_pids
+       mypid.append(os.fork())
+       if mypid[-1] != 0:
+               #log the bugger.
+               spawned_pids.extend(mypid)
+
+       if mypid[-1] == 0:
+               if func_call:
+                       spawned_pids = []
+
+               # this may look ugly, but basically it moves file descriptors around to ensure no
+               # handles that are needed are accidentally closed during the final dup2 calls.
+               trg_fd=[]
+               if type(fd_pipes)==types.DictType:
+                       src_fd=[]
+                       k=fd_pipes.keys()
+                       k.sort()
+
+                       #build list of which fds will be where, and where they are at currently
+                       for x in k:
+                               trg_fd.append(x)
+                               src_fd.append(fd_pipes[x])
+
+                       # run through said list dup'ing descriptors so that they won't be waxed
+                       # by other dup calls.
+                       for x in range(0,len(trg_fd)):
+                               if trg_fd[x] == src_fd[x]:
+                                       continue
+                               if trg_fd[x] in src_fd[x+1:]:
+                                       new=os.dup2(trg_fd[x],max(src_fd) + 1)
+                                       os.close(trg_fd[x])
+                                       try:
+                                               while True:
+                                                       src_fd[s.index(trg_fd[x])]=new
+                                       except SystemExit, e:
+                                               raise
+                                       except:
+                                               pass
+
+                       # transfer the fds to their final pre-exec position.
+                       for x in range(0,len(trg_fd)):
+                               if trg_fd[x] != src_fd[x]:
+                                       os.dup2(src_fd[x], trg_fd[x])
+               else:
+                       trg_fd=[0,1,2]
+
+               # wax all open descriptors that weren't requested be left open.
+               for x in range(0,max_fd_limit):
+                       if x not in trg_fd:
+                               try:
+                                       os.close(x)
+                                except SystemExit, e:
+                                        raise
+                                except:
+                                        pass
+
+                # note this order must be preserved- can't change gid/groups if you change uid first.
+                if selinux_capable and selinux_context:
+                        import selinux
+                        selinux.setexec(selinux_context)
+                if gid:
+                        os.setgid(gid)
+                if groups:
+                        os.setgroups(groups)
+                if uid:
+                        os.setuid(uid)
+                if umask:
+                        os.umask(umask)
+                else:
+                        os.umask(022)
+
+                try:
+                        #print "execing", myc, myargs
+                        if func_call:
+                                # either use a passed in func for interpretting the results, or return if no exception.
+                                # note the passed in list, and dict are expanded.
+                                if len(mycommand) == 4:
+                                        os._exit(mycommand[3](mycommand[0](*mycommand[1],**mycommand[2])))
+                                try:
+                                        mycommand[0](*mycommand[1],**mycommand[2])
+                                except Exception,e:
+                                        print "caught exception",e," in forked func",mycommand[0]
+                                sys.exit(0)
+
+                       #os.execvp(myc,myargs)
+                        os.execve(myc,myargs,env)
+                except SystemExit, e:
+                        raise
+                except Exception, e:
+                        if not func_call:
+                                raise str(e)+":\n   "+myc+" "+"".join(myargs)
+                        print "func call failed"
+
+                # If the execve fails, we need to report it, and exit
+                # *carefully* --- report error here
+                os._exit(1)
+                sys.exit(1)
+                return # should never get reached
+
+        # if we were logging, kill the pipes.
+        if logfile:
+                os.close(pr)
+                os.close(pw)
+
+        if returnpid:
+                return mypid
+
+        # loop through pids (typically one, unless logging), either waiting on their death, or waxing them
+        # if the main pid (mycommand) returned badly.
+        while len(mypid):
+                retval=os.waitpid(mypid[-1],0)[1]
+                if retval != 0:
+                        cleanup(mypid[0:-1],block_exceptions=False)
+                        # at this point we've killed all other kid pids generated via this call.
+                        # return now.
+                        if raw_exit_code:
+                                return retval
+                        return process_exit_code(retval,throw_signals=raise_signals)
+                else:
+                        mypid.pop(-1)
+        cleanup(mypid)
+        return 0
+
+def cmd(mycmd,myexc="",env={}):
+       try:
+               sys.stdout.flush()
+               retval=spawn_bash(mycmd,env)
+               if retval != 0:
+                       raise CatalystError,myexc
+       except:
+               raise
+
+def process_exit_code(retval,throw_signals=False):
+        """process a waitpid returned exit code, returning exit code if it exit'd, or the
+        signal if it died from signalling
+        if throw_signals is on, it raises a SystemExit if the process was signaled.
+        This is intended for usage with threads, although at the moment you can't signal individual
+        threads in python, only the master thread, so it's a questionable option."""
+        if (retval & 0xff)==0:
+                return retval >> 8 # return exit code
+        else:
+                if throw_signals:
+                        #use systemexit, since portage is stupid about exception catching.
+                        raise SystemExit()
+                return (retval & 0xff) << 8 # interrupted by signal
+
+
index 7c67d59c093fe9b405ac68108f48e7db9c20be0f..35d0bb6d101caf09e00ed854e790c19801ed994d 100644 (file)
@@ -1,7 +1,8 @@
 
-import sys, os, types, re, signal, traceback
+import sys, os, re, signal
 from catalyst.output import warn
 import catalyst.util
+from catalyst.error import *
 
 selinux_capable = False
 #userpriv_capable = (os.getuid() == 0)
@@ -17,36 +18,6 @@ except:
        # hokay, no resource module.
        max_fd_limit=256
 
-# pids this process knows of.
-spawned_pids = []
-
-def cleanup(pids,block_exceptions=True):
-        """function to go through and reap the list of pids passed to it"""
-        global spawned_pids
-        if type(pids) == int:
-                pids = [pids]
-        for x in pids:
-                try:
-                        os.kill(x,signal.SIGTERM)
-                        if os.waitpid(x,os.WNOHANG)[1] == 0:
-                                # feisty bugger, still alive.
-                                os.kill(x,signal.SIGKILL)
-                                os.waitpid(x,0)
-
-                except OSError, oe:
-                        if block_exceptions:
-                                pass
-                        if oe.errno not in (10,3):
-                                raise oe
-                except SystemExit:
-                        raise
-                except Exception:
-                        if block_exceptions:
-                                pass
-                try:                    spawned_pids.remove(x)
-                except IndexError:      pass
-
-
 required_config_file_values=["storedir","sharedir","distdir","portdir"]
 valid_config_file_values=required_config_file_values[:]
 valid_config_file_values.append("PKGCACHE")
@@ -72,294 +43,6 @@ valid_config_file_values.append("SEEDCACHE")
 
 verbosity=1
 
-class CatalystError(Exception):
-       def __init__(self, message):
-               if message:
-                       (type,value)=sys.exc_info()[:2]
-                       if value!=None:
-                               print
-                               print traceback.print_exc(file=sys.stdout)
-                       print
-                       print "!!! catalyst: "+message
-                       print
-
-class LockInUse(Exception):
-       def __init__(self, message):
-               if message:
-                       #(type,value)=sys.exc_info()[:2]
-                       #if value!=None:
-                           #print
-                           #kprint traceback.print_exc(file=sys.stdout)
-                       print
-                       print "!!! catalyst lock file in use: "+message
-                       print
-
-def spawn_bash(mycommand,env={},debug=False,opt_name=None,**keywords):
-       """spawn mycommand as an arguement to bash"""
-       args=[BASH_BINARY]
-       if not opt_name:
-           opt_name=mycommand.split()[0]
-       if not "BASH_ENV" in env:
-           env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
-       if debug:
-           args.append("-x")
-       args.append("-c")
-       args.append(mycommand)
-       return spawn(args,env=env,opt_name=opt_name,**keywords)
-
-#def spawn_get_output(mycommand,spawn_type=spawn,raw_exit_code=False,emulate_gso=True, \
-#        collect_fds=[1],fd_pipes=None,**keywords):
-def spawn_get_output(mycommand,raw_exit_code=False,emulate_gso=True, \
-        collect_fds=[1],fd_pipes=None,**keywords):
-        """call spawn, collecting the output to fd's specified in collect_fds list
-        emulate_gso is a compatability hack to emulate commands.getstatusoutput's return, minus the
-        requirement it always be a bash call (spawn_type controls the actual spawn call), and minus the
-        'lets let log only stdin and let stderr slide by'.
-
-        emulate_gso was deprecated from the day it was added, so convert your code over.
-        spawn_type is the passed in function to call- typically spawn_bash, spawn, spawn_sandbox, or spawn_fakeroot"""
-        global selinux_capable
-        pr,pw=os.pipe()
-
-        #if type(spawn_type) not in [types.FunctionType, types.MethodType]:
-        #        s="spawn_type must be passed a function, not",type(spawn_type),spawn_type
-        #        raise Exception,s
-
-        if fd_pipes==None:
-                fd_pipes={}
-                fd_pipes[0] = 0
-
-        for x in collect_fds:
-                fd_pipes[x] = pw
-        keywords["returnpid"]=True
-
-        mypid=spawn_bash(mycommand,fd_pipes=fd_pipes,**keywords)
-        os.close(pw)
-        if type(mypid) != types.ListType:
-                os.close(pr)
-                return [mypid, "%s: No such file or directory" % mycommand.split()[0]]
-
-        fd=os.fdopen(pr,"r")
-        mydata=fd.readlines()
-        fd.close()
-        if emulate_gso:
-                mydata="".join(mydata)
-                if len(mydata) and mydata[-1] == "\n":
-                        mydata=mydata[:-1]
-        retval=os.waitpid(mypid[0],0)[1]
-        cleanup(mypid)
-        if raw_exit_code:
-                return [retval,mydata]
-        retval=process_exit_code(retval)
-        return [retval, mydata]
-
-
-# base spawn function
-def spawn(mycommand,env={},raw_exit_code=False,opt_name=None,fd_pipes=None,returnpid=False,\
-        uid=None,gid=None,groups=None,umask=None,logfile=None,path_lookup=True,\
-        selinux_context=None, raise_signals=False, func_call=False):
-        """base fork/execve function.
-       mycommand is the desired command- if you need a command to execute in a bash/sandbox/fakeroot
-       environment, use the appropriate spawn call.  This is a straight fork/exec code path.
-       Can either have a tuple, or a string passed in.  If uid/gid/groups/umask specified, it changes
-       the forked process to said value.  If path_lookup is on, a non-absolute command will be converted
-       to an absolute command, otherwise it returns None.
-
-       selinux_context is the desired context, dependant on selinux being available.
-       opt_name controls the name the processor goes by.
-       fd_pipes controls which file descriptor numbers are left open in the forked process- it's a dict of
-       current fd's raw fd #, desired #.
-
-       func_call is a boolean for specifying to execute a python function- use spawn_func instead.
-       raise_signals is questionable.  Basically throw an exception if signal'd.  No exception is thrown
-       if raw_input is on.
-
-       logfile overloads the specified fd's to write to a tee process which logs to logfile
-       returnpid returns the relevant pids (a list, including the logging process if logfile is on).
-
-       non-returnpid calls to spawn will block till the process has exited, returning the exitcode/signal
-       raw_exit_code controls whether the actual waitpid result is returned, or intrepretted."""
-
-
-       myc=''
-       if not func_call:
-               if type(mycommand)==types.StringType:
-                       mycommand=mycommand.split()
-               myc = mycommand[0]
-               if not os.access(myc, os.X_OK):
-                       if not path_lookup:
-                               return None
-                       myc = catalyst.util.find_binary(myc)
-                       if myc == None:
-                           return None
-        mypid=[]
-       if logfile:
-               pr,pw=os.pipe()
-               mypid.extend(spawn(('tee','-i','-a',logfile),returnpid=True,fd_pipes={0:pr,1:1,2:2}))
-               retval=os.waitpid(mypid[-1],os.WNOHANG)[1]
-               if retval != 0:
-                       # he's dead jim.
-                       if raw_exit_code:
-                               return retval
-                       return process_exit_code(retval)
-
-               if fd_pipes == None:
-                       fd_pipes={}
-                       fd_pipes[0] = 0
-               fd_pipes[1]=pw
-               fd_pipes[2]=pw
-
-       if not opt_name:
-               opt_name = mycommand[0]
-       myargs=[opt_name]
-       myargs.extend(mycommand[1:])
-       global spawned_pids
-       mypid.append(os.fork())
-       if mypid[-1] != 0:
-               #log the bugger.
-               spawned_pids.extend(mypid)
-
-       if mypid[-1] == 0:
-               if func_call:
-                       spawned_pids = []
-
-               # this may look ugly, but basically it moves file descriptors around to ensure no
-               # handles that are needed are accidentally closed during the final dup2 calls.
-               trg_fd=[]
-               if type(fd_pipes)==types.DictType:
-                       src_fd=[]
-                       k=fd_pipes.keys()
-                       k.sort()
-
-                       #build list of which fds will be where, and where they are at currently
-                       for x in k:
-                               trg_fd.append(x)
-                               src_fd.append(fd_pipes[x])
-
-                       # run through said list dup'ing descriptors so that they won't be waxed
-                       # by other dup calls.
-                       for x in range(0,len(trg_fd)):
-                               if trg_fd[x] == src_fd[x]:
-                                       continue
-                               if trg_fd[x] in src_fd[x+1:]:
-                                       new=os.dup2(trg_fd[x],max(src_fd) + 1)
-                                       os.close(trg_fd[x])
-                                       try:
-                                               while True:
-                                                       src_fd[s.index(trg_fd[x])]=new
-                                       except SystemExit, e:
-                                               raise
-                                       except:
-                                               pass
-
-                       # transfer the fds to their final pre-exec position.
-                       for x in range(0,len(trg_fd)):
-                               if trg_fd[x] != src_fd[x]:
-                                       os.dup2(src_fd[x], trg_fd[x])
-               else:
-                       trg_fd=[0,1,2]
-
-               # wax all open descriptors that weren't requested be left open.
-               for x in range(0,max_fd_limit):
-                       if x not in trg_fd:
-                               try:
-                                       os.close(x)
-                                except SystemExit, e:
-                                        raise
-                                except:
-                                        pass
-
-                # note this order must be preserved- can't change gid/groups if you change uid first.
-                if selinux_capable and selinux_context:
-                        import selinux
-                        selinux.setexec(selinux_context)
-                if gid:
-                        os.setgid(gid)
-                if groups:
-                        os.setgroups(groups)
-                if uid:
-                        os.setuid(uid)
-                if umask:
-                        os.umask(umask)
-                else:
-                        os.umask(022)
-
-                try:
-                        #print "execing", myc, myargs
-                        if func_call:
-                                # either use a passed in func for interpretting the results, or return if no exception.
-                                # note the passed in list, and dict are expanded.
-                                if len(mycommand) == 4:
-                                        os._exit(mycommand[3](mycommand[0](*mycommand[1],**mycommand[2])))
-                                try:
-                                        mycommand[0](*mycommand[1],**mycommand[2])
-                                except Exception,e:
-                                        print "caught exception",e," in forked func",mycommand[0]
-                                sys.exit(0)
-
-                       #os.execvp(myc,myargs)
-                        os.execve(myc,myargs,env)
-                except SystemExit, e:
-                        raise
-                except Exception, e:
-                        if not func_call:
-                                raise str(e)+":\n   "+myc+" "+"".join(myargs)
-                        print "func call failed"
-
-                # If the execve fails, we need to report it, and exit
-                # *carefully* --- report error here
-                os._exit(1)
-                sys.exit(1)
-                return # should never get reached
-
-        # if we were logging, kill the pipes.
-        if logfile:
-                os.close(pr)
-                os.close(pw)
-
-        if returnpid:
-                return mypid
-
-        # loop through pids (typically one, unless logging), either waiting on their death, or waxing them
-        # if the main pid (mycommand) returned badly.
-        while len(mypid):
-                retval=os.waitpid(mypid[-1],0)[1]
-                if retval != 0:
-                        cleanup(mypid[0:-1],block_exceptions=False)
-                        # at this point we've killed all other kid pids generated via this call.
-                        # return now.
-                        if raw_exit_code:
-                                return retval
-                        return process_exit_code(retval,throw_signals=raise_signals)
-                else:
-                        mypid.pop(-1)
-        cleanup(mypid)
-        return 0
-
-def cmd(mycmd,myexc="",env={}):
-       try:
-               sys.stdout.flush()
-               retval=spawn_bash(mycmd,env)
-               if retval != 0:
-                       raise CatalystError,myexc
-       except:
-               raise
-
-def process_exit_code(retval,throw_signals=False):
-        """process a waitpid returned exit code, returning exit code if it exit'd, or the
-        signal if it died from signalling
-        if throw_signals is on, it raises a SystemExit if the process was signaled.
-        This is intended for usage with threads, although at the moment you can't signal individual
-        threads in python, only the master thread, so it's a questionable option."""
-        if (retval & 0xff)==0:
-                return retval >> 8 # return exit code
-        else:
-                if throw_signals:
-                        #use systemexit, since portage is stupid about exception catching.
-                        raise SystemExit()
-                return (retval & 0xff) << 8 # interrupted by signal
-
-
 def file_locate(settings,filelist,expand=1):
        #if expand=1, non-absolute paths will be accepted and
        # expanded to os.getcwd()+"/"+localpath if file exists
index 56499077df0475c4b38bf2b849bbfe42713a1b57..aa90dd02905ad970568e14fd4dc3d6ea9797e6e9 100644 (file)
@@ -13,6 +13,7 @@ import catalyst.arch
 from catalyst.output import warn
 import catalyst.util
 import catalyst.hash
+from catalyst.error import *
 
 class generic_stage_target(generic_target):
 
index 77a67607bfef9ac863054c5dbd8f0fcb2cadd999..a98bff9ead409c0237e74f2727f09c92640ebcd7 100644 (file)
@@ -7,6 +7,7 @@ import os,types,glob
 from catalyst.support import *
 from generic_stage import *
 import catalyst.util
+from catalyst.error import *
 
 class grp_target(generic_stage_target):
        def __init__(self,spec,addlargs):
index 91f51cc8a8b3218347c16a356a055603450debf5..74c865fc4895b5186a87cd80f52ca0c697d32115 100644 (file)
@@ -8,6 +8,7 @@ from catalyst.support import *
 from generic_stage import *
 import catalyst.util
 import catalyst.hash
+from catalyst.error import *
 
 class livecd_stage2_target(generic_stage_target):
        def __init__(self,spec,addlargs):
index 864ffe9931682fda1f1bca07e39608f4f9072653..970f70635726a22818b1b3425bd3507e04e70a07 100644 (file)
@@ -7,6 +7,7 @@ import os,string,types
 from catalyst.support import *
 from generic_stage import *
 import catalyst.util
+from catalyst.error import *
 
 class netboot_target(generic_stage_target):
        def __init__(self,spec,addlargs):
index 07886619b80e21bce21eb0740e78580a6100c525..eaaf34595933de73689471579f0c4606bd1ca771 100644 (file)
@@ -7,6 +7,7 @@ import os,string,types
 from catalyst.support import *
 from generic_stage import *
 import catalyst.util
+from catalyst.error import *
 
 class netboot2_target(generic_stage_target):
        def __init__(self,spec,addlargs):
index 7b4a6f3094a23df7a4b3c366b2d7dd0e8f8742b7..0dbe0a82c0024204a6addcfc2d614c4b70f2b110 100644 (file)
@@ -6,6 +6,7 @@ builder class for the tinderbox target
 from catalyst.support import *
 from generic_stage import *
 import catalyst.util
+from catalyst.error import *
 
 class tinderbox_target(generic_stage_target):
        def __init__(self,spec,addlargs):
index e715ed74963712558abb30d930aff8d74a7267ad..b97d1f1b228155d69580a10153466ec949cc00d5 100644 (file)
@@ -3,6 +3,7 @@ Collection of utility functions for catalyst
 """
 
 import sys, traceback, os, os.path
+from catalyst.error import *
 
 def capture_traceback():
        etype, value, tb = sys.exc_info()