public inbox for gentoo-catalyst@lists.gentoo.org
 help / color / mirror / Atom feed
From: Brian Dolbec <dolsen@gentoo.org>
To: gentoo-catalyst@lists.gentoo.org
Subject: [gentoo-catalyst] [PATCH 1/3] [1 of 3] Move base stage and target files to thier own sub-pkg
Date: Wed, 10 Sep 2014 20:50:48 -0700	[thread overview]
Message-ID: <1410407450-2888-2-git-send-email-dolsen@gentoo.org> (raw)
In-Reply-To: <1410407450-2888-1-git-send-email-dolsen@gentoo.org>

Fix an indent error in grp_target.py
---
 catalyst/base/__init__.py                |    1 +
 catalyst/base/clearbase.py               |  115 +++
 catalyst/base/genbase.py                 |   58 ++
 catalyst/base/stagebase.py               | 1630 ++++++++++++++++++++++++++++++
 catalyst/base/targetbase.py              |   15 +
 catalyst/targets/clearbase.py            |  115 ---
 catalyst/targets/embedded_target.py      |   12 +-
 catalyst/targets/genbase.py              |   58 --
 catalyst/targets/generic_stage_target.py | 1630 ------------------------------
 catalyst/targets/grp_target.py           |   34 +-
 catalyst/targets/livecd_stage1_target.py |   21 +-
 catalyst/targets/livecd_stage2_target.py |   13 +-
 catalyst/targets/netboot2_target.py      |   17 +-
 catalyst/targets/netboot_target.py       |   15 +-
 catalyst/targets/snapshot_target.py      |    4 +-
 catalyst/targets/stage1_target.py        |   17 +-
 catalyst/targets/stage2_target.py        |   15 +-
 catalyst/targets/stage3_target.py        |   12 +-
 catalyst/targets/stage4_target.py        |    8 +-
 catalyst/targets/targetbase.py           |   15 -
 catalyst/targets/tinderbox_target.py     |   11 +-
 21 files changed, 1927 insertions(+), 1889 deletions(-)
 create mode 100644 catalyst/base/__init__.py
 create mode 100644 catalyst/base/clearbase.py
 create mode 100644 catalyst/base/genbase.py
 create mode 100644 catalyst/base/stagebase.py
 create mode 100644 catalyst/base/targetbase.py
 delete mode 100644 catalyst/targets/clearbase.py
 delete mode 100644 catalyst/targets/genbase.py
 delete mode 100644 catalyst/targets/generic_stage_target.py
 delete mode 100644 catalyst/targets/targetbase.py

