#!/usr/bin/python2 -OO # Maintained in full by: # Catalyst Team # Release Engineering Team # Andrew Gaffney # Chris Gianelloni # $Id$ import os import sys import imp import string import getopt import pdb import os.path import modules.catalyst.config import modules.catalyst.util __maintainer__="Catalyst " __version__="2.0.15" conf_values={} def usage(): print "Usage catalyst [options] [-C variable=value...] [ -s identifier]" print " -a --clear-autoresume clear autoresume flags" print " -c --config use specified configuration file" print " -C --cli catalyst commandline (MUST BE LAST OPTION)" print " -d --debug enable debugging" print " -f --file read specfile" print " -F --fetchonly fetch files only" print " -h --help print this help message" print " -p --purge clear tmp dirs,package cache and autoresume flags" print " -P --purgeonly clear tmp dirs,package cache and autoresume flags and exit" print " -T --purgetmponly clear tmp dirs and autoresume flags and exit" print " -s --snapshot generate a release snapshot" print " -V --version display version information" print " -v --verbose verbose output" print print "Usage examples:" print print "Using the commandline option (-C, --cli) to build a Portage snapshot:" print "catalyst -C target=snapshot version_stamp=my_date" print print "Using the snapshot option (-s, --snapshot) to build a release snapshot:" print "catalyst -s 20071121" print print "Using the specfile option (-f, --file) to build a stage target:" print "catalyst -f stage1-specfile.spec" def version(): print "Catalyst, version "+__version__ print "Copyright 2003-2008 Gentoo Foundation" print "Copyright 2008-2012 various authors" print "Distributed under the GNU General Public License version 2.1\n" def parse_config(myconfig): # search a couple of different areas for the main config file myconf={} config_file="" confdefaults={ "storedir":"/var/tmp/catalyst",\ "sharedir":"/usr/share/catalyst","distdir":"/usr/portage/distfiles",\ "portdir":"/usr/portage","options":"",\ "snapshot_cache":"/var/tmp/catalyst/snapshot_cache",\ "hash_function":"crc32"} # first, try the one passed (presumably from the cmdline) if myconfig: if os.path.exists(myconfig): print "Using command line specified Catalyst configuration file, "+myconfig config_file=myconfig else: print "!!! catalyst: Could not use specified configuration file "+\ myconfig sys.exit(1) # next, try the default location elif os.path.exists("/etc/catalyst/catalyst.conf"): print "Using default Catalyst configuration file, /etc/catalyst/catalyst.conf" config_file="/etc/catalyst/catalyst.conf" # can't find a config file (we are screwed), so bail out else: print "!!! catalyst: Could not find a suitable configuration file" sys.exit(1) # now, try and parse the config file "config_file" try: # execfile(config_file, myconf, myconf) myconfig = modules.catalyst.config.ConfigParser(config_file) myconf.update(myconfig.get_values()) except: print "!!! catalyst: Unable to parse configuration file, "+myconfig sys.exit(1) # now, load up the values into conf_values so that we can use them for x in confdefaults.keys(): if x in myconf: print "Setting",x,"to config file value \""+myconf[x]+"\"" conf_values[x]=myconf[x] else: print "Setting",x,"to default value \""+confdefaults[x]+"\"" conf_values[x]=confdefaults[x] # parse out the rest of the options from the config file if "autoresume" in string.split(conf_values["options"]): print "Autoresuming support enabled." conf_values["AUTORESUME"]="1" if "bindist" in string.split(conf_values["options"]): print "Binary redistribution enabled" conf_values["BINDIST"]="1" else: print "Bindist is not enabled in catalyst.conf" print "Binary redistribution of generated stages/isos may be prohibited by law." print "Please see the use description for bindist on any package you are including." if "ccache" in string.split(conf_values["options"]): print "Compiler cache support enabled." conf_values["CCACHE"]="1" if "clear-autoresume" in string.split(conf_values["options"]): print "Cleaning autoresume flags support enabled." conf_values["CLEAR_AUTORESUME"]="1" if "distcc" in string.split(conf_values["options"]): print "Distcc support enabled." conf_values["DISTCC"]="1" if "icecream" in string.split(conf_values["options"]): print "Icecream compiler cluster support enabled." conf_values["ICECREAM"]="1" if "kerncache" in string.split(conf_values["options"]): print "Kernel cache support enabled." conf_values["KERNCACHE"]="1" if "pkgcache" in string.split(conf_values["options"]): print "Package cache support enabled." conf_values["PKGCACHE"]="1" if "preserve_libs" in string.split(conf_values["options"]): print "Preserving libs during unmerge." conf_values["PRESERVE_LIBS"]="1" if "purge" in string.split(conf_values["options"]): print "Purge support enabled." conf_values["PURGE"]="1" if "seedcache" in string.split(conf_values["options"]): print "Seed cache support enabled." conf_values["SEEDCACHE"]="1" if "snapcache" in string.split(conf_values["options"]): print "Snapshot cache support enabled." conf_values["SNAPCACHE"]="1" if "digests" in myconf: conf_values["digests"]=myconf["digests"] if "contents" in myconf: conf_values["contents"]=myconf["contents"] if "envscript" in myconf: print "Envscript support enabled." conf_values["ENVSCRIPT"]=myconf["envscript"] if "var_tmpfs_portage" in myconf: conf_values["var_tmpfs_portage"]=myconf["var_tmpfs_portage"]; if "port_logdir" in myconf: conf_values["port_logdir"]=myconf["port_logdir"]; def import_modules(): # import catalyst's own modules (i.e. catalyst_support and the arch modules) targetmap={} try: for x in required_build_targets: try: fh=open(conf_values["sharedir"]+"/modules/"+x+".py") module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE)) fh.close() except IOError: raise CatalystError,"Can't find "+x+".py plugin in "+\ conf_values["sharedir"]+"/modules/" for x in valid_build_targets: try: fh=open(conf_values["sharedir"]+"/modules/"+x+".py") module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE)) module.register(targetmap) fh.close() except IOError: raise CatalystError,"Can't find "+x+".py plugin in "+\ conf_values["sharedir"]+"/modules/" except ImportError: print "!!! catalyst: Python modules not found in "+\ conf_values["sharedir"]+"/modules; exiting." sys.exit(1) return targetmap def build_target(addlargs, targetmap): try: if addlargs["target"] not in targetmap: raise CatalystError,"Target \""+addlargs["target"]+"\" not available." mytarget=targetmap[addlargs["target"]](conf_values, addlargs) mytarget.run() except: modules.catalyst.util.print_traceback() print "!!! catalyst: Error encountered during run of target " + addlargs["target"] sys.exit(1) if __name__ == "__main__": targetmap={} version() if os.getuid() != 0: # catalyst cannot be run as a normal user due to chroots, mounts, etc print "!!! catalyst: This script requires root privileges to operate" sys.exit(2) # we need some options in order to work correctly if len(sys.argv) < 2: usage() sys.exit(2) # parse out the command line arguments try: opts,args = getopt.getopt(sys.argv[1:], "apPThvdc:C:f:FVs:", ["purge", "purgeonly", "purgetmponly", "help", "version", "debug",\ "clear-autoresume", "config=", "cli=", "file=", "fetch", "verbose","snapshot="]) except getopt.GetoptError: usage() sys.exit(2) # defaults for commandline opts debug=False verbose=False fetch=False myconfig="" myspecfile="" mycmdline=[] myopts=[] # check preconditions if len(opts) == 0: print "!!! catalyst: please specify one of either -f or -C\n" usage() sys.exit(2) run = False for o, a in opts: if o in ("-h", "--help"): usage() sys.exit(1) if o in ("-V", "--version"): print "Catalyst version "+__version__ sys.exit(1) if o in ("-d", "--debug"): conf_values["DEBUG"]="1" conf_values["VERBOSE"]="1" if o in ("-c", "--config"): myconfig=a if o in ("-C", "--cli"): run = True x=sys.argv.index(o)+1 while x < len(sys.argv): mycmdline.append(sys.argv[x]) x=x+1 if o in ("-f", "--file"): run = True myspecfile=a if o in ("-F", "--fetchonly"): conf_values["FETCH"]="1" if o in ("-v", "--verbose"): conf_values["VERBOSE"]="1" if o in ("-s", "--snapshot"): if len(sys.argv) < 3: print "!!! catalyst: missing snapshot identifier\n" usage() sys.exit(2) else: run = True mycmdline.append("target=snapshot") mycmdline.append("version_stamp="+a) if o in ("-p", "--purge"): conf_values["PURGE"] = "1" if o in ("-P", "--purgeonly"): conf_values["PURGEONLY"] = "1" if o in ("-T", "--purgetmponly"): conf_values["PURGETMPONLY"] = "1" if o in ("-a", "--clear-autoresume"): conf_values["CLEAR_AUTORESUME"] = "1" if not run: print "!!! catalyst: please specify one of either -f or -C\n" usage() sys.exit(2) # import configuration file and import our main module using those settings parse_config(myconfig) sys.path.append(conf_values["sharedir"]+"/modules") from catalyst_support import * # Start checking that digests are valid now that the hash_map was imported # from catalyst_support if "digests" in conf_values: for i in conf_values["digests"].split(): if i not in hash_map: print print i+" is not a valid digest entry" print "Valid digest entries:" print hash_map.keys() print print "Catalyst aborting...." sys.exit(2) if find_binary(hash_map[i][1]) == None: print print "digest="+i print "\tThe "+hash_map[i][1]+\ " binary was not found. It needs to be in your system path" print print "Catalyst aborting...." sys.exit(2) if "hash_function" in conf_values: if conf_values["hash_function"] not in hash_map: print print conf_values["hash_function"]+\ " is not a valid hash_function entry" print "Valid hash_function entries:" print hash_map.keys() print print "Catalyst aborting...." sys.exit(2) if find_binary(hash_map[conf_values["hash_function"]][1]) == None: print print "hash_function="+conf_values["hash_function"] print "\tThe "+hash_map[conf_values["hash_function"]][1]+\ " binary was not found. It needs to be in your system path" print print "Catalyst aborting...." sys.exit(2) # import the rest of the catalyst modules targetmap=import_modules() addlargs={} if myspecfile: spec = modules.catalyst.config.SpecParser(myspecfile) addlargs.update(spec.get_values()) if mycmdline: try: cmdline = modules.catalyst.config.ConfigParser() cmdline.parse_lines(mycmdline) addlargs.update(cmdline.get_values()) except CatalystError: print "!!! catalyst: Could not parse commandline, exiting." sys.exit(1) if "target" not in addlargs: raise CatalystError, "Required value \"target\" not specified." # everything is setup, so the build is a go try: build_target(addlargs, targetmap) except CatalystError: print print "Catalyst aborting...." sys.exit(2) except KeyboardInterrupt: print "\nCatalyst build aborted due to user interrupt ( Ctrl-C )" print print "Catalyst aborting...." sys.exit(2) except LockInUse: print "Catalyst aborting...." sys.exit(2) except: print "Catalyst aborting...." raise sys.exit(2)