if len(sys.argv)==1 or sys.argv[1] in ["-h","--help"]:
usage()
sys.exit(1)
-"""
-Overview of catalyst operation
-==============================
-
-* The program starts, and the local machine type is detected.
-
-* Based on this information, catalyst determines what kind of machine types
- it can build for (amd64 and ia64 can build for x86 as well, for example.)
- The appropriate arch plugins are loaded, which contain builder classes
- for each supported sub-arch.
-
-* Command-line arguments are parsed. If specified, a spec file is read.
-
-* These build variables are stored in an internal "spec" object, which will
- be a standard python dictionary. This spec dictionary contains all relevant
- build-related information.
-
-* The spec object is passed to the appropriate target constructor.
- The target constructor updates the spec object to contain data relevant
- to the particular target (stage1, stage3, grp, etc.)
-
-*** PROTOTYPE CODE UP TO HERE IS COMPLETE (drobbins, 26 Oct '03)
-
-* The full data of the spec object is written to disc, so there is a complete
- record of all variables that will be used to build what we're building. This
- will allow for another person to re-use this information to replicate our
- work (it should be possible to distribute a spec file along with a portage
- snapshot and a starter tarball, and our build can be replicated exactly on
- any machine.) The spec object contains data like CFLAGS, CHOST, subarch,
- mainarch, the profile used to build, and for GRP and LiveCDs the complete
- package build list. This is important to allow work to be replicated. It's
- possible that the stage1/2/3.sh and other scripts should be distributed as
- well, to allow proper replication of work.
-
-* The build process begins by calling the appropriate method of the builder
- instance. This includes cleanup, setup of chroot, entering the chroot,
- running the appropriate bash build script, checking for error conditions,
- and finishing up.
-
-* The catalyst process is now complete :)
-"""
-
-#map current machine information from uname() to the mainarch we are running
-#under
import targets
targetmap={}
myspec["storedir"]="/var/tmp/catalyst"
myspec["sharedir"]="/usr/share/catalyst"
#these would come from there too?:
-myspec["distdir"]="/usr/portage/distfiles"
+myspec["distdir"]="/mnt/misc/distfiles"
myspec["portdir"]="/usr/portage"
-#all the main program needs to do is figure out the target. The rest of the args go to the
-#target constructor
-
-#call target constructor, pass our "myspec" settings as well as cmdline arguments for parsing
-
-addlargs={}
-arg_parse(myspec,addlargs)
-if not targetmap.has_key(myspec["target"]):
- raise CatalystError,"Target \""+myspec["target"]+"\" not available."
-mytarget=targetmap[myspec["target"]](myspec,addlargs)
-mytarget.run()
-
+#determine target, call target constructor and hand it the rest of the arguments
+
+try:
+ addlargs={}
+ arg_parse(myspec,addlargs)
+ if not targetmap.has_key(myspec["target"]):
+ raise CatalystError,"Target \""+myspec["target"]+"\" not available."
+ mytarget=targetmap[myspec["target"]](myspec,addlargs)
+
+ #let's display our spec information in all its glory
+ print
+ spec_dump(myspec)
+ print
+
+ mytarget.run()
+except CatalystError:
+ sys.exit(1)
+# Examples:
# ./catalyst subarch=pentium4 version_stamp=20031016 target=stage3 rel_type=default rel_version=1.4 snapshot=20031016 source_subpath=default-x86-1.4/stage2-pentium4-20031016
-
+# ./catalyst target=snapshot version_stamp=20031028
-import sys,string
+import sys,string,os
config_file_values=["storedir","sharedir","distdir","portdir"]
def __init__(self, message):
if message:
print "catalyst: "+message
- sys.exit(1)
-
def die(msg=None):
- raise CatalystError, msg
+ warn(msg)
+ sys.exit(1)
def warn(msg):
print "catalyst: "+msg
+def ismount(path):
+ "enhanced to handle bind mounts"
+ if os.path.ismount(path):
+ return 1
+ a=open("/proc/mounts","r")
+ mylines=a.readlines()
+ a.close()
+ for line in mylines:
+ mysplit=line.split()
+ if path == mysplit[1]:
+ return 1
+ return 0
+
def arg_parse(mydict,remaining={}):
global config_file_values
for x in sys.argv[1:]:
-import os,stat,string,imp
+import os,stat,string,imp,types
from catalyst_support import *
class generic_target:
self.valid_values=self.required_values
generic_target.__init__(self,addlargs,myspec)
- #ensure we have all required user-supplied settings before proceeding
- for x in requiredspec:
- if not self.settings.has_key(x):
- raise CatalystError, "Required value \""+x+"\" not specified."
-
# map the mainarch we are running under to the mainarches we support for
# building stages and LiveCDs. (for example, on amd64, we can build stages for
# x86 or amd64.
paths=["/usr/portage/packages","/usr/portage/distfiles", "/var/tmp/distfiles", "/proc", "/root/.ccache", "/dev"]
if not os.path.exists(mypath):
return
- mypstat=os.stat(mypath)[stat.ST_DEV]
for x in paths:
if not os.path.exists(mypath+x):
continue
- teststat=os.stat(mypath+x)[stat.ST_DEV]
- if teststat!=mypstat:
+ if ismount(mypath+x):
#something is still mounted
raise CatalystError, x+" is still mounted; aborting."
- return 1
def dir_setup(self):
self.mount_safety_check()
raise CatalystError,"Couldn't bind mount "+x[0]
def unbind(self):
+ ouch=0
+ mypath=self.settings["chroot_path"]
for x in ["/usr/portage/distfiles","/proc","/dev"]:
- retval=os.system("umount "+self.settings["chroot_path"]+x)
+ if not os.path.exists(mypath+x):
+ continue
+ if not ismount(mypath+x):
+ #it's not mounted, continue
+ continue
+ retval=os.system("umount "+mypath+x)
if retval!=0:
- warning("Couldn't umount bind mount: "+self.settings["chroot_path"]+x)
-
- def setup(self):
- #setup will leave everything in unbound state if there is a failure
- self.dir_setup()
+ ouch=1
+ warn("Couldn't umount bind mount: "+mypath+x)
+ #keep trying to umount the others, to minimize damage if developer makes a mistake
+ if ouch:
+ #if any bind mounts really failed, then we need to raise this to potentially prevent
+ #an upcoming bash stage cleanup script from wiping our bind mounts.
+ raise CatalystError,"Couldn't umount one or more bind-mounts; aborting for safety."
+
+ def chroot_setup(self):
self.unpack_and_bind()
+ retval=os.system("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc")
+ if retval!=0:
+ raise CatalystError,"Could not copy resolv.conf into place."
+ def clean(self):
+ "do not call without first unbinding"
+ retval=os.system("rm "+self.settings["chroot_path"]+"/etc/resolv.conf")
+ if retval!=0:
+ raise CatalystError,"Could not clean up resolv.conf."
+ retval=os.system(self.settings["storedir"]+"/targets/"+self.settings["target"]+"/"+self.settings["target"]+".sh clean")
+ if retval!=0:
+ raise CatalystError,"clean script failed."
+
def run(self):
- self.setup()
+ self.dir_setup()
+ self.chroot_setup()
+ #modify the current environment. This is an ugly hack that should be fixed. We need this
+ #to use the os.system() call since we can't specify our own environ:
+ for x in self.settings.keys():
+ if type(self.settings[x])==types.StringType:
+ os.environ[x]=self.settings[x]
try:
- pass
+ retval=os.system(self.settings["storedir"]+"/targets/"+self.settings["target"]+"/"+self.settings["target"]+".sh run")
+ if retval!=0:
+ raise CatalystError,"build script failed."
finally:
- #always unbind
self.unbind()
-
+ self.clean()
+
+
class snapshot_target(generic_target):
def __init__(self,myspec,addlargs):
self.valid_values=["version_stamp","target"]
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo/src/catalyst/targets/stage2/Attic/stage2.sh,v 1.1 2003/10/15 05:23:14 zhen Exp $
+# $Header: /var/cvsroot/gentoo/src/catalyst/targets/stage2/Attic/stage2.sh,v 1.2 2003/10/28 22:09:23 drobbins Exp $
-$CHROOT . /bin/bash << EOF
+case $1 in
+run)
+ $CHROOT . /bin/bash << EOF
env-update
source /etc/profile
mkdir -p /usr/portage/packages/All
/usr/portage/scripts/bootstrap.sh || exit 1
EOF
-
-[ $? -ne 0 ] && die "Stage 2 build failure"
-
+ [ $? -ne 0 ] && exit 1
+ ;;
+clean)
+ # we need to have catalyst un-bind-mount things before
+ # we clean up.
+ $CHROOT . /bin/bash << EOF
+ if [ ${CCACHE} -eq 1 ]
+ then
+ emerge -C ccache
+ fi
+ rm -rf /usr/portage
+ rm -rf /tmp/*
+EOF
+ [ $? -ne 0 ] && exit 1
+ ;;
+*)
+ exit 1
+ ;;
+esac
# Copyright 1999-2003 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo/src/catalyst/targets/stage3/Attic/stage3.sh,v 1.1 2003/10/15 05:33:03 zhen Exp $
+# $Header: /var/cvsroot/gentoo/src/catalyst/targets/stage3/Attic/stage3.sh,v 1.2 2003/10/28 22:09:23 drobbins Exp $
-$CHROOT . /bin/bash << EOF
+case $1 in
+enter)
+ $CHROOT $chroot_path
+ ;;
+run)
+ $CHROOT $chroot_path /bin/bash << EOF
env-update
source /etc/profile
- if [ ${CCACHE} -eq 1 ]
+ if [ -n "${CCACHE}" ]
then
emerge --oneshot --nodeps --usepkg --buildpkg ccache || exit 1
fi
- if [ ${REL_TYPE} = "hardened" ]
+ if [ ${rel_type} = "hardened" ]
then
emerge --oneshot --nodeps hardened-gcc || exit 1
fi
export CONFIG_PROTECT="-*"
emerge system --usepkg --buildpkg || exit 1
EOF
-
-[ $? -ne 0 ] && die "Stage 3 build failure"
-
+ [ $? -ne 0 ] && exit 1
+ ;;
+clean)
+ $CHROOT $chroot_path /bin/bash << EOF
+ env-update
+ source /etc/profile
+ if [ -n "${CCACHE}" ]
+ then
+ emerge -C ccache || exit 1
+ fi
+EOF
+ [ $? -ne 0 ] && exit 1
+ ;;
+*)
+ exit 1
+ ;;
+esac