modules/generic_stage_target.py: Use 'portdir' instead of hard-coding '/usr/portage'
[catalyst.git] / modules / generic_stage_target.py
index ec032922746c5d002fbdee82171dd0e886f37064..0803a8c3185a5dd01cc7efc29cc079409d65b204 100644 (file)
@@ -1,9 +1,3 @@
-
-"""
-This class does all of the chroot setup, copying of files, etc. It is
-the driver class for pretty much everything that Catalyst does.
-"""
-
 import os,string,imp,types,shutil
 from catalyst_support import *
 from generic_target import *
@@ -11,7 +5,10 @@ from stat import *
 import catalyst_lock
 
 class generic_stage_target(generic_target):
-
+       """
+       This class does all of the chroot setup, copying of files, etc. It is
+       the driver class for pretty much everything that Catalyst does.
+       """
        def __init__(self,myspec,addlargs):
                self.required_values.extend(["version_stamp","target","subarch",\
                        "rel_type","profile","snapshot","source_subpath"])
@@ -81,21 +78,21 @@ class generic_stage_target(generic_target):
                                msg("Can't find/load "+x+".py plugin in "+\
                                        self.settings["sharedir"]+"/arch/")
 
-               if self.settings.has_key("chost"):
+               if "chost" in self.settings:
                        hostmachine = self.settings["chost"].split("-")[0]
-                       if not machinemap.has_key(hostmachine):
+                       if hostmachine not in machinemap:
                                raise CatalystError, "Unknown host machine type "+hostmachine
                        self.settings["hostarch"]=machinemap[hostmachine]
                else:
                        hostmachine = self.settings["subarch"]
-                       if machinemap.has_key(hostmachine):
+                       if hostmachine in machinemap:
                                hostmachine = machinemap[hostmachine]
                        self.settings["hostarch"]=hostmachine
-               if self.settings.has_key("cbuild"):
+               if "cbuild" in self.settings:
                        buildmachine = self.settings["cbuild"].split("-")[0]
                else:
                        buildmachine = os.uname()[4]
-               if not machinemap.has_key(buildmachine):
+               if buildmachine not in machinemap:
                        raise CatalystError, "Unknown build machine type "+buildmachine
                self.settings["buildarch"]=machinemap[buildmachine]
                self.settings["crosscompile"]=(self.settings["hostarch"]!=\
@@ -172,19 +169,19 @@ class generic_stage_target(generic_target):
                file_locate(self.settings,["source_path","snapshot_path","distdir"],\
                        expand=0)
                """ If we are using portage_confdir, check that as well. """
-               if self.settings.has_key("portage_confdir"):
+               if "portage_confdir" in self.settings:
                        file_locate(self.settings,["portage_confdir"],expand=0)
 
                """ Setup our mount points """
-               if self.settings.has_key("SNAPCACHE"):
-                       self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
+               if "SNAPCACHE" in self.settings:
+                       self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles","/var/tmp/portage"]
                        self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
                                "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
-                               "/usr/portage/distfiles":self.settings["distdir"]}
+                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
                else:
-                       self.mounts=["/proc","/dev","/usr/portage/distfiles"]
+                       self.mounts=["/proc","/dev","/usr/portage/distfiles","/var/tmp/portage"]
                        self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
-                               "/usr/portage/distfiles":self.settings["distdir"]}
+                               "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
                if os.uname()[0] == "Linux":
                        self.mounts.append("/dev/pts")
 
