lots of improvements
authorDaniel Robbins <drobbins@gentoo.org>
Tue, 28 Oct 2003 22:09:23 +0000 (22:09 +0000)
committerDaniel Robbins <drobbins@gentoo.org>
Tue, 28 Oct 2003 22:09:23 +0000 (22:09 +0000)
git-svn-id: svn+ssh://svn.gentoo.org/var/svnroot/catalyst/trunk@31 d1e1f19c-881f-0410-ab34-b69fee027534

catalyst
modules/catalyst_support.py
modules/targets.py
targets/stage2/stage2.sh
targets/stage3/stage3.sh

index b00f1c96cb3d78cdd89fa7847383545f1a312f0e..a209ffe294a2fb3b8bb9cadb31ddab1a64f61451 100755 (executable)
--- a/catalyst
+++ b/catalyst
@@ -13,50 +13,6 @@ def usage():
 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={}
@@ -73,20 +29,26 @@ myspec={}
 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
index afc559d27a3a782431c40e9d6ea6f62cf1afe568..ad171679a33c2ee7a56b3622c0d915e5562c5adf 100644 (file)
@@ -1,4 +1,4 @@
-import sys,string
+import sys,string,os
 
 config_file_values=["storedir","sharedir","distdir","portdir"]
 
@@ -6,14 +6,26 @@ class CatalystError(Exception):
        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:]:
index 934622af355b7a6d5937d285a687b1bac1b7dec2..9a86501e9a0231452c88ac3486d761ca8d4b8545 100644 (file)
@@ -1,4 +1,4 @@
-import os,stat,string,imp
+import os,stat,string,imp,types
 from catalyst_support import *
 
 class generic_target:
@@ -16,11 +16,6 @@ class generic_stage_target(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.
@@ -74,15 +69,12 @@ class generic_stage_target(generic_target):
                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()
@@ -111,24 +103,56 @@ class generic_stage_target(generic_target):
                                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"]
index 4e5d90d0db12d2a8c88e56e61edb62cc7d4dbe13..fd3e02727a3bd6d7ce7081d80f40391e3fa53bd8 100755 (executable)
@@ -1,8 +1,10 @@
 # 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
@@ -14,6 +16,22 @@ $CHROOT . /bin/bash << EOF
 
        /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
index 864d06303f4afb1f0036f1213f4cbe5e6e513006..d913fb577aeb0988df8772e3c650a373b9cad360 100755 (executable)
@@ -1,21 +1,40 @@
 # 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