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 *
13 class generic_stage_target(generic_target):
15 def __init__(self,myspec,addlargs):
16 self.required_values.extend(["version_stamp","target","subarch",\
17 "rel_type","profile","snapshot","source_subpath"])
19 self.valid_values.extend(["version_stamp","target","subarch",\
20 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
21 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
22 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
24 self.set_valid_build_kernel_vars(addlargs)
25 generic_target.__init__(self,myspec,addlargs)
28 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
29 work better with vapier's CBUILD stuff. I've removed the "monolithic"
30 machinemap from this file and split up its contents amongst the
31 various arch/foo.py files.
33 When register() is called on each module in the arch/ dir, it now
34 returns a tuple instead of acting on the subarchmap dict that is
35 passed to it. The tuple contains the values that were previously
36 added to subarchmap as well as a new list of CHOSTs that go along
37 with that arch. This allows us to build machinemap on the fly based
38 on the keys in subarchmap and the values of the 2nd list returned
41 Also, after talking with vapier. I have a slightly better idea of what
42 certain variables are used for and what they should be set to. Neither
43 'buildarch' or 'hostarch' are used directly, so their value doesn't
44 really matter. They are just compared to determine if we are
45 cross-compiling. Because of this, they are just set to the name of the
46 module in arch/ that the subarch is part of to make things simpler.
47 The entire build process is still based off of 'subarch' like it was
54 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
55 "/arch/") if x.endswith(".py")]:
57 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
59 This next line loads the plugin as a module and assigns it to
62 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
63 ".py",(".py","r",imp.PY_SOURCE))
65 This next line registers all the subarches supported in the
68 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
69 self.subarchmap.update(tmpsubarchmap)
70 for machine in tmpmachinemap:
71 machinemap[machine] = x
72 for subarch in tmpsubarchmap:
73 machinemap[subarch] = x
77 This message should probably change a bit, since everything in
78 the dir should load just fine. If it doesn't, it's probably a
79 syntax error in the module
81 msg("Can't find/load "+x+".py plugin in "+\
82 self.settings["sharedir"]+"/arch/")
84 if self.settings.has_key("chost"):
85 hostmachine = self.settings["chost"].split("-")[0]
86 if not machinemap.has_key(hostmachine):
87 raise CatalystError, "Unknown host machine type "+hostmachine
88 self.settings["hostarch"]=machinemap[hostmachine]
90 hostmachine = self.settings["subarch"]
91 if machinemap.has_key(hostmachine):
92 hostmachine = machinemap[hostmachine]
93 self.settings["hostarch"]=hostmachine
94 if self.settings.has_key("cbuild"):
95 buildmachine = self.settings["cbuild"].split("-")[0]
97 buildmachine = os.uname()[4]
98 if not machinemap.has_key(buildmachine):
99 raise CatalystError, "Unknown build machine type "+buildmachine
100 self.settings["buildarch"]=machinemap[buildmachine]
101 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
102 self.settings["buildarch"])
104 """ Call arch constructor, pass our settings """
106 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
108 print "Invalid subarch: "+self.settings["subarch"]
109 print "Choose one of the following:",
110 for x in self.subarchmap:
115 print "Using target:",self.settings["target"]
116 """ Print a nice informational message """
117 if self.settings["buildarch"]==self.settings["hostarch"]:
118 print "Building natively for",self.settings["hostarch"]
119 elif self.settings["crosscompile"]:
120 print "Cross-compiling on",self.settings["buildarch"],\
121 "for different machine type",self.settings["hostarch"]
123 print "Building on",self.settings["buildarch"],\
124 "for alternate personality type",self.settings["hostarch"]
126 """ This must be set first as other set_ options depend on this """
127 self.set_spec_prefix()
129 """ Define all of our core variables """
130 self.set_target_profile()
131 self.set_target_subpath()
132 self.set_source_subpath()
135 self.set_snapshot_path()
137 self.set_source_path()
138 self.set_snapcache_path()
139 self.set_chroot_path()
140 self.set_autoresume_path()
142 self.set_stage_path()
143 self.set_target_path()
145 self.set_controller_file()
146 self.set_action_sequence()
148 self.set_cleanables()
149 self.set_iso_volume_id()
150 self.set_build_kernel_vars()
152 self.set_install_mask()
162 self.set_busybox_config()
164 self.set_portage_overlay()
165 self.set_root_overlay()
168 This next line checks to make sure that the specified variables exist
172 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
174 """ If we are using portage_confdir, check that as well. """
175 if self.settings.has_key("portage_confdir"):
176 file_locate(self.settings,["portage_confdir"],expand=0)
178 """ Setup our mount points """
179 if self.settings.has_key("SNAPCACHE"):
180 self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
181 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
182 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
183 "/usr/portage/distfiles":self.settings["distdir"]}
185 self.mounts=["/proc","/dev","/usr/portage/distfiles"]
186 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
187 "/usr/portage/distfiles":self.settings["distdir"]}
188 if os.uname()[0] == "Linux":
189 self.mounts.append("/dev/pts")
194 Configure any user specified options (either in catalyst.conf or on
197 if self.settings.has_key("PKGCACHE"):
198 self.set_pkgcache_path()
199 print "Location of the package cache is "+\
200 self.settings["pkgcache_path"]
201 self.mounts.append("/usr/portage/packages")
202 self.mountmap["/usr/portage/packages"]=\
203 self.settings["pkgcache_path"]
205 if self.settings.has_key("KERNCACHE"):
206 self.set_kerncache_path()
207 print "Location of the kerncache is "+\
208 self.settings["kerncache_path"]
209 self.mounts.append("/tmp/kerncache")
210 self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
212 if self.settings.has_key("CCACHE"):
213 if os.environ.has_key("CCACHE_DIR"):
214 ccdir=os.environ["CCACHE_DIR"]
215 del os.environ["CCACHE_DIR"]
217 ccdir="/root/.ccache"
218 if not os.path.isdir(ccdir):
219 raise CatalystError,\
220 "Compiler cache support can't be enabled (can't find "+\
222 self.mounts.append("/var/tmp/ccache")
223 self.mountmap["/var/tmp/ccache"]=ccdir
224 """ for the chroot: """
225 self.env["CCACHE_DIR"]="/var/tmp/ccache"
227 if self.settings.has_key("ICECREAM"):
228 self.mounts.append("/var/cache/icecream")
229 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
230 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
232 def override_cbuild(self):
233 if self.makeconf.has_key("CBUILD"):
234 self.settings["CBUILD"]=self.makeconf["CBUILD"]
236 def override_chost(self):
237 if self.makeconf.has_key("CHOST"):
238 self.settings["CHOST"]=self.makeconf["CHOST"]
240 def override_cflags(self):
241 if self.makeconf.has_key("CFLAGS"):
242 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
244 def override_cxxflags(self):
245 if self.makeconf.has_key("CXXFLAGS"):
246 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
248 def override_ldflags(self):
249 if self.makeconf.has_key("LDFLAGS"):
250 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
252 def set_install_mask(self):
253 if self.settings.has_key("install_mask"):
254 if type(self.settings["install_mask"])!=types.StringType:
255 self.settings["install_mask"]=\
256 string.join(self.settings["install_mask"])
258 def set_spec_prefix(self):
259 self.settings["spec_prefix"]=self.settings["target"]
261 def set_target_profile(self):
262 self.settings["target_profile"]=self.settings["profile"]
264 def set_target_subpath(self):
265 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
266 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
267 self.settings["version_stamp"]
269 def set_source_subpath(self):
270 if type(self.settings["source_subpath"])!=types.StringType:
271 raise CatalystError,\
272 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
274 def set_pkgcache_path(self):
275 if self.settings.has_key("pkgcache_path"):
276 if type(self.settings["pkgcache_path"])!=types.StringType:
277 self.settings["pkgcache_path"]=\
278 normpath(string.join(self.settings["pkgcache_path"]))
280 self.settings["pkgcache_path"]=\
281 normpath(self.settings["storedir"]+"/packages/"+\
282 self.settings["target_subpath"]+"/")
284 def set_kerncache_path(self):
285 if self.settings.has_key("kerncache_path"):
286 if type(self.settings["kerncache_path"])!=types.StringType:
287 self.settings["kerncache_path"]=\
288 normpath(string.join(self.settings["kerncache_path"]))
290 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
291 "/kerncache/"+self.settings["target_subpath"]+"/")
293 def set_target_path(self):
294 self.settings["target_path"]=normpath(self.settings["storedir"]+\
295 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
296 if self.settings.has_key("AUTORESUME")\
297 and os.path.exists(self.settings["autoresume_path"]+\
298 "setup_target_path"):
300 "Resume point detected, skipping target path setup operation..."
302 """ First clean up any existing target stuff """
303 if os.path.isfile(self.settings["target_path"]):
304 cmd("rm -f "+self.settings["target_path"],\
305 "Could not remove existing file: "\
306 +self.settings["target_path"],env=self.env)
307 touch(self.settings["autoresume_path"]+"setup_target_path")
309 if not os.path.exists(self.settings["storedir"]+"/builds/"):
310 os.makedirs(self.settings["storedir"]+"/builds/")
312 def set_fsscript(self):
313 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
314 self.settings["fsscript"]=\
315 self.settings[self.settings["spec_prefix"]+"/fsscript"]
316 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
319 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
320 self.settings["rcadd"]=\
321 self.settings[self.settings["spec_prefix"]+"/rcadd"]
322 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
325 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
326 self.settings["rcdel"]=\
327 self.settings[self.settings["spec_prefix"]+"/rcdel"]
328 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
331 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
332 self.settings["cdtar"]=\
333 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
334 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
337 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
338 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
339 self.settings["iso"]=\
340 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
342 # This automatically prepends the build dir to the ISO output path
343 # if it doesn't start with a /
344 self.settings["iso"] = normpath(self.settings["storedir"] + \
345 "/builds/" + self.settings["rel_type"] + "/" + \
346 self.settings[self.settings["spec_prefix"]+"/iso"])
347 del self.settings[self.settings["spec_prefix"]+"/iso"]
349 def set_fstype(self):
350 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
351 self.settings["fstype"]=\
352 self.settings[self.settings["spec_prefix"]+"/fstype"]
353 del self.settings[self.settings["spec_prefix"]+"/fstype"]
355 if not self.settings.has_key("fstype"):
356 self.settings["fstype"]="normal"
357 for x in self.valid_values:
358 if x == self.settings["spec_prefix"]+"/fstype":
359 print "\n"+self.settings["spec_prefix"]+\
360 "/fstype is being set to the default of \"normal\"\n"
363 if self.settings.has_key("fstype"):
364 self.valid_values.append("fsops")
365 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
366 self.settings["fsops"]=\
367 self.settings[self.settings["spec_prefix"]+"/fsops"]
368 del self.settings[self.settings["spec_prefix"]+"/fsops"]
370 def set_source_path(self):
371 if self.settings.has_key("SEEDCACHE")\
372 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
373 self.settings["source_subpath"]+"/")):
374 self.settings["source_path"]=normpath(self.settings["storedir"]+\
375 "/tmp/"+self.settings["source_subpath"]+"/")
377 self.settings["source_path"]=normpath(self.settings["storedir"]+\
378 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
379 if os.path.isfile(self.settings["source_path"]):
380 # XXX: Is this even necessary if the previous check passes?
381 if os.path.exists(self.settings["source_path"]):
382 self.settings["source_path_hash"]=\
383 generate_hash(self.settings["source_path"],\
384 hash_function=self.settings["hash_function"],\
386 print "Source path set to "+self.settings["source_path"]
387 if os.path.isdir(self.settings["source_path"]):
388 print "\tIf this is not desired, remove this directory or turn off"
389 print "\tseedcache in the options of catalyst.conf the source path"
390 print "\twill then be "+\
391 normpath(self.settings["storedir"]+"/builds/"+\
392 self.settings["source_subpath"]+".tar.bz2\n")
394 def set_dest_path(self):
395 if self.settings.has_key("root_path"):
396 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
397 self.settings["root_path"])
399 self.settings["destpath"]=normpath(self.settings["chroot_path"])
401 def set_cleanables(self):
402 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
403 "/root/*","/usr/portage"]
405 def set_snapshot_path(self):
406 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
407 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
409 if os.path.exists(self.settings["snapshot_path"]):
410 self.settings["snapshot_path_hash"]=\
411 generate_hash(self.settings["snapshot_path"],\
412 hash_function=self.settings["hash_function"],verbose=False)
414 def set_snapcache_path(self):
415 if self.settings.has_key("SNAPCACHE"):
416 self.settings["snapshot_cache_path"]=\
417 normpath(self.settings["snapshot_cache"]+"/"+\
418 self.settings["snapshot"]+"/")
419 self.snapcache_lock=\
420 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
421 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
423 def set_chroot_path(self):
425 NOTE: the trailing slash is very important!
426 Things *will* break without it!
428 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
429 "/tmp/"+self.settings["target_subpath"]+"/")
430 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
432 def set_autoresume_path(self):
433 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
434 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
435 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
436 self.settings["version_stamp"]+"/")
437 if self.settings.has_key("AUTORESUME"):
438 print "The autoresume path is " + self.settings["autoresume_path"]
439 if not os.path.exists(self.settings["autoresume_path"]):
440 os.makedirs(self.settings["autoresume_path"],0755)
442 def set_controller_file(self):
443 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
444 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
447 def set_iso_volume_id(self):
448 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
449 self.settings["iso_volume_id"]=\
450 self.settings[self.settings["spec_prefix"]+"/volid"]
451 if len(self.settings["iso_volume_id"])>32:
452 raise CatalystError,\
453 "ISO volume ID must not exceed 32 characters."
455 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
457 def set_action_sequence(self):
458 """ Default action sequence for run method """
459 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
460 "config_profile_link","setup_confdir","portage_overlay",\
461 "base_dirs","bind","chroot_setup","setup_environment",\
462 "run_local","preclean","unbind","clean"]
463 # if self.settings.has_key("TARBALL") or \
464 # not self.settings.has_key("FETCH"):
465 if not self.settings.has_key("FETCH"):
466 self.settings["action_sequence"].append("capture")
467 self.settings["action_sequence"].append("clear_autoresume")
470 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
471 self.settings["use"]=\
472 self.settings[self.settings["spec_prefix"]+"/use"]
473 del self.settings[self.settings["spec_prefix"]+"/use"]
474 if self.settings.has_key("use"):
475 if type(self.settings["use"])==types.StringType:
476 self.settings["use"]=self.settings["use"].split()
477 self.settings["use"].append("bindist")
479 def set_stage_path(self):
480 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
482 def set_mounts(self):
485 def set_packages(self):
489 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
490 if type(self.settings[self.settings["spec_prefix"]+\
491 "/rm"])==types.StringType:
492 self.settings[self.settings["spec_prefix"]+"/rm"]=\
493 self.settings[self.settings["spec_prefix"]+"/rm"].split()
495 def set_linuxrc(self):
496 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
497 if type(self.settings[self.settings["spec_prefix"]+\
498 "/linuxrc"])==types.StringType:
499 self.settings["linuxrc"]=\
500 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
501 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
503 def set_busybox_config(self):
504 if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
505 if type(self.settings[self.settings["spec_prefix"]+\
506 "/busybox_config"])==types.StringType:
507 self.settings["busybox_config"]=\
508 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
509 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
511 def set_portage_overlay(self):
512 if self.settings.has_key("portage_overlay"):
513 if type(self.settings["portage_overlay"])==types.StringType:
514 self.settings["portage_overlay"]=\
515 self.settings["portage_overlay"].split()
516 print "portage_overlay directories are set to: \""+\
517 string.join(self.settings["portage_overlay"])+"\""
519 def set_overlay(self):
520 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
521 if type(self.settings[self.settings["spec_prefix"]+\
522 "/overlay"])==types.StringType:
523 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
524 self.settings[self.settings["spec_prefix"]+\
527 def set_root_overlay(self):
528 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
529 if type(self.settings[self.settings["spec_prefix"]+\
530 "/root_overlay"])==types.StringType:
531 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
532 self.settings[self.settings["spec_prefix"]+\
533 "/root_overlay"].split()
535 def set_root_path(self):
536 """ ROOT= variable for emerges """
537 self.settings["root_path"]="/"
539 def set_valid_build_kernel_vars(self,addlargs):
540 if addlargs.has_key("boot/kernel"):
541 if type(addlargs["boot/kernel"])==types.StringType:
542 loopy=[addlargs["boot/kernel"]]
544 loopy=addlargs["boot/kernel"]
547 self.valid_values.append("boot/kernel/"+x+"/aliases")
548 self.valid_values.append("boot/kernel/"+x+"/config")
549 self.valid_values.append("boot/kernel/"+x+"/console")
550 self.valid_values.append("boot/kernel/"+x+"/extraversion")
551 self.valid_values.append("boot/kernel/"+x+"/gk_action")
552 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
553 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
554 self.valid_values.append("boot/kernel/"+x+"/machine_type")
555 self.valid_values.append("boot/kernel/"+x+"/sources")
556 self.valid_values.append("boot/kernel/"+x+"/softlevel")
557 self.valid_values.append("boot/kernel/"+x+"/use")
558 self.valid_values.append("boot/kernel/"+x+"/packages")
559 if addlargs.has_key("boot/kernel/"+x+"/packages"):
560 if type(addlargs["boot/kernel/"+x+\
561 "/packages"])==types.StringType:
562 addlargs["boot/kernel/"+x+"/packages"]=\
563 [addlargs["boot/kernel/"+x+"/packages"]]
565 def set_build_kernel_vars(self):
566 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
567 self.settings["gk_mainargs"]=\
568 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
569 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
571 def kill_chroot_pids(self):
572 print "Checking for processes running in chroot and killing them."
575 Force environment variables to be exported so script can see them
577 self.setup_environment()
579 if os.path.exists(self.settings["sharedir"]+\
580 "/targets/support/kill-chroot-pids.sh"):
581 cmd("/bin/bash "+self.settings["sharedir"]+\
582 "/targets/support/kill-chroot-pids.sh",\
583 "kill-chroot-pids script failed.",env=self.env)
585 def mount_safety_check(self):
586 mypath=self.settings["chroot_path"]
589 Check and verify that none of our paths in mypath are mounted. We don't
590 want to clean up with things still mounted, and this allows us to check.
591 Returns 1 on ok, 0 on "something is still mounted" case.
594 if not os.path.exists(mypath):
597 for x in self.mounts:
598 if not os.path.exists(mypath+x):
601 if ismount(mypath+x):
602 """ Something is still mounted "" """
604 print x+" is still mounted; performing auto-bind-umount...",
605 """ Try to umount stuff ourselves """
607 if ismount(mypath+x):
608 raise CatalystError, "Auto-unbind failed for "+x
610 print "Auto-unbind successful..."
611 except CatalystError:
612 raise CatalystError, "Unable to auto-unbind "+x
617 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
620 if self.settings.has_key("SEEDCACHE"):
621 if os.path.isdir(self.settings["source_path"]):
622 """ SEEDCACHE Is a directory, use rsync """
623 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
624 " "+self.settings["chroot_path"]
625 display_msg="\nStarting rsync from "+\
626 self.settings["source_path"]+"\nto "+\
627 self.settings["chroot_path"]+\
628 " (This may take some time) ...\n"
629 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
630 self.settings["chroot_path"]+" failed."
632 """ SEEDCACHE is a not a directory, try untar'ing """
633 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
634 display_msg="\nStarting tar extract from "+\
635 self.settings["source_path"]+"\nto "+\
636 self.settings["chroot_path"]+\
637 " (This may take some time) ...\n"
638 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
639 self.settings["chroot_path"]
640 error_msg="Tarball extraction of "+\
641 self.settings["source_path"]+" to "+\
642 self.settings["chroot_path"]+" failed."
644 """ No SEEDCACHE, use tar """
645 display_msg="\nStarting tar extract from "+\
646 self.settings["source_path"]+"\nto "+\
647 self.settings["chroot_path"]+\
648 " (This may take some time) ...\n"
649 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
650 self.settings["chroot_path"]
651 error_msg="Tarball extraction of "+self.settings["source_path"]+\
652 " to "+self.settings["chroot_path"]+" failed."
654 if self.settings.has_key("AUTORESUME"):
655 if os.path.isdir(self.settings["source_path"]) \
656 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
657 """ Autoresume is valid, SEEDCACHE is valid """
659 invalid_snapshot=False
661 elif os.path.isfile(self.settings["source_path"]) \
662 and self.settings["source_path_hash"]==clst_unpack_hash:
663 """ Autoresume is valid, tarball is valid """
665 invalid_snapshot=True
667 elif os.path.isdir(self.settings["source_path"]) \
668 and not os.path.exists(self.settings["autoresume_path"]+\
670 """ Autoresume is invalid, SEEDCACHE """
672 invalid_snapshot=False
674 elif os.path.isfile(self.settings["source_path"]) \
675 and self.settings["source_path_hash"]!=clst_unpack_hash:
676 """ Autoresume is invalid, tarball """
678 invalid_snapshot=True
680 """ No autoresume, SEEDCACHE """
681 if self.settings.has_key("SEEDCACHE"):
682 """ SEEDCACHE so let's run rsync and let it clean up """
683 if os.path.isdir(self.settings["source_path"]):
685 invalid_snapshot=False
686 elif os.path.isfile(self.settings["source_path"]):
687 """ Tarball so unpack and remove anything already there """
689 invalid_snapshot=True
690 """ No autoresume, no SEEDCACHE """
692 """ Tarball so unpack and remove anything already there """
693 if os.path.isfile(self.settings["source_path"]):
695 invalid_snapshot=True
696 elif os.path.isdir(self.settings["source_path"]):
697 """ We should never reach this, so something is very wrong """
698 raise CatalystError,\
699 "source path is a dir but seedcache is not enabled"
702 self.mount_safety_check()
705 if self.settings.has_key("AUTORESUME"):
706 print "No Valid Resume point detected, cleaning up..."
708 self.clear_autoresume()
711 if not os.path.exists(self.settings["chroot_path"]):
712 os.makedirs(self.settings["chroot_path"])
714 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
715 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
717 if self.settings.has_key("PKGCACHE"):
718 if not os.path.exists(self.settings["pkgcache_path"]):
719 os.makedirs(self.settings["pkgcache_path"],0755)
721 if self.settings.has_key("KERNCACHE"):
722 if not os.path.exists(self.settings["kerncache_path"]):
723 os.makedirs(self.settings["kerncache_path"],0755)
726 cmd(unpack_cmd,error_msg,env=self.env)
728 if self.settings.has_key("source_path_hash"):
729 myf=open(self.settings["autoresume_path"]+"unpack","w")
730 myf.write(self.settings["source_path_hash"])
733 touch(self.settings["autoresume_path"]+"unpack")
735 print "Resume point detected, skipping unpack operation..."
737 def unpack_snapshot(self):
739 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
742 if self.settings.has_key("SNAPCACHE"):
743 snapshot_cache_hash=\
744 read_from_clst(self.settings["snapshot_cache_path"]+\
746 destdir=self.settings["snapshot_cache_path"]
747 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
748 unpack_errmsg="Error unpacking snapshot"
749 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
750 self.settings["snapshot_cache_path"]+\
751 " (This can take a long time)..."
752 cleanup_errmsg="Error removing existing snapshot cache directory."
753 self.snapshot_lock_object=self.snapcache_lock
755 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
756 print "Valid snapshot cache, skipping unpack of portage tree..."
759 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
760 cleanup_errmsg="Error removing existing snapshot directory."
762 "Cleaning up existing portage tree (This can take a long time)..."
763 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
764 self.settings["chroot_path"]+"/usr"
765 unpack_errmsg="Error unpacking snapshot"
767 if self.settings.has_key("AUTORESUME") \
768 and os.path.exists(self.settings["chroot_path"]+\
770 and os.path.exists(self.settings["autoresume_path"]\
772 and self.settings["snapshot_path_hash"] == snapshot_hash:
774 "Valid Resume point detected, skipping unpack of portage tree..."
778 if self.settings.has_key("SNAPCACHE"):
779 self.snapshot_lock_object.write_lock()
780 if os.path.exists(destdir):
782 cleanup_cmd="rm -rf "+destdir
783 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
784 if not os.path.exists(destdir):
785 os.makedirs(destdir,0755)
787 print "Unpacking portage tree (This can take a long time) ..."
788 cmd(unpack_cmd,unpack_errmsg,env=self.env)
790 if self.settings.has_key("SNAPCACHE"):
791 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
792 myf.write(self.settings["snapshot_path_hash"])
795 print "Setting snapshot autoresume point"
796 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
797 myf.write(self.settings["snapshot_path_hash"])
800 if self.settings.has_key("SNAPCACHE"):
801 self.snapshot_lock_object.unlock()
803 def config_profile_link(self):
804 if self.settings.has_key("AUTORESUME") \
805 and os.path.exists(self.settings["autoresume_path"]+\
806 "config_profile_link"):
808 "Resume point detected, skipping config_profile_link operation..."
810 # TODO: zmedico and I discussed making this a directory and pushing
811 # in a parent file, as well as other user-specified configuration.
812 print "Configuring profile link..."
813 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
814 "Error zapping profile link",env=self.env)
815 cmd("ln -sf ../usr/portage/profiles/"+\
816 self.settings["target_profile"]+" "+\
817 self.settings["chroot_path"]+"/etc/make.profile",\
818 "Error creating profile link",env=self.env)
819 touch(self.settings["autoresume_path"]+"config_profile_link")
821 def setup_confdir(self):
822 if self.settings.has_key("AUTORESUME") \
823 and os.path.exists(self.settings["autoresume_path"]+\
825 print "Resume point detected, skipping setup_confdir operation..."
827 if self.settings.has_key("portage_confdir"):
828 print "Configuring /etc/portage..."
829 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
830 "Error zapping /etc/portage",env=self.env)
831 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
832 self.settings["chroot_path"]+"/etc/portage",\
833 "Error copying /etc/portage",env=self.env)
834 touch(self.settings["autoresume_path"]+"setup_confdir")
836 def portage_overlay(self):
837 """ We copy the contents of our overlays to /usr/local/portage """
838 if self.settings.has_key("portage_overlay"):
839 for x in self.settings["portage_overlay"]:
840 if os.path.exists(x):
841 print "Copying overlay dir " +x
842 cmd("mkdir -p "+self.settings["chroot_path"]+\
843 "/usr/local/portage",\
844 "Could not make portage_overlay dir",env=self.env)
845 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
846 "/usr/local/portage",\
847 "Could not copy portage_overlay",env=self.env)
849 def root_overlay(self):
850 """ Copy over the root_overlay """
851 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
852 for x in self.settings[self.settings["spec_prefix"]+\
854 if os.path.exists(x):
855 print "Copying root_overlay: "+x
856 cmd("rsync -a "+x+"/ "+\
857 self.settings["chroot_path"],\
858 self.settings["spec_prefix"]+"/root_overlay: "+x+\
859 " copy failed.",env=self.env)
865 for x in self.mounts:
866 if not os.path.exists(self.settings["chroot_path"]+x):
867 os.makedirs(self.settings["chroot_path"]+x,0755)
869 if not os.path.exists(self.mountmap[x]):
870 os.makedirs(self.mountmap[x],0755)
873 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
874 self.snapshot_lock_object.read_lock()
875 if os.uname()[0] == "FreeBSD":
877 retval=os.system("mount -t devfs none "+\
878 self.settings["chroot_path"]+x)
880 retval=os.system("mount_nullfs "+src+" "+\
881 self.settings["chroot_path"]+x)
883 retval=os.system("mount --bind "+src+" "+\
884 self.settings["chroot_path"]+x)
887 raise CatalystError,"Couldn't bind mount "+src
891 mypath=self.settings["chroot_path"]
892 myrevmounts=self.mounts[:]
893 myrevmounts.reverse()
894 """ Unmount in reverse order for nested bind-mounts """
895 for x in myrevmounts:
896 if not os.path.exists(mypath+x):
899 if not ismount(mypath+x):
902 retval=os.system("umount "+\
903 os.path.join(mypath,x.lstrip(os.path.sep)))
906 warn("First attempt to unmount: "+mypath+x+" failed.")
907 warn("Killing any pids still running in the chroot")
909 self.kill_chroot_pids()
911 retval2=os.system("umount "+mypath+x)
914 warn("Couldn't umount bind mount: "+mypath+x)
916 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
919 It's possible the snapshot lock object isn't created yet.
920 This is because mount safety check calls unbind before the
921 target is fully initialized
923 self.snapshot_lock_object.unlock()
928 if any bind mounts really failed, then we need to raise
929 this to potentially prevent an upcoming bash stage cleanup script
930 from wiping our bind mounts.
932 raise CatalystError,\
933 "Couldn't umount one or more bind-mounts; aborting for safety."
935 def chroot_setup(self):
936 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
938 self.override_cbuild()
939 self.override_chost()
940 self.override_cflags()
941 self.override_cxxflags()
942 self.override_ldflags()
943 if self.settings.has_key("AUTORESUME") \
944 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
945 print "Resume point detected, skipping chroot_setup operation..."
947 print "Setting up chroot..."
949 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
951 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
952 "Could not copy resolv.conf into place.",env=self.env)
954 """ Copy over the envscript, if applicable """
955 if self.settings.has_key("ENVSCRIPT"):
956 if not os.path.exists(self.settings["ENVSCRIPT"]):
957 raise CatalystError,\
958 "Can't find envscript "+self.settings["ENVSCRIPT"]
960 print "\nWarning!!!!"
961 print "\tOverriding certain env variables may cause catastrophic failure."
962 print "\tIf your build fails look here first as the possible problem."
963 print "\tCatalyst assumes you know what you are doing when setting"
964 print "\t\tthese variables."
965 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
966 print "\tYou have been warned\n"
968 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
969 self.settings["chroot_path"]+"/tmp/envscript",\
970 "Could not copy envscript into place.",env=self.env)
972 """ Setup metadata_overlay """
973 if self.settings.has_key("METADATA_OVERLAY") \
974 and not self.settings.has_key("portage_confdir"):
975 if not os.path.exists(self.settings["chroot_path"]+\
977 cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
978 myf=open(self.settings["chroot_path"]+\
979 "/etc/portage/modules","a")
980 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
985 Copy over /etc/hosts from the host in case there are any
988 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
989 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
990 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
991 "Could not backup /etc/hosts",env=self.env)
992 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
993 "Could not copy /etc/hosts",env=self.env)
995 """ Modify and write out make.conf (for the chroot) """
996 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
997 "Could not remove "+self.settings["chroot_path"]+\
998 "/etc/make.conf",env=self.env)
999 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1000 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1001 myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1002 if self.settings.has_key("CFLAGS"):
1003 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1004 if self.settings.has_key("CXXFLAGS"):
1005 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1007 myf.write('CXXFLAGS="${CFLAGS}"\n')
1009 if self.settings.has_key("LDFLAGS"):
1010 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1011 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1012 if self.settings.has_key("CBUILD"):
1013 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")
1014 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1016 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")
1017 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1019 """ Figure out what our USE vars are for building """
1021 if self.settings.has_key("HOSTUSE"):
1022 myusevars.extend(self.settings["HOSTUSE"])
1024 if self.settings.has_key("use"):
1025 myusevars.extend(self.settings["use"])
1028 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1029 myusevars = sorted(set(myusevars))
1030 myf.write('USE="'+string.join(myusevars)+'"\n')
1031 if '-*' in myusevars:
1032 print "\nWarning!!! "
1033 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1034 "/use will cause portage to ignore"
1035 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1037 """ Setup the portage overlay """
1038 if self.settings.has_key("portage_overlay"):
1039 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1042 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1043 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1044 "Could not backup /etc/make.conf",env=self.env)
1045 touch(self.settings["autoresume_path"]+"chroot_setup")
1048 if self.settings.has_key("AUTORESUME") \
1049 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1050 print "Resume point detected, skipping fsscript operation..."
1052 if self.settings.has_key("fsscript"):
1053 if os.path.exists(self.settings["controller_file"]):
1054 cmd("/bin/bash "+self.settings["controller_file"]+\
1055 " fsscript","fsscript script failed.",env=self.env)
1056 touch(self.settings["autoresume_path"]+"fsscript")
1059 if self.settings.has_key("AUTORESUME") \
1060 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1061 print "Resume point detected, skipping rcupdate operation..."
1063 if os.path.exists(self.settings["controller_file"]):
1064 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1065 "rc-update script failed.",env=self.env)
1066 touch(self.settings["autoresume_path"]+"rcupdate")
1069 if self.settings.has_key("AUTORESUME") \
1070 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1071 print "Resume point detected, skipping clean operation..."
1073 for x in self.settings["cleanables"]:
1074 print "Cleaning chroot: "+x+"... "
1075 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1078 """ Put /etc/hosts back into place """
1079 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1080 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1081 self.settings["chroot_path"]+"/etc/hosts",\
1082 "Could not replace /etc/hosts",env=self.env)
1084 """ Remove our overlay """
1085 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1086 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1087 "Could not remove /usr/local/portage",env=self.env)
1088 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1090 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1092 """ Clean up old and obsoleted files in /etc """
1093 if os.path.exists(self.settings["stage_path"]+"/etc"):
1094 cmd("find "+self.settings["stage_path"]+\
1095 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1096 "Could not remove stray files in /etc",env=self.env)
1098 if os.path.exists(self.settings["controller_file"]):
1099 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1100 "clean script failed.",env=self.env)
1101 touch(self.settings["autoresume_path"]+"clean")
1104 if self.settings.has_key("AUTORESUME") \
1105 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1106 print "Resume point detected, skipping empty operation..."
1108 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1109 if type(self.settings[self.settings["spec_prefix"]+\
1110 "/empty"])==types.StringType:
1111 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1112 self.settings[self.settings["spec_prefix"]+\
1114 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1115 myemp=self.settings["destpath"]+x
1116 if not os.path.isdir(myemp):
1117 print x,"not a directory or does not exist, skipping 'empty' operation."
1119 print "Emptying directory",x
1121 stat the dir, delete the dir, recreate the dir and set
1122 the proper perms and ownership
1124 mystat=os.stat(myemp)
1125 shutil.rmtree(myemp)
1126 os.makedirs(myemp,0755)
1127 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1128 os.chmod(myemp,mystat[ST_MODE])
1129 touch(self.settings["autoresume_path"]+"empty")
1132 if self.settings.has_key("AUTORESUME") \
1133 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1134 print "Resume point detected, skipping remove operation..."
1136 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1137 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1139 We're going to shell out for all these cleaning
1140 operations, so we get easy glob handling.
1142 print "livecd: removing "+x
1143 os.system("rm -rf "+self.settings["chroot_path"]+x)
1145 if os.path.exists(self.settings["controller_file"]):
1146 cmd("/bin/bash "+self.settings["controller_file"]+\
1147 " clean","Clean failed.",env=self.env)
1148 touch(self.settings["autoresume_path"]+"remove")
1154 if self.settings.has_key("AUTORESUME") \
1155 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1156 print "Resume point detected, skipping preclean operation..."
1159 if os.path.exists(self.settings["controller_file"]):
1160 cmd("/bin/bash "+self.settings["controller_file"]+\
1161 " preclean","preclean script failed.",env=self.env)
1162 touch(self.settings["autoresume_path"]+"preclean")
1166 raise CatalystError, "Build failed, could not execute preclean"
1169 if self.settings.has_key("AUTORESUME") \
1170 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1171 print "Resume point detected, skipping capture operation..."
1173 """ Capture target in a tarball """
1174 mypath=self.settings["target_path"].split("/")
1175 """ Remove filename from path """
1176 mypath=string.join(mypath[:-1],"/")
1178 """ Now make sure path exists """
1179 if not os.path.exists(mypath):
1182 print "Creating stage tarball..."
1184 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1185 self.settings["stage_path"]+" .",\
1186 "Couldn't create stage tarball",env=self.env)
1188 self.gen_contents_file(self.settings["target_path"])
1189 self.gen_digest_file(self.settings["target_path"])
1191 touch(self.settings["autoresume_path"]+"capture")
1193 def run_local(self):
1194 if self.settings.has_key("AUTORESUME") \
1195 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1196 print "Resume point detected, skipping run_local operation..."
1199 if os.path.exists(self.settings["controller_file"]):
1200 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1201 "run script failed.",env=self.env)
1202 touch(self.settings["autoresume_path"]+"run_local")
1204 except CatalystError:
1206 raise CatalystError,"Stage build aborting due to error."
1208 def setup_environment(self):
1210 Modify the current environment. This is an ugly hack that should be
1211 fixed. We need this to use the os.system() call since we can't
1212 specify our own environ
1214 for x in self.settings.keys():
1215 """ Sanitize var names by doing "s|/-.|_|g" """
1216 varname="clst_"+string.replace(x,"/","_")
1217 varname=string.replace(varname,"-","_")
1218 varname=string.replace(varname,".","_")
1219 if type(self.settings[x])==types.StringType:
1220 """ Prefix to prevent namespace clashes """
1221 #os.environ[varname]=self.settings[x]
1222 self.env[varname]=self.settings[x]
1223 elif type(self.settings[x])==types.ListType:
1224 #os.environ[varname]=string.join(self.settings[x])
1225 self.env[varname]=string.join(self.settings[x])
1226 elif type(self.settings[x])==types.BooleanType:
1227 if self.settings[x]:
1228 self.env[varname]="true"
1230 self.env[varname]="false"
1231 if self.settings.has_key("makeopts"):
1232 self.env["MAKEOPTS"]=self.settings["makeopts"]
1235 self.chroot_lock.write_lock()
1237 """ Kill any pids in the chroot "" """
1238 self.kill_chroot_pids()
1240 """ Check for mounts right away and abort if we cannot unmount them """
1241 self.mount_safety_check()
1243 if self.settings.has_key("CLEAR_AUTORESUME"):
1244 self.clear_autoresume()
1246 if self.settings.has_key("PURGEONLY"):
1250 if self.settings.has_key("PURGE"):
1253 for x in self.settings["action_sequence"]:
1254 print "--- Running action sequence: "+x
1257 apply(getattr(self,x))
1259 self.mount_safety_check()
1262 self.chroot_lock.unlock()
1265 if self.settings.has_key("AUTORESUME") \
1266 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1267 print "Resume point detected, skipping unmerge operation..."
1269 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1270 if type(self.settings[self.settings["spec_prefix"]+\
1271 "/unmerge"])==types.StringType:
1272 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1273 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1275 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1277 for x in range(0,len(myunmerge)):
1279 Surround args with quotes for passing to bash, allows
1280 things like "<" to remain intact
1282 myunmerge[x]="'"+myunmerge[x]+"'"
1283 myunmerge=string.join(myunmerge)
1285 """ Before cleaning, unmerge stuff """
1287 cmd("/bin/bash "+self.settings["controller_file"]+\
1288 " unmerge "+ myunmerge,"Unmerge script failed.",\
1290 print "unmerge shell script"
1291 except CatalystError:
1294 touch(self.settings["autoresume_path"]+"unmerge")
1296 def target_setup(self):
1297 if self.settings.has_key("AUTORESUME") \
1298 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1299 print "Resume point detected, skipping target_setup operation..."
1301 print "Setting up filesystems per filesystem type"
1302 cmd("/bin/bash "+self.settings["controller_file"]+\
1303 " target_image_setup "+ self.settings["target_path"],\
1304 "target_image_setup script failed.",env=self.env)
1305 touch(self.settings["autoresume_path"]+"target_setup")
1307 def setup_overlay(self):
1308 if self.settings.has_key("AUTORESUME") \
1309 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1310 print "Resume point detected, skipping setup_overlay operation..."
1312 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1313 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1314 if os.path.exists(x):
1315 cmd("rsync -a "+x+"/ "+\
1316 self.settings["target_path"],\
1317 self.settings["spec_prefix"]+"overlay: "+x+\
1318 " copy failed.",env=self.env)
1319 touch(self.settings["autoresume_path"]+"setup_overlay")
1321 def create_iso(self):
1322 if self.settings.has_key("AUTORESUME") \
1323 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1324 print "Resume point detected, skipping create_iso operation..."
1326 """ Create the ISO """
1327 if self.settings.has_key("iso"):
1328 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1329 self.settings["iso"],"ISO creation script failed.",\
1331 self.gen_contents_file(self.settings["iso"])
1332 self.gen_digest_file(self.settings["iso"])
1333 touch(self.settings["autoresume_path"]+"create_iso")
1335 print "WARNING: livecd/iso was not defined."
1336 print "An ISO Image will not be created."
1338 def build_packages(self):
1339 if self.settings.has_key("AUTORESUME") \
1340 and os.path.exists(self.settings["autoresume_path"]+\
1342 print "Resume point detected, skipping build_packages operation..."
1344 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1345 if self.settings.has_key("AUTORESUME") \
1346 and os.path.exists(self.settings["autoresume_path"]+\
1348 print "Resume point detected, skipping build_packages operation..."
1351 list_bashify(self.settings[self.settings["spec_prefix"]\
1354 cmd("/bin/bash "+self.settings["controller_file"]+\
1355 " build_packages "+mypack,\
1356 "Error in attempt to build packages",env=self.env)
1357 touch(self.settings["autoresume_path"]+"build_packages")
1358 except CatalystError:
1360 raise CatalystError,self.settings["spec_prefix"]+\
1361 "build aborting due to error."
1363 def build_kernel(self):
1364 if self.settings.has_key("AUTORESUME") \
1365 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1366 print "Resume point detected, skipping build_kernel operation..."
1368 if self.settings.has_key("boot/kernel"):
1370 mynames=self.settings["boot/kernel"]
1371 if type(mynames)==types.StringType:
1374 Execute the script that sets up the kernel build environment
1376 cmd("/bin/bash "+self.settings["controller_file"]+\
1377 " pre-kmerge ","Runscript pre-kmerge failed",\
1380 for kname in mynames:
1381 if self.settings.has_key("AUTORESUME") \
1382 and os.path.exists(self.settings["autoresume_path"]\
1383 +"build_kernel_"+kname):
1384 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1385 else: # TODO: make this not require a kernel config
1387 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1389 raise CatalystError,\
1390 "Can't find kernel config: "+\
1391 self.settings["boot/kernel/"+kname+\
1395 raise CatalystError,\
1396 "Required value boot/kernel/config not specified"
1399 cmd("cp "+self.settings["boot/kernel/"+kname+\
1401 self.settings["chroot_path"]+"/var/tmp/"+\
1403 "Couldn't copy kernel config: "+\
1404 self.settings["boot/kernel/"+kname+\
1405 "/config"],env=self.env)
1407 except CatalystError:
1411 If we need to pass special options to the bootloader
1412 for this kernel put them into the environment
1414 if self.settings.has_key("boot/kernel/"+kname+\
1416 myopts=self.settings["boot/kernel/"+kname+\
1419 if type(myopts) != types.StringType:
1420 myopts = string.join(myopts)
1421 self.env[kname+"_kernelopts"]=myopts
1424 self.env[kname+"_kernelopts"]=""
1426 if not self.settings.has_key("boot/kernel/"+kname+\
1428 self.settings["boot/kernel/"+kname+\
1431 self.env["clst_kextraversion"]=\
1432 self.settings["boot/kernel/"+kname+\
1435 if self.settings.has_key("boot/kernel/"+kname+\
1436 "/initramfs_overlay"):
1437 if os.path.exists(self.settings["boot/kernel/"+\
1438 kname+"/initramfs_overlay"]):
1439 print "Copying initramfs_overlay dir "+\
1440 self.settings["boot/kernel/"+kname+\
1441 "/initramfs_overlay"]
1444 self.settings["chroot_path"]+\
1445 "/tmp/initramfs_overlay/"+\
1446 self.settings["boot/kernel/"+kname+\
1447 "/initramfs_overlay"],env=self.env)
1449 cmd("cp -R "+self.settings["boot/kernel/"+\
1450 kname+"/initramfs_overlay"]+"/* "+\
1451 self.settings["chroot_path"]+\
1452 "/tmp/initramfs_overlay/"+\
1453 self.settings["boot/kernel/"+kname+\
1454 "/initramfs_overlay"],env=self.env)
1456 """ Execute the script that builds the kernel """
1457 cmd("/bin/bash "+self.settings["controller_file"]+\
1459 "Runscript kernel build failed",env=self.env)
1461 if self.settings.has_key("boot/kernel/"+kname+\
1462 "/initramfs_overlay"):
1463 if os.path.exists(self.settings["chroot_path"]+\
1464 "/tmp/initramfs_overlay/"):
1465 print "Cleaning up temporary overlay dir"
1466 cmd("rm -R "+self.settings["chroot_path"]+\
1467 "/tmp/initramfs_overlay/",env=self.env)
1469 touch(self.settings["autoresume_path"]+\
1470 "build_kernel_"+kname)
1473 Execute the script that cleans up the kernel build
1476 cmd("/bin/bash "+self.settings["controller_file"]+\
1478 "Runscript post-kmerge failed",env=self.env)
1480 touch(self.settings["autoresume_path"]+"build_kernel")
1482 except CatalystError:
1484 raise CatalystError,\
1485 "build aborting due to kernel build error."
1487 def bootloader(self):
1488 if self.settings.has_key("AUTORESUME") \
1489 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1490 print "Resume point detected, skipping bootloader operation..."
1493 cmd("/bin/bash "+self.settings["controller_file"]+\
1494 " bootloader " + self.settings["target_path"],\
1495 "Bootloader script failed.",env=self.env)
1496 touch(self.settings["autoresume_path"]+"bootloader")
1497 except CatalystError:
1499 raise CatalystError,"Script aborting due to error."
1501 def livecd_update(self):
1502 if self.settings.has_key("AUTORESUME") \
1503 and os.path.exists(self.settings["autoresume_path"]+\
1505 print "Resume point detected, skipping build_packages operation..."
1508 cmd("/bin/bash "+self.settings["controller_file"]+\
1509 " livecd-update","livecd-update failed.",env=self.env)
1510 touch(self.settings["autoresume_path"]+"livecd_update")
1512 except CatalystError:
1514 raise CatalystError,"build aborting due to livecd_update error."
1516 def clear_chroot(self):
1517 myemp=self.settings["chroot_path"]
1518 if os.path.isdir(myemp):
1519 print "Emptying directory",myemp
1521 stat the dir, delete the dir, recreate the dir and set
1522 the proper perms and ownership
1524 mystat=os.stat(myemp)
1525 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1526 """ There's no easy way to change flags recursively in python """
1527 if os.uname()[0] == "FreeBSD":
1528 os.system("chflags -R noschg "+myemp)
1529 shutil.rmtree(myemp)
1530 os.makedirs(myemp,0755)
1531 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1532 os.chmod(myemp,mystat[ST_MODE])
1534 def clear_packages(self):
1535 if self.settings.has_key("PKGCACHE"):
1536 print "purging the pkgcache ..."
1538 myemp=self.settings["pkgcache_path"]
1539 if os.path.isdir(myemp):
1540 print "Emptying directory",myemp
1542 stat the dir, delete the dir, recreate the dir and set
1543 the proper perms and ownership
1545 mystat=os.stat(myemp)
1546 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1547 shutil.rmtree(myemp)
1548 os.makedirs(myemp,0755)
1549 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1550 os.chmod(myemp,mystat[ST_MODE])
1552 def clear_kerncache(self):
1553 if self.settings.has_key("KERNCACHE"):
1554 print "purging the kerncache ..."
1556 myemp=self.settings["kerncache_path"]
1557 if os.path.isdir(myemp):
1558 print "Emptying directory",myemp
1560 stat the dir, delete the dir, recreate the dir and set
1561 the proper perms and ownership
1563 mystat=os.stat(myemp)
1564 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1565 shutil.rmtree(myemp)
1566 os.makedirs(myemp,0755)
1567 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1568 os.chmod(myemp,mystat[ST_MODE])
1570 def clear_autoresume(self):
1571 """ Clean resume points since they are no longer needed """
1572 if self.settings.has_key("AUTORESUME"):
1573 print "Removing AutoResume Points: ..."
1574 myemp=self.settings["autoresume_path"]
1575 if os.path.isdir(myemp):
1576 if self.settings.has_key("AUTORESUME"):
1577 print "Emptying directory",myemp
1579 stat the dir, delete the dir, recreate the dir and set
1580 the proper perms and ownership
1582 mystat=os.stat(myemp)
1583 if os.uname()[0] == "FreeBSD":
1584 cmd("chflags -R noschg "+myemp,\
1585 "Could not remove immutable flag for file "\
1587 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1588 shutil.rmtree(myemp)
1589 os.makedirs(myemp,0755)
1590 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1591 os.chmod(myemp,mystat[ST_MODE])
1593 def gen_contents_file(self,file):
1594 if os.path.exists(file+".CONTENTS"):
1595 os.remove(file+".CONTENTS")
1596 if self.settings.has_key("contents"):
1597 if os.path.exists(file):
1598 myf=open(file+".CONTENTS","w")
1600 for i in self.settings["contents"].split():
1605 contents=generate_contents(file,contents_function=j,\
1606 verbose=self.settings.has_key("VERBOSE"))
1611 def gen_digest_file(self,file):
1612 if os.path.exists(file+".DIGESTS"):
1613 os.remove(file+".DIGESTS")
1614 if self.settings.has_key("digests"):
1615 if os.path.exists(file):
1616 myf=open(file+".DIGESTS","w")
1618 for i in self.settings["digests"].split():
1622 for f in [file, file+'.CONTENTS']:
1623 if os.path.exists(f):
1625 for k in hash_map.keys():
1626 hash=generate_hash(f,hash_function=k,verbose=\
1627 self.settings.has_key("VERBOSE"))
1631 hash=generate_hash(f,hash_function=j,verbose=\
1632 self.settings.has_key("VERBOSE"))
1637 countdown(10,"Purging Caches ...")
1638 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY"):
1639 print "clearing autoresume ..."
1640 self.clear_autoresume()
1642 print "clearing chroot ..."
1645 print "clearing package cache ..."
1646 self.clear_packages()
1648 print "clearing kerncache ..."
1649 self.clear_kerncache()
1651 # vim: ts=4 sw=4 sta et sts=4 ai