@@ -194,7 +191,7 @@ class generic_stage_target(generic_target):
                Configure any user specified options (either in catalyst.conf or on
                the command line).
                """
-               if self.settings.has_key("PKGCACHE"):
+               if "PKGCACHE" in self.settings:
                        self.set_pkgcache_path()
                        print "Location of the package cache is "+\
                                self.settings["pkgcache_path"]
@@ -202,15 +199,15 @@ class generic_stage_target(generic_target):
                        self.mountmap["/usr/portage/packages"]=\
                                self.settings["pkgcache_path"]
 
-               if self.settings.has_key("KERNCACHE"):
+               if "KERNCACHE" in self.settings:
                        self.set_kerncache_path()
                        print "Location of the kerncache is "+\
                                self.settings["kerncache_path"]
                        self.mounts.append("/tmp/kerncache")
                        self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
 
-               if self.settings.has_key("CCACHE"):
-                       if os.environ.has_key("CCACHE_DIR"):
+               if "CCACHE" in self.settings:
+                       if "CCACHE_DIR" in os.environ:
                                ccdir=os.environ["CCACHE_DIR"]
                                del os.environ["CCACHE_DIR"]
                        else:
@@ -224,33 +221,39 @@ class generic_stage_target(generic_target):
                        """ for the chroot: """
                        self.env["CCACHE_DIR"]="/var/tmp/ccache"
 
-               if self.settings.has_key("ICECREAM"):
+               if "ICECREAM" in self.settings:
                        self.mounts.append("/var/cache/icecream")
                        self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
                        self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
 
+               if "port_logdir" in self.settings:
+                       self.mounts.append("/var/log/portage")
+                       self.mountmap["/var/log/portage"]=self.settings["port_logdir"]
+                       self.env["PORT_LOGDIR"]="/var/log/portage"
+                       self.env["PORT_LOGDIR_CLEAN"]='find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
+
        def override_cbuild(self):
-               if self.makeconf.has_key("CBUILD"):
+               if "CBUILD" in self.makeconf:
                        self.settings["CBUILD"]=self.makeconf["CBUILD"]
 
        def override_chost(self):
-               if self.makeconf.has_key("CHOST"):
+               if "CHOST" in self.makeconf:
                        self.settings["CHOST"]=self.makeconf["CHOST"]
 
        def override_cflags(self):
-               if self.makeconf.has_key("CFLAGS"):
+               if "CFLAGS" in self.makeconf:
                        self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
 
        def override_cxxflags(self):
-               if self.makeconf.has_key("CXXFLAGS"):
+               if "CXXFLAGS" in self.makeconf:
                        self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
 
        def override_ldflags(self):
-               if self.makeconf.has_key("LDFLAGS"):
+               if "LDFLAGS" in self.makeconf:
                        self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
 
        def set_install_mask(self):
-               if self.settings.has_key("install_mask"):
+               if "install_mask" in self.settings:
                        if type(self.settings["install_mask"])!=types.StringType:
                                self.settings["install_mask"]=\
                                        string.join(self.settings["install_mask"])
@@ -272,7 +275,7 @@ class generic_stage_target(generic_target):
                                "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
 
        def set_pkgcache_path(self):
-               if self.settings.has_key("pkgcache_path"):
+               if "pkgcache_path" in self.settings:
                        if type(self.settings["pkgcache_path"])!=types.StringType:
                                self.settings["pkgcache_path"]=\
                                        normpath(string.join(self.settings["pkgcache_path"]))
@@ -282,7 +285,7 @@ class generic_stage_target(generic_target):
                                self.settings["target_subpath"]+"/")
 
        def set_kerncache_path(self):
-               if self.settings.has_key("kerncache_path"):
+               if "kerncache_path" in self.settings:
                        if type(self.settings["kerncache_path"])!=types.StringType:
                                self.settings["kerncache_path"]=\
                                        normpath(string.join(self.settings["kerncache_path"]))
@@ -293,7 +296,7 @@ class generic_stage_target(generic_target):
        def set_target_path(self):
                self.settings["target_path"]=normpath(self.settings["storedir"]+\
                        "/builds/"+self.settings["target_subpath"]+".tar.bz2")
-               if self.settings.has_key("AUTORESUME")\
+               if "AUTORESUME" in self.settings\
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "setup_target_path"):
                        print \
@@ -301,7 +304,7 @@ class generic_stage_target(generic_target):
                else:
                        """ First clean up any existing target stuff """
                        # XXX WTF are we removing the old tarball before we start building the
-                       # XXX new one? If the build fails, you don't want to be left with 
+                       # XXX new one? If the build fails, you don't want to be left with
                        # XXX nothing at all
 #                      if os.path.isfile(self.settings["target_path"]):
 #                              cmd("rm -f "+self.settings["target_path"],\
@@ -313,31 +316,31 @@ class generic_stage_target(generic_target):
                                os.makedirs(self.settings["storedir"]+"/builds/")
 
        def set_fsscript(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
+               if self.settings["spec_prefix"]+"/fsscript" in self.settings:
                        self.settings["fsscript"]=\
                                self.settings[self.settings["spec_prefix"]+"/fsscript"]
                        del self.settings[self.settings["spec_prefix"]+"/fsscript"]
 
        def set_rcadd(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
+               if self.settings["spec_prefix"]+"/rcadd" in self.settings:
                        self.settings["rcadd"]=\
                                self.settings[self.settings["spec_prefix"]+"/rcadd"]
                        del self.settings[self.settings["spec_prefix"]+"/rcadd"]
 
        def set_rcdel(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
+               if self.settings["spec_prefix"]+"/rcdel" in self.settings:
                        self.settings["rcdel"]=\
                                self.settings[self.settings["spec_prefix"]+"/rcdel"]
                        del self.settings[self.settings["spec_prefix"]+"/rcdel"]
 
        def set_cdtar(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
+               if self.settings["spec_prefix"]+"/cdtar" in self.settings:
                        self.settings["cdtar"]=\
                                normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
                        del self.settings[self.settings["spec_prefix"]+"/cdtar"]
 
        def set_iso(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
+               if self.settings["spec_prefix"]+"/iso" in self.settings:
                        if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
                                self.settings["iso"]=\
                                        normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
@@ -350,12 +353,12 @@ class generic_stage_target(generic_target):
                        del self.settings[self.settings["spec_prefix"]+"/iso"]
 
        def set_fstype(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
+               if self.settings["spec_prefix"]+"/fstype" in self.settings:
                        self.settings["fstype"]=\
                                self.settings[self.settings["spec_prefix"]+"/fstype"]
                        del self.settings[self.settings["spec_prefix"]+"/fstype"]
 
-               if not self.settings.has_key("fstype"):
+               if "fstype" not in self.settings:
                        self.settings["fstype"]="normal"
                        for x in self.valid_values:
                                if x ==  self.settings["spec_prefix"]+"/fstype":
@@ -363,15 +366,15 @@ class generic_stage_target(generic_target):
                                                "/fstype is being set to the default of \"normal\"\n"
 
        def set_fsops(self):
-               if self.settings.has_key("fstype"):
+               if "fstype" in self.settings:
                        self.valid_values.append("fsops")
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
+                       if self.settings["spec_prefix"]+"/fsops" in self.settings:
                                self.settings["fsops"]=\
                                        self.settings[self.settings["spec_prefix"]+"/fsops"]
                                del self.settings[self.settings["spec_prefix"]+"/fsops"]
 
        def set_source_path(self):
-               if self.settings.has_key("SEEDCACHE")\
+               if "SEEDCACHE" in self.settings\
                        and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
                                self.settings["source_subpath"]+"/")):
                        self.settings["source_path"]=normpath(self.settings["storedir"]+\
@@ -395,7 +398,7 @@ class generic_stage_target(generic_target):
                                self.settings["source_subpath"]+".tar.bz2\n")
 
        def set_dest_path(self):
-               if self.settings.has_key("root_path"):
+               if "root_path" in self.settings:
                        self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
                                self.settings["root_path"])
                else:
@@ -403,19 +406,27 @@ class generic_stage_target(generic_target):
 
        def set_cleanables(self):
                self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
-                       "/root/*","/usr/portage"]
+                       "/root/*", self.settings["portdir"]]
 
        def set_snapshot_path(self):
                self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-                       "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
+                       "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
 
                if os.path.exists(self.settings["snapshot_path"]):
                        self.settings["snapshot_path_hash"]=\
                                generate_hash(self.settings["snapshot_path"],\
                                hash_function=self.settings["hash_function"],verbose=False)
+               else:
+                       self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
+                               "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
+
+                       if os.path.exists(self.settings["snapshot_path"]):
+                               self.settings["snapshot_path_hash"]=\
+                                       generate_hash(self.settings["snapshot_path"],\
+                                       hash_function=self.settings["hash_function"],verbose=False)
 
        def set_snapcache_path(self):
-               if self.settings.has_key("SNAPCACHE"):
+               if "SNAPCACHE" in self.settings:
                        self.settings["snapshot_cache_path"]=\
                                normpath(self.settings["snapshot_cache"]+"/"+\
                                self.settings["snapshot"]+"/")
@@ -437,7 +448,7 @@ class generic_stage_target(generic_target):
                        "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
                        self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
                        self.settings["version_stamp"]+"/")
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        print "The autoresume path is " + self.settings["autoresume_path"]
                if not os.path.exists(self.settings["autoresume_path"]):
                        os.makedirs(self.settings["autoresume_path"],0755)
@@ -448,36 +459,40 @@ class generic_stage_target(generic_target):
                        "-controller.sh")
 
        def set_iso_volume_id(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
+               if self.settings["spec_prefix"]+"/volid" in self.settings:
                        self.settings["iso_volume_id"]=\
                                self.settings[self.settings["spec_prefix"]+"/volid"]
                        if len(self.settings["iso_volume_id"])>32:
                                raise CatalystError,\
                                        "ISO volume ID must not exceed 32 characters."
                else:
-                       self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"] 
+                       self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
 
        def set_action_sequence(self):
                """ Default action sequence for run method """
                self.settings["action_sequence"]=["unpack","unpack_snapshot",\
-                               "config_profile_link","setup_confdir","portage_overlay",\
+                               "setup_confdir","portage_overlay",\
                                "base_dirs","bind","chroot_setup","setup_environment",\
                                "run_local","preclean","unbind","clean"]
-#              if self.settings.has_key("TARBALL") or \
-#                      not self.settings.has_key("FETCH"):
-               if not self.settings.has_key("FETCH"):
+#              if "TARBALL" in self.settings or \
+#                      "FETCH" not in self.settings:
+               if "FETCH" not in self.settings:
                        self.settings["action_sequence"].append("capture")
                self.settings["action_sequence"].append("clear_autoresume")
 
        def set_use(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
+               if self.settings["spec_prefix"]+"/use" in self.settings:
                        self.settings["use"]=\
                                self.settings[self.settings["spec_prefix"]+"/use"]
                        del self.settings[self.settings["spec_prefix"]+"/use"]
-               if self.settings.has_key("use"):
-                       if type(self.settings["use"])==types.StringType:
-                               self.settings["use"]=self.settings["use"].split()
-                               self.settings["use"].append("bindist")
+               if "use" not in self.settings:
+                       self.settings["use"]=""
+               if type(self.settings["use"])==types.StringType:
+                       self.settings["use"]=self.settings["use"].split()
+
+               # Force bindist when options ask for it
+               if "BINDIST" in self.settings:
+                       self.settings["use"].append("bindist")
 
        def set_stage_path(self):
                self.settings["stage_path"]=normpath(self.settings["chroot_path"])
@@ -489,14 +504,14 @@ class generic_stage_target(generic_target):
                pass
 
        def set_rm(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
+               if self.settings["spec_prefix"]+"/rm" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/rm"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/rm"]=\
                                        self.settings[self.settings["spec_prefix"]+"/rm"].split()
 
        def set_linuxrc(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
+               if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/linuxrc"])==types.StringType:
                                self.settings["linuxrc"]=\
@@ -504,7 +519,7 @@ class generic_stage_target(generic_target):
                                del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
 
        def set_busybox_config(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
+               if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/busybox_config"])==types.StringType:
                                self.settings["busybox_config"]=\
@@ -512,7 +527,7 @@ class generic_stage_target(generic_target):
                                del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
 
        def set_portage_overlay(self):
-               if self.settings.has_key("portage_overlay"):
+               if "portage_overlay" in self.settings:
                        if type(self.settings["portage_overlay"])==types.StringType:
                                self.settings["portage_overlay"]=\
                                        self.settings["portage_overlay"].split()
@@ -520,7 +535,7 @@ class generic_stage_target(generic_target):
                                string.join(self.settings["portage_overlay"])+"\""
 
        def set_overlay(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
+               if self.settings["spec_prefix"]+"/overlay" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/overlay"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/overlay"]=\
@@ -528,7 +543,7 @@ class generic_stage_target(generic_target):
                                        "/overlay"].split()
 
        def set_root_overlay(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
+               if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
                        if type(self.settings[self.settings["spec_prefix"]+\
                                "/root_overlay"])==types.StringType:
                                self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
@@ -540,7 +555,7 @@ class generic_stage_target(generic_target):
                self.settings["root_path"]="/"
 
        def set_valid_build_kernel_vars(self,addlargs):
-               if addlargs.has_key("boot/kernel"):
+               if "boot/kernel" in addlargs:
                        if type(addlargs["boot/kernel"])==types.StringType:
                                loopy=[addlargs["boot/kernel"]]
                        else:
@@ -559,14 +574,14 @@ class generic_stage_target(generic_target):
                                self.valid_values.append("boot/kernel/"+x+"/softlevel")
                                self.valid_values.append("boot/kernel/"+x+"/use")
                                self.valid_values.append("boot/kernel/"+x+"/packages")
-                               if addlargs.has_key("boot/kernel/"+x+"/packages"):
+                               if "boot/kernel/"+x+"/packages" in addlargs:
                                        if type(addlargs["boot/kernel/"+x+\
                                                "/packages"])==types.StringType:
                                                addlargs["boot/kernel/"+x+"/packages"]=\
                                                        [addlargs["boot/kernel/"+x+"/packages"]]
 
        def set_build_kernel_vars(self):
-               if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
+               if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
                        self.settings["gk_mainargs"]=\
                                self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
                        del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
@@ -590,7 +605,7 @@ class generic_stage_target(generic_target):
 
                """
                Check and verify that none of our paths in mypath are mounted. We don't