diff --git a/catalyst/base/__init__.py b/catalyst/base/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/catalyst/base/__init__.py
@@ -0,0 +1 @@
+
diff --git a/catalyst/base/clearbase.py b/catalyst/base/clearbase.py
new file mode 100644
index 0000000..8519acc
--- /dev/null
+++ b/catalyst/base/clearbase.py
@@ -0,0 +1,115 @@
+
+import os
+import shutil
+from stat import ST_UID, ST_GID, ST_MODE
+
+
+from catalyst.support import cmd, countdown
+
+
+class ClearBase(object):
+	"""
+	This class does all of clearing after task completion
+	"""
+	def __init__(self, myspec):
+		self.settings = myspec
+
+
+
+	def clear_autoresume(self):
+		""" Clean resume points since they are no longer needed """
+		if "autoresume" in self.settings["options"]:
+			print "Removing AutoResume Points: ..."
+		myemp=self.settings["autoresume_path"]
+		if os.path.isdir(myemp):
+				if "autoresume" in self.settings["options"]:
+					print "Emptying directory",myemp
+				"""
+				stat the dir, delete the dir, recreate the dir and set
+				the proper perms and ownership
+				"""
+				mystat=os.stat(myemp)
+				if os.uname()[0] == "FreeBSD":
+					cmd("chflags -R noschg "+myemp,\
+						"Could not remove immutable flag for file "\
+						+myemp)
+				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
+				shutil.rmtree(myemp)
+				os.makedirs(myemp,0755)
+				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+				os.chmod(myemp,mystat[ST_MODE])
+
+
+	def clear_chroot(self):
+		myemp=self.settings["chroot_path"]
+		if os.path.isdir(myemp):
+			print "Emptying directory",myemp
+			"""
+			stat the dir, delete the dir, recreate the dir and set
+			the proper perms and ownership
+			"""
+			mystat=os.stat(myemp)
+			#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
+			""" There's no easy way to change flags recursively in python """
+			if os.uname()[0] == "FreeBSD":
+				os.system("chflags -R noschg "+myemp)
+			shutil.rmtree(myemp)
+			os.makedirs(myemp,0755)
+			os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+			os.chmod(myemp,mystat[ST_MODE])
+
+
+	def clear_packages(self):
+		if "pkgcache" in self.settings["options"]:
+			print "purging the pkgcache ..."
+
+			myemp=self.settings["pkgcache_path"]
+			if os.path.isdir(myemp):
+				print "Emptying directory",myemp
+				"""
+				stat the dir, delete the dir, recreate the dir and set
+				the proper perms and ownership
+				"""
+				mystat=os.stat(myemp)
+				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
+				shutil.rmtree(myemp)
+				os.makedirs(myemp,0755)
+				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+				os.chmod(myemp,mystat[ST_MODE])
+
+
+	def clear_kerncache(self):
+		if "kerncache" in self.settings["options"]:
+			print "purging the kerncache ..."
+
+			myemp=self.settings["kerncache_path"]
+			if os.path.isdir(myemp):
+				print "Emptying directory",myemp
+				"""
+				stat the dir, delete the dir, recreate the dir and set
+				the proper perms and ownership
+				"""
+				mystat=os.stat(myemp)
+				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
+				shutil.rmtree(myemp)
+				os.makedirs(myemp,0755)
+				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+				os.chmod(myemp,mystat[ST_MODE])
+
+
+	def purge(self):
+		countdown(10,"Purging Caches ...")
+		if any(k in self.settings["options"] for k in ("purge","purgeonly","purgetmponly")):
+			print "clearing autoresume ..."
+			self.clear_autoresume()
+
+			print "clearing chroot ..."
+			self.clear_chroot()
+
+			if "PURGETMPONLY" not in self.settings:
+				print "clearing package cache ..."
+				self.clear_packages()
+
+			print "clearing kerncache ..."
+			self.clear_kerncache()
+
diff --git a/catalyst/base/genbase.py b/catalyst/base/genbase.py
new file mode 100644
index 0000000..e818781
--- /dev/null
+++ b/catalyst/base/genbase.py
@@ -0,0 +1,58 @@
+
+
+import os
+
+
+class GenBase(object):
+	"""
+	This class does generation of the contents and digests files.
+	"""
+	def __init__(self,myspec):
+		self.settings = myspec
+
+
+	def gen_contents_file(self,file):
+		if os.path.exists(file+".CONTENTS"):
+			os.remove(file+".CONTENTS")
+		if "contents" in self.settings:
+			contents_map = self.settings["contents_map"]
+			if os.path.exists(file):
+				myf=open(file+".CONTENTS","w")
+				keys={}
+				for i in self.settings["contents"].split():
+					keys[i]=1
+					array=keys.keys()
+					array.sort()
+				for j in array:
+					contents = contents_map.generate_contents(file, j,
+						verbose="VERBOSE" in self.settings)
+					if contents:
+						myf.write(contents)
+				myf.close()
+
+	def gen_digest_file(self,file):
+		if os.path.exists(file+".DIGESTS"):
+			os.remove(file+".DIGESTS")
+		if "digests" in self.settings:
+			hash_map = self.settings["hash_map"]
+			if os.path.exists(file):
+				myf=open(file+".DIGESTS","w")
+				keys={}
+				for i in self.settings["digests"].split():
+					keys[i]=1
+					array=keys.keys()
+					array.sort()
+				for f in [file, file+'.CONTENTS']:
+					if os.path.exists(f):
+						if "all" in array:
+							for k in list(hash_map.hash_map):
+								hash = hash_map.generate_hash(f,hash_=k,
+									verbose = "VERBOSE" in self.settings)
+								myf.write(hash)
+						else:
+							for j in array:
+								hash = hash_map.generate_hash(f,hash_=j,
+									verbose = "VERBOSE" in self.settings)
+								myf.write(hash)
+				myf.close()
+
diff --git a/catalyst/base/stagebase.py b/catalyst/base/stagebase.py
new file mode 100644
index 0000000..bebb5dc
--- /dev/null
+++ b/catalyst/base/stagebase.py
@@ -0,0 +1,1630 @@
+
+import os
+import string
+import imp
+import types
+import shutil
+import sys
+from stat import ST_UID, ST_GID, ST_MODE
+
+# for convienience
+pjoin = os.path.join
+
+from catalyst.defaults import (SOURCE_MOUNT_DEFAULTS, TARGET_MOUNT_DEFAULTS,
+	PORT_LOGDIR_CLEAN)
+from catalyst.support import (CatalystError, msg, file_locate, normpath,
+	touch, cmd, warn, list_bashify, read_makeconf, read_from_clst, ismount)
+from catalyst.base.targetbase import TargetBase
+from catalyst.base.clearbase import ClearBase
+from catalyst.base.genbase import GenBase
+from catalyst.lock import LockDir
+
+
+class StageBase(TargetBase, ClearBase, GenBase):
+	"""
+	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"])
+
+		self.valid_values.extend(["version_stamp","target","subarch",\
+			"rel_type","profile","snapshot","source_subpath","portage_confdir",\
+			"cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
+			"distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
+
+		self.set_valid_build_kernel_vars(addlargs)
+		TargetBase.__init__(self, myspec, addlargs)
+		GenBase.__init__(self, myspec)
+		ClearBase.__init__(self, myspec)
+
+		"""
+		The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
+		work better with vapier's CBUILD stuff. I've removed the "monolithic"
+		machinemap from this file and split up its contents amongst the
+		various arch/foo.py files.
+
+		When register() is called on each module in the arch/ dir, it now
+		returns a tuple instead of acting on the subarchmap dict that is
+		passed to it. The tuple contains the values that were previously
+		added to subarchmap as well as a new list of CHOSTs that go along
+		with that arch. This allows us to build machinemap on the fly based
+		on the keys in subarchmap and the values of the 2nd list returned
+		(tmpmachinemap).
+
+		Also, after talking with vapier. I have a slightly better idea of what
+		certain variables are used for and what they should be set to. Neither
+		'buildarch' or 'hostarch' are used directly, so their value doesn't
+		really matter. They are just compared to determine if we are
+		cross-compiling. Because of this, they are just set to the name of the
+		module in arch/ that the subarch is part of to make things simpler.
+		The entire build process is still based off of 'subarch' like it was
+		previously. -agaffney
+		"""
+
+		self.archmap = {}
+		self.subarchmap = {}
+		machinemap = {}
+		arch_dir = self.settings["PythonDir"] + "/arch/"
+		for x in [x[:-3] for x in os.listdir(arch_dir) if x.endswith(".py")]:
+			if x == "__init__":
+				continue
+			try:
+				fh=open(arch_dir + x + ".py")
+				"""
+				This next line loads the plugin as a module and assigns it to
+				archmap[x]
+				"""
+				self.archmap[x]=imp.load_module(x,fh,"../arch/" + x + ".py",
+					(".py", "r", imp.PY_SOURCE))
+				"""
+				This next line registers all the subarches supported in the
+				plugin
+				"""
+				tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
+				self.subarchmap.update(tmpsubarchmap)
+				for machine in tmpmachinemap:
+					machinemap[machine] = x
+				for subarch in tmpsubarchmap:
+					machinemap[subarch] = x
+				fh.close()
+			except IOError:
+				"""
+				This message should probably change a bit, since everything in
+				the dir should load just fine. If it doesn't, it's probably a
+				syntax error in the module
+				"""
+				msg("Can't find/load " + x + ".py plugin in " + arch_dir)
+
+		if "chost" in self.settings:
+			hostmachine = self.settings["chost"].split("-")[0]
+			if hostmachine not in machinemap:
+				raise CatalystError, "Unknown host machine type "+hostmachine
+			self.settings["hostarch"]=machinemap[hostmachine]
+		else:
+			hostmachine = self.settings["subarch"]
+			if hostmachine in machinemap:
+				hostmachine = machinemap[hostmachine]
+			self.settings["hostarch"]=hostmachine
+		if "cbuild" in self.settings:
+			buildmachine = self.settings["cbuild"].split("-")[0]
+		else:
+			buildmachine = os.uname()[4]
+		if buildmachine not in machinemap:
+			raise CatalystError, "Unknown build machine type "+buildmachine
+		self.settings["buildarch"]=machinemap[buildmachine]
+		self.settings["crosscompile"]=(self.settings["hostarch"]!=\
+			self.settings["buildarch"])
+
+		""" Call arch constructor, pass our settings """
+		try:
+			self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
+		except KeyError:
+			print "Invalid subarch: "+self.settings["subarch"]
+			print "Choose one of the following:",
+			for x in self.subarchmap:
+				print x,
+			print
+			sys.exit(2)
+
+		print "Using target:",self.settings["target"]
+		""" Print a nice informational message """
+		if self.settings["buildarch"]==self.settings["hostarch"]:
+			print "Building natively for",self.settings["hostarch"]
+		elif self.settings["crosscompile"]:
+			print "Cross-compiling on",self.settings["buildarch"],\
+				"for different machine type",self.settings["hostarch"]
+		else:
+			print "Building on",self.settings["buildarch"],\
+				"for alternate personality type",self.settings["hostarch"]
+
+		""" This must be set first as other set_ options depend on this """
+		self.set_spec_prefix()
+
+		""" Define all of our core variables """
+		self.set_target_profile()
+		self.set_target_subpath()
+		self.set_source_subpath()
+
+		""" Set paths """
+		self.set_snapshot_path()
+		self.set_root_path()
+		self.set_source_path()
+		self.set_snapcache_path()
+		self.set_chroot_path()
+		self.set_autoresume_path()
+		self.set_dest_path()
+		self.set_stage_path()
+		self.set_target_path()
+
+		self.set_controller_file()
+		self.set_action_sequence()
+		self.set_use()
+		self.set_cleanables()
+		self.set_iso_volume_id()
+		self.set_build_kernel_vars()
+		self.set_fsscript()
+		self.set_install_mask()
+		self.set_rcadd()
+		self.set_rcdel()
+		self.set_cdtar()
+		self.set_fstype()
+		self.set_fsops()
+		self.set_iso()
+		self.set_packages()
+		self.set_rm()
+		self.set_linuxrc()
+		self.set_busybox_config()
+		self.set_overlay()
+		self.set_portage_overlay()
+		self.set_root_overlay()
+
+		"""
+		This next line checks to make sure that the specified variables exist
+		on disk.
+		"""
+		#pdb.set_trace()
+		file_locate(self.settings,["source_path","snapshot_path","distdir"],\
+			expand=0)
+		""" If we are using portage_confdir, check that as well. """
+		if "portage_confdir" in self.settings:
+			file_locate(self.settings,["portage_confdir"],expand=0)
+
+		""" Setup our mount points """
+		# initialize our target mounts.
+		self.target_mounts = TARGET_MOUNT_DEFAULTS.copy()
+
+		self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
+		# initialize our source mounts
+		self.mountmap = SOURCE_MOUNT_DEFAULTS.copy()
+		# update them from settings
+		self.mountmap["distdir"] = self.settings["distdir"]
+		if "snapcache" not in self.settings["options"]:
+			self.mounts.remove("portdir")
+			self.mountmap["portdir"] = None
+		else:
+			self.mountmap["portdir"] = normpath("/".join([
+				self.settings["snapshot_cache_path"],
+				self.settings["repo_name"],
+				]))
+		if os.uname()[0] == "Linux":
+			self.mounts.append("devpts")
+			self.mounts.append("shm")
+
+		self.set_mounts()
+
+		"""
+		Configure any user specified options (either in catalyst.conf or on
+		the command line).
+		"""
+		if "pkgcache" in self.settings["options"]:
+			self.set_pkgcache_path()
+			print "Location of the package cache is "+\
+				self.settings["pkgcache_path"]
+			self.mounts.append("packagedir")
+			self.mountmap["packagedir"] = self.settings["pkgcache_path"]
+
+		if "kerncache" in self.settings["options"]:
+			self.set_kerncache_path()
+			print "Location of the kerncache is "+\
+				self.settings["kerncache_path"]
+			self.mounts.append("kerncache")
+			self.mountmap["kerncache"] = self.settings["kerncache_path"]
+
+		if "ccache" in self.settings["options"]:
+			if "CCACHE_DIR" in os.environ:
+				ccdir=os.environ["CCACHE_DIR"]
+				del os.environ["CCACHE_DIR"]
+			else:
+				ccdir="/root/.ccache"
+			if not os.path.isdir(ccdir):
+				raise CatalystError,\
+					"Compiler cache support can't be enabled (can't find "+\
+					ccdir+")"
+			self.mounts.append("ccache")
+			self.mountmap["ccache"] = ccdir
+			""" for the chroot: """
+			self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
+
+		if "icecream" in self.settings["options"]:
+			self.mounts.append("icecream")
+			self.mountmap["icecream"] = self.settings["icecream"]
+			self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
+				self.env["PATH"]
+
+		if "port_logdir" in self.settings:
+			self.mounts.append("port_logdir")
+			self.mountmap["port_logdir"] = self.settings["port_logdir"]
+			self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
+			self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
+
+	def override_cbuild(self):
+		if "CBUILD" in self.makeconf:
+			self.settings["CBUILD"]=self.makeconf["CBUILD"]
+
+	def override_chost(self):
+		if "CHOST" in self.makeconf:
+			self.settings["CHOST"]=self.makeconf["CHOST"]
+
+	def override_cflags(self):
+		if "CFLAGS" in self.makeconf:
+			self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
+
+	def override_cxxflags(self):
+		if "CXXFLAGS" in self.makeconf:
+			self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
+
+	def override_ldflags(self):
+		if "LDFLAGS" in self.makeconf:
+			self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
+
+	def set_install_mask(self):
+		if "install_mask" in self.settings:
+			if type(self.settings["install_mask"])!=types.StringType:
+				self.settings["install_mask"]=\
+					string.join(self.settings["install_mask"])
+
+	def set_spec_prefix(self):
+		self.settings["spec_prefix"]=self.settings["target"]
+
+	def set_target_profile(self):
+		self.settings["target_profile"]=self.settings["profile"]
+
+	def set_target_subpath(self):
+		self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
+				self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
+				self.settings["version_stamp"]
+
+	def set_source_subpath(self):
+		if type(self.settings["source_subpath"])!=types.StringType:
+			raise CatalystError,\
+				"source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
+
+	def set_pkgcache_path(self):
+		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"]))
+		else:
+			self.settings["pkgcache_path"]=\
+				normpath(self.settings["storedir"]+"/packages/"+\
+				self.settings["target_subpath"]+"/")
+
+	def set_kerncache_path(self):
+		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"]))
+		else:
+			self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
+				"/kerncache/"+self.settings["target_subpath"]+"/")
+
+	def set_target_path(self):
+		self.settings["target_path"]=normpath(self.settings["storedir"]+\
+			"/builds/"+self.settings["target_subpath"]+".tar.bz2")
+		setup_target_path_resume = pjoin(self.settings["autoresume_path"],
+			"setup_target_path")
+		if "autoresume" in self.settings["options"] and \
+				os.path.exists(setup_target_path_resume):
+			print \
+				"Resume point detected, skipping target path setup operation..."
+		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 nothing at all
+#			if os.path.isfile(self.settings["target_path"]):
+#				cmd("rm -f "+self.settings["target_path"],\
+#					"Could not remove existing file: "\
+#					+self.settings["target_path"],env=self.env)
+			touch(setup_target_path_resume)
+
+			if not os.path.exists(self.settings["storedir"]+"/builds/"):
+				os.makedirs(self.settings["storedir"]+"/builds/")
+
+	def set_fsscript(self):
+		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["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["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["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["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"])
+			else:
+				# This automatically prepends the build dir to the ISO output path
+				# if it doesn't start with a /
+				self.settings["iso"] = normpath(self.settings["storedir"] + \
+					"/builds/" + self.settings["rel_type"] + "/" + \
+					self.settings[self.settings["spec_prefix"]+"/iso"])
+			del self.settings[self.settings["spec_prefix"]+"/iso"]
+
+	def set_fstype(self):
+		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 "fstype" not in self.settings:
+			self.settings["fstype"]="normal"
+			for x in self.valid_values:
+				if x ==  self.settings["spec_prefix"]+"/fstype":
+					print "\n"+self.settings["spec_prefix"]+\
+						"/fstype is being set to the default of \"normal\"\n"
+
+	def set_fsops(self):
+		if "fstype" in self.settings:
+			self.valid_values.append("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 "seedcache" in self.settings["options"]\
+			and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
+				self.settings["source_subpath"]+"/")):
+			self.settings["source_path"]=normpath(self.settings["storedir"]+\
+				"/tmp/"+self.settings["source_subpath"]+"/")
+		else:
+			self.settings["source_path"]=normpath(self.settings["storedir"]+\
+				"/builds/"+self.settings["source_subpath"]+".tar.bz2")
+			if os.path.isfile(self.settings["source_path"]):
+				# XXX: Is this even necessary if the previous check passes?
+				if os.path.exists(self.settings["source_path"]):
+					self.settings["source_path_hash"] = \
+						self.settings["hash_map"].generate_hash(
+							self.settings["source_path"],
+							hash_ = self.settings["hash_function"],
+							verbose = False)
+		print "Source path set to "+self.settings["source_path"]
+		if os.path.isdir(self.settings["source_path"]):
+			print "\tIf this is not desired, remove this directory or turn off"
+			print "\tseedcache in the options of catalyst.conf the source path"
+			print "\twill then be "+\
+				normpath(self.settings["storedir"]+"/builds/"+\
+				self.settings["source_subpath"]+".tar.bz2\n")
+
+	def set_dest_path(self):
+		if "root_path" in self.settings:
+			self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
+				self.settings["root_path"])
+		else:
+			self.settings["destpath"]=normpath(self.settings["chroot_path"])
+
+	def set_cleanables(self):
+		self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
+			"/root/*", self.settings["portdir"]]
+
+	def set_snapshot_path(self):
+		self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
+			"/snapshots/" + self.settings["snapshot_name"] +
+			self.settings["snapshot"] + ".tar.xz")
+
+		if os.path.exists(self.settings["snapshot_path"]):
+			self.settings["snapshot_path_hash"] = \
+				self.settings["hash_map"].generate_hash(
+					self.settings["snapshot_path"],
+					hash_ = self.settings["hash_function"],
+					verbose = False)
+		else:
+			self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
+				"/snapshots/" + self.settings["snapshot_name"] +
+				self.settings["snapshot"] + ".tar.bz2")
+
+			if os.path.exists(self.settings["snapshot_path"]):
+				self.settings["snapshot_path_hash"] = \
+					self.settings["hash_map"].generate_hash(
+						self.settings["snapshot_path"],
+						hash_ = self.settings["hash_function"],
+						verbose = False)
+
+	def set_snapcache_path(self):
+		if "snapcache" in self.settings["options"]:
+			self.settings["snapshot_cache_path"] = \
+				normpath(self.settings["snapshot_cache"] + "/" +
+					self.settings["snapshot"])
+			self.snapcache_lock=\
+				LockDir(self.settings["snapshot_cache_path"])
+			print "Caching snapshot to "+self.settings["snapshot_cache_path"]
+
+	def set_chroot_path(self):
+		"""
+		NOTE: the trailing slash has been removed
+		Things *could* break if you don't use a proper join()
+		"""
+		self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
+			"/tmp/"+self.settings["target_subpath"])
+		self.chroot_lock=LockDir(self.settings["chroot_path"])
+
+	def set_autoresume_path(self):
+		self.settings["autoresume_path"] = normpath(pjoin(
+			self.settings["storedir"], "tmp", self.settings["rel_type"],
+			".autoresume-%s-%s-%s"
+			%(self.settings["target"], self.settings["subarch"],
+				self.settings["version_stamp"])
+			))
+		if "autoresume" in self.settings["options"]:
+			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)
+
+	def set_controller_file(self):
+		self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
+			"/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
+			"-controller.sh")
+
+	def set_iso_volume_id(self):
+		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"]
+
+	def set_action_sequence(self):
+		""" Default action sequence for run method """
+		self.settings["action_sequence"]=["unpack","unpack_snapshot",\
+				"setup_confdir","portage_overlay",\
+				"base_dirs","bind","chroot_setup","setup_environment",\
+				"run_local","preclean","unbind","clean"]
+#		if "TARBALL" in self.settings or \
+#			"fetch" not in self.settings["options"]:
+		if "fetch" not in self.settings["options"]:
+			self.settings["action_sequence"].append("capture")
+		self.settings["action_sequence"].append("clear_autoresume")
+
+	def set_use(self):
+		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 "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"])
+
+	def set_mounts(self):
+		pass
+
+	def set_packages(self):
+		pass
+
+	def set_rm(self):
+		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["spec_prefix"]+"/linuxrc" in self.settings:
+			if type(self.settings[self.settings["spec_prefix"]+\
+				"/linuxrc"])==types.StringType:
+				self.settings["linuxrc"]=\
+					self.settings[self.settings["spec_prefix"]+"/linuxrc"]
+				del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
+
+	def set_busybox_config(self):
+		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"]=\
+					self.settings[self.settings["spec_prefix"]+"/busybox_config"]
+				del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
+
+	def set_portage_overlay(self):
+		if "portage_overlay" in self.settings:
+			if type(self.settings["portage_overlay"])==types.StringType:
+				self.settings["portage_overlay"]=\
+					self.settings["portage_overlay"].split()
+			print "portage_overlay directories are set to: \""+\
+				string.join(self.settings["portage_overlay"])+"\""
+
+	def set_overlay(self):
+		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"]=\
+					self.settings[self.settings["spec_prefix"]+\
+					"/overlay"].split()
+
+	def set_root_overlay(self):
+		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"]=\
+					self.settings[self.settings["spec_prefix"]+\
+					"/root_overlay"].split()
+
+	def set_root_path(self):
+		""" ROOT= variable for emerges """
+		self.settings["root_path"]="/"
+
+	def set_valid_build_kernel_vars(self,addlargs):
+		if "boot/kernel" in addlargs:
+			if type(addlargs["boot/kernel"])==types.StringType:
+				loopy=[addlargs["boot/kernel"]]
+			else:
+				loopy=addlargs["boot/kernel"]
+
+			for x in loopy:
+				self.valid_values.append("boot/kernel/"+x+"/aliases")
+				self.valid_values.append("boot/kernel/"+x+"/config")
+				self.valid_values.append("boot/kernel/"+x+"/console")
+				self.valid_values.append("boot/kernel/"+x+"/extraversion")
+				self.valid_values.append("boot/kernel/"+x+"/gk_action")
+				self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
+				self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
+				self.valid_values.append("boot/kernel/"+x+"/machine_type")
+				self.valid_values.append("boot/kernel/"+x+"/sources")
+				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 "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["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"]
+
+	def kill_chroot_pids(self):
+		print "Checking for processes running in chroot and killing them."
+
+		"""
+		Force environment variables to be exported so script can see them
+		"""
+		self.setup_environment()
+
+		if os.path.exists(self.settings["sharedir"]+\
+			"/targets/support/kill-chroot-pids.sh"):
+			cmd("/bin/bash "+self.settings["sharedir"]+\
+				"/targets/support/kill-chroot-pids.sh",\
+				"kill-chroot-pids script failed.",env=self.env)
+
+	def mount_safety_check(self):
+		"""
+		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.
+		Returns 1 on ok, 0 on "something is still mounted" case.
+		"""
+
+		if not os.path.exists(self.settings["chroot_path"]):
+			return
+
+		print "self.mounts =", self.mounts
+		for x in self.mounts:
+			target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
+			print "mount_safety_check() x =", x, target
+			if not os.path.exists(target):
+				continue
+
+			if ismount(target):
+				""" Something is still mounted "" """
+				try:
+					print target + " is still mounted; performing auto-bind-umount...",
+					""" Try to umount stuff ourselves """
+					self.unbind()
+					if ismount(target):
+						raise CatalystError, "Auto-unbind failed for " + target
+					else:
+						print "Auto-unbind successful..."
+				except CatalystError:
+					raise CatalystError, "Unable to auto-unbind " + target
+
+	def unpack(self):
+		unpack=True
+
+		unpack_resume = pjoin(self.settings["autoresume_path"], "unpack")
+		clst_unpack_hash=read_from_clst(unpack_resume)
+
+		if "seedcache" in self.settings["options"]:
+			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"]
+				display_msg="\nStarting rsync from "+\
+					self.settings["source_path"]+"\nto "+\
+					self.settings["chroot_path"]+\
+					" (This may take some time) ...\n"
+				error_msg="Rsync of "+self.settings["source_path"]+" to "+\
+					self.settings["chroot_path"]+" failed."
+			else:
+				""" SEEDCACHE is a not a directory, try untar'ing """
+				print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
+				display_msg="\nStarting tar extract from "+\
+					self.settings["source_path"]+"\nto "+\
+					self.settings["chroot_path"]+\
+						" (This may take some time) ...\n"
+				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."
+		else:
+			""" No SEEDCACHE, use tar """
+			display_msg="\nStarting tar extract from "+\
+				self.settings["source_path"]+"\nto "+\
+				self.settings["chroot_path"]+\
+				" (This may take some time) ...\n"
+			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 "autoresume" in self.settings["options"]:
+			if os.path.isdir(self.settings["source_path"]) \
+				and os.path.exists(unpack_resume):
+				""" Autoresume is valid, SEEDCACHE is valid """
+				unpack=False
+				invalid_snapshot=False
+
+			elif os.path.isfile(self.settings["source_path"]) \
+				and self.settings["source_path_hash"]==clst_unpack_hash:
+				""" Autoresume is valid, tarball is valid """
+				unpack=False
+				invalid_snapshot=True
+
+			elif os.path.isdir(self.settings["source_path"]) \
+				and not os.path.exists(unpack_resume):
+				""" Autoresume is invalid, SEEDCACHE """
+				unpack=True
+				invalid_snapshot=False
+
+			elif os.path.isfile(self.settings["source_path"]) \
+				and self.settings["source_path_hash"]!=clst_unpack_hash:
+				""" Autoresume is invalid, tarball """
+				unpack=True
+				invalid_snapshot=True
+		else:
+			""" No autoresume, SEEDCACHE """
+			if "seedcache" in self.settings["options"]:
+				""" SEEDCACHE so let's run rsync and let it clean up """
+				if os.path.isdir(self.settings["source_path"]):
+					unpack=True
+					invalid_snapshot=False
+				elif os.path.isfile(self.settings["source_path"]):
+					""" Tarball so unpack and remove anything already there """
+					unpack=True
+					invalid_snapshot=True
+				""" No autoresume, no SEEDCACHE """
+			else:
+				""" Tarball so unpack and remove anything already there """
+				if os.path.isfile(self.settings["source_path"]):
+					unpack=True
+					invalid_snapshot=True
+				elif os.path.isdir(self.settings["source_path"]):
+					""" We should never reach this, so something is very wrong """
+					raise CatalystError,\
+						"source path is a dir but seedcache is not enabled"
+
+		if unpack:
+			self.mount_safety_check()
+
+			if invalid_snapshot:
+				if "autoresume" in self.settings["options"]:
+					print "No Valid Resume point detected, cleaning up..."
+
+				self.clear_autoresume()
+				self.clear_chroot()
+
+			if not os.path.exists(self.settings["chroot_path"]):
+				os.makedirs(self.settings["chroot_path"])
+
+			if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
+				os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
+
+			if "pkgcache" in self.settings["options"]:
+				if not os.path.exists(self.settings["pkgcache_path"]):
+					os.makedirs(self.settings["pkgcache_path"],0755)
+
+			if "kerncache" in self.settings["options"]:
+				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 "source_path_hash" in self.settings:
+				myf=open(unpack_resume,"w")
+				myf.write(self.settings["source_path_hash"])
+				myf.close()
+			else:
+				touch(unpack_resume)
+		else:
+			print "Resume point detected, skipping unpack operation..."
+
+	def unpack_snapshot(self):
+		unpack=True
+		unpack_portage_resume = pjoin(self.settings["autoresume_path"],
+			"unpack_portage")
+		snapshot_hash=read_from_clst(unpack_portage_resume)
+
+		if "snapcache" in self.settings["options"]:
+			snapshot_cache_hash=\
+				read_from_clst(self.settings["snapshot_cache_path"] + "/" +
+					"catalyst-hash")
+			destdir=self.settings["snapshot_cache_path"]
+			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"]+\
+				" (This can take a long time)..."
+			cleanup_errmsg="Error removing existing snapshot cache directory."
+			self.snapshot_lock_object=self.snapcache_lock
+
+			if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
+				print "Valid snapshot cache, skipping unpack of portage tree..."
+				unpack=False
+		else:
+			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)..."
+			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 "autoresume" in self.settings["options"] \
+				and os.path.exists(self.settings["chroot_path"]+\
+					self.settings["portdir"]) \
+				and os.path.exists(unpack_portage_resume) \
+				and self.settings["snapshot_path_hash"] == snapshot_hash:
+					print \
+						"Valid Resume point detected, skipping unpack of portage tree..."
+					unpack=False
+
+		if unpack:
+			if "snapcache" in self.settings["options"]:
+				self.snapshot_lock_object.write_lock()
+			if os.path.exists(destdir):
+				print cleanup_msg
+				cleanup_cmd="rm -rf "+destdir
+				cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
+			if not os.path.exists(destdir):
+				os.makedirs(destdir,0755)
+
+			print "Unpacking portage tree (This can take a long time) ..."
+			cmd(unpack_cmd,unpack_errmsg,env=self.env)
+
+			if "snapcache" in self.settings["options"]:
+				myf=open(self.settings["snapshot_cache_path"] +
+					"/" + "catalyst-hash","w")
+				myf.write(self.settings["snapshot_path_hash"])
+				myf.close()
+			else:
+				print "Setting snapshot autoresume point"
+				myf=open(unpack_portage_resume,"w")
+				myf.write(self.settings["snapshot_path_hash"])
+				myf.close()
+
+			if "snapcache" in self.settings["options"]:
+				self.snapshot_lock_object.unlock()
+
+	def config_profile_link(self):
+		config_protect_link_resume = pjoin(self.settings["autoresume_path"],
+			"config_profile_link")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(config_protect_link_resume):
+			print \
+				"Resume point detected, skipping config_profile_link operation..."
+		else:
+			# 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/portage/make.profile",\
+					"Error zapping profile link",env=self.env)
+			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/portage/make.profile",\
+				"Error creating profile link",env=self.env)
+			touch(config_protect_link_resume)
+
+	def setup_confdir(self):
+		setup_confdir_resume = pjoin(self.settings["autoresume_path"],
+			"setup_confdir")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(setup_confdir_resume):
+			print "Resume point detected, skipping setup_confdir operation..."
+		else:
+			if "portage_confdir" in self.settings:
+				print "Configuring /etc/portage..."
+				cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
+					self.settings["chroot_path"]+"/etc/portage/",\
+					"Error copying /etc/portage",env=self.env)
+				touch(setup_confdir_resume)
+
+	def portage_overlay(self):
+		""" We copy the contents of our overlays to /usr/local/portage """
+		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"]+\
+						self.settings["local_overlay"],\
+						"Could not make portage_overlay dir",env=self.env)
+					cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
+						self.settings["local_overlay"],\
+						"Could not copy portage_overlay",env=self.env)
+
+	def root_overlay(self):
+		""" Copy over the root_overlay """
+		if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
+			for x in self.settings[self.settings["spec_prefix"]+\
+				"/root_overlay"]:
+				if os.path.exists(x):
+					print "Copying root_overlay: "+x
+					cmd("rsync -a "+x+"/ "+\
+						self.settings["chroot_path"],\
+						self.settings["spec_prefix"]+"/root_overlay: "+x+\
+						" copy failed.",env=self.env)
+
+	def base_dirs(self):
+		pass
+
+	def bind(self):
+		for x in self.mounts:
+			#print "bind(); x =", x
+			target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
+			if not os.path.exists(target):
+				os.makedirs(target, 0755)
+
+			if not os.path.exists(self.mountmap[x]):
+				if self.mountmap[x] not in ["tmpfs", "shmfs"]:
+					os.makedirs(self.mountmap[x], 0755)
+
+			src=self.mountmap[x]
+			#print "bind(); src =", src
+			if "snapcache" in self.settings["options"] and x == "portdir":
+				self.snapshot_lock_object.read_lock()
+			if os.uname()[0] == "FreeBSD":
+				if src == "/dev":
+					cmd = "mount -t devfs none " + target
+					retval=os.system(cmd)
+				else:
+					cmd = "mount_nullfs " + src + " " + target
+					retval=os.system(cmd)
+			else:
+				if src == "tmpfs":
+					if "var_tmpfs_portage" in self.settings:
+						cmd = "mount -t tmpfs -o size=" + \
+							self.settings["var_tmpfs_portage"] + "G " + \
+							src + " " + target
+						retval=os.system(cmd)
+				elif src == "shmfs":
+					cmd = "mount -t tmpfs -o noexec,nosuid,nodev shm " + target
+					retval=os.system(cmd)
+				else:
+					cmd = "mount --bind " + src + " " + target
+					#print "bind(); cmd =", cmd
+					retval=os.system(cmd)
+			if retval!=0:
+				self.unbind()
+				raise CatalystError,"Couldn't bind mount " + src
+
+	def unbind(self):
+		ouch=0
+		mypath=self.settings["chroot_path"]
+		myrevmounts=self.mounts[:]
+		myrevmounts.reverse()
+		""" Unmount in reverse order for nested bind-mounts """
+		for x in myrevmounts:
+			target = normpath(mypath + self.target_mounts[x])
+			if not os.path.exists(target):
+				continue
+
+			if not ismount(target):
+				continue
+
+			retval=os.system("umount " + target)
+
+			if retval!=0:
+				warn("First attempt to unmount: " + target + " failed.")
+				warn("Killing any pids still running in the chroot")
+
+				self.kill_chroot_pids()
+
+				retval2 = os.system("umount " + target)
+				if retval2!=0:
+					ouch=1
+					warn("Couldn't umount bind mount: " + target)
+
+			if "snapcache" in self.settings["options"] and x == "/usr/portage":
+				try:
+					"""
+					It's possible the snapshot lock object isn't created yet.
+					This is because mount safety check calls unbind before the
+					target is fully initialized
+					"""
+					self.snapshot_lock_object.unlock()
+				except:
+					pass
+		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.makeconf=read_makeconf(self.settings["chroot_path"]+\
+			"/etc/portage/make.conf")
+		self.override_cbuild()
+		self.override_chost()
+		self.override_cflags()
+		self.override_cxxflags()
+		self.override_ldflags()
+		chroot_setup_resume = pjoin(self.settings["autoresume_path"],
+			"chroot_setup")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(chroot_setup_resume):
+			print "Resume point detected, skipping chroot_setup operation..."
+		else:
+			print "Setting up chroot..."
+
+			#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 "envscript" in self.settings:
+				if not os.path.exists(self.settings["envscript"]):
+					raise CatalystError,\
+						"Can't find envscript "+self.settings["envscript"]
+
+				print "\nWarning!!!!"
+				print "\tOverriding certain env variables may cause catastrophic failure."
+				print "\tIf your build fails look here first as the possible problem."
+				print "\tCatalyst assumes you know what you are doing when setting"
+				print "\t\tthese variables."
+				print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
+				print "\tYou have been warned\n"
+
+				cmd("cp "+self.settings["envscript"]+" "+\
+					self.settings["chroot_path"]+"/tmp/envscript",\
+					"Could not copy envscript into place.",env=self.env)
+
+			"""
+			Copy over /etc/hosts from the host in case there are any
+			specialties in there
+			"""
+			if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
+				cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
+					self.settings["chroot_path"]+"/etc/hosts.catalyst",\
+					"Could not backup /etc/hosts",env=self.env)
+				cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
+					"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/portage/make.conf",\
+				"Could not remove "+self.settings["chroot_path"]+\
+				"/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 "CFLAGS" in self.settings:
+				myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
+			if "CXXFLAGS" in self.settings:
+				if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
+					myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
+				else:
+					myf.write('CXXFLAGS="${CFLAGS}"\n')
+			else:
+				myf.write('CXXFLAGS="${CFLAGS}"\n')
+
+			if "LDFLAGS" in self.settings:
+				myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
+				myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
+			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')
+
+			myf.write("# WARNING: Changing your CHOST is not something that should be done lightly.\n# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.\n")
+			myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
+
+			""" Figure out what our USE vars are for building """
+			myusevars=[]
+			if "HOSTUSE" in self.settings:
+				myusevars.extend(self.settings["HOSTUSE"])
+
+			if "use" in self.settings:
+				myusevars.extend(self.settings["use"])
+
+			if myusevars:
+				myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
+				myusevars = sorted(set(myusevars))
+				myf.write('USE="'+string.join(myusevars)+'"\n')
+				if '-*' in myusevars:
+					print "\nWarning!!!  "
+					print "\tThe use of -* in "+self.settings["spec_prefix"]+\
+						"/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="%s"\n' % self.settings['distdir'])
+			myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
+
+			""" Setup the 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/portage/make.conf "+\
+				self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
+				"Could not backup /etc/portage/make.conf",env=self.env)
+			touch(chroot_setup_resume)
+
+	def fsscript(self):
+		fsscript_resume = pjoin(self.settings["autoresume_path"], "fsscript")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(fsscript_resume):
+			print "Resume point detected, skipping fsscript operation..."
+		else:
+			if "fsscript" in self.settings:
+				if os.path.exists(self.settings["controller_file"]):
+					cmd(self.settings["controller_file"]+\
+						" fsscript","fsscript script failed.",env=self.env)
+					touch(fsscript_resume)
+
+	def rcupdate(self):
+		rcupdate_resume = pjoin(self.settings["autoresume_path"], "rcupdate")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(rcupdate_resume):
+			print "Resume point detected, skipping rcupdate operation..."
+		else:
+			if os.path.exists(self.settings["controller_file"]):
+				cmd(self.settings["controller_file"]+" rc-update",\
+					"rc-update script failed.",env=self.env)
+				touch(rcupdate_resume)
+
+	def clean(self):
+		clean_resume = pjoin(self.settings["autoresume_path"], "clean")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(clean_resume):
+			print "Resume point detected, skipping clean operation..."
+		else:
+			for x in self.settings["cleanables"]:
+				print "Cleaning chroot: "+x+"... "
+				cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
+					x,env=self.env)
+
+		""" Put /etc/hosts back into place """
+		if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
+			cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
+				self.settings["chroot_path"]+"/etc/hosts",\
+				"Could not replace /etc/hosts",env=self.env)
+
+		""" Remove our overlay """
+		if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
+			cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
+				"Could not remove " + self.settings["local_overlay"], env=self.env)
+			cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
+				"/etc/portage/make.conf",\
+				"Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
+
+		""" Clean up old and obsoleted files in /etc """
+		if os.path.exists(self.settings["stage_path"]+"/etc"):
+			cmd("find "+self.settings["stage_path"]+\
+				"/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
+				"Could not remove stray files in /etc",env=self.env)
+
+		if os.path.exists(self.settings["controller_file"]):
+			cmd(self.settings["controller_file"]+" clean",\
+				"clean script failed.",env=self.env)
+			touch(clean_resume)
+
+	def empty(self):
+		empty_resume = pjoin(self.settings["autoresume_path"], "empty")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(empty_resume):
+			print "Resume point detected, skipping empty operation..."
+		else:
+			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"]=\
+						self.settings[self.settings["spec_prefix"]+\
+						"/empty"].split()
+				for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
+					myemp=self.settings["destpath"]+x
+					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
+					"""
+					mystat=os.stat(myemp)
+					shutil.rmtree(myemp)
+					os.makedirs(myemp,0755)
+					os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
+					os.chmod(myemp,mystat[ST_MODE])
+			touch(empty_resume)
+
+	def remove(self):
+		remove_resume = pjoin(self.settings["autoresume_path"], "remove")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(remove_resume):
+			print "Resume point detected, skipping remove operation..."
+		else:
+			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
+					operations, so we get easy glob handling.
+					"""
+					print "livecd: removing "+x
+					os.system("rm -rf "+self.settings["chroot_path"]+x)
+				try:
+					if os.path.exists(self.settings["controller_file"]):
+						cmd(self.settings["controller_file"]+\
+							" clean","Clean  failed.",env=self.env)
+						touch(remove_resume)
+				except:
+					self.unbind()
+					raise
+
+	def preclean(self):
+		preclean_resume = pjoin(self.settings["autoresume_path"], "preclean")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(preclean_resume):
+			print "Resume point detected, skipping preclean operation..."
+		else:
+			try:
+				if os.path.exists(self.settings["controller_file"]):
+					cmd(self.settings["controller_file"]+\
+						" preclean","preclean script failed.",env=self.env)
+					touch(preclean_resume)
+
+			except:
+				self.unbind()
+				raise CatalystError, "Build failed, could not execute preclean"
+
+	def capture(self):
+		capture_resume = pjoin(self.settings["autoresume_path"], "capture")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(capture_resume):
+			print "Resume point detected, skipping capture operation..."
+		else:
+			""" Capture target in a tarball """
+			mypath=self.settings["target_path"].split("/")
+			""" Remove filename from path """
+			mypath=string.join(mypath[:-1],"/")
+
+			""" Now make sure path exists """
+			if not os.path.exists(mypath):
+				os.makedirs(mypath)
+
+			print "Creating stage tarball..."
+
+			cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
+				self.settings["stage_path"]+" .",\
+				"Couldn't create stage tarball",env=self.env)
+
+			self.gen_contents_file(self.settings["target_path"])
+			self.gen_digest_file(self.settings["target_path"])
+
+			touch(capture_resume)
+
+	def run_local(self):
+		run_local_resume = pjoin(self.settings["autoresume_path"], "run_local")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(run_local_resume):
+			print "Resume point detected, skipping run_local operation..."
+		else:
+			try:
+				if os.path.exists(self.settings["controller_file"]):
+					cmd(self.settings["controller_file"]+" run",\
+						"run script failed.",env=self.env)
+					touch(run_local_resume)
+
+			except CatalystError:
+				self.unbind()
+				raise CatalystError,"Stage build aborting due to error."
+
+	def setup_environment(self):
+		"""
+		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
+		"""
+		#print "setup_environment(); settings =", list(self.settings)
+		for x in list(self.settings):
+			#print "setup_environment(); processing:", x
+			if x == "options":
+				#self.env['clst_' + x] = ' '.join(self.settings[x])
+				for opt in self.settings[x]:
+					self.env['clst_' + opt.upper()] = "true"
+				continue
+			""" Sanitize var names by doing "s|/-.|_|g" """
+			varname="clst_"+string.replace(x,"/","_")
+			varname=string.replace(varname,"-","_")
+			varname=string.replace(varname,".","_")
+			if type(self.settings[x])==types.StringType:
+				""" Prefix to prevent namespace clashes """
+				#os.environ[varname]=self.settings[x]
+				self.env[varname]=self.settings[x]
+			elif type(self.settings[x])==types.ListType:
+				#os.environ[varname]=string.join(self.settings[x])
+				self.env[varname]=string.join(self.settings[x])
+			elif type(self.settings[x])==types.BooleanType:
+				if self.settings[x]:
+					self.env[varname]="true"
+				else:
+					self.env[varname]="false"
+		if "makeopts" in self.settings:
+			self.env["MAKEOPTS"]=self.settings["makeopts"]
+
+	def run(self):
+		self.chroot_lock.write_lock()
+
+		""" Kill any pids in the chroot "" """
+		self.kill_chroot_pids()
+
+		""" Check for mounts right away and abort if we cannot unmount them """
+		self.mount_safety_check()
+
+		if "clear-autoresume" in self.settings["options"]:
+			self.clear_autoresume()
+
+		if "purgetmponly" in self.settings["options"]:
+			self.purge()
+			return
+
+		if "PURGEONLY" in self.settings:
+			self.purge()
+			return
+
+		if "purge" in self.settings["options"]:
+			self.purge()
+
+		for x in self.settings["action_sequence"]:
+			print "--- Running action sequence: "+x
+			sys.stdout.flush()
+			try:
+				apply(getattr(self,x))
+			except:
+				self.mount_safety_check()
+				raise
+
+		self.chroot_lock.unlock()
+
+	def unmerge(self):
+		unmerge_resume = pjoin(self.settings["autoresume_path"], "unmerge")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(unmerge_resume):
+			print "Resume point detected, skipping unmerge operation..."
+		else:
+			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"]=\
+						[self.settings[self.settings["spec_prefix"]+"/unmerge"]]
+				myunmerge=\
+					self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
+
+				for x in range(0,len(myunmerge)):
+					"""
+					Surround args with quotes for passing to bash, allows
+					things like "<" to remain intact
+					"""
+					myunmerge[x]="'"+myunmerge[x]+"'"
+				myunmerge=string.join(myunmerge)
+
+				""" Before cleaning, unmerge stuff """
+				try:
+					cmd(self.settings["controller_file"]+\
+						" unmerge "+ myunmerge,"Unmerge script failed.",\
+						env=self.env)
+					print "unmerge shell script"
+				except CatalystError:
+					self.unbind()
+					raise
+				touch(unmerge_resume)
+
+	def target_setup(self):
+		target_setup_resume = pjoin(self.settings["autoresume_path"],
+			"target_setup")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(target_setup_resume):
+			print "Resume point detected, skipping target_setup operation..."
+		else:
+			print "Setting up filesystems per filesystem type"
+			cmd(self.settings["controller_file"]+\
+				" target_image_setup "+ self.settings["target_path"],\
+				"target_image_setup script failed.",env=self.env)
+			touch(target_setup_resume)
+
+	def setup_overlay(self):
+		setup_overlay_resume = pjoin(self.settings["autoresume_path"],
+			"setup_overlay")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(setup_overlay_resume):
+			print "Resume point detected, skipping setup_overlay operation..."
+		else:
+			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"],\
+							self.settings["spec_prefix"]+"overlay: "+x+\
+							" copy failed.",env=self.env)
+				touch(setup_overlay_resume)
+
+	def create_iso(self):
+		create_iso_resume = pjoin(self.settings["autoresume_path"], "create_iso")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(create_iso_resume):
+			print "Resume point detected, skipping create_iso operation..."
+		else:
+			""" Create the ISO """
+			if "iso" in self.settings:
+				cmd(self.settings["controller_file"]+" iso "+\
+					self.settings["iso"],"ISO creation script failed.",\
+					env=self.env)
+				self.gen_contents_file(self.settings["iso"])
+				self.gen_digest_file(self.settings["iso"])
+				touch(create_iso_resume)
+			else:
+				print "WARNING: livecd/iso was not defined."
+				print "An ISO Image will not be created."
+
+	def build_packages(self):
+		build_packages_resume = pjoin(self.settings["autoresume_path"],
+			"build_packages")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(build_packages_resume):
+			print "Resume point detected, skipping build_packages operation..."
+		else:
+			if self.settings["spec_prefix"]+"/packages" in self.settings:
+				if "autoresume" in self.settings["options"] \
+					and os.path.exists(self.settings["autoresume_path"]+\
+						"build_packages"):
+					print "Resume point detected, skipping build_packages operation..."
+				else:
+					mypack=\
+						list_bashify(self.settings[self.settings["spec_prefix"]\
+						+"/packages"])
+					try:
+						cmd(self.settings["controller_file"]+\
+							" build_packages "+mypack,\
+							"Error in attempt to build packages",env=self.env)
+						touch(build_packages_resume)
+					except CatalystError:
+						self.unbind()
+						raise CatalystError,self.settings["spec_prefix"]+\
+							"build aborting due to error."
+
+	def build_kernel(self):
+		'''Build all configured kernels'''
+		build_kernel_resume = pjoin(self.settings["autoresume_path"],
+			"build_kernel")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(build_kernel_resume):
+			print "Resume point detected, skipping build_kernel operation..."
+		else:
+			if "boot/kernel" in self.settings:
+				try:
+					mynames=self.settings["boot/kernel"]
+					if type(mynames)==types.StringType:
+						mynames=[mynames]
+					"""
+					Execute the script that sets up the kernel build environment
+					"""
+					cmd(self.settings["controller_file"]+\
+						" pre-kmerge ","Runscript pre-kmerge failed",\
+						env=self.env)
+					for kname in mynames:
+						self._build_kernel(kname=kname)
+					touch(build_kernel_resume)
+				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"
+		kname_resume = pjoin(self.settings["autoresume_path"],
+			"build_kernel_" + kname)
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(kname_resume):
+			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(kname_resume)
+
+		"""
+		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):
+		bootloader_resume = pjoin(self.settings["autoresume_path"], "bootloader")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(bootloader_resume):
+			print "Resume point detected, skipping bootloader operation..."
+		else:
+			try:
+				cmd(self.settings["controller_file"]+\
+					" bootloader " + self.settings["target_path"],\
+					"Bootloader script failed.",env=self.env)
+				touch(bootloader_resume)
+			except CatalystError:
+				self.unbind()
+				raise CatalystError,"Script aborting due to error."
+
+	def livecd_update(self):
+		livecd_update_resume = pjoin(self.settings["autoresume_path"],
+			"livecd_update")
+		if "autoresume" in self.settings["options"] \
+			and os.path.exists(livecd_update_resume):
+			print "Resume point detected, skipping build_packages operation..."
+		else:
+			try:
+				cmd(self.settings["controller_file"]+\
+					" livecd-update","livecd-update failed.",env=self.env)
+				touch(livecd_update_resume)
+
+			except CatalystError:
+				self.unbind()
+				raise CatalystError,"build aborting due to livecd_update error."
+
+# vim: ts=4 sw=4 sta et sts=4 ai
diff --git a/catalyst/base/targetbase.py b/catalyst/base/targetbase.py
new file mode 100644
index 0000000..e0c03df
--- /dev/null
+++ b/catalyst/base/targetbase.py
@@ -0,0 +1,15 @@
+import os
+
+from catalyst.support import *
+
+class TargetBase(object):
+	"""
+	The toplevel class for all targets. This is about as generic as we get.
+	"""
+	def __init__(self, myspec, addlargs):
+		addl_arg_parse(myspec,addlargs,self.required_values,self.valid_values)
+		self.settings=myspec
+		self.env = {
+			'PATH': '/bin:/sbin:/usr/bin:/usr/sbin',
+			'TERM': os.getenv('TERM', 'dumb'),
+			}
diff --git a/catalyst/targets/clearbase.py b/catalyst/targets/clearbase.py
deleted file mode 100644
index 8519acc..0000000
--- a/catalyst/targets/clearbase.py
+++ /dev/null
@@ -1,115 +0,0 @@
-
-import os
-import shutil
-from stat import ST_UID, ST_GID, ST_MODE
-
-
-from catalyst.support import cmd, countdown
-
-
-class ClearBase(object):
-	"""
-	This class does all of clearing after task completion
-	"""
-	def __init__(self, myspec):
-		self.settings = myspec
-
-
-
-	def clear_autoresume(self):
-		""" Clean resume points since they are no longer needed """
-		if "autoresume" in self.settings["options"]:
-			print "Removing AutoResume Points: ..."
-		myemp=self.settings["autoresume_path"]
-		if os.path.isdir(myemp):
-				if "autoresume" in self.settings["options"]:
-					print "Emptying directory",myemp
-				"""
-				stat the dir, delete the dir, recreate the dir and set
-				the proper perms and ownership
-				"""
-				mystat=os.stat(myemp)
-				if os.uname()[0] == "FreeBSD":
-					cmd("chflags -R noschg "+myemp,\
-						"Could not remove immutable flag for file "\
-						+myemp)
-				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
-				shutil.rmtree(myemp)
-				os.makedirs(myemp,0755)
-				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-				os.chmod(myemp,mystat[ST_MODE])
-
-
-	def clear_chroot(self):
-		myemp=self.settings["chroot_path"]
-		if os.path.isdir(myemp):
-			print "Emptying directory",myemp
-			"""
-			stat the dir, delete the dir, recreate the dir and set
-			the proper perms and ownership
-			"""
-			mystat=os.stat(myemp)
-			#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
-			""" There's no easy way to change flags recursively in python """
-			if os.uname()[0] == "FreeBSD":
-				os.system("chflags -R noschg "+myemp)
-			shutil.rmtree(myemp)
-			os.makedirs(myemp,0755)
-			os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-			os.chmod(myemp,mystat[ST_MODE])
-
-
-	def clear_packages(self):
-		if "pkgcache" in self.settings["options"]:
-			print "purging the pkgcache ..."
-
-			myemp=self.settings["pkgcache_path"]
-			if os.path.isdir(myemp):
-				print "Emptying directory",myemp
-				"""
-				stat the dir, delete the dir, recreate the dir and set
-				the proper perms and ownership
-				"""
-				mystat=os.stat(myemp)
-				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
-				shutil.rmtree(myemp)
-				os.makedirs(myemp,0755)
-				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-				os.chmod(myemp,mystat[ST_MODE])
-
-
-	def clear_kerncache(self):
-		if "kerncache" in self.settings["options"]:
-			print "purging the kerncache ..."
-
-			myemp=self.settings["kerncache_path"]
-			if os.path.isdir(myemp):
-				print "Emptying directory",myemp
-				"""
-				stat the dir, delete the dir, recreate the dir and set
-				the proper perms and ownership
-				"""
-				mystat=os.stat(myemp)
-				#cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
-				shutil.rmtree(myemp)
-				os.makedirs(myemp,0755)
-				os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-				os.chmod(myemp,mystat[ST_MODE])
-
-
-	def purge(self):
-		countdown(10,"Purging Caches ...")
-		if any(k in self.settings["options"] for k in ("purge","purgeonly","purgetmponly")):
-			print "clearing autoresume ..."
-			self.clear_autoresume()
-
-			print "clearing chroot ..."
-			self.clear_chroot()
-
-			if "PURGETMPONLY" not in self.settings:
-				print "clearing package cache ..."
-				self.clear_packages()
-
-			print "clearing kerncache ..."
-			self.clear_kerncache()
-
diff --git a/catalyst/targets/embedded_target.py b/catalyst/targets/embedded_target.py
index 7cee7a6..528d545 100644
--- a/catalyst/targets/embedded_target.py
+++ b/catalyst/targets/embedded_target.py
@@ -10,12 +10,12 @@ ROOT=/tmp/submerge emerge --something foo bar .
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,string,imp,types,shutil
-from catalyst.support import *
-from generic_stage_target import *
-from stat import *
 
