Fixed up action_sequence when using --fetchonly to not create tarballs or ISO images...
[catalyst.git] / modules / generic_stage_target.py
1 # $Header: /var/cvsroot/gentoo/src/catalyst/modules/generic_stage_target.py,v 1.141 2006/10/02 20:41:54 wolf31o2 Exp $
2
3 """
4 This class does all of the chroot setup, copying of files, etc. It is
5 the driver class for pretty much everything that Catalyst does.
6 """
7
8 import os,string,imp,types,shutil
9 from catalyst_support import *
10 from generic_target import *
11 from stat import *
12 import catalyst_lock
13 class generic_stage_target(generic_target):
14
15         def __init__(self,myspec,addlargs):
16                 self.required_values.extend(["version_stamp","target","subarch",\
17                         "rel_type","profile","snapshot","source_subpath"])
18                 
19                 self.valid_values.extend(["version_stamp","target","subarch",\
20                         "rel_type","profile","snapshot","source_subpath","portage_confdir",\
21                         "cflags","cxxflags","ldflags","chost","hostuse","portage_overlay",\
22                         "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
23                 
24                 self.set_valid_build_kernel_vars(addlargs)
25                 generic_target.__init__(self,myspec,addlargs)
26                 # map the mainarch we are running under to the mainarches we support for
27                 # building stages and LiveCDs. (for example, on amd64, we can build
28                 # stages for x86 or amd64.
29                 targetmap={     
30                                 "x86" : ["x86"],
31                                 "amd64" : ["x86","amd64"],
32                                 "sparc64" : ["sparc","sparc64"],
33                                 "ia64" : ["ia64"],
34                                 "alpha" : ["alpha"],
35                                 "sparc" : ["sparc"],
36                                 "sh" : ["sh"],
37                                 "s390" : ["s390"],
38                                 "ppc" : ["ppc"],
39                                 "ppc64" : ["ppc","ppc64"],
40                                 "hppa" : ["hppa"],
41                                 "mips" : ["mips"],
42                                 "arm" : ["arm"]
43                 }
44                 
45                 machinemap={    
46                                 "i386" : "x86",
47                                 "i486" : "x86",
48                                 "i586" : "x86",
49                                 "i686" : "x86",
50                                 "x86_64" : "amd64",
51                                 "sparc64" : "sparc64",
52                                 "ia64" : "ia64",
53                                 "alpha" : "alpha",
54                                 "sparc" : "sparc",
55                                 "sh2" : "sh",
56                                 "sh3" : "sh",
57                                 "sh4" : "sh",
58                                 "sh2eb" : "sh",
59                                 "sh3eb" : "sh",
60                                 "sh4eb" : "sh",
61                                 "s390" : "s390",
62                                 "ppc" : "ppc",
63                                 "ppc64" : "ppc64",
64                                 "parisc" : "hppa",
65                                 "parisc64" : "hppa",
66                                 "mips" : "mips",
67                                 "mips64" : "mips",
68                                 "arm" : "arm",
69                                 "armv4l" : "arm",
70                                 "armeb" : "arm",
71                                 "armv5b" : "arm"
72                 }
73                 
74                 mymachine=os.uname()[4]
75                 if not machinemap.has_key(mymachine):
76                         raise CatalystError, "Unknown machine type "+mymachine
77                         
78                 self.settings["hostarch"]=machinemap[mymachine]
79                 self.archmap={}
80                 self.subarchmap={}
81                 
82                 for x in targetmap[self.settings["hostarch"]]:
83                         try:
84                                 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
85                                 # This next line loads the plugin as a module and assigns it to
86                                 # archmap[x]
87                                 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+".py",(".py","r",imp.PY_SOURCE))
88                                 # This next line registers all the subarches supported in the
89                                 # plugin
90                                 self.archmap[x].register(self.subarchmap)
91                                 fh.close()      
92                         
93                         except IOError:
94                                 msg("Can't find "+x+".py plugin in "+self.settings["sharedir"]+"/arch/")
95                 # Call arch constructor, pass our settings
96                 try:
97                         self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
98                 except:
99                         print "Invalid subarch: "+self.settings["subarch"]
100                         print "Choose one of the following:",
101                         for x in self.subarchmap:
102                                 print x,
103                         print
104                         sys.exit(2)
105
106                 print "Using target:",self.settings["target"]
107                 # self.settings["mainarch"] should now be set by our arch constructor,
108                 # so we print a nice informational message:
109                 if self.settings["mainarch"]==self.settings["hostarch"]:
110                         print "Building natively for",self.settings["hostarch"]
111                 
112                 else:
113                         print "Building on",self.settings["hostarch"],"for alternate machine type",\
114                                 self.settings["mainarch"]
115                 # This should be first to be set as other set_ options depend on this
116                 self.set_spec_prefix()
117                 
118                 # define all of our core variables
119                 self.set_target_profile()
120                 self.set_target_subpath()
121                 self.set_source_subpath()
122
123                 # set paths
124                 self.set_snapshot_path()
125                 self.set_root_path()
126                 self.set_source_path()
127                 self.set_snapcache_path()
128                 self.set_chroot_path()
129                 self.set_autoresume_path()
130                 self.set_dest_path()
131                 self.set_stage_path()
132                 self.set_target_path()
133                 
134                 self.set_controller_file()
135                 self.set_action_sequence()
136                 self.set_use()
137                 self.set_cleanables()
138                 self.set_iso_volume_id()
139                 self.set_build_kernel_vars()
140                 self.set_fsscript()
141                 self.set_archscript()
142                 self.set_runscript()
143                 self.set_install_mask()
144                 self.set_rcadd()
145                 self.set_rcdel()
146                 self.set_cdtar()
147                 self.set_fstype()
148                 self.set_fsops()
149                 self.set_iso()
150                 self.set_packages()
151                 self.set_rm()
152                 self.set_linuxrc()
153                 self.set_overlay()      
154                 self.set_portage_overlay()      
155                 self.set_root_overlay() 
156                 
157                 # This next line checks to make sure that the specified variables exist
158                 # on disk.
159                 #pdb.set_trace()
160                 file_locate(self.settings,["source_path","snapshot_path","distdir"],expand=0)
161                 # If we are using portage_confdir, check that as well.
162                 if self.settings.has_key("portage_confdir"):
163                         file_locate(self.settings,["portage_confdir"],expand=0)
164                 
165                 # setup our mount points
166                 if self.settings.has_key("SNAPCACHE"):
167                         self.mounts=[ "/proc","/dev","/usr/portage","/usr/portage/distfiles" ]
168                         self.mountmap={"/proc":"/proc", "/dev":"/dev", "/dev/pts":"/dev/pts",\
169                                 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
170                                 "/usr/portage/distfiles":self.settings["distdir"]}
171                 else:
172                         self.mounts=[ "/proc","/dev","/usr/portage/distfiles" ]
173                         self.mountmap={"/proc":"/proc", "/dev":"/dev", "/dev/pts":"/dev/pts",\
174                                 "/usr/portage/distfiles":self.settings["distdir"]}
175                 if os.uname()[0] == "Linux":
176                         self.mounts.append("/dev/pts")
177
178                 self.set_mounts()
179
180                 # Configure any user specified options (either in catalyst.conf or on
181                 # the command line).
182                 if self.settings.has_key("PKGCACHE"):
183                         self.set_pkgcache_path()
184                         print "Location of the package cache is " + self.settings["pkgcache_path"]
185                         self.mounts.append("/usr/portage/packages")
186                         self.mountmap["/usr/portage/packages"]=self.settings["pkgcache_path"]
187                 
188                 if self.settings.has_key("KERNCACHE"):
189                         self.set_kerncache_path()
190                         print "Location of the kerncache is " + self.settings["kerncache_path"]
191                         self.mounts.append("/tmp/kerncache")
192                         self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
193
194                 if self.settings.has_key("CCACHE"):
195                         if os.environ.has_key("CCACHE_DIR"):
196                                 ccdir=os.environ["CCACHE_DIR"]
197                                 del os.environ["CCACHE_DIR"]
198                         else:
199                                 ccdir="/root/.ccache"
200                         if not os.path.isdir(ccdir):
201                                         raise CatalystError,\
202                                                 "Compiler cache support can't be enabled (can't find "+ccdir+")"
203                         self.mounts.append("/var/tmp/ccache")
204                         self.mountmap["/var/tmp/ccache"]=ccdir
205                         # for the chroot:
206                         self.env["CCACHE_DIR"]="/var/tmp/ccache"        
207
208         def override_chost(self):
209                 if self.makeconf.has_key("CHOST"):
210                         self.settings["CHOST"]=self.makeconf["CHOST"]
211         
212         def override_cflags(self):
213                 if self.makeconf.has_key("CFLAGS"):
214                         self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
215
216         def override_cxxflags(self):    
217                 if self.makeconf.has_key("CXXFLAGS"):
218                         self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
219         
220         def override_ldflags(self):
221                 if self.makeconf.has_key("LDFLAGS"):
222                         self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
223         
224         def set_install_mask(self):
225                 if self.settings.has_key("install_mask"):
226                         if type(self.settings["install_mask"]) != types.StringType:
227                                 self.settings["install_mask"]=string.join(self.settings["install_mask"])
228         
229         def set_spec_prefix(self):
230                 self.settings["spec_prefix"]=self.settings["target"]
231
232         def set_target_profile(self):
233                 self.settings["target_profile"]=self.settings["profile"]
234         
235         def set_target_subpath(self):
236                 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+self.settings["target"]+\
237                         "-"+self.settings["subarch"]+"-"+self.settings["version_stamp"]
238         
239         def set_source_subpath(self):
240                 if type(self.settings["source_subpath"]) != types.StringType:
241                         raise CatalystError, "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
242         
243         def set_pkgcache_path(self):
244                 if self.settings.has_key("pkgcache_path"):
245                         if type(self.settings["pkgcache_path"]) != types.StringType:
246                                 self.settings["pkgcache_path"]=normpath(string.join(self.settings["pkgcache_path"]))
247                 else:
248                         self.settings["pkgcache_path"]=normpath(self.settings["storedir"]+"/packages/"+\
249                                 self.settings["target_subpath"]+"/")
250
251         def set_kerncache_path(self):
252                 if self.settings.has_key("kerncache_path"):
253                         if type(self.settings["kerncache_path"]) != types.StringType:
254                                 self.settings["kerncache_path"]=normpath(string.join(self.settings["kerncache_path"]))
255                 else:
256                         self.settings["kerncache_path"]=normpath(self.settings["storedir"]+"/kerncache/"+\
257                                 self.settings["target_subpath"]+"/")
258
259         def set_target_path(self):
260                 self.settings["target_path"]=normpath(self.settings["storedir"]+"/builds/"+\
261                         self.settings["target_subpath"]+".tar.bz2")
262                 if self.settings.has_key("AUTORESUME") \
263                         and os.path.exists(self.settings["autoresume_path"]+"setup_target_path"):
264                         print "Resume point detected, skipping target path setup operation..."
265                 else:
266                         # first clean up any existing target stuff
267                         if os.path.isfile(self.settings["target_path"]):
268                                 cmd("rm -f "+self.settings["target_path"], \
269                                         "Could not remove existing file: "+self.settings["target_path"],env=self.env)
270                                 touch(self.settings["autoresume_path"]+"setup_target_path")
271                 
272                         if not os.path.exists(self.settings["storedir"]+"/builds/"):
273                                 os.makedirs(self.settings["storedir"]+"/builds/")
274
275         def set_archscript(self):
276             if self.settings.has_key(self.settings["spec_prefix"]+"/archscript"):
277                 print "\nWarning!!!  "
278                 print "\t"+self.settings["spec_prefix"]+"/archscript" + " is deprecated and no longer used.\n"
279         def set_runscript(self):
280             if self.settings.has_key(self.settings["spec_prefix"]+"/runscript"):
281                 print "\nWarning!!!  "
282                 print "\t"+self.settings["spec_prefix"]+"/runscript" + " is deprecated and no longer used.\n"
283
284         def set_fsscript(self): 
285                 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
286                         self.settings["fsscript"]=self.settings[self.settings["spec_prefix"]+"/fsscript"]
287                         del self.settings[self.settings["spec_prefix"]+"/fsscript"]
288         
289         def set_rcadd(self):    
290                 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
291                         self.settings["rcadd"]=self.settings[self.settings["spec_prefix"]+"/rcadd"]
292                         del self.settings[self.settings["spec_prefix"]+"/rcadd"]
293         
294         def set_rcdel(self):    
295                 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
296                         self.settings["rcdel"]=self.settings[self.settings["spec_prefix"]+"/rcdel"]
297                         del self.settings[self.settings["spec_prefix"]+"/rcdel"]
298
299         def set_cdtar(self):    
300                 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
301                         self.settings["cdtar"]=normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
302                         del self.settings[self.settings["spec_prefix"]+"/cdtar"]
303         
304         def set_iso(self):      
305                 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
306                         self.settings["iso"]=normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
307                         del self.settings[self.settings["spec_prefix"]+"/iso"]
308
309         def set_fstype(self):   
310                 if self.settings.has_key(self.settings["spec_prefix"]+"/cdfstype"):
311                         print "\nWarning!!!  "
312                         print self.settings["spec_prefix"]+"/cdfstype" + " is deprecated and may be removed."
313                         print "\tUse "+self.settings["spec_prefix"]+"/fstype" + " instead."
314                         print "\tConverting to "+self.settings["spec_prefix"]+"/fstype" + " internally."
315                         print "\tContinuing ....\n"
316                         self.settings["fstype"]=self.settings[self.settings["spec_prefix"]+"/cdfstype"]
317                         del self.settings[self.settings["spec_prefix"]+"/cdfstype"]
318                 
319                 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
320                         self.settings["fstype"]=self.settings[self.settings["spec_prefix"]+"/fstype"]
321                         del self.settings[self.settings["spec_prefix"]+"/fstype"]
322
323                 if not self.settings.has_key("fstype"):
324                         self.settings["fstype"]="normal"
325                         for x in self.valid_values:
326                                 if x ==  self.settings["spec_prefix"]+"/fstype" or x == self.settings["spec_prefix"]+"/cdfstype":
327                                         print "\n"+self.settings["spec_prefix"]+"/fstype is being set to the default of \"normal\"\n"
328
329         def set_fsops(self):
330                 if self.settings.has_key("fstype"):
331                         self.valid_values.append("fsops")
332                         if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
333                                 self.settings["fsops"]=self.settings[self.settings["spec_prefix"]+"/fsops"]
334                                 del self.settings[self.settings["spec_prefix"]+"/fsops"]
335         
336         def set_source_path(self):
337                 if self.settings.has_key("SEEDCACHE") and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+self.settings["source_subpath"]+"/")):
338                         self.settings["source_path"]=normpath(self.settings["storedir"]+"/tmp/"+self.settings["source_subpath"]+"/")
339                 else:
340                         self.settings["source_path"]=normpath(self.settings["storedir"]+"/builds/"+self.settings["source_subpath"]+".tar.bz2")
341                         if os.path.isfile(self.settings["source_path"]):
342                                 if os.path.exists(self.settings["source_path"]): # XXX: Is this even necessary if the previous check passes?
343                                         self.settings["source_path_hash"]=generate_hash(self.settings["source_path"],\
344                                                 hash_function=self.settings["hash_function"],verbose=False)
345                 print "Source path set to "+self.settings["source_path"]
346                 if os.path.isdir(self.settings["source_path"]):
347                         print "\tIf this is not desired, remove this directory or turn of seedcache in the options of catalyst.conf"
348                         print "\tthe source path will then be "+normpath(self.settings["storedir"]+"/builds/"+self.settings["source_subpath"]+".tar.bz2\n")
349
350         def set_dest_path(self):
351                 if self.settings.has_key("root_path"):
352                         self.settings["destpath"]=normpath(self.settings["chroot_path"]+self.settings["root_path"])
353                 else:
354                         self.settings["destpath"]=normpath(self.settings["chroot_path"])
355
356         def set_cleanables(self):
357                 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*","/root/*",\
358                                                 "/usr/portage"]
359
360         def set_snapshot_path(self):
361                 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+"/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
362                 
363                 if os.path.exists(self.settings["snapshot_path"]):
364                         self.settings["snapshot_path_hash"]=generate_hash(self.settings["snapshot_path"],\
365                                         hash_function=self.settings["hash_function"],verbose=False)
366         
367         def set_snapcache_path(self):
368                 if self.settings.has_key("SNAPCACHE"):
369                         self.settings["snapshot_cache_path"]=normpath(self.settings["snapshot_cache"]+"/"+self.settings["snapshot"]+"/")
370                         self.snapcache_lock=catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
371                         print "Caching snapshot to " + self.settings["snapshot_cache_path"]
372         
373         def set_chroot_path(self):
374                 # Note the trailing slash is very important and things would break without it
375                 self.settings["chroot_path"]=normpath(self.settings["storedir"]+"/tmp/"+self.settings["target_subpath"]+"/")
376                 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
377         
378         def set_autoresume_path(self):
379                 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+"/tmp/"+\
380                         self.settings["rel_type"]+"/"+".autoresume-"+self.settings["target"]+\
381                         "-"+self.settings["subarch"]+"-"+self.settings["version_stamp"]+"/")
382                 if self.settings.has_key("AUTORESUME"):
383                         print "The autoresume path is " + self.settings["autoresume_path"]
384                 if not os.path.exists(self.settings["autoresume_path"]):
385                         os.makedirs(self.settings["autoresume_path"],0755)
386         
387         def set_controller_file(self):
388                 self.settings["controller_file"]=normpath(self.settings["sharedir"]+"/targets/"+self.settings["target"]+"/"+self.settings["target"]+"-controller.sh")
389
390         def set_iso_volume_id(self):
391                 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
392                         self.settings["iso_volume_id"] = string.join(self.settings[self.settings["spec_prefix"]+"/volid"])
393                         if len(self.settings["iso_volume_id"])>32:
394                                 raise CatalystError,"ISO VOLUME ID: volid must not exceed 32 characters."
395                 else:
396                         self.settings["iso_volume_id"] = "catalyst " + self.settings["snapshot"] 
397                                                                                                                         
398         def set_action_sequence(self):
399                 # Default action sequence for run method
400                 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
401                                 "config_profile_link","setup_confdir","portage_overlay",\
402                                 "base_dirs","bind","chroot_setup","setup_environment",\
403                                 "run_local","preclean","unbind","clean"]
404 #               if self.settings.has_key("TARBALL") or \
405 #                       not self.settings.has_key("FETCH"):
406                 if not self.settings.has_key("FETCH"):
407                         self.settings["action_sequence"].append("capture")
408                 self.settings["action_sequence"].append("clear_autoresume")
409         
410         def set_use(self):
411                 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
412                         self.settings["use"]=self.settings[self.settings["spec_prefix"]+"/use"]
413                         del self.settings[self.settings["spec_prefix"]+"/use"]
414                 if self.settings.has_key("use"):
415                     if type(self.settings["use"])==types.StringType:
416                         self.settings["use"]=self.settings["use"].split()
417
418         def set_stage_path(self):
419                         self.settings["stage_path"]=normpath(self.settings["chroot_path"])
420         
421         def set_mounts(self):
422                 pass
423
424         def set_packages(self):
425                 pass
426
427         def set_rm(self):
428             if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
429                 if type(self.settings[self.settings["spec_prefix"]+"/rm"])==types.StringType:
430                     self.settings[self.settings["spec_prefix"]+"/rm"]=self.settings[self.settings["spec_prefix"]+"/rm"].split()
431
432         def set_linuxrc(self):
433             if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
434                         if type(self.settings[self.settings["spec_prefix"]+"/linuxrc"])==types.StringType:
435                                 self.settings["linuxrc"]=self.settings[self.settings["spec_prefix"]+"/linuxrc"]
436                                 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
437
438         def set_portage_overlay(self):
439                 if self.settings.has_key("portage_overlay"):
440                         if type(self.settings["portage_overlay"])==types.StringType:
441                                 self.settings["portage_overlay"]=self.settings["portage_overlay"].split()
442                         print "portage_overlay directories are set to: \"" + string.join(self.settings["portage_overlay"])+"\""
443         
444         def set_overlay(self):
445                 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
446                         if type(self.settings[self.settings["spec_prefix"]+"/overlay"])==types.StringType:
447                                 self.settings[self.settings["spec_prefix"]+"/overlay"]=self.settings[self.settings["spec_prefix"]+"/overlay"].split()
448         
449         def set_root_overlay(self):
450                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
451                         if type(self.settings[self.settings["spec_prefix"]+"/root_overlay"])==types.StringType:
452                                 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=self.settings[self.settings["spec_prefix"]+"/root_overlay"].split()
453         
454
455         def set_root_path(self):
456                 # ROOT= variable for emerges
457                 self.settings["root_path"]="/"
458
459         def set_valid_build_kernel_vars(self,addlargs):
460                 if addlargs.has_key("boot/kernel"):
461                         if type(addlargs["boot/kernel"]) == types.StringType:
462                                 loopy=[addlargs["boot/kernel"]]
463                         else:
464                                 loopy=addlargs["boot/kernel"]
465                             
466                         for x in loopy:
467                                 self.required_values.append("boot/kernel/"+x+"/sources")
468                                 self.required_values.append("boot/kernel/"+x+"/config")
469                                 self.valid_values.append("boot/kernel/"+x+"/aliases")
470                                 self.valid_values.append("boot/kernel/"+x+"/extraversion")
471                                 self.valid_values.append("boot/kernel/"+x+"/packages")
472                                 if addlargs.has_key("boot/kernel/"+x+"/packages"):
473                                         if type(addlargs["boot/kernel/"+x+"/packages"]) == types.StringType:
474                                                 addlargs["boot/kernel/"+x+"/packages"]=[addlargs["boot/kernel/"+x+"/packages"]]
475                                 self.valid_values.append("boot/kernel/"+x+"/use")
476                                 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
477                                 self.valid_values.append("boot/kernel/"+x+"/gk_action")
478                                 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
479                                 self.valid_values.append("boot/kernel/"+x+"/softlevel")
480                                 self.valid_values.append("boot/kernel/"+x+"/console")
481                                 self.valid_values.append("boot/kernel/"+x+"/machine_type")
482                                 self.valid_values.append("boot/kernel/"+x+"/postconf")
483                                 if addlargs.has_key("boot/kernel/"+x+"/postconf"):
484                                         print "boot/kernel/"+x+"/postconf is deprecated"
485                                         print "\tInternally moving these ebuilds to boot/kernel/"+x+"/packages"
486                                         print "\tPlease move them to boot/kernel/"+x+"/packages in your specfile"
487                                         if type(addlargs["boot/kernel/"+x+"/postconf"]) == types.StringType:
488                                                 loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
489                                         else:
490                                                 loop2=addlargs["boot/kernel/"+x+"/postconf"]
491                                 
492                                         for y in loop2:
493                                                 if not addlargs.has_key("boot/kernel/"+x+"/packages"):
494                                                         addlargs["boot/kernel/"+x+"/packages"]=[y]
495                                                 else:
496                                                         addlargs["boot/kernel/"+x+"/packages"].append(y)
497
498         def set_build_kernel_vars(self):
499             if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
500                 self.settings["devmanager"]=self.settings[self.settings["spec_prefix"]+"/devmanager"]
501                 del self.settings[self.settings["spec_prefix"]+"/devmanager"]
502             
503             if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
504                 self.settings["splashtype"]=self.settings[self.settings["spec_prefix"]+"/splashtype"]
505                 del self.settings[self.settings["spec_prefix"]+"/splashtype"]
506             
507             if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
508                 self.settings["gk_mainargs"]=self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
509                 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
510
511         def kill_chroot_pids(self):
512             print "Checking for processes running in chroot and killing them."
513             
514             # Force environment variables to be exported so script can see them
515             self.setup_environment()
516
517             if os.path.exists(self.settings["sharedir"]+"/targets/support/kill-chroot-pids.sh"):
518                             cmd("/bin/bash "+self.settings["sharedir"]+"/targets/support/kill-chroot-pids.sh",\
519                                                 "kill-chroot-pids script failed.",env=self.env)
520         
521         def mount_safety_check(self):
522                 mypath=self.settings["chroot_path"]
523                 
524                 """
525                 check and verify that none of our paths in mypath are mounted. We don't want to clean
526                 up with things still mounted, and this allows us to check. 
527                 returns 1 on ok, 0 on "something is still mounted" case.
528                 """
529                 if not os.path.exists(mypath):
530                         return
531                 
532                 for x in self.mounts:
533                         if not os.path.exists(mypath+x):
534                                 continue
535                         
536                         if ismount(mypath+x):
537                                 #something is still mounted
538                                 try:
539                                         print x+" is still mounted; performing auto-bind-umount...",
540                                         # try to umount stuff ourselves
541                                         self.unbind()
542                                         if ismount(mypath+x):
543                                                 raise CatalystError, "Auto-unbind failed for "+x
544                                         
545                                         else:
546                                                 print "Auto-unbind successful..."
547                                 
548                                 except CatalystError:
549                                         raise CatalystError, "Unable to auto-unbind "+x
550                 
551         def unpack(self):
552                 unpack=True
553
554                 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+"unpack")
555                 
556                 if self.settings.has_key("SEEDCACHE"):
557                         if os.path.isdir(self.settings["source_path"]): 
558                                 # SEEDCACHE Is a directory, use Rsync
559                                 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+" "+self.settings["chroot_path"]
560                                 display_msg="\nStarting rsync from "+self.settings["source_path"]+"\nto "+\
561                                         self.settings["chroot_path"]+" (This may take some time) ...\n"
562                                 error_msg="Rsync of "+self.settings["source_path"]+" to "+self.settings["chroot_path"]+" failed."
563                         else:
564                                 # SEEDCACHE is a not a directory, try untar'ing
565                                 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
566                                 display_msg="\nStarting tar extract from "+self.settings["source_path"]+"\nto "+\
567                                         self.settings["chroot_path"]+" (This may take some time) ...\n"
568                                 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+self.settings["chroot_path"]
569                                 error_msg="Tarball extraction of "+self.settings["source_path"]+" to "+self.settings["chroot_path"]+" failed."
570                 else:
571                         # No SEEDCACHE, use tar
572                         display_msg="\nStarting tar extract from "+self.settings["source_path"]+"\nto "+\
573                                 self.settings["chroot_path"]+" (This may take some time) ...\n"
574                         unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+self.settings["chroot_path"]
575                         error_msg="Tarball extraction of "+self.settings["source_path"]+" to "+self.settings["chroot_path"]+" failed."
576                 
577                 
578                 if self.settings.has_key("AUTORESUME"):
579                         # Autoresume is Valid, SeedCache is Valid
580                         if os.path.isdir(self.settings["source_path"]) and os.path.exists(self.settings["autoresume_path"]+"unpack"):
581                                 unpack=False
582                                 invalid_snapshot=False
583                         
584                         # Autoresume is Valid, Tarball is Valid
585                         elif os.path.isfile(self.settings["source_path"]) and self.settings["source_path_hash"] == clst_unpack_hash:
586                                 unpack=False
587                                 invalid_snapshot=True
588                         
589                         # Autoresume is InValid, SeedCache
590                         elif os.path.isdir(self.settings["source_path"]) and not os.path.exists(self.settings["autoresume_path"]+"unpack"):
591                                 unpack=True
592                                 invalid_snapshot=False
593                         
594                         # Autoresume is InValid, Tarball
595                         elif os.path.isfile(self.settings["source_path"]) and self.settings["source_path_hash"] != clst_unpack_hash:
596                                 unpack=True
597                                 invalid_snapshot=True
598                 else:
599                         # No Autoresume,SeedCache
600                         if self.settings.has_key("SEEDCACHE"):
601                                 
602                                 # Seed cache so lets run rsync and rsync can clean up extra junk
603                                 if os.path.isdir(self.settings["source_path"]):
604                                         unpack=True
605                                         invalid_snapshot=False
606                 
607                                 # Tarball so we better unpack and remove anything already there
608                                 elif os.path.isfile(self.settings["source_path"]):
609                                         unpack=True
610                                         invalid_snapshot=True
611                         
612                         # No Autoresume,No SeedCache
613                         else:
614                                 
615                                 # Tarball so we better unpack and remove anything already there
616                                 if os.path.isfile(self.settings["source_path"]):
617                                         unpack=True
618                                         invalid_snapshot=True
619                                 # Should never reach this if so something is very wrong
620                                 elif os.path.isdir(self.settings["source_path"]):
621                                         raise CatalystError,"source path is a dir but seedcache is not enabled"
622
623                 if unpack:
624                         self.mount_safety_check()
625                         
626                         if invalid_snapshot:
627                                 if self.settings.has_key("AUTORESUME"):
628                                         print "No Valid Resume point detected, cleaning up  ..."
629                                 
630                                 self.clear_autoresume()
631                                 self.clear_chroot()
632                         
633                         if not os.path.exists(self.settings["chroot_path"]):
634                                 os.makedirs(self.settings["chroot_path"])
635
636                         if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
637                                 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
638                         
639                         if self.settings.has_key("PKGCACHE"):   
640                                 if not os.path.exists(self.settings["pkgcache_path"]):
641                                         os.makedirs(self.settings["pkgcache_path"],0755)
642                         
643                         if self.settings.has_key("KERNCACHE"):  
644                                 if not os.path.exists(self.settings["kerncache_path"]):
645                                         os.makedirs(self.settings["kerncache_path"],0755)
646                         
647                         print display_msg
648                         cmd(unpack_cmd,error_msg,env=self.env)
649
650                         if self.settings.has_key("source_path_hash"):
651                                 myf=open(self.settings["autoresume_path"]+"unpack","w")
652                                 myf.write(self.settings["source_path_hash"])
653                                 myf.close()
654                         else:
655                                 touch(self.settings["autoresume_path"]+"unpack")
656                 else:
657                     print "Resume point detected, skipping unpack operation..."
658         
659
660         def unpack_snapshot(self):
661                 unpack=True
662                 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+"unpack_portage")
663                 
664                 if self.settings.has_key("SNAPCACHE"): 
665                         snapshot_cache_hash=read_from_clst(self.settings["snapshot_cache_path"]+"catalyst-hash")
666                         destdir=self.settings["snapshot_cache_path"]
667                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
668                         unpack_errmsg="Error unpacking snapshot"
669                         cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+self.settings["snapshot_cache_path"]+" (This can take a long time)..."
670                         cleanup_errmsg="Error removing existing snapshot cache directory."
671                         self.snapshot_lock_object=self.snapcache_lock
672                         
673                         if self.settings["snapshot_path_hash"] == snapshot_cache_hash:
674                                 print "Valid snapshot cache, skipping unpack of portage tree ..."
675                                 unpack=False
676                 
677                 else:
678                         destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
679                         cleanup_errmsg="Error removing existing snapshot directory."
680                         cleanup_msg="Cleaning up existing portage tree (This can take a long time) ..."
681                         unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+self.settings["chroot_path"]+"/usr"
682                         unpack_errmsg="Error unpacking snapshot"
683                 
684                         if self.settings.has_key("AUTORESUME") \
685                         and os.path.exists(self.settings["chroot_path"]+"/usr/portage/") \
686                         and os.path.exists(self.settings["autoresume_path"]+"unpack_portage") \
687                         and self.settings["snapshot_path_hash"] == snapshot_hash:
688                                 print "Valid Resume point detected, skipping unpack of portage tree..."
689                                 unpack=False
690                                     
691                 
692                 
693                 if unpack:
694                         if self.settings.has_key("SNAPCACHE"): 
695                             self.snapshot_lock_object.write_lock()
696                         if os.path.exists(destdir):
697                                 print cleanup_msg
698                                 cleanup_cmd="rm -rf "+destdir
699                                 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
700                         if not os.path.exists(destdir):
701                                 os.makedirs(destdir,0755)
702                         
703                         print "Unpacking portage tree (This can take a long time) ..."
704                         cmd(unpack_cmd,unpack_errmsg,env=self.env)
705
706                         if self.settings.has_key("SNAPCACHE"): 
707                                 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
708                                 myf.write(self.settings["snapshot_path_hash"])
709                                 myf.close()
710                         
711                         else:   
712                                 print "Setting snapshot autoresume point"
713                                 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
714                                 myf.write(self.settings["snapshot_path_hash"])
715                                 myf.close()
716                         
717                         if self.settings.has_key("SNAPCACHE"): 
718                             self.snapshot_lock_object.unlock()
719
720         def config_profile_link(self):
721                 if self.settings.has_key("AUTORESUME") \
722                         and os.path.exists(self.settings["autoresume_path"]+"config_profile_link"):
723                         print "Resume point detected, skipping config_profile_link operation..."
724                 else:
725                         print "Configuring profile link..."
726                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
727                                         "Error zapping profile link",env=self.env)
728                         cmd("ln -sf ../usr/portage/profiles/"+self.settings["target_profile"]+\
729                                 " "+self.settings["chroot_path"]+"/etc/make.profile","Error creating profile link",env=self.env)
730                         touch(self.settings["autoresume_path"]+"config_profile_link")
731                                        
732         def setup_confdir(self):        
733                 if self.settings.has_key("AUTORESUME") \
734                         and os.path.exists(self.settings["autoresume_path"]+"setup_confdir"):
735                         print "Resume point detected, skipping setup_confdir operation..."
736                 else:
737                         if self.settings.has_key("portage_confdir"):
738                                 print "Configuring /etc/portage..."
739                                 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage","Error zapping /etc/portage",env=self.env)
740                                 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+self.settings["chroot_path"]+\
741                                         "/etc/portage","Error copying /etc/portage",env=self.env)
742                                 touch(self.settings["autoresume_path"]+"setup_confdir")
743         
744         def portage_overlay(self):      
745             # copy over the portage overlays
746             # Always copy over the overlay incase it has changed
747             if self.settings.has_key("portage_overlay"):
748                 for x in self.settings["portage_overlay"]: 
749                         if os.path.exists(x):
750                                 print "Copying overlay dir " +x
751                                 cmd("mkdir -p "+self.settings["chroot_path"]+x,"Could not make portage_overlay dir",env=self.env)
752                                 #cmd("rsync -a --delete "+x+"/* "+self.settings["chroot_path"]+x,\
753                                 cmd("rsync -a --delete "+x+"/ "+self.settings["chroot_path"]+x,\
754                                                 "Could not copy portage_overlay",env=self.env)
755                                 #cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+x,"Could not copy portage_overlay",env=self.env)
756         
757         def root_overlay(self):
758             # copy over the root_overlay
759             # Always copy over the overlay incase it has changed
760                 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
761                         for x in self.settings[self.settings["spec_prefix"]+"/root_overlay"]: 
762                                 if os.path.exists(x):
763                                         print "Copying root_overlay: "+x
764                                         cmd("rsync -a "+x+"/ "+\
765                                                 self.settings["chroot_path"], self.settings["spec_prefix"]+"/root_overlay: "+x+" copy failed.",env=self.env)
766
767         def base_dirs(self):
768                 pass
769
770         def bind(self):
771                 for x in self.mounts: 
772                         if not os.path.exists(self.settings["chroot_path"]+x):
773                                 os.makedirs(self.settings["chroot_path"]+x,0755)
774                         
775                         if not os.path.exists(self.mountmap[x]):
776                                 os.makedirs(self.mountmap[x],0755)
777                         
778                         src=self.mountmap[x]
779                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
780                                 self.snapshot_lock_object.read_lock()
781                         if os.uname()[0] == "FreeBSD":
782                                 if src == "/dev":
783                                         retval=os.system("mount -t devfs none "+self.settings["chroot_path"]+x)
784                                 else:
785                                         retval=os.system("mount_nullfs "+src+" "+self.settings["chroot_path"]+x)
786                         else:
787                                 retval=os.system("mount --bind "+src+" "+self.settings["chroot_path"]+x)
788                         if retval!=0:
789                                 self.unbind()
790                                 raise CatalystError,"Couldn't bind mount "+src
791                             
792         
793         def unbind(self):
794                 ouch=0
795                 mypath=self.settings["chroot_path"]
796                 myrevmounts=self.mounts[:]
797                 myrevmounts.reverse()
798                 # unmount in reverse order for nested bind-mounts
799                 for x in myrevmounts:
800                         if not os.path.exists(mypath+x):
801                                 continue
802                         
803                         if not ismount(mypath+x):
804                                 # it's not mounted, continue
805                                 continue
806                         
807                         retval=os.system("umount "+os.path.join(mypath,x.lstrip(os.path.sep)))
808                         
809                         if retval!=0:
810                                 warn("First attempt to unmount: "+mypath+x+" failed.")
811                                 warn("Killing any pids still running in the chroot")
812                                 
813                                 self.kill_chroot_pids()
814                                 
815                                 retval2=os.system("umount "+mypath+x)
816                                 if retval2!=0:
817                                     ouch=1
818                                     warn("Couldn't umount bind mount: "+mypath+x)
819                                     # keep trying to umount the others, to minimize damage if developer makes a mistake
820                 
821                         if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
822                                 try:
823                                     # Its possible the snapshot lock object isnt created yet
824                                     # this is because mount safety check calls unbind before the target is fully initialized            
825                                     self.snapshot_lock_object.unlock()
826                                 except:
827                                     pass
828                 if ouch:
829                         """
830                         if any bind mounts really failed, then we need to raise
831                         this to potentially prevent an upcoming bash stage cleanup script
832                         from wiping our bind mounts.
833                         """
834                         raise CatalystError,"Couldn't umount one or more bind-mounts; aborting for safety."
835
836         def chroot_setup(self):
837                 self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
838                 self.override_chost()   
839                 self.override_cflags()
840                 self.override_cxxflags()        
841                 self.override_ldflags() 
842                 if self.settings.has_key("AUTORESUME") \
843                         and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
844                         print "Resume point detected, skipping chroot_setup operation..."
845                 else:
846                         print "Setting up chroot..."
847                         
848                         #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
849                         
850                         cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
851                                 "Could not copy resolv.conf into place.",env=self.env)
852                 
853                     # copy over the envscript, if applicable
854                         if self.settings.has_key("ENVSCRIPT"):
855                                 if not os.path.exists(self.settings["ENVSCRIPT"]):
856                                         raise CatalystError, "Can't find envscript "+self.settings["ENVSCRIPT"]
857                             
858                                 print "\nWarning!!!!"
859                                 print "\tOverriding certain env variables may cause catastrophic failure."
860                                 print "\tIf your build fails look here first as the possible problem."
861                                 print "\tCatalyst assumes you know what you are doing when setting"
862                                 print "\t\tthese variables."
863                                 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
864                                 print "\tYou have been warned\n"
865                                 
866                                 cmd("cp "+self.settings["ENVSCRIPT"]+" "+self.settings["chroot_path"]+"/tmp/envscript",\
867                                         "Could not copy envscript into place.",env=self.env)
868
869                     # Copy over /etc/hosts from the host in case there are any
870                         # specialties in there
871                         if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
872                                 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+self.settings["chroot_path"]+\
873                                         "/etc/hosts.bck", "Could not backup /etc/hosts",env=self.env)
874                                 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts", "Could not copy /etc/hosts",env=self.env)
875                         #self.override_chost()  
876                         #self.override_cflags()
877                         #self.override_cxxflags()       
878                         #self.override_ldflags()        
879                         # Modify and write out make.conf (for the chroot)
880                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf","Could not remove "+self.settings["chroot_path"]+"/etc/make.conf",\
881                                 env=self.env)
882                         myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
883                         myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
884                         myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
885                         myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
886                         if self.settings.has_key("CXXFLAGS"):
887                                 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
888                         else:
889                                 myf.write('CXXFLAGS="${CFLAGS}"\n')
890                     
891                         if self.settings.has_key("LDFLAGS"):
892                                 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
893                         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.\m")
894                         myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
895                     
896                     # Figure out what our USE vars are for building
897                         myusevars=[]
898                         if self.settings.has_key("HOSTUSE"):
899                                 myusevars.extend(self.settings["HOSTUSE"])
900                 
901                         if self.settings.has_key("use"):
902                                 myusevars.extend(self.settings["use"])
903                                 myf.write('USE="'+string.join(myusevars)+'"\n')
904
905                     # Setup the portage overlay 
906                         if self.settings.has_key("portage_overlay"):
907                                 myf.write('PORTDIR_OVERLAY="'+string.join(self.settings["portage_overlay"])+'"\n')
908                         
909                         myf.close()
910                         touch(self.settings["autoresume_path"]+"chroot_setup")
911         
912         def fsscript(self):
913                 if self.settings.has_key("AUTORESUME") \
914                         and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
915                         print "Resume point detected, skipping fsscript operation..."
916                 else:
917                     if self.settings.has_key("fsscript"):
918                         if os.path.exists(self.settings["controller_file"]):
919                             cmd("/bin/bash "+self.settings["controller_file"]+" fsscript","fsscript script failed.",env=self.env)
920                         touch(self.settings["autoresume_path"]+"fsscript")
921
922         def rcupdate(self):
923                 if self.settings.has_key("AUTORESUME") \
924                         and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
925                         print "Resume point detected, skipping rcupdate operation..."
926                 else:
927                     if os.path.exists(self.settings["controller_file"]):
928                         cmd("/bin/bash "+self.settings["controller_file"]+" rc-update","rc-update script failed.",env=self.env)
929                         touch(self.settings["autoresume_path"]+"rcupdate")
930
931         def clean(self):
932                 if self.settings.has_key("AUTORESUME") \
933                         and os.path.exists(self.settings["autoresume_path"]+"clean"):
934                         print "Resume point detected, skipping clean operation..."
935                 else:
936                     for x in self.settings["cleanables"]: 
937                             print "Cleaning chroot: "+x+"... "
938                             cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+x,env=self.env)
939
940                     # put /etc/hosts back into place
941                     if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.bck"):
942                             cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.bck "+self.settings["chroot_path"]+\
943                                           "/etc/hosts", "Could not replace /etc/hosts",env=self.env)
944         
945                     if os.path.exists(self.settings["controller_file"]):
946                         cmd("/bin/bash "+self.settings["controller_file"]+" clean","clean script failed.",env=self.env)
947                         touch(self.settings["autoresume_path"]+"clean")
948         
949         def empty(self):                
950             if self.settings.has_key("AUTORESUME") \
951                 and os.path.exists(self.settings["autoresume_path"]+"empty"):
952                 print "Resume point detected, skipping empty operation..."
953             else:
954                 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
955                     if type(self.settings[self.settings["spec_prefix"]+"/empty"])==types.StringType:
956                         self.settings[self.settings["spec_prefix"]+"/empty"]=self.settings[self.settings["spec_prefix"]+"/empty"].split()
957                     for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
958                         myemp=self.settings["destpath"]+x
959                         if not os.path.isdir(myemp):
960                             print x,"not a directory or does not exist, skipping 'empty' operation."
961                             continue
962                         print "Emptying directory",x
963                         # stat the dir, delete the dir, recreate the dir and set
964                         # the proper perms and ownership
965                         mystat=os.stat(myemp)
966                         shutil.rmtree(myemp)
967                         os.makedirs(myemp,0755)
968                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
969                         os.chmod(myemp,mystat[ST_MODE])
970                     touch(self.settings["autoresume_path"]+"empty")
971         
972         def remove(self):
973             if self.settings.has_key("AUTORESUME") \
974                 and os.path.exists(self.settings["autoresume_path"]+"remove"):
975                 print "Resume point detected, skipping remove operation..."
976             else:
977                 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
978                     for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
979                         # we're going to shell out for all these cleaning operations,
980                         # so we get easy glob handling
981                         print "livecd: removing "+x
982                         os.system("rm -rf "+self.settings["chroot_path"]+x)
983                 try:
984                     if os.path.exists(self.settings["controller_file"]):
985                             cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
986                                 "Clean  failed.",env=self.env)
987                             touch(self.settings["autoresume_path"]+"remove")
988                 except:
989                     self.unbind()
990                     raise
991
992         
993         def preclean(self):
994             if self.settings.has_key("AUTORESUME") \
995                 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
996                 print "Resume point detected, skipping preclean operation..."
997             else:
998                 try:
999                         if os.path.exists(self.settings["controller_file"]):
1000                                 cmd("/bin/bash "+self.settings["controller_file"]+" preclean","preclean script failed.",env=self.env)
1001                                 touch(self.settings["autoresume_path"]+"preclean")
1002                 
1003                 except:
1004                         self.unbind()
1005                         raise CatalystError, "Build failed, could not execute preclean"
1006
1007         def capture(self):
1008             if self.settings.has_key("AUTORESUME") \
1009                 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1010                 print "Resume point detected, skipping capture operation..."
1011             else:
1012                 """capture target in a tarball"""
1013                 mypath=self.settings["target_path"].split("/")
1014                 # remove filename from path
1015                 mypath=string.join(mypath[:-1],"/")
1016                 
1017                 # now make sure path exists
1018                 if not os.path.exists(mypath):
1019                         os.makedirs(mypath)
1020
1021                 print "Creating stage tarball..."
1022                 
1023                 cmd("tar cjpf "+self.settings["target_path"]+" -C "+self.settings["stage_path"]+\
1024                         " .","Couldn't create stage tarball",env=self.env)
1025
1026                 self.gen_digest_file(self.settings["target_path"])
1027
1028                 touch(self.settings["autoresume_path"]+"capture")
1029
1030         def run_local(self):
1031             if self.settings.has_key("AUTORESUME") \
1032                 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1033                 print "Resume point detected, skipping run_local operation..."
1034             else:
1035                 try:
1036                         if os.path.exists(self.settings["controller_file"]):
1037                                 cmd("/bin/bash "+self.settings["controller_file"]+" run","run script failed.",env=self.env)
1038                                 touch(self.settings["autoresume_path"]+"run_local")
1039
1040                 except CatalystError:
1041                         self.unbind()
1042                         raise CatalystError,"Stage build aborting due to error."
1043         
1044         def setup_environment(self):
1045                 # Modify the current environment. This is an ugly hack that should be
1046                 # fixed. We need this to use the os.system() call since we can't
1047                 # specify our own environ:
1048                 for x in self.settings.keys():
1049                         # "/" is replaced with "_", "-" is replaced with "_", and "." is
1050                         # replaced with "_"
1051                         varname="clst_"+string.replace(x,"/","_")
1052                         varname=string.replace(varname,"-","_")
1053                         varname=string.replace(varname,".","_")
1054                         if type(self.settings[x])==types.StringType:
1055                                 # prefix to prevent namespace clashes:
1056                                 #os.environ[varname]=self.settings[x]
1057                                 self.env[varname]=self.settings[x]
1058                         elif type(self.settings[x])==types.ListType:
1059                                 #os.environ[varname]=string.join(self.settings[x])
1060                                 self.env[varname]=string.join(self.settings[x])
1061                 if self.settings.has_key("makeopts"):
1062                         self.env["MAKEOPTS"]=self.settings["makeopts"]
1063                         
1064         def run(self):
1065                 self.chroot_lock.write_lock()
1066
1067                 # Kill any pids in the chroot
1068                 self.kill_chroot_pids()
1069
1070                 # Check for mounts right away and abort if we cannot unmount them.
1071                 self.mount_safety_check()
1072
1073                 if self.settings.has_key("CLEAR_AUTORESUME"):
1074                         self.clear_autoresume()
1075                 if self.settings.has_key("PURGE"):
1076                         self.purge()
1077
1078                 for x in self.settings["action_sequence"]:
1079                         print "Running action sequence: "+x
1080                         sys.stdout.flush()
1081                         try:
1082                                 apply(getattr(self,x))
1083                         except:
1084                                 self.mount_safety_check()
1085                                 raise
1086                 
1087                 self.chroot_lock.unlock()
1088
1089         def unmerge(self):
1090             if self.settings.has_key("AUTORESUME") \
1091                 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1092                     print "Resume point detected, skipping unmerge operation..."
1093             else:
1094                 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1095                     if type(self.settings[self.settings["spec_prefix"]+"/unmerge"])==types.StringType:
1096                         self.settings[self.settings["spec_prefix"]+"/unmerge"]=[self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1097                     myunmerge=self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1098                     
1099                     for x in range(0,len(myunmerge)):
1100                     #surround args with quotes for passing to bash,
1101                     #allows things like "<" to remain intact
1102                         myunmerge[x]="'"+myunmerge[x]+"'"
1103                     myunmerge=string.join(myunmerge)
1104                     
1105                     #before cleaning, unmerge stuff:
1106                     try:
1107                         cmd("/bin/bash "+self.settings["controller_file"]+" unmerge "+ myunmerge,\
1108                                 "Unmerge script failed.",env=self.env)
1109                         #cmd("/bin/bash "+self.settings["sharedir"]+"/targets/" \
1110                         #       +self.settings["target"]+"/unmerge.sh "+myunmerge,"Unmerge script failed.",env=self.env)
1111                         print "unmerge shell script"
1112                     except CatalystError:
1113                         self.unbind()
1114                         raise
1115
1116                 touch(self.settings["autoresume_path"]+"unmerge")
1117
1118         def target_setup(self):
1119             if self.settings.has_key("AUTORESUME") \
1120                 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1121                     print "Resume point detected, skipping target_setup operation..."
1122             else:
1123                 print "Setting up filesystems per filesystem type"
1124                 cmd("/bin/bash "+self.settings["controller_file"]+" target_image_setup "+ self.settings["target_path"],\
1125                                 "target_image_setup script failed.",env=self.env)
1126                 touch(self.settings["autoresume_path"]+"target_setup")
1127         
1128         def setup_overlay(self):        
1129                 if self.settings.has_key("AUTORESUME") \
1130                 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1131                         print "Resume point detected, skipping setup_overlay operation..."
1132                 else:
1133                         if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1134                                 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]: 
1135                                         if os.path.exists(x):
1136                                                 cmd("rsync -a "+x+"/ "+\
1137                                                         self.settings["target_path"], self.settings["spec_prefix"]+"overlay: "+x+" copy failed.",env=self.env)
1138                                 touch(self.settings["autoresume_path"]+"setup_overlay")
1139         
1140         def create_iso(self):
1141             if self.settings.has_key("AUTORESUME") \
1142                 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1143                     print "Resume point detected, skipping create_iso operation..."
1144             else:
1145                 # create the ISO - this is the preferred method (the iso scripts do not always work)
1146                 if self.settings.has_key("iso"):
1147                         cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1148                                 self.settings["iso"],"ISO creation script failed.",env=self.env)
1149                         self.gen_digest_file(self.settings["iso"])
1150                         touch(self.settings["autoresume_path"]+"create_iso")
1151                 
1152                 
1153                 else:
1154                         print "WARNING livecd/iso was not defined."
1155                         print "A CD Image will not be created, skipping create-iso.sh..."
1156
1157
1158         def build_packages(self):
1159             if self.settings.has_key("AUTORESUME") \
1160                 and os.path.exists(self.settings["autoresume_path"]+"build_packages"):
1161                     print "Resume point detected, skipping build_packages operation..."
1162             else:
1163                 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1164                         if self.settings.has_key("AUTORESUME") \
1165                                 and os.path.exists(self.settings["autoresume_path"]+"build_packages"):
1166                                         print "Resume point detected, skipping build_packages operation..."
1167                         else:
1168                                 mypack=list_bashify(self.settings[self.settings["spec_prefix"]+"/packages"])
1169                                 try:
1170                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1171                                                 " build_packages "+mypack,"Error in attempt to build packages",env=self.env)
1172                                         touch(self.settings["autoresume_path"]+"build_packages")
1173                                 except CatalystError:
1174                                         self.unbind()
1175                                         raise CatalystError,self.settings["spec_prefix"] + "build aborting due to error."
1176         
1177         def build_kernel(self):
1178                 if self.settings.has_key("AUTORESUME") \
1179                 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1180                         print "Resume point detected, skipping build_kernel operation..."
1181                 else:
1182                         if self.settings.has_key("boot/kernel"):
1183                                 try:
1184                                         mynames=self.settings["boot/kernel"]
1185                                         if type(mynames)==types.StringType:
1186                                                 mynames=[mynames]
1187                                         # execute the script that sets up the kernel build environment
1188                                         cmd("/bin/bash "+self.settings["controller_file"]+" pre-kmerge ",\
1189                                                 "Runscript pre-kmerge failed",env=self.env)
1190                 
1191                                         for kname in mynames:
1192                                                 if self.settings.has_key("AUTORESUME") \
1193                                                         and os.path.exists(self.settings["autoresume_path"]+"build_kernel_"+kname):
1194                                                         print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1195                                                 else:
1196                                                         try:
1197                                                                 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1198                                                                         self.unbind()
1199                                                                         raise CatalystError, "Can't find kernel config: " \
1200                                                                                 +self.settings["boot/kernel/"+kname+"/config"]
1201
1202                                                         except TypeError:
1203                                                                 raise CatalystError, "Required value boot/kernel/config not specified"
1204                         
1205                                                         try:
1206                                                                 cmd("cp "+self.settings["boot/kernel/"+kname+"/config"]+" "+ \
1207                                                                         self.settings["chroot_path"]+"/var/tmp/"+kname+".config", \
1208                                                                         "Couldn't copy kernel config: "+self.settings["boot/kernel/"+kname+"/config"],\
1209                                                                         env=self.env)
1210
1211                                                         except CatalystError:
1212                                                                 self.unbind()
1213
1214                                                         # If we need to pass special options to the bootloader
1215                                                         # for this kernel put them into the environment.
1216                                                         if self.settings.has_key("boot/kernel/"+kname+"/kernelopts"):
1217                                                                 myopts=self.settings["boot/kernel/"+kname+"/kernelopts"]
1218                                 
1219                                                                 if type(myopts) != types.StringType:
1220                                                                         myopts = string.join(myopts)
1221                                                                         self.env[kname+"_kernelopts"]=myopts
1222
1223                                                                 else:
1224                                                                         self.env[kname+"_kernelopts"]=""
1225                                             
1226                                                         if not self.settings.has_key("boot/kernel/"+kname+"/extraversion"):
1227                                                                 self.settings["boot/kernel/"+kname+"/extraversion"]=""
1228                                                 
1229                                                         self.env["clst_kextraversion"]=self.settings["boot/kernel/"+kname+"/extraversion"]
1230
1231                                                         if self.settings.has_key("boot/kernel/"+kname+"/initramfs_overlay"):
1232                                                                 if os.path.exists(self.settings["boot/kernel/"+kname+"/initramfs_overlay"]):
1233                                                                         print "Copying initramfs_overlay dir " +self.settings["boot/kernel/"+kname+"/initramfs_overlay"]
1234
1235                                                                         cmd("mkdir -p "+self.settings["chroot_path"]+"/tmp/initramfs_overlay/" + \
1236                                                                                 self.settings["boot/kernel/"+kname+"/initramfs_overlay"],env=self.env)
1237                                                 
1238                                                                         cmd("cp -R "+self.settings["boot/kernel/"+kname+"/initramfs_overlay"]+"/* " + \
1239                                                                                 self.settings["chroot_path"] + "/tmp/initramfs_overlay/" + \
1240                                                                                 self.settings["boot/kernel/"+kname+"/initramfs_overlay"],\
1241                                                                                 env=self.env)
1242         
1243
1244                                                         # execute the script that builds the kernel
1245                                                         cmd("/bin/bash "+self.settings["controller_file"]+" kernel "+kname,\
1246                                                                 "Runscript kernel build failed",env=self.env)
1247                                         
1248                                                         if self.settings.has_key("boot/kernel/"+kname+"/initramfs_overlay"):
1249                                                                 if os.path.exists(self.settings["chroot_path"]+"/tmp/initramfs_overlay/"):
1250                                                                         print "Cleaning up temporary overlay dir"
1251                                                                         cmd("rm -R "+self.settings["chroot_path"]+"/tmp/initramfs_overlay/",env=self.env)
1252
1253                                                         touch(self.settings["autoresume_path"]+"build_kernel_"+kname)
1254
1255                                                         # execute the script that cleans up the kernel build environment
1256                                                         cmd("/bin/bash "+self.settings["controller_file"]+" post-kmerge ",\
1257                                                                 "Runscript post-kmerge failed",env=self.env)
1258                                 
1259                                         touch(self.settings["autoresume_path"]+"build_kernel")
1260                         
1261                                 except CatalystError:
1262                                         self.unbind()
1263                                         raise CatalystError,"build aborting due to kernel build error."
1264
1265         def bootloader(self):
1266             if self.settings.has_key("AUTORESUME") \
1267                 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1268                     print "Resume point detected, skipping bootloader operation..."
1269             else:
1270                 try:
1271                         cmd("/bin/bash "+self.settings["controller_file"]+" bootloader " + self.settings["target_path"],\
1272                                 "Bootloader runscript failed.",env=self.env)
1273                         touch(self.settings["autoresume_path"]+"bootloader")
1274                 except CatalystError:
1275                         self.unbind()
1276                         raise CatalystError,"Runscript aborting due to error."
1277
1278         def livecd_update(self):
1279             if self.settings.has_key("AUTORESUME") \
1280                 and os.path.exists(self.settings["autoresume_path"]+"livecd_update"):
1281                     print "Resume point detected, skipping build_packages operation..."
1282             else:
1283                 try:
1284                         cmd("/bin/bash "+self.settings["controller_file"]+" livecd-update",\
1285                                 "livecd-update failed.",env=self.env)
1286                         touch(self.settings["autoresume_path"]+"livecd_update")
1287                 
1288                 except CatalystError:
1289                         self.unbind()
1290                         raise CatalystError,"build aborting due to livecd_update error."
1291
1292         def clear_chroot(self):
1293                 myemp=self.settings["chroot_path"]
1294                 if os.path.isdir(myemp):
1295                     print "Emptying directory",myemp
1296                     # stat the dir, delete the dir, recreate the dir and set
1297                     # the proper perms and ownership
1298                     mystat=os.stat(myemp)
1299                     #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1300                     if os.uname()[0] == "FreeBSD": # There's no easy way to change flags recursively in python
1301                             os.system("chflags -R noschg "+myemp)
1302                     shutil.rmtree(myemp)
1303                     os.makedirs(myemp,0755)
1304                     os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1305                     os.chmod(myemp,mystat[ST_MODE])
1306         
1307         def clear_packages(self):
1308             if self.settings.has_key("PKGCACHE"):
1309                 print "purging the pkgcache ..."
1310
1311                 myemp=self.settings["pkgcache_path"]
1312                 if os.path.isdir(myemp):
1313                     print "Emptying directory",myemp
1314                     # stat the dir, delete the dir, recreate the dir and set
1315                     # the proper perms and ownership
1316                     mystat=os.stat(myemp)
1317                     #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1318                     shutil.rmtree(myemp)
1319                     os.makedirs(myemp,0755)
1320                     os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1321                     os.chmod(myemp,mystat[ST_MODE])
1322         
1323         def clear_kerncache(self):
1324             if self.settings.has_key("KERNCACHE"):
1325                 print "purging the kerncache ..."
1326
1327                 myemp=self.settings["kerncache_path"]
1328                 if os.path.isdir(myemp):
1329                     print "Emptying directory",myemp
1330                     # stat the dir, delete the dir, recreate the dir and set
1331                     # the proper perms and ownership
1332                     mystat=os.stat(myemp)
1333                     #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1334                     shutil.rmtree(myemp)
1335                     os.makedirs(myemp,0755)
1336                     os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1337                     os.chmod(myemp,mystat[ST_MODE])
1338         
1339         def clear_autoresume(self):
1340                 # clean resume points since they are no longer needed
1341                 if self.settings.has_key("AUTORESUME"):
1342                         print "Removing AutoResume Points: ..."
1343                 myemp=self.settings["autoresume_path"]
1344                 if os.path.isdir(myemp):
1345                                 if self.settings.has_key("AUTORESUME"):
1346                                         print "Emptying directory",myemp
1347                                 # stat the dir, delete the dir, recreate the dir and set
1348                                 # the proper perms and ownership
1349                                 mystat=os.stat(myemp)
1350                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1351                                 shutil.rmtree(myemp)
1352                                 os.makedirs(myemp,0755)
1353                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1354                                 os.chmod(myemp,mystat[ST_MODE])
1355
1356         def gen_digest_file(self,file):
1357                 if os.path.exists(file+".DIGESTS"):
1358                         os.remove(file+".DIGESTS")
1359                 if self.settings.has_key("digests"):
1360                         if os.path.exists(file):
1361                                 myf=open(file+".DIGESTS","w")
1362                                 keys={}
1363                                 for i in self.settings["digests"].split():
1364                                         keys[i]=1
1365                                         array=keys.keys()
1366                                         array.sort()
1367                                 for j in array:
1368                                         if self.settings.has_key("VERBOSE"):
1369                                                 hash=generate_hash(file,hash_function=j,verbose=True)
1370                                         else:
1371                                                 hash=generate_hash(file,hash_function=j)
1372                                         myf.write(hash)
1373                                 myf.close()
1374
1375         def purge(self):
1376             countdown(10,"Purging Caches ...")
1377             if self.settings.has_key("PURGE"):
1378                 print "clearing autoresume ..."
1379                 self.clear_autoresume()
1380                 
1381                 print "clearing chroot ..."
1382                 self.clear_chroot()
1383                 
1384                 print "clearing package cache ..."
1385                 self.clear_packages()
1386                 
1387                 print "clearing kerncache ..."
1388                 self.clear_kerncache()
1389
1390 #vim: ts=4 sw=4 sta et sts=4 ai