-               want to clean up with things still mounted, and this allows us to check. 
+               want to clean up with things still mounted, and this allows us to check.
                Returns 1 on ok, 0 on "something is still mounted" case.
                """
 
@@ -620,8 +635,8 @@ class generic_stage_target(generic_target):
                clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
                        "unpack")
 
-               if self.settings.has_key("SEEDCACHE"):
-                       if os.path.isdir(self.settings["source_path"]): 
+               if "SEEDCACHE" in self.settings:
+                       if os.path.isdir(self.settings["source_path"]):
                                """ SEEDCACHE Is a directory, use rsync """
                                unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
                                        " "+self.settings["chroot_path"]
@@ -638,8 +653,12 @@ class generic_stage_target(generic_target):
                                        self.settings["source_path"]+"\nto "+\
                                        self.settings["chroot_path"]+\
                                                " (This may take some time) ...\n"
-                               unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
-                                       self.settings["chroot_path"]
+                               if "bz2" == self.settings["chroot_path"][-3:]:
+                                       unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                               self.settings["chroot_path"]
+                               else:
+                                       unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                               self.settings["chroot_path"]
                                error_msg="Tarball extraction of "+\
                                        self.settings["source_path"]+" to "+\
                                        self.settings["chroot_path"]+" failed."
@@ -649,12 +668,16 @@ class generic_stage_target(generic_target):
                                self.settings["source_path"]+"\nto "+\
                                self.settings["chroot_path"]+\
                                " (This may take some time) ...\n"
-                       unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
-                               self.settings["chroot_path"]
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                       self.settings["chroot_path"]
+                       else:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
+                                       self.settings["chroot_path"]
                        error_msg="Tarball extraction of "+self.settings["source_path"]+\
                                " to "+self.settings["chroot_path"]+" failed."
 
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        if os.path.isdir(self.settings["source_path"]) \
                                and os.path.exists(self.settings["autoresume_path"]+"unpack"):
                                """ Autoresume is valid, SEEDCACHE is valid """
@@ -666,7 +689,7 @@ class generic_stage_target(generic_target):
                                """ Autoresume is valid, tarball is valid """
                                unpack=False
                                invalid_snapshot=True
-                       
+
                        elif os.path.isdir(self.settings["source_path"]) \
                                and not os.path.exists(self.settings["autoresume_path"]+\
                                "unpack"):
@@ -681,7 +704,7 @@ class generic_stage_target(generic_target):
                                invalid_snapshot=True
                else:
                        """ No autoresume, SEEDCACHE """
-                       if self.settings.has_key("SEEDCACHE"):
+                       if "SEEDCACHE" in self.settings:
                                """ SEEDCACHE so let's run rsync and let it clean up """
                                if os.path.isdir(self.settings["source_path"]):
                                        unpack=True