-class embedded_target(generic_stage_target):
+from catalyst.support import normpath
+
+from catalyst.base.stagebase import StageBase
+
+class embedded_target(StageBase):
 	"""
 	Builder class for embedded target
 	"""
@@ -27,7 +27,7 @@ class embedded_target(generic_stage_target):
 		if "embedded/fs-type" in addlargs:
 			self.valid_values.append("embedded/fs-ops")
 
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 		self.set_build_kernel_vars(addlargs)
 
 	def set_action_sequence(self):
diff --git a/catalyst/targets/genbase.py b/catalyst/targets/genbase.py
deleted file mode 100644
index e818781..0000000
--- a/catalyst/targets/genbase.py
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-import os
-
-
-class GenBase(object):
-	"""
-	This class does generation of the contents and digests files.
-	"""
-	def __init__(self,myspec):
-		self.settings = myspec
-
-
-	def gen_contents_file(self,file):
-		if os.path.exists(file+".CONTENTS"):
-			os.remove(file+".CONTENTS")
-		if "contents" in self.settings:
-			contents_map = self.settings["contents_map"]
-			if os.path.exists(file):
-				myf=open(file+".CONTENTS","w")
-				keys={}
-				for i in self.settings["contents"].split():
-					keys[i]=1
-					array=keys.keys()
-					array.sort()
-				for j in array:
-					contents = contents_map.generate_contents(file, j,
-						verbose="VERBOSE" in self.settings)
-					if contents:
-						myf.write(contents)
-				myf.close()
-
-	def gen_digest_file(self,file):
-		if os.path.exists(file+".DIGESTS"):
-			os.remove(file+".DIGESTS")
-		if "digests" in self.settings:
-			hash_map = self.settings["hash_map"]
-			if os.path.exists(file):
-				myf=open(file+".DIGESTS","w")
-				keys={}
-				for i in self.settings["digests"].split():
-					keys[i]=1
-					array=keys.keys()
-					array.sort()
-				for f in [file, file+'.CONTENTS']:
-					if os.path.exists(f):
-						if "all" in array:
-							for k in list(hash_map.hash_map):
-								hash = hash_map.generate_hash(f,hash_=k,
-									verbose = "VERBOSE" in self.settings)
-								myf.write(hash)
-						else:
-							for j in array:
-								hash = hash_map.generate_hash(f,hash_=j,
-									verbose = "VERBOSE" in self.settings)
-								myf.write(hash)
-				myf.close()
-
diff --git a/catalyst/targets/generic_stage_target.py b/catalyst/targets/generic_stage_target.py
deleted file mode 100644
index 296eee3..0000000
--- a/catalyst/targets/generic_stage_target.py
+++ /dev/null
@@ -1,1630 +0,0 @@
-
-import os
-import string
-import imp
-import types
-import shutil
-import sys
-from stat import ST_UID, ST_GID, ST_MODE
-
-# for convienience
-pjoin = os.path.join
-
-from catalyst.defaults import (SOURCE_MOUNT_DEFAULTS, TARGET_MOUNT_DEFAULTS,
-	PORT_LOGDIR_CLEAN)
-from catalyst.support import (CatalystError, msg, file_locate, normpath,
-	touch, cmd, warn, list_bashify, read_makeconf, read_from_clst, ismount)
-from catalyst.targets.targetbase import TargetBase
-from catalyst.targets.clearbase import ClearBase
-from catalyst.targets.genbase import GenBase
-from catalyst.lock import LockDir
-
-
-class generic_stage_target(TargetBase, ClearBase, GenBase):
-	"""
-	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"])
-
-		self.valid_values.extend(["version_stamp","target","subarch",\
-			"rel_type","profile","snapshot","source_subpath","portage_confdir",\
-			"cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
-			"distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
-
-		self.set_valid_build_kernel_vars(addlargs)
-		TargetBase.__init__(self, myspec, addlargs)
-		GenBase.__init__(self, myspec)
-		ClearBase.__init__(self, myspec)
-
-		"""
-		The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
-		work better with vapier's CBUILD stuff. I've removed the "monolithic"
-		machinemap from this file and split up its contents amongst the
-		various arch/foo.py files.
-
-		When register() is called on each module in the arch/ dir, it now
-		returns a tuple instead of acting on the subarchmap dict that is
-		passed to it. The tuple contains the values that were previously
-		added to subarchmap as well as a new list of CHOSTs that go along
-		with that arch. This allows us to build machinemap on the fly based
-		on the keys in subarchmap and the values of the 2nd list returned
-		(tmpmachinemap).
-
-		Also, after talking with vapier. I have a slightly better idea of what
-		certain variables are used for and what they should be set to. Neither
-		'buildarch' or 'hostarch' are used directly, so their value doesn't
-		really matter. They are just compared to determine if we are
-		cross-compiling. Because of this, they are just set to the name of the
-		module in arch/ that the subarch is part of to make things simpler.
-		The entire build process is still based off of 'subarch' like it was
-		previously. -agaffney
-		"""
-
-		self.archmap = {}
-		self.subarchmap = {}
-		machinemap = {}
-		arch_dir = self.settings["PythonDir"] + "/arch/"
-		for x in [x[:-3] for x in os.listdir(arch_dir) if x.endswith(".py")]:
-			if x == "__init__":
-				continue
-			try:
-				fh=open(arch_dir + x + ".py")
-				"""
-				This next line loads the plugin as a module and assigns it to
-				archmap[x]
-				"""
-				self.archmap[x]=imp.load_module(x,fh,"../arch/" + x + ".py",
-					(".py", "r", imp.PY_SOURCE))
-				"""
-				This next line registers all the subarches supported in the
-				plugin
-				"""
-				tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
-				self.subarchmap.update(tmpsubarchmap)
-				for machine in tmpmachinemap:
-					machinemap[machine] = x
-				for subarch in tmpsubarchmap:
-					machinemap[subarch] = x
-				fh.close()
-			except IOError:
-				"""
-				This message should probably change a bit, since everything in
-				the dir should load just fine. If it doesn't, it's probably a
-				syntax error in the module
-				"""
-				msg("Can't find/load " + x + ".py plugin in " + arch_dir)
-
-		if "chost" in self.settings:
-			hostmachine = self.settings["chost"].split("-")[0]
-			if hostmachine not in machinemap:
-				raise CatalystError, "Unknown host machine type "+hostmachine
-			self.settings["hostarch"]=machinemap[hostmachine]
-		else:
-			hostmachine = self.settings["subarch"]
-			if hostmachine in machinemap:
-				hostmachine = machinemap[hostmachine]
-			self.settings["hostarch"]=hostmachine
-		if "cbuild" in self.settings:
-			buildmachine = self.settings["cbuild"].split("-")[0]
-		else:
-			buildmachine = os.uname()[4]
-		if buildmachine not in machinemap:
-			raise CatalystError, "Unknown build machine type "+buildmachine
-		self.settings["buildarch"]=machinemap[buildmachine]
-		self.settings["crosscompile"]=(self.settings["hostarch"]!=\
-			self.settings["buildarch"])
-
-		""" Call arch constructor, pass our settings """
-		try:
-			self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
-		except KeyError:
-			print "Invalid subarch: "+self.settings["subarch"]
-			print "Choose one of the following:",
-			for x in self.subarchmap:
-				print x,
-			print
-			sys.exit(2)
-
-		print "Using target:",self.settings["target"]
-		""" Print a nice informational message """
-		if self.settings["buildarch"]==self.settings["hostarch"]:
-			print "Building natively for",self.settings["hostarch"]
-		elif self.settings["crosscompile"]:
-			print "Cross-compiling on",self.settings["buildarch"],\
-				"for different machine type",self.settings["hostarch"]
-		else:
-			print "Building on",self.settings["buildarch"],\
-				"for alternate personality type",self.settings["hostarch"]
-
-		""" This must be set first as other set_ options depend on this """
-		self.set_spec_prefix()
-
-		""" Define all of our core variables """
-		self.set_target_profile()
-		self.set_target_subpath()
-		self.set_source_subpath()
-
-		""" Set paths """
-		self.set_snapshot_path()
-		self.set_root_path()
-		self.set_source_path()
-		self.set_snapcache_path()
-		self.set_chroot_path()
-		self.set_autoresume_path()
-		self.set_dest_path()
-		self.set_stage_path()
-		self.set_target_path()
-
-		self.set_controller_file()
-		self.set_action_sequence()
-		self.set_use()
-		self.set_cleanables()
-		self.set_iso_volume_id()
-		self.set_build_kernel_vars()
-		self.set_fsscript()
-		self.set_install_mask()
-		self.set_rcadd()
-		self.set_rcdel()
-		self.set_cdtar()
-		self.set_fstype()
-		self.set_fsops()
-		self.set_iso()
-		self.set_packages()
-		self.set_rm()
-		self.set_linuxrc()
-		self.set_busybox_config()
-		self.set_overlay()
-		self.set_portage_overlay()
-		self.set_root_overlay()
-
-		"""
-		This next line checks to make sure that the specified variables exist
-		on disk.
-		"""
-		#pdb.set_trace()
-		file_locate(self.settings,["source_path","snapshot_path","distdir"],\
-			expand=0)
-		""" If we are using portage_confdir, check that as well. """
-		if "portage_confdir" in self.settings:
-			file_locate(self.settings,["portage_confdir"],expand=0)
-
-		""" Setup our mount points """
-		# initialize our target mounts.
-		self.target_mounts = TARGET_MOUNT_DEFAULTS.copy()
-
-		self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
-		# initialize our source mounts
-		self.mountmap = SOURCE_MOUNT_DEFAULTS.copy()
-		# update them from settings
-		self.mountmap["distdir"] = self.settings["distdir"]
-		if "snapcache" not in self.settings["options"]:
-			self.mounts.remove("portdir")
-			self.mountmap["portdir"] = None
-		else:
-			self.mountmap["portdir"] = normpath("/".join([
-				self.settings["snapshot_cache_path"],
-				self.settings["repo_name"],
-				]))
-		if os.uname()[0] == "Linux":
-			self.mounts.append("devpts")
-			self.mounts.append("shm")
-
-		self.set_mounts()
-
-		"""
-		Configure any user specified options (either in catalyst.conf or on
-		the command line).
-		"""
-		if "pkgcache" in self.settings["options"]:
-			self.set_pkgcache_path()
-			print "Location of the package cache is "+\
-				self.settings["pkgcache_path"]
-			self.mounts.append("packagedir")
-			self.mountmap["packagedir"] = self.settings["pkgcache_path"]
-
-		if "kerncache" in self.settings["options"]:
-			self.set_kerncache_path()
-			print "Location of the kerncache is "+\
-				self.settings["kerncache_path"]
-			self.mounts.append("kerncache")
-			self.mountmap["kerncache"] = self.settings["kerncache_path"]
-
-		if "ccache" in self.settings["options"]:
-			if "CCACHE_DIR" in os.environ:
-				ccdir=os.environ["CCACHE_DIR"]
-				del os.environ["CCACHE_DIR"]
-			else:
-				ccdir="/root/.ccache"
-			if not os.path.isdir(ccdir):
-				raise CatalystError,\
-					"Compiler cache support can't be enabled (can't find "+\
-					ccdir+")"
-			self.mounts.append("ccache")
-			self.mountmap["ccache"] = ccdir
-			""" for the chroot: """
-			self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
-
-		if "icecream" in self.settings["options"]:
-			self.mounts.append("icecream")
-			self.mountmap["icecream"] = self.settings["icecream"]
-			self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
-				self.env["PATH"]
-
-		if "port_logdir" in self.settings:
-			self.mounts.append("port_logdir")
-			self.mountmap["port_logdir"] = self.settings["port_logdir"]
-			self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
-			self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
-
-	def override_cbuild(self):
-		if "CBUILD" in self.makeconf:
-			self.settings["CBUILD"]=self.makeconf["CBUILD"]
-
-	def override_chost(self):
-		if "CHOST" in self.makeconf:
-			self.settings["CHOST"]=self.makeconf["CHOST"]
-
-	def override_cflags(self):
-		if "CFLAGS" in self.makeconf:
-			self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
-
-	def override_cxxflags(self):
-		if "CXXFLAGS" in self.makeconf:
-			self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
-
-	def override_ldflags(self):
-		if "LDFLAGS" in self.makeconf:
-			self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
-
-	def set_install_mask(self):
-		if "install_mask" in self.settings:
-			if type(self.settings["install_mask"])!=types.StringType:
-				self.settings["install_mask"]=\
-					string.join(self.settings["install_mask"])
-
-	def set_spec_prefix(self):
-		self.settings["spec_prefix"]=self.settings["target"]
-
-	def set_target_profile(self):
-		self.settings["target_profile"]=self.settings["profile"]
-
-	def set_target_subpath(self):
-		self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
-				self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
-				self.settings["version_stamp"]
-
-	def set_source_subpath(self):
-		if type(self.settings["source_subpath"])!=types.StringType:
-			raise CatalystError,\
-				"source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
-
-	def set_pkgcache_path(self):
-		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"]))
-		else:
-			self.settings["pkgcache_path"]=\
-				normpath(self.settings["storedir"]+"/packages/"+\
-				self.settings["target_subpath"]+"/")
-
-	def set_kerncache_path(self):
-		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"]))
-		else:
-			self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
-				"/kerncache/"+self.settings["target_subpath"]+"/")
-
-	def set_target_path(self):
-		self.settings["target_path"]=normpath(self.settings["storedir"]+\
-			"/builds/"+self.settings["target_subpath"]+".tar.bz2")
-		setup_target_path_resume = pjoin(self.settings["autoresume_path"],
-			"setup_target_path")
-		if "autoresume" in self.settings["options"] and \
-				os.path.exists(setup_target_path_resume):
-			print \
-				"Resume point detected, skipping target path setup operation..."
-		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 nothing at all
-#			if os.path.isfile(self.settings["target_path"]):
-#				cmd("rm -f "+self.settings["target_path"],\
-#					"Could not remove existing file: "\
-#					+self.settings["target_path"],env=self.env)
-			touch(setup_target_path_resume)
-
-			if not os.path.exists(self.settings["storedir"]+"/builds/"):
-				os.makedirs(self.settings["storedir"]+"/builds/")
-
-	def set_fsscript(self):
-		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["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["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["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["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"])
-			else:
-				# This automatically prepends the build dir to the ISO output path
-				# if it doesn't start with a /
-				self.settings["iso"] = normpath(self.settings["storedir"] + \
-					"/builds/" + self.settings["rel_type"] + "/" + \
-					self.settings[self.settings["spec_prefix"]+"/iso"])
-			del self.settings[self.settings["spec_prefix"]+"/iso"]
-
-	def set_fstype(self):
-		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 "fstype" not in self.settings:
-			self.settings["fstype"]="normal"
-			for x in self.valid_values:
-				if x ==  self.settings["spec_prefix"]+"/fstype":
-					print "\n"+self.settings["spec_prefix"]+\
-						"/fstype is being set to the default of \"normal\"\n"
-
-	def set_fsops(self):
-		if "fstype" in self.settings:
-			self.valid_values.append("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 "seedcache" in self.settings["options"]\
-			and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
-				self.settings["source_subpath"]+"/")):
-			self.settings["source_path"]=normpath(self.settings["storedir"]+\
-				"/tmp/"+self.settings["source_subpath"]+"/")
-		else:
-			self.settings["source_path"]=normpath(self.settings["storedir"]+\
-				"/builds/"+self.settings["source_subpath"]+".tar.bz2")
-			if os.path.isfile(self.settings["source_path"]):
-				# XXX: Is this even necessary if the previous check passes?
-				if os.path.exists(self.settings["source_path"]):
-					self.settings["source_path_hash"] = \
-						self.settings["hash_map"].generate_hash(
-							self.settings["source_path"],
-							hash_ = self.settings["hash_function"],
-							verbose = False)
-		print "Source path set to "+self.settings["source_path"]
-		if os.path.isdir(self.settings["source_path"]):
-			print "\tIf this is not desired, remove this directory or turn off"
-			print "\tseedcache in the options of catalyst.conf the source path"
-			print "\twill then be "+\
-				normpath(self.settings["storedir"]+"/builds/"+\
-				self.settings["source_subpath"]+".tar.bz2\n")
-
-	def set_dest_path(self):
-		if "root_path" in self.settings:
-			self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
-				self.settings["root_path"])
-		else:
-			self.settings["destpath"]=normpath(self.settings["chroot_path"])
-
-	def set_cleanables(self):
-		self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
-			"/root/*", self.settings["portdir"]]
-
-	def set_snapshot_path(self):
-		self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-			"/snapshots/" + self.settings["snapshot_name"] +
-			self.settings["snapshot"] + ".tar.xz")
-
-		if os.path.exists(self.settings["snapshot_path"]):
-			self.settings["snapshot_path_hash"] = \
-				self.settings["hash_map"].generate_hash(
-					self.settings["snapshot_path"],
-					hash_ = self.settings["hash_function"],
-					verbose = False)
-		else:
-			self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
-				"/snapshots/" + self.settings["snapshot_name"] +
-				self.settings["snapshot"] + ".tar.bz2")
-
-			if os.path.exists(self.settings["snapshot_path"]):
-				self.settings["snapshot_path_hash"] = \
-					self.settings["hash_map"].generate_hash(
-						self.settings["snapshot_path"],
-						hash_ = self.settings["hash_function"],
-						verbose = False)
-
-	def set_snapcache_path(self):
-		if "snapcache" in self.settings["options"]:
-			self.settings["snapshot_cache_path"] = \
-				normpath(self.settings["snapshot_cache"] + "/" +
-					self.settings["snapshot"])
-			self.snapcache_lock=\
-				LockDir(self.settings["snapshot_cache_path"])
-			print "Caching snapshot to "+self.settings["snapshot_cache_path"]
-
-	def set_chroot_path(self):
-		"""
-		NOTE: the trailing slash has been removed
-		Things *could* break if you don't use a proper join()
-		"""
-		self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
-			"/tmp/"+self.settings["target_subpath"])
-		self.chroot_lock=LockDir(self.settings["chroot_path"])
-
-	def set_autoresume_path(self):
-		self.settings["autoresume_path"] = normpath(pjoin(
-			self.settings["storedir"], "tmp", self.settings["rel_type"],
-			".autoresume-%s-%s-%s"
-			%(self.settings["target"], self.settings["subarch"],
-				self.settings["version_stamp"])
-			))
-		if "autoresume" in self.settings["options"]:
-			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)
-
-	def set_controller_file(self):
-		self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
-			"/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
-			"-controller.sh")
-
-	def set_iso_volume_id(self):
-		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"]
-
-	def set_action_sequence(self):
-		""" Default action sequence for run method """
-		self.settings["action_sequence"]=["unpack","unpack_snapshot",\
-				"setup_confdir","portage_overlay",\
-				"base_dirs","bind","chroot_setup","setup_environment",\
-				"run_local","preclean","unbind","clean"]
-#		if "TARBALL" in self.settings or \
-#			"fetch" not in self.settings["options"]:
-		if "fetch" not in self.settings["options"]:
-			self.settings["action_sequence"].append("capture")
-		self.settings["action_sequence"].append("clear_autoresume")
-
-	def set_use(self):
-		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 "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"])
-
-	def set_mounts(self):
-		pass
-
-	def set_packages(self):
-		pass
-
-	def set_rm(self):
-		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["spec_prefix"]+"/linuxrc" in self.settings:
-			if type(self.settings[self.settings["spec_prefix"]+\
-				"/linuxrc"])==types.StringType:
-				self.settings["linuxrc"]=\
-					self.settings[self.settings["spec_prefix"]+"/linuxrc"]
-				del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
-
-	def set_busybox_config(self):
-		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"]=\
-					self.settings[self.settings["spec_prefix"]+"/busybox_config"]
-				del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
-
-	def set_portage_overlay(self):
-		if "portage_overlay" in self.settings:
-			if type(self.settings["portage_overlay"])==types.StringType:
-				self.settings["portage_overlay"]=\
-					self.settings["portage_overlay"].split()
-			print "portage_overlay directories are set to: \""+\
-				string.join(self.settings["portage_overlay"])+"\""
-
-	def set_overlay(self):
-		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"]=\
-					self.settings[self.settings["spec_prefix"]+\
-					"/overlay"].split()
-
-	def set_root_overlay(self):
-		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"]=\
-					self.settings[self.settings["spec_prefix"]+\
-					"/root_overlay"].split()
-
-	def set_root_path(self):
-		""" ROOT= variable for emerges """
-		self.settings["root_path"]="/"
-
-	def set_valid_build_kernel_vars(self,addlargs):
-		if "boot/kernel" in addlargs:
-			if type(addlargs["boot/kernel"])==types.StringType:
-				loopy=[addlargs["boot/kernel"]]
-			else:
-				loopy=addlargs["boot/kernel"]
-
-			for x in loopy:
-				self.valid_values.append("boot/kernel/"+x+"/aliases")
-				self.valid_values.append("boot/kernel/"+x+"/config")
-				self.valid_values.append("boot/kernel/"+x+"/console")
-				self.valid_values.append("boot/kernel/"+x+"/extraversion")
-				self.valid_values.append("boot/kernel/"+x+"/gk_action")
-				self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
-				self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
-				self.valid_values.append("boot/kernel/"+x+"/machine_type")
-				self.valid_values.append("boot/kernel/"+x+"/sources")
-				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 "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["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"]
-
-	def kill_chroot_pids(self):
-		print "Checking for processes running in chroot and killing them."
-
-		"""
-		Force environment variables to be exported so script can see them
-		"""
-		self.setup_environment()
-
-		if os.path.exists(self.settings["sharedir"]+\
-			"/targets/support/kill-chroot-pids.sh"):
-			cmd("/bin/bash "+self.settings["sharedir"]+\
-				"/targets/support/kill-chroot-pids.sh",\
-				"kill-chroot-pids script failed.",env=self.env)
-
-	def mount_safety_check(self):
-		"""
-		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.
-		Returns 1 on ok, 0 on "something is still mounted" case.
-		"""
-
-		if not os.path.exists(self.settings["chroot_path"]):
-			return
-
-		print "self.mounts =", self.mounts
-		for x in self.mounts:
-			target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
-			print "mount_safety_check() x =", x, target
-			if not os.path.exists(target):
-				continue
-
-			if ismount(target):
-				""" Something is still mounted "" """
-				try:
-					print target + " is still mounted; performing auto-bind-umount...",
-					""" Try to umount stuff ourselves """
-					self.unbind()
-					if ismount(target):
-						raise CatalystError, "Auto-unbind failed for " + target
-					else:
-						print "Auto-unbind successful..."
-				except CatalystError:
-					raise CatalystError, "Unable to auto-unbind " + target
-
-	def unpack(self):
-		unpack=True
-
-		unpack_resume = pjoin(self.settings["autoresume_path"], "unpack")
-		clst_unpack_hash=read_from_clst(unpack_resume)
-
-		if "seedcache" in self.settings["options"]:
-			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"]
-				display_msg="\nStarting rsync from "+\
-					self.settings["source_path"]+"\nto "+\
-					self.settings["chroot_path"]+\
-					" (This may take some time) ...\n"
-				error_msg="Rsync of "+self.settings["source_path"]+" to "+\
-					self.settings["chroot_path"]+" failed."
-			else:
-				""" SEEDCACHE is a not a directory, try untar'ing """
-				print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
-				display_msg="\nStarting tar extract from "+\
-					self.settings["source_path"]+"\nto "+\
-					self.settings["chroot_path"]+\
-						" (This may take some time) ...\n"
-				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."
-		else:
-			""" No SEEDCACHE, use tar """
-			display_msg="\nStarting tar extract from "+\
-				self.settings["source_path"]+"\nto "+\
-				self.settings["chroot_path"]+\
-				" (This may take some time) ...\n"
-			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 "autoresume" in self.settings["options"]:
-			if os.path.isdir(self.settings["source_path"]) \
-				and os.path.exists(unpack_resume):
-				""" Autoresume is valid, SEEDCACHE is valid """
-				unpack=False
-				invalid_snapshot=False
-
-			elif os.path.isfile(self.settings["source_path"]) \
-				and self.settings["source_path_hash"]==clst_unpack_hash:
-				""" Autoresume is valid, tarball is valid """
-				unpack=False
-				invalid_snapshot=True
-
-			elif os.path.isdir(self.settings["source_path"]) \
-				and not os.path.exists(unpack_resume):
-				""" Autoresume is invalid, SEEDCACHE """
-				unpack=True
-				invalid_snapshot=False
-
-			elif os.path.isfile(self.settings["source_path"]) \
-				and self.settings["source_path_hash"]!=clst_unpack_hash:
-				""" Autoresume is invalid, tarball """
-				unpack=True
-				invalid_snapshot=True
-		else:
-			""" No autoresume, SEEDCACHE """
-			if "seedcache" in self.settings["options"]:
-				""" SEEDCACHE so let's run rsync and let it clean up """
-				if os.path.isdir(self.settings["source_path"]):
-					unpack=True
-					invalid_snapshot=False
-				elif os.path.isfile(self.settings["source_path"]):
-					""" Tarball so unpack and remove anything already there """
-					unpack=True
-					invalid_snapshot=True
-				""" No autoresume, no SEEDCACHE """
-			else:
-				""" Tarball so unpack and remove anything already there """
-				if os.path.isfile(self.settings["source_path"]):
-					unpack=True
-					invalid_snapshot=True
-				elif os.path.isdir(self.settings["source_path"]):
-					""" We should never reach this, so something is very wrong """
-					raise CatalystError,\
-						"source path is a dir but seedcache is not enabled"
-
-		if unpack:
-			self.mount_safety_check()
-
-			if invalid_snapshot:
-				if "autoresume" in self.settings["options"]:
-					print "No Valid Resume point detected, cleaning up..."
-
-				self.clear_autoresume()
-				self.clear_chroot()
-
-			if not os.path.exists(self.settings["chroot_path"]):
-				os.makedirs(self.settings["chroot_path"])
-
-			if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
-				os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
-
-			if "pkgcache" in self.settings["options"]:
-				if not os.path.exists(self.settings["pkgcache_path"]):
-					os.makedirs(self.settings["pkgcache_path"],0755)
-
-			if "kerncache" in self.settings["options"]:
-				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 "source_path_hash" in self.settings:
-				myf=open(unpack_resume,"w")
-				myf.write(self.settings["source_path_hash"])
-				myf.close()
-			else:
-				touch(unpack_resume)
-		else:
-			print "Resume point detected, skipping unpack operation..."
-
-	def unpack_snapshot(self):
-		unpack=True
-		unpack_portage_resume = pjoin(self.settings["autoresume_path"],
-			"unpack_portage")
-		snapshot_hash=read_from_clst(unpack_portage_resume)
-
-		if "snapcache" in self.settings["options"]:
-			snapshot_cache_hash=\
-				read_from_clst(self.settings["snapshot_cache_path"] + "/" +
-					"catalyst-hash")
-			destdir=self.settings["snapshot_cache_path"]
-			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"]+\
-				" (This can take a long time)..."
-			cleanup_errmsg="Error removing existing snapshot cache directory."
-			self.snapshot_lock_object=self.snapcache_lock
-
-			if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
-				print "Valid snapshot cache, skipping unpack of portage tree..."
-				unpack=False
-		else:
-			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)..."
-			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 "autoresume" in self.settings["options"] \
-				and os.path.exists(self.settings["chroot_path"]+\
-					self.settings["portdir"]) \
-				and os.path.exists(unpack_portage_resume) \
-				and self.settings["snapshot_path_hash"] == snapshot_hash:
-					print \
-						"Valid Resume point detected, skipping unpack of portage tree..."
-					unpack=False
-
-		if unpack:
-			if "snapcache" in self.settings["options"]:
-				self.snapshot_lock_object.write_lock()
-			if os.path.exists(destdir):
-				print cleanup_msg
-				cleanup_cmd="rm -rf "+destdir
-				cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
-			if not os.path.exists(destdir):
-				os.makedirs(destdir,0755)
-
-			print "Unpacking portage tree (This can take a long time) ..."
-			cmd(unpack_cmd,unpack_errmsg,env=self.env)
-
-			if "snapcache" in self.settings["options"]:
-				myf=open(self.settings["snapshot_cache_path"] +
-					"/" + "catalyst-hash","w")
-				myf.write(self.settings["snapshot_path_hash"])
-				myf.close()
-			else:
-				print "Setting snapshot autoresume point"
-				myf=open(unpack_portage_resume,"w")
-				myf.write(self.settings["snapshot_path_hash"])
-				myf.close()
-
-			if "snapcache" in self.settings["options"]:
-				self.snapshot_lock_object.unlock()
-
-	def config_profile_link(self):
-		config_protect_link_resume = pjoin(self.settings["autoresume_path"],
-			"config_profile_link")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(config_protect_link_resume):
-			print \
-				"Resume point detected, skipping config_profile_link operation..."
-		else:
-			# 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/portage/make.profile",\
-					"Error zapping profile link",env=self.env)
-			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/portage/make.profile",\
-				"Error creating profile link",env=self.env)
-			touch(config_protect_link_resume)
-
-	def setup_confdir(self):
-		setup_confdir_resume = pjoin(self.settings["autoresume_path"],
-			"setup_confdir")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(setup_confdir_resume):
-			print "Resume point detected, skipping setup_confdir operation..."
-		else:
-			if "portage_confdir" in self.settings:
-				print "Configuring /etc/portage..."
-				cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
-					self.settings["chroot_path"]+"/etc/portage/",\
-					"Error copying /etc/portage",env=self.env)
-				touch(setup_confdir_resume)
-
-	def portage_overlay(self):
-		""" We copy the contents of our overlays to /usr/local/portage """
-		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"]+\
-						self.settings["local_overlay"],\
-						"Could not make portage_overlay dir",env=self.env)
-					cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
-						self.settings["local_overlay"],\
-						"Could not copy portage_overlay",env=self.env)
-
-	def root_overlay(self):
-		""" Copy over the root_overlay """
-		if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
-			for x in self.settings[self.settings["spec_prefix"]+\
-				"/root_overlay"]:
-				if os.path.exists(x):
-					print "Copying root_overlay: "+x
-					cmd("rsync -a "+x+"/ "+\
-						self.settings["chroot_path"],\
-						self.settings["spec_prefix"]+"/root_overlay: "+x+\
-						" copy failed.",env=self.env)
-
-	def base_dirs(self):
-		pass
-
-	def bind(self):
-		for x in self.mounts:
-			#print "bind(); x =", x
-			target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
-			if not os.path.exists(target):
-				os.makedirs(target, 0755)
-
-			if not os.path.exists(self.mountmap[x]):
-				if self.mountmap[x] not in ["tmpfs", "shmfs"]:
-					os.makedirs(self.mountmap[x], 0755)
-
-			src=self.mountmap[x]
-			#print "bind(); src =", src
-			if "snapcache" in self.settings["options"] and x == "portdir":
-				self.snapshot_lock_object.read_lock()
-			if os.uname()[0] == "FreeBSD":
-				if src == "/dev":
-					cmd = "mount -t devfs none " + target
-					retval=os.system(cmd)
-				else:
-					cmd = "mount_nullfs " + src + " " + target
-					retval=os.system(cmd)
-			else:
-				if src == "tmpfs":
-					if "var_tmpfs_portage" in self.settings:
-						cmd = "mount -t tmpfs -o size=" + \
-							self.settings["var_tmpfs_portage"] + "G " + \
-							src + " " + target
-						retval=os.system(cmd)
-				elif src == "shmfs":
-					cmd = "mount -t tmpfs -o noexec,nosuid,nodev shm " + target
-					retval=os.system(cmd)
-				else:
-					cmd = "mount --bind " + src + " " + target
-					#print "bind(); cmd =", cmd
-					retval=os.system(cmd)
-			if retval!=0:
-				self.unbind()
-				raise CatalystError,"Couldn't bind mount " + src
-
-	def unbind(self):
-		ouch=0
-		mypath=self.settings["chroot_path"]
-		myrevmounts=self.mounts[:]
-		myrevmounts.reverse()
-		""" Unmount in reverse order for nested bind-mounts """
-		for x in myrevmounts:
-			target = normpath(mypath + self.target_mounts[x])
-			if not os.path.exists(target):
-				continue
-
-			if not ismount(target):
-				continue
-
-			retval=os.system("umount " + target)
-
-			if retval!=0:
-				warn("First attempt to unmount: " + target + " failed.")
-				warn("Killing any pids still running in the chroot")
-
-				self.kill_chroot_pids()
-
-				retval2 = os.system("umount " + target)
-				if retval2!=0:
-					ouch=1
-					warn("Couldn't umount bind mount: " + target)
-
-			if "snapcache" in self.settings["options"] and x == "/usr/portage":
-				try:
-					"""
-					It's possible the snapshot lock object isn't created yet.
-					This is because mount safety check calls unbind before the
-					target is fully initialized
-					"""
-					self.snapshot_lock_object.unlock()
-				except:
-					pass
-		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.makeconf=read_makeconf(self.settings["chroot_path"]+\
-			"/etc/portage/make.conf")
-		self.override_cbuild()
-		self.override_chost()
-		self.override_cflags()
-		self.override_cxxflags()
-		self.override_ldflags()
-		chroot_setup_resume = pjoin(self.settings["autoresume_path"],
-			"chroot_setup")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(chroot_setup_resume):
-			print "Resume point detected, skipping chroot_setup operation..."
-		else:
-			print "Setting up chroot..."
-
-			#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 "envscript" in self.settings:
-				if not os.path.exists(self.settings["envscript"]):
-					raise CatalystError,\
-						"Can't find envscript "+self.settings["envscript"]
-
-				print "\nWarning!!!!"
-				print "\tOverriding certain env variables may cause catastrophic failure."
-				print "\tIf your build fails look here first as the possible problem."
-				print "\tCatalyst assumes you know what you are doing when setting"
-				print "\t\tthese variables."
-				print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
-				print "\tYou have been warned\n"
-
-				cmd("cp "+self.settings["envscript"]+" "+\
-					self.settings["chroot_path"]+"/tmp/envscript",\
-					"Could not copy envscript into place.",env=self.env)
-
-			"""
-			Copy over /etc/hosts from the host in case there are any
-			specialties in there
-			"""
-			if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
-				cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
-					self.settings["chroot_path"]+"/etc/hosts.catalyst",\
-					"Could not backup /etc/hosts",env=self.env)
-				cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
-					"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/portage/make.conf",\
-				"Could not remove "+self.settings["chroot_path"]+\
-				"/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 "CFLAGS" in self.settings:
-				myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
-			if "CXXFLAGS" in self.settings:
-				if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
-					myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
-				else:
-					myf.write('CXXFLAGS="${CFLAGS}"\n')
-			else:
-				myf.write('CXXFLAGS="${CFLAGS}"\n')
-
-			if "LDFLAGS" in self.settings:
-				myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
-				myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
-			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')
-
-			myf.write("# WARNING: Changing your CHOST is not something that should be done lightly.\n# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.\n")
-			myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
-
-			""" Figure out what our USE vars are for building """
-			myusevars=[]
-			if "HOSTUSE" in self.settings:
-				myusevars.extend(self.settings["HOSTUSE"])
-
-			if "use" in self.settings:
-				myusevars.extend(self.settings["use"])
-
-			if myusevars:
-				myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
-				myusevars = sorted(set(myusevars))
-				myf.write('USE="'+string.join(myusevars)+'"\n')
-				if '-*' in myusevars:
-					print "\nWarning!!!  "
-					print "\tThe use of -* in "+self.settings["spec_prefix"]+\
-						"/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="%s"\n' % self.settings['distdir'])
-			myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
-
-			""" Setup the 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/portage/make.conf "+\
-				self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
-				"Could not backup /etc/portage/make.conf",env=self.env)
-			touch(chroot_setup_resume)
-
-	def fsscript(self):
-		fsscript_resume = pjoin(self.settings["autoresume_path"], "fsscript")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(fsscript_resume):
-			print "Resume point detected, skipping fsscript operation..."
-		else:
-			if "fsscript" in self.settings:
-				if os.path.exists(self.settings["controller_file"]):
-					cmd(self.settings["controller_file"]+\
-						" fsscript","fsscript script failed.",env=self.env)
-					touch(fsscript_resume)
-
-	def rcupdate(self):
-		rcupdate_resume = pjoin(self.settings["autoresume_path"], "rcupdate")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(rcupdate_resume):
-			print "Resume point detected, skipping rcupdate operation..."
-		else:
-			if os.path.exists(self.settings["controller_file"]):
-				cmd(self.settings["controller_file"]+" rc-update",\
-					"rc-update script failed.",env=self.env)
-				touch(rcupdate_resume)
-
-	def clean(self):
-		clean_resume = pjoin(self.settings["autoresume_path"], "clean")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(clean_resume):
-			print "Resume point detected, skipping clean operation..."
-		else:
-			for x in self.settings["cleanables"]:
-				print "Cleaning chroot: "+x+"... "
-				cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
-					x,env=self.env)
-
-		""" Put /etc/hosts back into place """
-		if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
-			cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
-				self.settings["chroot_path"]+"/etc/hosts",\
-				"Could not replace /etc/hosts",env=self.env)
-
-		""" Remove our overlay """
-		if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
-			cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
-				"Could not remove " + self.settings["local_overlay"], env=self.env)
-			cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
-				"/etc/portage/make.conf",\
-				"Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
-
-		""" Clean up old and obsoleted files in /etc """
-		if os.path.exists(self.settings["stage_path"]+"/etc"):
-			cmd("find "+self.settings["stage_path"]+\
-				"/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
-				"Could not remove stray files in /etc",env=self.env)
-
-		if os.path.exists(self.settings["controller_file"]):
-			cmd(self.settings["controller_file"]+" clean",\
-				"clean script failed.",env=self.env)
-			touch(clean_resume)
-
-	def empty(self):
-		empty_resume = pjoin(self.settings["autoresume_path"], "empty")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(empty_resume):
-			print "Resume point detected, skipping empty operation..."
-		else:
-			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"]=\
-						self.settings[self.settings["spec_prefix"]+\
-						"/empty"].split()
-				for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
-					myemp=self.settings["destpath"]+x
-					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
-					"""
-					mystat=os.stat(myemp)
-					shutil.rmtree(myemp)
-					os.makedirs(myemp,0755)
-					os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
-					os.chmod(myemp,mystat[ST_MODE])
-			touch(empty_resume)
-
-	def remove(self):
-		remove_resume = pjoin(self.settings["autoresume_path"], "remove")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(remove_resume):
-			print "Resume point detected, skipping remove operation..."
-		else:
-			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
-					operations, so we get easy glob handling.
-					"""
-					print "livecd: removing "+x
-					os.system("rm -rf "+self.settings["chroot_path"]+x)
-				try:
-					if os.path.exists(self.settings["controller_file"]):
-						cmd(self.settings["controller_file"]+\
-							" clean","Clean  failed.",env=self.env)
-						touch(remove_resume)
-				except:
-					self.unbind()
-					raise
-
-	def preclean(self):
-		preclean_resume = pjoin(self.settings["autoresume_path"], "preclean")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(preclean_resume):
-			print "Resume point detected, skipping preclean operation..."
-		else:
-			try:
-				if os.path.exists(self.settings["controller_file"]):
-					cmd(self.settings["controller_file"]+\
-						" preclean","preclean script failed.",env=self.env)
-					touch(preclean_resume)
-
-			except:
-				self.unbind()
-				raise CatalystError, "Build failed, could not execute preclean"
-
-	def capture(self):
-		capture_resume = pjoin(self.settings["autoresume_path"], "capture")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(capture_resume):
-			print "Resume point detected, skipping capture operation..."
-		else:
-			""" Capture target in a tarball """
-			mypath=self.settings["target_path"].split("/")
-			""" Remove filename from path """
-			mypath=string.join(mypath[:-1],"/")
-
-			""" Now make sure path exists """
-			if not os.path.exists(mypath):
-				os.makedirs(mypath)
-
-			print "Creating stage tarball..."
-
-			cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
-				self.settings["stage_path"]+" .",\
-				"Couldn't create stage tarball",env=self.env)
-
-			self.gen_contents_file(self.settings["target_path"])
-			self.gen_digest_file(self.settings["target_path"])
-
-			touch(capture_resume)
-
-	def run_local(self):
-		run_local_resume = pjoin(self.settings["autoresume_path"], "run_local")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(run_local_resume):
-			print "Resume point detected, skipping run_local operation..."
-		else:
-			try:
-				if os.path.exists(self.settings["controller_file"]):
-					cmd(self.settings["controller_file"]+" run",\
-						"run script failed.",env=self.env)
-					touch(run_local_resume)
-
-			except CatalystError:
-				self.unbind()
-				raise CatalystError,"Stage build aborting due to error."
-
-	def setup_environment(self):
-		"""
-		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
-		"""
-		#print "setup_environment(); settings =", list(self.settings)
-		for x in list(self.settings):
-			#print "setup_environment(); processing:", x
-			if x == "options":
-				#self.env['clst_' + x] = ' '.join(self.settings[x])
-				for opt in self.settings[x]:
-					self.env['clst_' + opt.upper()] = "true"
-				continue
-			""" Sanitize var names by doing "s|/-.|_|g" """
-			varname="clst_"+string.replace(x,"/","_")
-			varname=string.replace(varname,"-","_")
-			varname=string.replace(varname,".","_")
-			if type(self.settings[x])==types.StringType:
-				""" Prefix to prevent namespace clashes """
-				#os.environ[varname]=self.settings[x]
-				self.env[varname]=self.settings[x]
-			elif type(self.settings[x])==types.ListType:
-				#os.environ[varname]=string.join(self.settings[x])
-				self.env[varname]=string.join(self.settings[x])
-			elif type(self.settings[x])==types.BooleanType:
-				if self.settings[x]:
-					self.env[varname]="true"
-				else:
-					self.env[varname]="false"
-		if "makeopts" in self.settings:
-			self.env["MAKEOPTS"]=self.settings["makeopts"]
-
-	def run(self):
-		self.chroot_lock.write_lock()
-
-		""" Kill any pids in the chroot "" """
-		self.kill_chroot_pids()
-
-		""" Check for mounts right away and abort if we cannot unmount them """
-		self.mount_safety_check()
-
-		if "clear-autoresume" in self.settings["options"]:
-			self.clear_autoresume()
-
-		if "purgetmponly" in self.settings["options"]:
-			self.purge()
-			return
-
-		if "PURGEONLY" in self.settings:
-			self.purge()
-			return
-
-		if "purge" in self.settings["options"]:
-			self.purge()
-
-		for x in self.settings["action_sequence"]:
-			print "--- Running action sequence: "+x
-			sys.stdout.flush()
-			try:
-				apply(getattr(self,x))
-			except:
-				self.mount_safety_check()
-				raise
-
-		self.chroot_lock.unlock()
-
-	def unmerge(self):
-		unmerge_resume = pjoin(self.settings["autoresume_path"], "unmerge")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(unmerge_resume):
-			print "Resume point detected, skipping unmerge operation..."
-		else:
-			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"]=\
-						[self.settings[self.settings["spec_prefix"]+"/unmerge"]]
-				myunmerge=\
-					self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
-
-				for x in range(0,len(myunmerge)):
-					"""
-					Surround args with quotes for passing to bash, allows
-					things like "<" to remain intact
-					"""
-					myunmerge[x]="'"+myunmerge[x]+"'"
-				myunmerge=string.join(myunmerge)
-
-				""" Before cleaning, unmerge stuff """
-				try:
-					cmd(self.settings["controller_file"]+\
-						" unmerge "+ myunmerge,"Unmerge script failed.",\
-						env=self.env)
-					print "unmerge shell script"
-				except CatalystError:
-					self.unbind()
-					raise
-				touch(unmerge_resume)
-
-	def target_setup(self):
-		target_setup_resume = pjoin(self.settings["autoresume_path"],
-			"target_setup")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(target_setup_resume):
-			print "Resume point detected, skipping target_setup operation..."
-		else:
-			print "Setting up filesystems per filesystem type"
-			cmd(self.settings["controller_file"]+\
-				" target_image_setup "+ self.settings["target_path"],\
-				"target_image_setup script failed.",env=self.env)
-			touch(target_setup_resume)
-
-	def setup_overlay(self):
-		setup_overlay_resume = pjoin(self.settings["autoresume_path"],
-			"setup_overlay")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(setup_overlay_resume):
-			print "Resume point detected, skipping setup_overlay operation..."
-		else:
-			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"],\
-							self.settings["spec_prefix"]+"overlay: "+x+\
-							" copy failed.",env=self.env)
-				touch(setup_overlay_resume)
-
-	def create_iso(self):
-		create_iso_resume = pjoin(self.settings["autoresume_path"], "create_iso")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(create_iso_resume):
-			print "Resume point detected, skipping create_iso operation..."
-		else:
-			""" Create the ISO """
-			if "iso" in self.settings:
-				cmd(self.settings["controller_file"]+" iso "+\
-					self.settings["iso"],"ISO creation script failed.",\
-					env=self.env)
-				self.gen_contents_file(self.settings["iso"])
-				self.gen_digest_file(self.settings["iso"])
-				touch(create_iso_resume)
-			else:
-				print "WARNING: livecd/iso was not defined."
-				print "An ISO Image will not be created."
-
-	def build_packages(self):
-		build_packages_resume = pjoin(self.settings["autoresume_path"],
-			"build_packages")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(build_packages_resume):
-			print "Resume point detected, skipping build_packages operation..."
-		else:
-			if self.settings["spec_prefix"]+"/packages" in self.settings:
-				if "autoresume" in self.settings["options"] \
-					and os.path.exists(self.settings["autoresume_path"]+\
-						"build_packages"):
-					print "Resume point detected, skipping build_packages operation..."
-				else:
-					mypack=\
-						list_bashify(self.settings[self.settings["spec_prefix"]\
-						+"/packages"])
-					try:
-						cmd(self.settings["controller_file"]+\
-							" build_packages "+mypack,\
-							"Error in attempt to build packages",env=self.env)
-						touch(build_packages_resume)
-					except CatalystError:
-						self.unbind()
-						raise CatalystError,self.settings["spec_prefix"]+\
-							"build aborting due to error."
-
-	def build_kernel(self):
-		'''Build all configured kernels'''
-		build_kernel_resume = pjoin(self.settings["autoresume_path"],
-			"build_kernel")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(build_kernel_resume):
-			print "Resume point detected, skipping build_kernel operation..."
-		else:
-			if "boot/kernel" in self.settings:
-				try:
-					mynames=self.settings["boot/kernel"]
-					if type(mynames)==types.StringType:
-						mynames=[mynames]
-					"""
-					Execute the script that sets up the kernel build environment
-					"""
-					cmd(self.settings["controller_file"]+\
-						" pre-kmerge ","Runscript pre-kmerge failed",\
-						env=self.env)
-					for kname in mynames:
-						self._build_kernel(kname=kname)
-					touch(build_kernel_resume)
-				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"
-		kname_resume = pjoin(self.settings["autoresume_path"],
-			"build_kernel_" + kname)
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(kname_resume):
-			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(kname_resume)
-
-		"""
-		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):
-		bootloader_resume = pjoin(self.settings["autoresume_path"], "bootloader")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(bootloader_resume):
-			print "Resume point detected, skipping bootloader operation..."
-		else:
-			try:
-				cmd(self.settings["controller_file"]+\
-					" bootloader " + self.settings["target_path"],\
-					"Bootloader script failed.",env=self.env)
-				touch(bootloader_resume)
-			except CatalystError:
-				self.unbind()
-				raise CatalystError,"Script aborting due to error."
-
-	def livecd_update(self):
-		livecd_update_resume = pjoin(self.settings["autoresume_path"],
-			"livecd_update")
-		if "autoresume" in self.settings["options"] \
-			and os.path.exists(livecd_update_resume):
-			print "Resume point detected, skipping build_packages operation..."
-		else:
-			try:
-				cmd(self.settings["controller_file"]+\
-					" livecd-update","livecd-update failed.",env=self.env)
-				touch(livecd_update_resume)
-
-			except CatalystError:
-				self.unbind()
-				raise CatalystError,"build aborting due to livecd_update error."
-
-# vim: ts=4 sw=4 sta et sts=4 ai
diff --git a/catalyst/targets/grp_target.py b/catalyst/targets/grp_target.py
index 033db75..deba80a 100644
--- a/catalyst/targets/grp_target.py
+++ b/catalyst/targets/grp_target.py
@@ -3,11 +3,18 @@ Gentoo Reference Platform (GRP) target
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,types,glob
-from catalyst.support import *
-from generic_stage_target import *
+import os
+import types
+import glob
 
