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/make.profile",\
817 "Error zapping profile link",env=self.env)
818 cmd("ln -sf ../usr/portage/profiles/"+\
819 self.settings["target_profile"]+" "+\
820 self.settings["chroot_path"]+"/etc/make.profile",\
821 "Error creating profile link",env=self.env)
822 touch(self.settings["autoresume_path"]+"config_profile_link")
824 def setup_confdir(self):
825 if self.settings.has_key("AUTORESUME") \
826 and os.path.exists(self.settings["autoresume_path"]+\
828 print "Resume point detected, skipping setup_confdir operation..."
830 if self.settings.has_key("portage_confdir"):
831 print "Configuring /etc/portage..."
832 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
833 "Error zapping /etc/portage",env=self.env)
834 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
835 self.settings["chroot_path"]+"/etc/portage",\
836 "Error copying /etc/portage",env=self.env)
837 touch(self.settings["autoresume_path"]+"setup_confdir")
839 def portage_overlay(self):
840 """ We copy the contents of our overlays to /usr/local/portage """
841 if self.settings.has_key("portage_overlay"):
842 for x in self.settings["portage_overlay"]:
843 if os.path.exists(x):
844 print "Copying overlay dir " +x
845 cmd("mkdir -p "+self.settings["chroot_path"]+\
846 "/usr/local/portage",\
847 "Could not make portage_overlay dir",env=self.env)
848 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
849 "/usr/local/portage",\
850 "Could not copy portage_overlay",env=self.env)
852 def root_overlay(self):
853 """ Copy over the root_overlay """
854 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
855 for x in self.settings[self.settings["spec_prefix"]+\
857 if os.path.exists(x):
858 print "Copying root_overlay: "+x
859 cmd("rsync -a "+x+"/ "+\
860 self.settings["chroot_path"],\
861 self.settings["spec_prefix"]+"/root_overlay: "+x+\
862 " copy failed.",env=self.env)
868 for x in self.mounts:
869 if not os.path.exists(self.settings["chroot_path"]+x):
870 os.makedirs(self.settings["chroot_path"]+x,0755)
872 if not os.path.exists(self.mountmap[x]):
873 os.makedirs(self.mountmap[x],0755)
876 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
877 self.snapshot_lock_object.read_lock()
878 if os.uname()[0] == "FreeBSD":
880 retval=os.system("mount -t devfs none "+\
881 self.settings["chroot_path"]+x)
883 retval=os.system("mount_nullfs "+src+" "+\
884 self.settings["chroot_path"]+x)
886 retval=os.system("mount --bind "+src+" "+\
887 self.settings["chroot_path"]+x)
890 raise CatalystError,"Couldn't bind mount "+src
894 mypath=self.settings["chroot_path"]
895 myrevmounts=self.mounts[:]
896 myrevmounts.reverse()
897 """ Unmount in reverse order for nested bind-mounts """
898 for x in myrevmounts:
899 if not os.path.exists(mypath+x):
902 if not ismount(mypath+x):
905 retval=os.system("umount "+\
906 os.path.join(mypath,x.lstrip(os.path.sep)))
909 warn("First attempt to unmount: "+mypath+x+" failed.")
910 warn("Killing any pids still running in the chroot")
912 self.kill_chroot_pids()
914 retval2=os.system("umount "+mypath+x)
917 warn("Couldn't umount bind mount: "+mypath+x)
919 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
922 It's possible the snapshot lock object isn't created yet.
923 This is because mount safety check calls unbind before the
924 target is fully initialized
926 self.snapshot_lock_object.unlock()
931 if any bind mounts really failed, then we need to raise
932 this to potentially prevent an upcoming bash stage cleanup script
933 from wiping our bind mounts.
935 raise CatalystError,\
936 "Couldn't umount one or more bind-mounts; aborting for safety."
938 def chroot_setup(self):
939 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
941 self.override_cbuild()
942 self.override_chost()
943 self.override_cflags()
944 self.override_cxxflags()
945 self.override_ldflags()
946 if self.settings.has_key("AUTORESUME") \
947 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
948 print "Resume point detected, skipping chroot_setup operation..."
950 print "Setting up chroot..."
952 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
954 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
955 "Could not copy resolv.conf into place.",env=self.env)
957 """ Copy over the envscript, if applicable """
958 if self.settings.has_key("ENVSCRIPT"):
959 if not os.path.exists(self.settings["ENVSCRIPT"]):
960 raise CatalystError,\
961 "Can't find envscript "+self.settings["ENVSCRIPT"]
963 print "\nWarning!!!!"
964 print "\tOverriding certain env variables may cause catastrophic failure."
965 print "\tIf your build fails look here first as the possible problem."
966 print "\tCatalyst assumes you know what you are doing when setting"
967 print "\t\tthese variables."
968 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
969 print "\tYou have been warned\n"
971 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
972 self.settings["chroot_path"]+"/tmp/envscript",\
973 "Could not copy envscript into place.",env=self.env)
975 """ Setup metadata_overlay """
976 if self.settings.has_key("METADATA_OVERLAY") \
977 and not self.settings.has_key("portage_confdir"):
978 if not os.path.exists(self.settings["chroot_path"]+\
980 cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
981 myf=open(self.settings["chroot_path"]+\
982 "/etc/portage/modules","a")
983 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
988 Copy over /etc/hosts from the host in case there are any
991 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
992 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
993 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
994 "Could not backup /etc/hosts",env=self.env)
995 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
996 "Could not copy /etc/hosts",env=self.env)
998 """ Modify and write out make.conf (for the chroot) """
999 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
1000 "Could not remove "+self.settings["chroot_path"]+\
1001 "/etc/make.conf",env=self.env)
1002 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1003 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1004 myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1005 if self.settings.has_key("CFLAGS"):
1006 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1007 if self.settings.has_key("CXXFLAGS"):
1008 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1010 myf.write('CXXFLAGS="${CFLAGS}"\n')
1012 if self.settings.has_key("LDFLAGS"):
1013 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1014 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1015 if self.settings.has_key("CBUILD"):
1016 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")
1017 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1019 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")
1020 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1022 """ Figure out what our USE vars are for building """
1024 if self.settings.has_key("HOSTUSE"):
1025 myusevars.extend(self.settings["HOSTUSE"])
1027 if self.settings.has_key("use"):
1028 myusevars.extend(self.settings["use"])
1031 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1032 myusevars = sorted(set(myusevars))
1033 myf.write('USE="'+string.join(myusevars)+'"\n')
1034 if '-*' in myusevars:
1035 print "\nWarning!!! "
1036 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1037 "/use will cause portage to ignore"
1038 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1040 """ Setup the portage overlay """
1041 if self.settings.has_key("portage_overlay"):
1042 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1045 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1046 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1047 "Could not backup /etc/make.conf",env=self.env)
1048 touch(self.settings["autoresume_path"]+"chroot_setup")
1051 if self.settings.has_key("AUTORESUME") \
1052 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1053 print "Resume point detected, skipping fsscript operation..."
1055 if self.settings.has_key("fsscript"):
1056 if os.path.exists(self.settings["controller_file"]):
1057 cmd("/bin/bash "+self.settings["controller_file"]+\
1058 " fsscript","fsscript script failed.",env=self.env)
1059 touch(self.settings["autoresume_path"]+"fsscript")
1062 if self.settings.has_key("AUTORESUME") \
1063 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1064 print "Resume point detected, skipping rcupdate operation..."
1066 if os.path.exists(self.settings["controller_file"]):
1067 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1068 "rc-update script failed.",env=self.env)
1069 touch(self.settings["autoresume_path"]+"rcupdate")
1072 if self.settings.has_key("AUTORESUME") \
1073 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1074 print "Resume point detected, skipping clean operation..."
1076 for x in self.settings["cleanables"]:
1077 print "Cleaning chroot: "+x+"... "
1078 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1081 """ Put /etc/hosts back into place """
1082 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1083 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1084 self.settings["chroot_path"]+"/etc/hosts",\
1085 "Could not replace /etc/hosts",env=self.env)
1087 """ Remove our overlay """
1088 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1089 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1090 "Could not remove /usr/local/portage",env=self.env)
1091 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1093 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1095 """ Clean up old and obsoleted files in /etc """
1096 if os.path.exists(self.settings["stage_path"]+"/etc"):
1097 cmd("find "+self.settings["stage_path"]+\
1098 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1099 "Could not remove stray files in /etc",env=self.env)
1101 if os.path.exists(self.settings["controller_file"]):
1102 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1103 "clean script failed.",env=self.env)
1104 touch(self.settings["autoresume_path"]+"clean")
1107 if self.settings.has_key("AUTORESUME") \
1108 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1109 print "Resume point detected, skipping empty operation..."
1111 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1112 if type(self.settings[self.settings["spec_prefix"]+\
1113 "/empty"])==types.StringType:
1114 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1115 self.settings[self.settings["spec_prefix"]+\
1117 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1118 myemp=self.settings["destpath"]+x
1119 if not os.path.isdir(myemp):
1120 print x,"not a directory or does not exist, skipping 'empty' operation."
1122 print "Emptying directory",x
1124 stat the dir, delete the dir, recreate the dir and set
1125 the proper perms and ownership
1127 mystat=os.stat(myemp)
1128 shutil.rmtree(myemp)
1129 os.makedirs(myemp,0755)
1130 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1131 os.chmod(myemp,mystat[ST_MODE])
1132 touch(self.settings["autoresume_path"]+"empty")
1135 if self.settings.has_key("AUTORESUME") \
1136 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1137 print "Resume point detected, skipping remove operation..."
1139 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1140 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1142 We're going to shell out for all these cleaning
1143 operations, so we get easy glob handling.
1145 print "livecd: removing "+x
1146 os.system("rm -rf "+self.settings["chroot_path"]+x)
1148 if os.path.exists(self.settings["controller_file"]):
1149 cmd("/bin/bash "+self.settings["controller_file"]+\
1150 " clean","Clean failed.",env=self.env)
1151 touch(self.settings["autoresume_path"]+"remove")
1157 if self.settings.has_key("AUTORESUME") \
1158 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1159 print "Resume point detected, skipping preclean operation..."
1162 if os.path.exists(self.settings["controller_file"]):
1163 cmd("/bin/bash "+self.settings["controller_file"]+\
1164 " preclean","preclean script failed.",env=self.env)
1165 touch(self.settings["autoresume_path"]+"preclean")
1169 raise CatalystError, "Build failed, could not execute preclean"
1172 if self.settings.has_key("AUTORESUME") \
1173 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1174 print "Resume point detected, skipping capture operation..."
1176 """ Capture target in a tarball """
1177 mypath=self.settings["target_path"].split("/")
1178 """ Remove filename from path """
1179 mypath=string.join(mypath[:-1],"/")
1181 """ Now make sure path exists """
1182 if not os.path.exists(mypath):
1185 print "Creating stage tarball..."
1187 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1188 self.settings["stage_path"]+" .",\
1189 "Couldn't create stage tarball",env=self.env)
1191 self.gen_contents_file(self.settings["target_path"])
1192 self.gen_digest_file(self.settings["target_path"])
1194 touch(self.settings["autoresume_path"]+"capture")
1196 def run_local(self):
1197 if self.settings.has_key("AUTORESUME") \
1198 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1199 print "Resume point detected, skipping run_local operation..."
1202 if os.path.exists(self.settings["controller_file"]):
1203 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1204 "run script failed.",env=self.env)
1205 touch(self.settings["autoresume_path"]+"run_local")
1207 except CatalystError:
1209 raise CatalystError,"Stage build aborting due to error."
1211 def setup_environment(self):
1213 Modify the current environment. This is an ugly hack that should be
1214 fixed. We need this to use the os.system() call since we can't
1215 specify our own environ
1217 for x in self.settings.keys():
1218 """ Sanitize var names by doing "s|/-.|_|g" """
1219 varname="clst_"+string.replace(x,"/","_")
1220 varname=string.replace(varname,"-","_")
1221 varname=string.replace(varname,".","_")
1222 if type(self.settings[x])==types.StringType:
1223 """ Prefix to prevent namespace clashes """
1224 #os.environ[varname]=self.settings[x]
1225 self.env[varname]=self.settings[x]
1226 elif type(self.settings[x])==types.ListType:
1227 #os.environ[varname]=string.join(self.settings[x])
1228 self.env[varname]=string.join(self.settings[x])
1229 elif type(self.settings[x])==types.BooleanType:
1230 if self.settings[x]:
1231 self.env[varname]="true"
1233 self.env[varname]="false"
1234 if self.settings.has_key("makeopts"):
1235 self.env["MAKEOPTS"]=self.settings["makeopts"]
1238 self.chroot_lock.write_lock()
1240 """ Kill any pids in the chroot "" """
1241 self.kill_chroot_pids()
1243 """ Check for mounts right away and abort if we cannot unmount them """
1244 self.mount_safety_check()
1246 if self.settings.has_key("CLEAR_AUTORESUME"):
1247 self.clear_autoresume()
1249 if self.settings.has_key("PURGEONLY"):
1253 if self.settings.has_key("PURGE"):
1256 for x in self.settings["action_sequence"]:
1257 print "--- Running action sequence: "+x
1260 apply(getattr(self,x))
1262 self.mount_safety_check()
1265 self.chroot_lock.unlock()
1268 if self.settings.has_key("AUTORESUME") \
1269 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1270 print "Resume point detected, skipping unmerge operation..."
1272 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1273 if type(self.settings[self.settings["spec_prefix"]+\
1274 "/unmerge"])==types.StringType:
1275 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1276 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1278 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1280 for x in range(0,len(myunmerge)):
1282 Surround args with quotes for passing to bash, allows
1283 things like "<" to remain intact
1285 myunmerge[x]="'"+myunmerge[x]+"'"
1286 myunmerge=string.join(myunmerge)
1288 """ Before cleaning, unmerge stuff """
1290 cmd("/bin/bash "+self.settings["controller_file"]+\
1291 " unmerge "+ myunmerge,"Unmerge script failed.",\
1293 print "unmerge shell script"
1294 except CatalystError:
1297 touch(self.settings["autoresume_path"]+"unmerge")
1299 def target_setup(self):
1300 if self.settings.has_key("AUTORESUME") \
1301 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1302 print "Resume point detected, skipping target_setup operation..."
1304 print "Setting up filesystems per filesystem type"
1305 cmd("/bin/bash "+self.settings["controller_file"]+\
1306 " target_image_setup "+ self.settings["target_path"],\
1307 "target_image_setup script failed.",env=self.env)
1308 touch(self.settings["autoresume_path"]+"target_setup")
1310 def setup_overlay(self):
1311 if self.settings.has_key("AUTORESUME") \
1312 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1313 print "Resume point detected, skipping setup_overlay operation..."
1315 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1316 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1317 if os.path.exists(x):
1318 cmd("rsync -a "+x+"/ "+\
1319 self.settings["target_path"],\
1320 self.settings["spec_prefix"]+"overlay: "+x+\
1321 " copy failed.",env=self.env)
1322 touch(self.settings["autoresume_path"]+"setup_overlay")
1324 def create_iso(self):
1325 if self.settings.has_key("AUTORESUME") \
1326 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1327 print "Resume point detected, skipping create_iso operation..."
1329 """ Create the ISO """
1330 if self.settings.has_key("iso"):
1331 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1332 self.settings["iso"],"ISO creation script failed.",\
1334 self.gen_contents_file(self.settings["iso"])
1335 self.gen_digest_file(self.settings["iso"])
1336 touch(self.settings["autoresume_path"]+"create_iso")
1338 print "WARNING: livecd/iso was not defined."
1339 print "An ISO Image will not be created."
1341 def build_packages(self):
1342 if self.settings.has_key("AUTORESUME") \
1343 and os.path.exists(self.settings["autoresume_path"]+\
1345 print "Resume point detected, skipping build_packages operation..."
1347 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1348 if self.settings.has_key("AUTORESUME") \
1349 and os.path.exists(self.settings["autoresume_path"]+\
1351 print "Resume point detected, skipping build_packages operation..."
1354 list_bashify(self.settings[self.settings["spec_prefix"]\
1357 cmd("/bin/bash "+self.settings["controller_file"]+\
1358 " build_packages "+mypack,\
1359 "Error in attempt to build packages",env=self.env)
1360 touch(self.settings["autoresume_path"]+"build_packages")
1361 except CatalystError:
1363 raise CatalystError,self.settings["spec_prefix"]+\
1364 "build aborting due to error."
1366 def build_kernel(self):
1367 if self.settings.has_key("AUTORESUME") \
1368 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1369 print "Resume point detected, skipping build_kernel operation..."
1371 if self.settings.has_key("boot/kernel"):
1373 mynames=self.settings["boot/kernel"]
1374 if type(mynames)==types.StringType:
1377 Execute the script that sets up the kernel build environment
1379 cmd("/bin/bash "+self.settings["controller_file"]+\
1380 " pre-kmerge ","Runscript pre-kmerge failed",\
1383 for kname in mynames:
1384 if self.settings.has_key("AUTORESUME") \
1385 and os.path.exists(self.settings["autoresume_path"]\
1386 +"build_kernel_"+kname):
1387 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1388 else: # TODO: make this not require a kernel config
1390 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1392 raise CatalystError,\
1393 "Can't find kernel config: "+\
1394 self.settings["boot/kernel/"+kname+\
1398 raise CatalystError,\
1399 "Required value boot/kernel/config not specified"
1402 cmd("cp "+self.settings["boot/kernel/"+kname+\
1404 self.settings["chroot_path"]+"/var/tmp/"+\
1406 "Couldn't copy kernel config: "+\
1407 self.settings["boot/kernel/"+kname+\
1408 "/config"],env=self.env)
1410 except CatalystError:
1414 If we need to pass special options to the bootloader
1415 for this kernel put them into the environment
1417 if self.settings.has_key("boot/kernel/"+kname+\
1419 myopts=self.settings["boot/kernel/"+kname+\
1422 if type(myopts) != types.StringType:
1423 myopts = string.join(myopts)
1424 self.env[kname+"_kernelopts"]=myopts
1427 self.env[kname+"_kernelopts"]=""
1429 if not self.settings.has_key("boot/kernel/"+kname+\
1431 self.settings["boot/kernel/"+kname+\
1434 self.env["clst_kextraversion"]=\
1435 self.settings["boot/kernel/"+kname+\
1438 if self.settings.has_key("boot/kernel/"+kname+\
1439 "/initramfs_overlay"):
1440 if os.path.exists(self.settings["boot/kernel/"+\
1441 kname+"/initramfs_overlay"]):
1442 print "Copying initramfs_overlay dir "+\
1443 self.settings["boot/kernel/"+kname+\
1444 "/initramfs_overlay"]
1447 self.settings["chroot_path"]+\
1448 "/tmp/initramfs_overlay/"+\
1449 self.settings["boot/kernel/"+kname+\
1450 "/initramfs_overlay"],env=self.env)
1452 cmd("cp -R "+self.settings["boot/kernel/"+\
1453 kname+"/initramfs_overlay"]+"/* "+\
1454 self.settings["chroot_path"]+\
1455 "/tmp/initramfs_overlay/"+\
1456 self.settings["boot/kernel/"+kname+\
1457 "/initramfs_overlay"],env=self.env)
1459 """ Execute the script that builds the kernel """
1460 cmd("/bin/bash "+self.settings["controller_file"]+\
1462 "Runscript kernel build failed",env=self.env)
1464 if self.settings.has_key("boot/kernel/"+kname+\
1465 "/initramfs_overlay"):
1466 if os.path.exists(self.settings["chroot_path"]+\
1467 "/tmp/initramfs_overlay/"):
1468 print "Cleaning up temporary overlay dir"
1469 cmd("rm -R "+self.settings["chroot_path"]+\
1470 "/tmp/initramfs_overlay/",env=self.env)
1472 touch(self.settings["autoresume_path"]+\
1473 "build_kernel_"+kname)
1476 Execute the script that cleans up the kernel build
1479 cmd("/bin/bash "+self.settings["controller_file"]+\
1481 "Runscript post-kmerge failed",env=self.env)
1483 touch(self.settings["autoresume_path"]+"build_kernel")
1485 except CatalystError:
1487 raise CatalystError,\
1488 "build aborting due to kernel build error."
1490 def bootloader(self):
1491 if self.settings.has_key("AUTORESUME") \
1492 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1493 print "Resume point detected, skipping bootloader operation..."
1496 cmd("/bin/bash "+self.settings["controller_file"]+\
1497 " bootloader " + self.settings["target_path"],\
1498 "Bootloader script failed.",env=self.env)
1499 touch(self.settings["autoresume_path"]+"bootloader")
1500 except CatalystError:
1502 raise CatalystError,"Script aborting due to error."
1504 def livecd_update(self):
1505 if self.settings.has_key("AUTORESUME") \
1506 and os.path.exists(self.settings["autoresume_path"]+\
1508 print "Resume point detected, skipping build_packages operation..."
1511 cmd("/bin/bash "+self.settings["controller_file"]+\
1512 " livecd-update","livecd-update failed.",env=self.env)
1513 touch(self.settings["autoresume_path"]+"livecd_update")
1515 except CatalystError:
1517 raise CatalystError,"build aborting due to livecd_update error."
1519 def clear_chroot(self):
1520 myemp=self.settings["chroot_path"]
1521 if os.path.isdir(myemp):
1522 print "Emptying directory",myemp
1524 stat the dir, delete the dir, recreate the dir and set
1525 the proper perms and ownership
1527 mystat=os.stat(myemp)
1528 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1529 """ There's no easy way to change flags recursively in python """
1530 if os.uname()[0] == "FreeBSD":
1531 os.system("chflags -R noschg "+myemp)
1532 shutil.rmtree(myemp)
1533 os.makedirs(myemp,0755)
1534 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1535 os.chmod(myemp,mystat[ST_MODE])
1537 def clear_packages(self):
1538 if self.settings.has_key("PKGCACHE"):
1539 print "purging the pkgcache ..."
1541 myemp=self.settings["pkgcache_path"]
1542 if os.path.isdir(myemp):
1543 print "Emptying directory",myemp
1545 stat the dir, delete the dir, recreate the dir and set
1546 the proper perms and ownership
1548 mystat=os.stat(myemp)
1549 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1550 shutil.rmtree(myemp)
1551 os.makedirs(myemp,0755)
1552 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1553 os.chmod(myemp,mystat[ST_MODE])
1555 def clear_kerncache(self):
1556 if self.settings.has_key("KERNCACHE"):
1557 print "purging the kerncache ..."
1559 myemp=self.settings["kerncache_path"]
1560 if os.path.isdir(myemp):
1561 print "Emptying directory",myemp
1563 stat the dir, delete the dir, recreate the dir and set
1564 the proper perms and ownership
1566 mystat=os.stat(myemp)
1567 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1568 shutil.rmtree(myemp)
1569 os.makedirs(myemp,0755)
1570 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1571 os.chmod(myemp,mystat[ST_MODE])
1573 def clear_autoresume(self):
1574 """ Clean resume points since they are no longer needed """
1575 if self.settings.has_key("AUTORESUME"):
1576 print "Removing AutoResume Points: ..."
1577 myemp=self.settings["autoresume_path"]
1578 if os.path.isdir(myemp):
1579 if self.settings.has_key("AUTORESUME"):
1580 print "Emptying directory",myemp
1582 stat the dir, delete the dir, recreate the dir and set
1583 the proper perms and ownership
1585 mystat=os.stat(myemp)
1586 if os.uname()[0] == "FreeBSD":
1587 cmd("chflags -R noschg "+myemp,\
1588 "Could not remove immutable flag for file "\
1590 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1591 shutil.rmtree(myemp)
1592 os.makedirs(myemp,0755)
1593 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1594 os.chmod(myemp,mystat[ST_MODE])
1596 def gen_contents_file(self,file):
1597 if os.path.exists(file+".CONTENTS"):
1598 os.remove(file+".CONTENTS")
1599 if self.settings.has_key("contents"):
1600 if os.path.exists(file):
1601 myf=open(file+".CONTENTS","w")
1603 for i in self.settings["contents"].split():
1608 contents=generate_contents(file,contents_function=j,\
1609 verbose=self.settings.has_key("VERBOSE"))
1614 def gen_digest_file(self,file):
1615 if os.path.exists(file+".DIGESTS"):
1616 os.remove(file+".DIGESTS")
1617 if self.settings.has_key("digests"):
1618 if os.path.exists(file):
1619 myf=open(file+".DIGESTS","w")
1621 for i in self.settings["digests"].split():
1625 for f in [file, file+'.CONTENTS']:
1626 if os.path.exists(f):
1628 for k in hash_map.keys():
1629 hash=generate_hash(f,hash_function=k,verbose=\
1630 self.settings.has_key("VERBOSE"))
1634 hash=generate_hash(f,hash_function=j,verbose=\
1635 self.settings.has_key("VERBOSE"))
1640 countdown(10,"Purging Caches ...")
1641 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY"):
1642 print "clearing autoresume ..."
1643 self.clear_autoresume()
1645 print "clearing chroot ..."
1648 print "clearing package cache ..."
1649 self.clear_packages()
1651 print "clearing kerncache ..."
1652 self.clear_kerncache()
1654 # vim: ts=4 sw=4 sta et sts=4 ai