@@ -705,7 +728,7 @@ class generic_stage_target(generic_target):
                        self.mount_safety_check()
 
                        if invalid_snapshot:
-                               if self.settings.has_key("AUTORESUME"):
+                               if "AUTORESUME" in self.settings:
                                        print "No Valid Resume point detected, cleaning up..."
 
                                self.clear_autoresume()
@@ -717,18 +740,18 @@ class generic_stage_target(generic_target):
                        if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
                                os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
 
-                       if self.settings.has_key("PKGCACHE"):
+                       if "PKGCACHE" in self.settings:
                                if not os.path.exists(self.settings["pkgcache_path"]):
                                        os.makedirs(self.settings["pkgcache_path"],0755)
 
-                       if self.settings.has_key("KERNCACHE"):
+                       if "KERNCACHE" in self.settings:
                                if not os.path.exists(self.settings["kerncache_path"]):
                                        os.makedirs(self.settings["kerncache_path"],0755)
 
                        print display_msg
                        cmd(unpack_cmd,error_msg,env=self.env)
 
-                       if self.settings.has_key("source_path_hash"):
+                       if "source_path_hash" in self.settings:
                                myf=open(self.settings["autoresume_path"]+"unpack","w")
                                myf.write(self.settings["source_path_hash"])
                                myf.close()
@@ -742,12 +765,15 @@ class generic_stage_target(generic_target):
                snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
                        "unpack_portage")
 
-               if self.settings.has_key("SNAPCACHE"): 
+               if "SNAPCACHE" in self.settings:
                        snapshot_cache_hash=\
                                read_from_clst(self.settings["snapshot_cache_path"]+\
                                "catalyst-hash")
                        destdir=self.settings["snapshot_cache_path"]
-                       unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
+                       else:
+                               unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
                        unpack_errmsg="Error unpacking snapshot"
                        cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
                                self.settings["snapshot_cache_path"]+\
@@ -759,17 +785,21 @@ class generic_stage_target(generic_target):
                                print "Valid snapshot cache, skipping unpack of portage tree..."
                                unpack=False
                else:
-                       destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
+                       destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
                        cleanup_errmsg="Error removing existing snapshot directory."
                        cleanup_msg=\
                                "Cleaning up existing portage tree (This can take a long time)..."
-                       unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
-                               self.settings["chroot_path"]+"/usr"
+                       if "bz2" == self.settings["chroot_path"][-3:]:
+                               unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
+                                       self.settings["chroot_path"]+"/usr"
+                       else:
+                               unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
+                                       self.settings["chroot_path"]+"/usr"
                        unpack_errmsg="Error unpacking snapshot"
 
-                       if self.settings.has_key("AUTORESUME") \
+                       if "AUTORESUME" in self.settings \
                                and os.path.exists(self.settings["chroot_path"]+\
-                                       "/usr/portage/") \
+                                       self.settings["portdir"]) \
                                and os.path.exists(self.settings["autoresume_path"]\
                                        +"unpack_portage") \
                                and self.settings["snapshot_path_hash"] == snapshot_hash:
@@ -778,7 +808,7 @@ class generic_stage_target(generic_target):
                                        unpack=False
 
                if unpack:
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                self.snapshot_lock_object.write_lock()
                        if os.path.exists(destdir):
                                print cleanup_msg
@@ -790,7 +820,7 @@ class generic_stage_target(generic_target):
                        print "Unpacking portage tree (This can take a long time) ..."
                        cmd(unpack_cmd,unpack_errmsg,env=self.env)
 
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
@@ -800,11 +830,11 @@ class generic_stage_target(generic_target):
                                myf.write(self.settings["snapshot_path_hash"])
                                myf.close()
 
-                       if self.settings.has_key("SNAPCACHE"): 
+                       if "SNAPCACHE" in self.settings:
                                self.snapshot_lock_object.unlock()
 
        def config_profile_link(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "config_profile_link"):
                        print \
@@ -813,33 +843,32 @@ class generic_stage_target(generic_target):
                        # TODO: zmedico and I discussed making this a directory and pushing
                        # in a parent file, as well as other user-specified configuration.
                        print "Configuring profile link..."
-                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
+                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
                                        "Error zapping profile link",env=self.env)
-                       cmd("ln -sf ../usr/portage/profiles/"+\
+                       cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
+                       cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
                                self.settings["target_profile"]+" "+\
-                               self.settings["chroot_path"]+"/etc/make.profile",\
+                               self.settings["chroot_path"]+"/etc/portage/make.profile",\
                                "Error creating profile link",env=self.env)
                        touch(self.settings["autoresume_path"]+"config_profile_link")
 
        def setup_confdir(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "setup_confdir"):
                        print "Resume point detected, skipping setup_confdir operation..."
                else:
-                       if self.settings.has_key("portage_confdir"):
+                       if "portage_confdir" in self.settings:
                                print "Configuring /etc/portage..."
-                               cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
-                                       "Error zapping /etc/portage",env=self.env)
-                               cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
-                                       self.settings["chroot_path"]+"/etc/portage",\
+                               cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
+                                       self.settings["chroot_path"]+"/etc/portage/",\
                                        "Error copying /etc/portage",env=self.env)
                                touch(self.settings["autoresume_path"]+"setup_confdir")
 
        def portage_overlay(self):
                """ We copy the contents of our overlays to /usr/local/portage """