-class grp_target(generic_stage_target):
+
+from catalyst.support import (CatalystError, normpath,
+	touch, cmd, list_bashify)
+
+from catalyst.base.stagebase import StageBase
+
+
+class grp_target(StageBase):
 	"""
 	The builder class for GRP (Gentoo Reference Platform) builds.
 	"""
@@ -32,7 +39,7 @@ class grp_target(generic_stage_target):
 			self.required_values.append("grp/"+x+"/packages")
 			self.required_values.append("grp/"+x+"/type")
 
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_target_path(self):
 		self.settings["target_path"]=normpath(self.settings["storedir"]+"/builds/"+self.settings["target_subpath"]+"/")
@@ -62,16 +69,15 @@ class grp_target(generic_stage_target):
 				raise CatalystError,"GRP build aborting due to error."
 
 	def set_use(self):
-		generic_stage_target.set_use(self)
-		if "BINDIST" in self.settings:
-			if "use" in self.settings:
-				self.settings["use"].append("bindist")
-			else:
-				self.settings["use"]=["bindist"]
+		StageBase.set_use(self)
+		if "use" in self.settings:
+			self.settings["use"].append("bindist")
+		else:
+			self.settings["use"]=["bindist"]
 
 	def set_mounts(self):
-	    self.mounts.append("/tmp/grp")
-            self.mountmap["/tmp/grp"]=self.settings["target_path"]
+		self.mounts.append("/tmp/grp")
+		self.mountmap["/tmp/grp"]=self.settings["target_path"]
 
 	def generate_digests(self):
 		for pkgset in self.settings["grp"]:
