Fix incorrect type for livecd/modblacklist.
[catalyst.git] / modules / livecd_stage2_target.py
index 5b8a8cefb35237cfe2ef50b8d5f5c908ad050b40..5be8fd23870d7955eee29230de511ddd8ea5b84f 100644 (file)
-# Distributed under the GNU General Public License version 2
-# Copyright 2003-2004 Gentoo Technologies, Inc.
-# $Header: /var/cvsroot/gentoo/src/catalyst/modules/livecd_stage2_target.py,v 1.11 2004/07/03 00:33:37 zhen Exp $
-
 """
-Builder class for a LiveCD stage2 build.
+LiveCD stage2 target, builds upon previous LiveCD stage1 tarball
 """
+# NOTE: That^^ docstring has influence catalyst-spec(5) man page generation.
 
-import os,string,types
+import os,string,types,stat,shutil
 from catalyst_support import *
 from generic_stage_target import *
 
 class livecd_stage2_target(generic_stage_target):
+       """
+       Builder class for a LiveCD stage2 build.
+       """
        def __init__(self,spec,addlargs):
-               self.required_values=["boot/kernel","livecd/cdfstype",\
-               "livecd/archscript","livecd/runscript"]
-               
+               self.required_values=["boot/kernel"]
+
                self.valid_values=[]
-               if not addlargs.has_key("boot/kernel"):
-                       raise CatalystError, "Required value boot/kernel not specified."
-                       
-               if type(addlargs["boot/kernel"]) == types.StringType:
-                       loopy=[addlargs["boot/kernel"]]
-                       
-               else:
-                       loopy=addlargs["boot/kernel"]
-                       
-               for x in loopy:
-                       self.required_values.append("boot/kernel/"+x+"/sources")
-                       self.required_values.append("boot/kernel/"+x+"/config")
-                       self.valid_values.append("boot/kernel/"+x+"/extraversion")
-                       self.valid_values.append("boot/kernel/"+x+"/packages")
-                       self.valid_values.append("boot/kernel/"+x+"/use")
-                       self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
-               
+
                self.valid_values.extend(self.required_values)
                self.valid_values.extend(["livecd/cdtar","livecd/empty","livecd/rm",\
                        "livecd/unmerge","livecd/iso","livecd/gk_mainargs","livecd/type",\
-                       "livecd/motd","livecd/overlay","livecd/modblacklist","livecd/bootsplash",\
-                       "livecd/rcadd","livecd/rcdel","livecd/fsscript"])
-               
+                       "livecd/readme","livecd/motd","livecd/overlay",\
+                       "livecd/modblacklist","livecd/splash_theme","livecd/rcadd",\
+                       "livecd/rcdel","livecd/fsscript","livecd/xinitrc",\
+                       "livecd/root_overlay","livecd/users","portage_overlay",\
+                       "livecd/fstype","livecd/fsops","livecd/linuxrc","livecd/bootargs",\
+                       "gamecd/conf","livecd/xdm","livecd/xsession","livecd/volid"])
+
                generic_stage_target.__init__(self,spec,addlargs)
-               file_locate(self.settings, ["livecd/cdtar","livecd/archscript","livecd/runscript"])
-               if self.settings.has_key("portage_confdir"):
-                       file_locate(self.settings,["portage_confdir"],expand=0)
-       
-       def unpack_and_bind(self):
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["cdroot_path"]+"/tmp/.unpack_and_bind"):
-                       print "Detected resume point, skipping unpack and bind operation..."
-               
-               else:
-                       if os.path.exists(self.settings["chroot_path"]):
-                               print "Removing previously-existing livecd-stage2 chroot directory..."
-                               cmd("rm -rf "+self.settings["chroot_path"],"Error removing livecd-stage2 chroot")
-                               os.makedirs(self.settings["chroot_path"])
-                               
-                       print "Copying livecd-stage1 result to new livecd-stage2 work directory..."
-                       cmd("cp -a "+self.settings["source_path"]+"/* "+self.settings["chroot_path"],
-                               "Error copying initial livecd-stage2")
-                       touch(self.settings["chroot_path"]+"/tmp/.unpack_and_bind")
-       
-               # we do not want to resume code below this line
-               print "Configuring profile link..."
-               cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile","Error zapping profile link")
-               cmd("ln -sf ../usr/portage/profiles/"+self.settings["target_profile"]+" "
-                       +self.settings["chroot_path"]+"/etc/make.profile","Error creating profile link")
-       
-               if self.settings.has_key("portage_confdir"):
-                       print "Configuring /etc/portage..."
-                       cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage","Error zapping /etc/portage")
-                       cmd("cp -R "+self.settings["portage_confdir"]+" "+self.settings["chroot_path"]+\
-                               "/etc/portage","Error copying /etc/portage")
+               if "livecd/type" not in self.settings:
+                       self.settings["livecd/type"] = "generic-livecd"
 