-               if self.settings.has_key("portage_overlay"):
-                       for x in self.settings["portage_overlay"]: 
+               if "portage_overlay" in self.settings:
+                       for x in self.settings["portage_overlay"]:
                                if os.path.exists(x):
                                        print "Copying overlay dir " +x
                                        cmd("mkdir -p "+self.settings["chroot_path"]+\
@@ -851,9 +880,9 @@ class generic_stage_target(generic_target):
 
        def root_overlay(self):
                """ Copy over the root_overlay """
-               if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
+               if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
                        for x in self.settings[self.settings["spec_prefix"]+\
-                               "/root_overlay"]: 
+                               "/root_overlay"]:
                                if os.path.exists(x):
                                        print "Copying root_overlay: "+x
                                        cmd("rsync -a "+x+"/ "+\
@@ -865,15 +894,16 @@ class generic_stage_target(generic_target):
                pass
 
        def bind(self):
-               for x in self.mounts: 
+               for x in self.mounts:
                        if not os.path.exists(self.settings["chroot_path"]+x):
                                os.makedirs(self.settings["chroot_path"]+x,0755)
 
                        if not os.path.exists(self.mountmap[x]):
-                               os.makedirs(self.mountmap[x],0755)
+                               if not self.mountmap[x] == "tmpfs":
+                                       os.makedirs(self.mountmap[x],0755)
 
                        src=self.mountmap[x]
-                       if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
+                       if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                self.snapshot_lock_object.read_lock()
                        if os.uname()[0] == "FreeBSD":
                                if src == "/dev":
@@ -883,8 +913,14 @@ class generic_stage_target(generic_target):
                                        retval=os.system("mount_nullfs "+src+" "+\
                                                self.settings["chroot_path"]+x)
                        else:
-                               retval=os.system("mount --bind "+src+" "+\
-                                       self.settings["chroot_path"]+x)
+                               if src == "tmpfs":
+                                       if "var_tmpfs_portage" in self.settings:
+                                               retval=os.system("mount -t tmpfs -o size="+\
+                                                       self.settings["var_tmpfs_portage"]+"G "+src+" "+\
+                                                       self.settings["chroot_path"]+x)
+                               else:
+                                       retval=os.system("mount --bind "+src+" "+\
+                                               self.settings["chroot_path"]+x)
                        if retval!=0:
                                self.unbind()
                                raise CatalystError,"Couldn't bind mount "+src
@@ -916,7 +952,7 @@ class generic_stage_target(generic_target):
                                        ouch=1
                                        warn("Couldn't umount bind mount: "+mypath+x)
 
-                       if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
+                       if "SNAPCACHE" in self.settings and x == "/usr/portage":
                                try:
                                        """
                                        It's possible the snapshot lock object isn't created yet.
@@ -937,25 +973,25 @@ class generic_stage_target(generic_target):
 
        def chroot_setup(self):
                self.makeconf=read_makeconf(self.settings["chroot_path"]+\
-                       "/etc/make.conf")
+                       "/etc/portage/make.conf")
                self.override_cbuild()
                self.override_chost()
                self.override_cflags()
-               self.override_cxxflags()        
-               self.override_ldflags() 
-               if self.settings.has_key("AUTORESUME") \
+               self.override_cxxflags()
+               self.override_ldflags()
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
                        print "Resume point detected, skipping chroot_setup operation..."
                else:
                        print "Setting up chroot..."
-                       
-                       #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
-                       
+
+                       #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
+
                        cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
                                "Could not copy resolv.conf into place.",env=self.env)
-               
+
                        """ Copy over the envscript, if applicable """
-                       if self.settings.has_key("ENVSCRIPT"):
+                       if "ENVSCRIPT" in self.settings:
                                if not os.path.exists(self.settings["ENVSCRIPT"]):
                                        raise CatalystError,\
                                                "Can't find envscript "+self.settings["ENVSCRIPT"]
@@ -984,15 +1020,15 @@ class generic_stage_target(generic_target):
                                        "Could not copy /etc/hosts",env=self.env)
 
                        """ Modify and write out make.conf (for the chroot) """
-                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
+                       cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
                                "Could not remove "+self.settings["chroot_path"]+\
-                               "/etc/make.conf",env=self.env)
-                       myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
+                               "/etc/portage/make.conf",env=self.env)
+                       myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
                        myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
                        myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
-                       if self.settings.has_key("CFLAGS"):
+                       if "CFLAGS" in self.settings:
                                myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
-                       if self.settings.has_key("CXXFLAGS"):
+                       if "CXXFLAGS" in self.settings:
                                if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
                                        myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
                                else:
@@ -1000,10 +1036,10 @@ class generic_stage_target(generic_target):
                        else:
                                myf.write('CXXFLAGS="${CFLAGS}"\n')
 
-                       if self.settings.has_key("LDFLAGS"):
+                       if "LDFLAGS" in self.settings:
                                myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
                                myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
-                       if self.settings.has_key("CBUILD"):
+                       if "CBUILD" in self.settings:
                                myf.write("# This should not be changed unless you know exactly what you are doing.  You\n# should probably be using a different stage, instead.\n")
                                myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
 
@@ -1012,10 +1048,10 @@ class generic_stage_target(generic_target):
 
                        """ Figure out what our USE vars are for building """
                        myusevars=[]
-                       if self.settings.has_key("HOSTUSE"):
+                       if "HOSTUSE" in self.settings:
                                myusevars.extend(self.settings["HOSTUSE"])
 
-                       if self.settings.has_key("use"):
+                       if "use" in self.settings:
                                myusevars.extend(self.settings["use"])
 
                        if myusevars:
@@ -1028,29 +1064,33 @@ class generic_stage_target(generic_target):
                                                "/use will cause portage to ignore"
                                        print "\tpackage.use in the profile and portage_confdir. You've been warned!"
 
+                       myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
+                       myf.write('DISTDIR="${PORTDIR}/distfiles"\n')
+                       myf.write('PKGDIR="${PORTDIR}/packages"\n')
+
                        """ Setup the portage overlay """
-                       if self.settings.has_key("portage_overlay"):
+                       if "portage_overlay" in self.settings:
                                myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
 
                        myf.close()
-                       cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
-                               self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
-                               "Could not backup /etc/make.conf",env=self.env)
+                       cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
+                               self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
+                               "Could not backup /etc/portage/make.conf",env=self.env)
                        touch(self.settings["autoresume_path"]+"chroot_setup")
 
        def fsscript(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
                        print "Resume point detected, skipping fsscript operation..."
                else:
-                       if self.settings.has_key("fsscript"):
+                       if "fsscript" in self.settings:
                                if os.path.exists(self.settings["controller_file"]):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " fsscript","fsscript script failed.",env=self.env)
                                        touch(self.settings["autoresume_path"]+"fsscript")
 
        def rcupdate(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
                        print "Resume point detected, skipping rcupdate operation..."
                else:
@@ -1060,11 +1100,11 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"rcupdate")
 
        def clean(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"clean"):
                        print "Resume point detected, skipping clean operation..."
                else:
-                       for x in self.settings["cleanables"]: 
+                       for x in self.settings["cleanables"]:
                                print "Cleaning chroot: "+x+"... "
                                cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
                                        x,env=self.env)
@@ -1080,7 +1120,7 @@ class generic_stage_target(generic_target):
                        cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
                                "Could not remove /usr/local/portage",env=self.env)
                        cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
-                               "/etc/make.conf",\
+                               "/etc/portage/make.conf",\
                                "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
 
                """ Clean up old and obsoleted files in /etc """
@@ -1095,11 +1135,11 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"clean")
 
        def empty(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"empty"):
                        print "Resume point detected, skipping empty operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
+                       if self.settings["spec_prefix"]+"/empty" in self.settings:
                                if type(self.settings[self.settings["spec_prefix"]+\
                                        "/empty"])==types.StringType:
                                        self.settings[self.settings["spec_prefix"]+"/empty"]=\
@@ -1107,11 +1147,11 @@ class generic_stage_target(generic_target):
                                                "/empty"].split()
                                for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
                                        myemp=self.settings["destpath"]+x
-                                       if not os.path.isdir(myemp):
+                                       if not os.path.isdir(myemp) or os.path.islink(myemp):
                                                print x,"not a directory or does not exist, skipping 'empty' operation."
                                                continue
                                        print "Emptying directory",x
-                                       """ 
+                                       """
                                        stat the dir, delete the dir, recreate the dir and set
                                        the proper perms and ownership
                                        """
@@ -1123,11 +1163,11 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"empty")
 
        def remove(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"remove"):
                        print "Resume point detected, skipping remove operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