@@ -108,7 +114,7 @@ class grp_target(generic_stage_target):
 						self.gen_digest_file(normpath(destdir+"/"+i))
 
 	def set_action_sequence(self):
-	    self.settings["action_sequence"]=["unpack","unpack_snapshot",\
+		self.settings["action_sequence"]=["unpack","unpack_snapshot",\
 					"config_profile_link","setup_confdir","portage_overlay","bind","chroot_setup",\
 					"setup_environment","run_local","unbind",\
 					"generate_digests","clear_autoresume"]
diff --git a/catalyst/targets/livecd_stage1_target.py b/catalyst/targets/livecd_stage1_target.py
index 6273c9e..a19f4ac 100644
--- a/catalyst/targets/livecd_stage1_target.py
+++ b/catalyst/targets/livecd_stage1_target.py
@@ -3,10 +3,17 @@ LiveCD stage1 target
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+import os
+import types
+import string
 
-class livecd_stage1_target(generic_stage_target):
+from catalyst.support import (normpath,
+	touch, cmd)
+
+from catalyst.base.stagebase import StageBase
+
+
+class livecd_stage1_target(StageBase):
 	"""
 	Builder class for LiveCD stage1.
 	"""
@@ -15,7 +22,7 @@ class livecd_stage1_target(generic_stage_target):
 		self.valid_values=self.required_values[:]
 
 		self.valid_values.extend(["livecd/use"])
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_action_sequence(self):
 		self.settings["action_sequence"]=["unpack","unpack_snapshot",\
@@ -45,7 +52,7 @@ class livecd_stage1_target(generic_stage_target):
 	                self.settings["spec_prefix"]="livecd"
 
 	def set_use(self):
-		generic_stage_target.set_use(self)
+		StageBase.set_use(self)
 		if "use" in self.settings:
 			self.settings["use"].append("livecd")
 			if "BINDIST" in self.settings:
@@ -56,7 +63,7 @@ class livecd_stage1_target(generic_stage_target):
 				self.settings["use"].append("bindist")
 
 	def set_packages(self):
-		generic_stage_target.set_packages(self)
+		StageBase.set_packages(self)
 		if self.settings["spec_prefix"]+"/packages" in self.settings:
 			if type(self.settings[self.settings["spec_prefix"]+"/packages"]) == types.StringType:
 				self.settings[self.settings["spec_prefix"]+"/packages"] = \
@@ -68,7 +75,7 @@ class livecd_stage1_target(generic_stage_target):
 			if type(self.settings["pkgcache_path"]) != types.StringType:
 				self.settings["pkgcache_path"]=normpath(string.join(self.settings["pkgcache_path"]))
 		else:
-			generic_stage_target.set_pkgcache_path(self)
+			StageBase.set_pkgcache_path(self)
 
 def register(foo):
 	foo.update({"livecd-stage1":livecd_stage1_target})
diff --git a/catalyst/targets/livecd_stage2_target.py b/catalyst/targets/livecd_stage2_target.py
index 11b1219..e7ae212 100644
--- a/catalyst/targets/livecd_stage2_target.py
+++ b/catalyst/targets/livecd_stage2_target.py
@@ -3,11 +3,14 @@ LiveCD stage2 target, builds upon previous LiveCD stage1 tarball
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,string,types,stat,shutil
-from catalyst.support import *
-from generic_stage_target import *
+import os
 
-class livecd_stage2_target(generic_stage_target):
+from catalyst.support import (normpath, file_locate, CatalystError, cmd,
+	read_from_clst, touch)
+from catalyst.base.stagebase import StageBase
+
+
+class livecd_stage2_target(StageBase):
 	"""
 	Builder class for a LiveCD stage2 build.
 	"""
@@ -26,7 +29,7 @@ class livecd_stage2_target(generic_stage_target):
 			"livecd/fstype","livecd/fsops","livecd/linuxrc","livecd/bootargs",\
 			"gamecd/conf","livecd/xdm","livecd/xsession","livecd/volid"])
 
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 		if "livecd/type" not in self.settings:
 			self.settings["livecd/type"] = "generic-livecd"
 
