From 0693a0472f1c722459cea27a23dedf84aed5bbd7 Mon Sep 17 00:00:00 2001 From: Andrew Gaffney Date: Sun, 11 Jan 2009 16:59:14 -0600 Subject: [PATCH] Move custom exception classes to catalyst.error and all spawn-related functions to catalyst.spawn --- ChangeLog | 12 + catalyst | 3 +- modules/catalyst/arch/powerpc.py | 1 + modules/catalyst/arch/sparc.py | 1 + modules/catalyst/arch/x86.py | 1 + modules/catalyst/config.py | 1 + modules/catalyst/error.py | 29 ++ modules/catalyst/hash.py | 1 + modules/catalyst/spawn.py | 304 +++++++++++++++++++++ modules/catalyst/support.py | 321 +---------------------- modules/catalyst/target/generic_stage.py | 1 + modules/catalyst/target/grp.py | 1 + modules/catalyst/target/livecd_stage2.py | 1 + modules/catalyst/target/netboot.py | 1 + modules/catalyst/target/netboot2.py | 1 + modules/catalyst/target/tinderbox.py | 1 + modules/catalyst/util.py | 1 + 17 files changed, 361 insertions(+), 320 deletions(-) create mode 100644 modules/catalyst/error.py create mode 100644 modules/catalyst/spawn.py diff --git a/ChangeLog b/ChangeLog index dfd9f24c..a0ff5b87 100644 --- 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 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 +modules/catalyst/hash.py, modules/catalyst/support.py, modules/catalyst/target/generic_stage.py, diff --git a/catalyst b/catalyst index ee8eb83e..35da3446 100755 --- 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 " __version__="2.99" diff --git a/modules/catalyst/arch/powerpc.py b/modules/catalyst/arch/powerpc.py index 50c848dc..ea28b04c 100644 --- a/modules/catalyst/arch/powerpc.py +++ b/modules/catalyst/arch/powerpc.py @@ -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" diff --git a/modules/catalyst/arch/sparc.py b/modules/catalyst/arch/sparc.py index 9404caf3..30c93240 100644 --- a/modules/catalyst/arch/sparc.py +++ b/modules/catalyst/arch/sparc.py @@ -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" diff --git a/modules/catalyst/arch/x86.py b/modules/catalyst/arch/x86.py index 960c6e1d..6c45b343 100644 --- a/modules/catalyst/arch/x86.py +++ b/modules/catalyst/arch/x86.py @@ -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" diff --git a/modules/catalyst/config.py b/modules/catalyst/config.py index 6f53bdd2..746a2c68 100644 --- a/modules/catalyst/config.py +++ b/modules/catalyst/config.py @@ -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 index 00000000..cc22e9b6 --- /dev/null +++ b/modules/catalyst/error.py @@ -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 + diff --git a/modules/catalyst/hash.py b/modules/catalyst/hash.py index 44c272de..7392010e 100644 --- a/modules/catalyst/hash.py +++ b/modules/catalyst/hash.py @@ -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 index 00000000..a6d37150 --- /dev/null +++ b/modules/catalyst/spawn.py @@ -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 + + diff --git a/modules/catalyst/support.py b/modules/catalyst/support.py index 7c67d59c..35d0bb6d 100644 --- a/modules/catalyst/support.py +++ b/modules/catalyst/support.py @@ -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 diff --git a/modules/catalyst/target/generic_stage.py b/modules/catalyst/target/generic_stage.py index 56499077..aa90dd02 100644 --- a/modules/catalyst/target/generic_stage.py +++ b/modules/catalyst/target/generic_stage.py @@ -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): diff --git a/modules/catalyst/target/grp.py b/modules/catalyst/target/grp.py index 77a67607..a98bff9e 100644 --- a/modules/catalyst/target/grp.py +++ b/modules/catalyst/target/grp.py @@ -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): diff --git a/modules/catalyst/target/livecd_stage2.py b/modules/catalyst/target/livecd_stage2.py index 91f51cc8..74c865fc 100644 --- a/modules/catalyst/target/livecd_stage2.py +++ b/modules/catalyst/target/livecd_stage2.py @@ -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): diff --git a/modules/catalyst/target/netboot.py b/modules/catalyst/target/netboot.py index 864ffe99..970f7063 100644 --- a/modules/catalyst/target/netboot.py +++ b/modules/catalyst/target/netboot.py @@ -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): diff --git a/modules/catalyst/target/netboot2.py b/modules/catalyst/target/netboot2.py index 07886619..eaaf3459 100644 --- a/modules/catalyst/target/netboot2.py +++ b/modules/catalyst/target/netboot2.py @@ -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): diff --git a/modules/catalyst/target/tinderbox.py b/modules/catalyst/target/tinderbox.py index 7b4a6f30..0dbe0a82 100644 --- a/modules/catalyst/target/tinderbox.py +++ b/modules/catalyst/target/tinderbox.py @@ -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): diff --git a/modules/catalyst/util.py b/modules/catalyst/util.py index e715ed74..b97d1f1b 100644 --- a/modules/catalyst/util.py +++ b/modules/catalyst/util.py @@ -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() -- 2.26.2