3 This class does all of the chroot setup, copying of files, etc. It is
4 the driver class for pretty much everything that Catalyst does.
7 import os,string,imp,types,shutil
8 from catalyst_support import *
9 from generic_target import *
12 class generic_stage_target(generic_target):
14 def __init__(self,myspec,addlargs):
15 self.required_values.extend(["version_stamp","target","subarch",\
16 "rel_type","profile","snapshot","source_subpath"])
18 self.valid_values.extend(["version_stamp","target","subarch",\
19 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
20 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
21 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
23 self.set_valid_build_kernel_vars(addlargs)
24 generic_target.__init__(self,myspec,addlargs)
27 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
28 work better with vapier's CBUILD stuff. I've removed the "monolithic"
29 machinemap from this file and split up its contents amongst the
30 various arch/foo.py files.
32 When register() is called on each module in the arch/ dir, it now
33 returns a tuple instead of acting on the subarchmap dict that is
34 passed to it. The tuple contains the values that were previously
35 added to subarchmap as well as a new list of CHOSTs that go along
36 with that arch. This allows us to build machinemap on the fly based
37 on the keys in subarchmap and the values of the 2nd list returned
40 Also, after talking with vapier. I have a slightly better idea of what
41 certain variables are used for and what they should be set to. Neither
42 'buildarch' or 'hostarch' are used directly, so their value doesn't
43 really matter. They are just compared to determine if we are
44 cross-compiling. Because of this, they are just set to the name of the
45 module in arch/ that the subarch is part of to make things simpler.
46 The entire build process is still based off of 'subarch' like it was
53 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
54 "/arch/") if x.endswith(".py")]:
56 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
58 This next line loads the plugin as a module and assigns it to
61 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
62 ".py",(".py","r",imp.PY_SOURCE))
64 This next line registers all the subarches supported in the
67 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
68 self.subarchmap.update(tmpsubarchmap)
69 for machine in tmpmachinemap:
70 machinemap[machine] = x
71 for subarch in tmpsubarchmap:
72 machinemap[subarch] = x
76 This message should probably change a bit, since everything in
77 the dir should load just fine. If it doesn't, it's probably a
78 syntax error in the module
80 msg("Can't find/load "+x+".py plugin in "+\
81 self.settings["sharedir"]+"/arch/")
83 if self.settings.has_key("chost"):
84 hostmachine = self.settings["chost"].split("-")[0]
85 if not machinemap.has_key(hostmachine):
86 raise CatalystError, "Unknown host machine type "+hostmachine
87 self.settings["hostarch"]=machinemap[hostmachine]
89 hostmachine = self.settings["subarch"]
90 if machinemap.has_key(hostmachine):
91 hostmachine = machinemap[hostmachine]
92 self.settings["hostarch"]=hostmachine
93 if self.settings.has_key("cbuild"):
94 buildmachine = self.settings["cbuild"].split("-")[0]
96 buildmachine = os.uname()[4]
97 if not machinemap.has_key(buildmachine):
98 raise CatalystError, "Unknown build machine type "+buildmachine
99 self.settings["buildarch"]=machinemap[buildmachine]
100 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
101 self.settings["buildarch"])
103 """ Call arch constructor, pass our settings """
105 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
107 print "Invalid subarch: "+self.settings["subarch"]
108 print "Choose one of the following:",
109 for x in self.subarchmap:
114 print "Using target:",self.settings["target"]
115 """ Print a nice informational message """
116 if self.settings["buildarch"]==self.settings["hostarch"]:
117 print "Building natively for",self.settings["hostarch"]
118 elif self.settings["crosscompile"]:
119 print "Cross-compiling on",self.settings["buildarch"],\
120 "for different machine type",self.settings["hostarch"]
122 print "Building on",self.settings["buildarch"],\
123 "for alternate personality type",self.settings["hostarch"]
125 """ This must be set first as other set_ options depend on this """
126 self.set_spec_prefix()
128 """ Define all of our core variables """
129 self.set_target_profile()
130 self.set_target_subpath()
131 self.set_source_subpath()
134 self.set_snapshot_path()
136 self.set_source_path()
137 self.set_snapcache_path()
138 self.set_chroot_path()
139 self.set_autoresume_path()
141 self.set_stage_path()
142 self.set_target_path()
144 self.set_controller_file()
145 self.set_action_sequence()
147 self.set_cleanables()
148 self.set_iso_volume_id()
149 self.set_build_kernel_vars()
151 # TODO: Remove archscript/runscript from next major version
152 self.set_archscript()
154 self.set_install_mask()
165 self.set_portage_overlay()
166 self.set_root_overlay()
169 This next line checks to make sure that the specified variables exist
173 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
175 """ If we are using portage_confdir, check that as well. """
176 if self.settings.has_key("portage_confdir"):
177 file_locate(self.settings,["portage_confdir"],expand=0)
179 """ Setup our mount points """
180 if self.settings.has_key("SNAPCACHE"):
181 self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
182 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
183 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
184 "/usr/portage/distfiles":self.settings["distdir"]}
186 self.mounts=["/proc","/dev","/usr/portage/distfiles"]
187 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
188 "/usr/portage/distfiles":self.settings["distdir"]}
189 if os.uname()[0] == "Linux":
190 self.mounts.append("/dev/pts")
195 Configure any user specified options (either in catalyst.conf or on
198 if self.settings.has_key("PKGCACHE"):
199 self.set_pkgcache_path()
200 print "Location of the package cache is "+\
201 self.settings["pkgcache_path"]
202 self.mounts.append("/usr/portage/packages")
203 self.mountmap["/usr/portage/packages"]=\
204 self.settings["pkgcache_path"]
206 if self.settings.has_key("KERNCACHE"):
207 self.set_kerncache_path()
208 print "Location of the kerncache is "+\
209 self.settings["kerncache_path"]
210 self.mounts.append("/tmp/kerncache")
211 self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
213 if self.settings.has_key("CCACHE"):
214 if os.environ.has_key("CCACHE_DIR"):
215 ccdir=os.environ["CCACHE_DIR"]
216 del os.environ["CCACHE_DIR"]
218 ccdir="/root/.ccache"
219 if not os.path.isdir(ccdir):
220 raise CatalystError,\
221 "Compiler cache support can't be enabled (can't find "+\
223 self.mounts.append("/var/tmp/ccache")
224 self.mountmap["/var/tmp/ccache"]=ccdir
225 """ for the chroot: """
226 self.env["CCACHE_DIR"]="/var/tmp/ccache"
228 if self.settings.has_key("ICECREAM"):
229 self.mounts.append("/var/cache/icecream")
230 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
231 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
233 def override_cbuild(self):
234 if self.makeconf.has_key("CBUILD"):
235 self.settings["CBUILD"]=self.makeconf["CBUILD"]
237 def override_chost(self):
238 if self.makeconf.has_key("CHOST"):
239 self.settings["CHOST"]=self.makeconf["CHOST"]
241 def override_cflags(self):
242 if self.makeconf.has_key("CFLAGS"):
243 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
245 def override_cxxflags(self):
246 if self.makeconf.has_key("CXXFLAGS"):
247 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
249 def override_ldflags(self):
250 if self.makeconf.has_key("LDFLAGS"):
251 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
253 def set_install_mask(self):
254 if self.settings.has_key("install_mask"):
255 if type(self.settings["install_mask"])!=types.StringType:
256 self.settings["install_mask"]=\
257 string.join(self.settings["install_mask"])
259 def set_spec_prefix(self):
260 self.settings["spec_prefix"]=self.settings["target"]
262 def set_target_profile(self):
263 self.settings["target_profile"]=self.settings["profile"]
265 def set_target_subpath(self):
266 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
267 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
268 self.settings["version_stamp"]
270 def set_source_subpath(self):
271 if type(self.settings["source_subpath"])!=types.StringType:
272 raise CatalystError,\
273 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
275 def set_pkgcache_path(self):
276 if self.settings.has_key("pkgcache_path"):
277 if type(self.settings["pkgcache_path"])!=types.StringType:
278 self.settings["pkgcache_path"]=\
279 normpath(string.join(self.settings["pkgcache_path"]))
281 self.settings["pkgcache_path"]=\
282 normpath(self.settings["storedir"]+"/packages/"+\
283 self.settings["target_subpath"]+"/")
285 def set_kerncache_path(self):
286 if self.settings.has_key("kerncache_path"):
287 if type(self.settings["kerncache_path"])!=types.StringType:
288 self.settings["kerncache_path"]=\
289 normpath(string.join(self.settings["kerncache_path"]))
291 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
292 "/kerncache/"+self.settings["target_subpath"]+"/")
294 def set_target_path(self):
295 self.settings["target_path"]=normpath(self.settings["storedir"]+\
296 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
297 if self.settings.has_key("AUTORESUME")\
298 and os.path.exists(self.settings["autoresume_path"]+\
299 "setup_target_path"):
301 "Resume point detected, skipping target path setup operation..."
303 """ First clean up any existing target stuff """
304 if os.path.isfile(self.settings["target_path"]):
305 cmd("rm -f "+self.settings["target_path"],\
306 "Could not remove existing file: "\
307 +self.settings["target_path"],env=self.env)
308 touch(self.settings["autoresume_path"]+"setup_target_path")
310 if not os.path.exists(self.settings["storedir"]+"/builds/"):
311 os.makedirs(self.settings["storedir"]+"/builds/")
313 def set_archscript(self):
314 if self.settings.has_key(self.settings["spec_prefix"]+"/archscript"):
315 # TODO: remove this warning/code with the next major version
316 print "\nWarning!!! "
317 print "\t"+self.settings["spec_prefix"]+"/archscript"+\
318 " is deprecated and no longer used.\n"
320 def set_runscript(self):
321 if self.settings.has_key(self.settings["spec_prefix"]+"/runscript"):
322 # TODO: remove this warning/code with the next major version
323 print "\nWarning!!! "
324 print "\t"+self.settings["spec_prefix"]+"/runscript"+\
325 " is deprecated and no longer used.\n"
327 def set_fsscript(self):
328 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
329 self.settings["fsscript"]=\
330 self.settings[self.settings["spec_prefix"]+"/fsscript"]
331 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
334 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
335 self.settings["rcadd"]=\
336 self.settings[self.settings["spec_prefix"]+"/rcadd"]
337 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
340 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
341 self.settings["rcdel"]=\
342 self.settings[self.settings["spec_prefix"]+"/rcdel"]
343 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
346 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
347 self.settings["cdtar"]=\
348 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
349 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
352 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
353 self.settings["iso"]=\
354 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
355 del self.settings[self.settings["spec_prefix"]+"/iso"]
357 def set_fstype(self):
358 if self.settings.has_key(self.settings["spec_prefix"]+"/cdfstype"):
359 # TODO: remove this warning/code with the next major version
360 print "\nWarning!!! "
361 print self.settings["spec_prefix"]+"/cdfstype"+\
362 " is deprecated and will be removed."
363 print "\tUse "+self.settings["spec_prefix"]+"/fstype"+" instead."
364 print "\tConverting to "+self.settings["spec_prefix"]+"/fstype"+\
366 print "\tContinuing ....\n"
367 self.settings["fstype"]=\
368 self.settings[self.settings["spec_prefix"]+"/cdfstype"]
369 del self.settings[self.settings["spec_prefix"]+"/cdfstype"]
371 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
372 self.settings["fstype"]=\
373 self.settings[self.settings["spec_prefix"]+"/fstype"]
374 del self.settings[self.settings["spec_prefix"]+"/fstype"]
376 if not self.settings.has_key("fstype"):
377 self.settings["fstype"]="normal"
378 for x in self.valid_values:
379 if x == self.settings["spec_prefix"]+"/fstype"\
380 or x == self.settings["spec_prefix"]+"/cdfstype":
381 print "\n"+self.settings["spec_prefix"]+\
382 "/fstype is being set to the default of \"normal\"\n"
385 if self.settings.has_key("fstype"):
386 self.valid_values.append("fsops")
387 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
388 self.settings["fsops"]=\
389 self.settings[self.settings["spec_prefix"]+"/fsops"]
390 del self.settings[self.settings["spec_prefix"]+"/fsops"]
392 def set_source_path(self):
393 if self.settings.has_key("SEEDCACHE")\
394 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
395 self.settings["source_subpath"]+"/")):
396 self.settings["source_path"]=normpath(self.settings["storedir"]+\
397 "/tmp/"+self.settings["source_subpath"]+"/")
399 self.settings["source_path"]=normpath(self.settings["storedir"]+\
400 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
401 if os.path.isfile(self.settings["source_path"]):
402 # XXX: Is this even necessary if the previous check passes?
403 if os.path.exists(self.settings["source_path"]):
404 self.settings["source_path_hash"]=\
405 generate_hash(self.settings["source_path"],\
406 hash_function=self.settings["hash_function"],\
408 print "Source path set to "+self.settings["source_path"]
409 if os.path.isdir(self.settings["source_path"]):
410 print "\tIf this is not desired, remove this directory or turn off seedcache in the options of catalyst.conf"
411 print "\tthe source path will then be "+\
412 normpath(self.settings["storedir"]+"/builds/"+\
413 self.settings["source_subpath"]+".tar.bz2\n")
415 def set_dest_path(self):
416 if self.settings.has_key("root_path"):
417 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
418 self.settings["root_path"])
420 self.settings["destpath"]=normpath(self.settings["chroot_path"])
422 def set_cleanables(self):
423 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
424 "/root/*","/usr/portage"]
426 def set_snapshot_path(self):
427 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
428 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
430 if os.path.exists(self.settings["snapshot_path"]):
431 self.settings["snapshot_path_hash"]=\
432 generate_hash(self.settings["snapshot_path"],\
433 hash_function=self.settings["hash_function"],verbose=False)
435 def set_snapcache_path(self):
436 if self.settings.has_key("SNAPCACHE"):
437 self.settings["snapshot_cache_path"]=\
438 normpath(self.settings["snapshot_cache"]+"/"+\
439 self.settings["snapshot"]+"/")
440 self.snapcache_lock=\
441 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
442 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
444 def set_chroot_path(self):
446 NOTE: the trailing slash is very important!
447 Things *will* break without it!
449 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
450 "/tmp/"+self.settings["target_subpath"]+"/")
451 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
453 def set_autoresume_path(self):
454 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
455 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
456 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
457 self.settings["version_stamp"]+"/")
458 if self.settings.has_key("AUTORESUME"):
459 print "The autoresume path is " + self.settings["autoresume_path"]
460 if not os.path.exists(self.settings["autoresume_path"]):
461 os.makedirs(self.settings["autoresume_path"],0755)
463 def set_controller_file(self):
464 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
465 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
468 def set_iso_volume_id(self):
469 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
470 self.settings["iso_volume_id"]=\
471 self.settings[self.settings["spec_prefix"]+"/volid"]
472 if len(self.settings["iso_volume_id"])>32:
473 raise CatalystError,\
474 "ISO volume ID must not exceed 32 characters."
476 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
478 def set_action_sequence(self):
479 """ Default action sequence for run method """
480 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
481 "config_profile_link","setup_confdir","portage_overlay",\
482 "base_dirs","bind","chroot_setup","setup_environment",\
483 "run_local","preclean","unbind","clean"]
484 # if self.settings.has_key("TARBALL") or \
485 # not self.settings.has_key("FETCH"):
486 if not self.settings.has_key("FETCH"):
487 self.settings["action_sequence"].append("capture")
488 self.settings["action_sequence"].append("clear_autoresume")
491 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
492 self.settings["use"]=\
493 self.settings[self.settings["spec_prefix"]+"/use"]
494 del self.settings[self.settings["spec_prefix"]+"/use"]
495 if self.settings.has_key("use"):
496 if type(self.settings["use"])==types.StringType:
497 self.settings["use"]=self.settings["use"].split()
498 self.settings["use"].append("bindist")
500 def set_stage_path(self):
501 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
503 def set_mounts(self):
506 def set_packages(self):
510 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
511 if type(self.settings[self.settings["spec_prefix"]+\
512 "/rm"])==types.StringType:
513 self.settings[self.settings["spec_prefix"]+"/rm"]=\
514 self.settings[self.settings["spec_prefix"]+"/rm"].split()
516 def set_linuxrc(self):
517 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
518 if type(self.settings[self.settings["spec_prefix"]+\
519 "/linuxrc"])==types.StringType:
520 self.settings["linuxrc"]=\
521 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
522 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
524 def set_portage_overlay(self):
525 if self.settings.has_key("portage_overlay"):
526 if type(self.settings["portage_overlay"])==types.StringType:
527 self.settings["portage_overlay"]=\
528 self.settings["portage_overlay"].split()
529 print "portage_overlay directories are set to: \""+\
530 string.join(self.settings["portage_overlay"])+"\""
532 def set_overlay(self):
533 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
534 if type(self.settings[self.settings["spec_prefix"]+\
535 "/overlay"])==types.StringType:
536 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
537 self.settings[self.settings["spec_prefix"]+\
540 def set_root_overlay(self):
541 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
542 if type(self.settings[self.settings["spec_prefix"]+\
543 "/root_overlay"])==types.StringType:
544 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
545 self.settings[self.settings["spec_prefix"]+\
546 "/root_overlay"].split()
548 def set_root_path(self):
549 """ ROOT= variable for emerges """
550 self.settings["root_path"]="/"
552 def set_valid_build_kernel_vars(self,addlargs):
553 if addlargs.has_key("boot/kernel"):
554 if type(addlargs["boot/kernel"])==types.StringType:
555 loopy=[addlargs["boot/kernel"]]
557 loopy=addlargs["boot/kernel"]
560 self.valid_values.append("boot/kernel/"+x+"/aliases")
561 self.valid_values.append("boot/kernel/"+x+"/config")
562 self.valid_values.append("boot/kernel/"+x+"/console")
563 self.valid_values.append("boot/kernel/"+x+"/extraversion")
564 self.valid_values.append("boot/kernel/"+x+"/gk_action")
565 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
566 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
567 self.valid_values.append("boot/kernel/"+x+"/machine_type")
568 self.valid_values.append("boot/kernel/"+x+"/sources")
569 self.valid_values.append("boot/kernel/"+x+"/softlevel")
570 self.valid_values.append("boot/kernel/"+x+"/use")
571 self.valid_values.append("boot/kernel/"+x+"/packages")
572 if addlargs.has_key("boot/kernel/"+x+"/packages"):
573 if type(addlargs["boot/kernel/"+x+\
574 "/packages"])==types.StringType:
575 addlargs["boot/kernel/"+x+"/packages"]=\
576 [addlargs["boot/kernel/"+x+"/packages"]]
577 # TODO: remove this warning/code with the next major version
578 self.valid_values.append("boot/kernel/"+x+"/postconf")
579 if addlargs.has_key("boot/kernel/"+x+"/postconf"):
580 print "boot/kernel/"+x+"/postconf is deprecated"
581 print "\tInternally moving these ebuilds to boot/kernel/"+\
583 print "\tPlease move them to boot/kernel/"+x+\
584 "/packages in your specfile"
585 if type(addlargs["boot/kernel/"+x+\
586 "/postconf"])==types.StringType:
587 loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
589 loop2=addlargs["boot/kernel/"+x+"/postconf"]
592 if not addlargs.has_key("boot/kernel/"+x+"/packages"):
593 addlargs["boot/kernel/"+x+"/packages"]=[y]
595 addlargs["boot/kernel/"+x+"/packages"].append(y)
597 def set_build_kernel_vars(self):
598 if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
599 # TODO: remove this warning/code with the next major version
600 print self.settings["spec_prefix"]+\
601 "/devmanager is deprecated and will be removed."
602 self.settings["devmanager"]=\
603 self.settings[self.settings["spec_prefix"]+"/devmanager"]
604 del self.settings[self.settings["spec_prefix"]+"/devmanager"]
606 if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
607 # TODO: remove this warning/code with the next major version
608 print self.settings["spec_prefix"]+\
609 "/splashtype is deprecated and will be removed."
610 self.settings["splashtype"]=\
611 self.settings[self.settings["spec_prefix"]+"/splashtype"]
612 del self.settings[self.settings["spec_prefix"]+"/splashtype"]
614 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
615 self.settings["gk_mainargs"]=\
616 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
617 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
619 def kill_chroot_pids(self):
620 print "Checking for processes running in chroot and killing them."
623 Force environment variables to be exported so script can see them
625 self.setup_environment()
627 if os.path.exists(self.settings["sharedir"]+\
628 "/targets/support/kill-chroot-pids.sh"):
629 cmd("/bin/bash "+self.settings["sharedir"]+\
630 "/targets/support/kill-chroot-pids.sh",\
631 "kill-chroot-pids script failed.",env=self.env)
633 def mount_safety_check(self):
634 mypath=self.settings["chroot_path"]
637 Check and verify that none of our paths in mypath are mounted. We don't
638 want to clean up with things still mounted, and this allows us to check.
639 Returns 1 on ok, 0 on "something is still mounted" case.
642 if not os.path.exists(mypath):
645 for x in self.mounts:
646 if not os.path.exists(mypath+x):
649 if ismount(mypath+x):
650 """ Something is still mounted "" """
652 print x+" is still mounted; performing auto-bind-umount...",
653 """ Try to umount stuff ourselves """
655 if ismount(mypath+x):
656 raise CatalystError, "Auto-unbind failed for "+x
658 print "Auto-unbind successful..."
659 except CatalystError:
660 raise CatalystError, "Unable to auto-unbind "+x
665 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
668 if self.settings.has_key("SEEDCACHE"):
669 if os.path.isdir(self.settings["source_path"]):
670 """ SEEDCACHE Is a directory, use rsync """
671 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
672 " "+self.settings["chroot_path"]
673 display_msg="\nStarting rsync from "+\
674 self.settings["source_path"]+"\nto "+\
675 self.settings["chroot_path"]+\
676 " (This may take some time) ...\n"
677 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
678 self.settings["chroot_path"]+" failed."
680 """ SEEDCACHE is a not a directory, try untar'ing """
681 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
682 display_msg="\nStarting tar extract from "+\
683 self.settings["source_path"]+"\nto "+\
684 self.settings["chroot_path"]+\
685 " (This may take some time) ...\n"
686 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
687 self.settings["chroot_path"]
688 error_msg="Tarball extraction of "+\
689 self.settings["source_path"]+" to "+\
690 self.settings["chroot_path"]+" failed."
692 """ No SEEDCACHE, use tar """
693 display_msg="\nStarting tar extract from "+\
694 self.settings["source_path"]+"\nto "+\
695 self.settings["chroot_path"]+\
696 " (This may take some time) ...\n"
697 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
698 self.settings["chroot_path"]
699 error_msg="Tarball extraction of "+self.settings["source_path"]+\
700 " to "+self.settings["chroot_path"]+" failed."
702 if self.settings.has_key("AUTORESUME"):
703 if os.path.isdir(self.settings["source_path"]) \
704 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
705 """ Autoresume is valid, SEEDCACHE is valid """
707 invalid_snapshot=False
709 elif os.path.isfile(self.settings["source_path"]) \
710 and self.settings["source_path_hash"]==clst_unpack_hash:
711 """ Autoresume is valid, tarball is valid """
713 invalid_snapshot=True
715 elif os.path.isdir(self.settings["source_path"]) \
716 and not os.path.exists(self.settings["autoresume_path"]+\
718 """ Autoresume is invalid, SEEDCACHE """
720 invalid_snapshot=False
722 elif os.path.isfile(self.settings["source_path"]) \
723 and self.settings["source_path_hash"]!=clst_unpack_hash:
724 """ Autoresume is invalid, tarball """
726 invalid_snapshot=True
728 """ No autoresume, SEEDCACHE """
729 if self.settings.has_key("SEEDCACHE"):
730 """ SEEDCACHE so let's run rsync and let it clean up """
731 if os.path.isdir(self.settings["source_path"]):
733 invalid_snapshot=False
734 elif os.path.isfile(self.settings["source_path"]):
735 """ Tarball so unpack and remove anything already there """
737 invalid_snapshot=True
738 """ No autoresume, no SEEDCACHE """
740 """ Tarball so unpack and remove anything already there """
741 if os.path.isfile(self.settings["source_path"]):
743 invalid_snapshot=True
744 elif os.path.isdir(self.settings["source_path"]):
745 """ We should never reach this, so something is very wrong """
746 raise CatalystError,\
747 "source path is a dir but seedcache is not enabled"
750 self.mount_safety_check()
753 if self.settings.has_key("AUTORESUME"):
754 print "No Valid Resume point detected, cleaning up..."
756 self.clear_autoresume()
759 if not os.path.exists(self.settings["chroot_path"]):
760 os.makedirs(self.settings["chroot_path"])
762 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
763 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
765 if self.settings.has_key("PKGCACHE"):
766 if not os.path.exists(self.settings["pkgcache_path"]):
767 os.makedirs(self.settings["pkgcache_path"],0755)
769 if self.settings.has_key("KERNCACHE"):
770 if not os.path.exists(self.settings["kerncache_path"]):
771 os.makedirs(self.settings["kerncache_path"],0755)
774 cmd(unpack_cmd,error_msg,env=self.env)
776 if self.settings.has_key("source_path_hash"):
777 myf=open(self.settings["autoresume_path"]+"unpack","w")
778 myf.write(self.settings["source_path_hash"])
781 touch(self.settings["autoresume_path"]+"unpack")
783 print "Resume point detected, skipping unpack operation..."
785 def unpack_snapshot(self):
787 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
790 if self.settings.has_key("SNAPCACHE"):
791 snapshot_cache_hash=\
792 read_from_clst(self.settings["snapshot_cache_path"]+\
794 destdir=self.settings["snapshot_cache_path"]
795 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
796 unpack_errmsg="Error unpacking snapshot"
797 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
798 self.settings["snapshot_cache_path"]+\
799 " (This can take a long time)..."
800 cleanup_errmsg="Error removing existing snapshot cache directory."
801 self.snapshot_lock_object=self.snapcache_lock
803 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
804 print "Valid snapshot cache, skipping unpack of portage tree..."
807 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
808 cleanup_errmsg="Error removing existing snapshot directory."
810 "Cleaning up existing portage tree (This can take a long time)..."
811 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
812 self.settings["chroot_path"]+"/usr"
813 unpack_errmsg="Error unpacking snapshot"
815 if self.settings.has_key("AUTORESUME") \
816 and os.path.exists(self.settings["chroot_path"]+\
818 and os.path.exists(self.settings["autoresume_path"]\
820 and self.settings["snapshot_path_hash"] == snapshot_hash:
822 "Valid Resume point detected, skipping unpack of portage tree..."
826 if self.settings.has_key("SNAPCACHE"):
827 self.snapshot_lock_object.write_lock()
828 if os.path.exists(destdir):
830 cleanup_cmd="rm -rf "+destdir
831 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
832 if not os.path.exists(destdir):
833 os.makedirs(destdir,0755)
835 print "Unpacking portage tree (This can take a long time) ..."
836 cmd(unpack_cmd,unpack_errmsg,env=self.env)
838 if self.settings.has_key("SNAPCACHE"):
839 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
840 myf.write(self.settings["snapshot_path_hash"])
843 print "Setting snapshot autoresume point"
844 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
845 myf.write(self.settings["snapshot_path_hash"])
848 if self.settings.has_key("SNAPCACHE"):
849 self.snapshot_lock_object.unlock()
851 def config_profile_link(self):
852 if self.settings.has_key("AUTORESUME") \
853 and os.path.exists(self.settings["autoresume_path"]+\
854 "config_profile_link"):
856 "Resume point detected, skipping config_profile_link operation..."
858 # TODO: zmedico and I discussed making this a directory and pushing
859 # in a parent file, as well as other user-specified configuration.
860 print "Configuring profile link..."
861 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
862 "Error zapping profile link",env=self.env)
863 cmd("ln -sf ../usr/portage/profiles/"+\
864 self.settings["target_profile"]+" "+\
865 self.settings["chroot_path"]+"/etc/make.profile",\
866 "Error creating profile link",env=self.env)
867 touch(self.settings["autoresume_path"]+"config_profile_link")
869 def setup_confdir(self):
870 if self.settings.has_key("AUTORESUME") \
871 and os.path.exists(self.settings["autoresume_path"]+\
873 print "Resume point detected, skipping setup_confdir operation..."
875 if self.settings.has_key("portage_confdir"):
876 print "Configuring /etc/portage..."
877 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
878 "Error zapping /etc/portage",env=self.env)
879 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
880 self.settings["chroot_path"]+"/etc/portage",\
881 "Error copying /etc/portage",env=self.env)
882 touch(self.settings["autoresume_path"]+"setup_confdir")
884 def portage_overlay(self):
885 """ We copy the contents of our overlays to /usr/local/portage """
886 if self.settings.has_key("portage_overlay"):
887 for x in self.settings["portage_overlay"]:
888 if os.path.exists(x):
889 print "Copying overlay dir " +x
890 cmd("mkdir -p "+self.settings["chroot_path"]+\
891 "/usr/local/portage",\
892 "Could not make portage_overlay dir",env=self.env)
893 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
894 "/usr/local/portage",\
895 "Could not copy portage_overlay",env=self.env)
897 def root_overlay(self):
898 """ Copy over the root_overlay """
899 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
900 for x in self.settings[self.settings["spec_prefix"]+\
902 if os.path.exists(x):
903 print "Copying root_overlay: "+x
904 cmd("rsync -a "+x+"/ "+\
905 self.settings["chroot_path"],\
906 self.settings["spec_prefix"]+"/root_overlay: "+x+\
907 " copy failed.",env=self.env)
913 for x in self.mounts:
914 if not os.path.exists(self.settings["chroot_path"]+x):
915 os.makedirs(self.settings["chroot_path"]+x,0755)
917 if not os.path.exists(self.mountmap[x]):
918 os.makedirs(self.mountmap[x],0755)
921 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
922 self.snapshot_lock_object.read_lock()
923 if os.uname()[0] == "FreeBSD":
925 retval=os.system("mount -t devfs none "+\
926 self.settings["chroot_path"]+x)
928 retval=os.system("mount_nullfs "+src+" "+\
929 self.settings["chroot_path"]+x)
931 retval=os.system("mount --bind "+src+" "+\
932 self.settings["chroot_path"]+x)
935 raise CatalystError,"Couldn't bind mount "+src
939 mypath=self.settings["chroot_path"]
940 myrevmounts=self.mounts[:]
941 myrevmounts.reverse()
942 """ Unmount in reverse order for nested bind-mounts """
943 for x in myrevmounts:
944 if not os.path.exists(mypath+x):
947 if not ismount(mypath+x):
950 retval=os.system("umount "+\
951 os.path.join(mypath,x.lstrip(os.path.sep)))
954 warn("First attempt to unmount: "+mypath+x+" failed.")
955 warn("Killing any pids still running in the chroot")
957 self.kill_chroot_pids()
959 retval2=os.system("umount "+mypath+x)
962 warn("Couldn't umount bind mount: "+mypath+x)
964 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
967 It's possible the snapshot lock object isn't created yet.
968 This is because mount safety check calls unbind before the
969 target is fully initialized
971 self.snapshot_lock_object.unlock()
976 if any bind mounts really failed, then we need to raise
977 this to potentially prevent an upcoming bash stage cleanup script
978 from wiping our bind mounts.
980 raise CatalystError,\
981 "Couldn't umount one or more bind-mounts; aborting for safety."
983 def chroot_setup(self):
984 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
986 self.override_cbuild()
987 self.override_chost()
988 self.override_cflags()
989 self.override_cxxflags()
990 self.override_ldflags()
991 if self.settings.has_key("AUTORESUME") \
992 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
993 print "Resume point detected, skipping chroot_setup operation..."
995 print "Setting up chroot..."
997 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
999 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1000 "Could not copy resolv.conf into place.",env=self.env)
1002 """ Copy over the envscript, if applicable """
1003 if self.settings.has_key("ENVSCRIPT"):
1004 if not os.path.exists(self.settings["ENVSCRIPT"]):
1005 raise CatalystError,\
1006 "Can't find envscript "+self.settings["ENVSCRIPT"]
1008 print "\nWarning!!!!"
1009 print "\tOverriding certain env variables may cause catastrophic failure."
1010 print "\tIf your build fails look here first as the possible problem."
1011 print "\tCatalyst assumes you know what you are doing when setting"
1012 print "\t\tthese variables."
1013 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1014 print "\tYou have been warned\n"
1016 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1017 self.settings["chroot_path"]+"/tmp/envscript",\
1018 "Could not copy envscript into place.",env=self.env)
1020 """ Setup metadata_overlay """
1021 if self.settings.has_key("METADATA_OVERLAY") \
1022 and not self.settings.has_key("portage_confdir"):
1023 if not os.path.exists(self.settings["chroot_path"]+\
1025 cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
1026 myf=open(self.settings["chroot_path"]+\
1027 "/etc/portage/modules","a")
1028 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
1033 Copy over /etc/hosts from the host in case there are any
1034 specialties in there
1036 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1037 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1038 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1039 "Could not backup /etc/hosts",env=self.env)
1040 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1041 "Could not copy /etc/hosts",env=self.env)
1043 """ Modify and write out make.conf (for the chroot) """
1044 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
1045 "Could not remove "+self.settings["chroot_path"]+\
1046 "/etc/make.conf",env=self.env)
1047 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1048 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1049 myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1050 if self.settings.has_key("CFLAGS"):
1051 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1052 if self.settings.has_key("CXXFLAGS"):
1053 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1055 myf.write('CXXFLAGS="${CFLAGS}"\n')
1057 if self.settings.has_key("LDFLAGS"):
1058 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1059 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1060 if self.settings.has_key("CBUILD"):
1061 myf.write("# This should not be changed unless you know exactly what you are doing. You\n# should probably be using a different stage, instead.\n")
1062 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1064 myf.write("# WARNING: Changing your CHOST is not something that should be done lightly.\n# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.\n")
1065 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1067 """ Figure out what our USE vars are for building """
1069 if self.settings.has_key("HOSTUSE"):
1070 myusevars.extend(self.settings["HOSTUSE"])
1072 if self.settings.has_key("use"):
1073 myusevars.extend(self.settings["use"])
1076 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1077 myusevars = sorted(set(myusevars))
1078 myf.write('USE="'+string.join(myusevars)+'"\n')
1079 if '-*' in myusevars:
1080 print "\nWarning!!! "
1081 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1082 "/use will cause portage to ignore"
1083 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1085 """ Setup the portage overlay """
1086 if self.settings.has_key("portage_overlay"):
1087 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1090 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1091 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1092 "Could not backup /etc/make.conf",env=self.env)
1093 touch(self.settings["autoresume_path"]+"chroot_setup")
1096 if self.settings.has_key("AUTORESUME") \
1097 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1098 print "Resume point detected, skipping fsscript operation..."
1100 if self.settings.has_key("fsscript"):
1101 if os.path.exists(self.settings["controller_file"]):
1102 cmd("/bin/bash "+self.settings["controller_file"]+\
1103 " fsscript","fsscript script failed.",env=self.env)
1104 touch(self.settings["autoresume_path"]+"fsscript")
1107 if self.settings.has_key("AUTORESUME") \
1108 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1109 print "Resume point detected, skipping rcupdate operation..."
1111 if os.path.exists(self.settings["controller_file"]):
1112 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1113 "rc-update script failed.",env=self.env)
1114 touch(self.settings["autoresume_path"]+"rcupdate")
1117 if self.settings.has_key("AUTORESUME") \
1118 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1119 print "Resume point detected, skipping clean operation..."
1121 for x in self.settings["cleanables"]:
1122 print "Cleaning chroot: "+x+"... "
1123 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1126 """ Put /etc/hosts back into place """
1127 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1128 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1129 self.settings["chroot_path"]+"/etc/hosts",\
1130 "Could not replace /etc/hosts",env=self.env)
1132 """ Remove our overlay """
1133 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1134 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1135 "Could not remove /usr/local/portage",env=self.env)
1136 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1138 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1140 """ Clean up old and obsoleted files in /etc """
1141 if os.path.exists(self.settings["stage_path"]+"/etc"):
1142 cmd("find "+self.settings["stage_path"]+\
1143 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1144 "Could not remove stray files in /etc",env=self.env)
1146 if os.path.exists(self.settings["controller_file"]):
1147 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1148 "clean script failed.",env=self.env)
1149 touch(self.settings["autoresume_path"]+"clean")
1152 if self.settings.has_key("AUTORESUME") \
1153 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1154 print "Resume point detected, skipping empty operation..."
1156 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1157 if type(self.settings[self.settings["spec_prefix"]+\
1158 "/empty"])==types.StringType:
1159 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1160 self.settings[self.settings["spec_prefix"]+\
1162 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1163 myemp=self.settings["destpath"]+x
1164 if not os.path.isdir(myemp):
1165 print x,"not a directory or does not exist, skipping 'empty' operation."
1167 print "Emptying directory",x
1169 stat the dir, delete the dir, recreate the dir and set
1170 the proper perms and ownership
1172 mystat=os.stat(myemp)
1173 shutil.rmtree(myemp)
1174 os.makedirs(myemp,0755)
1175 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1176 os.chmod(myemp,mystat[ST_MODE])
1177 touch(self.settings["autoresume_path"]+"empty")
1180 if self.settings.has_key("AUTORESUME") \
1181 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1182 print "Resume point detected, skipping remove operation..."
1184 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1185 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1187 We're going to shell out for all these cleaning
1188 operations, so we get easy glob handling.
1190 print "livecd: removing "+x
1191 os.system("rm -rf "+self.settings["chroot_path"]+x)
1193 if os.path.exists(self.settings["controller_file"]):
1194 cmd("/bin/bash "+self.settings["controller_file"]+\
1195 " clean","Clean failed.",env=self.env)
1196 touch(self.settings["autoresume_path"]+"remove")
1202 if self.settings.has_key("AUTORESUME") \
1203 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1204 print "Resume point detected, skipping preclean operation..."
1207 if os.path.exists(self.settings["controller_file"]):
1208 cmd("/bin/bash "+self.settings["controller_file"]+\
1209 " preclean","preclean script failed.",env=self.env)
1210 touch(self.settings["autoresume_path"]+"preclean")
1214 raise CatalystError, "Build failed, could not execute preclean"
1217 if self.settings.has_key("AUTORESUME") \
1218 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1219 print "Resume point detected, skipping capture operation..."
1221 """ Capture target in a tarball """
1222 mypath=self.settings["target_path"].split("/")
1223 """ Remove filename from path """
1224 mypath=string.join(mypath[:-1],"/")
1226 """ Now make sure path exists """
1227 if not os.path.exists(mypath):
1230 print "Creating stage tarball..."
1232 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1233 self.settings["stage_path"]+" .",\
1234 "Couldn't create stage tarball",env=self.env)
1236 self.gen_contents_file(self.settings["target_path"])
1237 self.gen_digest_file(self.settings["target_path"])
1239 touch(self.settings["autoresume_path"]+"capture")
1241 def run_local(self):
1242 if self.settings.has_key("AUTORESUME") \
1243 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1244 print "Resume point detected, skipping run_local operation..."
1247 if os.path.exists(self.settings["controller_file"]):
1248 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1249 "run script failed.",env=self.env)
1250 touch(self.settings["autoresume_path"]+"run_local")
1252 except CatalystError:
1254 raise CatalystError,"Stage build aborting due to error."
1256 def setup_environment(self):
1258 Modify the current environment. This is an ugly hack that should be
1259 fixed. We need this to use the os.system() call since we can't
1260 specify our own environ
1262 for x in self.settings.keys():
1263 """ Sanitize var names by doing "s|/-.|_|g" """
1264 varname="clst_"+string.replace(x,"/","_")
1265 varname=string.replace(varname,"-","_")
1266 varname=string.replace(varname,".","_")
1267 if type(self.settings[x])==types.StringType:
1268 """ Prefix to prevent namespace clashes """
1269 #os.environ[varname]=self.settings[x]
1270 self.env[varname]=self.settings[x]
1271 elif type(self.settings[x])==types.ListType:
1272 #os.environ[varname]=string.join(self.settings[x])
1273 self.env[varname]=string.join(self.settings[x])
1274 elif type(self.settings[x])==types.BooleanType:
1275 if self.settings[x]:
1276 self.env[varname]="true"
1278 self.env[varname]="false"
1279 if self.settings.has_key("makeopts"):
1280 self.env["MAKEOPTS"]=self.settings["makeopts"]
1283 self.chroot_lock.write_lock()
1285 """ Kill any pids in the chroot "" """
1286 self.kill_chroot_pids()
1288 """ Check for mounts right away and abort if we cannot unmount them """
1289 self.mount_safety_check()
1291 if self.settings.has_key("CLEAR_AUTORESUME"):
1292 self.clear_autoresume()
1293 if self.settings.has_key("PURGE"):
1296 for x in self.settings["action_sequence"]:
1297 print "--- Running action sequence: "+x
1300 apply(getattr(self,x))
1302 self.mount_safety_check()
1305 self.chroot_lock.unlock()
1308 if self.settings.has_key("AUTORESUME") \
1309 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1310 print "Resume point detected, skipping unmerge operation..."
1312 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1313 if type(self.settings[self.settings["spec_prefix"]+\
1314 "/unmerge"])==types.StringType:
1315 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1316 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1318 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1320 for x in range(0,len(myunmerge)):
1322 Surround args with quotes for passing to bash, allows
1323 things like "<" to remain intact
1325 myunmerge[x]="'"+myunmerge[x]+"'"
1326 myunmerge=string.join(myunmerge)
1328 """ Before cleaning, unmerge stuff """
1330 cmd("/bin/bash "+self.settings["controller_file"]+\
1331 " unmerge "+ myunmerge,"Unmerge script failed.",\
1333 print "unmerge shell script"
1334 except CatalystError:
1337 touch(self.settings["autoresume_path"]+"unmerge")
1339 def target_setup(self):
1340 if self.settings.has_key("AUTORESUME") \
1341 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1342 print "Resume point detected, skipping target_setup operation..."
1344 print "Setting up filesystems per filesystem type"
1345 cmd("/bin/bash "+self.settings["controller_file"]+\
1346 " target_image_setup "+ self.settings["target_path"],\
1347 "target_image_setup script failed.",env=self.env)
1348 touch(self.settings["autoresume_path"]+"target_setup")
1350 def setup_overlay(self):
1351 if self.settings.has_key("AUTORESUME") \
1352 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1353 print "Resume point detected, skipping setup_overlay operation..."
1355 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1356 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1357 if os.path.exists(x):
1358 cmd("rsync -a "+x+"/ "+\
1359 self.settings["target_path"],\
1360 self.settings["spec_prefix"]+"overlay: "+x+\
1361 " copy failed.",env=self.env)
1362 touch(self.settings["autoresume_path"]+"setup_overlay")
1364 def create_iso(self):
1365 if self.settings.has_key("AUTORESUME") \
1366 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1367 print "Resume point detected, skipping create_iso operation..."
1369 """ Create the ISO """
1370 if self.settings.has_key("iso"):
1371 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1372 self.settings["iso"],"ISO creation script failed.",\
1374 self.gen_contents_file(self.settings["iso"])
1375 self.gen_digest_file(self.settings["iso"])
1376 touch(self.settings["autoresume_path"]+"create_iso")
1378 print "WARNING: livecd/iso was not defined."
1379 print "An ISO Image will not be created."
1381 def build_packages(self):
1382 if self.settings.has_key("AUTORESUME") \
1383 and os.path.exists(self.settings["autoresume_path"]+\
1385 print "Resume point detected, skipping build_packages operation..."
1387 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1388 if self.settings.has_key("AUTORESUME") \
1389 and os.path.exists(self.settings["autoresume_path"]+\
1391 print "Resume point detected, skipping build_packages operation..."
1394 list_bashify(self.settings[self.settings["spec_prefix"]\
1397 cmd("/bin/bash "+self.settings["controller_file"]+\
1398 " build_packages "+mypack,\
1399 "Error in attempt to build packages",env=self.env)
1400 touch(self.settings["autoresume_path"]+"build_packages")
1401 except CatalystError:
1403 raise CatalystError,self.settings["spec_prefix"]+\
1404 "build aborting due to error."
1406 def build_kernel(self):
1407 if self.settings.has_key("AUTORESUME") \
1408 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1409 print "Resume point detected, skipping build_kernel operation..."
1411 if self.settings.has_key("boot/kernel"):
1413 mynames=self.settings["boot/kernel"]
1414 if type(mynames)==types.StringType:
1417 Execute the script that sets up the kernel build environment
1419 cmd("/bin/bash "+self.settings["controller_file"]+\
1420 " pre-kmerge ","Runscript pre-kmerge failed",\
1423 for kname in mynames:
1424 if self.settings.has_key("AUTORESUME") \
1425 and os.path.exists(self.settings["autoresume_path"]\
1426 +"build_kernel_"+kname):
1427 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1428 else: # TODO: make this not require a kernel config
1430 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1432 raise CatalystError,\
1433 "Can't find kernel config: "+\
1434 self.settings["boot/kernel/"+kname+\
1438 raise CatalystError,\
1439 "Required value boot/kernel/config not specified"
1442 cmd("cp "+self.settings["boot/kernel/"+kname+\
1444 self.settings["chroot_path"]+"/var/tmp/"+\
1446 "Couldn't copy kernel config: "+\
1447 self.settings["boot/kernel/"+kname+\
1448 "/config"],env=self.env)
1450 except CatalystError:
1454 If we need to pass special options to the bootloader
1455 for this kernel put them into the environment
1457 if self.settings.has_key("boot/kernel/"+kname+\
1459 myopts=self.settings["boot/kernel/"+kname+\
1462 if type(myopts) != types.StringType:
1463 myopts = string.join(myopts)
1464 self.env[kname+"_kernelopts"]=myopts
1467 self.env[kname+"_kernelopts"]=""
1469 if not self.settings.has_key("boot/kernel/"+kname+\
1471 self.settings["boot/kernel/"+kname+\
1474 self.env["clst_kextraversion"]=\
1475 self.settings["boot/kernel/"+kname+\
1478 if self.settings.has_key("boot/kernel/"+kname+\
1479 "/initramfs_overlay"):
1480 if os.path.exists(self.settings["boot/kernel/"+\
1481 kname+"/initramfs_overlay"]):
1482 print "Copying initramfs_overlay dir "+\
1483 self.settings["boot/kernel/"+kname+\
1484 "/initramfs_overlay"]
1487 self.settings["chroot_path"]+\
1488 "/tmp/initramfs_overlay/"+\
1489 self.settings["boot/kernel/"+kname+\
1490 "/initramfs_overlay"],env=self.env)
1492 cmd("cp -R "+self.settings["boot/kernel/"+\
1493 kname+"/initramfs_overlay"]+"/* "+\
1494 self.settings["chroot_path"]+\
1495 "/tmp/initramfs_overlay/"+\
1496 self.settings["boot/kernel/"+kname+\
1497 "/initramfs_overlay"],env=self.env)
1499 """ Execute the script that builds the kernel """
1500 cmd("/bin/bash "+self.settings["controller_file"]+\
1502 "Runscript kernel build failed",env=self.env)
1504 if self.settings.has_key("boot/kernel/"+kname+\
1505 "/initramfs_overlay"):
1506 if os.path.exists(self.settings["chroot_path"]+\
1507 "/tmp/initramfs_overlay/"):
1508 print "Cleaning up temporary overlay dir"
1509 cmd("rm -R "+self.settings["chroot_path"]+\
1510 "/tmp/initramfs_overlay/",env=self.env)
1512 touch(self.settings["autoresume_path"]+\
1513 "build_kernel_"+kname)
1516 Execute the script that cleans up the kernel build
1519 cmd("/bin/bash "+self.settings["controller_file"]+\
1521 "Runscript post-kmerge failed",env=self.env)
1523 touch(self.settings["autoresume_path"]+"build_kernel")
1525 except CatalystError:
1527 raise CatalystError,\
1528 "build aborting due to kernel build error."
1530 def bootloader(self):
1531 if self.settings.has_key("AUTORESUME") \
1532 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1533 print "Resume point detected, skipping bootloader operation..."
1536 cmd("/bin/bash "+self.settings["controller_file"]+\
1537 " bootloader " + self.settings["target_path"],\
1538 "Bootloader runscript failed.",env=self.env)
1539 touch(self.settings["autoresume_path"]+"bootloader")
1540 except CatalystError:
1542 raise CatalystError,"Runscript aborting due to error."
1544 def livecd_update(self):
1545 if self.settings.has_key("AUTORESUME") \
1546 and os.path.exists(self.settings["autoresume_path"]+\
1548 print "Resume point detected, skipping build_packages operation..."
1551 cmd("/bin/bash "+self.settings["controller_file"]+\
1552 " livecd-update","livecd-update failed.",env=self.env)
1553 touch(self.settings["autoresume_path"]+"livecd_update")
1555 except CatalystError:
1557 raise CatalystError,"build aborting due to livecd_update error."
1559 def clear_chroot(self):
1560 myemp=self.settings["chroot_path"]
1561 if os.path.isdir(myemp):
1562 print "Emptying directory",myemp
1564 stat the dir, delete the dir, recreate the dir and set
1565 the proper perms and ownership
1567 mystat=os.stat(myemp)
1568 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1569 """ There's no easy way to change flags recursively in python """
1570 if os.uname()[0] == "FreeBSD":
1571 os.system("chflags -R noschg "+myemp)
1572 shutil.rmtree(myemp)
1573 os.makedirs(myemp,0755)
1574 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1575 os.chmod(myemp,mystat[ST_MODE])
1577 def clear_packages(self):
1578 if self.settings.has_key("PKGCACHE"):
1579 print "purging the pkgcache ..."
1581 myemp=self.settings["pkgcache_path"]
1582 if os.path.isdir(myemp):
1583 print "Emptying directory",myemp
1585 stat the dir, delete the dir, recreate the dir and set
1586 the proper perms and ownership
1588 mystat=os.stat(myemp)
1589 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1590 shutil.rmtree(myemp)
1591 os.makedirs(myemp,0755)
1592 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1593 os.chmod(myemp,mystat[ST_MODE])
1595 def clear_kerncache(self):
1596 if self.settings.has_key("KERNCACHE"):
1597 print "purging the kerncache ..."
1599 myemp=self.settings["kerncache_path"]
1600 if os.path.isdir(myemp):
1601 print "Emptying directory",myemp
1603 stat the dir, delete the dir, recreate the dir and set
1604 the proper perms and ownership
1606 mystat=os.stat(myemp)
1607 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1608 shutil.rmtree(myemp)
1609 os.makedirs(myemp,0755)
1610 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1611 os.chmod(myemp,mystat[ST_MODE])
1613 def clear_autoresume(self):
1614 """ Clean resume points since they are no longer needed """
1615 if self.settings.has_key("AUTORESUME"):
1616 print "Removing AutoResume Points: ..."
1617 myemp=self.settings["autoresume_path"]
1618 if os.path.isdir(myemp):
1619 if self.settings.has_key("AUTORESUME"):
1620 print "Emptying directory",myemp
1622 stat the dir, delete the dir, recreate the dir and set
1623 the proper perms and ownership
1625 mystat=os.stat(myemp)
1626 if os.uname()[0] == "FreeBSD":
1627 cmd("chflags -R noschg "+myemp,\
1628 "Could not remove immutable flag for file "\
1630 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1631 shutil.rmtree(myemp)
1632 os.makedirs(myemp,0755)
1633 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1634 os.chmod(myemp,mystat[ST_MODE])
1636 def gen_contents_file(self,file):
1637 if os.path.exists(file+".CONTENTS"):
1638 os.remove(file+".CONTENTS")
1639 if self.settings.has_key("contents"):
1640 if os.path.exists(file):
1641 myf=open(file+".CONTENTS","w")
1643 for i in self.settings["contents"].split():
1648 contents=generate_contents(file,contents_function=j,\
1649 verbose=self.settings.has_key("VERBOSE"))
1654 def gen_digest_file(self,file):
1655 if os.path.exists(file+".DIGESTS"):
1656 os.remove(file+".DIGESTS")
1657 if self.settings.has_key("digests"):
1658 if os.path.exists(file):
1659 myf=open(file+".DIGESTS","w")
1661 for i in self.settings["digests"].split():
1665 for f in [file, file+'.CONTENTS']:
1666 if os.path.exists(f):
1668 hash=generate_hash(f,hash_function=j,verbose=\
1669 self.settings.has_key("VERBOSE"))
1674 countdown(10,"Purging Caches ...")
1675 if self.settings.has_key("PURGE"):
1676 print "clearing autoresume ..."
1677 self.clear_autoresume()
1679 print "clearing chroot ..."
1682 print "clearing package cache ..."
1683 self.clear_packages()
1685 print "clearing kerncache ..."
1686 self.clear_kerncache()
1688 # vim: ts=4 sw=4 sta et sts=4 ai