diff --git a/catalyst/targets/netboot2_target.py b/catalyst/targets/netboot2_target.py
index ea07d76..987afd8 100644
--- a/catalyst/targets/netboot2_target.py
+++ b/catalyst/targets/netboot2_target.py
@@ -3,11 +3,18 @@ netboot target, version 2
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,string,types
-from catalyst.support import *
-from generic_stage_target import *
+import os
+import types
+import shutil
+from stat import ST_UID, ST_GID, ST_MODE
 
-class netboot2_target(generic_stage_target):
+from catalyst.support import (CatalystError, normpath,
+	touch, cmd, list_bashify)
+
+from catalyst.base.stagebase import StageBase
+
+
+class netboot2_target(StageBase):
 	"""
 	Builder class for a netboot build, version 2
 	"""
@@ -38,7 +45,7 @@ class netboot2_target(generic_stage_target):
 		except:
 			raise CatalystError,"configuration error in netboot2/packages."
 
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 		self.set_build_kernel_vars()
 		self.settings["merge_path"]=normpath("/tmp/image/")
 
diff --git a/catalyst/targets/netboot_target.py b/catalyst/targets/netboot_target.py
index ae1eb04..c880289 100644
--- a/catalyst/targets/netboot_target.py
+++ b/catalyst/targets/netboot_target.py
@@ -3,11 +3,16 @@ netboot target, version 1
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,string,types
-from catalyst.support import *
-from generic_stage_target import *
+import os
+import types
 
