1 import os,string,imp,types,shutil
2 from catalyst_support import *
3 from generic_target import *
9 'find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
11 TARGET_MOUNTS_DEFAULTS = {
12 "ccache": "/var/tmp/ccache",
15 "distdir": "/usr/portage/distfiles",
16 "icecream": "/usr/lib/icecc/bin",
17 "kerncache": "/tmp/kerncache",
18 "packagedir": "/usr/portage/packages",
19 "portdir": "/usr/portage",
20 "port_tmpdir": "/var/tmp/portage",
21 "port_logdir": "/var/log/portage",
26 class generic_stage_target(generic_target):
28 This class does all of the chroot setup, copying of files, etc. It is
29 the driver class for pretty much everything that Catalyst does.
31 def __init__(self,myspec,addlargs):
32 self.required_values.extend(["version_stamp","target","subarch",\
33 "rel_type","profile","snapshot","source_subpath"])
35 self.valid_values.extend(["version_stamp","target","subarch",\
36 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
37 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
38 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
40 self.set_valid_build_kernel_vars(addlargs)
41 generic_target.__init__(self,myspec,addlargs)
44 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
45 work better with vapier's CBUILD stuff. I've removed the "monolithic"
46 machinemap from this file and split up its contents amongst the
47 various arch/foo.py files.
49 When register() is called on each module in the arch/ dir, it now
50 returns a tuple instead of acting on the subarchmap dict that is
51 passed to it. The tuple contains the values that were previously
52 added to subarchmap as well as a new list of CHOSTs that go along
53 with that arch. This allows us to build machinemap on the fly based
54 on the keys in subarchmap and the values of the 2nd list returned
57 Also, after talking with vapier. I have a slightly better idea of what
58 certain variables are used for and what they should be set to. Neither
59 'buildarch' or 'hostarch' are used directly, so their value doesn't
60 really matter. They are just compared to determine if we are
61 cross-compiling. Because of this, they are just set to the name of the
62 module in arch/ that the subarch is part of to make things simpler.
63 The entire build process is still based off of 'subarch' like it was
70 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
71 "/arch/") if x.endswith(".py")]:
73 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
75 This next line loads the plugin as a module and assigns it to
78 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
79 ".py",(".py","r",imp.PY_SOURCE))
81 This next line registers all the subarches supported in the
84 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
85 self.subarchmap.update(tmpsubarchmap)
86 for machine in tmpmachinemap:
87 machinemap[machine] = x
88 for subarch in tmpsubarchmap:
89 machinemap[subarch] = x
93 This message should probably change a bit, since everything in
94 the dir should load just fine. If it doesn't, it's probably a
95 syntax error in the module
97 msg("Can't find/load "+x+".py plugin in "+\
98 self.settings["sharedir"]+"/arch/")
100 if "chost" in self.settings:
101 hostmachine = self.settings["chost"].split("-")[0]
102 if hostmachine not in machinemap:
103 raise CatalystError, "Unknown host machine type "+hostmachine
104 self.settings["hostarch"]=machinemap[hostmachine]
106 hostmachine = self.settings["subarch"]
107 if hostmachine in machinemap:
108 hostmachine = machinemap[hostmachine]
109 self.settings["hostarch"]=hostmachine
110 if "cbuild" in self.settings:
111 buildmachine = self.settings["cbuild"].split("-")[0]
113 buildmachine = os.uname()[4]
114 if buildmachine not in machinemap:
115 raise CatalystError, "Unknown build machine type "+buildmachine
116 self.settings["buildarch"]=machinemap[buildmachine]
117 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
118 self.settings["buildarch"])
120 """ Call arch constructor, pass our settings """
122 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
124 print "Invalid subarch: "+self.settings["subarch"]
125 print "Choose one of the following:",
126 for x in self.subarchmap:
131 print "Using target:",self.settings["target"]
132 """ Print a nice informational message """
133 if self.settings["buildarch"]==self.settings["hostarch"]:
134 print "Building natively for",self.settings["hostarch"]
135 elif self.settings["crosscompile"]:
136 print "Cross-compiling on",self.settings["buildarch"],\
137 "for different machine type",self.settings["hostarch"]
139 print "Building on",self.settings["buildarch"],\
140 "for alternate personality type",self.settings["hostarch"]
142 """ This must be set first as other set_ options depend on this """
143 self.set_spec_prefix()
145 """ Define all of our core variables """
146 self.set_target_profile()
147 self.set_target_subpath()
148 self.set_source_subpath()
151 self.set_snapshot_path()
153 self.set_source_path()
154 self.set_snapcache_path()
155 self.set_chroot_path()
156 self.set_autoresume_path()
158 self.set_stage_path()
159 self.set_target_path()
161 self.set_controller_file()
162 self.set_action_sequence()
164 self.set_cleanables()
165 self.set_iso_volume_id()
166 self.set_build_kernel_vars()
168 self.set_install_mask()
178 self.set_busybox_config()
180 self.set_portage_overlay()
181 self.set_root_overlay()
184 This next line checks to make sure that the specified variables exist
188 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
190 """ If we are using portage_confdir, check that as well. """
191 if "portage_confdir" in self.settings:
192 file_locate(self.settings,["portage_confdir"],expand=0)
194 """ Setup our mount points """
195 # initialize our target mounts.
196 self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy()
197 if "SNAPCACHE" in self.settings:
198 self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
201 "devpts": "/dev/pts",
202 "distdir": self.settings["distdir"],
203 "portdir": normpath("/".join([
204 self.settings["snapshot_cache_path"],
205 self.settings["repo_name"],
207 "port_tmpdir": "tmpfs",
211 self.mounts = ["proc", "dev", "distdir", "port_tmpdir"]
212 self.mountmap = {"proc":"/proc", "dev":"/dev", "devpts":"/dev/pts",
213 "distdir":self.settings["distdir"], "port_tmpdir":"tmpfs"}
214 if os.uname()[0] == "Linux":
215 self.mounts.append("devpts")
220 Configure any user specified options (either in catalyst.conf or on
223 if "PKGCACHE" in self.settings:
224 self.set_pkgcache_path()
225 print "Location of the package cache is "+\
226 self.settings["pkgcache_path"]
227 self.mounts.append("packagedir")
228 self.mountmap["packagedir"] = self.settings["pkgcache_path"]
230 if "KERNCACHE" in self.settings:
231 self.set_kerncache_path()
232 print "Location of the kerncache is "+\
233 self.settings["kerncache_path"]
234 self.mounts.append("kerncache")
235 self.mountmap["kerncache"] = self.settings["kerncache_path"]
237 if "CCACHE" in self.settings:
238 if "CCACHE_DIR" in os.environ:
239 ccdir=os.environ["CCACHE_DIR"]
240 del os.environ["CCACHE_DIR"]
242 ccdir="/root/.ccache"
243 if not os.path.isdir(ccdir):
244 raise CatalystError,\
245 "Compiler cache support can't be enabled (can't find "+\
247 self.mounts.append("ccache")
248 self.mountmap["ccache"] = ccdir
249 """ for the chroot: """
250 self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
252 if "ICECREAM" in self.settings:
253 self.mounts.append("icecream")
254 self.mountmap["icecream"] = self.settings["icecream"]
255 self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
258 if "port_logdir" in self.settings:
259 self.mounts.append("port_logdir")
260 self.mountmap["port_logdir"] = self.settings["port_logdir"]
261 self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
262 self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
264 def override_cbuild(self):
265 if "CBUILD" in self.makeconf:
266 self.settings["CBUILD"]=self.makeconf["CBUILD"]
268 def override_chost(self):
269 if "CHOST" in self.makeconf:
270 self.settings["CHOST"]=self.makeconf["CHOST"]
272 def override_cflags(self):
273 if "CFLAGS" in self.makeconf:
274 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
276 def override_cxxflags(self):
277 if "CXXFLAGS" in self.makeconf:
278 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
280 def override_ldflags(self):
281 if "LDFLAGS" in self.makeconf:
282 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
284 def set_install_mask(self):
285 if "install_mask" in self.settings:
286 if type(self.settings["install_mask"])!=types.StringType:
287 self.settings["install_mask"]=\
288 string.join(self.settings["install_mask"])
290 def set_spec_prefix(self):
291 self.settings["spec_prefix"]=self.settings["target"]
293 def set_target_profile(self):
294 self.settings["target_profile"]=self.settings["profile"]
296 def set_target_subpath(self):
297 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
298 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
299 self.settings["version_stamp"]
301 def set_source_subpath(self):
302 if type(self.settings["source_subpath"])!=types.StringType:
303 raise CatalystError,\
304 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
306 def set_pkgcache_path(self):
307 if "pkgcache_path" in self.settings:
308 if type(self.settings["pkgcache_path"])!=types.StringType:
309 self.settings["pkgcache_path"]=\
310 normpath(string.join(self.settings["pkgcache_path"]))
312 self.settings["pkgcache_path"]=\
313 normpath(self.settings["storedir"]+"/packages/"+\
314 self.settings["target_subpath"]+"/")
316 def set_kerncache_path(self):
317 if "kerncache_path" in self.settings:
318 if type(self.settings["kerncache_path"])!=types.StringType:
319 self.settings["kerncache_path"]=\
320 normpath(string.join(self.settings["kerncache_path"]))
322 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
323 "/kerncache/"+self.settings["target_subpath"]+"/")
325 def set_target_path(self):
326 self.settings["target_path"]=normpath(self.settings["storedir"]+\
327 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
328 if "AUTORESUME" in self.settings\
329 and os.path.exists(self.settings["autoresume_path"]+\
330 "setup_target_path"):
332 "Resume point detected, skipping target path setup operation..."
334 """ First clean up any existing target stuff """
335 # XXX WTF are we removing the old tarball before we start building the
336 # XXX new one? If the build fails, you don't want to be left with
338 # if os.path.isfile(self.settings["target_path"]):
339 # cmd("rm -f "+self.settings["target_path"],\
340 # "Could not remove existing file: "\
341 # +self.settings["target_path"],env=self.env)
342 touch(self.settings["autoresume_path"]+"setup_target_path")
344 if not os.path.exists(self.settings["storedir"]+"/builds/"):
345 os.makedirs(self.settings["storedir"]+"/builds/")
347 def set_fsscript(self):
348 if self.settings["spec_prefix"]+"/fsscript" in self.settings:
349 self.settings["fsscript"]=\
350 self.settings[self.settings["spec_prefix"]+"/fsscript"]
351 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
354 if self.settings["spec_prefix"]+"/rcadd" in self.settings:
355 self.settings["rcadd"]=\
356 self.settings[self.settings["spec_prefix"]+"/rcadd"]
357 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
360 if self.settings["spec_prefix"]+"/rcdel" in self.settings:
361 self.settings["rcdel"]=\
362 self.settings[self.settings["spec_prefix"]+"/rcdel"]
363 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
366 if self.settings["spec_prefix"]+"/cdtar" in self.settings:
367 self.settings["cdtar"]=\
368 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
369 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
372 if self.settings["spec_prefix"]+"/iso" in self.settings:
373 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
374 self.settings["iso"]=\
375 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
377 # This automatically prepends the build dir to the ISO output path
378 # if it doesn't start with a /
379 self.settings["iso"] = normpath(self.settings["storedir"] + \
380 "/builds/" + self.settings["rel_type"] + "/" + \
381 self.settings[self.settings["spec_prefix"]+"/iso"])
382 del self.settings[self.settings["spec_prefix"]+"/iso"]
384 def set_fstype(self):
385 if self.settings["spec_prefix"]+"/fstype" in self.settings:
386 self.settings["fstype"]=\
387 self.settings[self.settings["spec_prefix"]+"/fstype"]
388 del self.settings[self.settings["spec_prefix"]+"/fstype"]
390 if "fstype" not in self.settings:
391 self.settings["fstype"]="normal"
392 for x in self.valid_values:
393 if x == self.settings["spec_prefix"]+"/fstype":
394 print "\n"+self.settings["spec_prefix"]+\
395 "/fstype is being set to the default of \"normal\"\n"
398 if "fstype" in self.settings:
399 self.valid_values.append("fsops")
400 if self.settings["spec_prefix"]+"/fsops" in self.settings:
401 self.settings["fsops"]=\
402 self.settings[self.settings["spec_prefix"]+"/fsops"]
403 del self.settings[self.settings["spec_prefix"]+"/fsops"]
405 def set_source_path(self):
406 if "SEEDCACHE" in self.settings\
407 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
408 self.settings["source_subpath"]+"/")):
409 self.settings["source_path"]=normpath(self.settings["storedir"]+\
410 "/tmp/"+self.settings["source_subpath"]+"/")
412 self.settings["source_path"]=normpath(self.settings["storedir"]+\
413 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
414 if os.path.isfile(self.settings["source_path"]):
415 # XXX: Is this even necessary if the previous check passes?
416 if os.path.exists(self.settings["source_path"]):
417 self.settings["source_path_hash"]=\
418 generate_hash(self.settings["source_path"],\
419 hash_function=self.settings["hash_function"],\
421 print "Source path set to "+self.settings["source_path"]
422 if os.path.isdir(self.settings["source_path"]):
423 print "\tIf this is not desired, remove this directory or turn off"
424 print "\tseedcache in the options of catalyst.conf the source path"
425 print "\twill then be "+\
426 normpath(self.settings["storedir"]+"/builds/"+\
427 self.settings["source_subpath"]+".tar.bz2\n")
429 def set_dest_path(self):
430 if "root_path" in self.settings:
431 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
432 self.settings["root_path"])
434 self.settings["destpath"]=normpath(self.settings["chroot_path"])
436 def set_cleanables(self):
437 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
438 "/root/*", self.settings["portdir"]]
440 def set_snapshot_path(self):
441 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
442 "/snapshots/" + self.settings["snapshot_name"] +
443 self.settings["snapshot"] + ".tar.xz")
445 if os.path.exists(self.settings["snapshot_path"]):
446 self.settings["snapshot_path_hash"]=\
447 generate_hash(self.settings["snapshot_path"],\
448 hash_function=self.settings["hash_function"],verbose=False)
450 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
451 "/snapshots/" + self.settings["snapshot_name"] +
452 self.settings["snapshot"] + ".tar.bz2")
454 if os.path.exists(self.settings["snapshot_path"]):
455 self.settings["snapshot_path_hash"]=\
456 generate_hash(self.settings["snapshot_path"],\
457 hash_function=self.settings["hash_function"],verbose=False)
459 def set_snapcache_path(self):
460 if "SNAPCACHE" in self.settings:
461 self.settings["snapshot_cache_path"]=\
462 normpath(self.settings["snapshot_cache"]+"/"+\
463 self.settings["snapshot"]+"/")
464 self.snapcache_lock=\
465 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
466 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
468 def set_chroot_path(self):
470 NOTE: the trailing slash is very important!
471 Things *will* break without it!
473 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
474 "/tmp/"+self.settings["target_subpath"]+"/")
475 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
477 def set_autoresume_path(self):
478 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
479 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
480 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
481 self.settings["version_stamp"]+"/")
482 if "AUTORESUME" in self.settings:
483 print "The autoresume path is " + self.settings["autoresume_path"]
484 if not os.path.exists(self.settings["autoresume_path"]):
485 os.makedirs(self.settings["autoresume_path"],0755)
487 def set_controller_file(self):
488 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
489 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
492 def set_iso_volume_id(self):
493 if self.settings["spec_prefix"]+"/volid" in self.settings:
494 self.settings["iso_volume_id"]=\
495 self.settings[self.settings["spec_prefix"]+"/volid"]
496 if len(self.settings["iso_volume_id"])>32:
497 raise CatalystError,\
498 "ISO volume ID must not exceed 32 characters."
500 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
502 def set_action_sequence(self):
503 """ Default action sequence for run method """
504 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
505 "setup_confdir","portage_overlay",\
506 "base_dirs","bind","chroot_setup","setup_environment",\
507 "run_local","preclean","unbind","clean"]
508 # if "TARBALL" in self.settings or \
509 # "FETCH" not in self.settings:
510 if "FETCH" not in self.settings:
511 self.settings["action_sequence"].append("capture")
512 self.settings["action_sequence"].append("clear_autoresume")
515 if self.settings["spec_prefix"]+"/use" in self.settings:
516 self.settings["use"]=\
517 self.settings[self.settings["spec_prefix"]+"/use"]
518 del self.settings[self.settings["spec_prefix"]+"/use"]
519 if "use" not in self.settings:
520 self.settings["use"]=""
521 if type(self.settings["use"])==types.StringType:
522 self.settings["use"]=self.settings["use"].split()
524 # Force bindist when options ask for it
525 if "BINDIST" in self.settings:
526 self.settings["use"].append("bindist")
528 def set_stage_path(self):
529 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
531 def set_mounts(self):
534 def set_packages(self):
538 if self.settings["spec_prefix"]+"/rm" in self.settings:
539 if type(self.settings[self.settings["spec_prefix"]+\
540 "/rm"])==types.StringType:
541 self.settings[self.settings["spec_prefix"]+"/rm"]=\
542 self.settings[self.settings["spec_prefix"]+"/rm"].split()
544 def set_linuxrc(self):
545 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
546 if type(self.settings[self.settings["spec_prefix"]+\
547 "/linuxrc"])==types.StringType:
548 self.settings["linuxrc"]=\
549 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
550 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
552 def set_busybox_config(self):
553 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
554 if type(self.settings[self.settings["spec_prefix"]+\
555 "/busybox_config"])==types.StringType:
556 self.settings["busybox_config"]=\
557 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
558 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
560 def set_portage_overlay(self):
561 if "portage_overlay" in self.settings:
562 if type(self.settings["portage_overlay"])==types.StringType:
563 self.settings["portage_overlay"]=\
564 self.settings["portage_overlay"].split()
565 print "portage_overlay directories are set to: \""+\
566 string.join(self.settings["portage_overlay"])+"\""
568 def set_overlay(self):
569 if self.settings["spec_prefix"]+"/overlay" in self.settings:
570 if type(self.settings[self.settings["spec_prefix"]+\
571 "/overlay"])==types.StringType:
572 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
573 self.settings[self.settings["spec_prefix"]+\
576 def set_root_overlay(self):
577 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
578 if type(self.settings[self.settings["spec_prefix"]+\
579 "/root_overlay"])==types.StringType:
580 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
581 self.settings[self.settings["spec_prefix"]+\
582 "/root_overlay"].split()
584 def set_root_path(self):
585 """ ROOT= variable for emerges """
586 self.settings["root_path"]="/"
588 def set_valid_build_kernel_vars(self,addlargs):
589 if "boot/kernel" in addlargs:
590 if type(addlargs["boot/kernel"])==types.StringType:
591 loopy=[addlargs["boot/kernel"]]
593 loopy=addlargs["boot/kernel"]
596 self.valid_values.append("boot/kernel/"+x+"/aliases")
597 self.valid_values.append("boot/kernel/"+x+"/config")
598 self.valid_values.append("boot/kernel/"+x+"/console")
599 self.valid_values.append("boot/kernel/"+x+"/extraversion")
600 self.valid_values.append("boot/kernel/"+x+"/gk_action")
601 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
602 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
603 self.valid_values.append("boot/kernel/"+x+"/machine_type")
604 self.valid_values.append("boot/kernel/"+x+"/sources")
605 self.valid_values.append("boot/kernel/"+x+"/softlevel")
606 self.valid_values.append("boot/kernel/"+x+"/use")
607 self.valid_values.append("boot/kernel/"+x+"/packages")
608 if "boot/kernel/"+x+"/packages" in addlargs:
609 if type(addlargs["boot/kernel/"+x+\
610 "/packages"])==types.StringType:
611 addlargs["boot/kernel/"+x+"/packages"]=\
612 [addlargs["boot/kernel/"+x+"/packages"]]
614 def set_build_kernel_vars(self):
615 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
616 self.settings["gk_mainargs"]=\
617 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
618 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
620 def kill_chroot_pids(self):
621 print "Checking for processes running in chroot and killing them."
624 Force environment variables to be exported so script can see them
626 self.setup_environment()
628 if os.path.exists(self.settings["sharedir"]+\
629 "/targets/support/kill-chroot-pids.sh"):
630 cmd("/bin/bash "+self.settings["sharedir"]+\
631 "/targets/support/kill-chroot-pids.sh",\
632 "kill-chroot-pids script failed.",env=self.env)
634 def mount_safety_check(self):
636 Check and verify that none of our paths in mypath are mounted. We don't
637 want to clean up with things still mounted, and this allows us to check.
638 Returns 1 on ok, 0 on "something is still mounted" case.
641 if not os.path.exists(self.settings["chroot_path"]):
644 print "self.mounts =", self.mounts
645 for x in self.mounts:
646 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
647 print "mount_safety_check() x =", x, target
648 if not os.path.exists(target):
652 """ Something is still mounted "" """
654 print target + " is still mounted; performing auto-bind-umount...",
655 """ Try to umount stuff ourselves """
658 raise CatalystError, "Auto-unbind failed for " + target
660 print "Auto-unbind successful..."
661 except CatalystError:
662 raise CatalystError, "Unable to auto-unbind " + target
667 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
670 if "SEEDCACHE" in self.settings:
671 if os.path.isdir(self.settings["source_path"]):
672 """ SEEDCACHE Is a directory, use rsync """
673 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
674 " "+self.settings["chroot_path"]
675 display_msg="\nStarting rsync from "+\
676 self.settings["source_path"]+"\nto "+\
677 self.settings["chroot_path"]+\
678 " (This may take some time) ...\n"
679 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
680 self.settings["chroot_path"]+" failed."
682 """ SEEDCACHE is a not a directory, try untar'ing """
683 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
684 display_msg="\nStarting tar extract from "+\
685 self.settings["source_path"]+"\nto "+\
686 self.settings["chroot_path"]+\
687 " (This may take some time) ...\n"
688 if "bz2" == self.settings["chroot_path"][-3:]:
689 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
690 self.settings["chroot_path"]
692 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
693 self.settings["chroot_path"]
694 error_msg="Tarball extraction of "+\
695 self.settings["source_path"]+" to "+\
696 self.settings["chroot_path"]+" failed."
698 """ No SEEDCACHE, use tar """
699 display_msg="\nStarting tar extract from "+\
700 self.settings["source_path"]+"\nto "+\
701 self.settings["chroot_path"]+\
702 " (This may take some time) ...\n"
703 if "bz2" == self.settings["chroot_path"][-3:]:
704 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
705 self.settings["chroot_path"]
707 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
708 self.settings["chroot_path"]
709 error_msg="Tarball extraction of "+self.settings["source_path"]+\
710 " to "+self.settings["chroot_path"]+" failed."
712 if "AUTORESUME" in self.settings:
713 if os.path.isdir(self.settings["source_path"]) \
714 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
715 """ Autoresume is valid, SEEDCACHE is valid """
717 invalid_snapshot=False
719 elif os.path.isfile(self.settings["source_path"]) \
720 and self.settings["source_path_hash"]==clst_unpack_hash:
721 """ Autoresume is valid, tarball is valid """
723 invalid_snapshot=True
725 elif os.path.isdir(self.settings["source_path"]) \
726 and not os.path.exists(self.settings["autoresume_path"]+\
728 """ Autoresume is invalid, SEEDCACHE """
730 invalid_snapshot=False
732 elif os.path.isfile(self.settings["source_path"]) \
733 and self.settings["source_path_hash"]!=clst_unpack_hash:
734 """ Autoresume is invalid, tarball """
736 invalid_snapshot=True
738 """ No autoresume, SEEDCACHE """
739 if "SEEDCACHE" in self.settings:
740 """ SEEDCACHE so let's run rsync and let it clean up """
741 if os.path.isdir(self.settings["source_path"]):
743 invalid_snapshot=False
744 elif os.path.isfile(self.settings["source_path"]):
745 """ Tarball so unpack and remove anything already there """
747 invalid_snapshot=True
748 """ No autoresume, no SEEDCACHE """
750 """ Tarball so unpack and remove anything already there """
751 if os.path.isfile(self.settings["source_path"]):
753 invalid_snapshot=True
754 elif os.path.isdir(self.settings["source_path"]):
755 """ We should never reach this, so something is very wrong """
756 raise CatalystError,\
757 "source path is a dir but seedcache is not enabled"
760 self.mount_safety_check()
763 if "AUTORESUME" in self.settings:
764 print "No Valid Resume point detected, cleaning up..."
766 self.clear_autoresume()
769 if not os.path.exists(self.settings["chroot_path"]):
770 os.makedirs(self.settings["chroot_path"])
772 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
773 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
775 if "PKGCACHE" in self.settings:
776 if not os.path.exists(self.settings["pkgcache_path"]):
777 os.makedirs(self.settings["pkgcache_path"],0755)
779 if "KERNCACHE" in self.settings:
780 if not os.path.exists(self.settings["kerncache_path"]):
781 os.makedirs(self.settings["kerncache_path"],0755)
784 cmd(unpack_cmd,error_msg,env=self.env)
786 if "source_path_hash" in self.settings:
787 myf=open(self.settings["autoresume_path"]+"unpack","w")
788 myf.write(self.settings["source_path_hash"])
791 touch(self.settings["autoresume_path"]+"unpack")
793 print "Resume point detected, skipping unpack operation..."
795 def unpack_snapshot(self):
797 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
800 if "SNAPCACHE" in self.settings:
801 snapshot_cache_hash=\
802 read_from_clst(self.settings["snapshot_cache_path"]+\
804 destdir=self.settings["snapshot_cache_path"]
805 if "bz2" == self.settings["chroot_path"][-3:]:
806 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
808 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
809 unpack_errmsg="Error unpacking snapshot"
810 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
811 self.settings["snapshot_cache_path"]+\
812 " (This can take a long time)..."
813 cleanup_errmsg="Error removing existing snapshot cache directory."
814 self.snapshot_lock_object=self.snapcache_lock
816 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
817 print "Valid snapshot cache, skipping unpack of portage tree..."
820 destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
821 cleanup_errmsg="Error removing existing snapshot directory."
823 "Cleaning up existing portage tree (This can take a long time)..."
824 if "bz2" == self.settings["chroot_path"][-3:]:
825 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
826 self.settings["chroot_path"]+"/usr"
828 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
829 self.settings["chroot_path"]+"/usr"
830 unpack_errmsg="Error unpacking snapshot"
832 if "AUTORESUME" in self.settings \
833 and os.path.exists(self.settings["chroot_path"]+\
834 self.settings["portdir"]) \
835 and os.path.exists(self.settings["autoresume_path"]\
837 and self.settings["snapshot_path_hash"] == snapshot_hash:
839 "Valid Resume point detected, skipping unpack of portage tree..."
843 if "SNAPCACHE" in self.settings:
844 self.snapshot_lock_object.write_lock()
845 if os.path.exists(destdir):
847 cleanup_cmd="rm -rf "+destdir
848 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
849 if not os.path.exists(destdir):
850 os.makedirs(destdir,0755)
852 print "Unpacking portage tree (This can take a long time) ..."
853 cmd(unpack_cmd,unpack_errmsg,env=self.env)
855 if "SNAPCACHE" in self.settings:
856 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
857 myf.write(self.settings["snapshot_path_hash"])
860 print "Setting snapshot autoresume point"
861 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
862 myf.write(self.settings["snapshot_path_hash"])
865 if "SNAPCACHE" in self.settings:
866 self.snapshot_lock_object.unlock()
868 def config_profile_link(self):
869 if "AUTORESUME" in self.settings \
870 and os.path.exists(self.settings["autoresume_path"]+\
871 "config_profile_link"):
873 "Resume point detected, skipping config_profile_link operation..."
875 # TODO: zmedico and I discussed making this a directory and pushing
876 # in a parent file, as well as other user-specified configuration.
877 print "Configuring profile link..."
878 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
879 "Error zapping profile link",env=self.env)
880 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
881 cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
882 self.settings["target_profile"]+" "+\
883 self.settings["chroot_path"]+"/etc/portage/make.profile",\
884 "Error creating profile link",env=self.env)
885 touch(self.settings["autoresume_path"]+"config_profile_link")
887 def setup_confdir(self):
888 if "AUTORESUME" in self.settings \
889 and os.path.exists(self.settings["autoresume_path"]+\
891 print "Resume point detected, skipping setup_confdir operation..."
893 if "portage_confdir" in self.settings:
894 print "Configuring /etc/portage..."
895 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
896 self.settings["chroot_path"]+"/etc/portage/",\
897 "Error copying /etc/portage",env=self.env)
898 touch(self.settings["autoresume_path"]+"setup_confdir")
900 def portage_overlay(self):
901 """ We copy the contents of our overlays to /usr/local/portage """
902 if "portage_overlay" in self.settings:
903 for x in self.settings["portage_overlay"]:
904 if os.path.exists(x):
905 print "Copying overlay dir " +x
906 cmd("mkdir -p "+self.settings["chroot_path"]+\
907 self.settings["local_overlay"],\
908 "Could not make portage_overlay dir",env=self.env)
909 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
910 self.settings["local_overlay"],\
911 "Could not copy portage_overlay",env=self.env)
913 def root_overlay(self):
914 """ Copy over the root_overlay """
915 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
916 for x in self.settings[self.settings["spec_prefix"]+\
918 if os.path.exists(x):
919 print "Copying root_overlay: "+x
920 cmd("rsync -a "+x+"/ "+\
921 self.settings["chroot_path"],\
922 self.settings["spec_prefix"]+"/root_overlay: "+x+\
923 " copy failed.",env=self.env)
929 for x in self.mounts:
930 #print "bind(); x =", x
931 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
932 if not os.path.exists(target):
933 os.makedirs(target, 0755)
935 if not os.path.exists(self.mountmap[x]):
936 if not self.mountmap[x] == "tmpfs":
937 os.makedirs(self.mountmap[x], 0755)
940 #print "bind(); src =", src
941 if "SNAPCACHE" in self.settings and x == "portdir":
942 self.snapshot_lock_object.read_lock()
943 if os.uname()[0] == "FreeBSD":
945 cmd = "mount -t devfs none " + target
946 retval=os.system(cmd)
948 cmd = "mount_nullfs " + src + " " + target
949 retval=os.system(cmd)
952 if "var_tmpfs_portage" in self.settings:
953 cmd = "mount -t tmpfs -o size=" + \
954 self.settings["var_tmpfs_portage"] + "G " + \
956 retval=os.system(cmd)
958 cmd = "mount --bind " + src + " " + target
959 #print "bind(); cmd =", cmd
960 retval=os.system(cmd)
963 raise CatalystError,"Couldn't bind mount " + src
967 mypath=self.settings["chroot_path"]
968 myrevmounts=self.mounts[:]
969 myrevmounts.reverse()
970 """ Unmount in reverse order for nested bind-mounts """
971 for x in myrevmounts:
972 target = normpath(mypath + self.target_mounts[x])
973 if not os.path.exists(target):
976 if not ismount(target):
979 retval=os.system("umount " + target)
982 warn("First attempt to unmount: " + target + " failed.")
983 warn("Killing any pids still running in the chroot")
985 self.kill_chroot_pids()
987 retval2 = os.system("umount " + target)
990 warn("Couldn't umount bind mount: " + target)
992 if "SNAPCACHE" in self.settings and x == "/usr/portage":
995 It's possible the snapshot lock object isn't created yet.
996 This is because mount safety check calls unbind before the
997 target is fully initialized
999 self.snapshot_lock_object.unlock()
1004 if any bind mounts really failed, then we need to raise
1005 this to potentially prevent an upcoming bash stage cleanup script
1006 from wiping our bind mounts.
1008 raise CatalystError,\
1009 "Couldn't umount one or more bind-mounts; aborting for safety."
1011 def chroot_setup(self):
1012 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
1013 "/etc/portage/make.conf")
1014 self.override_cbuild()
1015 self.override_chost()
1016 self.override_cflags()
1017 self.override_cxxflags()
1018 self.override_ldflags()
1019 if "AUTORESUME" in self.settings \
1020 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
1021 print "Resume point detected, skipping chroot_setup operation..."
1023 print "Setting up chroot..."
1025 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
1027 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1028 "Could not copy resolv.conf into place.",env=self.env)
1030 """ Copy over the envscript, if applicable """
1031 if "ENVSCRIPT" in self.settings:
1032 if not os.path.exists(self.settings["ENVSCRIPT"]):
1033 raise CatalystError,\
1034 "Can't find envscript "+self.settings["ENVSCRIPT"]
1036 print "\nWarning!!!!"
1037 print "\tOverriding certain env variables may cause catastrophic failure."
1038 print "\tIf your build fails look here first as the possible problem."
1039 print "\tCatalyst assumes you know what you are doing when setting"
1040 print "\t\tthese variables."
1041 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1042 print "\tYou have been warned\n"
1044 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1045 self.settings["chroot_path"]+"/tmp/envscript",\
1046 "Could not copy envscript into place.",env=self.env)
1049 Copy over /etc/hosts from the host in case there are any
1050 specialties in there
1052 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1053 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1054 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1055 "Could not backup /etc/hosts",env=self.env)
1056 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1057 "Could not copy /etc/hosts",env=self.env)
1059 """ Modify and write out make.conf (for the chroot) """
1060 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1061 "Could not remove "+self.settings["chroot_path"]+\
1062 "/etc/portage/make.conf",env=self.env)
1063 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1064 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1065 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1066 if "CFLAGS" in self.settings:
1067 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1068 if "CXXFLAGS" in self.settings:
1069 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1070 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1072 myf.write('CXXFLAGS="${CFLAGS}"\n')
1074 myf.write('CXXFLAGS="${CFLAGS}"\n')
1076 if "LDFLAGS" in self.settings:
1077 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1078 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1079 if "CBUILD" in self.settings:
1080 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")
1081 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1083 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")
1084 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1086 """ Figure out what our USE vars are for building """
1088 if "HOSTUSE" in self.settings:
1089 myusevars.extend(self.settings["HOSTUSE"])
1091 if "use" in self.settings:
1092 myusevars.extend(self.settings["use"])
1095 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1096 myusevars = sorted(set(myusevars))
1097 myf.write('USE="'+string.join(myusevars)+'"\n')
1098 if '-*' in myusevars:
1099 print "\nWarning!!! "
1100 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1101 "/use will cause portage to ignore"
1102 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1104 myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
1105 myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
1106 myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
1108 """ Setup the portage overlay """
1109 if "portage_overlay" in self.settings:
1110 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1113 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1114 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1115 "Could not backup /etc/portage/make.conf",env=self.env)
1116 touch(self.settings["autoresume_path"]+"chroot_setup")
1119 if "AUTORESUME" in self.settings \
1120 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1121 print "Resume point detected, skipping fsscript operation..."
1123 if "fsscript" in self.settings:
1124 if os.path.exists(self.settings["controller_file"]):
1125 cmd("/bin/bash "+self.settings["controller_file"]+\
1126 " fsscript","fsscript script failed.",env=self.env)
1127 touch(self.settings["autoresume_path"]+"fsscript")
1130 if "AUTORESUME" in self.settings \
1131 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1132 print "Resume point detected, skipping rcupdate operation..."
1134 if os.path.exists(self.settings["controller_file"]):
1135 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1136 "rc-update script failed.",env=self.env)
1137 touch(self.settings["autoresume_path"]+"rcupdate")
1140 if "AUTORESUME" in self.settings \
1141 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1142 print "Resume point detected, skipping clean operation..."
1144 for x in self.settings["cleanables"]:
1145 print "Cleaning chroot: "+x+"... "
1146 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1149 """ Put /etc/hosts back into place """
1150 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1151 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1152 self.settings["chroot_path"]+"/etc/hosts",\
1153 "Could not replace /etc/hosts",env=self.env)
1155 """ Remove our overlay """
1156 if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
1157 cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
1158 "Could not remove " + self.settings["local_overlay"], env=self.env)
1159 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1160 "/etc/portage/make.conf",\
1161 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1163 """ Clean up old and obsoleted files in /etc """
1164 if os.path.exists(self.settings["stage_path"]+"/etc"):
1165 cmd("find "+self.settings["stage_path"]+\
1166 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1167 "Could not remove stray files in /etc",env=self.env)
1169 if os.path.exists(self.settings["controller_file"]):
1170 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1171 "clean script failed.",env=self.env)
1172 touch(self.settings["autoresume_path"]+"clean")
1175 if "AUTORESUME" in self.settings \
1176 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1177 print "Resume point detected, skipping empty operation..."
1179 if self.settings["spec_prefix"]+"/empty" in self.settings:
1180 if type(self.settings[self.settings["spec_prefix"]+\
1181 "/empty"])==types.StringType:
1182 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1183 self.settings[self.settings["spec_prefix"]+\
1185 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1186 myemp=self.settings["destpath"]+x
1187 if not os.path.isdir(myemp) or os.path.islink(myemp):
1188 print x,"not a directory or does not exist, skipping 'empty' operation."
1190 print "Emptying directory",x
1192 stat the dir, delete the dir, recreate the dir and set
1193 the proper perms and ownership
1195 mystat=os.stat(myemp)
1196 shutil.rmtree(myemp)
1197 os.makedirs(myemp,0755)
1198 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1199 os.chmod(myemp,mystat[ST_MODE])
1200 touch(self.settings["autoresume_path"]+"empty")
1203 if "AUTORESUME" in self.settings \
1204 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1205 print "Resume point detected, skipping remove operation..."
1207 if self.settings["spec_prefix"]+"/rm" in self.settings:
1208 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1210 We're going to shell out for all these cleaning
1211 operations, so we get easy glob handling.
1213 print "livecd: removing "+x
1214 os.system("rm -rf "+self.settings["chroot_path"]+x)
1216 if os.path.exists(self.settings["controller_file"]):
1217 cmd("/bin/bash "+self.settings["controller_file"]+\
1218 " clean","Clean failed.",env=self.env)
1219 touch(self.settings["autoresume_path"]+"remove")
1225 if "AUTORESUME" in self.settings \
1226 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1227 print "Resume point detected, skipping preclean operation..."
1230 if os.path.exists(self.settings["controller_file"]):
1231 cmd("/bin/bash "+self.settings["controller_file"]+\
1232 " preclean","preclean script failed.",env=self.env)
1233 touch(self.settings["autoresume_path"]+"preclean")
1237 raise CatalystError, "Build failed, could not execute preclean"
1240 if "AUTORESUME" in self.settings \
1241 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1242 print "Resume point detected, skipping capture operation..."
1244 """ Capture target in a tarball """
1245 mypath=self.settings["target_path"].split("/")
1246 """ Remove filename from path """
1247 mypath=string.join(mypath[:-1],"/")
1249 """ Now make sure path exists """
1250 if not os.path.exists(mypath):
1253 print "Creating stage tarball..."
1255 cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1256 self.settings["stage_path"]+" .",\
1257 "Couldn't create stage tarball",env=self.env)
1259 self.gen_contents_file(self.settings["target_path"])
1260 self.gen_digest_file(self.settings["target_path"])
1262 touch(self.settings["autoresume_path"]+"capture")
1264 def run_local(self):
1265 if "AUTORESUME" in self.settings \
1266 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1267 print "Resume point detected, skipping run_local operation..."
1270 if os.path.exists(self.settings["controller_file"]):
1271 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1272 "run script failed.",env=self.env)
1273 touch(self.settings["autoresume_path"]+"run_local")
1275 except CatalystError:
1277 raise CatalystError,"Stage build aborting due to error."
1279 def setup_environment(self):
1281 Modify the current environment. This is an ugly hack that should be
1282 fixed. We need this to use the os.system() call since we can't
1283 specify our own environ
1285 for x in self.settings.keys():
1286 """ Sanitize var names by doing "s|/-.|_|g" """
1287 varname="clst_"+string.replace(x,"/","_")
1288 varname=string.replace(varname,"-","_")
1289 varname=string.replace(varname,".","_")
1290 if type(self.settings[x])==types.StringType:
1291 """ Prefix to prevent namespace clashes """
1292 #os.environ[varname]=self.settings[x]
1293 self.env[varname]=self.settings[x]
1294 elif type(self.settings[x])==types.ListType:
1295 #os.environ[varname]=string.join(self.settings[x])
1296 self.env[varname]=string.join(self.settings[x])
1297 elif type(self.settings[x])==types.BooleanType:
1298 if self.settings[x]:
1299 self.env[varname]="true"
1301 self.env[varname]="false"
1302 if "makeopts" in self.settings:
1303 self.env["MAKEOPTS"]=self.settings["makeopts"]
1306 self.chroot_lock.write_lock()
1308 """ Kill any pids in the chroot "" """
1309 self.kill_chroot_pids()
1311 """ Check for mounts right away and abort if we cannot unmount them """
1312 self.mount_safety_check()
1314 if "CLEAR_AUTORESUME" in self.settings:
1315 self.clear_autoresume()
1317 if "PURGETMPONLY" in self.settings:
1321 if "PURGEONLY" in self.settings:
1325 if "PURGE" in self.settings:
1328 for x in self.settings["action_sequence"]:
1329 print "--- Running action sequence: "+x
1332 apply(getattr(self,x))
1334 self.mount_safety_check()
1337 self.chroot_lock.unlock()
1340 if "AUTORESUME" in self.settings \
1341 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1342 print "Resume point detected, skipping unmerge operation..."
1344 if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1345 if type(self.settings[self.settings["spec_prefix"]+\
1346 "/unmerge"])==types.StringType:
1347 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1348 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1350 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1352 for x in range(0,len(myunmerge)):
1354 Surround args with quotes for passing to bash, allows
1355 things like "<" to remain intact
1357 myunmerge[x]="'"+myunmerge[x]+"'"
1358 myunmerge=string.join(myunmerge)
1360 """ Before cleaning, unmerge stuff """
1362 cmd("/bin/bash "+self.settings["controller_file"]+\
1363 " unmerge "+ myunmerge,"Unmerge script failed.",\
1365 print "unmerge shell script"
1366 except CatalystError:
1369 touch(self.settings["autoresume_path"]+"unmerge")
1371 def target_setup(self):
1372 if "AUTORESUME" in self.settings \
1373 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1374 print "Resume point detected, skipping target_setup operation..."
1376 print "Setting up filesystems per filesystem type"
1377 cmd("/bin/bash "+self.settings["controller_file"]+\
1378 " target_image_setup "+ self.settings["target_path"],\
1379 "target_image_setup script failed.",env=self.env)
1380 touch(self.settings["autoresume_path"]+"target_setup")
1382 def setup_overlay(self):
1383 if "AUTORESUME" in self.settings \
1384 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1385 print "Resume point detected, skipping setup_overlay operation..."
1387 if self.settings["spec_prefix"]+"/overlay" in self.settings:
1388 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1389 if os.path.exists(x):
1390 cmd("rsync -a "+x+"/ "+\
1391 self.settings["target_path"],\
1392 self.settings["spec_prefix"]+"overlay: "+x+\
1393 " copy failed.",env=self.env)
1394 touch(self.settings["autoresume_path"]+"setup_overlay")
1396 def create_iso(self):
1397 if "AUTORESUME" in self.settings \
1398 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1399 print "Resume point detected, skipping create_iso operation..."
1401 """ Create the ISO """
1402 if "iso" in self.settings:
1403 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1404 self.settings["iso"],"ISO creation script failed.",\
1406 self.gen_contents_file(self.settings["iso"])
1407 self.gen_digest_file(self.settings["iso"])
1408 touch(self.settings["autoresume_path"]+"create_iso")
1410 print "WARNING: livecd/iso was not defined."
1411 print "An ISO Image will not be created."
1413 def build_packages(self):
1414 if "AUTORESUME" in self.settings \
1415 and os.path.exists(self.settings["autoresume_path"]+\
1417 print "Resume point detected, skipping build_packages operation..."
1419 if self.settings["spec_prefix"]+"/packages" in self.settings:
1420 if "AUTORESUME" in self.settings \
1421 and os.path.exists(self.settings["autoresume_path"]+\
1423 print "Resume point detected, skipping build_packages operation..."
1426 list_bashify(self.settings[self.settings["spec_prefix"]\
1429 cmd("/bin/bash "+self.settings["controller_file"]+\
1430 " build_packages "+mypack,\
1431 "Error in attempt to build packages",env=self.env)
1432 touch(self.settings["autoresume_path"]+"build_packages")
1433 except CatalystError:
1435 raise CatalystError,self.settings["spec_prefix"]+\
1436 "build aborting due to error."
1438 def build_kernel(self):
1439 "Build all configured kernels"
1440 if "AUTORESUME" in self.settings \
1441 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1442 print "Resume point detected, skipping build_kernel operation..."
1444 if "boot/kernel" in self.settings:
1446 mynames=self.settings["boot/kernel"]
1447 if type(mynames)==types.StringType:
1450 Execute the script that sets up the kernel build environment
1452 cmd("/bin/bash "+self.settings["controller_file"]+\
1453 " pre-kmerge ","Runscript pre-kmerge failed",\
1455 for kname in mynames:
1456 self._build_kernel(kname=kname)
1457 touch(self.settings["autoresume_path"]+"build_kernel")
1458 except CatalystError:
1460 raise CatalystError,\
1461 "build aborting due to kernel build error."
1463 def _build_kernel(self, kname):
1464 "Build a single configured kernel by name"
1465 if "AUTORESUME" in self.settings \
1466 and os.path.exists(self.settings["autoresume_path"]\
1467 +"build_kernel_"+kname):
1468 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1470 self._copy_kernel_config(kname=kname)
1473 If we need to pass special options to the bootloader
1474 for this kernel put them into the environment
1476 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1477 myopts=self.settings["boot/kernel/"+kname+\
1480 if type(myopts) != types.StringType:
1481 myopts = string.join(myopts)
1482 self.env[kname+"_kernelopts"]=myopts
1485 self.env[kname+"_kernelopts"]=""
1487 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1488 self.settings["boot/kernel/"+kname+\
1491 self.env["clst_kextraversion"]=\
1492 self.settings["boot/kernel/"+kname+\
1495 self._copy_initramfs_overlay(kname=kname)
1497 """ Execute the script that builds the kernel """
1498 cmd("/bin/bash "+self.settings["controller_file"]+\
1500 "Runscript kernel build failed",env=self.env)
1502 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1503 if os.path.exists(self.settings["chroot_path"]+\
1504 "/tmp/initramfs_overlay/"):
1505 print "Cleaning up temporary overlay dir"
1506 cmd("rm -R "+self.settings["chroot_path"]+\
1507 "/tmp/initramfs_overlay/",env=self.env)
1509 touch(self.settings["autoresume_path"]+\
1510 "build_kernel_"+kname)
1513 Execute the script that cleans up the kernel build
1516 cmd("/bin/bash "+self.settings["controller_file"]+\
1518 "Runscript post-kmerge failed",env=self.env)
1520 def _copy_kernel_config(self, kname):
1521 if "boot/kernel/"+kname+"/config" in self.settings:
1522 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1524 raise CatalystError,\
1525 "Can't find kernel config: "+\
1526 self.settings["boot/kernel/"+kname+\
1530 cmd("cp "+self.settings["boot/kernel/"+kname+\
1532 self.settings["chroot_path"]+"/var/tmp/"+\
1534 "Couldn't copy kernel config: "+\
1535 self.settings["boot/kernel/"+kname+\
1536 "/config"],env=self.env)
1538 except CatalystError:
1541 def _copy_initramfs_overlay(self, kname):
1542 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1543 if os.path.exists(self.settings["boot/kernel/"+\
1544 kname+"/initramfs_overlay"]):
1545 print "Copying initramfs_overlay dir "+\
1546 self.settings["boot/kernel/"+kname+\
1547 "/initramfs_overlay"]
1550 self.settings["chroot_path"]+\
1551 "/tmp/initramfs_overlay/"+\
1552 self.settings["boot/kernel/"+kname+\
1553 "/initramfs_overlay"],env=self.env)
1555 cmd("cp -R "+self.settings["boot/kernel/"+\
1556 kname+"/initramfs_overlay"]+"/* "+\
1557 self.settings["chroot_path"]+\
1558 "/tmp/initramfs_overlay/"+\
1559 self.settings["boot/kernel/"+kname+\
1560 "/initramfs_overlay"],env=self.env)
1562 def bootloader(self):
1563 if "AUTORESUME" in self.settings \
1564 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1565 print "Resume point detected, skipping bootloader operation..."
1568 cmd("/bin/bash "+self.settings["controller_file"]+\
1569 " bootloader " + self.settings["target_path"],\
1570 "Bootloader script failed.",env=self.env)
1571 touch(self.settings["autoresume_path"]+"bootloader")
1572 except CatalystError:
1574 raise CatalystError,"Script aborting due to error."
1576 def livecd_update(self):
1577 if "AUTORESUME" in self.settings \
1578 and os.path.exists(self.settings["autoresume_path"]+\
1580 print "Resume point detected, skipping build_packages operation..."
1583 cmd("/bin/bash "+self.settings["controller_file"]+\
1584 " livecd-update","livecd-update failed.",env=self.env)
1585 touch(self.settings["autoresume_path"]+"livecd_update")
1587 except CatalystError:
1589 raise CatalystError,"build aborting due to livecd_update error."
1591 def clear_chroot(self):
1592 myemp=self.settings["chroot_path"]
1593 if os.path.isdir(myemp):
1594 print "Emptying directory",myemp
1596 stat the dir, delete the dir, recreate the dir and set
1597 the proper perms and ownership
1599 mystat=os.stat(myemp)
1600 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1601 """ There's no easy way to change flags recursively in python """
1602 if os.uname()[0] == "FreeBSD":
1603 os.system("chflags -R noschg "+myemp)
1604 shutil.rmtree(myemp)
1605 os.makedirs(myemp,0755)
1606 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1607 os.chmod(myemp,mystat[ST_MODE])
1609 def clear_packages(self):
1610 if "PKGCACHE" in self.settings:
1611 print "purging the pkgcache ..."
1613 myemp=self.settings["pkgcache_path"]
1614 if os.path.isdir(myemp):
1615 print "Emptying directory",myemp
1617 stat the dir, delete the dir, recreate the dir and set
1618 the proper perms and ownership
1620 mystat=os.stat(myemp)
1621 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1622 shutil.rmtree(myemp)
1623 os.makedirs(myemp,0755)
1624 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1625 os.chmod(myemp,mystat[ST_MODE])
1627 def clear_kerncache(self):
1628 if "KERNCACHE" in self.settings:
1629 print "purging the kerncache ..."
1631 myemp=self.settings["kerncache_path"]
1632 if os.path.isdir(myemp):
1633 print "Emptying directory",myemp
1635 stat the dir, delete the dir, recreate the dir and set
1636 the proper perms and ownership
1638 mystat=os.stat(myemp)
1639 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1640 shutil.rmtree(myemp)
1641 os.makedirs(myemp,0755)
1642 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1643 os.chmod(myemp,mystat[ST_MODE])
1645 def clear_autoresume(self):
1646 """ Clean resume points since they are no longer needed """
1647 if "AUTORESUME" in self.settings:
1648 print "Removing AutoResume Points: ..."
1649 myemp=self.settings["autoresume_path"]
1650 if os.path.isdir(myemp):
1651 if "AUTORESUME" in self.settings:
1652 print "Emptying directory",myemp
1654 stat the dir, delete the dir, recreate the dir and set
1655 the proper perms and ownership
1657 mystat=os.stat(myemp)
1658 if os.uname()[0] == "FreeBSD":
1659 cmd("chflags -R noschg "+myemp,\
1660 "Could not remove immutable flag for file "\
1662 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1663 shutil.rmtree(myemp)
1664 os.makedirs(myemp,0755)
1665 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1666 os.chmod(myemp,mystat[ST_MODE])
1668 def gen_contents_file(self,file):
1669 if os.path.exists(file+".CONTENTS"):
1670 os.remove(file+".CONTENTS")
1671 if "contents" in self.settings:
1672 if os.path.exists(file):
1673 myf=open(file+".CONTENTS","w")
1675 for i in self.settings["contents"].split():
1680 contents=generate_contents(file,contents_function=j,\
1681 verbose="VERBOSE" in self.settings)
1686 def gen_digest_file(self,file):
1687 if os.path.exists(file+".DIGESTS"):
1688 os.remove(file+".DIGESTS")
1689 if "digests" in self.settings:
1690 if os.path.exists(file):
1691 myf=open(file+".DIGESTS","w")
1693 for i in self.settings["digests"].split():
1697 for f in [file, file+'.CONTENTS']:
1698 if os.path.exists(f):
1700 for k in hash_map.keys():
1701 hash=generate_hash(f,hash_function=k,verbose=\
1702 "VERBOSE" in self.settings)
1706 hash=generate_hash(f,hash_function=j,verbose=\
1707 "VERBOSE" in self.settings)
1712 countdown(10,"Purging Caches ...")
1713 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1714 print "clearing autoresume ..."
1715 self.clear_autoresume()
1717 print "clearing chroot ..."
1720 if "PURGETMPONLY" not in self.settings:
1721 print "clearing package cache ..."
1722 self.clear_packages()
1724 print "clearing kerncache ..."
1725 self.clear_kerncache()
1727 # vim: ts=4 sw=4 sta et sts=4 ai