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"]
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"]}
182 self.mounts=["/proc","/dev","/usr/portage/distfiles"]
183 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
184 "/usr/portage/distfiles":self.settings["distdir"]}
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 def override_cbuild(self):
230 if self.makeconf.has_key("CBUILD"):
231 self.settings["CBUILD"]=self.makeconf["CBUILD"]
233 def override_chost(self):
234 if self.makeconf.has_key("CHOST"):
235 self.settings["CHOST"]=self.makeconf["CHOST"]
237 def override_cflags(self):
238 if self.makeconf.has_key("CFLAGS"):
239 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
241 def override_cxxflags(self):
242 if self.makeconf.has_key("CXXFLAGS"):
243 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
245 def override_ldflags(self):
246 if self.makeconf.has_key("LDFLAGS"):
247 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
249 def set_install_mask(self):
250 if self.settings.has_key("install_mask"):
251 if type(self.settings["install_mask"])!=types.StringType:
252 self.settings["install_mask"]=\
253 string.join(self.settings["install_mask"])
255 def set_spec_prefix(self):
256 self.settings["spec_prefix"]=self.settings["target"]
258 def set_target_profile(self):
259 self.settings["target_profile"]=self.settings["profile"]
261 def set_target_subpath(self):
262 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
263 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
264 self.settings["version_stamp"]
266 def set_source_subpath(self):
267 if type(self.settings["source_subpath"])!=types.StringType:
268 raise CatalystError,\
269 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
271 def set_pkgcache_path(self):
272 if self.settings.has_key("pkgcache_path"):
273 if type(self.settings["pkgcache_path"])!=types.StringType:
274 self.settings["pkgcache_path"]=\
275 normpath(string.join(self.settings["pkgcache_path"]))
277 self.settings["pkgcache_path"]=\
278 normpath(self.settings["storedir"]+"/packages/"+\
279 self.settings["target_subpath"]+"/")
281 def set_kerncache_path(self):
282 if self.settings.has_key("kerncache_path"):
283 if type(self.settings["kerncache_path"])!=types.StringType:
284 self.settings["kerncache_path"]=\
285 normpath(string.join(self.settings["kerncache_path"]))
287 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
288 "/kerncache/"+self.settings["target_subpath"]+"/")
290 def set_target_path(self):
291 self.settings["target_path"]=normpath(self.settings["storedir"]+\
292 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
293 if self.settings.has_key("AUTORESUME")\
294 and os.path.exists(self.settings["autoresume_path"]+\
295 "setup_target_path"):
297 "Resume point detected, skipping target path setup operation..."
299 """ First clean up any existing target stuff """
300 # XXX WTF are we removing the old tarball before we start building the
301 # XXX new one? If the build fails, you don't want to be left with
303 # if os.path.isfile(self.settings["target_path"]):
304 # cmd("rm -f "+self.settings["target_path"],\
305 # "Could not remove existing file: "\
306 # +self.settings["target_path"],env=self.env)
307 touch(self.settings["autoresume_path"]+"setup_target_path")
309 if not os.path.exists(self.settings["storedir"]+"/builds/"):
310 os.makedirs(self.settings["storedir"]+"/builds/")
312 def set_fsscript(self):
313 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
314 self.settings["fsscript"]=\
315 self.settings[self.settings["spec_prefix"]+"/fsscript"]
316 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
319 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
320 self.settings["rcadd"]=\
321 self.settings[self.settings["spec_prefix"]+"/rcadd"]
322 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
325 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
326 self.settings["rcdel"]=\
327 self.settings[self.settings["spec_prefix"]+"/rcdel"]
328 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
331 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
332 self.settings["cdtar"]=\
333 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
334 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
337 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
338 if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
339 self.settings["iso"]=\
340 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
342 # This automatically prepends the build dir to the ISO output path
343 # if it doesn't start with a /
344 self.settings["iso"] = normpath(self.settings["storedir"] + \
345 "/builds/" + self.settings["rel_type"] + "/" + \
346 self.settings[self.settings["spec_prefix"]+"/iso"])
347 del self.settings[self.settings["spec_prefix"]+"/iso"]
349 def set_fstype(self):
350 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
351 self.settings["fstype"]=\
352 self.settings[self.settings["spec_prefix"]+"/fstype"]
353 del self.settings[self.settings["spec_prefix"]+"/fstype"]
355 if not self.settings.has_key("fstype"):
356 self.settings["fstype"]="normal"
357 for x in self.valid_values:
358 if x == self.settings["spec_prefix"]+"/fstype":
359 print "\n"+self.settings["spec_prefix"]+\
360 "/fstype is being set to the default of \"normal\"\n"
363 if self.settings.has_key("fstype"):
364 self.valid_values.append("fsops")
365 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
366 self.settings["fsops"]=\
367 self.settings[self.settings["spec_prefix"]+"/fsops"]
368 del self.settings[self.settings["spec_prefix"]+"/fsops"]
370 def set_source_path(self):
371 if self.settings.has_key("SEEDCACHE")\
372 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
373 self.settings["source_subpath"]+"/")):
374 self.settings["source_path"]=normpath(self.settings["storedir"]+\
375 "/tmp/"+self.settings["source_subpath"]+"/")
377 self.settings["source_path"]=normpath(self.settings["storedir"]+\
378 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
379 if os.path.isfile(self.settings["source_path"]):
380 # XXX: Is this even necessary if the previous check passes?
381 if os.path.exists(self.settings["source_path"]):
382 self.settings["source_path_hash"]=\
383 generate_hash(self.settings["source_path"],\
384 hash_function=self.settings["hash_function"],\
386 print "Source path set to "+self.settings["source_path"]
387 if os.path.isdir(self.settings["source_path"]):
388 print "\tIf this is not desired, remove this directory or turn off"
389 print "\tseedcache in the options of catalyst.conf the source path"
390 print "\twill then be "+\
391 normpath(self.settings["storedir"]+"/builds/"+\
392 self.settings["source_subpath"]+".tar.bz2\n")
394 def set_dest_path(self):
395 if self.settings.has_key("root_path"):
396 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
397 self.settings["root_path"])
399 self.settings["destpath"]=normpath(self.settings["chroot_path"])
401 def set_cleanables(self):
402 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
403 "/root/*","/usr/portage"]
405 def set_snapshot_path(self):
406 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
407 "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
409 if os.path.exists(self.settings["snapshot_path"]):
410 self.settings["snapshot_path_hash"]=\
411 generate_hash(self.settings["snapshot_path"],\
412 hash_function=self.settings["hash_function"],verbose=False)
414 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
415 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
417 if os.path.exists(self.settings["snapshot_path"]):
418 self.settings["snapshot_path_hash"]=\
419 generate_hash(self.settings["snapshot_path"],\
420 hash_function=self.settings["hash_function"],verbose=False)
422 def set_snapcache_path(self):
423 if self.settings.has_key("SNAPCACHE"):
424 self.settings["snapshot_cache_path"]=\
425 normpath(self.settings["snapshot_cache"]+"/"+\
426 self.settings["snapshot"]+"/")
427 self.snapcache_lock=\
428 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
429 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
431 def set_chroot_path(self):
433 NOTE: the trailing slash is very important!
434 Things *will* break without it!
436 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
437 "/tmp/"+self.settings["target_subpath"]+"/")
438 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
440 def set_autoresume_path(self):
441 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
442 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
443 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
444 self.settings["version_stamp"]+"/")
445 if self.settings.has_key("AUTORESUME"):
446 print "The autoresume path is " + self.settings["autoresume_path"]
447 if not os.path.exists(self.settings["autoresume_path"]):
448 os.makedirs(self.settings["autoresume_path"],0755)
450 def set_controller_file(self):
451 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
452 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
455 def set_iso_volume_id(self):
456 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
457 self.settings["iso_volume_id"]=\
458 self.settings[self.settings["spec_prefix"]+"/volid"]
459 if len(self.settings["iso_volume_id"])>32:
460 raise CatalystError,\
461 "ISO volume ID must not exceed 32 characters."
463 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
465 def set_action_sequence(self):
466 """ Default action sequence for run method """
467 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
468 "setup_confdir","portage_overlay",\
469 "base_dirs","bind","chroot_setup","setup_environment",\
470 "run_local","preclean","unbind","clean"]
471 # if self.settings.has_key("TARBALL") or \
472 # not self.settings.has_key("FETCH"):
473 if not self.settings.has_key("FETCH"):
474 self.settings["action_sequence"].append("capture")
475 self.settings["action_sequence"].append("clear_autoresume")
478 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
479 self.settings["use"]=\
480 self.settings[self.settings["spec_prefix"]+"/use"]
481 del self.settings[self.settings["spec_prefix"]+"/use"]
482 if self.settings.has_key("use"):
483 if type(self.settings["use"])==types.StringType:
484 self.settings["use"]=self.settings["use"].split()
485 self.settings["use"].append("bindist")
487 def set_stage_path(self):
488 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
490 def set_mounts(self):
493 def set_packages(self):
497 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
498 if type(self.settings[self.settings["spec_prefix"]+\
499 "/rm"])==types.StringType:
500 self.settings[self.settings["spec_prefix"]+"/rm"]=\
501 self.settings[self.settings["spec_prefix"]+"/rm"].split()
503 def set_linuxrc(self):
504 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
505 if type(self.settings[self.settings["spec_prefix"]+\
506 "/linuxrc"])==types.StringType:
507 self.settings["linuxrc"]=\
508 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
509 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
511 def set_busybox_config(self):
512 if self.settings.has_key(self.settings["spec_prefix"]+"/busybox_config"):
513 if type(self.settings[self.settings["spec_prefix"]+\
514 "/busybox_config"])==types.StringType:
515 self.settings["busybox_config"]=\
516 self.settings[self.settings["spec_prefix"]+"/busybox_config"]
517 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
519 def set_portage_overlay(self):
520 if self.settings.has_key("portage_overlay"):
521 if type(self.settings["portage_overlay"])==types.StringType:
522 self.settings["portage_overlay"]=\
523 self.settings["portage_overlay"].split()
524 print "portage_overlay directories are set to: \""+\
525 string.join(self.settings["portage_overlay"])+"\""
527 def set_overlay(self):
528 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
529 if type(self.settings[self.settings["spec_prefix"]+\
530 "/overlay"])==types.StringType:
531 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
532 self.settings[self.settings["spec_prefix"]+\
535 def set_root_overlay(self):
536 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
537 if type(self.settings[self.settings["spec_prefix"]+\
538 "/root_overlay"])==types.StringType:
539 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
540 self.settings[self.settings["spec_prefix"]+\
541 "/root_overlay"].split()
543 def set_root_path(self):
544 """ ROOT= variable for emerges """
545 self.settings["root_path"]="/"
547 def set_valid_build_kernel_vars(self,addlargs):
548 if addlargs.has_key("boot/kernel"):
549 if type(addlargs["boot/kernel"])==types.StringType:
550 loopy=[addlargs["boot/kernel"]]
552 loopy=addlargs["boot/kernel"]
555 self.valid_values.append("boot/kernel/"+x+"/aliases")
556 self.valid_values.append("boot/kernel/"+x+"/config")
557 self.valid_values.append("boot/kernel/"+x+"/console")
558 self.valid_values.append("boot/kernel/"+x+"/extraversion")
559 self.valid_values.append("boot/kernel/"+x+"/gk_action")
560 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
561 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
562 self.valid_values.append("boot/kernel/"+x+"/machine_type")
563 self.valid_values.append("boot/kernel/"+x+"/sources")
564 self.valid_values.append("boot/kernel/"+x+"/softlevel")
565 self.valid_values.append("boot/kernel/"+x+"/use")
566 self.valid_values.append("boot/kernel/"+x+"/packages")
567 if addlargs.has_key("boot/kernel/"+x+"/packages"):
568 if type(addlargs["boot/kernel/"+x+\
569 "/packages"])==types.StringType:
570 addlargs["boot/kernel/"+x+"/packages"]=\
571 [addlargs["boot/kernel/"+x+"/packages"]]
573 def set_build_kernel_vars(self):
574 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
575 self.settings["gk_mainargs"]=\
576 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
577 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
579 def kill_chroot_pids(self):
580 print "Checking for processes running in chroot and killing them."
583 Force environment variables to be exported so script can see them
585 self.setup_environment()
587 if os.path.exists(self.settings["sharedir"]+\
588 "/targets/support/kill-chroot-pids.sh"):
589 cmd("/bin/bash "+self.settings["sharedir"]+\
590 "/targets/support/kill-chroot-pids.sh",\
591 "kill-chroot-pids script failed.",env=self.env)
593 def mount_safety_check(self):
594 mypath=self.settings["chroot_path"]
597 Check and verify that none of our paths in mypath are mounted. We don't
598 want to clean up with things still mounted, and this allows us to check.
599 Returns 1 on ok, 0 on "something is still mounted" case.
602 if not os.path.exists(mypath):
605 for x in self.mounts:
606 if not os.path.exists(mypath+x):
609 if ismount(mypath+x):
610 """ Something is still mounted "" """
612 print x+" is still mounted; performing auto-bind-umount...",
613 """ Try to umount stuff ourselves """
615 if ismount(mypath+x):
616 raise CatalystError, "Auto-unbind failed for "+x
618 print "Auto-unbind successful..."
619 except CatalystError:
620 raise CatalystError, "Unable to auto-unbind "+x
625 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
628 if self.settings.has_key("SEEDCACHE"):
629 if os.path.isdir(self.settings["source_path"]):
630 """ SEEDCACHE Is a directory, use rsync """
631 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
632 " "+self.settings["chroot_path"]
633 display_msg="\nStarting rsync from "+\
634 self.settings["source_path"]+"\nto "+\
635 self.settings["chroot_path"]+\
636 " (This may take some time) ...\n"
637 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
638 self.settings["chroot_path"]+" failed."
640 """ SEEDCACHE is a not a directory, try untar'ing """
641 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
642 display_msg="\nStarting tar extract from "+\
643 self.settings["source_path"]+"\nto "+\
644 self.settings["chroot_path"]+\
645 " (This may take some time) ...\n"
646 unpack_cmd="tar xpf "+self.settings["source_path"]+" -C "+\
647 self.settings["chroot_path"]
648 error_msg="Tarball extraction of "+\
649 self.settings["source_path"]+" to "+\
650 self.settings["chroot_path"]+" failed."
652 """ No SEEDCACHE, use tar """
653 display_msg="\nStarting tar extract from "+\
654 self.settings["source_path"]+"\nto "+\
655 self.settings["chroot_path"]+\
656 " (This may take some time) ...\n"
657 unpack_cmd="tar xpf "+self.settings["source_path"]+" -C "+\
658 self.settings["chroot_path"]
659 error_msg="Tarball extraction of "+self.settings["source_path"]+\
660 " to "+self.settings["chroot_path"]+" failed."
662 if self.settings.has_key("AUTORESUME"):
663 if os.path.isdir(self.settings["source_path"]) \
664 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
665 """ Autoresume is valid, SEEDCACHE is valid """
667 invalid_snapshot=False
669 elif os.path.isfile(self.settings["source_path"]) \
670 and self.settings["source_path_hash"]==clst_unpack_hash:
671 """ Autoresume is valid, tarball is valid """
673 invalid_snapshot=True
675 elif os.path.isdir(self.settings["source_path"]) \
676 and not os.path.exists(self.settings["autoresume_path"]+\
678 """ Autoresume is invalid, SEEDCACHE """
680 invalid_snapshot=False
682 elif os.path.isfile(self.settings["source_path"]) \
683 and self.settings["source_path_hash"]!=clst_unpack_hash:
684 """ Autoresume is invalid, tarball """
686 invalid_snapshot=True
688 """ No autoresume, SEEDCACHE """
689 if self.settings.has_key("SEEDCACHE"):
690 """ SEEDCACHE so let's run rsync and let it clean up """
691 if os.path.isdir(self.settings["source_path"]):
693 invalid_snapshot=False
694 elif os.path.isfile(self.settings["source_path"]):
695 """ Tarball so unpack and remove anything already there """
697 invalid_snapshot=True
698 """ No autoresume, no SEEDCACHE """
700 """ Tarball so unpack and remove anything already there """
701 if os.path.isfile(self.settings["source_path"]):
703 invalid_snapshot=True
704 elif os.path.isdir(self.settings["source_path"]):
705 """ We should never reach this, so something is very wrong """
706 raise CatalystError,\
707 "source path is a dir but seedcache is not enabled"
710 self.mount_safety_check()
713 if self.settings.has_key("AUTORESUME"):
714 print "No Valid Resume point detected, cleaning up..."
716 self.clear_autoresume()
719 if not os.path.exists(self.settings["chroot_path"]):
720 os.makedirs(self.settings["chroot_path"])
722 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
723 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
725 if self.settings.has_key("PKGCACHE"):
726 if not os.path.exists(self.settings["pkgcache_path"]):
727 os.makedirs(self.settings["pkgcache_path"],0755)
729 if self.settings.has_key("KERNCACHE"):
730 if not os.path.exists(self.settings["kerncache_path"]):
731 os.makedirs(self.settings["kerncache_path"],0755)
734 cmd(unpack_cmd,error_msg,env=self.env)
736 if self.settings.has_key("source_path_hash"):
737 myf=open(self.settings["autoresume_path"]+"unpack","w")
738 myf.write(self.settings["source_path_hash"])
741 touch(self.settings["autoresume_path"]+"unpack")
743 print "Resume point detected, skipping unpack operation..."
745 def unpack_snapshot(self):
747 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
750 if self.settings.has_key("SNAPCACHE"):
751 snapshot_cache_hash=\
752 read_from_clst(self.settings["snapshot_cache_path"]+\
754 destdir=self.settings["snapshot_cache_path"]
755 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
756 unpack_errmsg="Error unpacking snapshot"
757 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
758 self.settings["snapshot_cache_path"]+\
759 " (This can take a long time)..."
760 cleanup_errmsg="Error removing existing snapshot cache directory."
761 self.snapshot_lock_object=self.snapcache_lock
763 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
764 print "Valid snapshot cache, skipping unpack of portage tree..."
767 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
768 cleanup_errmsg="Error removing existing snapshot directory."
770 "Cleaning up existing portage tree (This can take a long time)..."
771 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
772 self.settings["chroot_path"]+"/usr"
773 unpack_errmsg="Error unpacking snapshot"
775 if self.settings.has_key("AUTORESUME") \
776 and os.path.exists(self.settings["chroot_path"]+\
778 and os.path.exists(self.settings["autoresume_path"]\
780 and self.settings["snapshot_path_hash"] == snapshot_hash:
782 "Valid Resume point detected, skipping unpack of portage tree..."
786 if self.settings.has_key("SNAPCACHE"):
787 self.snapshot_lock_object.write_lock()
788 if os.path.exists(destdir):
790 cleanup_cmd="rm -rf "+destdir
791 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
792 if not os.path.exists(destdir):
793 os.makedirs(destdir,0755)
795 print "Unpacking portage tree (This can take a long time) ..."
796 cmd(unpack_cmd,unpack_errmsg,env=self.env)
798 if self.settings.has_key("SNAPCACHE"):
799 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
800 myf.write(self.settings["snapshot_path_hash"])
803 print "Setting snapshot autoresume point"
804 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
805 myf.write(self.settings["snapshot_path_hash"])
808 if self.settings.has_key("SNAPCACHE"):
809 self.snapshot_lock_object.unlock()
811 def config_profile_link(self):
812 if self.settings.has_key("AUTORESUME") \
813 and os.path.exists(self.settings["autoresume_path"]+\
814 "config_profile_link"):
816 "Resume point detected, skipping config_profile_link operation..."
818 # TODO: zmedico and I discussed making this a directory and pushing
819 # in a parent file, as well as other user-specified configuration.
820 print "Configuring profile link..."
821 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
822 "Error zapping profile link",env=self.env)
823 cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
824 cmd("ln -sf ../../usr/portage/profiles/"+\
825 self.settings["target_profile"]+" "+\
826 self.settings["chroot_path"]+"/etc/portage/make.profile",\
827 "Error creating profile link",env=self.env)
828 touch(self.settings["autoresume_path"]+"config_profile_link")
830 def setup_confdir(self):
831 if self.settings.has_key("AUTORESUME") \
832 and os.path.exists(self.settings["autoresume_path"]+\
834 print "Resume point detected, skipping setup_confdir operation..."
836 if self.settings.has_key("portage_confdir"):
837 print "Configuring /etc/portage..."
838 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
839 self.settings["chroot_path"]+"/etc/portage/",\
840 "Error copying /etc/portage",env=self.env)
841 touch(self.settings["autoresume_path"]+"setup_confdir")
843 def portage_overlay(self):
844 """ We copy the contents of our overlays to /usr/local/portage """
845 if self.settings.has_key("portage_overlay"):
846 for x in self.settings["portage_overlay"]:
847 if os.path.exists(x):
848 print "Copying overlay dir " +x
849 cmd("mkdir -p "+self.settings["chroot_path"]+\
850 "/usr/local/portage",\
851 "Could not make portage_overlay dir",env=self.env)
852 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
853 "/usr/local/portage",\
854 "Could not copy portage_overlay",env=self.env)
856 def root_overlay(self):
857 """ Copy over the root_overlay """
858 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
859 for x in self.settings[self.settings["spec_prefix"]+\
861 if os.path.exists(x):
862 print "Copying root_overlay: "+x
863 cmd("rsync -a "+x+"/ "+\
864 self.settings["chroot_path"],\
865 self.settings["spec_prefix"]+"/root_overlay: "+x+\
866 " copy failed.",env=self.env)
872 for x in self.mounts:
873 if not os.path.exists(self.settings["chroot_path"]+x):
874 os.makedirs(self.settings["chroot_path"]+x,0755)
876 if not os.path.exists(self.mountmap[x]):
877 os.makedirs(self.mountmap[x],0755)
880 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
881 self.snapshot_lock_object.read_lock()
882 if os.uname()[0] == "FreeBSD":
884 retval=os.system("mount -t devfs none "+\
885 self.settings["chroot_path"]+x)
887 retval=os.system("mount_nullfs "+src+" "+\
888 self.settings["chroot_path"]+x)
890 retval=os.system("mount --bind "+src+" "+\
891 self.settings["chroot_path"]+x)
894 raise CatalystError,"Couldn't bind mount "+src
898 mypath=self.settings["chroot_path"]
899 myrevmounts=self.mounts[:]
900 myrevmounts.reverse()
901 """ Unmount in reverse order for nested bind-mounts """
902 for x in myrevmounts:
903 if not os.path.exists(mypath+x):
906 if not ismount(mypath+x):
909 retval=os.system("umount "+\
910 os.path.join(mypath,x.lstrip(os.path.sep)))
913 warn("First attempt to unmount: "+mypath+x+" failed.")
914 warn("Killing any pids still running in the chroot")
916 self.kill_chroot_pids()
918 retval2=os.system("umount "+mypath+x)
921 warn("Couldn't umount bind mount: "+mypath+x)
923 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
926 It's possible the snapshot lock object isn't created yet.
927 This is because mount safety check calls unbind before the
928 target is fully initialized
930 self.snapshot_lock_object.unlock()
935 if any bind mounts really failed, then we need to raise
936 this to potentially prevent an upcoming bash stage cleanup script
937 from wiping our bind mounts.
939 raise CatalystError,\
940 "Couldn't umount one or more bind-mounts; aborting for safety."
942 def chroot_setup(self):
943 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
944 "/etc/portage/make.conf")
945 self.override_cbuild()
946 self.override_chost()
947 self.override_cflags()
948 self.override_cxxflags()
949 self.override_ldflags()
950 if self.settings.has_key("AUTORESUME") \
951 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
952 print "Resume point detected, skipping chroot_setup operation..."
954 print "Setting up chroot..."
956 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
958 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
959 "Could not copy resolv.conf into place.",env=self.env)
961 """ Copy over the envscript, if applicable """
962 if self.settings.has_key("ENVSCRIPT"):
963 if not os.path.exists(self.settings["ENVSCRIPT"]):
964 raise CatalystError,\
965 "Can't find envscript "+self.settings["ENVSCRIPT"]
967 print "\nWarning!!!!"
968 print "\tOverriding certain env variables may cause catastrophic failure."
969 print "\tIf your build fails look here first as the possible problem."
970 print "\tCatalyst assumes you know what you are doing when setting"
971 print "\t\tthese variables."
972 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
973 print "\tYou have been warned\n"
975 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
976 self.settings["chroot_path"]+"/tmp/envscript",\
977 "Could not copy envscript into place.",env=self.env)
980 Copy over /etc/hosts from the host in case there are any
983 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
984 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
985 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
986 "Could not backup /etc/hosts",env=self.env)
987 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
988 "Could not copy /etc/hosts",env=self.env)
990 """ Modify and write out make.conf (for the chroot) """
991 cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
992 "Could not remove "+self.settings["chroot_path"]+\
993 "/etc/portage/make.conf",env=self.env)
994 myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
995 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
996 myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
997 if self.settings.has_key("CFLAGS"):
998 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
999 if self.settings.has_key("CXXFLAGS"):
1000 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1001 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1003 myf.write('CXXFLAGS="${CFLAGS}"\n')
1005 myf.write('CXXFLAGS="${CFLAGS}"\n')
1007 if self.settings.has_key("LDFLAGS"):
1008 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1009 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1010 if self.settings.has_key("CBUILD"):
1011 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")
1012 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1014 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")
1015 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1017 """ Figure out what our USE vars are for building """
1019 if self.settings.has_key("HOSTUSE"):
1020 myusevars.extend(self.settings["HOSTUSE"])
1022 if self.settings.has_key("use"):
1023 myusevars.extend(self.settings["use"])
1026 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1027 myusevars = sorted(set(myusevars))
1028 myf.write('USE="'+string.join(myusevars)+'"\n')
1029 if '-*' in myusevars:
1030 print "\nWarning!!! "
1031 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1032 "/use will cause portage to ignore"
1033 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1035 """ Setup the portage overlay """
1036 if self.settings.has_key("portage_overlay"):
1037 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1040 cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1041 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1042 "Could not backup /etc/portage/make.conf",env=self.env)
1043 touch(self.settings["autoresume_path"]+"chroot_setup")
1046 if self.settings.has_key("AUTORESUME") \
1047 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1048 print "Resume point detected, skipping fsscript operation..."
1050 if self.settings.has_key("fsscript"):
1051 if os.path.exists(self.settings["controller_file"]):
1052 cmd("/bin/bash "+self.settings["controller_file"]+\
1053 " fsscript","fsscript script failed.",env=self.env)
1054 touch(self.settings["autoresume_path"]+"fsscript")
1057 if self.settings.has_key("AUTORESUME") \
1058 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1059 print "Resume point detected, skipping rcupdate operation..."
1061 if os.path.exists(self.settings["controller_file"]):
1062 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1063 "rc-update script failed.",env=self.env)
1064 touch(self.settings["autoresume_path"]+"rcupdate")
1067 if self.settings.has_key("AUTORESUME") \
1068 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1069 print "Resume point detected, skipping clean operation..."
1071 for x in self.settings["cleanables"]:
1072 print "Cleaning chroot: "+x+"... "
1073 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1076 """ Put /etc/hosts back into place """
1077 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1078 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1079 self.settings["chroot_path"]+"/etc/hosts",\
1080 "Could not replace /etc/hosts",env=self.env)
1082 """ Remove our overlay """
1083 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1084 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1085 "Could not remove /usr/local/portage",env=self.env)
1086 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1087 "/etc/portage/make.conf",\
1088 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1090 """ Clean up old and obsoleted files in /etc """
1091 if os.path.exists(self.settings["stage_path"]+"/etc"):
1092 cmd("find "+self.settings["stage_path"]+\
1093 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1094 "Could not remove stray files in /etc",env=self.env)
1096 if os.path.exists(self.settings["controller_file"]):
1097 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1098 "clean script failed.",env=self.env)
1099 touch(self.settings["autoresume_path"]+"clean")
1102 if self.settings.has_key("AUTORESUME") \
1103 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1104 print "Resume point detected, skipping empty operation..."
1106 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1107 if type(self.settings[self.settings["spec_prefix"]+\
1108 "/empty"])==types.StringType:
1109 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1110 self.settings[self.settings["spec_prefix"]+\
1112 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1113 myemp=self.settings["destpath"]+x
1114 if not os.path.isdir(myemp):
1115 print x,"not a directory or does not exist, skipping 'empty' operation."
1117 print "Emptying directory",x
1119 stat the dir, delete the dir, recreate the dir and set
1120 the proper perms and ownership
1122 mystat=os.stat(myemp)
1123 shutil.rmtree(myemp)
1124 os.makedirs(myemp,0755)
1125 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1126 os.chmod(myemp,mystat[ST_MODE])
1127 touch(self.settings["autoresume_path"]+"empty")
1130 if self.settings.has_key("AUTORESUME") \
1131 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1132 print "Resume point detected, skipping remove operation..."
1134 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1135 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1137 We're going to shell out for all these cleaning
1138 operations, so we get easy glob handling.
1140 print "livecd: removing "+x
1141 os.system("rm -rf "+self.settings["chroot_path"]+x)
1143 if os.path.exists(self.settings["controller_file"]):
1144 cmd("/bin/bash "+self.settings["controller_file"]+\
1145 " clean","Clean failed.",env=self.env)
1146 touch(self.settings["autoresume_path"]+"remove")
1152 if self.settings.has_key("AUTORESUME") \
1153 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1154 print "Resume point detected, skipping preclean operation..."
1157 if os.path.exists(self.settings["controller_file"]):
1158 cmd("/bin/bash "+self.settings["controller_file"]+\
1159 " preclean","preclean script failed.",env=self.env)
1160 touch(self.settings["autoresume_path"]+"preclean")
1164 raise CatalystError, "Build failed, could not execute preclean"
1167 if self.settings.has_key("AUTORESUME") \
1168 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1169 print "Resume point detected, skipping capture operation..."
1171 """ Capture target in a tarball """
1172 mypath=self.settings["target_path"].split("/")
1173 """ Remove filename from path """
1174 mypath=string.join(mypath[:-1],"/")
1176 """ Now make sure path exists """
1177 if not os.path.exists(mypath):
1180 print "Creating stage tarball..."
1182 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1183 self.settings["stage_path"]+" .",\
1184 "Couldn't create stage tarball",env=self.env)
1186 self.gen_contents_file(self.settings["target_path"])
1187 self.gen_digest_file(self.settings["target_path"])
1189 touch(self.settings["autoresume_path"]+"capture")
1191 def run_local(self):
1192 if self.settings.has_key("AUTORESUME") \
1193 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1194 print "Resume point detected, skipping run_local operation..."
1197 if os.path.exists(self.settings["controller_file"]):
1198 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1199 "run script failed.",env=self.env)
1200 touch(self.settings["autoresume_path"]+"run_local")
1202 except CatalystError:
1204 raise CatalystError,"Stage build aborting due to error."
1206 def setup_environment(self):
1208 Modify the current environment. This is an ugly hack that should be
1209 fixed. We need this to use the os.system() call since we can't
1210 specify our own environ
1212 for x in self.settings.keys():
1213 """ Sanitize var names by doing "s|/-.|_|g" """
1214 varname="clst_"+string.replace(x,"/","_")
1215 varname=string.replace(varname,"-","_")
1216 varname=string.replace(varname,".","_")
1217 if type(self.settings[x])==types.StringType:
1218 """ Prefix to prevent namespace clashes """
1219 #os.environ[varname]=self.settings[x]
1220 self.env[varname]=self.settings[x]
1221 elif type(self.settings[x])==types.ListType:
1222 #os.environ[varname]=string.join(self.settings[x])
1223 self.env[varname]=string.join(self.settings[x])
1224 elif type(self.settings[x])==types.BooleanType:
1225 if self.settings[x]:
1226 self.env[varname]="true"
1228 self.env[varname]="false"
1229 if self.settings.has_key("makeopts"):
1230 self.env["MAKEOPTS"]=self.settings["makeopts"]
1233 self.chroot_lock.write_lock()
1235 """ Kill any pids in the chroot "" """
1236 self.kill_chroot_pids()
1238 """ Check for mounts right away and abort if we cannot unmount them """
1239 self.mount_safety_check()
1241 if self.settings.has_key("CLEAR_AUTORESUME"):
1242 self.clear_autoresume()
1244 if self.settings.has_key("PURGETMPONLY"):
1248 if self.settings.has_key("PURGEONLY"):
1252 if self.settings.has_key("PURGE"):
1255 for x in self.settings["action_sequence"]:
1256 print "--- Running action sequence: "+x
1259 apply(getattr(self,x))
1261 self.mount_safety_check()
1264 self.chroot_lock.unlock()
1267 if self.settings.has_key("AUTORESUME") \
1268 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1269 print "Resume point detected, skipping unmerge operation..."
1271 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1272 if type(self.settings[self.settings["spec_prefix"]+\
1273 "/unmerge"])==types.StringType:
1274 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1275 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1277 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1279 for x in range(0,len(myunmerge)):
1281 Surround args with quotes for passing to bash, allows
1282 things like "<" to remain intact
1284 myunmerge[x]="'"+myunmerge[x]+"'"
1285 myunmerge=string.join(myunmerge)
1287 """ Before cleaning, unmerge stuff """
1289 cmd("/bin/bash "+self.settings["controller_file"]+\
1290 " unmerge "+ myunmerge,"Unmerge script failed.",\
1292 print "unmerge shell script"
1293 except CatalystError:
1296 touch(self.settings["autoresume_path"]+"unmerge")
1298 def target_setup(self):
1299 if self.settings.has_key("AUTORESUME") \
1300 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1301 print "Resume point detected, skipping target_setup operation..."
1303 print "Setting up filesystems per filesystem type"
1304 cmd("/bin/bash "+self.settings["controller_file"]+\
1305 " target_image_setup "+ self.settings["target_path"],\
1306 "target_image_setup script failed.",env=self.env)
1307 touch(self.settings["autoresume_path"]+"target_setup")
1309 def setup_overlay(self):
1310 if self.settings.has_key("AUTORESUME") \
1311 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1312 print "Resume point detected, skipping setup_overlay operation..."
1314 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1315 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1316 if os.path.exists(x):
1317 cmd("rsync -a "+x+"/ "+\
1318 self.settings["target_path"],\
1319 self.settings["spec_prefix"]+"overlay: "+x+\
1320 " copy failed.",env=self.env)
1321 touch(self.settings["autoresume_path"]+"setup_overlay")
1323 def create_iso(self):
1324 if self.settings.has_key("AUTORESUME") \
1325 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1326 print "Resume point detected, skipping create_iso operation..."
1328 """ Create the ISO """
1329 if self.settings.has_key("iso"):
1330 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1331 self.settings["iso"],"ISO creation script failed.",\
1333 self.gen_contents_file(self.settings["iso"])
1334 self.gen_digest_file(self.settings["iso"])
1335 touch(self.settings["autoresume_path"]+"create_iso")
1337 print "WARNING: livecd/iso was not defined."
1338 print "An ISO Image will not be created."
1340 def build_packages(self):
1341 if self.settings.has_key("AUTORESUME") \
1342 and os.path.exists(self.settings["autoresume_path"]+\
1344 print "Resume point detected, skipping build_packages operation..."
1346 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1347 if self.settings.has_key("AUTORESUME") \
1348 and os.path.exists(self.settings["autoresume_path"]+\
1350 print "Resume point detected, skipping build_packages operation..."
1353 list_bashify(self.settings[self.settings["spec_prefix"]\
1356 cmd("/bin/bash "+self.settings["controller_file"]+\
1357 " build_packages "+mypack,\
1358 "Error in attempt to build packages",env=self.env)
1359 touch(self.settings["autoresume_path"]+"build_packages")
1360 except CatalystError:
1362 raise CatalystError,self.settings["spec_prefix"]+\
1363 "build aborting due to error."
1365 def build_kernel(self):
1366 if self.settings.has_key("AUTORESUME") \
1367 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1368 print "Resume point detected, skipping build_kernel operation..."
1370 if self.settings.has_key("boot/kernel"):
1372 mynames=self.settings["boot/kernel"]
1373 if type(mynames)==types.StringType:
1376 Execute the script that sets up the kernel build environment
1378 cmd("/bin/bash "+self.settings["controller_file"]+\
1379 " pre-kmerge ","Runscript pre-kmerge failed",\
1382 for kname in mynames:
1383 if self.settings.has_key("AUTORESUME") \
1384 and os.path.exists(self.settings["autoresume_path"]\
1385 +"build_kernel_"+kname):
1386 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1387 else: # TODO: make this not require a kernel config
1389 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1391 raise CatalystError,\
1392 "Can't find kernel config: "+\
1393 self.settings["boot/kernel/"+kname+\
1397 raise CatalystError,\
1398 "Required value boot/kernel/config not specified"
1401 cmd("cp "+self.settings["boot/kernel/"+kname+\
1403 self.settings["chroot_path"]+"/var/tmp/"+\
1405 "Couldn't copy kernel config: "+\
1406 self.settings["boot/kernel/"+kname+\
1407 "/config"],env=self.env)
1409 except CatalystError:
1413 If we need to pass special options to the bootloader
1414 for this kernel put them into the environment
1416 if self.settings.has_key("boot/kernel/"+kname+\
1418 myopts=self.settings["boot/kernel/"+kname+\
1421 if type(myopts) != types.StringType:
1422 myopts = string.join(myopts)
1423 self.env[kname+"_kernelopts"]=myopts
1426 self.env[kname+"_kernelopts"]=""
1428 if not self.settings.has_key("boot/kernel/"+kname+\
1430 self.settings["boot/kernel/"+kname+\
1433 self.env["clst_kextraversion"]=\
1434 self.settings["boot/kernel/"+kname+\
1437 if self.settings.has_key("boot/kernel/"+kname+\
1438 "/initramfs_overlay"):
1439 if os.path.exists(self.settings["boot/kernel/"+\
1440 kname+"/initramfs_overlay"]):
1441 print "Copying initramfs_overlay dir "+\
1442 self.settings["boot/kernel/"+kname+\
1443 "/initramfs_overlay"]
1446 self.settings["chroot_path"]+\
1447 "/tmp/initramfs_overlay/"+\
1448 self.settings["boot/kernel/"+kname+\
1449 "/initramfs_overlay"],env=self.env)
1451 cmd("cp -R "+self.settings["boot/kernel/"+\
1452 kname+"/initramfs_overlay"]+"/* "+\
1453 self.settings["chroot_path"]+\
1454 "/tmp/initramfs_overlay/"+\
1455 self.settings["boot/kernel/"+kname+\
1456 "/initramfs_overlay"],env=self.env)
1458 """ Execute the script that builds the kernel """
1459 cmd("/bin/bash "+self.settings["controller_file"]+\
1461 "Runscript kernel build failed",env=self.env)
1463 if self.settings.has_key("boot/kernel/"+kname+\
1464 "/initramfs_overlay"):
1465 if os.path.exists(self.settings["chroot_path"]+\
1466 "/tmp/initramfs_overlay/"):
1467 print "Cleaning up temporary overlay dir"
1468 cmd("rm -R "+self.settings["chroot_path"]+\
1469 "/tmp/initramfs_overlay/",env=self.env)
1471 touch(self.settings["autoresume_path"]+\
1472 "build_kernel_"+kname)
1475 Execute the script that cleans up the kernel build
1478 cmd("/bin/bash "+self.settings["controller_file"]+\
1480 "Runscript post-kmerge failed",env=self.env)
1482 touch(self.settings["autoresume_path"]+"build_kernel")
1484 except CatalystError:
1486 raise CatalystError,\
1487 "build aborting due to kernel build error."
1489 def bootloader(self):
1490 if self.settings.has_key("AUTORESUME") \
1491 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1492 print "Resume point detected, skipping bootloader operation..."
1495 cmd("/bin/bash "+self.settings["controller_file"]+\
1496 " bootloader " + self.settings["target_path"],\
1497 "Bootloader script failed.",env=self.env)
1498 touch(self.settings["autoresume_path"]+"bootloader")
1499 except CatalystError:
1501 raise CatalystError,"Script aborting due to error."
1503 def livecd_update(self):
1504 if self.settings.has_key("AUTORESUME") \
1505 and os.path.exists(self.settings["autoresume_path"]+\
1507 print "Resume point detected, skipping build_packages operation..."
1510 cmd("/bin/bash "+self.settings["controller_file"]+\
1511 " livecd-update","livecd-update failed.",env=self.env)
1512 touch(self.settings["autoresume_path"]+"livecd_update")
1514 except CatalystError:
1516 raise CatalystError,"build aborting due to livecd_update error."
1518 def clear_chroot(self):
1519 myemp=self.settings["chroot_path"]
1520 if os.path.isdir(myemp):
1521 print "Emptying directory",myemp
1523 stat the dir, delete the dir, recreate the dir and set
1524 the proper perms and ownership
1526 mystat=os.stat(myemp)
1527 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1528 """ There's no easy way to change flags recursively in python """
1529 if os.uname()[0] == "FreeBSD":
1530 os.system("chflags -R noschg "+myemp)
1531 shutil.rmtree(myemp)
1532 os.makedirs(myemp,0755)
1533 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1534 os.chmod(myemp,mystat[ST_MODE])
1536 def clear_packages(self):
1537 if self.settings.has_key("PKGCACHE"):
1538 print "purging the pkgcache ..."
1540 myemp=self.settings["pkgcache_path"]
1541 if os.path.isdir(myemp):
1542 print "Emptying directory",myemp
1544 stat the dir, delete the dir, recreate the dir and set
1545 the proper perms and ownership
1547 mystat=os.stat(myemp)
1548 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1549 shutil.rmtree(myemp)
1550 os.makedirs(myemp,0755)
1551 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1552 os.chmod(myemp,mystat[ST_MODE])
1554 def clear_kerncache(self):
1555 if self.settings.has_key("KERNCACHE"):
1556 print "purging the kerncache ..."
1558 myemp=self.settings["kerncache_path"]
1559 if os.path.isdir(myemp):
1560 print "Emptying directory",myemp
1562 stat the dir, delete the dir, recreate the dir and set
1563 the proper perms and ownership
1565 mystat=os.stat(myemp)
1566 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1567 shutil.rmtree(myemp)
1568 os.makedirs(myemp,0755)
1569 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1570 os.chmod(myemp,mystat[ST_MODE])
1572 def clear_autoresume(self):
1573 """ Clean resume points since they are no longer needed """
1574 if self.settings.has_key("AUTORESUME"):
1575 print "Removing AutoResume Points: ..."
1576 myemp=self.settings["autoresume_path"]
1577 if os.path.isdir(myemp):
1578 if self.settings.has_key("AUTORESUME"):
1579 print "Emptying directory",myemp
1581 stat the dir, delete the dir, recreate the dir and set
1582 the proper perms and ownership
1584 mystat=os.stat(myemp)
1585 if os.uname()[0] == "FreeBSD":
1586 cmd("chflags -R noschg "+myemp,\
1587 "Could not remove immutable flag for file "\
1589 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1590 shutil.rmtree(myemp)
1591 os.makedirs(myemp,0755)
1592 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1593 os.chmod(myemp,mystat[ST_MODE])
1595 def gen_contents_file(self,file):
1596 if os.path.exists(file+".CONTENTS"):
1597 os.remove(file+".CONTENTS")
1598 if self.settings.has_key("contents"):
1599 if os.path.exists(file):
1600 myf=open(file+".CONTENTS","w")
1602 for i in self.settings["contents"].split():
1607 contents=generate_contents(file,contents_function=j,\
1608 verbose=self.settings.has_key("VERBOSE"))
1613 def gen_digest_file(self,file):
1614 if os.path.exists(file+".DIGESTS"):
1615 os.remove(file+".DIGESTS")
1616 if self.settings.has_key("digests"):
1617 if os.path.exists(file):
1618 myf=open(file+".DIGESTS","w")
1620 for i in self.settings["digests"].split():
1624 for f in [file, file+'.CONTENTS']:
1625 if os.path.exists(f):
1627 for k in hash_map.keys():
1628 hash=generate_hash(f,hash_function=k,verbose=\
1629 self.settings.has_key("VERBOSE"))
1633 hash=generate_hash(f,hash_function=j,verbose=\
1634 self.settings.has_key("VERBOSE"))
1639 countdown(10,"Purging Caches ...")
1640 if self.settings.has_key("PURGE") or self.settings.has_key("PURGEONLY") or self.settings.has_key("PURGETMPONLY"):
1641 print "clearing autoresume ..."
1642 self.clear_autoresume()
1644 print "clearing chroot ..."
1647 if not self.settings.has_key("PURGETMPONLY"):
1648 print "clearing package cache ..."
1649 self.clear_packages()
1651 print "clearing kerncache ..."
1652 self.clear_kerncache()
1654 # vim: ts=4 sw=4 sta et sts=4 ai