+                       if self.settings["spec_prefix"]+"/rm" in self.settings:
                                for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
                                        """
                                        We're going to shell out for all these cleaning
@@ -1145,7 +1185,7 @@ class generic_stage_target(generic_target):
                                        raise
 
        def preclean(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"preclean"):
                        print "Resume point detected, skipping preclean operation..."
                else:
@@ -1154,13 +1194,13 @@ class generic_stage_target(generic_target):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " preclean","preclean script failed.",env=self.env)
                                        touch(self.settings["autoresume_path"]+"preclean")
-               
+
                        except:
                                self.unbind()
                                raise CatalystError, "Build failed, could not execute preclean"
 
        def capture(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"capture"):
                        print "Resume point detected, skipping capture operation..."
                else:
@@ -1175,7 +1215,7 @@ class generic_stage_target(generic_target):
 
                        print "Creating stage tarball..."
 
-                       cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
+                       cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
                                self.settings["stage_path"]+" .",\
                                "Couldn't create stage tarball",env=self.env)
 
@@ -1185,7 +1225,7 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"capture")
 
        def run_local(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"run_local"):
                        print "Resume point detected, skipping run_local operation..."
                else:
@@ -1222,7 +1262,7 @@ class generic_stage_target(generic_target):
                                        self.env[varname]="true"
                                else:
                                        self.env[varname]="false"
-               if self.settings.has_key("makeopts"):
+               if "makeopts" in self.settings:
                        self.env["MAKEOPTS"]=self.settings["makeopts"]
 
        def run(self):
@@ -1234,18 +1274,18 @@ class generic_stage_target(generic_target):
                """ Check for mounts right away and abort if we cannot unmount them """
                self.mount_safety_check()
 
-               if self.settings.has_key("CLEAR_AUTORESUME"):
+               if "CLEAR_AUTORESUME" in self.settings:
                        self.clear_autoresume()
 
-               if self.settings.has_key("PURGETMPONLY"):
+               if "PURGETMPONLY" in self.settings:
                        self.purge()
                        return
 
-               if self.settings.has_key("PURGEONLY"):
+               if "PURGEONLY" in self.settings:
                        self.purge()
                        return
 
-               if self.settings.has_key("PURGE"):
+               if "PURGE" in self.settings:
                        self.purge()
 
                for x in self.settings["action_sequence"]:
@@ -1256,15 +1296,15 @@ class generic_stage_target(generic_target):
                        except:
                                self.mount_safety_check()
                                raise
-               
+
                self.chroot_lock.unlock()
 
        def unmerge(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
                        print "Resume point detected, skipping unmerge operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
+                       if self.settings["spec_prefix"]+"/unmerge" in self.settings:
                                if type(self.settings[self.settings["spec_prefix"]+\
                                        "/unmerge"])==types.StringType:
                                        self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
@@ -1292,7 +1332,7 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"unmerge")
 
        def target_setup(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
                        print "Resume point detected, skipping target_setup operation..."
                else:
@@ -1303,12 +1343,12 @@ class generic_stage_target(generic_target):
                        touch(self.settings["autoresume_path"]+"target_setup")
 
        def setup_overlay(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
                        print "Resume point detected, skipping setup_overlay operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
-                               for x in self.settings[self.settings["spec_prefix"]+"/overlay"]: 
+                       if self.settings["spec_prefix"]+"/overlay" in self.settings:
+                               for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
                                        if os.path.exists(x):
                                                cmd("rsync -a "+x+"/ "+\
                                                        self.settings["target_path"],\
@@ -1317,12 +1357,12 @@ class generic_stage_target(generic_target):
                                touch(self.settings["autoresume_path"]+"setup_overlay")
 
        def create_iso(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
                        print "Resume point detected, skipping create_iso operation..."
                else:
                        """ Create the ISO """
-                       if self.settings.has_key("iso"):
+                       if "iso" in self.settings:
                                cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
                                        self.settings["iso"],"ISO creation script failed.",\
                                        env=self.env)
@@ -1334,13 +1374,13 @@ class generic_stage_target(generic_target):
                                print "An ISO Image will not be created."
 
        def build_packages(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "build_packages"):
                        print "Resume point detected, skipping build_packages operation..."
                else:
-                       if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
-                               if self.settings.has_key("AUTORESUME") \
+                       if self.settings["spec_prefix"]+"/packages" in self.settings:
+                               if "AUTORESUME" in self.settings \
                                        and os.path.exists(self.settings["autoresume_path"]+\
                                                "build_packages"):
                                        print "Resume point detected, skipping build_packages operation..."
@@ -1359,11 +1399,12 @@ class generic_stage_target(generic_target):
                                                        "build aborting due to error."
 
        def build_kernel(self):
-               if self.settings.has_key("AUTORESUME") \
+               "Build all configured kernels"
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
                        print "Resume point detected, skipping build_kernel operation..."
                else:
-                       if self.settings.has_key("boot/kernel"):
+                       if "boot/kernel" in self.settings:
                                try:
                                        mynames=self.settings["boot/kernel"]
                                        if type(mynames)==types.StringType:
@@ -1374,116 +1415,115 @@ class generic_stage_target(generic_target):
                                        cmd("/bin/bash "+self.settings["controller_file"]+\
                                                " pre-kmerge ","Runscript pre-kmerge failed",\
                                                env=self.env)
-
                                        for kname in mynames:
-                                               if self.settings.has_key("AUTORESUME") \
-                                                       and os.path.exists(self.settings["autoresume_path"]\
-                                                               +"build_kernel_"+kname):
-                                                       print "Resume point detected, skipping build_kernel for "+kname+" operation..."
-                                               else: # TODO: make this not require a kernel config
-                                                       try:
-                                                               if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
-                                                                       self.unbind()
-                                                                       raise CatalystError,\
-                                                                               "Can't find kernel config: "+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/config"]
-
-                                                       except TypeError:
-                                                               raise CatalystError,\
-                                                                       "Required value boot/kernel/config not specified"
-
-                                                       try:
-                                                               cmd("cp "+self.settings["boot/kernel/"+kname+\
-                                                                       "/config"]+" "+\
-                                                                       self.settings["chroot_path"]+"/var/tmp/"+\
-                                                                       kname+".config",\
-                                                                       "Couldn't copy kernel config: "+\
-                                                                       self.settings["boot/kernel/"+kname+\
-                                                                       "/config"],env=self.env)
-
-                                                       except CatalystError:
-                                                               self.unbind()
-
-                                                       """
-                                                       If we need to pass special options to the bootloader
-                                                       for this kernel put them into the environment
-                                                       """
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/kernelopts"):
-                                                               myopts=self.settings["boot/kernel/"+kname+\
-                                                                       "/kernelopts"]
-
-                                                               if type(myopts) != types.StringType:
-                                                                       myopts = string.join(myopts)
-                                                                       self.env[kname+"_kernelopts"]=myopts
-
-                                                               else:
-                                                                       self.env[kname+"_kernelopts"]=""
-
-                                                       if not self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/extraversion"):
-                                                               self.settings["boot/kernel/"+kname+\
-                                                                       "/extraversion"]=""
-
-                                                       self.env["clst_kextraversion"]=\
-                                                               self.settings["boot/kernel/"+kname+\
-                                                               "/extraversion"]
-
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/initramfs_overlay"):
-                                                               if os.path.exists(self.settings["boot/kernel/"+\
-                                                                       kname+"/initramfs_overlay"]):
-                                                                       print "Copying initramfs_overlay dir "+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"]
-
-                                                                       cmd("mkdir -p "+\
-                                                                               self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/"+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"],env=self.env)
-
-                                                                       cmd("cp -R "+self.settings["boot/kernel/"+\
-                                                                               kname+"/initramfs_overlay"]+"/* "+\
-                                                                               self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/"+\
-                                                                               self.settings["boot/kernel/"+kname+\
-                                                                               "/initramfs_overlay"],env=self.env)
-
-                                                       """ Execute the script that builds the kernel """
-                                                       cmd("/bin/bash "+self.settings["controller_file"]+\
-                                                               " kernel "+kname,\
-                                                               "Runscript kernel build failed",env=self.env)
-
-                                                       if self.settings.has_key("boot/kernel/"+kname+\
-                                                               "/initramfs_overlay"):
-                                                               if os.path.exists(self.settings["chroot_path"]+\
-                                                                       "/tmp/initramfs_overlay/"):
-                                                                       print "Cleaning up temporary overlay dir"
-                                                                       cmd("rm -R "+self.settings["chroot_path"]+\
-                                                                               "/tmp/initramfs_overlay/",env=self.env)
-
-                                                       touch(self.settings["autoresume_path"]+\
-                                                               "build_kernel_"+kname)
-
-                                                       """
-                                                       Execute the script that cleans up the kernel build
-                                                       environment
-                                                       """
-                                                       cmd("/bin/bash "+self.settings["controller_file"]+\
-                                                               " post-kmerge ",
-                                                               "Runscript post-kmerge failed",env=self.env)
-
+                                               self._build_kernel(kname=kname)
                                        touch(self.settings["autoresume_path"]+"build_kernel")
-
                                except CatalystError:
                                        self.unbind()
                                        raise CatalystError,\
                                                "build aborting due to kernel build error."
 
+       def _build_kernel(self, kname):
+               "Build a single configured kernel by name"
+               if "AUTORESUME" in self.settings \
+                       and os.path.exists(self.settings["autoresume_path"]\
+                               +"build_kernel_"+kname):
+                       print "Resume point detected, skipping build_kernel for "+kname+" operation..."
+                       return
+               self._copy_kernel_config(kname=kname)
+
+               """
+               If we need to pass special options to the bootloader
+               for this kernel put them into the environment
+               """
+               if "boot/kernel/"+kname+"/kernelopts" in self.settings:
+                       myopts=self.settings["boot/kernel/"+kname+\
+                               "/kernelopts"]
+
+                       if type(myopts) != types.StringType:
+                               myopts = string.join(myopts)
+                               self.env[kname+"_kernelopts"]=myopts
+
+                       else:
+                               self.env[kname+"_kernelopts"]=""
+
+               if "boot/kernel/"+kname+"/extraversion" not in self.settings:
+                       self.settings["boot/kernel/"+kname+\
+                               "/extraversion"]=""
+
+               self.env["clst_kextraversion"]=\
+                       self.settings["boot/kernel/"+kname+\
+                       "/extraversion"]
+
+               self._copy_initramfs_overlay(kname=kname)
+
+               """ Execute the script that builds the kernel """
+               cmd("/bin/bash "+self.settings["controller_file"]+\
+                       " kernel "+kname,\
+                       "Runscript kernel build failed",env=self.env)
+
+               if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
+                       if os.path.exists(self.settings["chroot_path"]+\
+                               "/tmp/initramfs_overlay/"):
+                               print "Cleaning up temporary overlay dir"
+                               cmd("rm -R "+self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/",env=self.env)
+
+               touch(self.settings["autoresume_path"]+\
+                       "build_kernel_"+kname)
+
+               """
+               Execute the script that cleans up the kernel build
+               environment
+               """
+               cmd("/bin/bash "+self.settings["controller_file"]+\
+                       " post-kmerge ",
+                       "Runscript post-kmerge failed",env=self.env)
+
+       def _copy_kernel_config(self, kname):
+               if "boot/kernel/"+kname+"/config" in self.settings:
+                       if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
+                               self.unbind()
+                               raise CatalystError,\
+                                       "Can't find kernel config: "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/config"]
+
+                       try:
+                               cmd("cp "+self.settings["boot/kernel/"+kname+\
+                                       "/config"]+" "+\
+                                       self.settings["chroot_path"]+"/var/tmp/"+\
+                                       kname+".config",\
+                                       "Couldn't copy kernel config: "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/config"],env=self.env)
+
+                       except CatalystError:
+                               self.unbind()
+
+       def _copy_initramfs_overlay(self, kname):
+               if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
+                       if os.path.exists(self.settings["boot/kernel/"+\
+                               kname+"/initramfs_overlay"]):
+                               print "Copying initramfs_overlay dir "+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"]
+
+                               cmd("mkdir -p "+\
+                                       self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/"+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"],env=self.env)
+
+                               cmd("cp -R "+self.settings["boot/kernel/"+\
+                                       kname+"/initramfs_overlay"]+"/* "+\
+                                       self.settings["chroot_path"]+\
+                                       "/tmp/initramfs_overlay/"+\
+                                       self.settings["boot/kernel/"+kname+\
+                                       "/initramfs_overlay"],env=self.env)
+
        def bootloader(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
                        print "Resume point detected, skipping bootloader operation..."
                else:
@@ -1497,7 +1537,7 @@ class generic_stage_target(generic_target):
                                raise CatalystError,"Script aborting due to error."
 
        def livecd_update(self):
-               if self.settings.has_key("AUTORESUME") \
+               if "AUTORESUME" in self.settings \
                        and os.path.exists(self.settings["autoresume_path"]+\
                                "livecd_update"):
                        print "Resume point detected, skipping build_packages operation..."
@@ -1530,7 +1570,7 @@ class generic_stage_target(generic_target):
                        os.chmod(myemp,mystat[ST_MODE])
 
        def clear_packages(self):
-               if self.settings.has_key("PKGCACHE"):
+               if "PKGCACHE" in self.settings:
                        print "purging the pkgcache ..."
 
                        myemp=self.settings["pkgcache_path"]
@@ -1548,7 +1588,7 @@ class generic_stage_target(generic_target):
                                os.chmod(myemp,mystat[ST_MODE])
 
        def clear_kerncache(self):
-               if self.settings.has_key("KERNCACHE"):
+               if "KERNCACHE" in self.settings:
                        print "purging the kerncache ..."
 
                        myemp=self.settings["kerncache_path"]
@@ -1567,11 +1607,11 @@ class generic_stage_target(generic_target):
 
        def clear_autoresume(self):
                """ Clean resume points since they are no longer needed """
-               if self.settings.has_key("AUTORESUME"):
+               if "AUTORESUME" in self.settings:
                        print "Removing AutoResume Points: ..."
                myemp=self.settings["autoresume_path"]
                if os.path.isdir(myemp):
-                               if self.settings.has_key("AUTORESUME"):
+                               if "AUTORESUME" in self.settings:
                                        print "Emptying directory",myemp
                                """
                                stat the dir, delete the dir, recreate the dir and set
