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)
976 Copy over /etc/hosts from the host in case there are any
979 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
980 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
981 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
982 "Could not backup /etc/hosts",env=self.env)
983 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
984 "Could not copy /etc/hosts",env=self.env)
986 """ Modify and write out make.conf (for the chroot) """
987 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
988 "Could not remove "+self.settings["chroot_path"]+\
989 "/etc/make.conf",env=self.env)
990 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
991 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
992 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
993 if self.settings.has_key("CFLAGS"):
994 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
995 if self.settings.has_key("CXXFLAGS"):
996 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
997 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
999 myf.write('CXXFLAGS="${CFLAGS}"\n')
1001 myf.write('CXXFLAGS="${CFLAGS}"\n')
1003 if self.settings.has_key("LDFLAGS"):
1004 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1005 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1006 if self.settings.has_key("CBUILD"):
1007 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")
1008 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1010 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")
1011 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1013 """ Figure out what our USE vars are for building """
1015 if self.settings.has_key("HOSTUSE"):
1016 myusevars.extend(self.settings["HOSTUSE"])
1018 if self.settings.has_key("use"):
1019 myusevars.extend(self.settings["use"])
1022 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1023 myusevars = sorted(set(myusevars))
1024 myf.write('USE="'+string.join(myusevars)+'"\n')
1025 if '-*' in myusevars:
1026 print "\nWarning!!! "
1027 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1028 "/use will cause portage to ignore"
1029 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1031 """ Setup the portage overlay """
1032 if self.settings.has_key("portage_overlay"):
1033 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1036 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1037 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1038 "Could not backup /etc/make.conf",env=self.env)
1039 touch(self.settings["autoresume_path"]+"chroot_setup")
1042 if self.settings.has_key("AUTORESUME") \
1043 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1044 print "Resume point detected, skipping fsscript operation..."
1046 if self.settings.has_key("fsscript"):
1047 if os.path.exists(self.settings["controller_file"]):
1048 cmd("/bin/bash "+self.settings["controller_file"]+\
1049 " fsscript","fsscript script failed.",env=self.env)
1050 touch(self.settings["autoresume_path"]+"fsscript")
1053 if self.settings.has_key("AUTORESUME") \
1054 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1055 print "Resume point detected, skipping rcupdate operation..."
1057 if os.path.exists(self.settings["controller_file"]):
1058 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1059 "rc-update script failed.",env=self.env)
1060 touch(self.settings["autoresume_path"]+"rcupdate")
1063 if self.settings.has_key("AUTORESUME") \
1064 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1065 print "Resume point detected, skipping clean operation..."
1067 for x in self.settings["cleanables"]:
1068 print "Cleaning chroot: "+x+"... "
1069 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1072 """ Put /etc/hosts back into place """
1073 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1074 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1075 self.settings["chroot_path"]+"/etc/hosts",\
1076 "Could not replace /etc/hosts",env=self.env)
1078 """ Remove our overlay """
1079 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1080 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1081 "Could not remove /usr/local/portage",env=self.env)
1082 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1084 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1086 """ Clean up old and obsoleted files in /etc """
1087 if os.path.exists(self.settings["stage_path"]+"/etc"):
1088 cmd("find "+self.settings["stage_path"]+\
1089 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1090 "Could not remove stray files in /etc",env=self.env)
1092 if os.path.exists(self.settings["controller_file"]):
1093 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1094 "clean script failed.",env=self.env)
1095 touch(self.settings["autoresume_path"]+"clean")
1098 if self.settings.has_key("AUTORESUME") \
1099 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1100 print "Resume point detected, skipping empty operation..."
1102 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1103 if type(self.settings[self.settings["spec_prefix"]+\
1104 "/empty"])==types.StringType:
1105 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1106 self.settings[self.settings["spec_prefix"]+\
1108 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1109 myemp=self.settings["destpath"]+x
1110 if not os.path.isdir(myemp):
1111 print x,"not a directory or does not exist, skipping 'empty' operation."
1113 print "Emptying directory",x
1115 stat the dir, delete the dir, recreate the dir and set
1116 the proper perms and ownership
1118 mystat=os.stat(myemp)
1119 shutil.rmtree(myemp)
1120 os.makedirs(myemp,0755)
1121 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1122 os.chmod(myemp,mystat[ST_MODE])
1123 touch(self.settings["autoresume_path"]+"empty")
1126 if self.settings.has_key("AUTORESUME") \
1127 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1128 print "Resume point detected, skipping remove operation..."
1130 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1131 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1133 We're going to shell out for all these cleaning
1134 operations, so we get easy glob handling.
1136 print "livecd: removing "+x
1137 os.system("rm -rf "+self.settings["chroot_path"]+x)
1139 if os.path.exists(self.settings["controller_file"]):
1140 cmd("/bin/bash "+self.settings["controller_file"]+\
1141 " clean","Clean failed.",env=self.env)
1142 touch(self.settings["autoresume_path"]+"remove")
1148 if self.settings.has_key("AUTORESUME") \
1149 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1150 print "Resume point detected, skipping preclean operation..."
1153 if os.path.exists(self.settings["controller_file"]):
1154 cmd("/bin/bash "+self.settings["controller_file"]+\
1155 " preclean","preclean script failed.",env=self.env)
1156 touch(self.settings["autoresume_path"]+"preclean")
1160 raise CatalystError, "Build failed, could not execute preclean"
1163 if self.settings.has_key("AUTORESUME") \
1164 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1165 print "Resume point detected, skipping capture operation..."
1167 """ Capture target in a tarball """
1168 mypath=self.settings["target_path"].split("/")
1169 """ Remove filename from path """
1170 mypath=string.join(mypath[:-1],"/")
1172 """ Now make sure path exists """
1173 if not os.path.exists(mypath):
1176 print "Creating stage tarball..."
1178 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1179 self.settings["stage_path"]+" .",\
1180 "Couldn't create stage tarball",env=self.env)
1182 self.gen_contents_file(self.settings["target_path"])
1183 self.gen_digest_file(self.settings["target_path"])
1185 touch(self.settings["autoresume_path"]+"capture")
1187 def run_local(self):
1188 if self.settings.has_key("AUTORESUME") \
1189 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1190 print "Resume point detected, skipping run_local operation..."
1193 if os.path.exists(self.settings["controller_file"]):
1194 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1195 "run script failed.",env=self.env)
1196 touch(self.settings["autoresume_path"]+"run_local")
1198 except CatalystError:
1200 raise CatalystError,"Stage build aborting due to error."
1202 def setup_environment(self):
1204 Modify the current environment. This is an ugly hack that should be
1205 fixed. We need this to use the os.system() call since we can't
1206 specify our own environ
1208 for x in self.settings.keys():
1209 """ Sanitize var names by doing "s|/-.|_|g" """
1210 varname="clst_"+string.replace(x,"/","_")
1211 varname=string.replace(varname,"-","_")
1212 varname=string.replace(varname,".","_")
1213 if type(self.settings[x])==types.StringType:
1214 """ Prefix to prevent namespace clashes """
1215 #os.environ[varname]=self.settings[x]
1216 self.env[varname]=self.settings[x]
1217 elif type(self.settings[x])==types.ListType:
1218 #os.environ[varname]=string.join(self.settings[x])
1219 self.env[varname]=string.join(self.settings[x])
1220 elif type(self.settings[x])==types.BooleanType:
1221 if self.settings[x]:
1222 self.env[varname]="true"
1224 self.env[varname]="false"
1225 if self.settings.has_key("makeopts"):
1226 self.env["MAKEOPTS"]=self.settings["makeopts"]
1229 self.chroot_lock.write_lock()
1231 """ Kill any pids in the chroot "" """
1232 self.kill_chroot_pids()
1234 """ Check for mounts right away and abort if we cannot unmount them """
1235 self.mount_safety_check()
1237 if self.settings.has_key("CLEAR_AUTORESUME"):
1238 self.clear_autoresume()
1240 if self.settings.has_key("PURGETMPONLY"):
1244 if self.settings.has_key("PURGEONLY"):
1248 if self.settings.has_key("PURGE"):
1251 for x in self.settings["action_sequence"]:
1252 print "--- Running action sequence: "+x
1255 apply(getattr(self,x))
1257 self.mount_safety_check()
1260 self.chroot_lock.unlock()
1263 if self.settings.has_key("AUTORESUME") \
1264 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1265 print "Resume point detected, skipping unmerge operation..."
1267 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1268 if type(self.settings[self.settings["spec_prefix"]+\
1269 "/unmerge"])==types.StringType:
1270 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1271 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1273 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1275 for x in range(0,len(myunmerge)):
1277 Surround args with quotes for passing to bash, allows
1278 things like "<" to remain intact
1280 myunmerge[x]="'"+myunmerge[x]+"'"
1281 myunmerge=string.join(myunmerge)
1283 """ Before cleaning, unmerge stuff """
1285 cmd("/bin/bash "+self.settings["controller_file"]+\
1286 " unmerge "+ myunmerge,"Unmerge script failed.",\
1288 print "unmerge shell script"
1289 except CatalystError:
1292 touch(self.settings["autoresume_path"]+"unmerge")
1294 def target_setup(self):
1295 if self.settings.has_key("AUTORESUME") \
1296 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1297 print "Resume point detected, skipping target_setup operation..."
1299 print "Setting up filesystems per filesystem type"
1300 cmd("/bin/bash "+self.settings["controller_file"]+\
1301 " target_image_setup "+ self.settings["target_path"],\
1302 "target_image_setup script failed.",env=self.env)
1303 touch(self.settings["autoresume_path"]+"target_setup")
1305 def setup_overlay(self):
1306 if self.settings.has_key("AUTORESUME") \
1307 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1308 print "Resume point detected, skipping setup_overlay operation..."
1310 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1311 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1312 if os.path.exists(x):
1313 cmd("rsync -a "+x+"/ "+\
1314 self.settings["target_path"],\
1315 self.settings["spec_prefix"]+"overlay: "+x+\
1316 " copy failed.",env=self.env)
1317 touch(self.settings["autoresume_path"]+"setup_overlay")
1319 def create_iso(self):
1320 if self.settings.has_key("AUTORESUME") \
1321 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1322 print "Resume point detected, skipping create_iso operation..."
1324 """ Create the ISO """
1325 if self.settings.has_key("iso"):
1326 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1327 self.settings["iso"],"ISO creation script failed.",\
1329 self.gen_contents_file(self.settings["iso"])
1330 self.gen_digest_file(self.settings["iso"])
1331 touch(self.settings["autoresume_path"]+"create_iso")
1333 print "WARNING: livecd/iso was not defined."
1334 print "An ISO Image will not be created."
1336 def build_packages(self):
1337 if self.settings.has_key("AUTORESUME") \
1338 and os.path.exists(self.settings["autoresume_path"]+\
1340 print "Resume point detected, skipping build_packages operation..."
1342 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1343 if self.settings.has_key("AUTORESUME") \
1344 and os.path.exists(self.settings["autoresume_path"]+\
1346 print "Resume point detected, skipping build_packages operation..."
1349 list_bashify(self.settings[self.settings["spec_prefix"]\
1352 cmd("/bin/bash "+self.settings["controller_file"]+\
1353 " build_packages "+mypack,\
1354 "Error in attempt to build packages",env=self.env)
1355 touch(self.settings["autoresume_path"]+"build_packages")
1356 except CatalystError:
1358 raise CatalystError,self.settings["spec_prefix"]+\
1359 "build aborting due to error."
1361 def build_kernel(self):
1362 if self.settings.has_key("AUTORESUME") \
1363 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1364 print "Resume point detected, skipping build_kernel operation..."
1366 if self.settings.has_key("boot/kernel"):
1368 mynames=self.settings["boot/kernel"]
1369 if type(mynames)==types.StringType:
1372 Execute the script that sets up the kernel build environment
1374 cmd("/bin/bash "+self.settings["controller_file"]+\
1375 " pre-kmerge ","Runscript pre-kmerge failed",\
1378 for kname in mynames:
1379 if self.settings.has_key("AUTORESUME") \
1380 and os.path.exists(self.settings["autoresume_path"]\
1381 +"build_kernel_"+kname):
1382 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1383 else: # TODO: make this not require a kernel config
1385 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1387 raise CatalystError,\
1388 "Can't find kernel config: "+\
1389 self.settings["boot/kernel/"+kname+\
1393 raise CatalystError,\
1394 "Required value boot/kernel/config not specified"
1397 cmd("cp "+self.settings["boot/kernel/"+kname+\
1399 self.settings["chroot_path"]+"/var/tmp/"+\
1401 "Couldn't copy kernel config: "+\
1402 self.settings["boot/kernel/"+kname+\
1403 "/config"],env=self.env)
1405 except CatalystError:
1409 If we need to pass special options to the bootloader
1410 for this kernel put them into the environment
1412 if self.settings.has_key("boot/kernel/"+kname+\
1414 myopts=self.settings["boot/kernel/"+kname+\
1417 if type(myopts) != types.StringType:
1418 myopts = string.join(myopts)
1419 self.env[kname+"_kernelopts"]=myopts
1422 self.env[kname+"_kernelopts"]=""
1424 if not self.settings.has_key("boot/kernel/"+kname+\
1426 self.settings["boot/kernel/"+kname+\
1429 self.env["clst_kextraversion"]=\
1430 self.settings["boot/kernel/"+kname+\
1433 if self.settings.has_key("boot/kernel/"+kname+\
1434 "/initramfs_overlay"):
1435 if os.path.exists(self.settings["boot/kernel/"+\
1436 kname+"/initramfs_overlay"]):
1437 print "Copying initramfs_overlay dir "+\
1438 self.settings["boot/kernel/"+kname+\
1439 "/initramfs_overlay"]
1442 self.settings["chroot_path"]+\
1443 "/tmp/initramfs_overlay/"+\
1444 self.settings["boot/kernel/"+kname+\
1445 "/initramfs_overlay"],env=self.env)
1447 cmd("cp -R "+self.settings["boot/kernel/"+\
1448 kname+"/initramfs_overlay"]+"/* "+\
1449 self.settings["chroot_path"]+\
1450 "/tmp/initramfs_overlay/"+\
1451 self.settings["boot/kernel/"+kname+\
1452 "/initramfs_overlay"],env=self.env)
1454 """ Execute the script that builds the kernel """
1455 cmd("/bin/bash "+self.settings["controller_file"]+\
1457 "Runscript kernel build failed",env=self.env)
1459 if self.settings.has_key("boot/kernel/"+kname+\
1460 "/initramfs_overlay"):
1461 if os.path.exists(self.settings["chroot_path"]+\
1462 "/tmp/initramfs_overlay/"):
1463 print "Cleaning up temporary overlay dir"
1464 cmd("rm -R "+self.settings["chroot_path"]+\
1465 "/tmp/initramfs_overlay/",env=self.env)
1467 touch(self.settings["autoresume_path"]+\
1468 "build_kernel_"+kname)
1471 Execute the script that cleans up the kernel build
1474 cmd("/bin/bash "+self.settings["controller_file"]+\
1476 "Runscript post-kmerge failed",env=self.env)
1478 touch(self.settings["autoresume_path"]+"build_kernel")
1480 except CatalystError:
1482 raise CatalystError,\
1483 "build aborting due to kernel build error."
1485 def bootloader(self):
1486 if self.settings.has_key("AUTORESUME") \
1487 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1488 print "Resume point detected, skipping bootloader operation..."
1491 cmd("/bin/bash "+self.settings["controller_file"]+\
1492 " bootloader " + self.settings["target_path"],\
1493 "Bootloader script failed.",env=self.env)
1494 touch(self.settings["autoresume_path"]+"bootloader")
1495 except CatalystError:
1497 raise CatalystError,"Script aborting due to error."
1499 def livecd_update(self):
1500 if self.settings.has_key("AUTORESUME") \
1501 and os.path.exists(self.settings["autoresume_path"]+\
1503 print "Resume point detected, skipping build_packages operation..."
1506 cmd("/bin/bash "+self.settings["controller_file"]+\
1507 " livecd-update","livecd-update failed.",env=self.env)
1508 touch(self.settings["autoresume_path"]+"livecd_update")
1510 except CatalystError:
1512 raise CatalystError,"build aborting due to livecd_update error."
1514 def clear_chroot(self):
1515 myemp=self.settings["chroot_path"]
1516 if os.path.isdir(myemp):
1517 print "Emptying directory",myemp
1519 stat the dir, delete the dir, recreate the dir and set
1520 the proper perms and ownership
1522 mystat=os.stat(myemp)
1523 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1524 """ There's no easy way to change flags recursively in python """
1525 if os.uname()[0] == "FreeBSD":
1526 os.system("chflags -R noschg "+myemp)
1527 shutil.rmtree(myemp)
1528 os.makedirs(myemp,0755)
1529 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1530 os.chmod(myemp,mystat[ST_MODE])
1532 def clear_packages(self):
1533 if self.settings.has_key("PKGCACHE"):
1534 print "purging the pkgcache ..."
1536 myemp=self.settings["pkgcache_path"]
1537 if os.path.isdir(myemp):
1538 print "Emptying directory",myemp
1540 stat the dir, delete the dir, recreate the dir and set
1541 the proper perms and ownership
1543 mystat=os.stat(myemp)
1544 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1545 shutil.rmtree(myemp)
1546 os.makedirs(myemp,0755)
1547 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1548 os.chmod(myemp,mystat[ST_MODE])
1550 def clear_kerncache(self):
1551 if self.settings.has_key("KERNCACHE"):
1552 print "purging the kerncache ..."
1554 myemp=self.settings["kerncache_path"]
1555 if os.path.isdir(myemp):
1556 print "Emptying directory",myemp
1558 stat the dir, delete the dir, recreate the dir and set
1559 the proper perms and ownership
1561 mystat=os.stat(myemp)
1562 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1563 shutil.rmtree(myemp)
1564 os.makedirs(myemp,0755)
1565 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1566 os.chmod(myemp,mystat[ST_MODE])
1568 def clear_autoresume(self):
1569 """ Clean resume points since they are no longer needed """
1570 if self.settings.has_key("AUTORESUME"):
1571 print "Removing AutoResume Points: ..."
1572 myemp=self.settings["autoresume_path"]
1573 if os.path.isdir(myemp):
1574 if self.settings.has_key("AUTORESUME"):
1575 print "Emptying directory",myemp
1577 stat the dir, delete the dir, recreate the dir and set
1578 the proper perms and ownership
1580 mystat=os.stat(myemp)
1581 if os.uname()[0] == "FreeBSD":
1582 cmd("chflags -R noschg "+myemp,\
1583 "Could not remove immutable flag for file "\
1585 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1586 shutil.rmtree(myemp)
1587 os.makedirs(myemp,0755)
1588 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1589 os.chmod(myemp,mystat[ST_MODE])
1591 def gen_contents_file(self,file):
1592 if os.path.exists(file+".CONTENTS"):
1593 os.remove(file+".CONTENTS")
1594 if self.settings.has_key("contents"):
1595 if os.path.exists(file):
1596 myf=open(file+".CONTENTS","w")
1598 for i in self.settings["contents"].split():
1603 contents=generate_contents(file,contents_function=j,\
1604 verbose=self.settings.has_key("VERBOSE"))
1609 def gen_digest_file(self,file):
1610 if os.path.exists(file+".DIGESTS"):
1611 os.remove(file+".DIGESTS")
1612 if self.settings.has_key("digests"):
1613 if os.path.exists(file):
1614 myf=open(file+".DIGESTS","w")
1616 for i in self.settings["digests"].split():
1620 for f in [file, file+'.CONTENTS']:
1621 if os.path.exists(f):
1623 for k in hash_map.keys():
1624 hash=generate_hash(f,hash_function=k,verbose=\
1625 self.settings.has_key("VERBOSE"))
1629 hash=generate_hash(f,hash_function=j,verbose=\
1630 self.settings.has_key("VERBOSE"))
1635 countdown(10,"Purging Caches ...")
1636 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY") or self.settings.has_key("PURGETMPONLY"):
1637 print "clearing autoresume ..."
1638 self.clear_autoresume()
1640 print "clearing chroot ..."
1643 if not self.settings.has_key("PURGETMPONLY"):
1644 print "clearing package cache ..."
1645 self.clear_packages()
1647 print "clearing kerncache ..."
1648 self.clear_kerncache()
1650 # vim: ts=4 sw=4 sta et sts=4 ai