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'
12 class generic_stage_target(generic_target):
14 This class does all of the chroot setup, copying of files, etc. It is
15 the driver class for pretty much everything that Catalyst does.
17 def __init__(self,myspec,addlargs):
18 self.required_values.extend(["version_stamp","target","subarch",\
19 "rel_type","profile","snapshot","source_subpath"])
21 self.valid_values.extend(["version_stamp","target","subarch",\
22 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
23 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
24 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
26 self.set_valid_build_kernel_vars(addlargs)
27 generic_target.__init__(self,myspec,addlargs)
30 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
31 work better with vapier's CBUILD stuff. I've removed the "monolithic"
32 machinemap from this file and split up its contents amongst the
33 various arch/foo.py files.
35 When register() is called on each module in the arch/ dir, it now
36 returns a tuple instead of acting on the subarchmap dict that is
37 passed to it. The tuple contains the values that were previously
38 added to subarchmap as well as a new list of CHOSTs that go along
39 with that arch. This allows us to build machinemap on the fly based
40 on the keys in subarchmap and the values of the 2nd list returned
43 Also, after talking with vapier. I have a slightly better idea of what
44 certain variables are used for and what they should be set to. Neither
45 'buildarch' or 'hostarch' are used directly, so their value doesn't
46 really matter. They are just compared to determine if we are
47 cross-compiling. Because of this, they are just set to the name of the
48 module in arch/ that the subarch is part of to make things simpler.
49 The entire build process is still based off of 'subarch' like it was
56 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
57 "/arch/") if x.endswith(".py")]:
59 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
61 This next line loads the plugin as a module and assigns it to
64 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
65 ".py",(".py","r",imp.PY_SOURCE))
67 This next line registers all the subarches supported in the
70 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
71 self.subarchmap.update(tmpsubarchmap)
72 for machine in tmpmachinemap:
73 machinemap[machine] = x
74 for subarch in tmpsubarchmap:
75 machinemap[subarch] = x
79 This message should probably change a bit, since everything in
80 the dir should load just fine. If it doesn't, it's probably a
81 syntax error in the module
83 msg("Can't find/load "+x+".py plugin in "+\
84 self.settings["sharedir"]+"/arch/")
86 if "chost" in self.settings:
87 hostmachine = self.settings["chost"].split("-")[0]
88 if hostmachine not in machinemap:
89 raise CatalystError, "Unknown host machine type "+hostmachine
90 self.settings["hostarch"]=machinemap[hostmachine]
92 hostmachine = self.settings["subarch"]
93 if hostmachine in machinemap:
94 hostmachine = machinemap[hostmachine]
95 self.settings["hostarch"]=hostmachine
96 if "cbuild" in self.settings:
97 buildmachine = self.settings["cbuild"].split("-")[0]
99 buildmachine = os.uname()[4]
100 if buildmachine not in machinemap:
101 raise CatalystError, "Unknown build machine type "+buildmachine
102 self.settings["buildarch"]=machinemap[buildmachine]
103 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
104 self.settings["buildarch"])
106 """ Call arch constructor, pass our settings """
108 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
110 print "Invalid subarch: "+self.settings["subarch"]
111 print "Choose one of the following:",
112 for x in self.subarchmap:
117 print "Using target:",self.settings["target"]
118 """ Print a nice informational message """
119 if self.settings["buildarch"]==self.settings["hostarch"]:
120 print "Building natively for",self.settings["hostarch"]
121 elif self.settings["crosscompile"]:
122 print "Cross-compiling on",self.settings["buildarch"],\
123 "for different machine type",self.settings["hostarch"]
125 print "Building on",self.settings["buildarch"],\
126 "for alternate personality type",self.settings["hostarch"]
128 """ This must be set first as other set_ options depend on this """
129 self.set_spec_prefix()
131 """ Define all of our core variables """
132 self.set_target_profile()
133 self.set_target_subpath()
134 self.set_source_subpath()
137 self.set_snapshot_path()
139 self.set_source_path()
140 self.set_snapcache_path()
141 self.set_chroot_path()
142 self.set_autoresume_path()
144 self.set_stage_path()
145 self.set_target_path()
147 self.set_controller_file()
148 self.set_action_sequence()
150 self.set_cleanables()
151 self.set_iso_volume_id()
152 self.set_build_kernel_vars()
154 self.set_install_mask()
164 self.set_busybox_config()
166 self.set_portage_overlay()
167 self.set_root_overlay()
170 This next line checks to make sure that the specified variables exist
174 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
176 """ If we are using portage_confdir, check that as well. """
177 if "portage_confdir" in self.settings:
178 file_locate(self.settings,["portage_confdir"],expand=0)
180 """ Setup our mount points """
181 if "SNAPCACHE" in self.settings:
182 self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
185 "devpts": "/dev/pts",
186 "distdir": self.settings["distdir"],
187 "portdir": normpath("/".join([
188 self.settings["snapshot_cache_path"],
189 self.settings["repo_name"],
191 "port_tmpdir": "tmpfs",
195 self.mounts = ["proc", "dev", "distdir", "port_tmpdir"]
196 self.mountmap = {"proc":"/proc", "dev":"/dev", "devpts":"/dev/pts",
197 "distdir":self.settings["distdir"], "port_tmpdir":"tmpfs"}
198 if os.uname()[0] == "Linux":
199 self.mounts.append("devpts")
204 Configure any user specified options (either in catalyst.conf or on
207 if "PKGCACHE" in self.settings:
208 self.set_pkgcache_path()
209 print "Location of the package cache is "+\
210 self.settings["pkgcache_path"]
211 self.mounts.append("packagedir")
212 self.mountmap["packagedir"] = self.settings["pkgcache_path"]
214 if "KERNCACHE" in self.settings:
215 self.set_kerncache_path()
216 print "Location of the kerncache is "+\
217 self.settings["kerncache_path"]
218 self.mounts.append("kerncache")
219 self.mountmap["kerncache"] = self.settings["kerncache_path"]
221 if "CCACHE" in self.settings:
222 if "CCACHE_DIR" in os.environ:
223 ccdir=os.environ["CCACHE_DIR"]
224 del os.environ["CCACHE_DIR"]
226 ccdir="/root/.ccache"
227 if not os.path.isdir(ccdir):
228 raise CatalystError,\
229 "Compiler cache support can't be enabled (can't find "+\
231 self.mounts.append("ccache")
232 self.mountmap["ccache"] = ccdir
233 """ for the chroot: """
234 self.env["CCACHE_DIR"]="/var/tmp/ccache"
236 if "ICECREAM" in self.settings:
237 self.mounts.append("/var/cache/icecream")
238 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
239 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
241 if "port_logdir" in self.settings:
242 self.mounts.append("port_logdir")
243 self.mountmap["port_logdir"] = self.settings["port_logdir"]
244 self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
245 self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
247 def override_cbuild(self):
248 if "CBUILD" in self.makeconf:
249 self.settings["CBUILD"]=self.makeconf["CBUILD"]
251 def override_chost(self):
252 if "CHOST" in self.makeconf:
253 self.settings["CHOST"]=self.makeconf["CHOST"]
255 def override_cflags(self):
256 if "CFLAGS" in self.makeconf:
257 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
259 def override_cxxflags(self):
260 if "CXXFLAGS" in self.makeconf:
261 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
263 def override_ldflags(self):
264 if "LDFLAGS" in self.makeconf:
265 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
267 def set_install_mask(self):
268 if "install_mask" in self.settings:
269 if type(self.settings["install_mask"])!=types.StringType:
270 self.settings["install_mask"]=\
271 string.join(self.settings["install_mask"])
273 def set_spec_prefix(self):
274 self.settings["spec_prefix"]=self.settings["target"]
276 def set_target_profile(self):
277 self.settings["target_profile"]=self.settings["profile"]
279 def set_target_subpath(self):
280 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
281 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
282 self.settings["version_stamp"]
284 def set_source_subpath(self):
285 if type(self.settings["source_subpath"])!=types.StringType:
286 raise CatalystError,\
287 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
289 def set_pkgcache_path(self):
290 if "pkgcache_path" in self.settings:
291 if type(self.settings["pkgcache_path"])!=types.StringType:
292 self.settings["pkgcache_path"]=\
293 normpath(string.join(self.settings["pkgcache_path"]))
295 self.settings["pkgcache_path"]=\
296 normpath(self.settings["storedir"]+"/packages/"+\
297 self.settings["target_subpath"]+"/")
299 def set_kerncache_path(self):
300 if "kerncache_path" in self.settings:
301 if type(self.settings["kerncache_path"])!=types.StringType:
302 self.settings["kerncache_path"]=\
303 normpath(string.join(self.settings["kerncache_path"]))
305 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
306 "/kerncache/"+self.settings["target_subpath"]+"/")
308 def set_target_path(self):
309 self.settings["target_path"]=normpath(self.settings["storedir"]+\
310 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
311 if "AUTORESUME" in self.settings\
312 and os.path.exists(self.settings["autoresume_path"]+\
313 "setup_target_path"):
315 "Resume point detected, skipping target path setup operation..."
317 """ First clean up any existing target stuff """
318 # XXX WTF are we removing the old tarball before we start building the
319 # XXX new one? If the build fails, you don't want to be left with
321 # if os.path.isfile(self.settings["target_path"]):
322 # cmd("rm -f "+self.settings["target_path"],\
323 # "Could not remove existing file: "\
324 # +self.settings["target_path"],env=self.env)
325 touch(self.settings["autoresume_path"]+"setup_target_path")
327 if not os.path.exists(self.settings["storedir"]+"/builds/"):
328 os.makedirs(self.settings["storedir"]+"/builds/")
330 def set_fsscript(self):
331 if self.settings["spec_prefix"]+"/fsscript" in self.settings:
332 self.settings["fsscript"]=\
333 self.settings[self.settings["spec_prefix"]+"/fsscript"]
334 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
337 if self.settings["spec_prefix"]+"/rcadd" in self.settings:
338 self.settings["rcadd"]=\
339 self.settings[self.settings["spec_prefix"]+"/rcadd"]
340 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
343 if self.settings["spec_prefix"]+"/rcdel" in self.settings:
344 self.settings["rcdel"]=\
345 self.settings[self.settings["spec_prefix"]+"/rcdel"]
346 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
349 if self.settings["spec_prefix"]+"/cdtar" in self.settings:
350 self.settings["cdtar"]=\
351 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
352 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
355 if self.settings["spec_prefix"]+"/iso" in self.settings:
356 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
357 self.settings["iso"]=\
358 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
360 # This automatically prepends the build dir to the ISO output path
361 # if it doesn't start with a /
362 self.settings["iso"] = normpath(self.settings["storedir"] + \
363 "/builds/" + self.settings["rel_type"] + "/" + \
364 self.settings[self.settings["spec_prefix"]+"/iso"])
365 del self.settings[self.settings["spec_prefix"]+"/iso"]
367 def set_fstype(self):
368 if self.settings["spec_prefix"]+"/fstype" in self.settings:
369 self.settings["fstype"]=\
370 self.settings[self.settings["spec_prefix"]+"/fstype"]
371 del self.settings[self.settings["spec_prefix"]+"/fstype"]
373 if "fstype" not in self.settings:
374 self.settings["fstype"]="normal"
375 for x in self.valid_values:
376 if x == self.settings["spec_prefix"]+"/fstype":
377 print "\n"+self.settings["spec_prefix"]+\
378 "/fstype is being set to the default of \"normal\"\n"
381 if "fstype" in self.settings:
382 self.valid_values.append("fsops")
383 if self.settings["spec_prefix"]+"/fsops" in self.settings:
384 self.settings["fsops"]=\
385 self.settings[self.settings["spec_prefix"]+"/fsops"]
386 del self.settings[self.settings["spec_prefix"]+"/fsops"]
388 def set_source_path(self):
389 if "SEEDCACHE" in self.settings\
390 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
391 self.settings["source_subpath"]+"/")):
392 self.settings["source_path"]=normpath(self.settings["storedir"]+\
393 "/tmp/"+self.settings["source_subpath"]+"/")
395 self.settings["source_path"]=normpath(self.settings["storedir"]+\
396 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
397 if os.path.isfile(self.settings["source_path"]):
398 # XXX: Is this even necessary if the previous check passes?
399 if os.path.exists(self.settings["source_path"]):
400 self.settings["source_path_hash"]=\
401 generate_hash(self.settings["source_path"],\
402 hash_function=self.settings["hash_function"],\
404 print "Source path set to "+self.settings["source_path"]
405 if os.path.isdir(self.settings["source_path"]):
406 print "\tIf this is not desired, remove this directory or turn off"
407 print "\tseedcache in the options of catalyst.conf the source path"
408 print "\twill then be "+\
409 normpath(self.settings["storedir"]+"/builds/"+\
410 self.settings["source_subpath"]+".tar.bz2\n")
412 def set_dest_path(self):
413 if "root_path" in self.settings:
414 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
415 self.settings["root_path"])
417 self.settings["destpath"]=normpath(self.settings["chroot_path"])
419 def set_cleanables(self):
420 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
421 "/root/*", self.settings["portdir"]]
423 def set_snapshot_path(self):
424 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
425 "/snapshots/" + self.settings["snapshot_name"] +
426 self.settings["snapshot"] + ".tar.xz")
428 if os.path.exists(self.settings["snapshot_path"]):
429 self.settings["snapshot_path_hash"]=\
430 generate_hash(self.settings["snapshot_path"],\
431 hash_function=self.settings["hash_function"],verbose=False)
433 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
434 "/snapshots/" + self.settings["snapshot_name"] +
435 self.settings["snapshot"] + ".tar.bz2")
437 if os.path.exists(self.settings["snapshot_path"]):
438 self.settings["snapshot_path_hash"]=\
439 generate_hash(self.settings["snapshot_path"],\
440 hash_function=self.settings["hash_function"],verbose=False)
442 def set_snapcache_path(self):
443 if "SNAPCACHE" in self.settings:
444 self.settings["snapshot_cache_path"]=\
445 normpath(self.settings["snapshot_cache"]+"/"+\
446 self.settings["snapshot"]+"/")
447 self.snapcache_lock=\
448 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
449 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
451 def set_chroot_path(self):
453 NOTE: the trailing slash is very important!
454 Things *will* break without it!
456 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
457 "/tmp/"+self.settings["target_subpath"]+"/")
458 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
460 def set_autoresume_path(self):
461 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
462 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
463 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
464 self.settings["version_stamp"]+"/")
465 if "AUTORESUME" in self.settings:
466 print "The autoresume path is " + self.settings["autoresume_path"]
467 if not os.path.exists(self.settings["autoresume_path"]):
468 os.makedirs(self.settings["autoresume_path"],0755)
470 def set_controller_file(self):
471 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
472 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
475 def set_iso_volume_id(self):
476 if self.settings["spec_prefix"]+"/volid" in self.settings:
477 self.settings["iso_volume_id"]=\
478 self.settings[self.settings["spec_prefix"]+"/volid"]
479 if len(self.settings["iso_volume_id"])>32:
480 raise CatalystError,\
481 "ISO volume ID must not exceed 32 characters."
483 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
485 def set_action_sequence(self):
486 """ Default action sequence for run method """
487 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
488 "setup_confdir","portage_overlay",\
489 "base_dirs","bind","chroot_setup","setup_environment",\
490 "run_local","preclean","unbind","clean"]
491 # if "TARBALL" in self.settings or \
492 # "FETCH" not in self.settings:
493 if "FETCH" not in self.settings:
494 self.settings["action_sequence"].append("capture")
495 self.settings["action_sequence"].append("clear_autoresume")
498 if self.settings["spec_prefix"]+"/use" in self.settings:
499 self.settings["use"]=\
500 self.settings[self.settings["spec_prefix"]+"/use"]
501 del self.settings[self.settings["spec_prefix"]+"/use"]
502 if "use" not in self.settings:
503 self.settings["use"]=""
504 if type(self.settings["use"])==types.StringType:
505 self.settings["use"]=self.settings["use"].split()
507 # Force bindist when options ask for it
508 if "BINDIST" in self.settings:
509 self.settings["use"].append("bindist")
511 def set_stage_path(self):
512 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
514 def set_mounts(self):
517 def set_packages(self):
521 if self.settings["spec_prefix"]+"/rm" in self.settings:
522 if type(self.settings[self.settings["spec_prefix"]+\
523 "/rm"])==types.StringType:
524 self.settings[self.settings["spec_prefix"]+"/rm"]=\
525 self.settings[self.settings["spec_prefix"]+"/rm"].split()
527 def set_linuxrc(self):
528 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
529 if type(self.settings[self.settings["spec_prefix"]+\
530 "/linuxrc"])==types.StringType:
531 self.settings["linuxrc"]=\
532 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
533 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
535 def set_busybox_config(self):
536 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
537 if type(self.settings[self.settings["spec_prefix"]+\
538 "/busybox_config"])==types.StringType:
539 self.settings["busybox_config"]=\
540 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
541 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
543 def set_portage_overlay(self):
544 if "portage_overlay" in self.settings:
545 if type(self.settings["portage_overlay"])==types.StringType:
546 self.settings["portage_overlay"]=\
547 self.settings["portage_overlay"].split()
548 print "portage_overlay directories are set to: \""+\
549 string.join(self.settings["portage_overlay"])+"\""
551 def set_overlay(self):
552 if self.settings["spec_prefix"]+"/overlay" in self.settings:
553 if type(self.settings[self.settings["spec_prefix"]+\
554 "/overlay"])==types.StringType:
555 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
556 self.settings[self.settings["spec_prefix"]+\
559 def set_root_overlay(self):
560 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
561 if type(self.settings[self.settings["spec_prefix"]+\
562 "/root_overlay"])==types.StringType:
563 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
564 self.settings[self.settings["spec_prefix"]+\
565 "/root_overlay"].split()
567 def set_root_path(self):
568 """ ROOT= variable for emerges """
569 self.settings["root_path"]="/"
571 def set_valid_build_kernel_vars(self,addlargs):
572 if "boot/kernel" in addlargs:
573 if type(addlargs["boot/kernel"])==types.StringType:
574 loopy=[addlargs["boot/kernel"]]
576 loopy=addlargs["boot/kernel"]
579 self.valid_values.append("boot/kernel/"+x+"/aliases")
580 self.valid_values.append("boot/kernel/"+x+"/config")
581 self.valid_values.append("boot/kernel/"+x+"/console")
582 self.valid_values.append("boot/kernel/"+x+"/extraversion")
583 self.valid_values.append("boot/kernel/"+x+"/gk_action")
584 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
585 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
586 self.valid_values.append("boot/kernel/"+x+"/machine_type")
587 self.valid_values.append("boot/kernel/"+x+"/sources")
588 self.valid_values.append("boot/kernel/"+x+"/softlevel")
589 self.valid_values.append("boot/kernel/"+x+"/use")
590 self.valid_values.append("boot/kernel/"+x+"/packages")
591 if "boot/kernel/"+x+"/packages" in addlargs:
592 if type(addlargs["boot/kernel/"+x+\
593 "/packages"])==types.StringType:
594 addlargs["boot/kernel/"+x+"/packages"]=\
595 [addlargs["boot/kernel/"+x+"/packages"]]
597 def set_build_kernel_vars(self):
598 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
599 self.settings["gk_mainargs"]=\
600 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
601 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
603 def kill_chroot_pids(self):
604 print "Checking for processes running in chroot and killing them."
607 Force environment variables to be exported so script can see them
609 self.setup_environment()
611 if os.path.exists(self.settings["sharedir"]+\
612 "/targets/support/kill-chroot-pids.sh"):
613 cmd("/bin/bash "+self.settings["sharedir"]+\
614 "/targets/support/kill-chroot-pids.sh",\
615 "kill-chroot-pids script failed.",env=self.env)
617 def mount_safety_check(self):
618 mypath=self.settings["chroot_path"]
621 Check and verify that none of our paths in mypath are mounted. We don't
622 want to clean up with things still mounted, and this allows us to check.
623 Returns 1 on ok, 0 on "something is still mounted" case.
626 if not os.path.exists(mypath):
629 for x in self.mounts:
630 if not os.path.exists(mypath + self.mountmap[x]):
633 if ismount(mypath + self.mountmap[x]):
634 """ Something is still mounted "" """
636 print self.mountmap[x] + " is still mounted; performing auto-bind-umount...",
637 """ Try to umount stuff ourselves """
639 if ismount(mypath + self.mountmap[x]):
640 raise CatalystError, "Auto-unbind failed for " + self.mountmap[x]
642 print "Auto-unbind successful..."
643 except CatalystError:
644 raise CatalystError, "Unable to auto-unbind " + self.mountmap[x]
649 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
652 if "SEEDCACHE" in self.settings:
653 if os.path.isdir(self.settings["source_path"]):
654 """ SEEDCACHE Is a directory, use rsync """
655 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
656 " "+self.settings["chroot_path"]
657 display_msg="\nStarting rsync from "+\
658 self.settings["source_path"]+"\nto "+\
659 self.settings["chroot_path"]+\
660 " (This may take some time) ...\n"
661 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
662 self.settings["chroot_path"]+" failed."
664 """ SEEDCACHE is a not a directory, try untar'ing """
665 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
666 display_msg="\nStarting tar extract from "+\
667 self.settings["source_path"]+"\nto "+\
668 self.settings["chroot_path"]+\
669 " (This may take some time) ...\n"
670 if "bz2" == self.settings["chroot_path"][-3:]:
671 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
672 self.settings["chroot_path"]
674 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
675 self.settings["chroot_path"]
676 error_msg="Tarball extraction of "+\
677 self.settings["source_path"]+" to "+\
678 self.settings["chroot_path"]+" failed."
680 """ No SEEDCACHE, use tar """
681 display_msg="\nStarting tar extract from "+\
682 self.settings["source_path"]+"\nto "+\
683 self.settings["chroot_path"]+\
684 " (This may take some time) ...\n"
685 if "bz2" == self.settings["chroot_path"][-3:]:
686 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
687 self.settings["chroot_path"]
689 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
690 self.settings["chroot_path"]
691 error_msg="Tarball extraction of "+self.settings["source_path"]+\
692 " to "+self.settings["chroot_path"]+" failed."
694 if "AUTORESUME" in self.settings:
695 if os.path.isdir(self.settings["source_path"]) \
696 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
697 """ Autoresume is valid, SEEDCACHE is valid """
699 invalid_snapshot=False
701 elif os.path.isfile(self.settings["source_path"]) \
702 and self.settings["source_path_hash"]==clst_unpack_hash:
703 """ Autoresume is valid, tarball is valid """
705 invalid_snapshot=True
707 elif os.path.isdir(self.settings["source_path"]) \
708 and not os.path.exists(self.settings["autoresume_path"]+\
710 """ Autoresume is invalid, SEEDCACHE """
712 invalid_snapshot=False
714 elif os.path.isfile(self.settings["source_path"]) \
715 and self.settings["source_path_hash"]!=clst_unpack_hash:
716 """ Autoresume is invalid, tarball """
718 invalid_snapshot=True
720 """ No autoresume, SEEDCACHE """
721 if "SEEDCACHE" in self.settings:
722 """ SEEDCACHE so let's run rsync and let it clean up """
723 if os.path.isdir(self.settings["source_path"]):
725 invalid_snapshot=False
726 elif os.path.isfile(self.settings["source_path"]):
727 """ Tarball so unpack and remove anything already there """
729 invalid_snapshot=True
730 """ No autoresume, no SEEDCACHE """
732 """ Tarball so unpack and remove anything already there """
733 if os.path.isfile(self.settings["source_path"]):
735 invalid_snapshot=True
736 elif os.path.isdir(self.settings["source_path"]):
737 """ We should never reach this, so something is very wrong """
738 raise CatalystError,\
739 "source path is a dir but seedcache is not enabled"
742 self.mount_safety_check()
745 if "AUTORESUME" in self.settings:
746 print "No Valid Resume point detected, cleaning up..."
748 self.clear_autoresume()
751 if not os.path.exists(self.settings["chroot_path"]):
752 os.makedirs(self.settings["chroot_path"])
754 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
755 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
757 if "PKGCACHE" in self.settings:
758 if not os.path.exists(self.settings["pkgcache_path"]):
759 os.makedirs(self.settings["pkgcache_path"],0755)
761 if "KERNCACHE" in self.settings:
762 if not os.path.exists(self.settings["kerncache_path"]):
763 os.makedirs(self.settings["kerncache_path"],0755)
766 cmd(unpack_cmd,error_msg,env=self.env)
768 if "source_path_hash" in self.settings:
769 myf=open(self.settings["autoresume_path"]+"unpack","w")
770 myf.write(self.settings["source_path_hash"])
773 touch(self.settings["autoresume_path"]+"unpack")
775 print "Resume point detected, skipping unpack operation..."
777 def unpack_snapshot(self):
779 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
782 if "SNAPCACHE" in self.settings:
783 snapshot_cache_hash=\
784 read_from_clst(self.settings["snapshot_cache_path"]+\
786 destdir=self.settings["snapshot_cache_path"]
787 if "bz2" == self.settings["chroot_path"][-3:]:
788 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
790 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
791 unpack_errmsg="Error unpacking snapshot"
792 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
793 self.settings["snapshot_cache_path"]+\
794 " (This can take a long time)..."
795 cleanup_errmsg="Error removing existing snapshot cache directory."
796 self.snapshot_lock_object=self.snapcache_lock
798 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
799 print "Valid snapshot cache, skipping unpack of portage tree..."
802 destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
803 cleanup_errmsg="Error removing existing snapshot directory."
805 "Cleaning up existing portage tree (This can take a long time)..."
806 if "bz2" == self.settings["chroot_path"][-3:]:
807 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
808 self.settings["chroot_path"]+"/usr"
810 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
811 self.settings["chroot_path"]+"/usr"
812 unpack_errmsg="Error unpacking snapshot"
814 if "AUTORESUME" in self.settings \
815 and os.path.exists(self.settings["chroot_path"]+\
816 self.settings["portdir"]) \
817 and os.path.exists(self.settings["autoresume_path"]\
819 and self.settings["snapshot_path_hash"] == snapshot_hash:
821 "Valid Resume point detected, skipping unpack of portage tree..."
825 if "SNAPCACHE" in self.settings:
826 self.snapshot_lock_object.write_lock()
827 if os.path.exists(destdir):
829 cleanup_cmd="rm -rf "+destdir
830 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
831 if not os.path.exists(destdir):
832 os.makedirs(destdir,0755)
834 print "Unpacking portage tree (This can take a long time) ..."
835 cmd(unpack_cmd,unpack_errmsg,env=self.env)
837 if "SNAPCACHE" in self.settings:
838 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
839 myf.write(self.settings["snapshot_path_hash"])
842 print "Setting snapshot autoresume point"
843 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
844 myf.write(self.settings["snapshot_path_hash"])
847 if "SNAPCACHE" in self.settings:
848 self.snapshot_lock_object.unlock()
850 def config_profile_link(self):
851 if "AUTORESUME" in self.settings \
852 and os.path.exists(self.settings["autoresume_path"]+\
853 "config_profile_link"):
855 "Resume point detected, skipping config_profile_link operation..."
857 # TODO: zmedico and I discussed making this a directory and pushing
858 # in a parent file, as well as other user-specified configuration.
859 print "Configuring profile link..."
860 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
861 "Error zapping profile link",env=self.env)
862 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
863 cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
864 self.settings["target_profile"]+" "+\
865 self.settings["chroot_path"]+"/etc/portage/make.profile",\
866 "Error creating profile link",env=self.env)
867 touch(self.settings["autoresume_path"]+"config_profile_link")
869 def setup_confdir(self):
870 if "AUTORESUME" in self.settings \
871 and os.path.exists(self.settings["autoresume_path"]+\
873 print "Resume point detected, skipping setup_confdir operation..."
875 if "portage_confdir" in self.settings:
876 print "Configuring /etc/portage..."
877 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
878 self.settings["chroot_path"]+"/etc/portage/",\
879 "Error copying /etc/portage",env=self.env)
880 touch(self.settings["autoresume_path"]+"setup_confdir")
882 def portage_overlay(self):
883 """ We copy the contents of our overlays to /usr/local/portage """
884 if "portage_overlay" in self.settings:
885 for x in self.settings["portage_overlay"]:
886 if os.path.exists(x):
887 print "Copying overlay dir " +x
888 cmd("mkdir -p "+self.settings["chroot_path"]+\
889 self.settings["local_overlay"],\
890 "Could not make portage_overlay dir",env=self.env)
891 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
892 self.settings["local_overlay"],\
893 "Could not copy portage_overlay",env=self.env)
895 def root_overlay(self):
896 """ Copy over the root_overlay """
897 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
898 for x in self.settings[self.settings["spec_prefix"]+\
900 if os.path.exists(x):
901 print "Copying root_overlay: "+x
902 cmd("rsync -a "+x+"/ "+\
903 self.settings["chroot_path"],\
904 self.settings["spec_prefix"]+"/root_overlay: "+x+\
905 " copy failed.",env=self.env)
911 for x in self.mounts:
912 if not os.path.exists(self.settings["chroot_path"] + self.mountmap[x]):
913 os.makedirs(self.settings["chroot_path"]+x,0755)
915 if not os.path.exists(self.mountmap[x]):
916 if not self.mountmap[x] == "tmpfs":
917 os.makedirs(self.mountmap[x],0755)
920 #print "bind(); src =", src
921 if "SNAPCACHE" in self.settings and x == "portdir":
922 self.snapshot_lock_object.read_lock()
923 if os.uname()[0] == "FreeBSD":
925 retval = os.system("mount -t devfs none " +
926 self.settings["chroot_path"] + src)
928 retval = os.system("mount_nullfs " + src + " " +
929 self.settings["chroot_path"] + src)
932 if "var_tmpfs_portage" in self.settings:
933 retval=os.system("mount -t tmpfs -o size="+\
934 self.settings["var_tmpfs_portage"]+"G "+src+" "+\
935 self.settings["chroot_path"]+x)
937 retval = os.system("mount --bind " + src + " " +
938 self.settings["chroot_path"] + src)
941 raise CatalystError,"Couldn't bind mount " + src
945 mypath=self.settings["chroot_path"]
946 myrevmounts=self.mounts[:]
947 myrevmounts.reverse()
948 """ Unmount in reverse order for nested bind-mounts """
949 for x in myrevmounts:
950 if not os.path.exists(mypath + self.mountmap[x]):
953 if not ismount(mypath + self.mountmap[x]):
956 retval=os.system("umount "+\
957 os.path.join(mypath, self.mountmap[x].lstrip(os.path.sep)))
960 warn("First attempt to unmount: " + mypath +
961 self.mountmap[x] +" failed.")
962 warn("Killing any pids still running in the chroot")
964 self.kill_chroot_pids()
966 retval2 = os.system("umount " + mypath + self.mountmap[x])
969 warn("Couldn't umount bind mount: " + mypath + self.mountmap[x])
971 if "SNAPCACHE" in self.settings and x == "/usr/portage":
974 It's possible the snapshot lock object isn't created yet.
975 This is because mount safety check calls unbind before the
976 target is fully initialized
978 self.snapshot_lock_object.unlock()
983 if any bind mounts really failed, then we need to raise
984 this to potentially prevent an upcoming bash stage cleanup script
985 from wiping our bind mounts.
987 raise CatalystError,\
988 "Couldn't umount one or more bind-mounts; aborting for safety."
990 def chroot_setup(self):
991 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
992 "/etc/portage/make.conf")
993 self.override_cbuild()
994 self.override_chost()
995 self.override_cflags()
996 self.override_cxxflags()
997 self.override_ldflags()
998 if "AUTORESUME" in self.settings \
999 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
1000 print "Resume point detected, skipping chroot_setup operation..."
1002 print "Setting up chroot..."
1004 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
1006 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1007 "Could not copy resolv.conf into place.",env=self.env)
1009 """ Copy over the envscript, if applicable """
1010 if "ENVSCRIPT" in self.settings:
1011 if not os.path.exists(self.settings["ENVSCRIPT"]):
1012 raise CatalystError,\
1013 "Can't find envscript "+self.settings["ENVSCRIPT"]
1015 print "\nWarning!!!!"
1016 print "\tOverriding certain env variables may cause catastrophic failure."
1017 print "\tIf your build fails look here first as the possible problem."
1018 print "\tCatalyst assumes you know what you are doing when setting"
1019 print "\t\tthese variables."
1020 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1021 print "\tYou have been warned\n"
1023 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1024 self.settings["chroot_path"]+"/tmp/envscript",\
1025 "Could not copy envscript into place.",env=self.env)
1028 Copy over /etc/hosts from the host in case there are any
1029 specialties in there
1031 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1032 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1033 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1034 "Could not backup /etc/hosts",env=self.env)
1035 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1036 "Could not copy /etc/hosts",env=self.env)
1038 """ Modify and write out make.conf (for the chroot) """
1039 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1040 "Could not remove "+self.settings["chroot_path"]+\
1041 "/etc/portage/make.conf",env=self.env)
1042 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1043 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1044 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1045 if "CFLAGS" in self.settings:
1046 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1047 if "CXXFLAGS" in self.settings:
1048 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1049 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1051 myf.write('CXXFLAGS="${CFLAGS}"\n')
1053 myf.write('CXXFLAGS="${CFLAGS}"\n')
1055 if "LDFLAGS" in self.settings:
1056 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1057 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1058 if "CBUILD" in self.settings:
1059 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")
1060 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1062 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")
1063 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1065 """ Figure out what our USE vars are for building """
1067 if "HOSTUSE" in self.settings:
1068 myusevars.extend(self.settings["HOSTUSE"])
1070 if "use" in self.settings:
1071 myusevars.extend(self.settings["use"])
1074 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1075 myusevars = sorted(set(myusevars))
1076 myf.write('USE="'+string.join(myusevars)+'"\n')
1077 if '-*' in myusevars:
1078 print "\nWarning!!! "
1079 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1080 "/use will cause portage to ignore"
1081 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1083 myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
1084 myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
1085 myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
1087 """ Setup the portage overlay """
1088 if "portage_overlay" in self.settings:
1089 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1092 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1093 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1094 "Could not backup /etc/portage/make.conf",env=self.env)
1095 touch(self.settings["autoresume_path"]+"chroot_setup")
1098 if "AUTORESUME" in self.settings \
1099 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1100 print "Resume point detected, skipping fsscript operation..."
1102 if "fsscript" in self.settings:
1103 if os.path.exists(self.settings["controller_file"]):
1104 cmd("/bin/bash "+self.settings["controller_file"]+\
1105 " fsscript","fsscript script failed.",env=self.env)
1106 touch(self.settings["autoresume_path"]+"fsscript")
1109 if "AUTORESUME" in self.settings \
1110 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1111 print "Resume point detected, skipping rcupdate operation..."
1113 if os.path.exists(self.settings["controller_file"]):
1114 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1115 "rc-update script failed.",env=self.env)
1116 touch(self.settings["autoresume_path"]+"rcupdate")
1119 if "AUTORESUME" in self.settings \
1120 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1121 print "Resume point detected, skipping clean operation..."
1123 for x in self.settings["cleanables"]:
1124 print "Cleaning chroot: "+x+"... "
1125 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1128 """ Put /etc/hosts back into place """
1129 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1130 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1131 self.settings["chroot_path"]+"/etc/hosts",\
1132 "Could not replace /etc/hosts",env=self.env)
1134 """ Remove our overlay """
1135 if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
1136 cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
1137 "Could not remove " + self.settings["local_overlay"], env=self.env)
1138 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1139 "/etc/portage/make.conf",\
1140 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1142 """ Clean up old and obsoleted files in /etc """
1143 if os.path.exists(self.settings["stage_path"]+"/etc"):
1144 cmd("find "+self.settings["stage_path"]+\
1145 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1146 "Could not remove stray files in /etc",env=self.env)
1148 if os.path.exists(self.settings["controller_file"]):
1149 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1150 "clean script failed.",env=self.env)
1151 touch(self.settings["autoresume_path"]+"clean")
1154 if "AUTORESUME" in self.settings \
1155 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1156 print "Resume point detected, skipping empty operation..."
1158 if self.settings["spec_prefix"]+"/empty" in self.settings:
1159 if type(self.settings[self.settings["spec_prefix"]+\
1160 "/empty"])==types.StringType:
1161 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1162 self.settings[self.settings["spec_prefix"]+\
1164 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1165 myemp=self.settings["destpath"]+x
1166 if not os.path.isdir(myemp) or os.path.islink(myemp):
1167 print x,"not a directory or does not exist, skipping 'empty' operation."
1169 print "Emptying directory",x
1171 stat the dir, delete the dir, recreate the dir and set
1172 the proper perms and ownership
1174 mystat=os.stat(myemp)
1175 shutil.rmtree(myemp)
1176 os.makedirs(myemp,0755)
1177 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1178 os.chmod(myemp,mystat[ST_MODE])
1179 touch(self.settings["autoresume_path"]+"empty")
1182 if "AUTORESUME" in self.settings \
1183 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1184 print "Resume point detected, skipping remove operation..."
1186 if self.settings["spec_prefix"]+"/rm" in self.settings:
1187 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1189 We're going to shell out for all these cleaning
1190 operations, so we get easy glob handling.
1192 print "livecd: removing "+x
1193 os.system("rm -rf "+self.settings["chroot_path"]+x)
1195 if os.path.exists(self.settings["controller_file"]):
1196 cmd("/bin/bash "+self.settings["controller_file"]+\
1197 " clean","Clean failed.",env=self.env)
1198 touch(self.settings["autoresume_path"]+"remove")
1204 if "AUTORESUME" in self.settings \
1205 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1206 print "Resume point detected, skipping preclean operation..."
1209 if os.path.exists(self.settings["controller_file"]):
1210 cmd("/bin/bash "+self.settings["controller_file"]+\
1211 " preclean","preclean script failed.",env=self.env)
1212 touch(self.settings["autoresume_path"]+"preclean")
1216 raise CatalystError, "Build failed, could not execute preclean"
1219 if "AUTORESUME" in self.settings \
1220 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1221 print "Resume point detected, skipping capture operation..."
1223 """ Capture target in a tarball """
1224 mypath=self.settings["target_path"].split("/")
1225 """ Remove filename from path """
1226 mypath=string.join(mypath[:-1],"/")
1228 """ Now make sure path exists """
1229 if not os.path.exists(mypath):
1232 print "Creating stage tarball..."
1234 cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1235 self.settings["stage_path"]+" .",\
1236 "Couldn't create stage tarball",env=self.env)
1238 self.gen_contents_file(self.settings["target_path"])
1239 self.gen_digest_file(self.settings["target_path"])
1241 touch(self.settings["autoresume_path"]+"capture")
1243 def run_local(self):
1244 if "AUTORESUME" in self.settings \
1245 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1246 print "Resume point detected, skipping run_local operation..."
1249 if os.path.exists(self.settings["controller_file"]):
1250 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1251 "run script failed.",env=self.env)
1252 touch(self.settings["autoresume_path"]+"run_local")
1254 except CatalystError:
1256 raise CatalystError,"Stage build aborting due to error."
1258 def setup_environment(self):
1260 Modify the current environment. This is an ugly hack that should be
1261 fixed. We need this to use the os.system() call since we can't
1262 specify our own environ
1264 for x in self.settings.keys():
1265 """ Sanitize var names by doing "s|/-.|_|g" """
1266 varname="clst_"+string.replace(x,"/","_")
1267 varname=string.replace(varname,"-","_")
1268 varname=string.replace(varname,".","_")
1269 if type(self.settings[x])==types.StringType:
1270 """ Prefix to prevent namespace clashes """
1271 #os.environ[varname]=self.settings[x]
1272 self.env[varname]=self.settings[x]
1273 elif type(self.settings[x])==types.ListType:
1274 #os.environ[varname]=string.join(self.settings[x])
1275 self.env[varname]=string.join(self.settings[x])
1276 elif type(self.settings[x])==types.BooleanType:
1277 if self.settings[x]:
1278 self.env[varname]="true"
1280 self.env[varname]="false"
1281 if "makeopts" in self.settings:
1282 self.env["MAKEOPTS"]=self.settings["makeopts"]
1285 self.chroot_lock.write_lock()
1287 """ Kill any pids in the chroot "" """
1288 self.kill_chroot_pids()
1290 """ Check for mounts right away and abort if we cannot unmount them """
1291 self.mount_safety_check()
1293 if "CLEAR_AUTORESUME" in self.settings:
1294 self.clear_autoresume()
1296 if "PURGETMPONLY" in self.settings:
1300 if "PURGEONLY" in self.settings:
1304 if "PURGE" in self.settings:
1307 for x in self.settings["action_sequence"]:
1308 print "--- Running action sequence: "+x
1311 apply(getattr(self,x))
1313 self.mount_safety_check()
1316 self.chroot_lock.unlock()
1319 if "AUTORESUME" in self.settings \
1320 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1321 print "Resume point detected, skipping unmerge operation..."
1323 if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1324 if type(self.settings[self.settings["spec_prefix"]+\
1325 "/unmerge"])==types.StringType:
1326 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1327 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1329 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1331 for x in range(0,len(myunmerge)):
1333 Surround args with quotes for passing to bash, allows
1334 things like "<" to remain intact
1336 myunmerge[x]="'"+myunmerge[x]+"'"
1337 myunmerge=string.join(myunmerge)
1339 """ Before cleaning, unmerge stuff """
1341 cmd("/bin/bash "+self.settings["controller_file"]+\
1342 " unmerge "+ myunmerge,"Unmerge script failed.",\
1344 print "unmerge shell script"
1345 except CatalystError:
1348 touch(self.settings["autoresume_path"]+"unmerge")
1350 def target_setup(self):
1351 if "AUTORESUME" in self.settings \
1352 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1353 print "Resume point detected, skipping target_setup operation..."
1355 print "Setting up filesystems per filesystem type"
1356 cmd("/bin/bash "+self.settings["controller_file"]+\
1357 " target_image_setup "+ self.settings["target_path"],\
1358 "target_image_setup script failed.",env=self.env)
1359 touch(self.settings["autoresume_path"]+"target_setup")
1361 def setup_overlay(self):
1362 if "AUTORESUME" in self.settings \
1363 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1364 print "Resume point detected, skipping setup_overlay operation..."
1366 if self.settings["spec_prefix"]+"/overlay" in self.settings:
1367 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1368 if os.path.exists(x):
1369 cmd("rsync -a "+x+"/ "+\
1370 self.settings["target_path"],\
1371 self.settings["spec_prefix"]+"overlay: "+x+\
1372 " copy failed.",env=self.env)
1373 touch(self.settings["autoresume_path"]+"setup_overlay")
1375 def create_iso(self):
1376 if "AUTORESUME" in self.settings \
1377 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1378 print "Resume point detected, skipping create_iso operation..."
1380 """ Create the ISO """
1381 if "iso" in self.settings:
1382 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1383 self.settings["iso"],"ISO creation script failed.",\
1385 self.gen_contents_file(self.settings["iso"])
1386 self.gen_digest_file(self.settings["iso"])
1387 touch(self.settings["autoresume_path"]+"create_iso")
1389 print "WARNING: livecd/iso was not defined."
1390 print "An ISO Image will not be created."
1392 def build_packages(self):
1393 if "AUTORESUME" in self.settings \
1394 and os.path.exists(self.settings["autoresume_path"]+\
1396 print "Resume point detected, skipping build_packages operation..."
1398 if self.settings["spec_prefix"]+"/packages" in self.settings:
1399 if "AUTORESUME" in self.settings \
1400 and os.path.exists(self.settings["autoresume_path"]+\
1402 print "Resume point detected, skipping build_packages operation..."
1405 list_bashify(self.settings[self.settings["spec_prefix"]\
1408 cmd("/bin/bash "+self.settings["controller_file"]+\
1409 " build_packages "+mypack,\
1410 "Error in attempt to build packages",env=self.env)
1411 touch(self.settings["autoresume_path"]+"build_packages")
1412 except CatalystError:
1414 raise CatalystError,self.settings["spec_prefix"]+\
1415 "build aborting due to error."
1417 def build_kernel(self):
1418 "Build all configured kernels"
1419 if "AUTORESUME" in self.settings \
1420 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1421 print "Resume point detected, skipping build_kernel operation..."
1423 if "boot/kernel" in self.settings:
1425 mynames=self.settings["boot/kernel"]
1426 if type(mynames)==types.StringType:
1429 Execute the script that sets up the kernel build environment
1431 cmd("/bin/bash "+self.settings["controller_file"]+\
1432 " pre-kmerge ","Runscript pre-kmerge failed",\
1434 for kname in mynames:
1435 self._build_kernel(kname=kname)
1436 touch(self.settings["autoresume_path"]+"build_kernel")
1437 except CatalystError:
1439 raise CatalystError,\
1440 "build aborting due to kernel build error."
1442 def _build_kernel(self, kname):
1443 "Build a single configured kernel by name"
1444 if "AUTORESUME" in self.settings \
1445 and os.path.exists(self.settings["autoresume_path"]\
1446 +"build_kernel_"+kname):
1447 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1449 self._copy_kernel_config(kname=kname)
1452 If we need to pass special options to the bootloader
1453 for this kernel put them into the environment
1455 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1456 myopts=self.settings["boot/kernel/"+kname+\
1459 if type(myopts) != types.StringType:
1460 myopts = string.join(myopts)
1461 self.env[kname+"_kernelopts"]=myopts
1464 self.env[kname+"_kernelopts"]=""
1466 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1467 self.settings["boot/kernel/"+kname+\
1470 self.env["clst_kextraversion"]=\
1471 self.settings["boot/kernel/"+kname+\
1474 self._copy_initramfs_overlay(kname=kname)
1476 """ Execute the script that builds the kernel """
1477 cmd("/bin/bash "+self.settings["controller_file"]+\
1479 "Runscript kernel build failed",env=self.env)
1481 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1482 if os.path.exists(self.settings["chroot_path"]+\
1483 "/tmp/initramfs_overlay/"):
1484 print "Cleaning up temporary overlay dir"
1485 cmd("rm -R "+self.settings["chroot_path"]+\
1486 "/tmp/initramfs_overlay/",env=self.env)
1488 touch(self.settings["autoresume_path"]+\
1489 "build_kernel_"+kname)
1492 Execute the script that cleans up the kernel build
1495 cmd("/bin/bash "+self.settings["controller_file"]+\
1497 "Runscript post-kmerge failed",env=self.env)
1499 def _copy_kernel_config(self, kname):
1500 if "boot/kernel/"+kname+"/config" in self.settings:
1501 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1503 raise CatalystError,\
1504 "Can't find kernel config: "+\
1505 self.settings["boot/kernel/"+kname+\
1509 cmd("cp "+self.settings["boot/kernel/"+kname+\
1511 self.settings["chroot_path"]+"/var/tmp/"+\
1513 "Couldn't copy kernel config: "+\
1514 self.settings["boot/kernel/"+kname+\
1515 "/config"],env=self.env)
1517 except CatalystError:
1520 def _copy_initramfs_overlay(self, kname):
1521 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1522 if os.path.exists(self.settings["boot/kernel/"+\
1523 kname+"/initramfs_overlay"]):
1524 print "Copying initramfs_overlay dir "+\
1525 self.settings["boot/kernel/"+kname+\
1526 "/initramfs_overlay"]
1529 self.settings["chroot_path"]+\
1530 "/tmp/initramfs_overlay/"+\
1531 self.settings["boot/kernel/"+kname+\
1532 "/initramfs_overlay"],env=self.env)
1534 cmd("cp -R "+self.settings["boot/kernel/"+\
1535 kname+"/initramfs_overlay"]+"/* "+\
1536 self.settings["chroot_path"]+\
1537 "/tmp/initramfs_overlay/"+\
1538 self.settings["boot/kernel/"+kname+\
1539 "/initramfs_overlay"],env=self.env)
1541 def bootloader(self):
1542 if "AUTORESUME" in self.settings \
1543 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1544 print "Resume point detected, skipping bootloader operation..."
1547 cmd("/bin/bash "+self.settings["controller_file"]+\
1548 " bootloader " + self.settings["target_path"],\
1549 "Bootloader script failed.",env=self.env)
1550 touch(self.settings["autoresume_path"]+"bootloader")
1551 except CatalystError:
1553 raise CatalystError,"Script aborting due to error."
1555 def livecd_update(self):
1556 if "AUTORESUME" in self.settings \
1557 and os.path.exists(self.settings["autoresume_path"]+\
1559 print "Resume point detected, skipping build_packages operation..."
1562 cmd("/bin/bash "+self.settings["controller_file"]+\
1563 " livecd-update","livecd-update failed.",env=self.env)
1564 touch(self.settings["autoresume_path"]+"livecd_update")
1566 except CatalystError:
1568 raise CatalystError,"build aborting due to livecd_update error."
1570 def clear_chroot(self):
1571 myemp=self.settings["chroot_path"]
1572 if os.path.isdir(myemp):
1573 print "Emptying directory",myemp
1575 stat the dir, delete the dir, recreate the dir and set
1576 the proper perms and ownership
1578 mystat=os.stat(myemp)
1579 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1580 """ There's no easy way to change flags recursively in python """
1581 if os.uname()[0] == "FreeBSD":
1582 os.system("chflags -R noschg "+myemp)
1583 shutil.rmtree(myemp)
1584 os.makedirs(myemp,0755)
1585 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1586 os.chmod(myemp,mystat[ST_MODE])
1588 def clear_packages(self):
1589 if "PKGCACHE" in self.settings:
1590 print "purging the pkgcache ..."
1592 myemp=self.settings["pkgcache_path"]
1593 if os.path.isdir(myemp):
1594 print "Emptying directory",myemp
1596 stat the dir, delete the dir, recreate the dir and set
1597 the proper perms and ownership
1599 mystat=os.stat(myemp)
1600 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1601 shutil.rmtree(myemp)
1602 os.makedirs(myemp,0755)
1603 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1604 os.chmod(myemp,mystat[ST_MODE])
1606 def clear_kerncache(self):
1607 if "KERNCACHE" in self.settings:
1608 print "purging the kerncache ..."
1610 myemp=self.settings["kerncache_path"]
1611 if os.path.isdir(myemp):
1612 print "Emptying directory",myemp
1614 stat the dir, delete the dir, recreate the dir and set
1615 the proper perms and ownership
1617 mystat=os.stat(myemp)
1618 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1619 shutil.rmtree(myemp)
1620 os.makedirs(myemp,0755)
1621 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1622 os.chmod(myemp,mystat[ST_MODE])
1624 def clear_autoresume(self):
1625 """ Clean resume points since they are no longer needed """
1626 if "AUTORESUME" in self.settings:
1627 print "Removing AutoResume Points: ..."
1628 myemp=self.settings["autoresume_path"]
1629 if os.path.isdir(myemp):
1630 if "AUTORESUME" in self.settings:
1631 print "Emptying directory",myemp
1633 stat the dir, delete the dir, recreate the dir and set
1634 the proper perms and ownership
1636 mystat=os.stat(myemp)
1637 if os.uname()[0] == "FreeBSD":
1638 cmd("chflags -R noschg "+myemp,\
1639 "Could not remove immutable flag for file "\
1641 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1642 shutil.rmtree(myemp)
1643 os.makedirs(myemp,0755)
1644 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1645 os.chmod(myemp,mystat[ST_MODE])
1647 def gen_contents_file(self,file):
1648 if os.path.exists(file+".CONTENTS"):
1649 os.remove(file+".CONTENTS")
1650 if "contents" in self.settings:
1651 if os.path.exists(file):
1652 myf=open(file+".CONTENTS","w")
1654 for i in self.settings["contents"].split():
1659 contents=generate_contents(file,contents_function=j,\
1660 verbose="VERBOSE" in self.settings)
1665 def gen_digest_file(self,file):
1666 if os.path.exists(file+".DIGESTS"):
1667 os.remove(file+".DIGESTS")
1668 if "digests" in self.settings:
1669 if os.path.exists(file):
1670 myf=open(file+".DIGESTS","w")
1672 for i in self.settings["digests"].split():
1676 for f in [file, file+'.CONTENTS']:
1677 if os.path.exists(f):
1679 for k in hash_map.keys():
1680 hash=generate_hash(f,hash_function=k,verbose=\
1681 "VERBOSE" in self.settings)
1685 hash=generate_hash(f,hash_function=j,verbose=\
1686 "VERBOSE" in self.settings)
1691 countdown(10,"Purging Caches ...")
1692 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1693 print "clearing autoresume ..."
1694 self.clear_autoresume()
1696 print "clearing chroot ..."
1699 if "PURGETMPONLY" not in self.settings:
1700 print "clearing package cache ..."
1701 self.clear_packages()
1703 print "clearing kerncache ..."
1704 self.clear_kerncache()
1706 # vim: ts=4 sw=4 sta et sts=4 ai