-               for x in self.mounts: 
-                       if not os.path.exists(self.settings["chroot_path"]+x):
-                               os.makedirs(self.settings["chroot_path"]+x)
-                       if not os.path.exists(self.mountmap[x]):
-                               os.makedirs(self.mountmap[x])
-                       src=self.mountmap[x]
-                       retval=os.system("mount --bind "+src+" "+self.settings["chroot_path"]+x)
-                       if retval!=0:
-                               self.unbind()
-                               raise CatalystError,"Couldn't bind mount "+src
-                       
-       def unmerge(self):
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["chroot_path"]+"/tmp/unmerge"):
-                       print "Detected resume point, skipping unmerge operation..."
-               
-               else:
-                       if self.settings.has_key("livecd/unmerge"):
-                               if type(self.settings["livecd/unmerge"])==types.StringType:
-                                       self.settings["livecd/unmerge"]=[self.settings["livecd/unmerge"]]
-                               myunmerge=self.settings["livecd/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("/bin/bash "+self.settings["sharedir"]+"/targets/"
-                                               +self.settings["target"]+"/unmerge.sh "+myunmerge,"Unmerge script failed.")
-                               
-                               except CatalystError:
-                                       self.unbind()
-                                       raise
-                               touch(self.settings["chroot_path"]+"/tmp/unmerge")
+               file_locate(self.settings, ["cdtar","controller_file"])
 
-       def clean(self):
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["chroot_path"]+"/tmp/.clean"):
-                       print "Detected resume point, skipping clean operation..."
-               
+       def set_source_path(self):
+               self.settings["source_path"]=normpath(self.settings["storedir"]+"/builds/"+self.settings["source_subpath"]+".tar.bz2")
+               if os.path.isfile(self.settings["source_path"]):
+                       self.settings["source_path_hash"]=generate_hash(self.settings["source_path"])
                else:
-                       generic_stage_target.clean(self)
-                       try:
-                               cmd("/bin/bash "+self.settings["livecd/runscript"]+" clean",\
-                                       "Clean runscript failed.")
-                       except:
-                               self.unbind()
-                               raise
-                       touch(self.settings["chroot_path"]+"/tmp/.clean")
+                       self.settings["source_path"]=normpath(self.settings["storedir"]+"/tmp/"+self.settings["source_subpath"]+"/")
+               if not os.path.exists(self.settings["source_path"]):
+                       raise CatalystError,"Source Path: "+self.settings["source_path"]+" does not exist."
+
+       def set_spec_prefix(self):
+           self.settings["spec_prefix"]="livecd"
 
-       def preclean(self):
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["chroot_path"]+"/tmp/.preclean"):
-                       print "Detected resume point, skipping preclean operation..."
-               
+       def set_target_path(self):
+               self.settings["target_path"]=normpath(self.settings["storedir"]+"/builds/"+self.settings["target_subpath"]+"/")
+               if "AUTORESUME" in self.settings \
+                       and os.path.exists(self.settings["autoresume_path"]+"setup_target_path"):
+                               print "Resume point detected, skipping target path setup operation..."
                else:
+                       # first clean up any existing target stuff
+                       if os.path.isdir(self.settings["target_path"]):
+                               cmd("rm -rf "+self.settings["target_path"],
+                               "Could not remove existing directory: "+self.settings["target_path"],env=self.env)
+                               touch(self.settings["autoresume_path"]+"setup_target_path")
+                       if not os.path.exists(self.settings["target_path"]):
+                               os.makedirs(self.settings["target_path"])
+
+       def run_local(self):
+               # what modules do we want to blacklist?
+               if "livecd/modblacklist" in self.settings:
                        try:
-                               cmd("/bin/bash "+self.settings["livecd/runscript"]+" preclean",
-                                       "Preclean runscript failed.")
-                       
+                               myf=open(self.settings["chroot_path"]+"/etc/modprobe.d/blacklist.conf","a")
                        except:
                                self.unbind()
-                               raise
-                       touch(self.settings["chroot_path"]+"/tmp/.preclean")
+                               raise CatalystError,"Couldn't open "+self.settings["chroot_path"]+"/etc/modprobe.d/blacklist.conf."
 
