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 *
14 class generic_stage_target(generic_target):
16 def __init__(self,myspec,addlargs):
17 self.required_values.extend(["version_stamp","target","subarch",\
18 "rel_type","profile","snapshot","source_subpath"])
20 self.valid_values.extend(["version_stamp","target","subarch",\
21 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
22 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
23 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
25 self.set_valid_build_kernel_vars(addlargs)
26 generic_target.__init__(self,myspec,addlargs)
29 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
30 work better with vapier's CBUILD stuff. I've removed the "monolithic"
31 machinemap from this file and split up its contents amongst the
32 various arch/foo.py files.
34 When register() is called on each module in the arch/ dir, it now
35 returns a tuple instead of acting on the subarchmap dict that is
36 passed to it. The tuple contains the values that were previously
37 added to subarchmap as well as a new list of CHOSTs that go along
38 with that arch. This allows us to build machinemap on the fly based
39 on the keys in subarchmap and the values of the 2nd list returned
42 Also, after talking with vapier. I have a slightly better idea of what
43 certain variables are used for and what they should be set to. Neither
44 'buildarch' or 'hostarch' are used directly, so their value doesn't
45 really matter. They are just compared to determine if we are
46 cross-compiling. Because of this, they are just set to the name of the
47 module in arch/ that the subarch is part of to make things simpler.
48 The entire build process is still based off of 'subarch' like it was
55 arches = catalyst.arch.arches()
56 for x in arches.get_arches():
57 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
58 self.subarchmap.update(x.__subarch_map)
59 for machine in x.__machine_map:
60 machinemap[machine] = x
61 for subarch in x.__subarch_map:
62 machinemap[subarch] = x
64 if self.settings.has_key("chost"):
65 hostmachine = self.settings["chost"].split("-")[0]
66 if not machinemap.has_key(hostmachine):
67 raise CatalystError, "Unknown host machine type "+hostmachine
68 self.settings["hostarch"]=machinemap[hostmachine]
70 hostmachine = self.settings["subarch"]
71 if machinemap.has_key(hostmachine):
72 hostmachine = machinemap[hostmachine]
73 self.settings["hostarch"]=hostmachine
74 if self.settings.has_key("cbuild"):
75 buildmachine = self.settings["cbuild"].split("-")[0]
77 buildmachine = os.uname()[4]
78 if not machinemap.has_key(buildmachine):
79 raise CatalystError, "Unknown build machine type "+buildmachine
80 self.settings["buildarch"]=machinemap[buildmachine]
81 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
82 self.settings["buildarch"])
84 """ Call arch constructor, pass our settings """
86 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
88 print "Invalid subarch: "+self.settings["subarch"]
89 print "Choose one of the following:",
90 for x in self.subarchmap:
95 print "Using target:",self.settings["target"]
96 """ Print a nice informational message """
97 if self.settings["buildarch"]==self.settings["hostarch"]:
98 print "Building natively for",self.settings["hostarch"]
99 elif self.settings["crosscompile"]:
100 print "Cross-compiling on",self.settings["buildarch"],\
101 "for different machine type",self.settings["hostarch"]
103 print "Building on",self.settings["buildarch"],\
104 "for alternate personality type",self.settings["hostarch"]
106 """ This must be set first as other set_ options depend on this """
107 self.set_spec_prefix()
109 """ Define all of our core variables """
110 self.set_target_profile()
111 self.set_target_subpath()
112 self.set_source_subpath()
115 self.set_snapshot_path()
117 self.set_source_path()
118 self.set_snapcache_path()
119 self.set_chroot_path()
120 self.set_autoresume_path()
122 self.set_stage_path()
123 self.set_target_path()
125 self.set_controller_file()
126 self.set_action_sequence()
128 self.set_cleanables()
129 self.set_iso_volume_id()
130 self.set_build_kernel_vars()
132 self.set_install_mask()
142 self.set_busybox_config()
144 self.set_portage_overlay()
145 self.set_root_overlay()
148 This next line checks to make sure that the specified variables exist
152 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
154 """ If we are using portage_confdir, check that as well. """
155 if self.settings.has_key("portage_confdir"):
156 file_locate(self.settings,["portage_confdir"],expand=0)
158 """ Setup our mount points """
159 if self.settings.has_key("SNAPCACHE"):
160 self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
161 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
162 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
163 "/usr/portage/distfiles":self.settings["distdir"]}
165 self.mounts=["/proc","/dev","/usr/portage/distfiles"]
166 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
167 "/usr/portage/distfiles":self.settings["distdir"]}
168 if os.uname()[0] == "Linux":
169 self.mounts.append("/dev/pts")
174 Configure any user specified options (either in catalyst.conf or on
177 if self.settings.has_key("PKGCACHE"):
178 self.set_pkgcache_path()
179 print "Location of the package cache is "+\
180 self.settings["pkgcache_path"]
181 self.mounts.append("/usr/portage/packages")
182 self.mountmap["/usr/portage/packages"]=\
183 self.settings["pkgcache_path"]
185 if self.settings.has_key("KERNCACHE"):
186 self.set_kerncache_path()
187 print "Location of the kerncache is "+\
188 self.settings["kerncache_path"]
189 self.mounts.append("/tmp/kerncache")
190 self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
192 if self.settings.has_key("CCACHE"):
193 if os.environ.has_key("CCACHE_DIR"):
194 ccdir=os.environ["CCACHE_DIR"]
195 del os.environ["CCACHE_DIR"]
197 ccdir="/root/.ccache"
198 if not os.path.isdir(ccdir):
199 raise CatalystError,\
200 "Compiler cache support can't be enabled (can't find "+\
202 self.mounts.append("/var/tmp/ccache")
203 self.mountmap["/var/tmp/ccache"]=ccdir
204 """ for the chroot: """
205 self.env["CCACHE_DIR"]="/var/tmp/ccache"
207 if self.settings.has_key("ICECREAM"):
208 self.mounts.append("/var/cache/icecream")
209 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
210 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
212 def override_cbuild(self):
213 if self.makeconf.has_key("CBUILD"):
214 self.settings["CBUILD"]=self.makeconf["CBUILD"]
216 def override_chost(self):
217 if self.makeconf.has_key("CHOST"):
218 self.settings["CHOST"]=self.makeconf["CHOST"]
220 def override_cflags(self):
221 if self.makeconf.has_key("CFLAGS"):
222 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
224 def override_cxxflags(self):
225 if self.makeconf.has_key("CXXFLAGS"):
226 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
228 def override_ldflags(self):
229 if self.makeconf.has_key("LDFLAGS"):
230 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
232 def set_install_mask(self):
233 if self.settings.has_key("install_mask"):
234 if type(self.settings["install_mask"])!=types.StringType:
235 self.settings["install_mask"]=\
236 string.join(self.settings["install_mask"])
238 def set_spec_prefix(self):
239 self.settings["spec_prefix"]=self.settings["target"]
241 def set_target_profile(self):
242 self.settings["target_profile"]=self.settings["profile"]
244 def set_target_subpath(self):
245 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
246 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
247 self.settings["version_stamp"]
249 def set_source_subpath(self):
250 if type(self.settings["source_subpath"])!=types.StringType:
251 raise CatalystError,\
252 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
254 def set_pkgcache_path(self):
255 if self.settings.has_key("pkgcache_path"):
256 if type(self.settings["pkgcache_path"])!=types.StringType:
257 self.settings["pkgcache_path"]=\
258 normpath(string.join(self.settings["pkgcache_path"]))
260 self.settings["pkgcache_path"]=\
261 normpath(self.settings["storedir"]+"/packages/"+\
262 self.settings["target_subpath"]+"/")
264 def set_kerncache_path(self):
265 if self.settings.has_key("kerncache_path"):
266 if type(self.settings["kerncache_path"])!=types.StringType:
267 self.settings["kerncache_path"]=\
268 normpath(string.join(self.settings["kerncache_path"]))
270 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
271 "/kerncache/"+self.settings["target_subpath"]+"/")
273 def set_target_path(self):
274 self.settings["target_path"]=normpath(self.settings["storedir"]+\
275 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
276 if self.settings.has_key("AUTORESUME")\
277 and os.path.exists(self.settings["autoresume_path"]+\
278 "setup_target_path"):
280 "Resume point detected, skipping target path setup operation..."
282 """ First clean up any existing target stuff """
283 # XXX WTF are we removing the old tarball before we start building the
284 # XXX new one? If the build fails, you don't want to be left with
286 # if os.path.isfile(self.settings["target_path"]):
287 # cmd("rm -f "+self.settings["target_path"],\
288 # "Could not remove existing file: "\
289 # +self.settings["target_path"],env=self.env)
290 touch(self.settings["autoresume_path"]+"setup_target_path")
292 if not os.path.exists(self.settings["storedir"]+"/builds/"):
293 os.makedirs(self.settings["storedir"]+"/builds/")
295 def set_fsscript(self):
296 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
297 self.settings["fsscript"]=\
298 self.settings[self.settings["spec_prefix"]+"/fsscript"]
299 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
302 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
303 self.settings["rcadd"]=\
304 self.settings[self.settings["spec_prefix"]+"/rcadd"]
305 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
308 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
309 self.settings["rcdel"]=\
310 self.settings[self.settings["spec_prefix"]+"/rcdel"]
311 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
314 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
315 self.settings["cdtar"]=\
316 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
317 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
320 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
321 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
322 self.settings["iso"]=\
323 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
325 # This automatically prepends the build dir to the ISO output path
326 # if it doesn't start with a /
327 self.settings["iso"] = normpath(self.settings["storedir"] + \
328 "/builds/" + self.settings["rel_type"] + "/" + \
329 self.settings[self.settings["spec_prefix"]+"/iso"])
330 del self.settings[self.settings["spec_prefix"]+"/iso"]
332 def set_fstype(self):
333 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
334 self.settings["fstype"]=\
335 self.settings[self.settings["spec_prefix"]+"/fstype"]
336 del self.settings[self.settings["spec_prefix"]+"/fstype"]
338 if not self.settings.has_key("fstype"):
339 self.settings["fstype"]="normal"
340 for x in self.valid_values:
341 if x == self.settings["spec_prefix"]+"/fstype":
342 print "\n"+self.settings["spec_prefix"]+\
343 "/fstype is being set to the default of \"normal\"\n"
346 if self.settings.has_key("fstype"):
347 self.valid_values.append("fsops")
348 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
349 self.settings["fsops"]=\
350 self.settings[self.settings["spec_prefix"]+"/fsops"]
351 del self.settings[self.settings["spec_prefix"]+"/fsops"]
353 def set_source_path(self):
354 if self.settings.has_key("SEEDCACHE")\
355 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
356 self.settings["source_subpath"]+"/")):
357 self.settings["source_path"]=normpath(self.settings["storedir"]+\
358 "/tmp/"+self.settings["source_subpath"]+"/")
360 self.settings["source_path"]=normpath(self.settings["storedir"]+\
361 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
362 if os.path.isfile(self.settings["source_path"]):
363 # XXX: Is this even necessary if the previous check passes?
364 if os.path.exists(self.settings["source_path"]):
365 self.settings["source_path_hash"]=\
366 generate_hash(self.settings["source_path"],\
367 hash_function=self.settings["hash_function"],\
369 print "Source path set to "+self.settings["source_path"]
370 if os.path.isdir(self.settings["source_path"]):
371 print "\tIf this is not desired, remove this directory or turn off"
372 print "\tseedcache in the options of catalyst.conf the source path"
373 print "\twill then be "+\
374 normpath(self.settings["storedir"]+"/builds/"+\
375 self.settings["source_subpath"]+".tar.bz2\n")
377 def set_dest_path(self):
378 if self.settings.has_key("root_path"):
379 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
380 self.settings["root_path"])
382 self.settings["destpath"]=normpath(self.settings["chroot_path"])
384 def set_cleanables(self):
385 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
386 "/root/*","/usr/portage"]
388 def set_snapshot_path(self):
389 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
390 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
392 if os.path.exists(self.settings["snapshot_path"]):
393 self.settings["snapshot_path_hash"]=\
394 generate_hash(self.settings["snapshot_path"],\
395 hash_function=self.settings["hash_function"],verbose=False)
397 def set_snapcache_path(self):
398 if self.settings.has_key("SNAPCACHE"):
399 self.settings["snapshot_cache_path"]=\
400 normpath(self.settings["snapshot_cache"]+"/"+\
401 self.settings["snapshot"]+"/")
402 self.snapcache_lock=\
403 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
404 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
406 def set_chroot_path(self):
408 NOTE: the trailing slash is very important!
409 Things *will* break without it!
411 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
412 "/tmp/"+self.settings["target_subpath"]+"/")
413 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
415 def set_autoresume_path(self):
416 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
417 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
418 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
419 self.settings["version_stamp"]+"/")
420 if self.settings.has_key("AUTORESUME"):
421 print "The autoresume path is " + self.settings["autoresume_path"]
422 if not os.path.exists(self.settings["autoresume_path"]):
423 os.makedirs(self.settings["autoresume_path"],0755)
425 def set_controller_file(self):
426 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
427 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
430 def set_iso_volume_id(self):
431 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
432 self.settings["iso_volume_id"]=\
433 self.settings[self.settings["spec_prefix"]+"/volid"]
434 if len(self.settings["iso_volume_id"])>32:
435 raise CatalystError,\
436 "ISO volume ID must not exceed 32 characters."
438 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
440 def set_action_sequence(self):
441 """ Default action sequence for run method """
442 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
443 "config_profile_link","setup_confdir","portage_overlay",\
444 "base_dirs","bind","chroot_setup","setup_environment",\
445 "run_local","preclean","unbind","clean"]
446 # if self.settings.has_key("TARBALL") or \
447 # not self.settings.has_key("FETCH"):
448 if not self.settings.has_key("FETCH"):
449 self.settings["action_sequence"].append("capture")
450 self.settings["action_sequence"].append("clear_autoresume")
453 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
454 self.settings["use"]=\
455 self.settings[self.settings["spec_prefix"]+"/use"]
456 del self.settings[self.settings["spec_prefix"]+"/use"]
457 if self.settings.has_key("use"):
458 if type(self.settings["use"])==types.StringType:
459 self.settings["use"]=self.settings["use"].split()
460 self.settings["use"].append("bindist")
462 def set_stage_path(self):
463 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
465 def set_mounts(self):
468 def set_packages(self):
472 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
473 if type(self.settings[self.settings["spec_prefix"]+\
474 "/rm"])==types.StringType:
475 self.settings[self.settings["spec_prefix"]+"/rm"]=\
476 self.settings[self.settings["spec_prefix"]+"/rm"].split()
478 def set_linuxrc(self):
479 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
480 if type(self.settings[self.settings["spec_prefix"]+\
481 "/linuxrc"])==types.StringType:
482 self.settings["linuxrc"]=\
483 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
484 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
486 def set_busybox_config(self):
487 if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
488 if type(self.settings[self.settings["spec_prefix"]+\
489 "/busybox_config"])==types.StringType:
490 self.settings["busybox_config"]=\
491 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
492 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
494 def set_portage_overlay(self):
495 if self.settings.has_key("portage_overlay"):
496 if type(self.settings["portage_overlay"])==types.StringType:
497 self.settings["portage_overlay"]=\
498 self.settings["portage_overlay"].split()
499 print "portage_overlay directories are set to: \""+\
500 string.join(self.settings["portage_overlay"])+"\""
502 def set_overlay(self):
503 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
504 if type(self.settings[self.settings["spec_prefix"]+\
505 "/overlay"])==types.StringType:
506 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
507 self.settings[self.settings["spec_prefix"]+\
510 def set_root_overlay(self):
511 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
512 if type(self.settings[self.settings["spec_prefix"]+\
513 "/root_overlay"])==types.StringType:
514 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
515 self.settings[self.settings["spec_prefix"]+\
516 "/root_overlay"].split()
518 def set_root_path(self):
519 """ ROOT= variable for emerges """
520 self.settings["root_path"]="/"
522 def set_valid_build_kernel_vars(self,addlargs):
523 if addlargs.has_key("boot/kernel"):
524 if type(addlargs["boot/kernel"])==types.StringType:
525 loopy=[addlargs["boot/kernel"]]
527 loopy=addlargs["boot/kernel"]
530 self.valid_values.append("boot/kernel/"+x+"/aliases")
531 self.valid_values.append("boot/kernel/"+x+"/config")
532 self.valid_values.append("boot/kernel/"+x+"/console")
533 self.valid_values.append("boot/kernel/"+x+"/extraversion")
534 self.valid_values.append("boot/kernel/"+x+"/gk_action")
535 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
536 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
537 self.valid_values.append("boot/kernel/"+x+"/machine_type")
538 self.valid_values.append("boot/kernel/"+x+"/sources")
539 self.valid_values.append("boot/kernel/"+x+"/softlevel")
540 self.valid_values.append("boot/kernel/"+x+"/use")
541 self.valid_values.append("boot/kernel/"+x+"/packages")
542 if addlargs.has_key("boot/kernel/"+x+"/packages"):
543 if type(addlargs["boot/kernel/"+x+\
544 "/packages"])==types.StringType:
545 addlargs["boot/kernel/"+x+"/packages"]=\
546 [addlargs["boot/kernel/"+x+"/packages"]]
548 def set_build_kernel_vars(self):
549 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
550 self.settings["gk_mainargs"]=\
551 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
552 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
554 def kill_chroot_pids(self):
555 print "Checking for processes running in chroot and killing them."
558 Force environment variables to be exported so script can see them
560 self.setup_environment()
562 if os.path.exists(self.settings["sharedir"]+\
563 "/targets/support/kill-chroot-pids.sh"):
564 cmd("/bin/bash "+self.settings["sharedir"]+\
565 "/targets/support/kill-chroot-pids.sh",\
566 "kill-chroot-pids script failed.",env=self.env)
568 def mount_safety_check(self):
569 mypath=self.settings["chroot_path"]
572 Check and verify that none of our paths in mypath are mounted. We don't
573 want to clean up with things still mounted, and this allows us to check.
574 Returns 1 on ok, 0 on "something is still mounted" case.
577 if not os.path.exists(mypath):
580 for x in self.mounts:
581 if not os.path.exists(mypath+x):
584 if ismount(mypath+x):
585 """ Something is still mounted "" """
587 print x+" is still mounted; performing auto-bind-umount...",
588 """ Try to umount stuff ourselves """
590 if ismount(mypath+x):
591 raise CatalystError, "Auto-unbind failed for "+x
593 print "Auto-unbind successful..."
594 except CatalystError:
595 raise CatalystError, "Unable to auto-unbind "+x
600 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
603 if self.settings.has_key("SEEDCACHE"):
604 if os.path.isdir(self.settings["source_path"]):
605 """ SEEDCACHE Is a directory, use rsync """
606 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
607 " "+self.settings["chroot_path"]
608 display_msg="\nStarting rsync from "+\
609 self.settings["source_path"]+"\nto "+\
610 self.settings["chroot_path"]+\
611 " (This may take some time) ...\n"
612 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
613 self.settings["chroot_path"]+" failed."
615 """ SEEDCACHE is a not a directory, try untar'ing """
616 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
617 display_msg="\nStarting tar extract from "+\
618 self.settings["source_path"]+"\nto "+\
619 self.settings["chroot_path"]+\
620 " (This may take some time) ...\n"
621 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
622 self.settings["chroot_path"]
623 error_msg="Tarball extraction of "+\
624 self.settings["source_path"]+" to "+\
625 self.settings["chroot_path"]+" failed."
627 """ No SEEDCACHE, use tar """
628 display_msg="\nStarting tar extract from "+\
629 self.settings["source_path"]+"\nto "+\
630 self.settings["chroot_path"]+\
631 " (This may take some time) ...\n"
632 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
633 self.settings["chroot_path"]
634 error_msg="Tarball extraction of "+self.settings["source_path"]+\
635 " to "+self.settings["chroot_path"]+" failed."
637 if self.settings.has_key("AUTORESUME"):
638 if os.path.isdir(self.settings["source_path"]) \
639 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
640 """ Autoresume is valid, SEEDCACHE is valid """
642 invalid_snapshot=False
644 elif os.path.isfile(self.settings["source_path"]) \
645 and self.settings["source_path_hash"]==clst_unpack_hash:
646 """ Autoresume is valid, tarball is valid """
648 invalid_snapshot=True
650 elif os.path.isdir(self.settings["source_path"]) \
651 and not os.path.exists(self.settings["autoresume_path"]+\
653 """ Autoresume is invalid, SEEDCACHE """
655 invalid_snapshot=False
657 elif os.path.isfile(self.settings["source_path"]) \
658 and self.settings["source_path_hash"]!=clst_unpack_hash:
659 """ Autoresume is invalid, tarball """
661 invalid_snapshot=True
663 """ No autoresume, SEEDCACHE """
664 if self.settings.has_key("SEEDCACHE"):
665 """ SEEDCACHE so let's run rsync and let it clean up """
666 if os.path.isdir(self.settings["source_path"]):
668 invalid_snapshot=False
669 elif os.path.isfile(self.settings["source_path"]):
670 """ Tarball so unpack and remove anything already there """
672 invalid_snapshot=True
673 """ No autoresume, no SEEDCACHE """
675 """ Tarball so unpack and remove anything already there """
676 if os.path.isfile(self.settings["source_path"]):
678 invalid_snapshot=True
679 elif os.path.isdir(self.settings["source_path"]):
680 """ We should never reach this, so something is very wrong """
681 raise CatalystError,\
682 "source path is a dir but seedcache is not enabled"
685 self.mount_safety_check()
688 if self.settings.has_key("AUTORESUME"):
689 print "No Valid Resume point detected, cleaning up..."
691 self.clear_autoresume()
694 if not os.path.exists(self.settings["chroot_path"]):
695 os.makedirs(self.settings["chroot_path"])
697 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
698 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
700 if self.settings.has_key("PKGCACHE"):
701 if not os.path.exists(self.settings["pkgcache_path"]):
702 os.makedirs(self.settings["pkgcache_path"],0755)
704 if self.settings.has_key("KERNCACHE"):
705 if not os.path.exists(self.settings["kerncache_path"]):
706 os.makedirs(self.settings["kerncache_path"],0755)
709 cmd(unpack_cmd,error_msg,env=self.env)
711 if self.settings.has_key("source_path_hash"):
712 myf=open(self.settings["autoresume_path"]+"unpack","w")
713 myf.write(self.settings["source_path_hash"])
716 touch(self.settings["autoresume_path"]+"unpack")
718 print "Resume point detected, skipping unpack operation..."
720 def unpack_snapshot(self):
722 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
725 if self.settings.has_key("SNAPCACHE"):
726 snapshot_cache_hash=\
727 read_from_clst(self.settings["snapshot_cache_path"]+\
729 destdir=self.settings["snapshot_cache_path"]
730 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
731 unpack_errmsg="Error unpacking snapshot"
732 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
733 self.settings["snapshot_cache_path"]+\
734 " (This can take a long time)..."
735 cleanup_errmsg="Error removing existing snapshot cache directory."
736 self.snapshot_lock_object=self.snapcache_lock
738 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
739 print "Valid snapshot cache, skipping unpack of portage tree..."
742 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
743 cleanup_errmsg="Error removing existing snapshot directory."
745 "Cleaning up existing portage tree (This can take a long time)..."
746 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
747 self.settings["chroot_path"]+"/usr"
748 unpack_errmsg="Error unpacking snapshot"
750 if self.settings.has_key("AUTORESUME") \
751 and os.path.exists(self.settings["chroot_path"]+\
753 and os.path.exists(self.settings["autoresume_path"]\
755 and self.settings["snapshot_path_hash"] == snapshot_hash:
757 "Valid Resume point detected, skipping unpack of portage tree..."
761 if self.settings.has_key("SNAPCACHE"):
762 self.snapshot_lock_object.write_lock()
763 if os.path.exists(destdir):
765 cleanup_cmd="rm -rf "+destdir
766 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
767 if not os.path.exists(destdir):
768 os.makedirs(destdir,0755)
770 print "Unpacking portage tree (This can take a long time) ..."
771 cmd(unpack_cmd,unpack_errmsg,env=self.env)
773 if self.settings.has_key("SNAPCACHE"):
774 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
775 myf.write(self.settings["snapshot_path_hash"])
778 print "Setting snapshot autoresume point"
779 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
780 myf.write(self.settings["snapshot_path_hash"])
783 if self.settings.has_key("SNAPCACHE"):
784 self.snapshot_lock_object.unlock()
786 def config_profile_link(self):
787 if self.settings.has_key("AUTORESUME") \
788 and os.path.exists(self.settings["autoresume_path"]+\
789 "config_profile_link"):
791 "Resume point detected, skipping config_profile_link operation..."
793 # TODO: zmedico and I discussed making this a directory and pushing
794 # in a parent file, as well as other user-specified configuration.
795 print "Configuring profile link..."
796 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
797 "Error zapping profile link",env=self.env)
798 cmd("ln -sf ../usr/portage/profiles/"+\
799 self.settings["target_profile"]+" "+\
800 self.settings["chroot_path"]+"/etc/make.profile",\
801 "Error creating profile link",env=self.env)
802 touch(self.settings["autoresume_path"]+"config_profile_link")
804 def setup_confdir(self):
805 if self.settings.has_key("AUTORESUME") \
806 and os.path.exists(self.settings["autoresume_path"]+\
808 print "Resume point detected, skipping setup_confdir operation..."
810 if self.settings.has_key("portage_confdir"):
811 print "Configuring /etc/portage..."
812 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
813 "Error zapping /etc/portage",env=self.env)
814 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
815 self.settings["chroot_path"]+"/etc/portage",\
816 "Error copying /etc/portage",env=self.env)
817 touch(self.settings["autoresume_path"]+"setup_confdir")
819 def portage_overlay(self):
820 """ We copy the contents of our overlays to /usr/local/portage """
821 if self.settings.has_key("portage_overlay"):
822 for x in self.settings["portage_overlay"]:
823 if os.path.exists(x):
824 print "Copying overlay dir " +x
825 cmd("mkdir -p "+self.settings["chroot_path"]+\
826 "/usr/local/portage",\
827 "Could not make portage_overlay dir",env=self.env)
828 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
829 "/usr/local/portage",\
830 "Could not copy portage_overlay",env=self.env)
832 def root_overlay(self):
833 """ Copy over the root_overlay """
834 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
835 for x in self.settings[self.settings["spec_prefix"]+\
837 if os.path.exists(x):
838 print "Copying root_overlay: "+x
839 cmd("rsync -a "+x+"/ "+\
840 self.settings["chroot_path"],\
841 self.settings["spec_prefix"]+"/root_overlay: "+x+\
842 " copy failed.",env=self.env)
848 for x in self.mounts:
849 if not os.path.exists(self.settings["chroot_path"]+x):
850 os.makedirs(self.settings["chroot_path"]+x,0755)
852 if not os.path.exists(self.mountmap[x]):
853 os.makedirs(self.mountmap[x],0755)
856 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
857 self.snapshot_lock_object.read_lock()
858 if os.uname()[0] == "FreeBSD":
860 retval=os.system("mount -t devfs none "+\
861 self.settings["chroot_path"]+x)
863 retval=os.system("mount_nullfs "+src+" "+\
864 self.settings["chroot_path"]+x)
866 retval=os.system("mount --bind "+src+" "+\
867 self.settings["chroot_path"]+x)
870 raise CatalystError,"Couldn't bind mount "+src
874 mypath=self.settings["chroot_path"]
875 myrevmounts=self.mounts[:]
876 myrevmounts.reverse()
877 """ Unmount in reverse order for nested bind-mounts """
878 for x in myrevmounts:
879 if not os.path.exists(mypath+x):
882 if not ismount(mypath+x):
885 retval=os.system("umount "+\
886 os.path.join(mypath,x.lstrip(os.path.sep)))
889 warn("First attempt to unmount: "+mypath+x+" failed.")
890 warn("Killing any pids still running in the chroot")
892 self.kill_chroot_pids()
894 retval2=os.system("umount "+mypath+x)
897 warn("Couldn't umount bind mount: "+mypath+x)
899 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
902 It's possible the snapshot lock object isn't created yet.
903 This is because mount safety check calls unbind before the
904 target is fully initialized
906 self.snapshot_lock_object.unlock()
911 if any bind mounts really failed, then we need to raise
912 this to potentially prevent an upcoming bash stage cleanup script
913 from wiping our bind mounts.
915 raise CatalystError,\
916 "Couldn't umount one or more bind-mounts; aborting for safety."
918 def chroot_setup(self):
919 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
921 self.override_cbuild()
922 self.override_chost()
923 self.override_cflags()
924 self.override_cxxflags()
925 self.override_ldflags()
926 if self.settings.has_key("AUTORESUME") \
927 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
928 print "Resume point detected, skipping chroot_setup operation..."
930 print "Setting up chroot..."
932 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
934 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
935 "Could not copy resolv.conf into place.",env=self.env)
937 """ Copy over the envscript, if applicable """
938 if self.settings.has_key("ENVSCRIPT"):
939 if not os.path.exists(self.settings["ENVSCRIPT"]):
940 raise CatalystError,\
941 "Can't find envscript "+self.settings["ENVSCRIPT"]
943 print "\nWarning!!!!"
944 print "\tOverriding certain env variables may cause catastrophic failure."
945 print "\tIf your build fails look here first as the possible problem."
946 print "\tCatalyst assumes you know what you are doing when setting"
947 print "\t\tthese variables."
948 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
949 print "\tYou have been warned\n"
951 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
952 self.settings["chroot_path"]+"/tmp/envscript",\
953 "Could not copy envscript into place.",env=self.env)
955 """ Setup metadata_overlay """
956 if self.settings.has_key("METADATA_OVERLAY") \
957 and not self.settings.has_key("portage_confdir"):
958 if not os.path.exists(self.settings["chroot_path"]+\
960 cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
961 myf=open(self.settings["chroot_path"]+\
962 "/etc/portage/modules","a")
963 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
968 Copy over /etc/hosts from the host in case there are any
971 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
972 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
973 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
974 "Could not backup /etc/hosts",env=self.env)
975 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
976 "Could not copy /etc/hosts",env=self.env)
978 """ Modify and write out make.conf (for the chroot) """
979 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
980 "Could not remove "+self.settings["chroot_path"]+\
981 "/etc/make.conf",env=self.env)
982 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
983 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
984 myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
985 if self.settings.has_key("CFLAGS"):
986 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
987 if self.settings.has_key("CXXFLAGS"):
988 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
990 myf.write('CXXFLAGS="${CFLAGS}"\n')
992 if self.settings.has_key("LDFLAGS"):
993 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
994 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
995 if self.settings.has_key("CBUILD"):
996 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")
997 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
999 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")
1000 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1002 """ Figure out what our USE vars are for building """
1004 if self.settings.has_key("HOSTUSE"):
1005 myusevars.extend(self.settings["HOSTUSE"])
1007 if self.settings.has_key("use"):
1008 myusevars.extend(self.settings["use"])
1011 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1012 myusevars = sorted(set(myusevars))
1013 myf.write('USE="'+string.join(myusevars)+'"\n')
1014 if '-*' in myusevars:
1015 print "\nWarning!!! "
1016 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1017 "/use will cause portage to ignore"
1018 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1020 """ Setup the portage overlay """
1021 if self.settings.has_key("portage_overlay"):
1022 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1025 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1026 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1027 "Could not backup /etc/make.conf",env=self.env)
1028 touch(self.settings["autoresume_path"]+"chroot_setup")
1031 if self.settings.has_key("AUTORESUME") \
1032 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1033 print "Resume point detected, skipping fsscript operation..."
1035 if self.settings.has_key("fsscript"):
1036 if os.path.exists(self.settings["controller_file"]):
1037 cmd("/bin/bash "+self.settings["controller_file"]+\
1038 " fsscript","fsscript script failed.",env=self.env)
1039 touch(self.settings["autoresume_path"]+"fsscript")
1042 if self.settings.has_key("AUTORESUME") \
1043 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1044 print "Resume point detected, skipping rcupdate operation..."
1046 if os.path.exists(self.settings["controller_file"]):
1047 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1048 "rc-update script failed.",env=self.env)
1049 touch(self.settings["autoresume_path"]+"rcupdate")
1052 if self.settings.has_key("AUTORESUME") \
1053 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1054 print "Resume point detected, skipping clean operation..."
1056 for x in self.settings["cleanables"]:
1057 print "Cleaning chroot: "+x+"... "
1058 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1061 """ Put /etc/hosts back into place """
1062 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1063 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1064 self.settings["chroot_path"]+"/etc/hosts",\
1065 "Could not replace /etc/hosts",env=self.env)
1067 """ Remove our overlay """
1068 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1069 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1070 "Could not remove /usr/local/portage",env=self.env)
1071 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1073 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1075 """ Clean up old and obsoleted files in /etc """
1076 if os.path.exists(self.settings["stage_path"]+"/etc"):
1077 cmd("find "+self.settings["stage_path"]+\
1078 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1079 "Could not remove stray files in /etc",env=self.env)
1081 if os.path.exists(self.settings["controller_file"]):
1082 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1083 "clean script failed.",env=self.env)
1084 touch(self.settings["autoresume_path"]+"clean")
1087 if self.settings.has_key("AUTORESUME") \
1088 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1089 print "Resume point detected, skipping empty operation..."
1091 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1092 if type(self.settings[self.settings["spec_prefix"]+\
1093 "/empty"])==types.StringType:
1094 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1095 self.settings[self.settings["spec_prefix"]+\
1097 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1098 myemp=self.settings["destpath"]+x
1099 if not os.path.isdir(myemp):
1100 print x,"not a directory or does not exist, skipping 'empty' operation."
1102 print "Emptying directory",x
1104 stat the dir, delete the dir, recreate the dir and set
1105 the proper perms and ownership
1107 mystat=os.stat(myemp)
1108 shutil.rmtree(myemp)
1109 os.makedirs(myemp,0755)
1110 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1111 os.chmod(myemp,mystat[ST_MODE])
1112 touch(self.settings["autoresume_path"]+"empty")
1115 if self.settings.has_key("AUTORESUME") \
1116 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1117 print "Resume point detected, skipping remove operation..."
1119 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1120 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1122 We're going to shell out for all these cleaning
1123 operations, so we get easy glob handling.
1125 print "livecd: removing "+x
1126 os.system("rm -rf "+self.settings["chroot_path"]+x)
1128 if os.path.exists(self.settings["controller_file"]):
1129 cmd("/bin/bash "+self.settings["controller_file"]+\
1130 " clean","Clean failed.",env=self.env)
1131 touch(self.settings["autoresume_path"]+"remove")
1137 if self.settings.has_key("AUTORESUME") \
1138 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1139 print "Resume point detected, skipping preclean operation..."
1142 if os.path.exists(self.settings["controller_file"]):
1143 cmd("/bin/bash "+self.settings["controller_file"]+\
1144 " preclean","preclean script failed.",env=self.env)
1145 touch(self.settings["autoresume_path"]+"preclean")
1149 raise CatalystError, "Build failed, could not execute preclean"
1152 if self.settings.has_key("AUTORESUME") \
1153 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1154 print "Resume point detected, skipping capture operation..."
1156 """ Capture target in a tarball """
1157 mypath=self.settings["target_path"].split("/")
1158 """ Remove filename from path """
1159 mypath=string.join(mypath[:-1],"/")
1161 """ Now make sure path exists """
1162 if not os.path.exists(mypath):
1165 print "Creating stage tarball..."
1167 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1168 self.settings["stage_path"]+" .",\
1169 "Couldn't create stage tarball",env=self.env)
1171 self.gen_contents_file(self.settings["target_path"])
1172 self.gen_digest_file(self.settings["target_path"])
1174 touch(self.settings["autoresume_path"]+"capture")
1176 def run_local(self):
1177 if self.settings.has_key("AUTORESUME") \
1178 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1179 print "Resume point detected, skipping run_local operation..."
1182 if os.path.exists(self.settings["controller_file"]):
1183 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1184 "run script failed.",env=self.env)
1185 touch(self.settings["autoresume_path"]+"run_local")
1187 except CatalystError:
1189 raise CatalystError,"Stage build aborting due to error."
1191 def setup_environment(self):
1193 Modify the current environment. This is an ugly hack that should be
1194 fixed. We need this to use the os.system() call since we can't
1195 specify our own environ
1197 for x in self.settings.keys():
1198 """ Sanitize var names by doing "s|/-.|_|g" """
1199 varname="clst_"+string.replace(x,"/","_")
1200 varname=string.replace(varname,"-","_")
1201 varname=string.replace(varname,".","_")
1202 if type(self.settings[x])==types.StringType:
1203 """ Prefix to prevent namespace clashes """
1204 #os.environ[varname]=self.settings[x]
1205 self.env[varname]=self.settings[x]
1206 elif type(self.settings[x])==types.ListType:
1207 #os.environ[varname]=string.join(self.settings[x])
1208 self.env[varname]=string.join(self.settings[x])
1209 elif type(self.settings[x])==types.BooleanType:
1210 if self.settings[x]:
1211 self.env[varname]="true"
1213 self.env[varname]="false"
1214 if self.settings.has_key("makeopts"):
1215 self.env["MAKEOPTS"]=self.settings["makeopts"]
1218 self.chroot_lock.write_lock()
1220 """ Kill any pids in the chroot "" """
1221 self.kill_chroot_pids()
1223 """ Check for mounts right away and abort if we cannot unmount them """
1224 self.mount_safety_check()
1226 if self.settings.has_key("CLEAR_AUTORESUME"):
1227 self.clear_autoresume()
1229 if self.settings.has_key("PURGEONLY"):
1233 if self.settings.has_key("PURGE"):
1236 for x in self.settings["action_sequence"]:
1237 print "--- Running action sequence: "+x
1240 apply(getattr(self,x))
1242 self.mount_safety_check()
1245 self.chroot_lock.unlock()
1248 if self.settings.has_key("AUTORESUME") \
1249 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1250 print "Resume point detected, skipping unmerge operation..."
1252 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1253 if type(self.settings[self.settings["spec_prefix"]+\
1254 "/unmerge"])==types.StringType:
1255 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1256 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1258 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1260 for x in range(0,len(myunmerge)):
1262 Surround args with quotes for passing to bash, allows
1263 things like "<" to remain intact
1265 myunmerge[x]="'"+myunmerge[x]+"'"
1266 myunmerge=string.join(myunmerge)
1268 """ Before cleaning, unmerge stuff """
1270 cmd("/bin/bash "+self.settings["controller_file"]+\
1271 " unmerge "+ myunmerge,"Unmerge script failed.",\
1273 print "unmerge shell script"
1274 except CatalystError:
1277 touch(self.settings["autoresume_path"]+"unmerge")
1279 def target_setup(self):
1280 if self.settings.has_key("AUTORESUME") \
1281 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1282 print "Resume point detected, skipping target_setup operation..."
1284 print "Setting up filesystems per filesystem type"
1285 cmd("/bin/bash "+self.settings["controller_file"]+\
1286 " target_image_setup "+ self.settings["target_path"],\
1287 "target_image_setup script failed.",env=self.env)
1288 touch(self.settings["autoresume_path"]+"target_setup")
1290 def setup_overlay(self):
1291 if self.settings.has_key("AUTORESUME") \
1292 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1293 print "Resume point detected, skipping setup_overlay operation..."
1295 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1296 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1297 if os.path.exists(x):
1298 cmd("rsync -a "+x+"/ "+\
1299 self.settings["target_path"],\
1300 self.settings["spec_prefix"]+"overlay: "+x+\
1301 " copy failed.",env=self.env)
1302 touch(self.settings["autoresume_path"]+"setup_overlay")
1304 def create_iso(self):
1305 if self.settings.has_key("AUTORESUME") \
1306 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1307 print "Resume point detected, skipping create_iso operation..."
1309 """ Create the ISO """
1310 if self.settings.has_key("iso"):
1311 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1312 self.settings["iso"],"ISO creation script failed.",\
1314 self.gen_contents_file(self.settings["iso"])
1315 self.gen_digest_file(self.settings["iso"])
1316 touch(self.settings["autoresume_path"]+"create_iso")
1318 print "WARNING: livecd/iso was not defined."
1319 print "An ISO Image will not be created."
1321 def build_packages(self):
1322 if self.settings.has_key("AUTORESUME") \
1323 and os.path.exists(self.settings["autoresume_path"]+\
1325 print "Resume point detected, skipping build_packages operation..."
1327 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1328 if self.settings.has_key("AUTORESUME") \
1329 and os.path.exists(self.settings["autoresume_path"]+\
1331 print "Resume point detected, skipping build_packages operation..."
1334 list_bashify(self.settings[self.settings["spec_prefix"]\
1337 cmd("/bin/bash "+self.settings["controller_file"]+\
1338 " build_packages "+mypack,\
1339 "Error in attempt to build packages",env=self.env)
1340 touch(self.settings["autoresume_path"]+"build_packages")
1341 except CatalystError:
1343 raise CatalystError,self.settings["spec_prefix"]+\
1344 "build aborting due to error."
1346 def build_kernel(self):
1347 if self.settings.has_key("AUTORESUME") \
1348 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1349 print "Resume point detected, skipping build_kernel operation..."
1351 if self.settings.has_key("boot/kernel"):
1353 mynames=self.settings["boot/kernel"]
1354 if type(mynames)==types.StringType:
1357 Execute the script that sets up the kernel build environment
1359 cmd("/bin/bash "+self.settings["controller_file"]+\
1360 " pre-kmerge ","Runscript pre-kmerge failed",\
1363 for kname in mynames:
1364 if self.settings.has_key("AUTORESUME") \
1365 and os.path.exists(self.settings["autoresume_path"]\
1366 +"build_kernel_"+kname):
1367 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1368 else: # TODO: make this not require a kernel config
1370 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1372 raise CatalystError,\
1373 "Can't find kernel config: "+\
1374 self.settings["boot/kernel/"+kname+\
1378 raise CatalystError,\
1379 "Required value boot/kernel/config not specified"
1382 cmd("cp "+self.settings["boot/kernel/"+kname+\
1384 self.settings["chroot_path"]+"/var/tmp/"+\
1386 "Couldn't copy kernel config: "+\
1387 self.settings["boot/kernel/"+kname+\
1388 "/config"],env=self.env)
1390 except CatalystError:
1394 If we need to pass special options to the bootloader
1395 for this kernel put them into the environment
1397 if self.settings.has_key("boot/kernel/"+kname+\
1399 myopts=self.settings["boot/kernel/"+kname+\
1402 if type(myopts) != types.StringType:
1403 myopts = string.join(myopts)
1404 self.env[kname+"_kernelopts"]=myopts
1407 self.env[kname+"_kernelopts"]=""
1409 if not self.settings.has_key("boot/kernel/"+kname+\
1411 self.settings["boot/kernel/"+kname+\
1414 self.env["clst_kextraversion"]=\
1415 self.settings["boot/kernel/"+kname+\
1418 if self.settings.has_key("boot/kernel/"+kname+\
1419 "/initramfs_overlay"):
1420 if os.path.exists(self.settings["boot/kernel/"+\
1421 kname+"/initramfs_overlay"]):
1422 print "Copying initramfs_overlay dir "+\
1423 self.settings["boot/kernel/"+kname+\
1424 "/initramfs_overlay"]
1427 self.settings["chroot_path"]+\
1428 "/tmp/initramfs_overlay/"+\
1429 self.settings["boot/kernel/"+kname+\
1430 "/initramfs_overlay"],env=self.env)
1432 cmd("cp -R "+self.settings["boot/kernel/"+\
1433 kname+"/initramfs_overlay"]+"/* "+\
1434 self.settings["chroot_path"]+\
1435 "/tmp/initramfs_overlay/"+\
1436 self.settings["boot/kernel/"+kname+\
1437 "/initramfs_overlay"],env=self.env)
1439 """ Execute the script that builds the kernel """
1440 cmd("/bin/bash "+self.settings["controller_file"]+\
1442 "Runscript kernel build failed",env=self.env)
1444 if self.settings.has_key("boot/kernel/"+kname+\
1445 "/initramfs_overlay"):
1446 if os.path.exists(self.settings["chroot_path"]+\
1447 "/tmp/initramfs_overlay/"):
1448 print "Cleaning up temporary overlay dir"
1449 cmd("rm -R "+self.settings["chroot_path"]+\
1450 "/tmp/initramfs_overlay/",env=self.env)
1452 touch(self.settings["autoresume_path"]+\
1453 "build_kernel_"+kname)
1456 Execute the script that cleans up the kernel build
1459 cmd("/bin/bash "+self.settings["controller_file"]+\
1461 "Runscript post-kmerge failed",env=self.env)
1463 touch(self.settings["autoresume_path"]+"build_kernel")
1465 except CatalystError:
1467 raise CatalystError,\
1468 "build aborting due to kernel build error."
1470 def bootloader(self):
1471 if self.settings.has_key("AUTORESUME") \
1472 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1473 print "Resume point detected, skipping bootloader operation..."
1476 cmd("/bin/bash "+self.settings["controller_file"]+\
1477 " bootloader " + self.settings["target_path"],\
1478 "Bootloader script failed.",env=self.env)
1479 touch(self.settings["autoresume_path"]+"bootloader")
1480 except CatalystError:
1482 raise CatalystError,"Script aborting due to error."
1484 def livecd_update(self):
1485 if self.settings.has_key("AUTORESUME") \
1486 and os.path.exists(self.settings["autoresume_path"]+\
1488 print "Resume point detected, skipping build_packages operation..."
1491 cmd("/bin/bash "+self.settings["controller_file"]+\
1492 " livecd-update","livecd-update failed.",env=self.env)
1493 touch(self.settings["autoresume_path"]+"livecd_update")
1495 except CatalystError:
1497 raise CatalystError,"build aborting due to livecd_update error."
1499 def clear_chroot(self):
1500 myemp=self.settings["chroot_path"]
1501 if os.path.isdir(myemp):
1502 print "Emptying directory",myemp
1504 stat the dir, delete the dir, recreate the dir and set
1505 the proper perms and ownership
1507 mystat=os.stat(myemp)
1508 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1509 """ There's no easy way to change flags recursively in python """
1510 if os.uname()[0] == "FreeBSD":
1511 os.system("chflags -R noschg "+myemp)
1512 shutil.rmtree(myemp)
1513 os.makedirs(myemp,0755)
1514 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1515 os.chmod(myemp,mystat[ST_MODE])
1517 def clear_packages(self):
1518 if self.settings.has_key("PKGCACHE"):
1519 print "purging the pkgcache ..."
1521 myemp=self.settings["pkgcache_path"]
1522 if os.path.isdir(myemp):
1523 print "Emptying directory",myemp
1525 stat the dir, delete the dir, recreate the dir and set
1526 the proper perms and ownership
1528 mystat=os.stat(myemp)
1529 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1530 shutil.rmtree(myemp)
1531 os.makedirs(myemp,0755)
1532 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1533 os.chmod(myemp,mystat[ST_MODE])
1535 def clear_kerncache(self):
1536 if self.settings.has_key("KERNCACHE"):
1537 print "purging the kerncache ..."
1539 myemp=self.settings["kerncache_path"]
1540 if os.path.isdir(myemp):
1541 print "Emptying directory",myemp
1543 stat the dir, delete the dir, recreate the dir and set
1544 the proper perms and ownership
1546 mystat=os.stat(myemp)
1547 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1548 shutil.rmtree(myemp)
1549 os.makedirs(myemp,0755)
1550 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1551 os.chmod(myemp,mystat[ST_MODE])
1553 def clear_autoresume(self):
1554 """ Clean resume points since they are no longer needed """
1555 if self.settings.has_key("AUTORESUME"):
1556 print "Removing AutoResume Points: ..."
1557 myemp=self.settings["autoresume_path"]
1558 if os.path.isdir(myemp):
1559 if self.settings.has_key("AUTORESUME"):
1560 print "Emptying directory",myemp
1562 stat the dir, delete the dir, recreate the dir and set
1563 the proper perms and ownership
1565 mystat=os.stat(myemp)
1566 if os.uname()[0] == "FreeBSD":
1567 cmd("chflags -R noschg "+myemp,\
1568 "Could not remove immutable flag for file "\
1570 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1571 shutil.rmtree(myemp)
1572 os.makedirs(myemp,0755)
1573 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1574 os.chmod(myemp,mystat[ST_MODE])
1576 def gen_contents_file(self,file):
1577 if os.path.exists(file+".CONTENTS"):
1578 os.remove(file+".CONTENTS")
1579 if self.settings.has_key("contents"):
1580 if os.path.exists(file):
1581 myf=open(file+".CONTENTS","w")
1583 for i in self.settings["contents"].split():
1588 contents=generate_contents(file,contents_function=j,\
1589 verbose=self.settings.has_key("VERBOSE"))
1594 def gen_digest_file(self,file):
1595 if os.path.exists(file+".DIGESTS"):
1596 os.remove(file+".DIGESTS")
1597 if self.settings.has_key("digests"):
1598 if os.path.exists(file):
1599 myf=open(file+".DIGESTS","w")
1601 for i in self.settings["digests"].split():
1605 for f in [file, file+'.CONTENTS']:
1606 if os.path.exists(f):
1608 for k in hash_map.keys():
1609 hash=generate_hash(f,hash_function=k,verbose=\
1610 self.settings.has_key("VERBOSE"))
1614 hash=generate_hash(f,hash_function=j,verbose=\
1615 self.settings.has_key("VERBOSE"))
1620 countdown(10,"Purging Caches ...")
1621 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY"):
1622 print "clearing autoresume ..."
1623 self.clear_autoresume()
1625 print "clearing chroot ..."
1628 print "clearing package cache ..."
1629 self.clear_packages()
1631 print "clearing kerncache ..."
1632 self.clear_kerncache()
1634 # vim: ts=4 sw=4 sta et sts=4 ai