-class netboot_target(generic_stage_target):
+from catalyst.support import (CatalystError, normpath,
+	cmd, list_bashify, file_locate)
+
+from catalyst.base.stagebase import StageBase
+
+
+class netboot_target(StageBase):
 	"""
 	Builder class for a netboot build.
 	"""
@@ -36,7 +41,7 @@ class netboot_target(generic_stage_target):
 		except:
 			raise CatalystError,"configuration error in netboot/packages."
 
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 		self.set_build_kernel_vars(addlargs)
 		if "netboot/busybox_config" in addlargs:
 			file_locate(self.settings, ["netboot/busybox_config"])
diff --git a/catalyst/targets/snapshot_target.py b/catalyst/targets/snapshot_target.py
index 3289bbd..337ff1d 100644
--- a/catalyst/targets/snapshot_target.py
+++ b/catalyst/targets/snapshot_target.py
@@ -8,8 +8,8 @@ from stat import ST_UID, ST_GID, ST_MODE
 
 
 from catalyst.support import normpath, cmd
-from catalyst.targets.targetbase import TargetBase
-from catalyst.targets.genbase import GenBase
+from catalyst.base.targetbase import TargetBase
+from catalyst.base.genbase import GenBase
 
 class snapshot_target(TargetBase, GenBase):
 	"""
diff --git a/catalyst/targets/stage1_target.py b/catalyst/targets/stage1_target.py
index 8d5a674..0a36432 100644
--- a/catalyst/targets/stage1_target.py
+++ b/catalyst/targets/stage1_target.py
@@ -3,10 +3,13 @@ stage1 target
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+import os
 
-class stage1_target(generic_stage_target):
+from catalyst.support import normpath, list_to_string
+from catalyst.base.stagebase import StageBase
+
+
+class stage1_target(StageBase):
 	"""
 	Builder class for a stage1 installation tarball build.
 	"""
@@ -14,7 +17,7 @@ class stage1_target(generic_stage_target):
 		self.required_values=[]
 		self.valid_values=["chost"]
 		self.valid_values.extend(["update_seed","update_seed_command"])
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_stage_path(self):
 		self.settings["stage_path"]=normpath(self.settings["chroot_path"]+self.settings["root_path"])
@@ -26,11 +29,11 @@ class stage1_target(generic_stage_target):
 		print "stage1 root path is "+self.settings["root_path"]
 
 	def set_cleanables(self):
-		generic_stage_target.set_cleanables(self)
+		StageBase.set_cleanables(self)
 		self.settings["cleanables"].extend([\
 		"/usr/share/zoneinfo", "/etc/portage/package*"])
 
-	# XXX: How do these override_foo() functions differ from the ones in generic_stage_target and why aren't they in stage3_target?
+	# XXX: How do these override_foo() functions differ from the ones in StageBase and why aren't they in stage3_target?
 
 	def override_chost(self):
 		if "chost" in self.settings:
@@ -49,7 +52,7 @@ class stage1_target(generic_stage_target):
 			self.settings["LDFLAGS"]=list_to_string(self.settings["ldflags"])
 
 	def set_portage_overlay(self):
-		generic_stage_target.set_portage_overlay(self)
+		StageBase.set_portage_overlay(self)
 		if "portage_overlay" in self.settings:
 			print "\nWARNING !!!!!"
 			print "\tUsing an portage overlay for earlier stages could cause build issues."
diff --git a/catalyst/targets/stage2_target.py b/catalyst/targets/stage2_target.py
index 94d4a1e..783d42e 100644
--- a/catalyst/targets/stage2_target.py
+++ b/catalyst/targets/stage2_target.py
@@ -3,17 +3,20 @@ stage2 target, builds upon previous stage1 tarball
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+import os
 
-class stage2_target(generic_stage_target):
+from catalyst.support import normpath, list_to_string
+from catalyst.base.stagebase import StageBase
+
+
+class stage2_target(StageBase):
 	"""
 	Builder class for a stage2 installation tarball build.
 	"""
 	def __init__(self,spec,addlargs):
 		self.required_values=[]
 		self.valid_values=["chost"]
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_source_path(self):
 		if "seedcache" in self.settings["options"] and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+self.settings["source_subpath"]+"/tmp/stage1root/")):
@@ -34,7 +37,7 @@ class stage2_target(generic_stage_target):
 			print "\tthe source path will then be "+normpath(self.settings["storedir"]+"/builds/"+self.settings["source_subpath"]+".tar.bz2\n")
 
 	# XXX: How do these override_foo() functions differ from the ones in
-	# generic_stage_target and why aren't they in stage3_target?
+	# StageBase and why aren't they in stage3_target?
 
 	def override_chost(self):
 		if "chost" in self.settings:
@@ -53,7 +56,7 @@ class stage2_target(generic_stage_target):
 			self.settings["LDFLAGS"]=list_to_string(self.settings["ldflags"])
 
 	def set_portage_overlay(self):
-			generic_stage_target.set_portage_overlay(self)
+			StageBase.set_portage_overlay(self)
 			if "portage_overlay" in self.settings:
 				print "\nWARNING !!!!!"
 				print "\tUsing an portage overlay for earlier stages could cause build issues."
diff --git a/catalyst/targets/stage3_target.py b/catalyst/targets/stage3_target.py
index 89edd66..28021b1 100644
--- a/catalyst/targets/stage3_target.py
+++ b/catalyst/targets/stage3_target.py
@@ -3,20 +3,20 @@ stage3 target, builds upon previous stage2/stage3 tarball
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+from catalyst.base.stagebase import StageBase
 
-class stage3_target(generic_stage_target):
+
+class stage3_target(StageBase):
 	"""
 	Builder class for a stage3 installation tarball build.
 	"""
 	def __init__(self,spec,addlargs):
 		self.required_values=[]
 		self.valid_values=[]
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_portage_overlay(self):
-		generic_stage_target.set_portage_overlay(self)
+		StageBase.set_portage_overlay(self)
 		if "portage_overlay" in self.settings:
 			print "\nWARNING !!!!!"
 			print "\tUsing an overlay for earlier stages could cause build issues."
@@ -24,7 +24,7 @@ class stage3_target(generic_stage_target):
 			print "\tDont say we did not warn you\n"
 
 	def set_cleanables(self):
-		generic_stage_target.set_cleanables(self)
+		StageBase.set_cleanables(self)
 
 def register(foo):
 	foo.update({"stage3":stage3_target})
diff --git a/catalyst/targets/stage4_target.py b/catalyst/targets/stage4_target.py
index e2b8a79..0d725c7 100644
--- a/catalyst/targets/stage4_target.py
+++ b/catalyst/targets/stage4_target.py
@@ -3,10 +3,10 @@ stage4 target, builds upon previous stage3/stage4 tarball
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+from catalyst.base.stagebase import StageBase
 
-class stage4_target(generic_stage_target):
+
+class stage4_target(StageBase):
 	"""
 	Builder class for stage4.
 	"""
@@ -18,7 +18,7 @@ class stage4_target(generic_stage_target):
 				"stage4/gk_mainargs","splash_theme",\
 				"portage_overlay","stage4/rcadd","stage4/rcdel",\
 				"stage4/linuxrc","stage4/unmerge","stage4/rm","stage4/empty"])
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def set_cleanables(self):
 		self.settings["cleanables"]=["/var/tmp/*","/tmp/*"]
diff --git a/catalyst/targets/targetbase.py b/catalyst/targets/targetbase.py
deleted file mode 100644
index e0c03df..0000000
--- a/catalyst/targets/targetbase.py
+++ /dev/null
@@ -1,15 +0,0 @@
-import os
-
-from catalyst.support import *
-
-class TargetBase(object):
-	"""
-	The toplevel class for all targets. This is about as generic as we get.
-	"""
-	def __init__(self, myspec, addlargs):
-		addl_arg_parse(myspec,addlargs,self.required_values,self.valid_values)
-		self.settings=myspec
-		self.env = {
-			'PATH': '/bin:/sbin:/usr/bin:/usr/sbin',
-			'TERM': os.getenv('TERM', 'dumb'),
-			}
diff --git a/catalyst/targets/tinderbox_target.py b/catalyst/targets/tinderbox_target.py
index ea11d3f..1e245f2 100644
--- a/catalyst/targets/tinderbox_target.py
+++ b/catalyst/targets/tinderbox_target.py
@@ -3,10 +3,13 @@ Tinderbox target
 """
 # NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-from catalyst.support import *
