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",
25 SOURCE_MOUNTS_DEFAULTS = {
28 "distdir": "/usr/portage/distfiles",
29 "portdir": "/usr/portage",
30 "port_tmpdir": "tmpfs",
35 class generic_stage_target(generic_target):
37 This class does all of the chroot setup, copying of files, etc. It is
38 the driver class for pretty much everything that Catalyst does.
40 def __init__(self,myspec,addlargs):
41 self.required_values.extend(["version_stamp","target","subarch",\
42 "rel_type","profile","snapshot","source_subpath"])
44 self.valid_values.extend(["version_stamp","target","subarch",\
45 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
46 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
47 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
49 self.set_valid_build_kernel_vars(addlargs)
50 generic_target.__init__(self,myspec,addlargs)
53 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
54 work better with vapier's CBUILD stuff. I've removed the "monolithic"
55 machinemap from this file and split up its contents amongst the
56 various arch/foo.py files.
58 When register() is called on each module in the arch/ dir, it now
59 returns a tuple instead of acting on the subarchmap dict that is
60 passed to it. The tuple contains the values that were previously
61 added to subarchmap as well as a new list of CHOSTs that go along
62 with that arch. This allows us to build machinemap on the fly based
63 on the keys in subarchmap and the values of the 2nd list returned
66 Also, after talking with vapier. I have a slightly better idea of what
67 certain variables are used for and what they should be set to. Neither
68 'buildarch' or 'hostarch' are used directly, so their value doesn't
69 really matter. They are just compared to determine if we are
70 cross-compiling. Because of this, they are just set to the name of the
71 module in arch/ that the subarch is part of to make things simpler.
72 The entire build process is still based off of 'subarch' like it was
79 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
80 "/arch/") if x.endswith(".py")]:
82 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
84 This next line loads the plugin as a module and assigns it to
87 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
88 ".py",(".py","r",imp.PY_SOURCE))
90 This next line registers all the subarches supported in the
93 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
94 self.subarchmap.update(tmpsubarchmap)
95 for machine in tmpmachinemap:
96 machinemap[machine] = x
97 for subarch in tmpsubarchmap:
98 machinemap[subarch] = x
102 This message should probably change a bit, since everything in
103 the dir should load just fine. If it doesn't, it's probably a
104 syntax error in the module
106 msg("Can't find/load "+x+".py plugin in "+\
107 self.settings["sharedir"]+"/arch/")
109 if "chost" in self.settings:
110 hostmachine = self.settings["chost"].split("-")[0]
111 if hostmachine not in machinemap:
112 raise CatalystError, "Unknown host machine type "+hostmachine
113 self.settings["hostarch"]=machinemap[hostmachine]
115 hostmachine = self.settings["subarch"]
116 if hostmachine in machinemap:
117 hostmachine = machinemap[hostmachine]
118 self.settings["hostarch"]=hostmachine
119 if "cbuild" in self.settings:
120 buildmachine = self.settings["cbuild"].split("-")[0]
122 buildmachine = os.uname()[4]
123 if buildmachine not in machinemap:
124 raise CatalystError, "Unknown build machine type "+buildmachine
125 self.settings["buildarch"]=machinemap[buildmachine]
126 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
127 self.settings["buildarch"])
129 """ Call arch constructor, pass our settings """
131 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
133 print "Invalid subarch: "+self.settings["subarch"]
134 print "Choose one of the following:",
135 for x in self.subarchmap:
140 print "Using target:",self.settings["target"]
141 """ Print a nice informational message """
142 if self.settings["buildarch"]==self.settings["hostarch"]:
143 print "Building natively for",self.settings["hostarch"]
144 elif self.settings["crosscompile"]:
145 print "Cross-compiling on",self.settings["buildarch"],\
146 "for different machine type",self.settings["hostarch"]
148 print "Building on",self.settings["buildarch"],\
149 "for alternate personality type",self.settings["hostarch"]
151 """ This must be set first as other set_ options depend on this """
152 self.set_spec_prefix()
154 """ Define all of our core variables """
155 self.set_target_profile()
156 self.set_target_subpath()
157 self.set_source_subpath()
160 self.set_snapshot_path()
162 self.set_source_path()
163 self.set_snapcache_path()
164 self.set_chroot_path()
165 self.set_autoresume_path()
167 self.set_stage_path()
168 self.set_target_path()
170 self.set_controller_file()
171 self.set_action_sequence()
173 self.set_cleanables()
174 self.set_iso_volume_id()
175 self.set_build_kernel_vars()
177 self.set_install_mask()
187 self.set_busybox_config()
189 self.set_portage_overlay()
190 self.set_root_overlay()
193 This next line checks to make sure that the specified variables exist
197 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
199 """ If we are using portage_confdir, check that as well. """
200 if "portage_confdir" in self.settings:
201 file_locate(self.settings,["portage_confdir"],expand=0)
203 """ Setup our mount points """
204 # initialize our target mounts.
205 self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy()
207 self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
208 # initialize our source mounts
209 self.mountmap = SOURCE_MOUNTS_DEFAULTS.copy()
210 # update them from settings
211 self.mountmap["distdir"] = self.settings["distdir"]
212 self.mountmap["portdir"] = normpath("/".join([
213 self.settings["snapshot_cache_path"],
214 self.settings["repo_name"],
216 if "SNAPCACHE" not in self.settings:
217 self.mounts.remove("portdir")
218 #self.mountmap["portdir"] = None
219 if os.uname()[0] == "Linux":
220 self.mounts.append("devpts")
225 Configure any user specified options (either in catalyst.conf or on
228 if "PKGCACHE" in self.settings:
229 self.set_pkgcache_path()
230 print "Location of the package cache is "+\
231 self.settings["pkgcache_path"]
232 self.mounts.append("packagedir")
233 self.mountmap["packagedir"] = self.settings["pkgcache_path"]
235 if "KERNCACHE" in self.settings:
236 self.set_kerncache_path()
237 print "Location of the kerncache is "+\
238 self.settings["kerncache_path"]
239 self.mounts.append("kerncache")
240 self.mountmap["kerncache"] = self.settings["kerncache_path"]
242 if "CCACHE" in self.settings:
243 if "CCACHE_DIR" in os.environ:
244 ccdir=os.environ["CCACHE_DIR"]
245 del os.environ["CCACHE_DIR"]
247 ccdir="/root/.ccache"
248 if not os.path.isdir(ccdir):
249 raise CatalystError,\
250 "Compiler cache support can't be enabled (can't find "+\
252 self.mounts.append("ccache")
253 self.mountmap["ccache"] = ccdir
254 """ for the chroot: """
255 self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
257 if "ICECREAM" in self.settings:
258 self.mounts.append("icecream")
259 self.mountmap["icecream"] = self.settings["icecream"]
260 self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
263 if "port_logdir" in self.settings:
264 self.mounts.append("port_logdir")
265 self.mountmap["port_logdir"] = self.settings["port_logdir"]
266 self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
267 self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
269 def override_cbuild(self):
270 if "CBUILD" in self.makeconf:
271 self.settings["CBUILD"]=self.makeconf["CBUILD"]
273 def override_chost(self):
274 if "CHOST" in self.makeconf:
275 self.settings["CHOST"]=self.makeconf["CHOST"]
277 def override_cflags(self):
278 if "CFLAGS" in self.makeconf:
279 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
281 def override_cxxflags(self):
282 if "CXXFLAGS" in self.makeconf:
283 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
285 def override_ldflags(self):
286 if "LDFLAGS" in self.makeconf:
287 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
289 def set_install_mask(self):
290 if "install_mask" in self.settings:
291 if type(self.settings["install_mask"])!=types.StringType:
292 self.settings["install_mask"]=\
293 string.join(self.settings["install_mask"])
295 def set_spec_prefix(self):
296 self.settings["spec_prefix"]=self.settings["target"]
298 def set_target_profile(self):
299 self.settings["target_profile"]=self.settings["profile"]
301 def set_target_subpath(self):
302 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
303 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
304 self.settings["version_stamp"]
306 def set_source_subpath(self):
307 if type(self.settings["source_subpath"])!=types.StringType:
308 raise CatalystError,\
309 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
311 def set_pkgcache_path(self):
312 if "pkgcache_path" in self.settings:
313 if type(self.settings["pkgcache_path"])!=types.StringType:
314 self.settings["pkgcache_path"]=\
315 normpath(string.join(self.settings["pkgcache_path"]))
317 self.settings["pkgcache_path"]=\
318 normpath(self.settings["storedir"]+"/packages/"+\
319 self.settings["target_subpath"]+"/")
321 def set_kerncache_path(self):
322 if "kerncache_path" in self.settings:
323 if type(self.settings["kerncache_path"])!=types.StringType:
324 self.settings["kerncache_path"]=\
325 normpath(string.join(self.settings["kerncache_path"]))
327 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
328 "/kerncache/"+self.settings["target_subpath"]+"/")
330 def set_target_path(self):
331 self.settings["target_path"]=normpath(self.settings["storedir"]+\
332 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
333 if "AUTORESUME" in self.settings\
334 and os.path.exists(self.settings["autoresume_path"]+\
335 "setup_target_path"):
337 "Resume point detected, skipping target path setup operation..."
339 """ First clean up any existing target stuff """
340 # XXX WTF are we removing the old tarball before we start building the
341 # XXX new one? If the build fails, you don't want to be left with
343 # if os.path.isfile(self.settings["target_path"]):
344 # cmd("rm -f "+self.settings["target_path"],\
345 # "Could not remove existing file: "\
346 # +self.settings["target_path"],env=self.env)
347 touch(self.settings["autoresume_path"]+"setup_target_path")
349 if not os.path.exists(self.settings["storedir"]+"/builds/"):
350 os.makedirs(self.settings["storedir"]+"/builds/")
352 def set_fsscript(self):
353 if self.settings["spec_prefix"]+"/fsscript" in self.settings:
354 self.settings["fsscript"]=\
355 self.settings[self.settings["spec_prefix"]+"/fsscript"]
356 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
359 if self.settings["spec_prefix"]+"/rcadd" in self.settings:
360 self.settings["rcadd"]=\
361 self.settings[self.settings["spec_prefix"]+"/rcadd"]
362 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
365 if self.settings["spec_prefix"]+"/rcdel" in self.settings:
366 self.settings["rcdel"]=\
367 self.settings[self.settings["spec_prefix"]+"/rcdel"]
368 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
371 if self.settings["spec_prefix"]+"/cdtar" in self.settings:
372 self.settings["cdtar"]=\
373 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
374 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
377 if self.settings["spec_prefix"]+"/iso" in self.settings:
378 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
379 self.settings["iso"]=\
380 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
382 # This automatically prepends the build dir to the ISO output path
383 # if it doesn't start with a /
384 self.settings["iso"] = normpath(self.settings["storedir"] + \
385 "/builds/" + self.settings["rel_type"] + "/" + \
386 self.settings[self.settings["spec_prefix"]+"/iso"])
387 del self.settings[self.settings["spec_prefix"]+"/iso"]
389 def set_fstype(self):
390 if self.settings["spec_prefix"]+"/fstype" in self.settings:
391 self.settings["fstype"]=\
392 self.settings[self.settings["spec_prefix"]+"/fstype"]
393 del self.settings[self.settings["spec_prefix"]+"/fstype"]
395 if "fstype" not in self.settings:
396 self.settings["fstype"]="normal"
397 for x in self.valid_values:
398 if x == self.settings["spec_prefix"]+"/fstype":
399 print "\n"+self.settings["spec_prefix"]+\
400 "/fstype is being set to the default of \"normal\"\n"
403 if "fstype" in self.settings:
404 self.valid_values.append("fsops")
405 if self.settings["spec_prefix"]+"/fsops" in self.settings:
406 self.settings["fsops"]=\
407 self.settings[self.settings["spec_prefix"]+"/fsops"]
408 del self.settings[self.settings["spec_prefix"]+"/fsops"]
410 def set_source_path(self):
411 if "SEEDCACHE" in self.settings\
412 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
413 self.settings["source_subpath"]+"/")):
414 self.settings["source_path"]=normpath(self.settings["storedir"]+\
415 "/tmp/"+self.settings["source_subpath"]+"/")
417 self.settings["source_path"]=normpath(self.settings["storedir"]+\
418 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
419 if os.path.isfile(self.settings["source_path"]):
420 # XXX: Is this even necessary if the previous check passes?
421 if os.path.exists(self.settings["source_path"]):
422 self.settings["source_path_hash"]=\
423 generate_hash(self.settings["source_path"],\
424 hash_function=self.settings["hash_function"],\
426 print "Source path set to "+self.settings["source_path"]
427 if os.path.isdir(self.settings["source_path"]):
428 print "\tIf this is not desired, remove this directory or turn off"
429 print "\tseedcache in the options of catalyst.conf the source path"
430 print "\twill then be "+\
431 normpath(self.settings["storedir"]+"/builds/"+\
432 self.settings["source_subpath"]+".tar.bz2\n")
434 def set_dest_path(self):
435 if "root_path" in self.settings:
436 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
437 self.settings["root_path"])
439 self.settings["destpath"]=normpath(self.settings["chroot_path"])
441 def set_cleanables(self):
442 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
443 "/root/*", self.settings["portdir"]]
445 def set_snapshot_path(self):
446 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
447 "/snapshots/" + self.settings["snapshot_name"] +
448 self.settings["snapshot"] + ".tar.xz")
450 if os.path.exists(self.settings["snapshot_path"]):
451 self.settings["snapshot_path_hash"]=\
452 generate_hash(self.settings["snapshot_path"],\
453 hash_function=self.settings["hash_function"],verbose=False)
455 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
456 "/snapshots/" + self.settings["snapshot_name"] +
457 self.settings["snapshot"] + ".tar.bz2")
459 if os.path.exists(self.settings["snapshot_path"]):
460 self.settings["snapshot_path_hash"]=\
461 generate_hash(self.settings["snapshot_path"],\
462 hash_function=self.settings["hash_function"],verbose=False)
464 def set_snapcache_path(self):
465 if "SNAPCACHE" in self.settings:
466 self.settings["snapshot_cache_path"]=\
467 normpath(self.settings["snapshot_cache"]+"/"+\
468 self.settings["snapshot"]+"/")
469 self.snapcache_lock=\
470 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
471 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
473 def set_chroot_path(self):
475 NOTE: the trailing slash is very important!
476 Things *will* break without it!
478 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
479 "/tmp/"+self.settings["target_subpath"]+"/")
480 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
482 def set_autoresume_path(self):
483 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
484 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
485 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
486 self.settings["version_stamp"]+"/")
487 if "AUTORESUME" in self.settings:
488 print "The autoresume path is " + self.settings["autoresume_path"]
489 if not os.path.exists(self.settings["autoresume_path"]):
490 os.makedirs(self.settings["autoresume_path"],0755)
492 def set_controller_file(self):
493 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
494 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
497 def set_iso_volume_id(self):
498 if self.settings["spec_prefix"]+"/volid" in self.settings:
499 self.settings["iso_volume_id"]=\
500 self.settings[self.settings["spec_prefix"]+"/volid"]
501 if len(self.settings["iso_volume_id"])>32:
502 raise CatalystError,\
503 "ISO volume ID must not exceed 32 characters."
505 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
507 def set_action_sequence(self):
508 """ Default action sequence for run method """
509 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
510 "setup_confdir","portage_overlay",\
511 "base_dirs","bind","chroot_setup","setup_environment",\
512 "run_local","preclean","unbind","clean"]
513 # if "TARBALL" in self.settings or \
514 # "FETCH" not in self.settings:
515 if "FETCH" not in self.settings:
516 self.settings["action_sequence"].append("capture")
517 self.settings["action_sequence"].append("clear_autoresume")
520 if self.settings["spec_prefix"]+"/use" in self.settings:
521 self.settings["use"]=\
522 self.settings[self.settings["spec_prefix"]+"/use"]
523 del self.settings[self.settings["spec_prefix"]+"/use"]
524 if "use" not in self.settings:
525 self.settings["use"]=""
526 if type(self.settings["use"])==types.StringType:
527 self.settings["use"]=self.settings["use"].split()
529 # Force bindist when options ask for it
530 if "BINDIST" in self.settings:
531 self.settings["use"].append("bindist")
533 def set_stage_path(self):
534 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
536 def set_mounts(self):
539 def set_packages(self):
543 if self.settings["spec_prefix"]+"/rm" in self.settings:
544 if type(self.settings[self.settings["spec_prefix"]+\
545 "/rm"])==types.StringType:
546 self.settings[self.settings["spec_prefix"]+"/rm"]=\
547 self.settings[self.settings["spec_prefix"]+"/rm"].split()
549 def set_linuxrc(self):
550 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
551 if type(self.settings[self.settings["spec_prefix"]+\
552 "/linuxrc"])==types.StringType:
553 self.settings["linuxrc"]=\
554 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
555 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
557 def set_busybox_config(self):
558 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
559 if type(self.settings[self.settings["spec_prefix"]+\
560 "/busybox_config"])==types.StringType:
561 self.settings["busybox_config"]=\
562 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
563 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
565 def set_portage_overlay(self):
566 if "portage_overlay" in self.settings:
567 if type(self.settings["portage_overlay"])==types.StringType:
568 self.settings["portage_overlay"]=\
569 self.settings["portage_overlay"].split()
570 print "portage_overlay directories are set to: \""+\
571 string.join(self.settings["portage_overlay"])+"\""
573 def set_overlay(self):
574 if self.settings["spec_prefix"]+"/overlay" in self.settings:
575 if type(self.settings[self.settings["spec_prefix"]+\
576 "/overlay"])==types.StringType:
577 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
578 self.settings[self.settings["spec_prefix"]+\
581 def set_root_overlay(self):
582 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
583 if type(self.settings[self.settings["spec_prefix"]+\
584 "/root_overlay"])==types.StringType:
585 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
586 self.settings[self.settings["spec_prefix"]+\
587 "/root_overlay"].split()
589 def set_root_path(self):
590 """ ROOT= variable for emerges """
591 self.settings["root_path"]="/"
593 def set_valid_build_kernel_vars(self,addlargs):
594 if "boot/kernel" in addlargs:
595 if type(addlargs["boot/kernel"])==types.StringType:
596 loopy=[addlargs["boot/kernel"]]
598 loopy=addlargs["boot/kernel"]
601 self.valid_values.append("boot/kernel/"+x+"/aliases")
602 self.valid_values.append("boot/kernel/"+x+"/config")
603 self.valid_values.append("boot/kernel/"+x+"/console")
604 self.valid_values.append("boot/kernel/"+x+"/extraversion")
605 self.valid_values.append("boot/kernel/"+x+"/gk_action")
606 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
607 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
608 self.valid_values.append("boot/kernel/"+x+"/machine_type")
609 self.valid_values.append("boot/kernel/"+x+"/sources")
610 self.valid_values.append("boot/kernel/"+x+"/softlevel")
611 self.valid_values.append("boot/kernel/"+x+"/use")
612 self.valid_values.append("boot/kernel/"+x+"/packages")
613 if "boot/kernel/"+x+"/packages" in addlargs:
614 if type(addlargs["boot/kernel/"+x+\
615 "/packages"])==types.StringType:
616 addlargs["boot/kernel/"+x+"/packages"]=\
617 [addlargs["boot/kernel/"+x+"/packages"]]
619 def set_build_kernel_vars(self):
620 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
621 self.settings["gk_mainargs"]=\
622 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
623 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
625 def kill_chroot_pids(self):
626 print "Checking for processes running in chroot and killing them."
629 Force environment variables to be exported so script can see them
631 self.setup_environment()
633 if os.path.exists(self.settings["sharedir"]+\
634 "/targets/support/kill-chroot-pids.sh"):
635 cmd("/bin/bash "+self.settings["sharedir"]+\
636 "/targets/support/kill-chroot-pids.sh",\
637 "kill-chroot-pids script failed.",env=self.env)
639 def mount_safety_check(self):
641 Check and verify that none of our paths in mypath are mounted. We don't
642 want to clean up with things still mounted, and this allows us to check.
643 Returns 1 on ok, 0 on "something is still mounted" case.
646 if not os.path.exists(self.settings["chroot_path"]):
649 print "self.mounts =", self.mounts
650 for x in self.mounts:
651 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
652 print "mount_safety_check() x =", x, target
653 if not os.path.exists(target):
657 """ Something is still mounted "" """
659 print target + " is still mounted; performing auto-bind-umount...",
660 """ Try to umount stuff ourselves """
663 raise CatalystError, "Auto-unbind failed for " + target
665 print "Auto-unbind successful..."
666 except CatalystError:
667 raise CatalystError, "Unable to auto-unbind " + target
672 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
675 if "SEEDCACHE" in self.settings:
676 if os.path.isdir(self.settings["source_path"]):
677 """ SEEDCACHE Is a directory, use rsync """
678 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
679 " "+self.settings["chroot_path"]
680 display_msg="\nStarting rsync from "+\
681 self.settings["source_path"]+"\nto "+\
682 self.settings["chroot_path"]+\
683 " (This may take some time) ...\n"
684 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
685 self.settings["chroot_path"]+" failed."
687 """ SEEDCACHE is a not a directory, try untar'ing """
688 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
689 display_msg="\nStarting tar extract from "+\
690 self.settings["source_path"]+"\nto "+\
691 self.settings["chroot_path"]+\
692 " (This may take some time) ...\n"
693 if "bz2" == self.settings["chroot_path"][-3:]:
694 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
695 self.settings["chroot_path"]
697 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
698 self.settings["chroot_path"]
699 error_msg="Tarball extraction of "+\
700 self.settings["source_path"]+" to "+\
701 self.settings["chroot_path"]+" failed."
703 """ No SEEDCACHE, use tar """
704 display_msg="\nStarting tar extract from "+\
705 self.settings["source_path"]+"\nto "+\
706 self.settings["chroot_path"]+\
707 " (This may take some time) ...\n"
708 if "bz2" == self.settings["chroot_path"][-3:]:
709 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
710 self.settings["chroot_path"]
712 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
713 self.settings["chroot_path"]
714 error_msg="Tarball extraction of "+self.settings["source_path"]+\
715 " to "+self.settings["chroot_path"]+" failed."
717 if "AUTORESUME" in self.settings:
718 if os.path.isdir(self.settings["source_path"]) \
719 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
720 """ Autoresume is valid, SEEDCACHE is valid """
722 invalid_snapshot=False
724 elif os.path.isfile(self.settings["source_path"]) \
725 and self.settings["source_path_hash"]==clst_unpack_hash:
726 """ Autoresume is valid, tarball is valid """
728 invalid_snapshot=True
730 elif os.path.isdir(self.settings["source_path"]) \
731 and not os.path.exists(self.settings["autoresume_path"]+\
733 """ Autoresume is invalid, SEEDCACHE """
735 invalid_snapshot=False
737 elif os.path.isfile(self.settings["source_path"]) \
738 and self.settings["source_path_hash"]!=clst_unpack_hash:
739 """ Autoresume is invalid, tarball """
741 invalid_snapshot=True
743 """ No autoresume, SEEDCACHE """
744 if "SEEDCACHE" in self.settings:
745 """ SEEDCACHE so let's run rsync and let it clean up """
746 if os.path.isdir(self.settings["source_path"]):
748 invalid_snapshot=False
749 elif os.path.isfile(self.settings["source_path"]):
750 """ Tarball so unpack and remove anything already there """
752 invalid_snapshot=True
753 """ No autoresume, no SEEDCACHE """
755 """ Tarball so unpack and remove anything already there """
756 if os.path.isfile(self.settings["source_path"]):
758 invalid_snapshot=True
759 elif os.path.isdir(self.settings["source_path"]):
760 """ We should never reach this, so something is very wrong """
761 raise CatalystError,\
762 "source path is a dir but seedcache is not enabled"
765 self.mount_safety_check()
768 if "AUTORESUME" in self.settings:
769 print "No Valid Resume point detected, cleaning up..."
771 self.clear_autoresume()
774 if not os.path.exists(self.settings["chroot_path"]):
775 os.makedirs(self.settings["chroot_path"])
777 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
778 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
780 if "PKGCACHE" in self.settings:
781 if not os.path.exists(self.settings["pkgcache_path"]):
782 os.makedirs(self.settings["pkgcache_path"],0755)
784 if "KERNCACHE" in self.settings:
785 if not os.path.exists(self.settings["kerncache_path"]):
786 os.makedirs(self.settings["kerncache_path"],0755)
789 cmd(unpack_cmd,error_msg,env=self.env)
791 if "source_path_hash" in self.settings:
792 myf=open(self.settings["autoresume_path"]+"unpack","w")
793 myf.write(self.settings["source_path_hash"])
796 touch(self.settings["autoresume_path"]+"unpack")
798 print "Resume point detected, skipping unpack operation..."
800 def unpack_snapshot(self):
802 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
805 if "SNAPCACHE" in self.settings:
806 snapshot_cache_hash=\
807 read_from_clst(self.settings["snapshot_cache_path"]+\
809 destdir=self.settings["snapshot_cache_path"]
810 if "bz2" == self.settings["chroot_path"][-3:]:
811 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
813 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
814 unpack_errmsg="Error unpacking snapshot"
815 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
816 self.settings["snapshot_cache_path"]+\
817 " (This can take a long time)..."
818 cleanup_errmsg="Error removing existing snapshot cache directory."
819 self.snapshot_lock_object=self.snapcache_lock
821 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
822 print "Valid snapshot cache, skipping unpack of portage tree..."
825 destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
826 cleanup_errmsg="Error removing existing snapshot directory."
828 "Cleaning up existing portage tree (This can take a long time)..."
829 if "bz2" == self.settings["chroot_path"][-3:]:
830 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
831 self.settings["chroot_path"]+"/usr"
833 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
834 self.settings["chroot_path"]+"/usr"
835 unpack_errmsg="Error unpacking snapshot"
837 if "AUTORESUME" in self.settings \
838 and os.path.exists(self.settings["chroot_path"]+\
839 self.settings["portdir"]) \
840 and os.path.exists(self.settings["autoresume_path"]\
842 and self.settings["snapshot_path_hash"] == snapshot_hash:
844 "Valid Resume point detected, skipping unpack of portage tree..."
848 if "SNAPCACHE" in self.settings:
849 self.snapshot_lock_object.write_lock()
850 if os.path.exists(destdir):
852 cleanup_cmd="rm -rf "+destdir
853 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
854 if not os.path.exists(destdir):
855 os.makedirs(destdir,0755)
857 print "Unpacking portage tree (This can take a long time) ..."
858 cmd(unpack_cmd,unpack_errmsg,env=self.env)
860 if "SNAPCACHE" in self.settings:
861 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
862 myf.write(self.settings["snapshot_path_hash"])
865 print "Setting snapshot autoresume point"
866 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
867 myf.write(self.settings["snapshot_path_hash"])
870 if "SNAPCACHE" in self.settings:
871 self.snapshot_lock_object.unlock()
873 def config_profile_link(self):
874 if "AUTORESUME" in self.settings \
875 and os.path.exists(self.settings["autoresume_path"]+\
876 "config_profile_link"):
878 "Resume point detected, skipping config_profile_link operation..."
880 # TODO: zmedico and I discussed making this a directory and pushing
881 # in a parent file, as well as other user-specified configuration.
882 print "Configuring profile link..."
883 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
884 "Error zapping profile link",env=self.env)
885 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
886 cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
887 self.settings["target_profile"]+" "+\
888 self.settings["chroot_path"]+"/etc/portage/make.profile",\
889 "Error creating profile link",env=self.env)
890 touch(self.settings["autoresume_path"]+"config_profile_link")
892 def setup_confdir(self):
893 if "AUTORESUME" in self.settings \
894 and os.path.exists(self.settings["autoresume_path"]+\
896 print "Resume point detected, skipping setup_confdir operation..."
898 if "portage_confdir" in self.settings:
899 print "Configuring /etc/portage..."
900 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
901 self.settings["chroot_path"]+"/etc/portage/",\
902 "Error copying /etc/portage",env=self.env)
903 touch(self.settings["autoresume_path"]+"setup_confdir")
905 def portage_overlay(self):
906 """ We copy the contents of our overlays to /usr/local/portage """
907 if "portage_overlay" in self.settings:
908 for x in self.settings["portage_overlay"]:
909 if os.path.exists(x):
910 print "Copying overlay dir " +x
911 cmd("mkdir -p "+self.settings["chroot_path"]+\
912 self.settings["local_overlay"],\
913 "Could not make portage_overlay dir",env=self.env)
914 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
915 self.settings["local_overlay"],\
916 "Could not copy portage_overlay",env=self.env)
918 def root_overlay(self):
919 """ Copy over the root_overlay """
920 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
921 for x in self.settings[self.settings["spec_prefix"]+\
923 if os.path.exists(x):
924 print "Copying root_overlay: "+x
925 cmd("rsync -a "+x+"/ "+\
926 self.settings["chroot_path"],\
927 self.settings["spec_prefix"]+"/root_overlay: "+x+\
928 " copy failed.",env=self.env)
934 for x in self.mounts:
935 #print "bind(); x =", x
936 target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
937 if not os.path.exists(target):
938 os.makedirs(target, 0755)
940 if not os.path.exists(self.mountmap[x]):
941 if not self.mountmap[x] == "tmpfs":
942 os.makedirs(self.mountmap[x], 0755)
945 #print "bind(); src =", src
946 if "SNAPCACHE" in self.settings and x == "portdir":
947 self.snapshot_lock_object.read_lock()
948 if os.uname()[0] == "FreeBSD":
950 cmd = "mount -t devfs none " + target
951 retval=os.system(cmd)
953 cmd = "mount_nullfs " + src + " " + target
954 retval=os.system(cmd)
957 if "var_tmpfs_portage" in self.settings:
958 cmd = "mount -t tmpfs -o size=" + \
959 self.settings["var_tmpfs_portage"] + "G " + \
961 retval=os.system(cmd)
963 cmd = "mount --bind " + src + " " + target
964 #print "bind(); cmd =", cmd
965 retval=os.system(cmd)
968 raise CatalystError,"Couldn't bind mount " + src
972 mypath=self.settings["chroot_path"]
973 myrevmounts=self.mounts[:]
974 myrevmounts.reverse()
975 """ Unmount in reverse order for nested bind-mounts """
976 for x in myrevmounts:
977 target = normpath(mypath + self.target_mounts[x])
978 if not os.path.exists(target):
981 if not ismount(target):
984 retval=os.system("umount " + target)
987 warn("First attempt to unmount: " + target + " failed.")
988 warn("Killing any pids still running in the chroot")
990 self.kill_chroot_pids()
992 retval2 = os.system("umount " + target)
995 warn("Couldn't umount bind mount: " + target)
997 if "SNAPCACHE" in self.settings and x == "/usr/portage":
1000 It's possible the snapshot lock object isn't created yet.
1001 This is because mount safety check calls unbind before the
1002 target is fully initialized
1004 self.snapshot_lock_object.unlock()
1009 if any bind mounts really failed, then we need to raise
1010 this to potentially prevent an upcoming bash stage cleanup script
1011 from wiping our bind mounts.
1013 raise CatalystError,\
1014 "Couldn't umount one or more bind-mounts; aborting for safety."
1016 def chroot_setup(self):
1017 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
1018 "/etc/portage/make.conf")
1019 self.override_cbuild()
1020 self.override_chost()
1021 self.override_cflags()
1022 self.override_cxxflags()
1023 self.override_ldflags()
1024 if "AUTORESUME" in self.settings \
1025 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
1026 print "Resume point detected, skipping chroot_setup operation..."
1028 print "Setting up chroot..."
1030 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
1032 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1033 "Could not copy resolv.conf into place.",env=self.env)
1035 """ Copy over the envscript, if applicable """
1036 if "ENVSCRIPT" in self.settings:
1037 if not os.path.exists(self.settings["ENVSCRIPT"]):
1038 raise CatalystError,\
1039 "Can't find envscript "+self.settings["ENVSCRIPT"]
1041 print "\nWarning!!!!"
1042 print "\tOverriding certain env variables may cause catastrophic failure."
1043 print "\tIf your build fails look here first as the possible problem."
1044 print "\tCatalyst assumes you know what you are doing when setting"
1045 print "\t\tthese variables."
1046 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1047 print "\tYou have been warned\n"
1049 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1050 self.settings["chroot_path"]+"/tmp/envscript",\
1051 "Could not copy envscript into place.",env=self.env)
1054 Copy over /etc/hosts from the host in case there are any
1055 specialties in there
1057 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1058 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1059 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1060 "Could not backup /etc/hosts",env=self.env)
1061 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1062 "Could not copy /etc/hosts",env=self.env)
1064 """ Modify and write out make.conf (for the chroot) """
1065 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1066 "Could not remove "+self.settings["chroot_path"]+\
1067 "/etc/portage/make.conf",env=self.env)
1068 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1069 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1070 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1071 if "CFLAGS" in self.settings:
1072 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1073 if "CXXFLAGS" in self.settings:
1074 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1075 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1077 myf.write('CXXFLAGS="${CFLAGS}"\n')
1079 myf.write('CXXFLAGS="${CFLAGS}"\n')
1081 if "LDFLAGS" in self.settings:
1082 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1083 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1084 if "CBUILD" in self.settings:
1085 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")
1086 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1088 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")
1089 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1091 """ Figure out what our USE vars are for building """
1093 if "HOSTUSE" in self.settings:
1094 myusevars.extend(self.settings["HOSTUSE"])
1096 if "use" in self.settings:
1097 myusevars.extend(self.settings["use"])
1100 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1101 myusevars = sorted(set(myusevars))
1102 myf.write('USE="'+string.join(myusevars)+'"\n')
1103 if '-*' in myusevars:
1104 print "\nWarning!!! "
1105 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1106 "/use will cause portage to ignore"
1107 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1109 myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
1110 myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
1111 myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
1113 """ Setup the portage overlay """
1114 if "portage_overlay" in self.settings:
1115 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1118 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1119 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1120 "Could not backup /etc/portage/make.conf",env=self.env)
1121 touch(self.settings["autoresume_path"]+"chroot_setup")
1124 if "AUTORESUME" in self.settings \
1125 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1126 print "Resume point detected, skipping fsscript operation..."
1128 if "fsscript" in self.settings:
1129 if os.path.exists(self.settings["controller_file"]):
1130 cmd("/bin/bash "+self.settings["controller_file"]+\
1131 " fsscript","fsscript script failed.",env=self.env)
1132 touch(self.settings["autoresume_path"]+"fsscript")
1135 if "AUTORESUME" in self.settings \
1136 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1137 print "Resume point detected, skipping rcupdate operation..."
1139 if os.path.exists(self.settings["controller_file"]):
1140 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1141 "rc-update script failed.",env=self.env)
1142 touch(self.settings["autoresume_path"]+"rcupdate")
1145 if "AUTORESUME" in self.settings \
1146 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1147 print "Resume point detected, skipping clean operation..."
1149 for x in self.settings["cleanables"]:
1150 print "Cleaning chroot: "+x+"... "
1151 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1154 """ Put /etc/hosts back into place """
1155 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1156 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1157 self.settings["chroot_path"]+"/etc/hosts",\
1158 "Could not replace /etc/hosts",env=self.env)
1160 """ Remove our overlay """
1161 if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
1162 cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
1163 "Could not remove " + self.settings["local_overlay"], env=self.env)
1164 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1165 "/etc/portage/make.conf",\
1166 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1168 """ Clean up old and obsoleted files in /etc """
1169 if os.path.exists(self.settings["stage_path"]+"/etc"):
1170 cmd("find "+self.settings["stage_path"]+\
1171 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1172 "Could not remove stray files in /etc",env=self.env)
1174 if os.path.exists(self.settings["controller_file"]):
1175 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1176 "clean script failed.",env=self.env)
1177 touch(self.settings["autoresume_path"]+"clean")
1180 if "AUTORESUME" in self.settings \
1181 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1182 print "Resume point detected, skipping empty operation..."
1184 if self.settings["spec_prefix"]+"/empty" in self.settings:
1185 if type(self.settings[self.settings["spec_prefix"]+\
1186 "/empty"])==types.StringType:
1187 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1188 self.settings[self.settings["spec_prefix"]+\
1190 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1191 myemp=self.settings["destpath"]+x
1192 if not os.path.isdir(myemp) or os.path.islink(myemp):
1193 print x,"not a directory or does not exist, skipping 'empty' operation."
1195 print "Emptying directory",x
1197 stat the dir, delete the dir, recreate the dir and set
1198 the proper perms and ownership
1200 mystat=os.stat(myemp)
1201 shutil.rmtree(myemp)
1202 os.makedirs(myemp,0755)
1203 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1204 os.chmod(myemp,mystat[ST_MODE])
1205 touch(self.settings["autoresume_path"]+"empty")
1208 if "AUTORESUME" in self.settings \
1209 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1210 print "Resume point detected, skipping remove operation..."
1212 if self.settings["spec_prefix"]+"/rm" in self.settings:
1213 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1215 We're going to shell out for all these cleaning
1216 operations, so we get easy glob handling.
1218 print "livecd: removing "+x
1219 os.system("rm -rf "+self.settings["chroot_path"]+x)
1221 if os.path.exists(self.settings["controller_file"]):
1222 cmd("/bin/bash "+self.settings["controller_file"]+\
1223 " clean","Clean failed.",env=self.env)
1224 touch(self.settings["autoresume_path"]+"remove")
1230 if "AUTORESUME" in self.settings \
1231 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1232 print "Resume point detected, skipping preclean operation..."
1235 if os.path.exists(self.settings["controller_file"]):
1236 cmd("/bin/bash "+self.settings["controller_file"]+\
1237 " preclean","preclean script failed.",env=self.env)
1238 touch(self.settings["autoresume_path"]+"preclean")
1242 raise CatalystError, "Build failed, could not execute preclean"
1245 if "AUTORESUME" in self.settings \
1246 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1247 print "Resume point detected, skipping capture operation..."
1249 """ Capture target in a tarball """
1250 mypath=self.settings["target_path"].split("/")
1251 """ Remove filename from path """
1252 mypath=string.join(mypath[:-1],"/")
1254 """ Now make sure path exists """
1255 if not os.path.exists(mypath):
1258 print "Creating stage tarball..."
1260 cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1261 self.settings["stage_path"]+" .",\
1262 "Couldn't create stage tarball",env=self.env)
1264 self.gen_contents_file(self.settings["target_path"])
1265 self.gen_digest_file(self.settings["target_path"])
1267 touch(self.settings["autoresume_path"]+"capture")
1269 def run_local(self):
1270 if "AUTORESUME" in self.settings \
1271 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1272 print "Resume point detected, skipping run_local operation..."
1275 if os.path.exists(self.settings["controller_file"]):
1276 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1277 "run script failed.",env=self.env)
1278 touch(self.settings["autoresume_path"]+"run_local")
1280 except CatalystError:
1282 raise CatalystError,"Stage build aborting due to error."
1284 def setup_environment(self):
1286 Modify the current environment. This is an ugly hack that should be
1287 fixed. We need this to use the os.system() call since we can't
1288 specify our own environ
1290 for x in self.settings.keys():
1291 """ Sanitize var names by doing "s|/-.|_|g" """
1292 varname="clst_"+string.replace(x,"/","_")
1293 varname=string.replace(varname,"-","_")
1294 varname=string.replace(varname,".","_")
1295 if type(self.settings[x])==types.StringType:
1296 """ Prefix to prevent namespace clashes """
1297 #os.environ[varname]=self.settings[x]
1298 self.env[varname]=self.settings[x]
1299 elif type(self.settings[x])==types.ListType:
1300 #os.environ[varname]=string.join(self.settings[x])
1301 self.env[varname]=string.join(self.settings[x])
1302 elif type(self.settings[x])==types.BooleanType:
1303 if self.settings[x]:
1304 self.env[varname]="true"
1306 self.env[varname]="false"
1307 if "makeopts" in self.settings:
1308 self.env["MAKEOPTS"]=self.settings["makeopts"]
1311 self.chroot_lock.write_lock()
1313 """ Kill any pids in the chroot "" """
1314 self.kill_chroot_pids()
1316 """ Check for mounts right away and abort if we cannot unmount them """
1317 self.mount_safety_check()
1319 if "CLEAR_AUTORESUME" in self.settings:
1320 self.clear_autoresume()
1322 if "PURGETMPONLY" in self.settings:
1326 if "PURGEONLY" in self.settings:
1330 if "PURGE" in self.settings:
1333 for x in self.settings["action_sequence"]:
1334 print "--- Running action sequence: "+x
1337 apply(getattr(self,x))
1339 self.mount_safety_check()
1342 self.chroot_lock.unlock()
1345 if "AUTORESUME" in self.settings \
1346 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1347 print "Resume point detected, skipping unmerge operation..."
1349 if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1350 if type(self.settings[self.settings["spec_prefix"]+\
1351 "/unmerge"])==types.StringType:
1352 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1353 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1355 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1357 for x in range(0,len(myunmerge)):
1359 Surround args with quotes for passing to bash, allows
1360 things like "<" to remain intact
1362 myunmerge[x]="'"+myunmerge[x]+"'"
1363 myunmerge=string.join(myunmerge)
1365 """ Before cleaning, unmerge stuff """
1367 cmd("/bin/bash "+self.settings["controller_file"]+\
1368 " unmerge "+ myunmerge,"Unmerge script failed.",\
1370 print "unmerge shell script"
1371 except CatalystError:
1374 touch(self.settings["autoresume_path"]+"unmerge")
1376 def target_setup(self):
1377 if "AUTORESUME" in self.settings \
1378 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1379 print "Resume point detected, skipping target_setup operation..."
1381 print "Setting up filesystems per filesystem type"
1382 cmd("/bin/bash "+self.settings["controller_file"]+\
1383 " target_image_setup "+ self.settings["target_path"],\
1384 "target_image_setup script failed.",env=self.env)
1385 touch(self.settings["autoresume_path"]+"target_setup")
1387 def setup_overlay(self):
1388 if "AUTORESUME" in self.settings \
1389 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1390 print "Resume point detected, skipping setup_overlay operation..."
1392 if self.settings["spec_prefix"]+"/overlay" in self.settings:
1393 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1394 if os.path.exists(x):
1395 cmd("rsync -a "+x+"/ "+\
1396 self.settings["target_path"],\
1397 self.settings["spec_prefix"]+"overlay: "+x+\
1398 " copy failed.",env=self.env)
1399 touch(self.settings["autoresume_path"]+"setup_overlay")
1401 def create_iso(self):
1402 if "AUTORESUME" in self.settings \
1403 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1404 print "Resume point detected, skipping create_iso operation..."
1406 """ Create the ISO """
1407 if "iso" in self.settings:
1408 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1409 self.settings["iso"],"ISO creation script failed.",\
1411 self.gen_contents_file(self.settings["iso"])
1412 self.gen_digest_file(self.settings["iso"])
1413 touch(self.settings["autoresume_path"]+"create_iso")
1415 print "WARNING: livecd/iso was not defined."
1416 print "An ISO Image will not be created."
1418 def build_packages(self):
1419 if "AUTORESUME" in self.settings \
1420 and os.path.exists(self.settings["autoresume_path"]+\
1422 print "Resume point detected, skipping build_packages operation..."
1424 if self.settings["spec_prefix"]+"/packages" in self.settings:
1425 if "AUTORESUME" in self.settings \
1426 and os.path.exists(self.settings["autoresume_path"]+\
1428 print "Resume point detected, skipping build_packages operation..."
1431 list_bashify(self.settings[self.settings["spec_prefix"]\
1434 cmd("/bin/bash "+self.settings["controller_file"]+\
1435 " build_packages "+mypack,\
1436 "Error in attempt to build packages",env=self.env)
1437 touch(self.settings["autoresume_path"]+"build_packages")
1438 except CatalystError:
1440 raise CatalystError,self.settings["spec_prefix"]+\
1441 "build aborting due to error."
1443 def build_kernel(self):
1444 "Build all configured kernels"
1445 if "AUTORESUME" in self.settings \
1446 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1447 print "Resume point detected, skipping build_kernel operation..."
1449 if "boot/kernel" in self.settings:
1451 mynames=self.settings["boot/kernel"]
1452 if type(mynames)==types.StringType:
1455 Execute the script that sets up the kernel build environment
1457 cmd("/bin/bash "+self.settings["controller_file"]+\
1458 " pre-kmerge ","Runscript pre-kmerge failed",\
1460 for kname in mynames:
1461 self._build_kernel(kname=kname)
1462 touch(self.settings["autoresume_path"]+"build_kernel")
1463 except CatalystError:
1465 raise CatalystError,\
1466 "build aborting due to kernel build error."
1468 def _build_kernel(self, kname):
1469 "Build a single configured kernel by name"
1470 if "AUTORESUME" in self.settings \
1471 and os.path.exists(self.settings["autoresume_path"]\
1472 +"build_kernel_"+kname):
1473 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1475 self._copy_kernel_config(kname=kname)
1478 If we need to pass special options to the bootloader
1479 for this kernel put them into the environment
1481 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1482 myopts=self.settings["boot/kernel/"+kname+\
1485 if type(myopts) != types.StringType:
1486 myopts = string.join(myopts)
1487 self.env[kname+"_kernelopts"]=myopts
1490 self.env[kname+"_kernelopts"]=""
1492 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1493 self.settings["boot/kernel/"+kname+\
1496 self.env["clst_kextraversion"]=\
1497 self.settings["boot/kernel/"+kname+\
1500 self._copy_initramfs_overlay(kname=kname)
1502 """ Execute the script that builds the kernel """
1503 cmd("/bin/bash "+self.settings["controller_file"]+\
1505 "Runscript kernel build failed",env=self.env)
1507 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1508 if os.path.exists(self.settings["chroot_path"]+\
1509 "/tmp/initramfs_overlay/"):
1510 print "Cleaning up temporary overlay dir"
1511 cmd("rm -R "+self.settings["chroot_path"]+\
1512 "/tmp/initramfs_overlay/",env=self.env)
1514 touch(self.settings["autoresume_path"]+\
1515 "build_kernel_"+kname)
1518 Execute the script that cleans up the kernel build
1521 cmd("/bin/bash "+self.settings["controller_file"]+\
1523 "Runscript post-kmerge failed",env=self.env)
1525 def _copy_kernel_config(self, kname):
1526 if "boot/kernel/"+kname+"/config" in self.settings:
1527 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1529 raise CatalystError,\
1530 "Can't find kernel config: "+\
1531 self.settings["boot/kernel/"+kname+\
1535 cmd("cp "+self.settings["boot/kernel/"+kname+\
1537 self.settings["chroot_path"]+"/var/tmp/"+\
1539 "Couldn't copy kernel config: "+\
1540 self.settings["boot/kernel/"+kname+\
1541 "/config"],env=self.env)
1543 except CatalystError:
1546 def _copy_initramfs_overlay(self, kname):
1547 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1548 if os.path.exists(self.settings["boot/kernel/"+\
1549 kname+"/initramfs_overlay"]):
1550 print "Copying initramfs_overlay dir "+\
1551 self.settings["boot/kernel/"+kname+\
1552 "/initramfs_overlay"]
1555 self.settings["chroot_path"]+\
1556 "/tmp/initramfs_overlay/"+\
1557 self.settings["boot/kernel/"+kname+\
1558 "/initramfs_overlay"],env=self.env)
1560 cmd("cp -R "+self.settings["boot/kernel/"+\
1561 kname+"/initramfs_overlay"]+"/* "+\
1562 self.settings["chroot_path"]+\
1563 "/tmp/initramfs_overlay/"+\
1564 self.settings["boot/kernel/"+kname+\
1565 "/initramfs_overlay"],env=self.env)
1567 def bootloader(self):
1568 if "AUTORESUME" in self.settings \
1569 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1570 print "Resume point detected, skipping bootloader operation..."
1573 cmd("/bin/bash "+self.settings["controller_file"]+\
1574 " bootloader " + self.settings["target_path"],\
1575 "Bootloader script failed.",env=self.env)
1576 touch(self.settings["autoresume_path"]+"bootloader")
1577 except CatalystError:
1579 raise CatalystError,"Script aborting due to error."
1581 def livecd_update(self):
1582 if "AUTORESUME" in self.settings \
1583 and os.path.exists(self.settings["autoresume_path"]+\
1585 print "Resume point detected, skipping build_packages operation..."
1588 cmd("/bin/bash "+self.settings["controller_file"]+\
1589 " livecd-update","livecd-update failed.",env=self.env)
1590 touch(self.settings["autoresume_path"]+"livecd_update")
1592 except CatalystError:
1594 raise CatalystError,"build aborting due to livecd_update error."
1596 def clear_chroot(self):
1597 myemp=self.settings["chroot_path"]
1598 if os.path.isdir(myemp):
1599 print "Emptying directory",myemp
1601 stat the dir, delete the dir, recreate the dir and set
1602 the proper perms and ownership
1604 mystat=os.stat(myemp)
1605 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1606 """ There's no easy way to change flags recursively in python """
1607 if os.uname()[0] == "FreeBSD":
1608 os.system("chflags -R noschg "+myemp)
1609 shutil.rmtree(myemp)
1610 os.makedirs(myemp,0755)
1611 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1612 os.chmod(myemp,mystat[ST_MODE])
1614 def clear_packages(self):
1615 if "PKGCACHE" in self.settings:
1616 print "purging the pkgcache ..."
1618 myemp=self.settings["pkgcache_path"]
1619 if os.path.isdir(myemp):
1620 print "Emptying directory",myemp
1622 stat the dir, delete the dir, recreate the dir and set
1623 the proper perms and ownership
1625 mystat=os.stat(myemp)
1626 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1627 shutil.rmtree(myemp)
1628 os.makedirs(myemp,0755)
1629 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1630 os.chmod(myemp,mystat[ST_MODE])
1632 def clear_kerncache(self):
1633 if "KERNCACHE" in self.settings:
1634 print "purging the kerncache ..."
1636 myemp=self.settings["kerncache_path"]
1637 if os.path.isdir(myemp):
1638 print "Emptying directory",myemp
1640 stat the dir, delete the dir, recreate the dir and set
1641 the proper perms and ownership
1643 mystat=os.stat(myemp)
1644 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1645 shutil.rmtree(myemp)
1646 os.makedirs(myemp,0755)
1647 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1648 os.chmod(myemp,mystat[ST_MODE])
1650 def clear_autoresume(self):
1651 """ Clean resume points since they are no longer needed """
1652 if "AUTORESUME" in self.settings:
1653 print "Removing AutoResume Points: ..."
1654 myemp=self.settings["autoresume_path"]
1655 if os.path.isdir(myemp):
1656 if "AUTORESUME" in self.settings:
1657 print "Emptying directory",myemp
1659 stat the dir, delete the dir, recreate the dir and set
1660 the proper perms and ownership
1662 mystat=os.stat(myemp)
1663 if os.uname()[0] == "FreeBSD":
1664 cmd("chflags -R noschg "+myemp,\
1665 "Could not remove immutable flag for file "\
1667 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1668 shutil.rmtree(myemp)
1669 os.makedirs(myemp,0755)
1670 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1671 os.chmod(myemp,mystat[ST_MODE])
1673 def gen_contents_file(self,file):
1674 if os.path.exists(file+".CONTENTS"):
1675 os.remove(file+".CONTENTS")
1676 if "contents" in self.settings:
1677 if os.path.exists(file):
1678 myf=open(file+".CONTENTS","w")
1680 for i in self.settings["contents"].split():
1685 contents=generate_contents(file,contents_function=j,\
1686 verbose="VERBOSE" in self.settings)
1691 def gen_digest_file(self,file):
1692 if os.path.exists(file+".DIGESTS"):
1693 os.remove(file+".DIGESTS")
1694 if "digests" in self.settings:
1695 if os.path.exists(file):
1696 myf=open(file+".DIGESTS","w")
1698 for i in self.settings["digests"].split():
1702 for f in [file, file+'.CONTENTS']:
1703 if os.path.exists(f):
1705 for k in hash_map.keys():
1706 hash=generate_hash(f,hash_function=k,verbose=\
1707 "VERBOSE" in self.settings)
1711 hash=generate_hash(f,hash_function=j,verbose=\
1712 "VERBOSE" in self.settings)
1717 countdown(10,"Purging Caches ...")
1718 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1719 print "clearing autoresume ..."
1720 self.clear_autoresume()
1722 print "clearing chroot ..."
1725 if "PURGETMPONLY" not in self.settings:
1726 print "clearing package cache ..."
1727 self.clear_packages()
1729 print "clearing kerncache ..."
1730 self.clear_kerncache()
1732 # vim: ts=4 sw=4 sta et sts=4 ai