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 SOURCE_MOUNTS_DEFAULTS = {
29 "distdir": "/usr/portage/distfiles",
30 "portdir": "/usr/portage",
31 "port_tmpdir": "tmpfs",
37 class generic_stage_target(generic_target):
39 This class does all of the chroot setup, copying of files, etc. It is
40 the driver class for pretty much everything that Catalyst does.
42 def __init__(self,myspec,addlargs):
43 self.required_values.extend(["version_stamp","target","subarch",\
44 "rel_type","profile","snapshot","source_subpath"])
46 self.valid_values.extend(["version_stamp","target","subarch",\
47 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
48 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
49 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
51 self.set_valid_build_kernel_vars(addlargs)
52 generic_target.__init__(self,myspec,addlargs)
55 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
56 work better with vapier's CBUILD stuff. I've removed the "monolithic"
57 machinemap from this file and split up its contents amongst the
58 various arch/foo.py files.
60 When register() is called on each module in the arch/ dir, it now
61 returns a tuple instead of acting on the subarchmap dict that is
62 passed to it. The tuple contains the values that were previously
63 added to subarchmap as well as a new list of CHOSTs that go along
64 with that arch. This allows us to build machinemap on the fly based
65 on the keys in subarchmap and the values of the 2nd list returned
68 Also, after talking with vapier. I have a slightly better idea of what
69 certain variables are used for and what they should be set to. Neither
70 'buildarch' or 'hostarch' are used directly, so their value doesn't
71 really matter. They are just compared to determine if we are
72 cross-compiling. Because of this, they are just set to the name of the
73 module in arch/ that the subarch is part of to make things simpler.
74 The entire build process is still based off of 'subarch' like it was
81 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
82 "/arch/") if x.endswith(".py")]:
84 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
86 This next line loads the plugin as a module and assigns it to
89 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
90 ".py",(".py","r",imp.PY_SOURCE))
92 This next line registers all the subarches supported in the
95 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
96 self.subarchmap.update(tmpsubarchmap)
97 for machine in tmpmachinemap:
98 machinemap[machine] = x
99 for subarch in tmpsubarchmap:
100 machinemap[subarch] = x
104 This message should probably change a bit, since everything in
105 the dir should load just fine. If it doesn't, it's probably a
106 syntax error in the module
108 msg("Can't find/load "+x+".py plugin in "+\
109 self.settings["sharedir"]+"/arch/")
111 if "chost" in self.settings:
112 hostmachine = self.settings["chost"].split("-")[0]
113 if hostmachine not in machinemap:
114 raise CatalystError, "Unknown host machine type "+hostmachine
115 self.settings["hostarch"]=machinemap[hostmachine]
117 hostmachine = self.settings["subarch"]
118 if hostmachine in machinemap:
119 hostmachine = machinemap[hostmachine]
120 self.settings["hostarch"]=hostmachine
121 if "cbuild" in self.settings:
122 buildmachine = self.settings["cbuild"].split("-")[0]
124 buildmachine = os.uname()[4]
125 if buildmachine not in machinemap:
126 raise CatalystError, "Unknown build machine type "+buildmachine
127 self.settings["buildarch"]=machinemap[buildmachine]
128 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
129 self.settings["buildarch"])
131 """ Call arch constructor, pass our settings """
133 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
135 print "Invalid subarch: "+self.settings["subarch"]
136 print "Choose one of the following:",
137 for x in self.subarchmap:
142 print "Using target:",self.settings["target"]
143 """ Print a nice informational message """
144 if self.settings["buildarch"]==self.settings["hostarch"]:
145 print "Building natively for",self.settings["hostarch"]
146 elif self.settings["crosscompile"]:
147 print "Cross-compiling on",self.settings["buildarch"],\
148 "for different machine type",self.settings["hostarch"]
150 print "Building on",self.settings["buildarch"],\
151 "for alternate personality type",self.settings["hostarch"]
153 """ This must be set first as other set_ options depend on this """
154 self.set_spec_prefix()
156 """ Define all of our core variables """
157 self.set_target_profile()
158 self.set_target_subpath()
159 self.set_source_subpath()
162 self.set_snapshot_path()
164 self.set_source_path()
165 self.set_snapcache_path()
166 self.set_chroot_path()
167 self.set_autoresume_path()
169 self.set_stage_path()
170 self.set_target_path()
172 self.set_controller_file()
173 self.set_action_sequence()
175 self.set_cleanables()
176 self.set_iso_volume_id()
177 self.set_build_kernel_vars()
179 self.set_install_mask()
189 self.set_busybox_config()
191 self.set_portage_overlay()
192 self.set_root_overlay()
195 This next line checks to make sure that the specified variables exist
199 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
201 """ If we are using portage_confdir, check that as well. """
202 if "portage_confdir" in self.settings:
203 file_locate(self.settings,["portage_confdir"],expand=0)
205 """ Setup our mount points """
206 # initialize our target mounts.
207 self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy()
209 self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
210 # initialize our source mounts
211 self.mountmap = SOURCE_MOUNTS_DEFAULTS.copy()
212 # update them from settings
213 self.mountmap["distdir"] = self.settings["distdir"]
214 self.mountmap["portdir"] = normpath("/".join([
215 self.settings["snapshot_cache_path"],
216 self.settings["repo_name"],
218 if "SNAPCACHE" not in self.settings:
219 self.mounts.remove("portdir")
220 #self.mountmap["portdir"] = None
221 if os.uname()[0] == "Linux":
222 self.mounts.append("devpts")
223 self.mounts.append("shm")
228 Configure any user specified options (either in catalyst.conf or on
231 if "PKGCACHE" in self.settings:
232 self.set_pkgcache_path()
233 print "Location of the package cache is "+\
234 self.settings["pkgcache_path"]
235 self.mounts.append("packagedir")
236 self.mountmap["packagedir"] = self.settings["pkgcache_path"]
238 if "KERNCACHE" in self.settings:
239 self.set_kerncache_path()
240 print "Location of the kerncache is "+\
241 self.settings["kerncache_path"]
242 self.mounts.append("kerncache")
243 self.mountmap["kerncache"] = self.settings["kerncache_path"]
245 if "CCACHE" in self.settings:
246 if "CCACHE_DIR" in os.environ:
247 ccdir=os.environ["CCACHE_DIR"]
248 del os.environ["CCACHE_DIR"]
250 ccdir="/root/.ccache"
251 if not os.path.isdir(ccdir):
252 raise CatalystError,\
253 "Compiler cache support can't be enabled (can't find "+\
255 self.mounts.append("ccache")
256 self.mountmap["ccache"] = ccdir
257 """ for the chroot: """
258 self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
260 if "ICECREAM" in self.settings:
261 self.mounts.append("icecream")
262 self.mountmap["icecream"] = self.settings["icecream"]
263 self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
266 if "port_logdir" in self.settings:
267 self.mounts.append("port_logdir")
268 self.mountmap["port_logdir"] = self.settings["port_logdir"]
269 self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
270 self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
272 def override_cbuild(self):
273 if "CBUILD" in self.makeconf:
274 self.settings["CBUILD"]=self.makeconf["CBUILD"]
276 def override_chost(self):
277 if "CHOST" in self.makeconf:
278 self.settings["CHOST"]=self.makeconf["CHOST"]
280 def override_cflags(self):
281 if "CFLAGS" in self.makeconf:
282 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
284 def override_cxxflags(self):
285 if "CXXFLAGS" in self.makeconf:
286 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
288 def override_ldflags(self):
289 if "LDFLAGS" in self.makeconf:
290 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
292 def set_install_mask(self):
293 if "install_mask" in self.settings:
294 if type(self.settings["install_mask"])!=types.StringType:
295 self.settings["install_mask"]=\
296 string.join(self.settings["install_mask"])
298 def set_spec_prefix(self):
299 self.settings["spec_prefix"]=self.settings["target"]
301 def set_target_profile(self):
302 self.settings["target_profile"]=self.settings["profile"]
304 def set_target_subpath(self):
305 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
306 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
307 self.settings["version_stamp"]
309 def set_source_subpath(self):
310 if type(self.settings["source_subpath"])!=types.StringType:
311 raise CatalystError,\
312 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
314 def set_pkgcache_path(self):
315 if "pkgcache_path" in self.settings:
316 if type(self.settings["pkgcache_path"])!=types.StringType:
317 self.settings["pkgcache_path"]=\
318 normpath(string.join(self.settings["pkgcache_path"]))
320 self.settings["pkgcache_path"]=\
321 normpath(self.settings["storedir"]+"/packages/"+\
322 self.settings["target_subpath"]+"/")
324 def set_kerncache_path(self):
325 if "kerncache_path" in self.settings:
326 if type(self.settings["kerncache_path"])!=types.StringType:
327 self.settings["kerncache_path"]=\
328 normpath(string.join(self.settings["kerncache_path"]))
330 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
331 "/kerncache/"+self.settings["target_subpath"]+"/")
333 def set_target_path(self):
334 self.settings["target_path"]=normpath(self.settings["storedir"]+\
335 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
336 if "AUTORESUME" in self.settings\
337 and os.path.exists(self.settings["autoresume_path"]+\
338 "setup_target_path"):
340 "Resume point detected, skipping target path setup operation..."
342 """ First clean up any existing target stuff """
343 # XXX WTF are we removing the old tarball before we start building the
344 # XXX new one? If the build fails, you don't want to be left with
346 # if os.path.isfile(self.settings["target_path"]):
347 # cmd("rm -f "+self.settings["target_path"],\
348 # "Could not remove existing file: "\
349 # +self.settings["target_path"],env=self.env)
350 touch(self.settings["autoresume_path"]+"setup_target_path")
352 if not os.path.exists(self.settings["storedir"]+"/builds/"):
353 os.makedirs(self.settings["storedir"]+"/builds/")
355 def set_fsscript(self):
356 if self.settings["spec_prefix"]+"/fsscript" in self.settings:
357 self.settings["fsscript"]=\
358 self.settings[self.settings["spec_prefix"]+"/fsscript"]
359 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
362 if self.settings["spec_prefix"]+"/rcadd" in self.settings:
363 self.settings["rcadd"]=\
364 self.settings[self.settings["spec_prefix"]+"/rcadd"]
365 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
368 if self.settings["spec_prefix"]+"/rcdel" in self.settings:
369 self.settings["rcdel"]=\
370 self.settings[self.settings["spec_prefix"]+"/rcdel"]
371 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
374 if self.settings["spec_prefix"]+"/cdtar" in self.settings:
375 self.settings["cdtar"]=\
376 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
377 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
380 if self.settings["spec_prefix"]+"/iso" in self.settings:
381 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
382 self.settings["iso"]=\
383 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
385 # This automatically prepends the build dir to the ISO output path
386 # if it doesn't start with a /
387 self.settings["iso"] = normpath(self.settings["storedir"] + \
388 "/builds/" + self.settings["rel_type"] + "/" + \
389 self.settings[self.settings["spec_prefix"]+"/iso"])
390 del self.settings[self.settings["spec_prefix"]+"/iso"]
392 def set_fstype(self):
393 if self.settings["spec_prefix"]+"/fstype" in self.settings:
394 self.settings["fstype"]=\
395 self.settings[self.settings["spec_prefix"]+"/fstype"]
396 del self.settings[self.settings["spec_prefix"]+"/fstype"]
398 if "fstype" not in self.settings:
399 self.settings["fstype"]="normal"
400 for x in self.valid_values:
401 if x == self.settings["spec_prefix"]+"/fstype":
402 print "\n"+self.settings["spec_prefix"]+\
403 "/fstype is being set to the default of \"normal\"\n"
406 if "fstype" in self.settings:
407 self.valid_values.append("fsops")
408 if self.settings["spec_prefix"]+"/fsops" in self.settings:
409 self.settings["fsops"]=\
410 self.settings[self.settings["spec_prefix"]+"/fsops"]
411 del self.settings[self.settings["spec_prefix"]+"/fsops"]
413 def set_source_path(self):
414 if "SEEDCACHE" in self.settings\
415 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
416 self.settings["source_subpath"]+"/")):
417 self.settings["source_path"]=normpath(self.settings["storedir"]+\
418 "/tmp/"+self.settings["source_subpath"]+"/")
420 self.settings["source_path"]=normpath(self.settings["storedir"]+\
421 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
422 if os.path.isfile(self.settings["source_path"]):
423 # XXX: Is this even necessary if the previous check passes?
424 if os.path.exists(self.settings["source_path"]):
425 self.settings["source_path_hash"]=\
426 generate_hash(self.settings["source_path"],\
427 hash_function=self.settings["hash_function"],\
429 print "Source path set to "+self.settings["source_path"]
430 if os.path.isdir(self.settings["source_path"]):
431 print "\tIf this is not desired, remove this directory or turn off"
432 print "\tseedcache in the options of catalyst.conf the source path"
433 print "\twill then be "+\
434 normpath(self.settings["storedir"]+"/builds/"+\
435 self.settings["source_subpath"]+".tar.bz2\n")
437 def set_dest_path(self):
438 if "root_path" in self.settings:
439 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
440 self.settings["root_path"])
442 self.settings["destpath"]=normpath(self.settings["chroot_path"])
444 def set_cleanables(self):
445 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
446 "/root/*", self.settings["portdir"]]
448 def set_snapshot_path(self):
449 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
450 "/snapshots/" + self.settings["snapshot_name"] +
451 self.settings["snapshot"] + ".tar.xz")
453 if os.path.exists(self.settings["snapshot_path"]):
454 self.settings["snapshot_path_hash"]=\
455 generate_hash(self.settings["snapshot_path"],\
456 hash_function=self.settings["hash_function"],verbose=False)
458 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
459 "/snapshots/" + self.settings["snapshot_name"] +
460 self.settings["snapshot"] + ".tar.bz2")
462 if os.path.exists(self.settings["snapshot_path"]):
463 self.settings["snapshot_path_hash"]=\
464 generate_hash(self.settings["snapshot_path"],\
465 hash_function=self.settings["hash_function"],verbose=False)
467 def set_snapcache_path(self):
468 if "SNAPCACHE" in self.settings:
469 self.settings["snapshot_cache_path"] = \
470 normpath(self.settings["snapshot_cache"] + "/" +
471 self.settings["snapshot"])
472 self.snapcache_lock=\
473 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
474 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
476 def set_chroot_path(self):
478 NOTE: the trailing slash has been removed
479 Things *could* break if you don't use a proper join()
481 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
482 "/tmp/"+self.settings["target_subpath"])
483 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
485 def set_autoresume_path(self):
486 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
487 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
488 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
489 self.settings["version_stamp"]+"/")
490 if "AUTORESUME" in self.settings:
491 print "The autoresume path is " + self.settings["autoresume_path"]
492 if not os.path.exists(self.settings["autoresume_path"]):
493 os.makedirs(self.settings["autoresume_path"],0755)
495 def set_controller_file(self):
496 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
497 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
500 def set_iso_volume_id(self):
501 if self.settings["spec_prefix"]+"/volid" in self.settings:
502 self.settings["iso_volume_id"]=\
503 self.settings[self.settings["spec_prefix"]+"/volid"]
504 if len(self.settings["iso_volume_id"])>32:
505 raise CatalystError,\
506 "ISO volume ID must not exceed 32 characters."
508 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
510 def set_action_sequence(self):
511 """ Default action sequence for run method """
512 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
513 "setup_confdir","portage_overlay",\
514 "base_dirs","bind","chroot_setup","setup_environment",\
515 "run_local","preclean","unbind","clean"]
516 # if "TARBALL" in self.settings or \
517 # "FETCH" not in self.settings:
518 if "FETCH" not in self.settings:
519 self.settings["action_sequence"].append("capture")
520 self.settings["action_sequence"].append("clear_autoresume")
523 if self.settings["spec_prefix"]+"/use" in self.settings:
524 self.settings["use"]=\
525 self.settings[self.settings["spec_prefix"]+"/use"]
526 del self.settings[self.settings["spec_prefix"]+"/use"]
527 if "use" not in self.settings:
528 self.settings["use"]=""
529 if type(self.settings["use"])==types.StringType:
530 self.settings["use"]=self.settings["use"].split()
532 # Force bindist when options ask for it
533 if "BINDIST" in self.settings:
534 self.settings["use"].append("bindist")
536 def set_stage_path(self):
537 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
539 def set_mounts(self):
542 def set_packages(self):
546 if self.settings["spec_prefix"]+"/rm" in self.settings:
547 if type(self.settings[self.settings["spec_prefix"]+\
548 "/rm"])==types.StringType:
549 self.settings[self.settings["spec_prefix"]+"/rm"]=\
550 self.settings[self.settings["spec_prefix"]+"/rm"].split()
552 def set_linuxrc(self):
553 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
554 if type(self.settings[self.settings["spec_prefix"]+\
555 "/linuxrc"])==types.StringType:
556 self.settings["linuxrc"]=\
557 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
558 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
560 def set_busybox_config(self):
561 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
562 if type(self.settings[self.settings["spec_prefix"]+\
563 "/busybox_config"])==types.StringType:
564 self.settings["busybox_config"]=\
565 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
566 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
568 def set_portage_overlay(self):
569 if "portage_overlay" in self.settings:
570 if type(self.settings["portage_overlay"])==types.StringType:
571 self.settings["portage_overlay"]=\
572 self.settings["portage_overlay"].split()
573 print "portage_overlay directories are set to: \""+\
574 string.join(self.settings["portage_overlay"])+"\""
576 def set_overlay(self):
577 if self.settings["spec_prefix"]+"/overlay" in self.settings:
578 if type(self.settings[self.settings["spec_prefix"]+\
579 "/overlay"])==types.StringType:
580 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
581 self.settings[self.settings["spec_prefix"]+\
584 def set_root_overlay(self):
585 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
586 if type(self.settings[self.settings["spec_prefix"]+\
587 "/root_overlay"])==types.StringType:
588 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
589 self.settings[self.settings["spec_prefix"]+\
590 "/root_overlay"].split()
592 def set_root_path(self):
593 """ ROOT= variable for emerges """
594 self.settings["root_path"]="/"
596 def set_valid_build_kernel_vars(self,addlargs):
597 if "boot/kernel" in addlargs:
598 if type(addlargs["boot/kernel"])==types.StringType:
599 loopy=[addlargs["boot/kernel"]]
601 loopy=addlargs["boot/kernel"]
604 self.valid_values.append("boot/kernel/"+x+"/aliases")
605 self.valid_values.append("boot/kernel/"+x+"/config")
606 self.valid_values.append("boot/kernel/"+x+"/console")
607 self.valid_values.append("boot/kernel/"+x+"/extraversion")
608 self.valid_values.append("boot/kernel/"+x+"/gk_action")
609 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
610 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
611 self.valid_values.append("boot/kernel/"+x+"/machine_type")
612 self.valid_values.append("boot/kernel/"+x+"/sources")
613 self.valid_values.append("boot/kernel/"+x+"/softlevel")
614 self.valid_values.append("boot/kernel/"+x+"/use")
615 self.valid_values.append("boot/kernel/"+x+"/packages")
616 if "boot/kernel/"+x+"/packages" in addlargs:
617 if type(addlargs["boot/kernel/"+x+\
618 "/packages"])==types.StringType:
619 addlargs["boot/kernel/"+x+"/packages"]=\
620 [addlargs["boot/kernel/"+x+"/packages"]]
622 def set_build_kernel_vars(self):
623 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
624 self.settings["gk_mainargs"]=\
625 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
626 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
628 def kill_chroot_pids(self):
629 print "Checking for processes running in chroot and killing them."
632 Force environment variables to be exported so script can see them
634 self.setup_environment()
636 if os.path.exists(self.settings["sharedir"]+\
637 "/targets/support/kill-chroot-pids.sh"):
638 cmd("/bin/bash "+self.settings["sharedir"]+\
639 "/targets/support/kill-chroot-pids.sh",\
640 "kill-chroot-pids script failed.",env=self.env)
642 def mount_safety_check(self):
644 Check and verify that none of our paths in mypath are mounted. We don't
645 want to clean up with things still mounted, and this allows us to check.
646 Returns 1 on ok, 0 on "something is still mounted" case.
649 if not os.path.exists(self.settings["chroot_path"]):
652 print "self.mounts =", self.mounts
653 for x in self.mounts:
654 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
655 print "mount_safety_check() x =", x, target
656 if not os.path.exists(target):
660 """ Something is still mounted "" """
662 print target + " is still mounted; performing auto-bind-umount...",
663 """ Try to umount stuff ourselves """
666 raise CatalystError, "Auto-unbind failed for " + target
668 print "Auto-unbind successful..."
669 except CatalystError:
670 raise CatalystError, "Unable to auto-unbind " + target
675 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
678 if "SEEDCACHE" in self.settings:
679 if os.path.isdir(self.settings["source_path"]):
680 """ SEEDCACHE Is a directory, use rsync """
681 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
682 " "+self.settings["chroot_path"]
683 display_msg="\nStarting rsync from "+\
684 self.settings["source_path"]+"\nto "+\
685 self.settings["chroot_path"]+\
686 " (This may take some time) ...\n"
687 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
688 self.settings["chroot_path"]+" failed."
690 """ SEEDCACHE is a not a directory, try untar'ing """
691 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
692 display_msg="\nStarting tar extract from "+\
693 self.settings["source_path"]+"\nto "+\
694 self.settings["chroot_path"]+\
695 " (This may take some time) ...\n"
696 if "bz2" == self.settings["chroot_path"][-3:]:
697 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
698 self.settings["chroot_path"]
700 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
701 self.settings["chroot_path"]
702 error_msg="Tarball extraction of "+\
703 self.settings["source_path"]+" to "+\
704 self.settings["chroot_path"]+" failed."
706 """ No SEEDCACHE, use tar """
707 display_msg="\nStarting tar extract from "+\
708 self.settings["source_path"]+"\nto "+\
709 self.settings["chroot_path"]+\
710 " (This may take some time) ...\n"
711 if "bz2" == self.settings["chroot_path"][-3:]:
712 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
713 self.settings["chroot_path"]
715 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
716 self.settings["chroot_path"]
717 error_msg="Tarball extraction of "+self.settings["source_path"]+\
718 " to "+self.settings["chroot_path"]+" failed."
720 if "AUTORESUME" in self.settings:
721 if os.path.isdir(self.settings["source_path"]) \
722 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
723 """ Autoresume is valid, SEEDCACHE is valid """
725 invalid_snapshot=False
727 elif os.path.isfile(self.settings["source_path"]) \
728 and self.settings["source_path_hash"]==clst_unpack_hash:
729 """ Autoresume is valid, tarball is valid """
731 invalid_snapshot=True
733 elif os.path.isdir(self.settings["source_path"]) \
734 and not os.path.exists(self.settings["autoresume_path"]+\
736 """ Autoresume is invalid, SEEDCACHE """
738 invalid_snapshot=False
740 elif os.path.isfile(self.settings["source_path"]) \
741 and self.settings["source_path_hash"]!=clst_unpack_hash:
742 """ Autoresume is invalid, tarball """
744 invalid_snapshot=True
746 """ No autoresume, SEEDCACHE """
747 if "SEEDCACHE" in self.settings:
748 """ SEEDCACHE so let's run rsync and let it clean up """
749 if os.path.isdir(self.settings["source_path"]):
751 invalid_snapshot=False
752 elif os.path.isfile(self.settings["source_path"]):
753 """ Tarball so unpack and remove anything already there """
755 invalid_snapshot=True
756 """ No autoresume, no SEEDCACHE """
758 """ Tarball so unpack and remove anything already there """
759 if os.path.isfile(self.settings["source_path"]):
761 invalid_snapshot=True
762 elif os.path.isdir(self.settings["source_path"]):
763 """ We should never reach this, so something is very wrong """
764 raise CatalystError,\
765 "source path is a dir but seedcache is not enabled"
768 self.mount_safety_check()
771 if "AUTORESUME" in self.settings:
772 print "No Valid Resume point detected, cleaning up..."
774 self.clear_autoresume()
777 if not os.path.exists(self.settings["chroot_path"]):
778 os.makedirs(self.settings["chroot_path"])
780 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
781 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
783 if "PKGCACHE" in self.settings:
784 if not os.path.exists(self.settings["pkgcache_path"]):
785 os.makedirs(self.settings["pkgcache_path"],0755)
787 if "KERNCACHE" in self.settings:
788 if not os.path.exists(self.settings["kerncache_path"]):
789 os.makedirs(self.settings["kerncache_path"],0755)
792 cmd(unpack_cmd,error_msg,env=self.env)
794 if "source_path_hash" in self.settings:
795 myf=open(self.settings["autoresume_path"]+"unpack","w")
796 myf.write(self.settings["source_path_hash"])
799 touch(self.settings["autoresume_path"]+"unpack")
801 print "Resume point detected, skipping unpack operation..."
803 def unpack_snapshot(self):
805 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
808 if "SNAPCACHE" in self.settings:
809 snapshot_cache_hash=\
810 read_from_clst(self.settings["snapshot_cache_path"] + "/" +
812 destdir=self.settings["snapshot_cache_path"]
813 if "bz2" == self.settings["chroot_path"][-3:]:
814 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
816 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
817 unpack_errmsg="Error unpacking snapshot"
818 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
819 self.settings["snapshot_cache_path"]+\
820 " (This can take a long time)..."
821 cleanup_errmsg="Error removing existing snapshot cache directory."
822 self.snapshot_lock_object=self.snapcache_lock
824 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
825 print "Valid snapshot cache, skipping unpack of portage tree..."
828 destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
829 cleanup_errmsg="Error removing existing snapshot directory."
831 "Cleaning up existing portage tree (This can take a long time)..."
832 if "bz2" == self.settings["chroot_path"][-3:]:
833 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
834 self.settings["chroot_path"]+"/usr"
836 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
837 self.settings["chroot_path"]+"/usr"
838 unpack_errmsg="Error unpacking snapshot"
840 if "AUTORESUME" in self.settings \
841 and os.path.exists(self.settings["chroot_path"]+\
842 self.settings["portdir"]) \
843 and os.path.exists(self.settings["autoresume_path"]\
845 and self.settings["snapshot_path_hash"] == snapshot_hash:
847 "Valid Resume point detected, skipping unpack of portage tree..."
851 if "SNAPCACHE" in self.settings:
852 self.snapshot_lock_object.write_lock()
853 if os.path.exists(destdir):
855 cleanup_cmd="rm -rf "+destdir
856 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
857 if not os.path.exists(destdir):
858 os.makedirs(destdir,0755)
860 print "Unpacking portage tree (This can take a long time) ..."
861 cmd(unpack_cmd,unpack_errmsg,env=self.env)
863 if "SNAPCACHE" in self.settings:
864 myf=open(self.settings["snapshot_cache_path"] +
865 "/" + "catalyst-hash","w")
866 myf.write(self.settings["snapshot_path_hash"])
869 print "Setting snapshot autoresume point"
870 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
871 myf.write(self.settings["snapshot_path_hash"])
874 if "SNAPCACHE" in self.settings:
875 self.snapshot_lock_object.unlock()
877 def config_profile_link(self):
878 if "AUTORESUME" in self.settings \
879 and os.path.exists(self.settings["autoresume_path"]+\
880 "config_profile_link"):
882 "Resume point detected, skipping config_profile_link operation..."
884 # TODO: zmedico and I discussed making this a directory and pushing
885 # in a parent file, as well as other user-specified configuration.
886 print "Configuring profile link..."
887 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
888 "Error zapping profile link",env=self.env)
889 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
890 cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
891 self.settings["target_profile"]+" "+\
892 self.settings["chroot_path"]+"/etc/portage/make.profile",\
893 "Error creating profile link",env=self.env)
894 touch(self.settings["autoresume_path"]+"config_profile_link")
896 def setup_confdir(self):
897 if "AUTORESUME" in self.settings \
898 and os.path.exists(self.settings["autoresume_path"]+\
900 print "Resume point detected, skipping setup_confdir operation..."
902 if "portage_confdir" in self.settings:
903 print "Configuring /etc/portage..."
904 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
905 self.settings["chroot_path"]+"/etc/portage/",\
906 "Error copying /etc/portage",env=self.env)
907 touch(self.settings["autoresume_path"]+"setup_confdir")
909 def portage_overlay(self):
910 """ We copy the contents of our overlays to /usr/local/portage """
911 if "portage_overlay" in self.settings:
912 for x in self.settings["portage_overlay"]:
913 if os.path.exists(x):
914 print "Copying overlay dir " +x
915 cmd("mkdir -p "+self.settings["chroot_path"]+\
916 self.settings["local_overlay"],\
917 "Could not make portage_overlay dir",env=self.env)
918 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
919 self.settings["local_overlay"],\
920 "Could not copy portage_overlay",env=self.env)
922 def root_overlay(self):
923 """ Copy over the root_overlay """
924 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
925 for x in self.settings[self.settings["spec_prefix"]+\
927 if os.path.exists(x):
928 print "Copying root_overlay: "+x
929 cmd("rsync -a "+x+"/ "+\
930 self.settings["chroot_path"],\
931 self.settings["spec_prefix"]+"/root_overlay: "+x+\
932 " copy failed.",env=self.env)
938 for x in self.mounts:
939 #print "bind(); x =", x
940 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
941 if not os.path.exists(target):
942 os.makedirs(target, 0755)
944 if not os.path.exists(self.mountmap[x]):
945 if self.mountmap[x] not in ["tmpfs", "shmfs"]:
946 os.makedirs(self.mountmap[x], 0755)
949 #print "bind(); src =", src
950 if "SNAPCACHE" in self.settings and x == "portdir":
951 self.snapshot_lock_object.read_lock()
952 if os.uname()[0] == "FreeBSD":
954 cmd = "mount -t devfs none " + target
955 retval=os.system(cmd)
957 cmd = "mount_nullfs " + src + " " + target
958 retval=os.system(cmd)
961 if "var_tmpfs_portage" in self.settings:
962 cmd = "mount -t tmpfs -o size=" + \
963 self.settings["var_tmpfs_portage"] + "G " + \
965 retval=os.system(cmd)
967 cmd = "mount -t tmpfs -o noexec,nosuid,nodev shm " + target
968 retval=os.system(cmd)
970 cmd = "mount --bind " + src + " " + target
971 #print "bind(); cmd =", cmd
972 retval=os.system(cmd)
975 raise CatalystError,"Couldn't bind mount " + src
979 mypath=self.settings["chroot_path"]
980 myrevmounts=self.mounts[:]
981 myrevmounts.reverse()
982 """ Unmount in reverse order for nested bind-mounts """
983 for x in myrevmounts:
984 target = normpath(mypath + self.target_mounts[x])
985 if not os.path.exists(target):
988 if not ismount(target):
991 retval=os.system("umount " + target)
994 warn("First attempt to unmount: " + target + " failed.")
995 warn("Killing any pids still running in the chroot")
997 self.kill_chroot_pids()
999 retval2 = os.system("umount " + target)
1002 warn("Couldn't umount bind mount: " + target)
1004 if "SNAPCACHE" in self.settings and x == "/usr/portage":
1007 It's possible the snapshot lock object isn't created yet.
1008 This is because mount safety check calls unbind before the
1009 target is fully initialized
1011 self.snapshot_lock_object.unlock()
1016 if any bind mounts really failed, then we need to raise
1017 this to potentially prevent an upcoming bash stage cleanup script
1018 from wiping our bind mounts.
1020 raise CatalystError,\
1021 "Couldn't umount one or more bind-mounts; aborting for safety."
1023 def chroot_setup(self):
1024 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
1025 "/etc/portage/make.conf")
1026 self.override_cbuild()
1027 self.override_chost()
1028 self.override_cflags()
1029 self.override_cxxflags()
1030 self.override_ldflags()
1031 if "AUTORESUME" in self.settings \
1032 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
1033 print "Resume point detected, skipping chroot_setup operation..."
1035 print "Setting up chroot..."
1037 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
1039 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1040 "Could not copy resolv.conf into place.",env=self.env)
1042 """ Copy over the envscript, if applicable """
1043 if "ENVSCRIPT" in self.settings:
1044 if not os.path.exists(self.settings["ENVSCRIPT"]):
1045 raise CatalystError,\
1046 "Can't find envscript "+self.settings["ENVSCRIPT"]
1048 print "\nWarning!!!!"
1049 print "\tOverriding certain env variables may cause catastrophic failure."
1050 print "\tIf your build fails look here first as the possible problem."
1051 print "\tCatalyst assumes you know what you are doing when setting"
1052 print "\t\tthese variables."
1053 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1054 print "\tYou have been warned\n"
1056 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1057 self.settings["chroot_path"]+"/tmp/envscript",\
1058 "Could not copy envscript into place.",env=self.env)
1061 Copy over /etc/hosts from the host in case there are any
1062 specialties in there
1064 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1065 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1066 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1067 "Could not backup /etc/hosts",env=self.env)
1068 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1069 "Could not copy /etc/hosts",env=self.env)
1071 """ Modify and write out make.conf (for the chroot) """
1072 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1073 "Could not remove "+self.settings["chroot_path"]+\
1074 "/etc/portage/make.conf",env=self.env)
1075 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1076 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1077 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1078 if "CFLAGS" in self.settings:
1079 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1080 if "CXXFLAGS" in self.settings:
1081 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1082 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1084 myf.write('CXXFLAGS="${CFLAGS}"\n')
1086 myf.write('CXXFLAGS="${CFLAGS}"\n')
1088 if "LDFLAGS" in self.settings:
1089 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1090 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1091 if "CBUILD" in self.settings:
1092 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")
1093 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1095 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")
1096 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1098 """ Figure out what our USE vars are for building """
1100 if "HOSTUSE" in self.settings:
1101 myusevars.extend(self.settings["HOSTUSE"])
1103 if "use" in self.settings:
1104 myusevars.extend(self.settings["use"])
1107 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1108 myusevars = sorted(set(myusevars))
1109 myf.write('USE="'+string.join(myusevars)+'"\n')
1110 if '-*' in myusevars:
1111 print "\nWarning!!! "
1112 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1113 "/use will cause portage to ignore"
1114 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1116 myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
1117 myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
1118 myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
1120 """ Setup the portage overlay """
1121 if "portage_overlay" in self.settings:
1122 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1125 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1126 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1127 "Could not backup /etc/portage/make.conf",env=self.env)
1128 touch(self.settings["autoresume_path"]+"chroot_setup")
1131 if "AUTORESUME" in self.settings \
1132 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1133 print "Resume point detected, skipping fsscript operation..."
1135 if "fsscript" in self.settings:
1136 if os.path.exists(self.settings["controller_file"]):
1137 cmd("/bin/bash "+self.settings["controller_file"]+\
1138 " fsscript","fsscript script failed.",env=self.env)
1139 touch(self.settings["autoresume_path"]+"fsscript")
1142 if "AUTORESUME" in self.settings \
1143 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1144 print "Resume point detected, skipping rcupdate operation..."
1146 if os.path.exists(self.settings["controller_file"]):
1147 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1148 "rc-update script failed.",env=self.env)
1149 touch(self.settings["autoresume_path"]+"rcupdate")
1152 if "AUTORESUME" in self.settings \
1153 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1154 print "Resume point detected, skipping clean operation..."
1156 for x in self.settings["cleanables"]:
1157 print "Cleaning chroot: "+x+"... "
1158 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1161 """ Put /etc/hosts back into place """
1162 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1163 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1164 self.settings["chroot_path"]+"/etc/hosts",\
1165 "Could not replace /etc/hosts",env=self.env)
1167 """ Remove our overlay """
1168 if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
1169 cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
1170 "Could not remove " + self.settings["local_overlay"], env=self.env)
1171 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1172 "/etc/portage/make.conf",\
1173 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1175 """ Clean up old and obsoleted files in /etc """
1176 if os.path.exists(self.settings["stage_path"]+"/etc"):
1177 cmd("find "+self.settings["stage_path"]+\
1178 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1179 "Could not remove stray files in /etc",env=self.env)
1181 if os.path.exists(self.settings["controller_file"]):
1182 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1183 "clean script failed.",env=self.env)
1184 touch(self.settings["autoresume_path"]+"clean")
1187 if "AUTORESUME" in self.settings \
1188 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1189 print "Resume point detected, skipping empty operation..."
1191 if self.settings["spec_prefix"]+"/empty" in self.settings:
1192 if type(self.settings[self.settings["spec_prefix"]+\
1193 "/empty"])==types.StringType:
1194 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1195 self.settings[self.settings["spec_prefix"]+\
1197 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1198 myemp=self.settings["destpath"]+x
1199 if not os.path.isdir(myemp) or os.path.islink(myemp):
1200 print x,"not a directory or does not exist, skipping 'empty' operation."
1202 print "Emptying directory",x
1204 stat the dir, delete the dir, recreate the dir and set
1205 the proper perms and ownership
1207 mystat=os.stat(myemp)
1208 shutil.rmtree(myemp)
1209 os.makedirs(myemp,0755)
1210 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1211 os.chmod(myemp,mystat[ST_MODE])
1212 touch(self.settings["autoresume_path"]+"empty")
1215 if "AUTORESUME" in self.settings \
1216 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1217 print "Resume point detected, skipping remove operation..."
1219 if self.settings["spec_prefix"]+"/rm" in self.settings:
1220 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1222 We're going to shell out for all these cleaning
1223 operations, so we get easy glob handling.
1225 print "livecd: removing "+x
1226 os.system("rm -rf "+self.settings["chroot_path"]+x)
1228 if os.path.exists(self.settings["controller_file"]):
1229 cmd("/bin/bash "+self.settings["controller_file"]+\
1230 " clean","Clean failed.",env=self.env)
1231 touch(self.settings["autoresume_path"]+"remove")
1237 if "AUTORESUME" in self.settings \
1238 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1239 print "Resume point detected, skipping preclean operation..."
1242 if os.path.exists(self.settings["controller_file"]):
1243 cmd("/bin/bash "+self.settings["controller_file"]+\
1244 " preclean","preclean script failed.",env=self.env)
1245 touch(self.settings["autoresume_path"]+"preclean")
1249 raise CatalystError, "Build failed, could not execute preclean"
1252 if "AUTORESUME" in self.settings \
1253 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1254 print "Resume point detected, skipping capture operation..."
1256 """ Capture target in a tarball """
1257 mypath=self.settings["target_path"].split("/")
1258 """ Remove filename from path """
1259 mypath=string.join(mypath[:-1],"/")
1261 """ Now make sure path exists """
1262 if not os.path.exists(mypath):
1265 print "Creating stage tarball..."
1267 cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1268 self.settings["stage_path"]+" .",\
1269 "Couldn't create stage tarball",env=self.env)
1271 self.gen_contents_file(self.settings["target_path"])
1272 self.gen_digest_file(self.settings["target_path"])
1274 touch(self.settings["autoresume_path"]+"capture")
1276 def run_local(self):
1277 if "AUTORESUME" in self.settings \
1278 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1279 print "Resume point detected, skipping run_local operation..."
1282 if os.path.exists(self.settings["controller_file"]):
1283 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1284 "run script failed.",env=self.env)
1285 touch(self.settings["autoresume_path"]+"run_local")
1287 except CatalystError:
1289 raise CatalystError,"Stage build aborting due to error."
1291 def setup_environment(self):
1293 Modify the current environment. This is an ugly hack that should be
1294 fixed. We need this to use the os.system() call since we can't
1295 specify our own environ
1297 for x in self.settings.keys():
1298 """ Sanitize var names by doing "s|/-.|_|g" """
1299 varname="clst_"+string.replace(x,"/","_")
1300 varname=string.replace(varname,"-","_")
1301 varname=string.replace(varname,".","_")
1302 if type(self.settings[x])==types.StringType:
1303 """ Prefix to prevent namespace clashes """
1304 #os.environ[varname]=self.settings[x]
1305 self.env[varname]=self.settings[x]
1306 elif type(self.settings[x])==types.ListType:
1307 #os.environ[varname]=string.join(self.settings[x])
1308 self.env[varname]=string.join(self.settings[x])
1309 elif type(self.settings[x])==types.BooleanType:
1310 if self.settings[x]:
1311 self.env[varname]="true"
1313 self.env[varname]="false"
1314 if "makeopts" in self.settings:
1315 self.env["MAKEOPTS"]=self.settings["makeopts"]
1318 self.chroot_lock.write_lock()
1320 """ Kill any pids in the chroot "" """
1321 self.kill_chroot_pids()
1323 """ Check for mounts right away and abort if we cannot unmount them """
1324 self.mount_safety_check()
1326 if "CLEAR_AUTORESUME" in self.settings:
1327 self.clear_autoresume()
1329 if "PURGETMPONLY" in self.settings:
1333 if "PURGEONLY" in self.settings:
1337 if "PURGE" in self.settings:
1340 for x in self.settings["action_sequence"]:
1341 print "--- Running action sequence: "+x
1344 apply(getattr(self,x))
1346 self.mount_safety_check()
1349 self.chroot_lock.unlock()
1352 if "AUTORESUME" in self.settings \
1353 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1354 print "Resume point detected, skipping unmerge operation..."
1356 if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1357 if type(self.settings[self.settings["spec_prefix"]+\
1358 "/unmerge"])==types.StringType:
1359 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1360 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1362 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1364 for x in range(0,len(myunmerge)):
1366 Surround args with quotes for passing to bash, allows
1367 things like "<" to remain intact
1369 myunmerge[x]="'"+myunmerge[x]+"'"
1370 myunmerge=string.join(myunmerge)
1372 """ Before cleaning, unmerge stuff """
1374 cmd("/bin/bash "+self.settings["controller_file"]+\
1375 " unmerge "+ myunmerge,"Unmerge script failed.",\
1377 print "unmerge shell script"
1378 except CatalystError:
1381 touch(self.settings["autoresume_path"]+"unmerge")
1383 def target_setup(self):
1384 if "AUTORESUME" in self.settings \
1385 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1386 print "Resume point detected, skipping target_setup operation..."
1388 print "Setting up filesystems per filesystem type"
1389 cmd("/bin/bash "+self.settings["controller_file"]+\
1390 " target_image_setup "+ self.settings["target_path"],\
1391 "target_image_setup script failed.",env=self.env)
1392 touch(self.settings["autoresume_path"]+"target_setup")
1394 def setup_overlay(self):
1395 if "AUTORESUME" in self.settings \
1396 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1397 print "Resume point detected, skipping setup_overlay operation..."
1399 if self.settings["spec_prefix"]+"/overlay" in self.settings:
1400 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1401 if os.path.exists(x):
1402 cmd("rsync -a "+x+"/ "+\
1403 self.settings["target_path"],\
1404 self.settings["spec_prefix"]+"overlay: "+x+\
1405 " copy failed.",env=self.env)
1406 touch(self.settings["autoresume_path"]+"setup_overlay")
1408 def create_iso(self):
1409 if "AUTORESUME" in self.settings \
1410 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1411 print "Resume point detected, skipping create_iso operation..."
1413 """ Create the ISO """
1414 if "iso" in self.settings:
1415 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1416 self.settings["iso"],"ISO creation script failed.",\
1418 self.gen_contents_file(self.settings["iso"])
1419 self.gen_digest_file(self.settings["iso"])
1420 touch(self.settings["autoresume_path"]+"create_iso")
1422 print "WARNING: livecd/iso was not defined."
1423 print "An ISO Image will not be created."
1425 def build_packages(self):
1426 if "AUTORESUME" in self.settings \
1427 and os.path.exists(self.settings["autoresume_path"]+\
1429 print "Resume point detected, skipping build_packages operation..."
1431 if self.settings["spec_prefix"]+"/packages" in self.settings:
1432 if "AUTORESUME" in self.settings \
1433 and os.path.exists(self.settings["autoresume_path"]+\
1435 print "Resume point detected, skipping build_packages operation..."
1438 list_bashify(self.settings[self.settings["spec_prefix"]\
1441 cmd("/bin/bash "+self.settings["controller_file"]+\
1442 " build_packages "+mypack,\
1443 "Error in attempt to build packages",env=self.env)
1444 touch(self.settings["autoresume_path"]+"build_packages")
1445 except CatalystError:
1447 raise CatalystError,self.settings["spec_prefix"]+\
1448 "build aborting due to error."
1450 def build_kernel(self):
1451 "Build all configured kernels"
1452 if "AUTORESUME" in self.settings \
1453 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1454 print "Resume point detected, skipping build_kernel operation..."
1456 if "boot/kernel" in self.settings:
1458 mynames=self.settings["boot/kernel"]
1459 if type(mynames)==types.StringType:
1462 Execute the script that sets up the kernel build environment
1464 cmd("/bin/bash "+self.settings["controller_file"]+\
1465 " pre-kmerge ","Runscript pre-kmerge failed",\
1467 for kname in mynames:
1468 self._build_kernel(kname=kname)
1469 touch(self.settings["autoresume_path"]+"build_kernel")
1470 except CatalystError:
1472 raise CatalystError,\
1473 "build aborting due to kernel build error."
1475 def _build_kernel(self, kname):
1476 "Build a single configured kernel by name"
1477 if "AUTORESUME" in self.settings \
1478 and os.path.exists(self.settings["autoresume_path"]\
1479 +"build_kernel_"+kname):
1480 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1482 self._copy_kernel_config(kname=kname)
1485 If we need to pass special options to the bootloader
1486 for this kernel put them into the environment
1488 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1489 myopts=self.settings["boot/kernel/"+kname+\
1492 if type(myopts) != types.StringType:
1493 myopts = string.join(myopts)
1494 self.env[kname+"_kernelopts"]=myopts
1497 self.env[kname+"_kernelopts"]=""
1499 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1500 self.settings["boot/kernel/"+kname+\
1503 self.env["clst_kextraversion"]=\
1504 self.settings["boot/kernel/"+kname+\
1507 self._copy_initramfs_overlay(kname=kname)
1509 """ Execute the script that builds the kernel """
1510 cmd("/bin/bash "+self.settings["controller_file"]+\
1512 "Runscript kernel build failed",env=self.env)
1514 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1515 if os.path.exists(self.settings["chroot_path"]+\
1516 "/tmp/initramfs_overlay/"):
1517 print "Cleaning up temporary overlay dir"
1518 cmd("rm -R "+self.settings["chroot_path"]+\
1519 "/tmp/initramfs_overlay/",env=self.env)
1521 touch(self.settings["autoresume_path"]+\
1522 "build_kernel_"+kname)
1525 Execute the script that cleans up the kernel build
1528 cmd("/bin/bash "+self.settings["controller_file"]+\
1530 "Runscript post-kmerge failed",env=self.env)
1532 def _copy_kernel_config(self, kname):
1533 if "boot/kernel/"+kname+"/config" in self.settings:
1534 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1536 raise CatalystError,\
1537 "Can't find kernel config: "+\
1538 self.settings["boot/kernel/"+kname+\
1542 cmd("cp "+self.settings["boot/kernel/"+kname+\
1544 self.settings["chroot_path"]+"/var/tmp/"+\
1546 "Couldn't copy kernel config: "+\
1547 self.settings["boot/kernel/"+kname+\
1548 "/config"],env=self.env)
1550 except CatalystError:
1553 def _copy_initramfs_overlay(self, kname):
1554 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1555 if os.path.exists(self.settings["boot/kernel/"+\
1556 kname+"/initramfs_overlay"]):
1557 print "Copying initramfs_overlay dir "+\
1558 self.settings["boot/kernel/"+kname+\
1559 "/initramfs_overlay"]
1562 self.settings["chroot_path"]+\
1563 "/tmp/initramfs_overlay/"+\
1564 self.settings["boot/kernel/"+kname+\
1565 "/initramfs_overlay"],env=self.env)
1567 cmd("cp -R "+self.settings["boot/kernel/"+\
1568 kname+"/initramfs_overlay"]+"/* "+\
1569 self.settings["chroot_path"]+\
1570 "/tmp/initramfs_overlay/"+\
1571 self.settings["boot/kernel/"+kname+\
1572 "/initramfs_overlay"],env=self.env)
1574 def bootloader(self):
1575 if "AUTORESUME" in self.settings \
1576 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1577 print "Resume point detected, skipping bootloader operation..."
1580 cmd("/bin/bash "+self.settings["controller_file"]+\
1581 " bootloader " + self.settings["target_path"],\
1582 "Bootloader script failed.",env=self.env)
1583 touch(self.settings["autoresume_path"]+"bootloader")
1584 except CatalystError:
1586 raise CatalystError,"Script aborting due to error."
1588 def livecd_update(self):
1589 if "AUTORESUME" in self.settings \
1590 and os.path.exists(self.settings["autoresume_path"]+\
1592 print "Resume point detected, skipping build_packages operation..."
1595 cmd("/bin/bash "+self.settings["controller_file"]+\
1596 " livecd-update","livecd-update failed.",env=self.env)
1597 touch(self.settings["autoresume_path"]+"livecd_update")
1599 except CatalystError:
1601 raise CatalystError,"build aborting due to livecd_update error."
1603 def clear_chroot(self):
1604 myemp=self.settings["chroot_path"]
1605 if os.path.isdir(myemp):
1606 print "Emptying directory",myemp
1608 stat the dir, delete the dir, recreate the dir and set
1609 the proper perms and ownership
1611 mystat=os.stat(myemp)
1612 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1613 """ There's no easy way to change flags recursively in python """
1614 if os.uname()[0] == "FreeBSD":
1615 os.system("chflags -R noschg "+myemp)
1616 shutil.rmtree(myemp)
1617 os.makedirs(myemp,0755)
1618 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1619 os.chmod(myemp,mystat[ST_MODE])
1621 def clear_packages(self):
1622 if "PKGCACHE" in self.settings:
1623 print "purging the pkgcache ..."
1625 myemp=self.settings["pkgcache_path"]
1626 if os.path.isdir(myemp):
1627 print "Emptying directory",myemp
1629 stat the dir, delete the dir, recreate the dir and set
1630 the proper perms and ownership
1632 mystat=os.stat(myemp)
1633 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1634 shutil.rmtree(myemp)
1635 os.makedirs(myemp,0755)
1636 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1637 os.chmod(myemp,mystat[ST_MODE])
1639 def clear_kerncache(self):
1640 if "KERNCACHE" in self.settings:
1641 print "purging the kerncache ..."
1643 myemp=self.settings["kerncache_path"]
1644 if os.path.isdir(myemp):
1645 print "Emptying directory",myemp
1647 stat the dir, delete the dir, recreate the dir and set
1648 the proper perms and ownership
1650 mystat=os.stat(myemp)
1651 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1652 shutil.rmtree(myemp)
1653 os.makedirs(myemp,0755)
1654 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1655 os.chmod(myemp,mystat[ST_MODE])
1657 def clear_autoresume(self):
1658 """ Clean resume points since they are no longer needed """
1659 if "AUTORESUME" in self.settings:
1660 print "Removing AutoResume Points: ..."
1661 myemp=self.settings["autoresume_path"]
1662 if os.path.isdir(myemp):
1663 if "AUTORESUME" in self.settings:
1664 print "Emptying directory",myemp
1666 stat the dir, delete the dir, recreate the dir and set
1667 the proper perms and ownership
1669 mystat=os.stat(myemp)
1670 if os.uname()[0] == "FreeBSD":
1671 cmd("chflags -R noschg "+myemp,\
1672 "Could not remove immutable flag for file "\
1674 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1675 shutil.rmtree(myemp)
1676 os.makedirs(myemp,0755)
1677 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1678 os.chmod(myemp,mystat[ST_MODE])
1680 def gen_contents_file(self,file):
1681 if os.path.exists(file+".CONTENTS"):
1682 os.remove(file+".CONTENTS")
1683 if "contents" in self.settings:
1684 if os.path.exists(file):
1685 myf=open(file+".CONTENTS","w")
1687 for i in self.settings["contents"].split():
1692 contents=generate_contents(file,contents_function=j,\
1693 verbose="VERBOSE" in self.settings)
1698 def gen_digest_file(self,file):
1699 if os.path.exists(file+".DIGESTS"):
1700 os.remove(file+".DIGESTS")
1701 if "digests" in self.settings:
1702 if os.path.exists(file):
1703 myf=open(file+".DIGESTS","w")
1705 for i in self.settings["digests"].split():
1709 for f in [file, file+'.CONTENTS']:
1710 if os.path.exists(f):
1712 for k in hash_map.keys():
1713 hash=generate_hash(f,hash_function=k,verbose=\
1714 "VERBOSE" in self.settings)
1718 hash=generate_hash(f,hash_function=j,verbose=\
1719 "VERBOSE" in self.settings)
1724 countdown(10,"Purging Caches ...")
1725 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1726 print "clearing autoresume ..."
1727 self.clear_autoresume()
1729 print "clearing chroot ..."
1732 if "PURGETMPONLY" not in self.settings:
1733 print "clearing package cache ..."
1734 self.clear_packages()
1736 print "clearing kerncache ..."
1737 self.clear_kerncache()
1739 # vim: ts=4 sw=4 sta et sts=4 ai