-       def cdroot_setup(self):
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["chroot_path"]+"/tmp/.cdroot_setup"):
-                       print "Detected resume point, skipping cdroot setup..."
-               
-               else:
-                       cmd("/bin/bash "+self.settings["livecd/runscript"]+" cdfs","CDFS runscript failed.")
-                       if self.settings.has_key("livecd/overlay"):
-                               cmd("/bin/cp -a "+self.settings["livecd/overlay"]+"/* "+\
-                                       self.settings["cdroot_path"],"LiveCD overlay copy failed.")
-                                       
-                       touch(self.settings["chroot_path"]+"/tmp/.cdroot_setup")
-               
-               # create the ISO - this is the preferred method (the iso scripts do not always work)
-               if self.settings.has_key("livecd/iso"):
-                       cmd("/bin/bash "+self.settings["livecd/runscript"]+" iso "+\
-                               self.settings["livecd/iso"],"ISO creation runscript failed.")
-               
-               print "livecd-stage2: complete!"
+                       myf.write("\n#Added by Catalyst:")
+                       # workaround until config.py is using configparser
+                       if isinstance(self.settings["livecd/modblacklist"], str):
+                               self.settings["livecd/modblacklist"] = self.settings["livecd/modblacklist"].split()
+                       for x in self.settings["livecd/modblacklist"]:
+                               myf.write("\nblacklist "+x)
+                       myf.close()
 
-       def build_kernel(self):
-               mynames=self.settings["boot/kernel"]
-               if type(mynames)==types.StringType:
-                       mynames=[mynames]
-               args=[]
-               args.append(`len(mynames)`)
-               
-               for kname in mynames:
-                       args.append(kname)
-                       args.append(self.settings["boot/kernel/"+kname+"/sources"])
-                       try:
-                               if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
-                                       self.unbind()
-                                       raise CatalystError, "Can't find kernel config: " \
-                                               +self.settings["boot/kernel/"+kname+"/config"]
-                       
-                       except TypeError:
-                               raise CatalystError, "Required value boot/kernel/config not specified"
-                       
-                       """
-                       We must support multiple configs for the same kernel,
-                       so we must manually edit the EXTRAVERSION on the kernel to allow them to coexist.
-                       The extraversion field gets appended to the current EXTRAVERSION
-                       in the kernel Makefile.  Examples of this usage are UP vs SMP kernels,
-                       and on PPC64 we need a seperate pSeries, iSeries, and PPC970 (G5) kernels,
-                       all compiled off the same source, without having to release a seperate 
-                       livecd for each (since other than the kernel, they are all binary compatible)
-                       """
-                       if self.settings.has_key("boot/kernel/"+kname+"/extraversion"):
-                               # extraversion is now an optional parameter, so that don't need to
-                               # worry about it unless they have to
-                               args.append(self.settings["boot/kernel/"+kname+"/extraversion"])
-                       
-                       else:
-                               # this value will be detected on the bash side and indicate
-                               # that EXTRAVERSION processing
-                               # should be skipped
-                               args.append("NULL_VALUE")
-                       
-                       # write out /var/tmp/kname.(use|packages) files, used for kernel USE
-                       # and extra packages settings
-                       for extra in ["use","packages","gk_kernargs"]:
-                               if self.settings.has_key("boot/kernel/"+kname+"/"+extra):
-                                       myex=self.settings["boot/kernel/"+kname+"/"+extra]
-                                       if type(myex)==types.ListType:
-                                               myex=string.join(myex)
-                                       try:
-                                               myf=open(self.settings["chroot_path"]+"/var/tmp/"+kname+"."+extra,"w")
-                                       except:
-                                               self.unbind()
-                                               raise CatalystError,"Couldn't create file /var/tmp/"+kname+"."+extra+" in chroot."
-                                       # write out to the file 
-                                       if extra=="use":
-                                               myf.write("export USE=\""+myex+"\"\n")
-                                       if extra=="gk_kernargs":
-                                               myf.write("export clst_livecd_gk_kernargs=\""+myex+"\"\n")
-                                       else:
-                                               myf.write(myex+"\n")
-                                       myf.close()
-                       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"])
-               
-                       except CatalystError:
-                               self.unbind()
+       def unpack(self):
+               unpack=True
+               display_msg=None
 
-                       # If we need to pass special options to the bootloader
-                       # for this kernel put them into the environment.
-                       if self.settings.has_key("boot/kernel/"+kname+"/kernelopts"):
-                               myopts=self.settings["boot/kernel/"+kname+"/kernelopts"]
-                               
-                               if type(myopts) != types.StringType:
-                                       myopts = string.join(myopts)
-                               os.putenv(kname+"_kernelopts", myopts)
+               clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+"unpack")
 
-                       else:
-                               os.putenv(kname+"_kernelopts", "")
+               if os.path.isdir(self.settings["source_path"]):
+                       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."
+                       invalid_snapshot=False
 
-                       # execute the script that builds the kernel
-                       cmd("/bin/bash "+self.settings["livecd/runscript"]+" kernel "+list_bashify(args),
-                               "Runscript kernel build failed")
+               if "AUTORESUME" in self.settings:
+                       if os.path.isdir(self.settings["source_path"]) and \
+                               os.path.exists(self.settings["autoresume_path"]+"unpack"):
+                               print "Resume point detected, skipping unpack operation..."
+                               unpack=False
+                       elif "source_path_hash" in self.settings:
+                               if self.settings["source_path_hash"] != clst_unpack_hash:
+                                       invalid_snapshot=True
 