-from generic_stage_target import *
+import os
 
-class tinderbox_target(generic_stage_target):
+from catalyst.support import cmd, list_bashify, CatalystError
+from catalyst.base.stagebase import StageBase
+
+
+class tinderbox_target(StageBase):
 	"""
 	Builder class for the tinderbox target
 	"""
@@ -14,7 +17,7 @@ class tinderbox_target(generic_stage_target):
 		self.required_values=["tinderbox/packages"]
 		self.valid_values=self.required_values[:]
 		self.valid_values.extend(["tinderbox/use"])
-		generic_stage_target.__init__(self,spec,addlargs)
+		StageBase.__init__(self,spec,addlargs)
 
 	def run_local(self):
 		# tinderbox
-- 
2.1.0



  reply	other threads:[~2014-09-11  3:51 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-11  3:50 [gentoo-catalyst] [PATCH 0/3] Code breakup & restructuring Brian Dolbec
2014-09-11  3:50 ` Brian Dolbec [this message]
2014-09-11  3:50 ` [gentoo-catalyst] [PATCH 2/3] [2 of 3] Update module loading for the new python structure Brian Dolbec
2014-09-11  3:50 ` [gentoo-catalyst] [PATCH 3/3] [3 of 3] Rename all target .py files and classes without _target in them Brian Dolbec

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1410407450-2888-2-git-send-email-dolsen@gentoo.org \
    --to=dolsen@gentoo.org \
    --cc=gentoo-catalyst@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox