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 # XXX WTF are we removing the old tarball before we start building the
304 # XXX new one? If the build fails, you don't want to be left with
306 # if os.path.isfile(self.settings["target_path"]):
307 # cmd("rm -f "+self.settings["target_path"],\
308 # "Could not remove existing file: "\
309 # +self.settings["target_path"],env=self.env)
310 touch(self.settings["autoresume_path"]+"setup_target_path")
312 if not os.path.exists(self.settings["storedir"]+"/builds/"):
313 os.makedirs(self.settings["storedir"]+"/builds/")
315 def set_fsscript(self):
316 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
317 self.settings["fsscript"]=\
318 self.settings[self.settings["spec_prefix"]+"/fsscript"]
319 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
322 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
323 self.settings["rcadd"]=\
324 self.settings[self.settings["spec_prefix"]+"/rcadd"]
325 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
328 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
329 self.settings["rcdel"]=\
330 self.settings[self.settings["spec_prefix"]+"/rcdel"]
331 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
334 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
335 self.settings["cdtar"]=\
336 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
337 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
340 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
341 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
342 self.settings["iso"]=\
343 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
345 # This automatically prepends the build dir to the ISO output path
346 # if it doesn't start with a /
347 self.settings["iso"] = normpath(self.settings["storedir"] + \
348 "/builds/" + self.settings["rel_type"] + "/" + \
349 self.settings[self.settings["spec_prefix"]+"/iso"])
350 del self.settings[self.settings["spec_prefix"]+"/iso"]
352 def set_fstype(self):
353 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
354 self.settings["fstype"]=\
355 self.settings[self.settings["spec_prefix"]+"/fstype"]
356 del self.settings[self.settings["spec_prefix"]+"/fstype"]
358 if not self.settings.has_key("fstype"):
359 self.settings["fstype"]="normal"
360 for x in self.valid_values:
361 if x == self.settings["spec_prefix"]+"/fstype":
362 print "\n"+self.settings["spec_prefix"]+\
363 "/fstype is being set to the default of \"normal\"\n"
366 if self.settings.has_key("fstype"):
367 self.valid_values.append("fsops")
368 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
369 self.settings["fsops"]=\
370 self.settings[self.settings["spec_prefix"]+"/fsops"]
371 del self.settings[self.settings["spec_prefix"]+"/fsops"]
373 def set_source_path(self):
374 if self.settings.has_key("SEEDCACHE")\
375 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
376 self.settings["source_subpath"]+"/")):
377 self.settings["source_path"]=normpath(self.settings["storedir"]+\
378 "/tmp/"+self.settings["source_subpath"]+"/")
380 self.settings["source_path"]=normpath(self.settings["storedir"]+\
381 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
382 if os.path.isfile(self.settings["source_path"]):
383 # XXX: Is this even necessary if the previous check passes?
384 if os.path.exists(self.settings["source_path"]):
385 self.settings["source_path_hash"]=\
386 generate_hash(self.settings["source_path"],\
387 hash_function=self.settings["hash_function"],\
389 print "Source path set to "+self.settings["source_path"]
390 if os.path.isdir(self.settings["source_path"]):
391 print "\tIf this is not desired, remove this directory or turn off"
392 print "\tseedcache in the options of catalyst.conf the source path"
393 print "\twill then be "+\
394 normpath(self.settings["storedir"]+"/builds/"+\
395 self.settings["source_subpath"]+".tar.bz2\n")
397 def set_dest_path(self):
398 if self.settings.has_key("root_path"):
399 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
400 self.settings["root_path"])
402 self.settings["destpath"]=normpath(self.settings["chroot_path"])
404 def set_cleanables(self):
405 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
406 "/root/*","/usr/portage"]
408 def set_snapshot_path(self):
409 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
410 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
412 if os.path.exists(self.settings["snapshot_path"]):
413 self.settings["snapshot_path_hash"]=\
414 generate_hash(self.settings["snapshot_path"],\
415 hash_function=self.settings["hash_function"],verbose=False)
417 def set_snapcache_path(self):
418 if self.settings.has_key("SNAPCACHE"):
419 self.settings["snapshot_cache_path"]=\
420 normpath(self.settings["snapshot_cache"]+"/"+\
421 self.settings["snapshot"]+"/")
422 self.snapcache_lock=\
423 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
424 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
426 def set_chroot_path(self):
428 NOTE: the trailing slash is very important!
429 Things *will* break without it!
431 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
432 "/tmp/"+self.settings["target_subpath"]+"/")
433 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
435 def set_autoresume_path(self):
436 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
437 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
438 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
439 self.settings["version_stamp"]+"/")
440 if self.settings.has_key("AUTORESUME"):
441 print "The autoresume path is " + self.settings["autoresume_path"]
442 if not os.path.exists(self.settings["autoresume_path"]):
443 os.makedirs(self.settings["autoresume_path"],0755)
445 def set_controller_file(self):
446 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
447 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
450 def set_iso_volume_id(self):
451 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
452 self.settings["iso_volume_id"]=\
453 self.settings[self.settings["spec_prefix"]+"/volid"]
454 if len(self.settings["iso_volume_id"])>32:
455 raise CatalystError,\
456 "ISO volume ID must not exceed 32 characters."
458 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
460 def set_action_sequence(self):
461 """ Default action sequence for run method """
462 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
463 "config_profile_link","setup_confdir","portage_overlay",\
464 "base_dirs","bind","chroot_setup","setup_environment",\
465 "run_local","preclean","unbind","clean"]
466 # if self.settings.has_key("TARBALL") or \
467 # not self.settings.has_key("FETCH"):
468 if not self.settings.has_key("FETCH"):
469 self.settings["action_sequence"].append("capture")
470 self.settings["action_sequence"].append("clear_autoresume")
473 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
474 self.settings["use"]=\
475 self.settings[self.settings["spec_prefix"]+"/use"]
476 del self.settings[self.settings["spec_prefix"]+"/use"]
477 if self.settings.has_key("use"):
478 if type(self.settings["use"])==types.StringType:
479 self.settings["use"]=self.settings["use"].split()
480 self.settings["use"].append("bindist")
482 def set_stage_path(self):
483 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
485 def set_mounts(self):
488 def set_packages(self):
492 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
493 if type(self.settings[self.settings["spec_prefix"]+\
494 "/rm"])==types.StringType:
495 self.settings[self.settings["spec_prefix"]+"/rm"]=\
496 self.settings[self.settings["spec_prefix"]+"/rm"].split()
498 def set_linuxrc(self):
499 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
500 if type(self.settings[self.settings["spec_prefix"]+\
501 "/linuxrc"])==types.StringType:
502 self.settings["linuxrc"]=\
503 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
504 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
506 def set_busybox_config(self):
507 if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
508 if type(self.settings[self.settings["spec_prefix"]+\
509 "/busybox_config"])==types.StringType:
510 self.settings["busybox_config"]=\
511 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
512 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
514 def set_portage_overlay(self):
515 if self.settings.has_key("portage_overlay"):
516 if type(self.settings["portage_overlay"])==types.StringType:
517 self.settings["portage_overlay"]=\
518 self.settings["portage_overlay"].split()
519 print "portage_overlay directories are set to: \""+\
520 string.join(self.settings["portage_overlay"])+"\""
522 def set_overlay(self):
523 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
524 if type(self.settings[self.settings["spec_prefix"]+\
525 "/overlay"])==types.StringType:
526 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
527 self.settings[self.settings["spec_prefix"]+\
530 def set_root_overlay(self):
531 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
532 if type(self.settings[self.settings["spec_prefix"]+\
533 "/root_overlay"])==types.StringType:
534 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
535 self.settings[self.settings["spec_prefix"]+\
536 "/root_overlay"].split()
538 def set_root_path(self):
539 """ ROOT= variable for emerges """
540 self.settings["root_path"]="/"
542 def set_valid_build_kernel_vars(self,addlargs):
543 if addlargs.has_key("boot/kernel"):
544 if type(addlargs["boot/kernel"])==types.StringType:
545 loopy=[addlargs["boot/kernel"]]
547 loopy=addlargs["boot/kernel"]
550 self.valid_values.append("boot/kernel/"+x+"/aliases")
551 self.valid_values.append("boot/kernel/"+x+"/config")
552 self.valid_values.append("boot/kernel/"+x+"/console")
553 self.valid_values.append("boot/kernel/"+x+"/extraversion")
554 self.valid_values.append("boot/kernel/"+x+"/gk_action")
555 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
556 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
557 self.valid_values.append("boot/kernel/"+x+"/machine_type")
558 self.valid_values.append("boot/kernel/"+x+"/sources")
559 self.valid_values.append("boot/kernel/"+x+"/softlevel")
560 self.valid_values.append("boot/kernel/"+x+"/use")
561 self.valid_values.append("boot/kernel/"+x+"/packages")
562 if addlargs.has_key("boot/kernel/"+x+"/packages"):
563 if type(addlargs["boot/kernel/"+x+\
564 "/packages"])==types.StringType:
565 addlargs["boot/kernel/"+x+"/packages"]=\
566 [addlargs["boot/kernel/"+x+"/packages"]]
568 def set_build_kernel_vars(self):
569 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
570 self.settings["gk_mainargs"]=\
571 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
572 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
574 def kill_chroot_pids(self):
575 print "Checking for processes running in chroot and killing them."
578 Force environment variables to be exported so script can see them
580 self.setup_environment()
582 if os.path.exists(self.settings["sharedir"]+\
583 "/targets/support/kill-chroot-pids.sh"):
584 cmd("/bin/bash "+self.settings["sharedir"]+\
585 "/targets/support/kill-chroot-pids.sh",\
586 "kill-chroot-pids script failed.",env=self.env)
588 def mount_safety_check(self):
589 mypath=self.settings["chroot_path"]
592 Check and verify that none of our paths in mypath are mounted. We don't
593 want to clean up with things still mounted, and this allows us to check.
594 Returns 1 on ok, 0 on "something is still mounted" case.
597 if not os.path.exists(mypath):
600 for x in self.mounts:
601 if not os.path.exists(mypath+x):
604 if ismount(mypath+x):
605 """ Something is still mounted "" """
607 print x+" is still mounted; performing auto-bind-umount...",
608 """ Try to umount stuff ourselves """
610 if ismount(mypath+x):
611 raise CatalystError, "Auto-unbind failed for "+x
613 print "Auto-unbind successful..."
614 except CatalystError:
615 raise CatalystError, "Unable to auto-unbind "+x
620 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
623 if self.settings.has_key("SEEDCACHE"):
624 if os.path.isdir(self.settings["source_path"]):
625 """ SEEDCACHE Is a directory, use rsync """
626 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
627 " "+self.settings["chroot_path"]
628 display_msg="\nStarting rsync from "+\
629 self.settings["source_path"]+"\nto "+\
630 self.settings["chroot_path"]+\
631 " (This may take some time) ...\n"
632 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
633 self.settings["chroot_path"]+" failed."
635 """ SEEDCACHE is a not a directory, try untar'ing """
636 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
637 display_msg="\nStarting tar extract from "+\
638 self.settings["source_path"]+"\nto "+\
639 self.settings["chroot_path"]+\
640 " (This may take some time) ...\n"
641 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
642 self.settings["chroot_path"]
643 error_msg="Tarball extraction of "+\
644 self.settings["source_path"]+" to "+\
645 self.settings["chroot_path"]+" failed."
647 """ No SEEDCACHE, use tar """
648 display_msg="\nStarting tar extract from "+\
649 self.settings["source_path"]+"\nto "+\
650 self.settings["chroot_path"]+\
651 " (This may take some time) ...\n"
652 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
653 self.settings["chroot_path"]
654 error_msg="Tarball extraction of "+self.settings["source_path"]+\
655 " to "+self.settings["chroot_path"]+" failed."
657 if self.settings.has_key("AUTORESUME"):
658 if os.path.isdir(self.settings["source_path"]) \
659 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
660 """ Autoresume is valid, SEEDCACHE is valid """
662 invalid_snapshot=False
664 elif os.path.isfile(self.settings["source_path"]) \
665 and self.settings["source_path_hash"]==clst_unpack_hash:
666 """ Autoresume is valid, tarball is valid """
668 invalid_snapshot=True
670 elif os.path.isdir(self.settings["source_path"]) \
671 and not os.path.exists(self.settings["autoresume_path"]+\
673 """ Autoresume is invalid, SEEDCACHE """
675 invalid_snapshot=False
677 elif os.path.isfile(self.settings["source_path"]) \
678 and self.settings["source_path_hash"]!=clst_unpack_hash:
679 """ Autoresume is invalid, tarball """
681 invalid_snapshot=True
683 """ No autoresume, SEEDCACHE """
684 if self.settings.has_key("SEEDCACHE"):
685 """ SEEDCACHE so let's run rsync and let it clean up """
686 if os.path.isdir(self.settings["source_path"]):
688 invalid_snapshot=False
689 elif os.path.isfile(self.settings["source_path"]):
690 """ Tarball so unpack and remove anything already there """
692 invalid_snapshot=True
693 """ No autoresume, no SEEDCACHE """
695 """ Tarball so unpack and remove anything already there """
696 if os.path.isfile(self.settings["source_path"]):
698 invalid_snapshot=True
699 elif os.path.isdir(self.settings["source_path"]):
700 """ We should never reach this, so something is very wrong """
701 raise CatalystError,\
702 "source path is a dir but seedcache is not enabled"
705 self.mount_safety_check()
708 if self.settings.has_key("AUTORESUME"):
709 print "No Valid Resume point detected, cleaning up..."
711 self.clear_autoresume()
714 if not os.path.exists(self.settings["chroot_path"]):
715 os.makedirs(self.settings["chroot_path"])
717 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
718 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
720 if self.settings.has_key("PKGCACHE"):
721 if not os.path.exists(self.settings["pkgcache_path"]):
722 os.makedirs(self.settings["pkgcache_path"],0755)
724 if self.settings.has_key("KERNCACHE"):
725 if not os.path.exists(self.settings["kerncache_path"]):
726 os.makedirs(self.settings["kerncache_path"],0755)
729 cmd(unpack_cmd,error_msg,env=self.env)
731 if self.settings.has_key("source_path_hash"):
732 myf=open(self.settings["autoresume_path"]+"unpack","w")
733 myf.write(self.settings["source_path_hash"])
736 touch(self.settings["autoresume_path"]+"unpack")
738 print "Resume point detected, skipping unpack operation..."
740 def unpack_snapshot(self):
742 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
745 if self.settings.has_key("SNAPCACHE"):
746 snapshot_cache_hash=\
747 read_from_clst(self.settings["snapshot_cache_path"]+\
749 destdir=self.settings["snapshot_cache_path"]
750 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
751 unpack_errmsg="Error unpacking snapshot"
752 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
753 self.settings["snapshot_cache_path"]+\
754 " (This can take a long time)..."
755 cleanup_errmsg="Error removing existing snapshot cache directory."
756 self.snapshot_lock_object=self.snapcache_lock
758 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
759 print "Valid snapshot cache, skipping unpack of portage tree..."
762 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
763 cleanup_errmsg="Error removing existing snapshot directory."
765 "Cleaning up existing portage tree (This can take a long time)..."
766 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
767 self.settings["chroot_path"]+"/usr"
768 unpack_errmsg="Error unpacking snapshot"
770 if self.settings.has_key("AUTORESUME") \
771 and os.path.exists(self.settings["chroot_path"]+\
773 and os.path.exists(self.settings["autoresume_path"]\
775 and self.settings["snapshot_path_hash"] == snapshot_hash:
777 "Valid Resume point detected, skipping unpack of portage tree..."
781 if self.settings.has_key("SNAPCACHE"):
782 self.snapshot_lock_object.write_lock()
783 if os.path.exists(destdir):
785 cleanup_cmd="rm -rf "+destdir
786 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
787 if not os.path.exists(destdir):
788 os.makedirs(destdir,0755)
790 print "Unpacking portage tree (This can take a long time) ..."
791 cmd(unpack_cmd,unpack_errmsg,env=self.env)
793 if self.settings.has_key("SNAPCACHE"):
794 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
795 myf.write(self.settings["snapshot_path_hash"])
798 print "Setting snapshot autoresume point"
799 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
800 myf.write(self.settings["snapshot_path_hash"])
803 if self.settings.has_key("SNAPCACHE"):
804 self.snapshot_lock_object.unlock()
806 def config_profile_link(self):
807 if self.settings.has_key("AUTORESUME") \
808 and os.path.exists(self.settings["autoresume_path"]+\
809 "config_profile_link"):
811 "Resume point detected, skipping config_profile_link operation..."
813 # TODO: zmedico and I discussed making this a directory and pushing
814 # in a parent file, as well as other user-specified configuration.
815 print "Configuring profile link..."
816 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
817 "Error zapping profile link",env=self.env)
818 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
819 cmd("ln -sf ../../usr/portage/profiles/"+\
820 self.settings["target_profile"]+" "+\
821 self.settings["chroot_path"]+"/etc/portage/make.profile",\
822 "Error creating profile link",env=self.env)
823 touch(self.settings["autoresume_path"]+"config_profile_link")
825 def setup_confdir(self):
826 if self.settings.has_key("AUTORESUME") \
827 and os.path.exists(self.settings["autoresume_path"]+\
829 print "Resume point detected, skipping setup_confdir operation..."
831 if self.settings.has_key("portage_confdir"):
832 print "Configuring /etc/portage..."
833 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
834 "Error zapping /etc/portage",env=self.env)
835 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
836 self.settings["chroot_path"]+"/etc/portage",\
837 "Error copying /etc/portage",env=self.env)
838 touch(self.settings["autoresume_path"]+"setup_confdir")
840 def portage_overlay(self):
841 """ We copy the contents of our overlays to /usr/local/portage """
842 if self.settings.has_key("portage_overlay"):
843 for x in self.settings["portage_overlay"]:
844 if os.path.exists(x):
845 print "Copying overlay dir " +x
846 cmd("mkdir -p "+self.settings["chroot_path"]+\
847 "/usr/local/portage",\
848 "Could not make portage_overlay dir",env=self.env)
849 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
850 "/usr/local/portage",\
851 "Could not copy portage_overlay",env=self.env)
853 def root_overlay(self):
854 """ Copy over the root_overlay """
855 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
856 for x in self.settings[self.settings["spec_prefix"]+\
858 if os.path.exists(x):
859 print "Copying root_overlay: "+x
860 cmd("rsync -a "+x+"/ "+\
861 self.settings["chroot_path"],\
862 self.settings["spec_prefix"]+"/root_overlay: "+x+\
863 " copy failed.",env=self.env)
869 for x in self.mounts:
870 if not os.path.exists(self.settings["chroot_path"]+x):
871 os.makedirs(self.settings["chroot_path"]+x,0755)
873 if not os.path.exists(self.mountmap[x]):
874 os.makedirs(self.mountmap[x],0755)
877 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
878 self.snapshot_lock_object.read_lock()
879 if os.uname()[0] == "FreeBSD":
881 retval=os.system("mount -t devfs none "+\
882 self.settings["chroot_path"]+x)
884 retval=os.system("mount_nullfs "+src+" "+\
885 self.settings["chroot_path"]+x)
887 retval=os.system("mount --bind "+src+" "+\
888 self.settings["chroot_path"]+x)
891 raise CatalystError,"Couldn't bind mount "+src
895 mypath=self.settings["chroot_path"]
896 myrevmounts=self.mounts[:]
897 myrevmounts.reverse()
898 """ Unmount in reverse order for nested bind-mounts """
899 for x in myrevmounts:
900 if not os.path.exists(mypath+x):
903 if not ismount(mypath+x):
906 retval=os.system("umount "+\
907 os.path.join(mypath,x.lstrip(os.path.sep)))
910 warn("First attempt to unmount: "+mypath+x+" failed.")
911 warn("Killing any pids still running in the chroot")
913 self.kill_chroot_pids()
915 retval2=os.system("umount "+mypath+x)
918 warn("Couldn't umount bind mount: "+mypath+x)
920 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
923 It's possible the snapshot lock object isn't created yet.
924 This is because mount safety check calls unbind before the
925 target is fully initialized
927 self.snapshot_lock_object.unlock()
932 if any bind mounts really failed, then we need to raise
933 this to potentially prevent an upcoming bash stage cleanup script
934 from wiping our bind mounts.
936 raise CatalystError,\
937 "Couldn't umount one or more bind-mounts; aborting for safety."
939 def chroot_setup(self):
940 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
942 self.override_cbuild()
943 self.override_chost()
944 self.override_cflags()
945 self.override_cxxflags()
946 self.override_ldflags()
947 if self.settings.has_key("AUTORESUME") \
948 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
949 print "Resume point detected, skipping chroot_setup operation..."
951 print "Setting up chroot..."
953 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
955 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
956 "Could not copy resolv.conf into place.",env=self.env)
958 """ Copy over the envscript, if applicable """
959 if self.settings.has_key("ENVSCRIPT"):
960 if not os.path.exists(self.settings["ENVSCRIPT"]):
961 raise CatalystError,\
962 "Can't find envscript "+self.settings["ENVSCRIPT"]
964 print "\nWarning!!!!"
965 print "\tOverriding certain env variables may cause catastrophic failure."
966 print "\tIf your build fails look here first as the possible problem."
967 print "\tCatalyst assumes you know what you are doing when setting"
968 print "\t\tthese variables."
969 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
970 print "\tYou have been warned\n"
972 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
973 self.settings["chroot_path"]+"/tmp/envscript",\
974 "Could not copy envscript into place.",env=self.env)
977 Copy over /etc/hosts from the host in case there are any
980 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
981 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
982 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
983 "Could not backup /etc/hosts",env=self.env)
984 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
985 "Could not copy /etc/hosts",env=self.env)
987 """ Modify and write out make.conf (for the chroot) """
988 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
989 "Could not remove "+self.settings["chroot_path"]+\
990 "/etc/make.conf",env=self.env)
991 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
992 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
993 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
994 if self.settings.has_key("CFLAGS"):
995 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
996 if self.settings.has_key("CXXFLAGS"):
997 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
998 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1000 myf.write('CXXFLAGS="${CFLAGS}"\n')
1002 myf.write('CXXFLAGS="${CFLAGS}"\n')
1004 if self.settings.has_key("LDFLAGS"):
1005 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1006 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1007 if self.settings.has_key("CBUILD"):
1008 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")
1009 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1011 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")
1012 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1014 """ Figure out what our USE vars are for building """
1016 if self.settings.has_key("HOSTUSE"):
1017 myusevars.extend(self.settings["HOSTUSE"])
1019 if self.settings.has_key("use"):
1020 myusevars.extend(self.settings["use"])
1023 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1024 myusevars = sorted(set(myusevars))
1025 myf.write('USE="'+string.join(myusevars)+'"\n')
1026 if '-*' in myusevars:
1027 print "\nWarning!!! "
1028 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1029 "/use will cause portage to ignore"
1030 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1032 """ Setup the portage overlay """
1033 if self.settings.has_key("portage_overlay"):
1034 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1037 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1038 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1039 "Could not backup /etc/make.conf",env=self.env)
1040 touch(self.settings["autoresume_path"]+"chroot_setup")
1043 if self.settings.has_key("AUTORESUME") \
1044 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1045 print "Resume point detected, skipping fsscript operation..."
1047 if self.settings.has_key("fsscript"):
1048 if os.path.exists(self.settings["controller_file"]):
1049 cmd("/bin/bash "+self.settings["controller_file"]+\
1050 " fsscript","fsscript script failed.",env=self.env)
1051 touch(self.settings["autoresume_path"]+"fsscript")
1054 if self.settings.has_key("AUTORESUME") \
1055 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1056 print "Resume point detected, skipping rcupdate operation..."
1058 if os.path.exists(self.settings["controller_file"]):
1059 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1060 "rc-update script failed.",env=self.env)
1061 touch(self.settings["autoresume_path"]+"rcupdate")
1064 if self.settings.has_key("AUTORESUME") \
1065 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1066 print "Resume point detected, skipping clean operation..."
1068 for x in self.settings["cleanables"]:
1069 print "Cleaning chroot: "+x+"... "
1070 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1073 """ Put /etc/hosts back into place """
1074 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1075 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1076 self.settings["chroot_path"]+"/etc/hosts",\
1077 "Could not replace /etc/hosts",env=self.env)
1079 """ Remove our overlay """
1080 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1081 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1082 "Could not remove /usr/local/portage",env=self.env)
1083 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1085 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1087 """ Clean up old and obsoleted files in /etc """
1088 if os.path.exists(self.settings["stage_path"]+"/etc"):
1089 cmd("find "+self.settings["stage_path"]+\
1090 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1091 "Could not remove stray files in /etc",env=self.env)
1093 if os.path.exists(self.settings["controller_file"]):
1094 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1095 "clean script failed.",env=self.env)
1096 touch(self.settings["autoresume_path"]+"clean")
1099 if self.settings.has_key("AUTORESUME") \
1100 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1101 print "Resume point detected, skipping empty operation..."
1103 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1104 if type(self.settings[self.settings["spec_prefix"]+\
1105 "/empty"])==types.StringType:
1106 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1107 self.settings[self.settings["spec_prefix"]+\
1109 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1110 myemp=self.settings["destpath"]+x
1111 if not os.path.isdir(myemp):
1112 print x,"not a directory or does not exist, skipping 'empty' operation."
1114 print "Emptying directory",x
1116 stat the dir, delete the dir, recreate the dir and set
1117 the proper perms and ownership
1119 mystat=os.stat(myemp)
1120 shutil.rmtree(myemp)
1121 os.makedirs(myemp,0755)
1122 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1123 os.chmod(myemp,mystat[ST_MODE])
1124 touch(self.settings["autoresume_path"]+"empty")
1127 if self.settings.has_key("AUTORESUME") \
1128 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1129 print "Resume point detected, skipping remove operation..."
1131 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1132 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1134 We're going to shell out for all these cleaning
1135 operations, so we get easy glob handling.
1137 print "livecd: removing "+x
1138 os.system("rm -rf "+self.settings["chroot_path"]+x)
1140 if os.path.exists(self.settings["controller_file"]):
1141 cmd("/bin/bash "+self.settings["controller_file"]+\
1142 " clean","Clean failed.",env=self.env)
1143 touch(self.settings["autoresume_path"]+"remove")
1149 if self.settings.has_key("AUTORESUME") \
1150 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1151 print "Resume point detected, skipping preclean operation..."
1154 if os.path.exists(self.settings["controller_file"]):
1155 cmd("/bin/bash "+self.settings["controller_file"]+\
1156 " preclean","preclean script failed.",env=self.env)
1157 touch(self.settings["autoresume_path"]+"preclean")
1161 raise CatalystError, "Build failed, could not execute preclean"
1164 if self.settings.has_key("AUTORESUME") \
1165 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1166 print "Resume point detected, skipping capture operation..."
1168 """ Capture target in a tarball """
1169 mypath=self.settings["target_path"].split("/")
1170 """ Remove filename from path """
1171 mypath=string.join(mypath[:-1],"/")
1173 """ Now make sure path exists """
1174 if not os.path.exists(mypath):
1177 print "Creating stage tarball..."
1179 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1180 self.settings["stage_path"]+" .",\
1181 "Couldn't create stage tarball",env=self.env)
1183 self.gen_contents_file(self.settings["target_path"])
1184 self.gen_digest_file(self.settings["target_path"])
1186 touch(self.settings["autoresume_path"]+"capture")
1188 def run_local(self):
1189 if self.settings.has_key("AUTORESUME") \
1190 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1191 print "Resume point detected, skipping run_local operation..."
1194 if os.path.exists(self.settings["controller_file"]):
1195 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1196 "run script failed.",env=self.env)
1197 touch(self.settings["autoresume_path"]+"run_local")
1199 except CatalystError:
1201 raise CatalystError,"Stage build aborting due to error."
1203 def setup_environment(self):
1205 Modify the current environment. This is an ugly hack that should be
1206 fixed. We need this to use the os.system() call since we can't
1207 specify our own environ
1209 for x in self.settings.keys():
1210 """ Sanitize var names by doing "s|/-.|_|g" """
1211 varname="clst_"+string.replace(x,"/","_")
1212 varname=string.replace(varname,"-","_")
1213 varname=string.replace(varname,".","_")
1214 if type(self.settings[x])==types.StringType:
1215 """ Prefix to prevent namespace clashes """
1216 #os.environ[varname]=self.settings[x]
1217 self.env[varname]=self.settings[x]
1218 elif type(self.settings[x])==types.ListType:
1219 #os.environ[varname]=string.join(self.settings[x])
1220 self.env[varname]=string.join(self.settings[x])
1221 elif type(self.settings[x])==types.BooleanType:
1222 if self.settings[x]:
1223 self.env[varname]="true"
1225 self.env[varname]="false"
1226 if self.settings.has_key("makeopts"):
1227 self.env["MAKEOPTS"]=self.settings["makeopts"]
1230 self.chroot_lock.write_lock()
1232 """ Kill any pids in the chroot "" """
1233 self.kill_chroot_pids()
1235 """ Check for mounts right away and abort if we cannot unmount them """
1236 self.mount_safety_check()
1238 if self.settings.has_key("CLEAR_AUTORESUME"):
1239 self.clear_autoresume()
1241 if self.settings.has_key("PURGETMPONLY"):
1245 if self.settings.has_key("PURGEONLY"):
1249 if self.settings.has_key("PURGE"):
1252 for x in self.settings["action_sequence"]:
1253 print "--- Running action sequence: "+x
1256 apply(getattr(self,x))
1258 self.mount_safety_check()
1261 self.chroot_lock.unlock()
1264 if self.settings.has_key("AUTORESUME") \
1265 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1266 print "Resume point detected, skipping unmerge operation..."
1268 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1269 if type(self.settings[self.settings["spec_prefix"]+\
1270 "/unmerge"])==types.StringType:
1271 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1272 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1274 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1276 for x in range(0,len(myunmerge)):
1278 Surround args with quotes for passing to bash, allows
1279 things like "<" to remain intact
1281 myunmerge[x]="'"+myunmerge[x]+"'"
1282 myunmerge=string.join(myunmerge)
1284 """ Before cleaning, unmerge stuff """
1286 cmd("/bin/bash "+self.settings["controller_file"]+\
1287 " unmerge "+ myunmerge,"Unmerge script failed.",\
1289 print "unmerge shell script"
1290 except CatalystError:
1293 touch(self.settings["autoresume_path"]+"unmerge")
1295 def target_setup(self):
1296 if self.settings.has_key("AUTORESUME") \
1297 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1298 print "Resume point detected, skipping target_setup operation..."
1300 print "Setting up filesystems per filesystem type"
1301 cmd("/bin/bash "+self.settings["controller_file"]+\
1302 " target_image_setup "+ self.settings["target_path"],\
1303 "target_image_setup script failed.",env=self.env)
1304 touch(self.settings["autoresume_path"]+"target_setup")
1306 def setup_overlay(self):
1307 if self.settings.has_key("AUTORESUME") \
1308 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1309 print "Resume point detected, skipping setup_overlay operation..."
1311 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1312 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1313 if os.path.exists(x):
1314 cmd("rsync -a "+x+"/ "+\
1315 self.settings["target_path"],\
1316 self.settings["spec_prefix"]+"overlay: "+x+\
1317 " copy failed.",env=self.env)
1318 touch(self.settings["autoresume_path"]+"setup_overlay")
1320 def create_iso(self):
1321 if self.settings.has_key("AUTORESUME") \
1322 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1323 print "Resume point detected, skipping create_iso operation..."
1325 """ Create the ISO """
1326 if self.settings.has_key("iso"):
1327 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1328 self.settings["iso"],"ISO creation script failed.",\
1330 self.gen_contents_file(self.settings["iso"])
1331 self.gen_digest_file(self.settings["iso"])
1332 touch(self.settings["autoresume_path"]+"create_iso")
1334 print "WARNING: livecd/iso was not defined."
1335 print "An ISO Image will not be created."
1337 def build_packages(self):
1338 if self.settings.has_key("AUTORESUME") \
1339 and os.path.exists(self.settings["autoresume_path"]+\
1341 print "Resume point detected, skipping build_packages operation..."
1343 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1344 if self.settings.has_key("AUTORESUME") \
1345 and os.path.exists(self.settings["autoresume_path"]+\
1347 print "Resume point detected, skipping build_packages operation..."
1350 list_bashify(self.settings[self.settings["spec_prefix"]\
1353 cmd("/bin/bash "+self.settings["controller_file"]+\
1354 " build_packages "+mypack,\
1355 "Error in attempt to build packages",env=self.env)
1356 touch(self.settings["autoresume_path"]+"build_packages")
1357 except CatalystError:
1359 raise CatalystError,self.settings["spec_prefix"]+\
1360 "build aborting due to error."
1362 def build_kernel(self):
1363 if self.settings.has_key("AUTORESUME") \
1364 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1365 print "Resume point detected, skipping build_kernel operation..."
1367 if self.settings.has_key("boot/kernel"):
1369 mynames=self.settings["boot/kernel"]
1370 if type(mynames)==types.StringType:
1373 Execute the script that sets up the kernel build environment
1375 cmd("/bin/bash "+self.settings["controller_file"]+\
1376 " pre-kmerge ","Runscript pre-kmerge failed",\
1379 for kname in mynames:
1380 if self.settings.has_key("AUTORESUME") \
1381 and os.path.exists(self.settings["autoresume_path"]\
1382 +"build_kernel_"+kname):
1383 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1384 else: # TODO: make this not require a kernel config
1386 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1388 raise CatalystError,\
1389 "Can't find kernel config: "+\
1390 self.settings["boot/kernel/"+kname+\
1394 raise CatalystError,\
1395 "Required value boot/kernel/config not specified"
1398 cmd("cp "+self.settings["boot/kernel/"+kname+\
1400 self.settings["chroot_path"]+"/var/tmp/"+\
1402 "Couldn't copy kernel config: "+\
1403 self.settings["boot/kernel/"+kname+\
1404 "/config"],env=self.env)
1406 except CatalystError:
1410 If we need to pass special options to the bootloader
1411 for this kernel put them into the environment
1413 if self.settings.has_key("boot/kernel/"+kname+\
1415 myopts=self.settings["boot/kernel/"+kname+\
1418 if type(myopts) != types.StringType:
1419 myopts = string.join(myopts)
1420 self.env[kname+"_kernelopts"]=myopts
1423 self.env[kname+"_kernelopts"]=""
1425 if not self.settings.has_key("boot/kernel/"+kname+\
1427 self.settings["boot/kernel/"+kname+\
1430 self.env["clst_kextraversion"]=\
1431 self.settings["boot/kernel/"+kname+\
1434 if self.settings.has_key("boot/kernel/"+kname+\
1435 "/initramfs_overlay"):
1436 if os.path.exists(self.settings["boot/kernel/"+\
1437 kname+"/initramfs_overlay"]):
1438 print "Copying initramfs_overlay dir "+\
1439 self.settings["boot/kernel/"+kname+\
1440 "/initramfs_overlay"]
1443 self.settings["chroot_path"]+\
1444 "/tmp/initramfs_overlay/"+\
1445 self.settings["boot/kernel/"+kname+\
1446 "/initramfs_overlay"],env=self.env)
1448 cmd("cp -R "+self.settings["boot/kernel/"+\
1449 kname+"/initramfs_overlay"]+"/* "+\
1450 self.settings["chroot_path"]+\
1451 "/tmp/initramfs_overlay/"+\
1452 self.settings["boot/kernel/"+kname+\
1453 "/initramfs_overlay"],env=self.env)
1455 """ Execute the script that builds the kernel """
1456 cmd("/bin/bash "+self.settings["controller_file"]+\
1458 "Runscript kernel build failed",env=self.env)
1460 if self.settings.has_key("boot/kernel/"+kname+\
1461 "/initramfs_overlay"):
1462 if os.path.exists(self.settings["chroot_path"]+\
1463 "/tmp/initramfs_overlay/"):
1464 print "Cleaning up temporary overlay dir"
1465 cmd("rm -R "+self.settings["chroot_path"]+\
1466 "/tmp/initramfs_overlay/",env=self.env)
1468 touch(self.settings["autoresume_path"]+\
1469 "build_kernel_"+kname)
1472 Execute the script that cleans up the kernel build
1475 cmd("/bin/bash "+self.settings["controller_file"]+\
1477 "Runscript post-kmerge failed",env=self.env)
1479 touch(self.settings["autoresume_path"]+"build_kernel")
1481 except CatalystError:
1483 raise CatalystError,\
1484 "build aborting due to kernel build error."
1486 def bootloader(self):
1487 if self.settings.has_key("AUTORESUME") \
1488 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1489 print "Resume point detected, skipping bootloader operation..."
1492 cmd("/bin/bash "+self.settings["controller_file"]+\
1493 " bootloader " + self.settings["target_path"],\
1494 "Bootloader script failed.",env=self.env)
1495 touch(self.settings["autoresume_path"]+"bootloader")
1496 except CatalystError:
1498 raise CatalystError,"Script aborting due to error."
1500 def livecd_update(self):
1501 if self.settings.has_key("AUTORESUME") \
1502 and os.path.exists(self.settings["autoresume_path"]+\
1504 print "Resume point detected, skipping build_packages operation..."
1507 cmd("/bin/bash "+self.settings["controller_file"]+\
1508 " livecd-update","livecd-update failed.",env=self.env)
1509 touch(self.settings["autoresume_path"]+"livecd_update")
1511 except CatalystError:
1513 raise CatalystError,"build aborting due to livecd_update error."
1515 def clear_chroot(self):
1516 myemp=self.settings["chroot_path"]
1517 if os.path.isdir(myemp):
1518 print "Emptying directory",myemp
1520 stat the dir, delete the dir, recreate the dir and set
1521 the proper perms and ownership
1523 mystat=os.stat(myemp)
1524 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1525 """ There's no easy way to change flags recursively in python """
1526 if os.uname()[0] == "FreeBSD":
1527 os.system("chflags -R noschg "+myemp)
1528 shutil.rmtree(myemp)
1529 os.makedirs(myemp,0755)
1530 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1531 os.chmod(myemp,mystat[ST_MODE])
1533 def clear_packages(self):
1534 if self.settings.has_key("PKGCACHE"):
1535 print "purging the pkgcache ..."
1537 myemp=self.settings["pkgcache_path"]
1538 if os.path.isdir(myemp):
1539 print "Emptying directory",myemp
1541 stat the dir, delete the dir, recreate the dir and set
1542 the proper perms and ownership
1544 mystat=os.stat(myemp)
1545 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1546 shutil.rmtree(myemp)
1547 os.makedirs(myemp,0755)
1548 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1549 os.chmod(myemp,mystat[ST_MODE])
1551 def clear_kerncache(self):
1552 if self.settings.has_key("KERNCACHE"):
1553 print "purging the kerncache ..."
1555 myemp=self.settings["kerncache_path"]
1556 if os.path.isdir(myemp):
1557 print "Emptying directory",myemp
1559 stat the dir, delete the dir, recreate the dir and set
1560 the proper perms and ownership
1562 mystat=os.stat(myemp)
1563 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1564 shutil.rmtree(myemp)
1565 os.makedirs(myemp,0755)
1566 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1567 os.chmod(myemp,mystat[ST_MODE])
1569 def clear_autoresume(self):
1570 """ Clean resume points since they are no longer needed """
1571 if self.settings.has_key("AUTORESUME"):
1572 print "Removing AutoResume Points: ..."
1573 myemp=self.settings["autoresume_path"]
1574 if os.path.isdir(myemp):
1575 if self.settings.has_key("AUTORESUME"):
1576 print "Emptying directory",myemp
1578 stat the dir, delete the dir, recreate the dir and set
1579 the proper perms and ownership
1581 mystat=os.stat(myemp)
1582 if os.uname()[0] == "FreeBSD":
1583 cmd("chflags -R noschg "+myemp,\
1584 "Could not remove immutable flag for file "\
1586 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1587 shutil.rmtree(myemp)
1588 os.makedirs(myemp,0755)
1589 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1590 os.chmod(myemp,mystat[ST_MODE])
1592 def gen_contents_file(self,file):
1593 if os.path.exists(file+".CONTENTS"):
1594 os.remove(file+".CONTENTS")
1595 if self.settings.has_key("contents"):
1596 if os.path.exists(file):
1597 myf=open(file+".CONTENTS","w")
1599 for i in self.settings["contents"].split():
1604 contents=generate_contents(file,contents_function=j,\
1605 verbose=self.settings.has_key("VERBOSE"))
1610 def gen_digest_file(self,file):
1611 if os.path.exists(file+".DIGESTS"):
1612 os.remove(file+".DIGESTS")
1613 if self.settings.has_key("digests"):
1614 if os.path.exists(file):
1615 myf=open(file+".DIGESTS","w")
1617 for i in self.settings["digests"].split():
1621 for f in [file, file+'.CONTENTS']:
1622 if os.path.exists(f):
1624 for k in hash_map.keys():
1625 hash=generate_hash(f,hash_function=k,verbose=\
1626 self.settings.has_key("VERBOSE"))
1630 hash=generate_hash(f,hash_function=j,verbose=\
1631 self.settings.has_key("VERBOSE"))
1636 countdown(10,"Purging Caches ...")
1637 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY") or self.settings.has_key("PURGETMPONLY"):
1638 print "clearing autoresume ..."
1639 self.clear_autoresume()
1641 print "clearing chroot ..."
1644 if not self.settings.has_key("PURGETMPONLY"):
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