1 import os,string,imp,types,shutil
2 from catalyst_support import *
3 from generic_target import *
7 class generic_stage_target(generic_target):
9 This class does all of the chroot setup, copying of files, etc. It is
10 the driver class for pretty much everything that Catalyst does.
12 def __init__(self,myspec,addlargs):
13 self.required_values.extend(["version_stamp","target","subarch",\
14 "rel_type","profile","snapshot","source_subpath"])
16 self.valid_values.extend(["version_stamp","target","subarch",\
17 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
18 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
19 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
21 self.set_valid_build_kernel_vars(addlargs)
22 generic_target.__init__(self,myspec,addlargs)
25 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
26 work better with vapier's CBUILD stuff. I've removed the "monolithic"
27 machinemap from this file and split up its contents amongst the
28 various arch/foo.py files.
30 When register() is called on each module in the arch/ dir, it now
31 returns a tuple instead of acting on the subarchmap dict that is
32 passed to it. The tuple contains the values that were previously
33 added to subarchmap as well as a new list of CHOSTs that go along
34 with that arch. This allows us to build machinemap on the fly based
35 on the keys in subarchmap and the values of the 2nd list returned
38 Also, after talking with vapier. I have a slightly better idea of what
39 certain variables are used for and what they should be set to. Neither
40 'buildarch' or 'hostarch' are used directly, so their value doesn't
41 really matter. They are just compared to determine if we are
42 cross-compiling. Because of this, they are just set to the name of the
43 module in arch/ that the subarch is part of to make things simpler.
44 The entire build process is still based off of 'subarch' like it was
51 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
52 "/arch/") if x.endswith(".py")]:
54 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
56 This next line loads the plugin as a module and assigns it to
59 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
60 ".py",(".py","r",imp.PY_SOURCE))
62 This next line registers all the subarches supported in the
65 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
66 self.subarchmap.update(tmpsubarchmap)
67 for machine in tmpmachinemap:
68 machinemap[machine] = x
69 for subarch in tmpsubarchmap:
70 machinemap[subarch] = x
74 This message should probably change a bit, since everything in
75 the dir should load just fine. If it doesn't, it's probably a
76 syntax error in the module
78 msg("Can't find/load "+x+".py plugin in "+\
79 self.settings["sharedir"]+"/arch/")
81 if self.settings.has_key("chost"):
82 hostmachine = self.settings["chost"].split("-")[0]
83 if not machinemap.has_key(hostmachine):
84 raise CatalystError, "Unknown host machine type "+hostmachine
85 self.settings["hostarch"]=machinemap[hostmachine]
87 hostmachine = self.settings["subarch"]
88 if machinemap.has_key(hostmachine):
89 hostmachine = machinemap[hostmachine]
90 self.settings["hostarch"]=hostmachine
91 if self.settings.has_key("cbuild"):
92 buildmachine = self.settings["cbuild"].split("-")[0]
94 buildmachine = os.uname()[4]
95 if not machinemap.has_key(buildmachine):
96 raise CatalystError, "Unknown build machine type "+buildmachine
97 self.settings["buildarch"]=machinemap[buildmachine]
98 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
99 self.settings["buildarch"])
101 """ Call arch constructor, pass our settings """
103 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
105 print "Invalid subarch: "+self.settings["subarch"]
106 print "Choose one of the following:",
107 for x in self.subarchmap:
112 print "Using target:",self.settings["target"]
113 """ Print a nice informational message """
114 if self.settings["buildarch"]==self.settings["hostarch"]:
115 print "Building natively for",self.settings["hostarch"]
116 elif self.settings["crosscompile"]:
117 print "Cross-compiling on",self.settings["buildarch"],\
118 "for different machine type",self.settings["hostarch"]
120 print "Building on",self.settings["buildarch"],\
121 "for alternate personality type",self.settings["hostarch"]
123 """ This must be set first as other set_ options depend on this """
124 self.set_spec_prefix()
126 """ Define all of our core variables """
127 self.set_target_profile()
128 self.set_target_subpath()
129 self.set_source_subpath()
132 self.set_snapshot_path()
134 self.set_source_path()
135 self.set_snapcache_path()
136 self.set_chroot_path()
137 self.set_autoresume_path()
139 self.set_stage_path()
140 self.set_target_path()
142 self.set_controller_file()
143 self.set_action_sequence()
145 self.set_cleanables()
146 self.set_iso_volume_id()
147 self.set_build_kernel_vars()
149 self.set_install_mask()
159 self.set_busybox_config()
161 self.set_portage_overlay()
162 self.set_root_overlay()
165 This next line checks to make sure that the specified variables exist
169 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
171 """ If we are using portage_confdir, check that as well. """
172 if self.settings.has_key("portage_confdir"):
173 file_locate(self.settings,["portage_confdir"],expand=0)
175 """ Setup our mount points """
176 if self.settings.has_key("SNAPCACHE"):
177 self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles","/var/tmp/portage"]
178 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
179 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
180 "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
182 self.mounts=["/proc","/dev","/usr/portage/distfiles","/var/tmp/portage"]
183 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
184 "/usr/portage/distfiles":self.settings["distdir"],"/var/tmp/portage":"tmpfs"}
185 if os.uname()[0] == "Linux":
186 self.mounts.append("/dev/pts")
191 Configure any user specified options (either in catalyst.conf or on
194 if self.settings.has_key("PKGCACHE"):
195 self.set_pkgcache_path()
196 print "Location of the package cache is "+\
197 self.settings["pkgcache_path"]
198 self.mounts.append("/usr/portage/packages")
199 self.mountmap["/usr/portage/packages"]=\
200 self.settings["pkgcache_path"]
202 if self.settings.has_key("KERNCACHE"):
203 self.set_kerncache_path()
204 print "Location of the kerncache is "+\
205 self.settings["kerncache_path"]
206 self.mounts.append("/tmp/kerncache")
207 self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
209 if self.settings.has_key("CCACHE"):
210 if os.environ.has_key("CCACHE_DIR"):
211 ccdir=os.environ["CCACHE_DIR"]
212 del os.environ["CCACHE_DIR"]
214 ccdir="/root/.ccache"
215 if not os.path.isdir(ccdir):
216 raise CatalystError,\
217 "Compiler cache support can't be enabled (can't find "+\
219 self.mounts.append("/var/tmp/ccache")
220 self.mountmap["/var/tmp/ccache"]=ccdir
221 """ for the chroot: """
222 self.env["CCACHE_DIR"]="/var/tmp/ccache"
224 if self.settings.has_key("ICECREAM"):
225 self.mounts.append("/var/cache/icecream")
226 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
227 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
229 if self.settings.has_key("port_logdir"):
230 self.mounts.append("/var/log/portage")
231 self.mountmap["/var/log/portage"]=self.settings["port_logdir"]
232 self.env["PORT_LOGDIR"]="/var/log/portage"
233 self.env["PORT_LOGDIR_CLEAN"]='find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
235 def override_cbuild(self):
236 if self.makeconf.has_key("CBUILD"):
237 self.settings["CBUILD"]=self.makeconf["CBUILD"]
239 def override_chost(self):
240 if self.makeconf.has_key("CHOST"):
241 self.settings["CHOST"]=self.makeconf["CHOST"]
243 def override_cflags(self):
244 if self.makeconf.has_key("CFLAGS"):
245 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
247 def override_cxxflags(self):
248 if self.makeconf.has_key("CXXFLAGS"):
249 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
251 def override_ldflags(self):
252 if self.makeconf.has_key("LDFLAGS"):
253 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
255 def set_install_mask(self):
256 if self.settings.has_key("install_mask"):
257 if type(self.settings["install_mask"])!=types.StringType:
258 self.settings["install_mask"]=\
259 string.join(self.settings["install_mask"])
261 def set_spec_prefix(self):
262 self.settings["spec_prefix"]=self.settings["target"]
264 def set_target_profile(self):
265 self.settings["target_profile"]=self.settings["profile"]
267 def set_target_subpath(self):
268 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
269 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
270 self.settings["version_stamp"]
272 def set_source_subpath(self):
273 if type(self.settings["source_subpath"])!=types.StringType:
274 raise CatalystError,\
275 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
277 def set_pkgcache_path(self):
278 if self.settings.has_key("pkgcache_path"):
279 if type(self.settings["pkgcache_path"])!=types.StringType:
280 self.settings["pkgcache_path"]=\
281 normpath(string.join(self.settings["pkgcache_path"]))
283 self.settings["pkgcache_path"]=\
284 normpath(self.settings["storedir"]+"/packages/"+\
285 self.settings["target_subpath"]+"/")
287 def set_kerncache_path(self):
288 if self.settings.has_key("kerncache_path"):
289 if type(self.settings["kerncache_path"])!=types.StringType:
290 self.settings["kerncache_path"]=\
291 normpath(string.join(self.settings["kerncache_path"]))
293 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
294 "/kerncache/"+self.settings["target_subpath"]+"/")
296 def set_target_path(self):
297 self.settings["target_path"]=normpath(self.settings["storedir"]+\
298 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
299 if self.settings.has_key("AUTORESUME")\
300 and os.path.exists(self.settings["autoresume_path"]+\
301 "setup_target_path"):
303 "Resume point detected, skipping target path setup operation..."
305 """ First clean up any existing target stuff """
306 # XXX WTF are we removing the old tarball before we start building the
307 # XXX new one? If the build fails, you don't want to be left with
309 # if os.path.isfile(self.settings["target_path"]):
310 # cmd("rm -f "+self.settings["target_path"],\
311 # "Could not remove existing file: "\
312 # +self.settings["target_path"],env=self.env)
313 touch(self.settings["autoresume_path"]+"setup_target_path")
315 if not os.path.exists(self.settings["storedir"]+"/builds/"):
316 os.makedirs(self.settings["storedir"]+"/builds/")
318 def set_fsscript(self):
319 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
320 self.settings["fsscript"]=\
321 self.settings[self.settings["spec_prefix"]+"/fsscript"]
322 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
325 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
326 self.settings["rcadd"]=\
327 self.settings[self.settings["spec_prefix"]+"/rcadd"]
328 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
331 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
332 self.settings["rcdel"]=\
333 self.settings[self.settings["spec_prefix"]+"/rcdel"]
334 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
337 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
338 self.settings["cdtar"]=\
339 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
340 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
343 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
344 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
345 self.settings["iso"]=\
346 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
348 # This automatically prepends the build dir to the ISO output path
349 # if it doesn't start with a /
350 self.settings["iso"] = normpath(self.settings["storedir"] + \
351 "/builds/" + self.settings["rel_type"] + "/" + \
352 self.settings[self.settings["spec_prefix"]+"/iso"])
353 del self.settings[self.settings["spec_prefix"]+"/iso"]
355 def set_fstype(self):
356 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
357 self.settings["fstype"]=\
358 self.settings[self.settings["spec_prefix"]+"/fstype"]
359 del self.settings[self.settings["spec_prefix"]+"/fstype"]
361 if not self.settings.has_key("fstype"):
362 self.settings["fstype"]="normal"
363 for x in self.valid_values:
364 if x == self.settings["spec_prefix"]+"/fstype":
365 print "\n"+self.settings["spec_prefix"]+\
366 "/fstype is being set to the default of \"normal\"\n"
369 if self.settings.has_key("fstype"):
370 self.valid_values.append("fsops")
371 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
372 self.settings["fsops"]=\
373 self.settings[self.settings["spec_prefix"]+"/fsops"]
374 del self.settings[self.settings["spec_prefix"]+"/fsops"]
376 def set_source_path(self):
377 if self.settings.has_key("SEEDCACHE")\
378 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
379 self.settings["source_subpath"]+"/")):
380 self.settings["source_path"]=normpath(self.settings["storedir"]+\
381 "/tmp/"+self.settings["source_subpath"]+"/")
383 self.settings["source_path"]=normpath(self.settings["storedir"]+\
384 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
385 if os.path.isfile(self.settings["source_path"]):
386 # XXX: Is this even necessary if the previous check passes?
387 if os.path.exists(self.settings["source_path"]):
388 self.settings["source_path_hash"]=\
389 generate_hash(self.settings["source_path"],\
390 hash_function=self.settings["hash_function"],\
392 print "Source path set to "+self.settings["source_path"]
393 if os.path.isdir(self.settings["source_path"]):
394 print "\tIf this is not desired, remove this directory or turn off"
395 print "\tseedcache in the options of catalyst.conf the source path"
396 print "\twill then be "+\
397 normpath(self.settings["storedir"]+"/builds/"+\
398 self.settings["source_subpath"]+".tar.bz2\n")
400 def set_dest_path(self):
401 if self.settings.has_key("root_path"):
402 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
403 self.settings["root_path"])
405 self.settings["destpath"]=normpath(self.settings["chroot_path"])
407 def set_cleanables(self):
408 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
409 "/root/*","/usr/portage"]
411 def set_snapshot_path(self):
412 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
413 "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
415 if os.path.exists(self.settings["snapshot_path"]):
416 self.settings["snapshot_path_hash"]=\
417 generate_hash(self.settings["snapshot_path"],\
418 hash_function=self.settings["hash_function"],verbose=False)
420 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
421 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
423 if os.path.exists(self.settings["snapshot_path"]):
424 self.settings["snapshot_path_hash"]=\
425 generate_hash(self.settings["snapshot_path"],\
426 hash_function=self.settings["hash_function"],verbose=False)
428 def set_snapcache_path(self):
429 if self.settings.has_key("SNAPCACHE"):
430 self.settings["snapshot_cache_path"]=\
431 normpath(self.settings["snapshot_cache"]+"/"+\
432 self.settings["snapshot"]+"/")
433 self.snapcache_lock=\
434 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
435 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
437 def set_chroot_path(self):
439 NOTE: the trailing slash is very important!
440 Things *will* break without it!
442 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
443 "/tmp/"+self.settings["target_subpath"]+"/")
444 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
446 def set_autoresume_path(self):
447 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
448 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
449 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
450 self.settings["version_stamp"]+"/")
451 if self.settings.has_key("AUTORESUME"):
452 print "The autoresume path is " + self.settings["autoresume_path"]
453 if not os.path.exists(self.settings["autoresume_path"]):
454 os.makedirs(self.settings["autoresume_path"],0755)
456 def set_controller_file(self):
457 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
458 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
461 def set_iso_volume_id(self):
462 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
463 self.settings["iso_volume_id"]=\
464 self.settings[self.settings["spec_prefix"]+"/volid"]
465 if len(self.settings["iso_volume_id"])>32:
466 raise CatalystError,\
467 "ISO volume ID must not exceed 32 characters."
469 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
471 def set_action_sequence(self):
472 """ Default action sequence for run method """
473 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
474 "setup_confdir","portage_overlay",\
475 "base_dirs","bind","chroot_setup","setup_environment",\
476 "run_local","preclean","unbind","clean"]
477 # if self.settings.has_key("TARBALL") or \
478 # not self.settings.has_key("FETCH"):
479 if not self.settings.has_key("FETCH"):
480 self.settings["action_sequence"].append("capture")
481 self.settings["action_sequence"].append("clear_autoresume")
484 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
485 self.settings["use"]=\
486 self.settings[self.settings["spec_prefix"]+"/use"]
487 del self.settings[self.settings["spec_prefix"]+"/use"]
488 if not self.settings.has_key("use"):
489 self.settings["use"]=""
490 if type(self.settings["use"])==types.StringType:
491 self.settings["use"]=self.settings["use"].split()
493 # Force bindist for all targets
494 self.settings["use"].append("bindist")
496 def set_stage_path(self):
497 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
499 def set_mounts(self):
502 def set_packages(self):
506 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
507 if type(self.settings[self.settings["spec_prefix"]+\
508 "/rm"])==types.StringType:
509 self.settings[self.settings["spec_prefix"]+"/rm"]=\
510 self.settings[self.settings["spec_prefix"]+"/rm"].split()
512 def set_linuxrc(self):
513 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
514 if type(self.settings[self.settings["spec_prefix"]+\
515 "/linuxrc"])==types.StringType:
516 self.settings["linuxrc"]=\
517 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
518 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
520 def set_busybox_config(self):
521 if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
522 if type(self.settings[self.settings["spec_prefix"]+\
523 "/busybox_config"])==types.StringType:
524 self.settings["busybox_config"]=\
525 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
526 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
528 def set_portage_overlay(self):
529 if self.settings.has_key("portage_overlay"):
530 if type(self.settings["portage_overlay"])==types.StringType:
531 self.settings["portage_overlay"]=\
532 self.settings["portage_overlay"].split()
533 print "portage_overlay directories are set to: \""+\
534 string.join(self.settings["portage_overlay"])+"\""
536 def set_overlay(self):
537 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
538 if type(self.settings[self.settings["spec_prefix"]+\
539 "/overlay"])==types.StringType:
540 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
541 self.settings[self.settings["spec_prefix"]+\
544 def set_root_overlay(self):
545 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
546 if type(self.settings[self.settings["spec_prefix"]+\
547 "/root_overlay"])==types.StringType:
548 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
549 self.settings[self.settings["spec_prefix"]+\
550 "/root_overlay"].split()
552 def set_root_path(self):
553 """ ROOT= variable for emerges """
554 self.settings["root_path"]="/"
556 def set_valid_build_kernel_vars(self,addlargs):
557 if addlargs.has_key("boot/kernel"):
558 if type(addlargs["boot/kernel"])==types.StringType:
559 loopy=[addlargs["boot/kernel"]]
561 loopy=addlargs["boot/kernel"]
564 self.valid_values.append("boot/kernel/"+x+"/aliases")
565 self.valid_values.append("boot/kernel/"+x+"/config")
566 self.valid_values.append("boot/kernel/"+x+"/console")
567 self.valid_values.append("boot/kernel/"+x+"/extraversion")
568 self.valid_values.append("boot/kernel/"+x+"/gk_action")
569 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
570 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
571 self.valid_values.append("boot/kernel/"+x+"/machine_type")
572 self.valid_values.append("boot/kernel/"+x+"/sources")
573 self.valid_values.append("boot/kernel/"+x+"/softlevel")
574 self.valid_values.append("boot/kernel/"+x+"/use")
575 self.valid_values.append("boot/kernel/"+x+"/packages")
576 if addlargs.has_key("boot/kernel/"+x+"/packages"):
577 if type(addlargs["boot/kernel/"+x+\
578 "/packages"])==types.StringType:
579 addlargs["boot/kernel/"+x+"/packages"]=\
580 [addlargs["boot/kernel/"+x+"/packages"]]
582 def set_build_kernel_vars(self):
583 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
584 self.settings["gk_mainargs"]=\
585 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
586 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
588 def kill_chroot_pids(self):
589 print "Checking for processes running in chroot and killing them."
592 Force environment variables to be exported so script can see them
594 self.setup_environment()
596 if os.path.exists(self.settings["sharedir"]+\
597 "/targets/support/kill-chroot-pids.sh"):
598 cmd("/bin/bash "+self.settings["sharedir"]+\
599 "/targets/support/kill-chroot-pids.sh",\
600 "kill-chroot-pids script failed.",env=self.env)
602 def mount_safety_check(self):
603 mypath=self.settings["chroot_path"]
606 Check and verify that none of our paths in mypath are mounted. We don't
607 want to clean up with things still mounted, and this allows us to check.
608 Returns 1 on ok, 0 on "something is still mounted" case.
611 if not os.path.exists(mypath):
614 for x in self.mounts:
615 if not os.path.exists(mypath+x):
618 if ismount(mypath+x):
619 """ Something is still mounted "" """
621 print x+" is still mounted; performing auto-bind-umount...",
622 """ Try to umount stuff ourselves """
624 if ismount(mypath+x):
625 raise CatalystError, "Auto-unbind failed for "+x
627 print "Auto-unbind successful..."
628 except CatalystError:
629 raise CatalystError, "Unable to auto-unbind "+x
634 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
637 if self.settings.has_key("SEEDCACHE"):
638 if os.path.isdir(self.settings["source_path"]):
639 """ SEEDCACHE Is a directory, use rsync """
640 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
641 " "+self.settings["chroot_path"]
642 display_msg="\nStarting rsync from "+\
643 self.settings["source_path"]+"\nto "+\
644 self.settings["chroot_path"]+\
645 " (This may take some time) ...\n"
646 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
647 self.settings["chroot_path"]+" failed."
649 """ SEEDCACHE is a not a directory, try untar'ing """
650 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
651 display_msg="\nStarting tar extract from "+\
652 self.settings["source_path"]+"\nto "+\
653 self.settings["chroot_path"]+\
654 " (This may take some time) ...\n"
655 if "bz2" == self.settings["chroot_path"][-3:]:
656 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
657 self.settings["chroot_path"]
659 unpack_cmd="tar xpf "+self.settings["source_path"]+" -C "+\
660 self.settings["chroot_path"]
661 error_msg="Tarball extraction of "+\
662 self.settings["source_path"]+" to "+\
663 self.settings["chroot_path"]+" failed."
665 """ No SEEDCACHE, use tar """
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 xpf "+self.settings["source_path"]+" -C "+\
675 self.settings["chroot_path"]
676 error_msg="Tarball extraction of "+self.settings["source_path"]+\
677 " to "+self.settings["chroot_path"]+" failed."
679 if self.settings.has_key("AUTORESUME"):
680 if os.path.isdir(self.settings["source_path"]) \
681 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
682 """ Autoresume is valid, SEEDCACHE is valid """
684 invalid_snapshot=False
686 elif os.path.isfile(self.settings["source_path"]) \
687 and self.settings["source_path_hash"]==clst_unpack_hash:
688 """ Autoresume is valid, tarball is valid """
690 invalid_snapshot=True
692 elif os.path.isdir(self.settings["source_path"]) \
693 and not os.path.exists(self.settings["autoresume_path"]+\
695 """ Autoresume is invalid, SEEDCACHE """
697 invalid_snapshot=False
699 elif os.path.isfile(self.settings["source_path"]) \
700 and self.settings["source_path_hash"]!=clst_unpack_hash:
701 """ Autoresume is invalid, tarball """
703 invalid_snapshot=True
705 """ No autoresume, SEEDCACHE """
706 if self.settings.has_key("SEEDCACHE"):
707 """ SEEDCACHE so let's run rsync and let it clean up """
708 if os.path.isdir(self.settings["source_path"]):
710 invalid_snapshot=False
711 elif os.path.isfile(self.settings["source_path"]):
712 """ Tarball so unpack and remove anything already there """
714 invalid_snapshot=True
715 """ No autoresume, no SEEDCACHE """
717 """ Tarball so unpack and remove anything already there """
718 if os.path.isfile(self.settings["source_path"]):
720 invalid_snapshot=True
721 elif os.path.isdir(self.settings["source_path"]):
722 """ We should never reach this, so something is very wrong """
723 raise CatalystError,\
724 "source path is a dir but seedcache is not enabled"
727 self.mount_safety_check()
730 if self.settings.has_key("AUTORESUME"):
731 print "No Valid Resume point detected, cleaning up..."
733 self.clear_autoresume()
736 if not os.path.exists(self.settings["chroot_path"]):
737 os.makedirs(self.settings["chroot_path"])
739 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
740 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
742 if self.settings.has_key("PKGCACHE"):
743 if not os.path.exists(self.settings["pkgcache_path"]):
744 os.makedirs(self.settings["pkgcache_path"],0755)
746 if self.settings.has_key("KERNCACHE"):
747 if not os.path.exists(self.settings["kerncache_path"]):
748 os.makedirs(self.settings["kerncache_path"],0755)
751 cmd(unpack_cmd,error_msg,env=self.env)
753 if self.settings.has_key("source_path_hash"):
754 myf=open(self.settings["autoresume_path"]+"unpack","w")
755 myf.write(self.settings["source_path_hash"])
758 touch(self.settings["autoresume_path"]+"unpack")
760 print "Resume point detected, skipping unpack operation..."
762 def unpack_snapshot(self):
764 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
767 if self.settings.has_key("SNAPCACHE"):
768 snapshot_cache_hash=\
769 read_from_clst(self.settings["snapshot_cache_path"]+\
771 destdir=self.settings["snapshot_cache_path"]
772 if "bz2" == self.settings["chroot_path"][-3:]:
773 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
775 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
776 unpack_errmsg="Error unpacking snapshot"
777 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
778 self.settings["snapshot_cache_path"]+\
779 " (This can take a long time)..."
780 cleanup_errmsg="Error removing existing snapshot cache directory."
781 self.snapshot_lock_object=self.snapcache_lock
783 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
784 print "Valid snapshot cache, skipping unpack of portage tree..."
787 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
788 cleanup_errmsg="Error removing existing snapshot directory."
790 "Cleaning up existing portage tree (This can take a long time)..."
791 if "bz2" == self.settings["chroot_path"][-3:]:
792 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
793 self.settings["chroot_path"]+"/usr"
795 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
796 self.settings["chroot_path"]+"/usr"
797 unpack_errmsg="Error unpacking snapshot"
799 if self.settings.has_key("AUTORESUME") \
800 and os.path.exists(self.settings["chroot_path"]+\
802 and os.path.exists(self.settings["autoresume_path"]\
804 and self.settings["snapshot_path_hash"] == snapshot_hash:
806 "Valid Resume point detected, skipping unpack of portage tree..."
810 if self.settings.has_key("SNAPCACHE"):
811 self.snapshot_lock_object.write_lock()
812 if os.path.exists(destdir):
814 cleanup_cmd="rm -rf "+destdir
815 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
816 if not os.path.exists(destdir):
817 os.makedirs(destdir,0755)
819 print "Unpacking portage tree (This can take a long time) ..."
820 cmd(unpack_cmd,unpack_errmsg,env=self.env)
822 if self.settings.has_key("SNAPCACHE"):
823 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
824 myf.write(self.settings["snapshot_path_hash"])
827 print "Setting snapshot autoresume point"
828 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
829 myf.write(self.settings["snapshot_path_hash"])
832 if self.settings.has_key("SNAPCACHE"):
833 self.snapshot_lock_object.unlock()
835 def config_profile_link(self):
836 if self.settings.has_key("AUTORESUME") \
837 and os.path.exists(self.settings["autoresume_path"]+\
838 "config_profile_link"):
840 "Resume point detected, skipping config_profile_link operation..."
842 # TODO: zmedico and I discussed making this a directory and pushing
843 # in a parent file, as well as other user-specified configuration.
844 print "Configuring profile link..."
845 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
846 "Error zapping profile link",env=self.env)
847 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
848 cmd("ln -sf ../../usr/portage/profiles/"+\
849 self.settings["target_profile"]+" "+\
850 self.settings["chroot_path"]+"/etc/portage/make.profile",\
851 "Error creating profile link",env=self.env)
852 touch(self.settings["autoresume_path"]+"config_profile_link")
854 def setup_confdir(self):
855 if self.settings.has_key("AUTORESUME") \
856 and os.path.exists(self.settings["autoresume_path"]+\
858 print "Resume point detected, skipping setup_confdir operation..."
860 if self.settings.has_key("portage_confdir"):
861 print "Configuring /etc/portage..."
862 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
863 self.settings["chroot_path"]+"/etc/portage/",\
864 "Error copying /etc/portage",env=self.env)
865 touch(self.settings["autoresume_path"]+"setup_confdir")
867 def portage_overlay(self):
868 """ We copy the contents of our overlays to /usr/local/portage """
869 if self.settings.has_key("portage_overlay"):
870 for x in self.settings["portage_overlay"]:
871 if os.path.exists(x):
872 print "Copying overlay dir " +x
873 cmd("mkdir -p "+self.settings["chroot_path"]+\
874 "/usr/local/portage",\
875 "Could not make portage_overlay dir",env=self.env)
876 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
877 "/usr/local/portage",\
878 "Could not copy portage_overlay",env=self.env)
880 def root_overlay(self):
881 """ Copy over the root_overlay """
882 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
883 for x in self.settings[self.settings["spec_prefix"]+\
885 if os.path.exists(x):
886 print "Copying root_overlay: "+x
887 cmd("rsync -a "+x+"/ "+\
888 self.settings["chroot_path"],\
889 self.settings["spec_prefix"]+"/root_overlay: "+x+\
890 " copy failed.",env=self.env)
896 for x in self.mounts:
897 if not os.path.exists(self.settings["chroot_path"]+x):
898 os.makedirs(self.settings["chroot_path"]+x,0755)
900 if not os.path.exists(self.mountmap[x]):
901 if not self.mountmap[x] == "tmpfs":
902 os.makedirs(self.mountmap[x],0755)
905 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
906 self.snapshot_lock_object.read_lock()
907 if os.uname()[0] == "FreeBSD":
909 retval=os.system("mount -t devfs none "+\
910 self.settings["chroot_path"]+x)
912 retval=os.system("mount_nullfs "+src+" "+\
913 self.settings["chroot_path"]+x)
916 if self.settings.has_key("var_tmpfs_portage"):
917 retval=os.system("mount -t tmpfs -o size="+\
918 self.settings["var_tmpfs_portage"]+"G "+src+" "+\
919 self.settings["chroot_path"]+x)
921 retval=os.system("mount --bind "+src+" "+\
922 self.settings["chroot_path"]+x)
925 raise CatalystError,"Couldn't bind mount "+src
929 mypath=self.settings["chroot_path"]
930 myrevmounts=self.mounts[:]
931 myrevmounts.reverse()
932 """ Unmount in reverse order for nested bind-mounts """
933 for x in myrevmounts:
934 if not os.path.exists(mypath+x):
937 if not ismount(mypath+x):
940 retval=os.system("umount "+\
941 os.path.join(mypath,x.lstrip(os.path.sep)))
944 warn("First attempt to unmount: "+mypath+x+" failed.")
945 warn("Killing any pids still running in the chroot")
947 self.kill_chroot_pids()
949 retval2=os.system("umount "+mypath+x)
952 warn("Couldn't umount bind mount: "+mypath+x)
954 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
957 It's possible the snapshot lock object isn't created yet.
958 This is because mount safety check calls unbind before the
959 target is fully initialized
961 self.snapshot_lock_object.unlock()
966 if any bind mounts really failed, then we need to raise
967 this to potentially prevent an upcoming bash stage cleanup script
968 from wiping our bind mounts.
970 raise CatalystError,\
971 "Couldn't umount one or more bind-mounts; aborting for safety."
973 def chroot_setup(self):
974 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
975 "/etc/portage/make.conf")
976 self.override_cbuild()
977 self.override_chost()
978 self.override_cflags()
979 self.override_cxxflags()
980 self.override_ldflags()
981 if self.settings.has_key("AUTORESUME") \
982 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
983 print "Resume point detected, skipping chroot_setup operation..."
985 print "Setting up chroot..."
987 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
989 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
990 "Could not copy resolv.conf into place.",env=self.env)
992 """ Copy over the envscript, if applicable """
993 if self.settings.has_key("ENVSCRIPT"):
994 if not os.path.exists(self.settings["ENVSCRIPT"]):
995 raise CatalystError,\
996 "Can't find envscript "+self.settings["ENVSCRIPT"]
998 print "\nWarning!!!!"
999 print "\tOverriding certain env variables may cause catastrophic failure."
1000 print "\tIf your build fails look here first as the possible problem."
1001 print "\tCatalyst assumes you know what you are doing when setting"
1002 print "\t\tthese variables."
1003 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1004 print "\tYou have been warned\n"
1006 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1007 self.settings["chroot_path"]+"/tmp/envscript",\
1008 "Could not copy envscript into place.",env=self.env)
1011 Copy over /etc/hosts from the host in case there are any
1012 specialties in there
1014 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1015 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1016 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1017 "Could not backup /etc/hosts",env=self.env)
1018 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1019 "Could not copy /etc/hosts",env=self.env)
1021 """ Modify and write out make.conf (for the chroot) """
1022 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1023 "Could not remove "+self.settings["chroot_path"]+\
1024 "/etc/portage/make.conf",env=self.env)
1025 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1026 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1027 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1028 if self.settings.has_key("CFLAGS"):
1029 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1030 if self.settings.has_key("CXXFLAGS"):
1031 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1032 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1034 myf.write('CXXFLAGS="${CFLAGS}"\n')
1036 myf.write('CXXFLAGS="${CFLAGS}"\n')
1038 if self.settings.has_key("LDFLAGS"):
1039 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1040 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1041 if self.settings.has_key("CBUILD"):
1042 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")
1043 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1045 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")
1046 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1048 """ Figure out what our USE vars are for building """
1050 if self.settings.has_key("HOSTUSE"):
1051 myusevars.extend(self.settings["HOSTUSE"])
1053 if self.settings.has_key("use"):
1054 myusevars.extend(self.settings["use"])
1057 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1058 myusevars = sorted(set(myusevars))
1059 myf.write('USE="'+string.join(myusevars)+'"\n')
1060 if '-*' in myusevars:
1061 print "\nWarning!!! "
1062 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1063 "/use will cause portage to ignore"
1064 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1066 """ Setup the portage overlay """
1067 if self.settings.has_key("portage_overlay"):
1068 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1071 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1072 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1073 "Could not backup /etc/portage/make.conf",env=self.env)
1074 touch(self.settings["autoresume_path"]+"chroot_setup")
1077 if self.settings.has_key("AUTORESUME") \
1078 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1079 print "Resume point detected, skipping fsscript operation..."
1081 if self.settings.has_key("fsscript"):
1082 if os.path.exists(self.settings["controller_file"]):
1083 cmd("/bin/bash "+self.settings["controller_file"]+\
1084 " fsscript","fsscript script failed.",env=self.env)
1085 touch(self.settings["autoresume_path"]+"fsscript")
1088 if self.settings.has_key("AUTORESUME") \
1089 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1090 print "Resume point detected, skipping rcupdate operation..."
1092 if os.path.exists(self.settings["controller_file"]):
1093 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1094 "rc-update script failed.",env=self.env)
1095 touch(self.settings["autoresume_path"]+"rcupdate")
1098 if self.settings.has_key("AUTORESUME") \
1099 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1100 print "Resume point detected, skipping clean operation..."
1102 for x in self.settings["cleanables"]:
1103 print "Cleaning chroot: "+x+"... "
1104 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1107 """ Put /etc/hosts back into place """
1108 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1109 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1110 self.settings["chroot_path"]+"/etc/hosts",\
1111 "Could not replace /etc/hosts",env=self.env)
1113 """ Remove our overlay """
1114 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1115 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1116 "Could not remove /usr/local/portage",env=self.env)
1117 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1118 "/etc/portage/make.conf",\
1119 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1121 """ Clean up old and obsoleted files in /etc """
1122 if os.path.exists(self.settings["stage_path"]+"/etc"):
1123 cmd("find "+self.settings["stage_path"]+\
1124 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1125 "Could not remove stray files in /etc",env=self.env)
1127 if os.path.exists(self.settings["controller_file"]):
1128 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1129 "clean script failed.",env=self.env)
1130 touch(self.settings["autoresume_path"]+"clean")
1133 if self.settings.has_key("AUTORESUME") \
1134 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1135 print "Resume point detected, skipping empty operation..."
1137 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1138 if type(self.settings[self.settings["spec_prefix"]+\
1139 "/empty"])==types.StringType:
1140 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1141 self.settings[self.settings["spec_prefix"]+\
1143 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1144 myemp=self.settings["destpath"]+x
1145 if not os.path.isdir(myemp):
1146 print x,"not a directory or does not exist, skipping 'empty' operation."
1148 print "Emptying directory",x
1150 stat the dir, delete the dir, recreate the dir and set
1151 the proper perms and ownership
1153 mystat=os.stat(myemp)
1154 shutil.rmtree(myemp)
1155 os.makedirs(myemp,0755)
1156 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1157 os.chmod(myemp,mystat[ST_MODE])
1158 touch(self.settings["autoresume_path"]+"empty")
1161 if self.settings.has_key("AUTORESUME") \
1162 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1163 print "Resume point detected, skipping remove operation..."
1165 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1166 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1168 We're going to shell out for all these cleaning
1169 operations, so we get easy glob handling.
1171 print "livecd: removing "+x
1172 os.system("rm -rf "+self.settings["chroot_path"]+x)
1174 if os.path.exists(self.settings["controller_file"]):
1175 cmd("/bin/bash "+self.settings["controller_file"]+\
1176 " clean","Clean failed.",env=self.env)
1177 touch(self.settings["autoresume_path"]+"remove")
1183 if self.settings.has_key("AUTORESUME") \
1184 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1185 print "Resume point detected, skipping preclean operation..."
1188 if os.path.exists(self.settings["controller_file"]):
1189 cmd("/bin/bash "+self.settings["controller_file"]+\
1190 " preclean","preclean script failed.",env=self.env)
1191 touch(self.settings["autoresume_path"]+"preclean")
1195 raise CatalystError, "Build failed, could not execute preclean"
1198 if self.settings.has_key("AUTORESUME") \
1199 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1200 print "Resume point detected, skipping capture operation..."
1202 """ Capture target in a tarball """
1203 mypath=self.settings["target_path"].split("/")
1204 """ Remove filename from path """
1205 mypath=string.join(mypath[:-1],"/")
1207 """ Now make sure path exists """
1208 if not os.path.exists(mypath):
1211 print "Creating stage tarball..."
1213 cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1214 self.settings["stage_path"]+" .",\
1215 "Couldn't create stage tarball",env=self.env)
1217 self.gen_contents_file(self.settings["target_path"])
1218 self.gen_digest_file(self.settings["target_path"])
1220 touch(self.settings["autoresume_path"]+"capture")
1222 def run_local(self):
1223 if self.settings.has_key("AUTORESUME") \
1224 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1225 print "Resume point detected, skipping run_local operation..."
1228 if os.path.exists(self.settings["controller_file"]):
1229 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1230 "run script failed.",env=self.env)
1231 touch(self.settings["autoresume_path"]+"run_local")
1233 except CatalystError:
1235 raise CatalystError,"Stage build aborting due to error."
1237 def setup_environment(self):
1239 Modify the current environment. This is an ugly hack that should be
1240 fixed. We need this to use the os.system() call since we can't
1241 specify our own environ
1243 for x in self.settings.keys():
1244 """ Sanitize var names by doing "s|/-.|_|g" """
1245 varname="clst_"+string.replace(x,"/","_")
1246 varname=string.replace(varname,"-","_")
1247 varname=string.replace(varname,".","_")
1248 if type(self.settings[x])==types.StringType:
1249 """ Prefix to prevent namespace clashes """
1250 #os.environ[varname]=self.settings[x]
1251 self.env[varname]=self.settings[x]
1252 elif type(self.settings[x])==types.ListType:
1253 #os.environ[varname]=string.join(self.settings[x])
1254 self.env[varname]=string.join(self.settings[x])
1255 elif type(self.settings[x])==types.BooleanType:
1256 if self.settings[x]:
1257 self.env[varname]="true"
1259 self.env[varname]="false"
1260 if self.settings.has_key("makeopts"):
1261 self.env["MAKEOPTS"]=self.settings["makeopts"]
1264 self.chroot_lock.write_lock()
1266 """ Kill any pids in the chroot "" """
1267 self.kill_chroot_pids()
1269 """ Check for mounts right away and abort if we cannot unmount them """
1270 self.mount_safety_check()
1272 if self.settings.has_key("CLEAR_AUTORESUME"):
1273 self.clear_autoresume()
1275 if self.settings.has_key("PURGETMPONLY"):
1279 if self.settings.has_key("PURGEONLY"):
1283 if self.settings.has_key("PURGE"):
1286 for x in self.settings["action_sequence"]:
1287 print "--- Running action sequence: "+x
1290 apply(getattr(self,x))
1292 self.mount_safety_check()
1295 self.chroot_lock.unlock()
1298 if self.settings.has_key("AUTORESUME") \
1299 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1300 print "Resume point detected, skipping unmerge operation..."
1302 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1303 if type(self.settings[self.settings["spec_prefix"]+\
1304 "/unmerge"])==types.StringType:
1305 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1306 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1308 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1310 for x in range(0,len(myunmerge)):
1312 Surround args with quotes for passing to bash, allows
1313 things like "<" to remain intact
1315 myunmerge[x]="'"+myunmerge[x]+"'"
1316 myunmerge=string.join(myunmerge)
1318 """ Before cleaning, unmerge stuff """
1320 cmd("/bin/bash "+self.settings["controller_file"]+\
1321 " unmerge "+ myunmerge,"Unmerge script failed.",\
1323 print "unmerge shell script"
1324 except CatalystError:
1327 touch(self.settings["autoresume_path"]+"unmerge")
1329 def target_setup(self):
1330 if self.settings.has_key("AUTORESUME") \
1331 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1332 print "Resume point detected, skipping target_setup operation..."
1334 print "Setting up filesystems per filesystem type"
1335 cmd("/bin/bash "+self.settings["controller_file"]+\
1336 " target_image_setup "+ self.settings["target_path"],\
1337 "target_image_setup script failed.",env=self.env)
1338 touch(self.settings["autoresume_path"]+"target_setup")
1340 def setup_overlay(self):
1341 if self.settings.has_key("AUTORESUME") \
1342 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1343 print "Resume point detected, skipping setup_overlay operation..."
1345 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1346 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1347 if os.path.exists(x):
1348 cmd("rsync -a "+x+"/ "+\
1349 self.settings["target_path"],\
1350 self.settings["spec_prefix"]+"overlay: "+x+\
1351 " copy failed.",env=self.env)
1352 touch(self.settings["autoresume_path"]+"setup_overlay")
1354 def create_iso(self):
1355 if self.settings.has_key("AUTORESUME") \
1356 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1357 print "Resume point detected, skipping create_iso operation..."
1359 """ Create the ISO """
1360 if self.settings.has_key("iso"):
1361 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1362 self.settings["iso"],"ISO creation script failed.",\
1364 self.gen_contents_file(self.settings["iso"])
1365 self.gen_digest_file(self.settings["iso"])
1366 touch(self.settings["autoresume_path"]+"create_iso")
1368 print "WARNING: livecd/iso was not defined."
1369 print "An ISO Image will not be created."
1371 def build_packages(self):
1372 if self.settings.has_key("AUTORESUME") \
1373 and os.path.exists(self.settings["autoresume_path"]+\
1375 print "Resume point detected, skipping build_packages operation..."
1377 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1378 if self.settings.has_key("AUTORESUME") \
1379 and os.path.exists(self.settings["autoresume_path"]+\
1381 print "Resume point detected, skipping build_packages operation..."
1384 list_bashify(self.settings[self.settings["spec_prefix"]\
1387 cmd("/bin/bash "+self.settings["controller_file"]+\
1388 " build_packages "+mypack,\
1389 "Error in attempt to build packages",env=self.env)
1390 touch(self.settings["autoresume_path"]+"build_packages")
1391 except CatalystError:
1393 raise CatalystError,self.settings["spec_prefix"]+\
1394 "build aborting due to error."
1396 def build_kernel(self):
1397 if self.settings.has_key("AUTORESUME") \
1398 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1399 print "Resume point detected, skipping build_kernel operation..."
1401 if self.settings.has_key("boot/kernel"):
1403 mynames=self.settings["boot/kernel"]
1404 if type(mynames)==types.StringType:
1407 Execute the script that sets up the kernel build environment
1409 cmd("/bin/bash "+self.settings["controller_file"]+\
1410 " pre-kmerge ","Runscript pre-kmerge failed",\
1413 for kname in mynames:
1414 if self.settings.has_key("AUTORESUME") \
1415 and os.path.exists(self.settings["autoresume_path"]\
1416 +"build_kernel_"+kname):
1417 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1418 else: # TODO: make this not require a kernel config
1420 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1422 raise CatalystError,\
1423 "Can't find kernel config: "+\
1424 self.settings["boot/kernel/"+kname+\
1428 raise CatalystError,\
1429 "Required value boot/kernel/config not specified"
1432 cmd("cp "+self.settings["boot/kernel/"+kname+\
1434 self.settings["chroot_path"]+"/var/tmp/"+\
1436 "Couldn't copy kernel config: "+\
1437 self.settings["boot/kernel/"+kname+\
1438 "/config"],env=self.env)
1440 except CatalystError:
1444 If we need to pass special options to the bootloader
1445 for this kernel put them into the environment
1447 if self.settings.has_key("boot/kernel/"+kname+\
1449 myopts=self.settings["boot/kernel/"+kname+\
1452 if type(myopts) != types.StringType:
1453 myopts = string.join(myopts)
1454 self.env[kname+"_kernelopts"]=myopts
1457 self.env[kname+"_kernelopts"]=""
1459 if not self.settings.has_key("boot/kernel/"+kname+\
1461 self.settings["boot/kernel/"+kname+\
1464 self.env["clst_kextraversion"]=\
1465 self.settings["boot/kernel/"+kname+\
1468 if self.settings.has_key("boot/kernel/"+kname+\
1469 "/initramfs_overlay"):
1470 if os.path.exists(self.settings["boot/kernel/"+\
1471 kname+"/initramfs_overlay"]):
1472 print "Copying initramfs_overlay dir "+\
1473 self.settings["boot/kernel/"+kname+\
1474 "/initramfs_overlay"]
1477 self.settings["chroot_path"]+\
1478 "/tmp/initramfs_overlay/"+\
1479 self.settings["boot/kernel/"+kname+\
1480 "/initramfs_overlay"],env=self.env)
1482 cmd("cp -R "+self.settings["boot/kernel/"+\
1483 kname+"/initramfs_overlay"]+"/* "+\
1484 self.settings["chroot_path"]+\
1485 "/tmp/initramfs_overlay/"+\
1486 self.settings["boot/kernel/"+kname+\
1487 "/initramfs_overlay"],env=self.env)
1489 """ Execute the script that builds the kernel """
1490 cmd("/bin/bash "+self.settings["controller_file"]+\
1492 "Runscript kernel build failed",env=self.env)
1494 if self.settings.has_key("boot/kernel/"+kname+\
1495 "/initramfs_overlay"):
1496 if os.path.exists(self.settings["chroot_path"]+\
1497 "/tmp/initramfs_overlay/"):
1498 print "Cleaning up temporary overlay dir"
1499 cmd("rm -R "+self.settings["chroot_path"]+\
1500 "/tmp/initramfs_overlay/",env=self.env)
1502 touch(self.settings["autoresume_path"]+\
1503 "build_kernel_"+kname)
1506 Execute the script that cleans up the kernel build
1509 cmd("/bin/bash "+self.settings["controller_file"]+\
1511 "Runscript post-kmerge failed",env=self.env)
1513 touch(self.settings["autoresume_path"]+"build_kernel")
1515 except CatalystError:
1517 raise CatalystError,\
1518 "build aborting due to kernel build error."
1520 def bootloader(self):
1521 if self.settings.has_key("AUTORESUME") \
1522 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1523 print "Resume point detected, skipping bootloader operation..."
1526 cmd("/bin/bash "+self.settings["controller_file"]+\
1527 " bootloader " + self.settings["target_path"],\
1528 "Bootloader script failed.",env=self.env)
1529 touch(self.settings["autoresume_path"]+"bootloader")
1530 except CatalystError:
1532 raise CatalystError,"Script aborting due to error."
1534 def livecd_update(self):
1535 if self.settings.has_key("AUTORESUME") \
1536 and os.path.exists(self.settings["autoresume_path"]+\
1538 print "Resume point detected, skipping build_packages operation..."
1541 cmd("/bin/bash "+self.settings["controller_file"]+\
1542 " livecd-update","livecd-update failed.",env=self.env)
1543 touch(self.settings["autoresume_path"]+"livecd_update")
1545 except CatalystError:
1547 raise CatalystError,"build aborting due to livecd_update error."
1549 def clear_chroot(self):
1550 myemp=self.settings["chroot_path"]
1551 if os.path.isdir(myemp):
1552 print "Emptying directory",myemp
1554 stat the dir, delete the dir, recreate the dir and set
1555 the proper perms and ownership
1557 mystat=os.stat(myemp)
1558 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1559 """ There's no easy way to change flags recursively in python """
1560 if os.uname()[0] == "FreeBSD":
1561 os.system("chflags -R noschg "+myemp)
1562 shutil.rmtree(myemp)
1563 os.makedirs(myemp,0755)
1564 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1565 os.chmod(myemp,mystat[ST_MODE])
1567 def clear_packages(self):
1568 if self.settings.has_key("PKGCACHE"):
1569 print "purging the pkgcache ..."
1571 myemp=self.settings["pkgcache_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 shutil.rmtree(myemp)
1581 os.makedirs(myemp,0755)
1582 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1583 os.chmod(myemp,mystat[ST_MODE])
1585 def clear_kerncache(self):
1586 if self.settings.has_key("KERNCACHE"):
1587 print "purging the kerncache ..."
1589 myemp=self.settings["kerncache_path"]
1590 if os.path.isdir(myemp):
1591 print "Emptying directory",myemp
1593 stat the dir, delete the dir, recreate the dir and set
1594 the proper perms and ownership
1596 mystat=os.stat(myemp)
1597 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1598 shutil.rmtree(myemp)
1599 os.makedirs(myemp,0755)
1600 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1601 os.chmod(myemp,mystat[ST_MODE])
1603 def clear_autoresume(self):
1604 """ Clean resume points since they are no longer needed """
1605 if self.settings.has_key("AUTORESUME"):
1606 print "Removing AutoResume Points: ..."
1607 myemp=self.settings["autoresume_path"]
1608 if os.path.isdir(myemp):
1609 if self.settings.has_key("AUTORESUME"):
1610 print "Emptying directory",myemp
1612 stat the dir, delete the dir, recreate the dir and set
1613 the proper perms and ownership
1615 mystat=os.stat(myemp)
1616 if os.uname()[0] == "FreeBSD":
1617 cmd("chflags -R noschg "+myemp,\
1618 "Could not remove immutable flag for file "\
1620 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1621 shutil.rmtree(myemp)
1622 os.makedirs(myemp,0755)
1623 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1624 os.chmod(myemp,mystat[ST_MODE])
1626 def gen_contents_file(self,file):
1627 if os.path.exists(file+".CONTENTS"):
1628 os.remove(file+".CONTENTS")
1629 if self.settings.has_key("contents"):
1630 if os.path.exists(file):
1631 myf=open(file+".CONTENTS","w")
1633 for i in self.settings["contents"].split():
1638 contents=generate_contents(file,contents_function=j,\
1639 verbose=self.settings.has_key("VERBOSE"))
1644 def gen_digest_file(self,file):
1645 if os.path.exists(file+".DIGESTS"):
1646 os.remove(file+".DIGESTS")
1647 if self.settings.has_key("digests"):
1648 if os.path.exists(file):
1649 myf=open(file+".DIGESTS","w")
1651 for i in self.settings["digests"].split():
1655 for f in [file, file+'.CONTENTS']:
1656 if os.path.exists(f):
1658 for k in hash_map.keys():
1659 hash=generate_hash(f,hash_function=k,verbose=\
1660 self.settings.has_key("VERBOSE"))
1664 hash=generate_hash(f,hash_function=j,verbose=\
1665 self.settings.has_key("VERBOSE"))
1670 countdown(10,"Purging Caches ...")
1671 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY") or self.settings.has_key("PURGETMPONLY"):
1672 print "clearing autoresume ..."
1673 self.clear_autoresume()
1675 print "clearing chroot ..."
1678 if not self.settings.has_key("PURGETMPONLY"):
1679 print "clearing package cache ..."
1680 self.clear_packages()
1682 print "clearing kerncache ..."
1683 self.clear_kerncache()
1685 # vim: ts=4 sw=4 sta et sts=4 ai