@@ -1591,7 +1631,7 @@ class generic_stage_target(generic_target):
        def gen_contents_file(self,file):
                if os.path.exists(file+".CONTENTS"):
                        os.remove(file+".CONTENTS")
-               if self.settings.has_key("contents"):
+               if "contents" in self.settings:
                        if os.path.exists(file):
                                myf=open(file+".CONTENTS","w")
                                keys={}
@@ -1601,7 +1641,7 @@ class generic_stage_target(generic_target):
                                        array.sort()
                                for j in array:
                                        contents=generate_contents(file,contents_function=j,\
-                                               verbose=self.settings.has_key("VERBOSE"))
+                                               verbose="VERBOSE" in self.settings)
                                        if contents:
                                                myf.write(contents)
                                myf.close()
@@ -1609,7 +1649,7 @@ class generic_stage_target(generic_target):
        def gen_digest_file(self,file):
                if os.path.exists(file+".DIGESTS"):
                        os.remove(file+".DIGESTS")
-               if self.settings.has_key("digests"):
+               if "digests" in self.settings:
                        if os.path.exists(file):
                                myf=open(file+".DIGESTS","w")
                                keys={}
@@ -1622,29 +1662,29 @@ class generic_stage_target(generic_target):
                                                if "all" in array:
                                                        for k in hash_map.keys():
                                                                hash=generate_hash(f,hash_function=k,verbose=\
-                                                                       self.settings.has_key("VERBOSE"))
+                                                                       "VERBOSE" in self.settings)
                                                                myf.write(hash)
                                                else:
                                                        for j in array:
                                                                hash=generate_hash(f,hash_function=j,verbose=\
-                                                                       self.settings.has_key("VERBOSE"))
+                                                                       "VERBOSE" in self.settings)
                                                                myf.write(hash)
                                myf.close()
 
        def purge(self):
                countdown(10,"Purging Caches ...")
-               if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY") or self.settings.has_key("PURGETMPONLY"):
+               if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
                        print "clearing autoresume ..."
                        self.clear_autoresume()
 
                        print "clearing chroot ..."
                        self.clear_chroot()
 
-                       if not self.settings.has_key("PURGETMPONLY"):
+                       if "PURGETMPONLY" not in self.settings:
                                print "clearing package cache ..."
                                self.clear_packages()
 
                        print "clearing kerncache ..."
                        self.clear_kerncache()
 
-# vim: ts=4 sw=4 sta et sts=4 ai 
+# vim: ts=4 sw=4 sta et sts=4 ai