-       def run_local(self):
-               # first clean up any existing cdroot stuff
-               # unless of course we are resuming
-               if self.settings.has_key("AUTORESUME") \
-                       and os.path.exists(self.settings["chroot_path"]+"/tmp/.run_local_cdroot_clean"):
-                       print "Detected resume point, not cleaning cdroot_path..."
-               
-               else:
-                       if os.path.exists(self.settings["cdroot_path"]):
-                               print "cleaning previous livecd-stage2 build"
-                               cmd("rm -rf "+self.settings["cdroot_path"],
-                                       "Could not remove existing directory: "+self.settings["cdroot_path"])
-                       else:
-                               os.makedirs(self.settings["cdroot_path"])
-                               touch(self.settings["chroot_path"]+"/tmp/.run_local_cdroot_clean")
-                               
-               # the runscripts do the real building, so execute them now
-               # this is the part that we want to resume on since it is the most time consuming
-               try:
-                       if self.settings.has_key("AUTORESUME") \
-                               and os.path.exists(self.settings["chroot_path"]+"/tmp/.run_local_kernel_script"):
-                               print "Resume point detected, skipping kernel build runscript..."
-                       
-                       else:
-                               self.build_kernel()
-                               touch(self.settings["chroot_path"]+"/tmp/.run_local_kernel_script")
-                       
-                       if self.settings.has_key("AUTORESUME") \
-                               and os.path.exists(self.settings["chroot_path"]+"/tmp/.run_local_bootloader_script"):
-                               print "Resume point detected, skipping bootloader runscript..."
-                       
-                       else:
-                               cmd("/bin/bash "+self.settings["livecd/runscript"]+" bootloader","Bootloader runscript failed.")
-                               touch(self.settings["chroot_path"]+"/tmp/.run_local_bootloader_script")
-               
-               except CatalystError:
-                       self.unbind()
-                       raise CatalystError,"Runscript aborting due to error."
+               if unpack:
+                       self.mount_safety_check()
+                       if invalid_snapshot:
+                               print "No Valid Resume point detected, cleaning up  ..."
+                               #os.remove(self.settings["autoresume_path"]+"dir_setup")
+                               self.clear_autoresume()
+                               self.clear_chroot()
+                               #self.dir_setup()
 
-               # what modules do we want to blacklist?
-               if self.settings.has_key("AUTORESUME") \
-                               and os.path.exists(self.settings["chroot_path"]+"/tmp/.run_local_blacklist"):
-                               print "Resume point detected, skipping module blacklisting..."
-               
-               else:
-                       if self.settings.has_key("livecd/modblacklist"):
-                               try:
-                                       myf=open(self.settings["chroot_path"]+"/etc/hotplug/blacklist","a")
-                               except:
-                                       self.unbind()
-                                       raise CatalystError,"Couldn't open "+self.settings["chroot_path"]+"/etc/hotplug/blacklist."
-                               myf.write("\n#Added by Catalyst:")
-                               for x in self.settings["livecd/modblacklist"]:
-                                       myf.write("\n"+x)
+                       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:
+                               if not os.path.exists(self.settings["pkgcache_path"]):
+                                       os.makedirs(self.settings["pkgcache_path"],0755)
+
+                       if not display_msg:
+                               raise CatalystError,"Could not find appropriate source. Please check the 'source_subpath' setting in the spec file."
+
+                       print display_msg
+                       cmd(unpack_cmd,error_msg,env=self.env)
+
+                       if "source_path_hash" in self.settings:
+                               myf=open(self.settings["autoresume_path"]+"unpack","w")
+                               myf.write(self.settings["source_path_hash"])
                                myf.close()
-                       touch(self.settings["chroot_path"]+"/tmp/.run_local_blacklist")
+                       else:
+                               touch(self.settings["autoresume_path"]+"unpack")
+
+       def set_action_sequence(self):
+               self.settings["action_sequence"]=["unpack","unpack_snapshot",\
+                               "config_profile_link","setup_confdir","portage_overlay",\
+                               "bind","chroot_setup","setup_environment","run_local",\
+                               "build_kernel"]
+               if "FETCH" not in self.settings:
+                       self.settings["action_sequence"] += ["bootloader","preclean",\
+                               "livecd_update","root_overlay","fsscript","rcupdate","unmerge",\
+                               "unbind","remove","empty","target_setup",\
+                               "setup_overlay","create_iso"]
+               self.settings["action_sequence"].append("clear_autoresume")
 
 def register(foo):
        foo.update({"livecd-stage2":livecd_stage2_target})