3 This class does all of the chroot setup, copying of files, etc. It is
4 the driver class for pretty much everything that Catalyst does.
7 import os,string,imp,types,shutil
8 from catalyst_support import *
9 from generic_target import *
12 class generic_stage_target(generic_target):
14 def __init__(self,myspec,addlargs):
15 self.required_values.extend(["version_stamp","target","subarch",\
16 "rel_type","profile","snapshot","source_subpath"])
18 self.valid_values.extend(["version_stamp","target","subarch",\
19 "rel_type","profile","snapshot","source_subpath","portage_confdir",\
20 "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
21 "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
23 self.set_valid_build_kernel_vars(addlargs)
24 generic_target.__init__(self,myspec,addlargs)
27 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
28 work better with vapier's CBUILD stuff. I've removed the "monolithic"
29 machinemap from this file and split up its contents amongst the
30 various arch/foo.py files.
32 When register() is called on each module in the arch/ dir, it now
33 returns a tuple instead of acting on the subarchmap dict that is
34 passed to it. The tuple contains the values that were previously
35 added to subarchmap as well as a new list of CHOSTs that go along
36 with that arch. This allows us to build machinemap on the fly based
37 on the keys in subarchmap and the values of the 2nd list returned
40 Also, after talking with vapier. I have a slightly better idea of what
41 certain variables are used for and what they should be set to. Neither
42 'buildarch' or 'hostarch' are used directly, so their value doesn't
43 really matter. They are just compared to determine if we are
44 cross-compiling. Because of this, they are just set to the name of the
45 module in arch/ that the subarch is part of to make things simpler.
46 The entire build process is still based off of 'subarch' like it was
53 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
54 "/arch/") if x.endswith(".py")]:
56 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
58 This next line loads the plugin as a module and assigns it to
61 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
62 ".py",(".py","r",imp.PY_SOURCE))
64 This next line registers all the subarches supported in the
67 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
68 self.subarchmap.update(tmpsubarchmap)
69 for machine in tmpmachinemap:
70 machinemap[machine] = x
71 for subarch in tmpsubarchmap:
72 machinemap[subarch] = x
76 This message should probably change a bit, since everything in
77 the dir should load just fine. If it doesn't, it's probably a
78 syntax error in the module
80 msg("Can't find/load "+x+".py plugin in "+\
81 self.settings["sharedir"]+"/arch/")
83 if self.settings.has_key("chost"):
84 hostmachine = self.settings["chost"].split("-")[0]
85 if not machinemap.has_key(hostmachine):
86 raise CatalystError, "Unknown host machine type "+hostmachine
87 self.settings["hostarch"]=machinemap[hostmachine]
89 hostmachine = self.settings["subarch"]
90 if machinemap.has_key(hostmachine):
91 hostmachine = machinemap[hostmachine]
92 self.settings["hostarch"]=hostmachine
93 if self.settings.has_key("cbuild"):
94 buildmachine = self.settings["cbuild"].split("-")[0]
96 buildmachine = os.uname()[4]
97 if not machinemap.has_key(buildmachine):
98 raise CatalystError, "Unknown build machine type "+buildmachine
99 self.settings["buildarch"]=machinemap[buildmachine]
100 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
101 self.settings["buildarch"])
103 """ Call arch constructor, pass our settings """
105 self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
107 print "Invalid subarch: "+self.settings["subarch"]
108 print "Choose one of the following:",
109 for x in self.subarchmap:
114 print "Using target:",self.settings["target"]
115 """ Print a nice informational message """
116 if self.settings["buildarch"]==self.settings["hostarch"]:
117 print "Building natively for",self.settings["hostarch"]
118 elif self.settings["crosscompile"]:
119 print "Cross-compiling on",self.settings["buildarch"],\
120 "for different machine type",self.settings["hostarch"]
122 print "Building on",self.settings["buildarch"],\
123 "for alternate personality type",self.settings["hostarch"]
125 """ This must be set first as other set_ options depend on this """
126 self.set_spec_prefix()
128 """ Define all of our core variables """
129 self.set_target_profile()
130 self.set_target_subpath()
131 self.set_source_subpath()
134 self.set_snapshot_path()
136 self.set_source_path()
137 self.set_snapcache_path()
138 self.set_chroot_path()
139 self.set_autoresume_path()
141 self.set_stage_path()
142 self.set_target_path()
144 self.set_controller_file()
145 self.set_action_sequence()
147 self.set_cleanables()
148 self.set_iso_volume_id()
149 self.set_build_kernel_vars()
151 # TODO: Remove archscript/runscript from next major version
152 self.set_archscript()
154 self.set_install_mask()
165 self.set_portage_overlay()
166 self.set_root_overlay()
169 This next line checks to make sure that the specified variables exist
173 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
175 """ If we are using portage_confdir, check that as well. """
176 if self.settings.has_key("portage_confdir"):
177 file_locate(self.settings,["portage_confdir"],expand=0)
179 """ Setup our mount points """
180 if self.settings.has_key("SNAPCACHE"):
181 self.mounts=["/proc","/dev","/usr/portage","/usr/portage/distfiles"]
182 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
183 "/usr/portage":self.settings["snapshot_cache_path"]+"/portage",\
184 "/usr/portage/distfiles":self.settings["distdir"]}
186 self.mounts=["/proc","/dev","/usr/portage/distfiles"]
187 self.mountmap={"/proc":"/proc","/dev":"/dev","/dev/pts":"/dev/pts",\
188 "/usr/portage/distfiles":self.settings["distdir"]}
189 if os.uname()[0] == "Linux":
190 self.mounts.append("/dev/pts")
195 Configure any user specified options (either in catalyst.conf or on
198 if self.settings.has_key("PKGCACHE"):
199 self.set_pkgcache_path()
200 print "Location of the package cache is "+\
201 self.settings["pkgcache_path"]
202 self.mounts.append("/usr/portage/packages")
203 self.mountmap["/usr/portage/packages"]=\
204 self.settings["pkgcache_path"]
206 if self.settings.has_key("KERNCACHE"):
207 self.set_kerncache_path()
208 print "Location of the kerncache is "+\
209 self.settings["kerncache_path"]
210 self.mounts.append("/tmp/kerncache")
211 self.mountmap["/tmp/kerncache"]=self.settings["kerncache_path"]
213 if self.settings.has_key("CCACHE"):
214 if os.environ.has_key("CCACHE_DIR"):
215 ccdir=os.environ["CCACHE_DIR"]
216 del os.environ["CCACHE_DIR"]
218 ccdir="/root/.ccache"
219 if not os.path.isdir(ccdir):
220 raise CatalystError,\
221 "Compiler cache support can't be enabled (can't find "+\
223 self.mounts.append("/var/tmp/ccache")
224 self.mountmap["/var/tmp/ccache"]=ccdir
225 """ for the chroot: """
226 self.env["CCACHE_DIR"]="/var/tmp/ccache"
228 if self.settings.has_key("ICECREAM"):
229 self.mounts.append("/var/cache/icecream")
230 self.mountmap["/var/cache/icecream"]="/var/cache/icecream"
231 self.env["PATH"]="/usr/lib/icecc/bin:"+self.env["PATH"]
233 def override_cbuild(self):
234 if self.makeconf.has_key("CBUILD"):
235 self.settings["CBUILD"]=self.makeconf["CBUILD"]
237 def override_chost(self):
238 if self.makeconf.has_key("CHOST"):
239 self.settings["CHOST"]=self.makeconf["CHOST"]
241 def override_cflags(self):
242 if self.makeconf.has_key("CFLAGS"):
243 self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
245 def override_cxxflags(self):
246 if self.makeconf.has_key("CXXFLAGS"):
247 self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
249 def override_ldflags(self):
250 if self.makeconf.has_key("LDFLAGS"):
251 self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
253 def set_install_mask(self):
254 if self.settings.has_key("install_mask"):
255 if type(self.settings["install_mask"])!=types.StringType:
256 self.settings["install_mask"]=\
257 string.join(self.settings["install_mask"])
259 def set_spec_prefix(self):
260 self.settings["spec_prefix"]=self.settings["target"]
262 def set_target_profile(self):
263 self.settings["target_profile"]=self.settings["profile"]
265 def set_target_subpath(self):
266 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
267 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
268 self.settings["version_stamp"]
270 def set_source_subpath(self):
271 if type(self.settings["source_subpath"])!=types.StringType:
272 raise CatalystError,\
273 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
275 def set_pkgcache_path(self):
276 if self.settings.has_key("pkgcache_path"):
277 if type(self.settings["pkgcache_path"])!=types.StringType:
278 self.settings["pkgcache_path"]=\
279 normpath(string.join(self.settings["pkgcache_path"]))
281 self.settings["pkgcache_path"]=\
282 normpath(self.settings["storedir"]+"/packages/"+\
283 self.settings["target_subpath"]+"/")
285 def set_kerncache_path(self):
286 if self.settings.has_key("kerncache_path"):
287 if type(self.settings["kerncache_path"])!=types.StringType:
288 self.settings["kerncache_path"]=\
289 normpath(string.join(self.settings["kerncache_path"]))
291 self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
292 "/kerncache/"+self.settings["target_subpath"]+"/")
294 def set_target_path(self):
295 self.settings["target_path"]=normpath(self.settings["storedir"]+\
296 "/builds/"+self.settings["target_subpath"]+".tar.bz2")
297 if self.settings.has_key("AUTORESUME")\
298 and os.path.exists(self.settings["autoresume_path"]+\
299 "setup_target_path"):
301 "Resume point detected, skipping target path setup operation..."
303 """ First clean up any existing target stuff """
304 if os.path.isfile(self.settings["target_path"]):
305 cmd("rm -f "+self.settings["target_path"],\
306 "Could not remove existing file: "\
307 +self.settings["target_path"],env=self.env)
308 touch(self.settings["autoresume_path"]+"setup_target_path")
310 if not os.path.exists(self.settings["storedir"]+"/builds/"):
311 os.makedirs(self.settings["storedir"]+"/builds/")
313 def set_archscript(self):
314 if self.settings.has_key(self.settings["spec_prefix"]+"/archscript"):
315 # TODO: remove this warning/code with the next major version
316 print "\nWarning!!! "
317 print "\t"+self.settings["spec_prefix"]+"/archscript"+\
318 " is deprecated and no longer used.\n"
320 def set_runscript(self):
321 if self.settings.has_key(self.settings["spec_prefix"]+"/runscript"):
322 # TODO: remove this warning/code with the next major version
323 print "\nWarning!!! "
324 print "\t"+self.settings["spec_prefix"]+"/runscript"+\
325 " is deprecated and no longer used.\n"
327 def set_fsscript(self):
328 if self.settings.has_key(self.settings["spec_prefix"]+"/fsscript"):
329 self.settings["fsscript"]=\
330 self.settings[self.settings["spec_prefix"]+"/fsscript"]
331 del self.settings[self.settings["spec_prefix"]+"/fsscript"]
334 if self.settings.has_key(self.settings["spec_prefix"]+"/rcadd"):
335 self.settings["rcadd"]=\
336 self.settings[self.settings["spec_prefix"]+"/rcadd"]
337 del self.settings[self.settings["spec_prefix"]+"/rcadd"]
340 if self.settings.has_key(self.settings["spec_prefix"]+"/rcdel"):
341 self.settings["rcdel"]=\
342 self.settings[self.settings["spec_prefix"]+"/rcdel"]
343 del self.settings[self.settings["spec_prefix"]+"/rcdel"]
346 if self.settings.has_key(self.settings["spec_prefix"]+"/cdtar"):
347 self.settings["cdtar"]=\
348 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
349 del self.settings[self.settings["spec_prefix"]+"/cdtar"]
352 if self.settings.has_key(self.settings["spec_prefix"]+"/iso"):
353 self.settings["iso"]=\
354 normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
355 del self.settings[self.settings["spec_prefix"]+"/iso"]
357 def set_fstype(self):
358 if self.settings.has_key(self.settings["spec_prefix"]+"/cdfstype"):
359 # TODO: remove this warning/code with the next major version
360 print "\nWarning!!! "
361 print self.settings["spec_prefix"]+"/cdfstype"+\
362 " is deprecated and will be removed."
363 print "\tUse "+self.settings["spec_prefix"]+"/fstype"+" instead."
364 print "\tConverting to "+self.settings["spec_prefix"]+"/fstype"+\
366 print "\tContinuing ....\n"
367 self.settings["fstype"]=\
368 self.settings[self.settings["spec_prefix"]+"/cdfstype"]
369 del self.settings[self.settings["spec_prefix"]+"/cdfstype"]
371 if self.settings.has_key(self.settings["spec_prefix"]+"/fstype"):
372 self.settings["fstype"]=\
373 self.settings[self.settings["spec_prefix"]+"/fstype"]
374 del self.settings[self.settings["spec_prefix"]+"/fstype"]
376 if not self.settings.has_key("fstype"):
377 self.settings["fstype"]="normal"
378 for x in self.valid_values:
379 if x == self.settings["spec_prefix"]+"/fstype"\
380 or x == self.settings["spec_prefix"]+"/cdfstype":
381 print "\n"+self.settings["spec_prefix"]+\
382 "/fstype is being set to the default of \"normal\"\n"
385 if self.settings.has_key("fstype"):
386 self.valid_values.append("fsops")
387 if self.settings.has_key(self.settings["spec_prefix"]+"/fsops"):
388 self.settings["fsops"]=\
389 self.settings[self.settings["spec_prefix"]+"/fsops"]
390 del self.settings[self.settings["spec_prefix"]+"/fsops"]
392 def set_source_path(self):
393 if self.settings.has_key("SEEDCACHE")\
394 and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
395 self.settings["source_subpath"]+"/")):
396 self.settings["source_path"]=normpath(self.settings["storedir"]+\
397 "/tmp/"+self.settings["source_subpath"]+"/")
399 self.settings["source_path"]=normpath(self.settings["storedir"]+\
400 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
401 if os.path.isfile(self.settings["source_path"]):
402 # XXX: Is this even necessary if the previous check passes?
403 if os.path.exists(self.settings["source_path"]):
404 self.settings["source_path_hash"]=\
405 generate_hash(self.settings["source_path"],\
406 hash_function=self.settings["hash_function"],\
408 print "Source path set to "+self.settings["source_path"]
409 if os.path.isdir(self.settings["source_path"]):
410 print "\tIf this is not desired, remove this directory or turn off"
411 print "\tseedcache in the options of catalyst.conf the source path"
412 print "\twill then be "+\
413 normpath(self.settings["storedir"]+"/builds/"+\
414 self.settings["source_subpath"]+".tar.bz2\n")
416 def set_dest_path(self):
417 if self.settings.has_key("root_path"):
418 self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
419 self.settings["root_path"])
421 self.settings["destpath"]=normpath(self.settings["chroot_path"])
423 def set_cleanables(self):
424 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
425 "/root/*","/usr/portage"]
427 def set_snapshot_path(self):
428 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
429 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
431 if os.path.exists(self.settings["snapshot_path"]):
432 self.settings["snapshot_path_hash"]=\
433 generate_hash(self.settings["snapshot_path"],\
434 hash_function=self.settings["hash_function"],verbose=False)
436 def set_snapcache_path(self):
437 if self.settings.has_key("SNAPCACHE"):
438 self.settings["snapshot_cache_path"]=\
439 normpath(self.settings["snapshot_cache"]+"/"+\
440 self.settings["snapshot"]+"/")
441 self.snapcache_lock=\
442 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
443 print "Caching snapshot to "+self.settings["snapshot_cache_path"]
445 def set_chroot_path(self):
447 NOTE: the trailing slash is very important!
448 Things *will* break without it!
450 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
451 "/tmp/"+self.settings["target_subpath"]+"/")
452 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
454 def set_autoresume_path(self):
455 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
456 "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
457 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
458 self.settings["version_stamp"]+"/")
459 if self.settings.has_key("AUTORESUME"):
460 print "The autoresume path is " + self.settings["autoresume_path"]
461 if not os.path.exists(self.settings["autoresume_path"]):
462 os.makedirs(self.settings["autoresume_path"],0755)
464 def set_controller_file(self):
465 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
466 "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
469 def set_iso_volume_id(self):
470 if self.settings.has_key(self.settings["spec_prefix"]+"/volid"):
471 self.settings["iso_volume_id"]=\
472 self.settings[self.settings["spec_prefix"]+"/volid"]
473 if len(self.settings["iso_volume_id"])>32:
474 raise CatalystError,\
475 "ISO volume ID must not exceed 32 characters."
477 self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
479 def set_action_sequence(self):
480 """ Default action sequence for run method """
481 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
482 "config_profile_link","setup_confdir","portage_overlay",\
483 "base_dirs","bind","chroot_setup","setup_environment",\
484 "run_local","preclean","unbind","clean"]
485 # if self.settings.has_key("TARBALL") or \
486 # not self.settings.has_key("FETCH"):
487 if not self.settings.has_key("FETCH"):
488 self.settings["action_sequence"].append("capture")
489 self.settings["action_sequence"].append("clear_autoresume")
492 if self.settings.has_key(self.settings["spec_prefix"]+"/use"):
493 self.settings["use"]=\
494 self.settings[self.settings["spec_prefix"]+"/use"]
495 del self.settings[self.settings["spec_prefix"]+"/use"]
496 if self.settings.has_key("use"):
497 if type(self.settings["use"])==types.StringType:
498 self.settings["use"]=self.settings["use"].split()
499 self.settings["use"].append("bindist")
501 def set_stage_path(self):
502 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
504 def set_mounts(self):
507 def set_packages(self):
511 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
512 if type(self.settings[self.settings["spec_prefix"]+\
513 "/rm"])==types.StringType:
514 self.settings[self.settings["spec_prefix"]+"/rm"]=\
515 self.settings[self.settings["spec_prefix"]+"/rm"].split()
517 def set_linuxrc(self):
518 if self.settings.has_key(self.settings["spec_prefix"]+"/linuxrc"):
519 if type(self.settings[self.settings["spec_prefix"]+\
520 "/linuxrc"])==types.StringType:
521 self.settings["linuxrc"]=\
522 self.settings[self.settings["spec_prefix"]+"/linuxrc"]
523 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
525 def set_portage_overlay(self):
526 if self.settings.has_key("portage_overlay"):
527 if type(self.settings["portage_overlay"])==types.StringType:
528 self.settings["portage_overlay"]=\
529 self.settings["portage_overlay"].split()
530 print "portage_overlay directories are set to: \""+\
531 string.join(self.settings["portage_overlay"])+"\""
533 def set_overlay(self):
534 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
535 if type(self.settings[self.settings["spec_prefix"]+\
536 "/overlay"])==types.StringType:
537 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
538 self.settings[self.settings["spec_prefix"]+\
541 def set_root_overlay(self):
542 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
543 if type(self.settings[self.settings["spec_prefix"]+\
544 "/root_overlay"])==types.StringType:
545 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
546 self.settings[self.settings["spec_prefix"]+\
547 "/root_overlay"].split()
549 def set_root_path(self):
550 """ ROOT= variable for emerges """
551 self.settings["root_path"]="/"
553 def set_valid_build_kernel_vars(self,addlargs):
554 if addlargs.has_key("boot/kernel"):
555 if type(addlargs["boot/kernel"])==types.StringType:
556 loopy=[addlargs["boot/kernel"]]
558 loopy=addlargs["boot/kernel"]
561 self.valid_values.append("boot/kernel/"+x+"/aliases")
562 self.valid_values.append("boot/kernel/"+x+"/config")
563 self.valid_values.append("boot/kernel/"+x+"/console")
564 self.valid_values.append("boot/kernel/"+x+"/extraversion")
565 self.valid_values.append("boot/kernel/"+x+"/gk_action")
566 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
567 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
568 self.valid_values.append("boot/kernel/"+x+"/machine_type")
569 self.valid_values.append("boot/kernel/"+x+"/sources")
570 self.valid_values.append("boot/kernel/"+x+"/softlevel")
571 self.valid_values.append("boot/kernel/"+x+"/use")
572 self.valid_values.append("boot/kernel/"+x+"/packages")
573 if addlargs.has_key("boot/kernel/"+x+"/packages"):
574 if type(addlargs["boot/kernel/"+x+\
575 "/packages"])==types.StringType:
576 addlargs["boot/kernel/"+x+"/packages"]=\
577 [addlargs["boot/kernel/"+x+"/packages"]]
578 # TODO: remove this warning/code with the next major version
579 self.valid_values.append("boot/kernel/"+x+"/postconf")
580 if addlargs.has_key("boot/kernel/"+x+"/postconf"):
581 print "boot/kernel/"+x+"/postconf is deprecated"
582 print "\tInternally moving these ebuilds to boot/kernel/"+\
584 print "\tPlease move them to boot/kernel/"+x+\
585 "/packages in your specfile"
586 if type(addlargs["boot/kernel/"+x+\
587 "/postconf"])==types.StringType:
588 loop2=[addlargs["boot/kernel/"+x+"/postconf"]]
590 loop2=addlargs["boot/kernel/"+x+"/postconf"]
593 if not addlargs.has_key("boot/kernel/"+x+"/packages"):
594 addlargs["boot/kernel/"+x+"/packages"]=[y]
596 addlargs["boot/kernel/"+x+"/packages"].append(y)
598 def set_build_kernel_vars(self):
599 if self.settings.has_key(self.settings["spec_prefix"]+"/devmanager"):
600 # TODO: remove this warning/code with the next major version
601 print self.settings["spec_prefix"]+\
602 "/devmanager is deprecated and will be removed."
603 self.settings["devmanager"]=\
604 self.settings[self.settings["spec_prefix"]+"/devmanager"]
605 del self.settings[self.settings["spec_prefix"]+"/devmanager"]
607 if self.settings.has_key(self.settings["spec_prefix"]+"/splashtype"):
608 # TODO: remove this warning/code with the next major version
609 print self.settings["spec_prefix"]+\
610 "/splashtype is deprecated and will be removed."
611 self.settings["splashtype"]=\
612 self.settings[self.settings["spec_prefix"]+"/splashtype"]
613 del self.settings[self.settings["spec_prefix"]+"/splashtype"]
615 if self.settings.has_key(self.settings["spec_prefix"]+"/gk_mainargs"):
616 self.settings["gk_mainargs"]=\
617 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
618 del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
620 def kill_chroot_pids(self):
621 print "Checking for processes running in chroot and killing them."
624 Force environment variables to be exported so script can see them
626 self.setup_environment()
628 if os.path.exists(self.settings["sharedir"]+\
629 "/targets/support/kill-chroot-pids.sh"):
630 cmd("/bin/bash "+self.settings["sharedir"]+\
631 "/targets/support/kill-chroot-pids.sh",\
632 "kill-chroot-pids script failed.",env=self.env)
634 def mount_safety_check(self):
635 mypath=self.settings["chroot_path"]
638 Check and verify that none of our paths in mypath are mounted. We don't
639 want to clean up with things still mounted, and this allows us to check.
640 Returns 1 on ok, 0 on "something is still mounted" case.
643 if not os.path.exists(mypath):
646 for x in self.mounts:
647 if not os.path.exists(mypath+x):
650 if ismount(mypath+x):
651 """ Something is still mounted "" """
653 print x+" is still mounted; performing auto-bind-umount...",
654 """ Try to umount stuff ourselves """
656 if ismount(mypath+x):
657 raise CatalystError, "Auto-unbind failed for "+x
659 print "Auto-unbind successful..."
660 except CatalystError:
661 raise CatalystError, "Unable to auto-unbind "+x
666 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
669 if self.settings.has_key("SEEDCACHE"):
670 if os.path.isdir(self.settings["source_path"]):
671 """ SEEDCACHE Is a directory, use rsync """
672 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
673 " "+self.settings["chroot_path"]
674 display_msg="\nStarting rsync from "+\
675 self.settings["source_path"]+"\nto "+\
676 self.settings["chroot_path"]+\
677 " (This may take some time) ...\n"
678 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
679 self.settings["chroot_path"]+" failed."
681 """ SEEDCACHE is a not a directory, try untar'ing """
682 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
683 display_msg="\nStarting tar extract from "+\
684 self.settings["source_path"]+"\nto "+\
685 self.settings["chroot_path"]+\
686 " (This may take some time) ...\n"
687 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
688 self.settings["chroot_path"]
689 error_msg="Tarball extraction of "+\
690 self.settings["source_path"]+" to "+\
691 self.settings["chroot_path"]+" failed."
693 """ No SEEDCACHE, use tar """
694 display_msg="\nStarting tar extract from "+\
695 self.settings["source_path"]+"\nto "+\
696 self.settings["chroot_path"]+\
697 " (This may take some time) ...\n"
698 unpack_cmd="tar xjpf "+self.settings["source_path"]+" -C "+\
699 self.settings["chroot_path"]
700 error_msg="Tarball extraction of "+self.settings["source_path"]+\
701 " to "+self.settings["chroot_path"]+" failed."
703 if self.settings.has_key("AUTORESUME"):
704 if os.path.isdir(self.settings["source_path"]) \
705 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
706 """ Autoresume is valid, SEEDCACHE is valid """
708 invalid_snapshot=False
710 elif os.path.isfile(self.settings["source_path"]) \
711 and self.settings["source_path_hash"]==clst_unpack_hash:
712 """ Autoresume is valid, tarball is valid """
714 invalid_snapshot=True
716 elif os.path.isdir(self.settings["source_path"]) \
717 and not os.path.exists(self.settings["autoresume_path"]+\
719 """ Autoresume is invalid, SEEDCACHE """
721 invalid_snapshot=False
723 elif os.path.isfile(self.settings["source_path"]) \
724 and self.settings["source_path_hash"]!=clst_unpack_hash:
725 """ Autoresume is invalid, tarball """
727 invalid_snapshot=True
729 """ No autoresume, SEEDCACHE """
730 if self.settings.has_key("SEEDCACHE"):
731 """ SEEDCACHE so let's run rsync and let it clean up """
732 if os.path.isdir(self.settings["source_path"]):
734 invalid_snapshot=False
735 elif os.path.isfile(self.settings["source_path"]):
736 """ Tarball so unpack and remove anything already there """
738 invalid_snapshot=True
739 """ No autoresume, no SEEDCACHE """
741 """ Tarball so unpack and remove anything already there """
742 if os.path.isfile(self.settings["source_path"]):
744 invalid_snapshot=True
745 elif os.path.isdir(self.settings["source_path"]):
746 """ We should never reach this, so something is very wrong """
747 raise CatalystError,\
748 "source path is a dir but seedcache is not enabled"
751 self.mount_safety_check()
754 if self.settings.has_key("AUTORESUME"):
755 print "No Valid Resume point detected, cleaning up..."
757 self.clear_autoresume()
760 if not os.path.exists(self.settings["chroot_path"]):
761 os.makedirs(self.settings["chroot_path"])
763 if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
764 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
766 if self.settings.has_key("PKGCACHE"):
767 if not os.path.exists(self.settings["pkgcache_path"]):
768 os.makedirs(self.settings["pkgcache_path"],0755)
770 if self.settings.has_key("KERNCACHE"):
771 if not os.path.exists(self.settings["kerncache_path"]):
772 os.makedirs(self.settings["kerncache_path"],0755)
775 cmd(unpack_cmd,error_msg,env=self.env)
777 if self.settings.has_key("source_path_hash"):
778 myf=open(self.settings["autoresume_path"]+"unpack","w")
779 myf.write(self.settings["source_path_hash"])
782 touch(self.settings["autoresume_path"]+"unpack")
784 print "Resume point detected, skipping unpack operation..."
786 def unpack_snapshot(self):
788 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
791 if self.settings.has_key("SNAPCACHE"):
792 snapshot_cache_hash=\
793 read_from_clst(self.settings["snapshot_cache_path"]+\
795 destdir=self.settings["snapshot_cache_path"]
796 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+destdir
797 unpack_errmsg="Error unpacking snapshot"
798 cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
799 self.settings["snapshot_cache_path"]+\
800 " (This can take a long time)..."
801 cleanup_errmsg="Error removing existing snapshot cache directory."
802 self.snapshot_lock_object=self.snapcache_lock
804 if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
805 print "Valid snapshot cache, skipping unpack of portage tree..."
808 destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
809 cleanup_errmsg="Error removing existing snapshot directory."
811 "Cleaning up existing portage tree (This can take a long time)..."
812 unpack_cmd="tar xjpf "+self.settings["snapshot_path"]+" -C "+\
813 self.settings["chroot_path"]+"/usr"
814 unpack_errmsg="Error unpacking snapshot"
816 if self.settings.has_key("AUTORESUME") \
817 and os.path.exists(self.settings["chroot_path"]+\
819 and os.path.exists(self.settings["autoresume_path"]\
821 and self.settings["snapshot_path_hash"] == snapshot_hash:
823 "Valid Resume point detected, skipping unpack of portage tree..."
827 if self.settings.has_key("SNAPCACHE"):
828 self.snapshot_lock_object.write_lock()
829 if os.path.exists(destdir):
831 cleanup_cmd="rm -rf "+destdir
832 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
833 if not os.path.exists(destdir):
834 os.makedirs(destdir,0755)
836 print "Unpacking portage tree (This can take a long time) ..."
837 cmd(unpack_cmd,unpack_errmsg,env=self.env)
839 if self.settings.has_key("SNAPCACHE"):
840 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
841 myf.write(self.settings["snapshot_path_hash"])
844 print "Setting snapshot autoresume point"
845 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
846 myf.write(self.settings["snapshot_path_hash"])
849 if self.settings.has_key("SNAPCACHE"):
850 self.snapshot_lock_object.unlock()
852 def config_profile_link(self):
853 if self.settings.has_key("AUTORESUME") \
854 and os.path.exists(self.settings["autoresume_path"]+\
855 "config_profile_link"):
857 "Resume point detected, skipping config_profile_link operation..."
859 # TODO: zmedico and I discussed making this a directory and pushing
860 # in a parent file, as well as other user-specified configuration.
861 print "Configuring profile link..."
862 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.profile",\
863 "Error zapping profile link",env=self.env)
864 cmd("ln -sf ../usr/portage/profiles/"+\
865 self.settings["target_profile"]+" "+\
866 self.settings["chroot_path"]+"/etc/make.profile",\
867 "Error creating profile link",env=self.env)
868 touch(self.settings["autoresume_path"]+"config_profile_link")
870 def setup_confdir(self):
871 if self.settings.has_key("AUTORESUME") \
872 and os.path.exists(self.settings["autoresume_path"]+\
874 print "Resume point detected, skipping setup_confdir operation..."
876 if self.settings.has_key("portage_confdir"):
877 print "Configuring /etc/portage..."
878 cmd("rm -rf "+self.settings["chroot_path"]+"/etc/portage",\
879 "Error zapping /etc/portage",env=self.env)
880 cmd("cp -R "+self.settings["portage_confdir"]+"/ "+\
881 self.settings["chroot_path"]+"/etc/portage",\
882 "Error copying /etc/portage",env=self.env)
883 touch(self.settings["autoresume_path"]+"setup_confdir")
885 def portage_overlay(self):
886 """ We copy the contents of our overlays to /usr/local/portage """
887 if self.settings.has_key("portage_overlay"):
888 for x in self.settings["portage_overlay"]:
889 if os.path.exists(x):
890 print "Copying overlay dir " +x
891 cmd("mkdir -p "+self.settings["chroot_path"]+\
892 "/usr/local/portage",\
893 "Could not make portage_overlay dir",env=self.env)
894 cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
895 "/usr/local/portage",\
896 "Could not copy portage_overlay",env=self.env)
898 def root_overlay(self):
899 """ Copy over the root_overlay """
900 if self.settings.has_key(self.settings["spec_prefix"]+"/root_overlay"):
901 for x in self.settings[self.settings["spec_prefix"]+\
903 if os.path.exists(x):
904 print "Copying root_overlay: "+x
905 cmd("rsync -a "+x+"/ "+\
906 self.settings["chroot_path"],\
907 self.settings["spec_prefix"]+"/root_overlay: "+x+\
908 " copy failed.",env=self.env)
914 for x in self.mounts:
915 if not os.path.exists(self.settings["chroot_path"]+x):
916 os.makedirs(self.settings["chroot_path"]+x,0755)
918 if not os.path.exists(self.mountmap[x]):
919 os.makedirs(self.mountmap[x],0755)
922 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
923 self.snapshot_lock_object.read_lock()
924 if os.uname()[0] == "FreeBSD":
926 retval=os.system("mount -t devfs none "+\
927 self.settings["chroot_path"]+x)
929 retval=os.system("mount_nullfs "+src+" "+\
930 self.settings["chroot_path"]+x)
932 retval=os.system("mount --bind "+src+" "+\
933 self.settings["chroot_path"]+x)
936 raise CatalystError,"Couldn't bind mount "+src
940 mypath=self.settings["chroot_path"]
941 myrevmounts=self.mounts[:]
942 myrevmounts.reverse()
943 """ Unmount in reverse order for nested bind-mounts """
944 for x in myrevmounts:
945 if not os.path.exists(mypath+x):
948 if not ismount(mypath+x):
951 retval=os.system("umount "+\
952 os.path.join(mypath,x.lstrip(os.path.sep)))
955 warn("First attempt to unmount: "+mypath+x+" failed.")
956 warn("Killing any pids still running in the chroot")
958 self.kill_chroot_pids()
960 retval2=os.system("umount "+mypath+x)
963 warn("Couldn't umount bind mount: "+mypath+x)
965 if self.settings.has_key("SNAPCACHE") and x == "/usr/portage":
968 It's possible the snapshot lock object isn't created yet.
969 This is because mount safety check calls unbind before the
970 target is fully initialized
972 self.snapshot_lock_object.unlock()
977 if any bind mounts really failed, then we need to raise
978 this to potentially prevent an upcoming bash stage cleanup script
979 from wiping our bind mounts.
981 raise CatalystError,\
982 "Couldn't umount one or more bind-mounts; aborting for safety."
984 def chroot_setup(self):
985 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
987 self.override_cbuild()
988 self.override_chost()
989 self.override_cflags()
990 self.override_cxxflags()
991 self.override_ldflags()
992 if self.settings.has_key("AUTORESUME") \
993 and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
994 print "Resume point detected, skipping chroot_setup operation..."
996 print "Setting up chroot..."
998 #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/make.conf")
1000 cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1001 "Could not copy resolv.conf into place.",env=self.env)
1003 """ Copy over the envscript, if applicable """
1004 if self.settings.has_key("ENVSCRIPT"):
1005 if not os.path.exists(self.settings["ENVSCRIPT"]):
1006 raise CatalystError,\
1007 "Can't find envscript "+self.settings["ENVSCRIPT"]
1009 print "\nWarning!!!!"
1010 print "\tOverriding certain env variables may cause catastrophic failure."
1011 print "\tIf your build fails look here first as the possible problem."
1012 print "\tCatalyst assumes you know what you are doing when setting"
1013 print "\t\tthese variables."
1014 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1015 print "\tYou have been warned\n"
1017 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1018 self.settings["chroot_path"]+"/tmp/envscript",\
1019 "Could not copy envscript into place.",env=self.env)
1021 """ Setup metadata_overlay """
1022 if self.settings.has_key("METADATA_OVERLAY") \
1023 and not self.settings.has_key("portage_confdir"):
1024 if not os.path.exists(self.settings["chroot_path"]+\
1026 cmd("mkdir "+self.settings["chroot_path"]+"/etc/portage")
1027 myf=open(self.settings["chroot_path"]+\
1028 "/etc/portage/modules","a")
1029 myf.write("portdbapi.auxdbmodule = cache.metadata_overlay.database\n")
1034 Copy over /etc/hosts from the host in case there are any
1035 specialties in there
1037 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1038 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1039 self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1040 "Could not backup /etc/hosts",env=self.env)
1041 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1042 "Could not copy /etc/hosts",env=self.env)
1044 """ Modify and write out make.conf (for the chroot) """
1045 cmd("rm -f "+self.settings["chroot_path"]+"/etc/make.conf",\
1046 "Could not remove "+self.settings["chroot_path"]+\
1047 "/etc/make.conf",env=self.env)
1048 myf=open(self.settings["chroot_path"]+"/etc/make.conf","w")
1049 myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1050 myf.write("# Please consult /etc/make.conf.example for a more detailed example.\n")
1051 if self.settings.has_key("CFLAGS"):
1052 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1053 if self.settings.has_key("CXXFLAGS"):
1054 myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1056 myf.write('CXXFLAGS="${CFLAGS}"\n')
1058 if self.settings.has_key("LDFLAGS"):
1059 myf.write("# LDFLAGS is unsupported. USE AT YOUR OWN RISK!\n")
1060 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1061 if self.settings.has_key("CBUILD"):
1062 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")
1063 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1065 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")
1066 myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1068 """ Figure out what our USE vars are for building """
1070 if self.settings.has_key("HOSTUSE"):
1071 myusevars.extend(self.settings["HOSTUSE"])
1073 if self.settings.has_key("use"):
1074 myusevars.extend(self.settings["use"])
1077 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1078 myusevars = sorted(set(myusevars))
1079 myf.write('USE="'+string.join(myusevars)+'"\n')
1080 if '-*' in myusevars:
1081 print "\nWarning!!! "
1082 print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1083 "/use will cause portage to ignore"
1084 print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1086 """ Setup the portage overlay """
1087 if self.settings.has_key("portage_overlay"):
1088 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1091 cmd("cp "+self.settings["chroot_path"]+"/etc/make.conf "+\
1092 self.settings["chroot_path"]+"/etc/make.conf.catalyst",\
1093 "Could not backup /etc/make.conf",env=self.env)
1094 touch(self.settings["autoresume_path"]+"chroot_setup")
1097 if self.settings.has_key("AUTORESUME") \
1098 and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1099 print "Resume point detected, skipping fsscript operation..."
1101 if self.settings.has_key("fsscript"):
1102 if os.path.exists(self.settings["controller_file"]):
1103 cmd("/bin/bash "+self.settings["controller_file"]+\
1104 " fsscript","fsscript script failed.",env=self.env)
1105 touch(self.settings["autoresume_path"]+"fsscript")
1108 if self.settings.has_key("AUTORESUME") \
1109 and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1110 print "Resume point detected, skipping rcupdate operation..."
1112 if os.path.exists(self.settings["controller_file"]):
1113 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1114 "rc-update script failed.",env=self.env)
1115 touch(self.settings["autoresume_path"]+"rcupdate")
1118 if self.settings.has_key("AUTORESUME") \
1119 and os.path.exists(self.settings["autoresume_path"]+"clean"):
1120 print "Resume point detected, skipping clean operation..."
1122 for x in self.settings["cleanables"]:
1123 print "Cleaning chroot: "+x+"... "
1124 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1127 """ Put /etc/hosts back into place """
1128 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1129 cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1130 self.settings["chroot_path"]+"/etc/hosts",\
1131 "Could not replace /etc/hosts",env=self.env)
1133 """ Remove our overlay """
1134 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1135 cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1136 "Could not remove /usr/local/portage",env=self.env)
1137 cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1139 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1141 """ Clean up old and obsoleted files in /etc """
1142 if os.path.exists(self.settings["stage_path"]+"/etc"):
1143 cmd("find "+self.settings["stage_path"]+\
1144 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1145 "Could not remove stray files in /etc",env=self.env)
1147 if os.path.exists(self.settings["controller_file"]):
1148 cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1149 "clean script failed.",env=self.env)
1150 touch(self.settings["autoresume_path"]+"clean")
1153 if self.settings.has_key("AUTORESUME") \
1154 and os.path.exists(self.settings["autoresume_path"]+"empty"):
1155 print "Resume point detected, skipping empty operation..."
1157 if self.settings.has_key(self.settings["spec_prefix"]+"/empty"):
1158 if type(self.settings[self.settings["spec_prefix"]+\
1159 "/empty"])==types.StringType:
1160 self.settings[self.settings["spec_prefix"]+"/empty"]=\
1161 self.settings[self.settings["spec_prefix"]+\
1163 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1164 myemp=self.settings["destpath"]+x
1165 if not os.path.isdir(myemp):
1166 print x,"not a directory or does not exist, skipping 'empty' operation."
1168 print "Emptying directory",x
1170 stat the dir, delete the dir, recreate the dir and set
1171 the proper perms and ownership
1173 mystat=os.stat(myemp)
1174 shutil.rmtree(myemp)
1175 os.makedirs(myemp,0755)
1176 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1177 os.chmod(myemp,mystat[ST_MODE])
1178 touch(self.settings["autoresume_path"]+"empty")
1181 if self.settings.has_key("AUTORESUME") \
1182 and os.path.exists(self.settings["autoresume_path"]+"remove"):
1183 print "Resume point detected, skipping remove operation..."
1185 if self.settings.has_key(self.settings["spec_prefix"]+"/rm"):
1186 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1188 We're going to shell out for all these cleaning
1189 operations, so we get easy glob handling.
1191 print "livecd: removing "+x
1192 os.system("rm -rf "+self.settings["chroot_path"]+x)
1194 if os.path.exists(self.settings["controller_file"]):
1195 cmd("/bin/bash "+self.settings["controller_file"]+\
1196 " clean","Clean failed.",env=self.env)
1197 touch(self.settings["autoresume_path"]+"remove")
1203 if self.settings.has_key("AUTORESUME") \
1204 and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1205 print "Resume point detected, skipping preclean operation..."
1208 if os.path.exists(self.settings["controller_file"]):
1209 cmd("/bin/bash "+self.settings["controller_file"]+\
1210 " preclean","preclean script failed.",env=self.env)
1211 touch(self.settings["autoresume_path"]+"preclean")
1215 raise CatalystError, "Build failed, could not execute preclean"
1218 if self.settings.has_key("AUTORESUME") \
1219 and os.path.exists(self.settings["autoresume_path"]+"capture"):
1220 print "Resume point detected, skipping capture operation..."
1222 """ Capture target in a tarball """
1223 mypath=self.settings["target_path"].split("/")
1224 """ Remove filename from path """
1225 mypath=string.join(mypath[:-1],"/")
1227 """ Now make sure path exists """
1228 if not os.path.exists(mypath):
1231 print "Creating stage tarball..."
1233 cmd("tar cjpf "+self.settings["target_path"]+" -C "+\
1234 self.settings["stage_path"]+" .",\
1235 "Couldn't create stage tarball",env=self.env)
1237 self.gen_contents_file(self.settings["target_path"])
1238 self.gen_digest_file(self.settings["target_path"])
1240 touch(self.settings["autoresume_path"]+"capture")
1242 def run_local(self):
1243 if self.settings.has_key("AUTORESUME") \
1244 and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1245 print "Resume point detected, skipping run_local operation..."
1248 if os.path.exists(self.settings["controller_file"]):
1249 cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1250 "run script failed.",env=self.env)
1251 touch(self.settings["autoresume_path"]+"run_local")
1253 except CatalystError:
1255 raise CatalystError,"Stage build aborting due to error."
1257 def setup_environment(self):
1259 Modify the current environment. This is an ugly hack that should be
1260 fixed. We need this to use the os.system() call since we can't
1261 specify our own environ
1263 for x in self.settings.keys():
1264 """ Sanitize var names by doing "s|/-.|_|g" """
1265 varname="clst_"+string.replace(x,"/","_")
1266 varname=string.replace(varname,"-","_")
1267 varname=string.replace(varname,".","_")
1268 if type(self.settings[x])==types.StringType:
1269 """ Prefix to prevent namespace clashes """
1270 #os.environ[varname]=self.settings[x]
1271 self.env[varname]=self.settings[x]
1272 elif type(self.settings[x])==types.ListType:
1273 #os.environ[varname]=string.join(self.settings[x])
1274 self.env[varname]=string.join(self.settings[x])
1275 elif type(self.settings[x])==types.BooleanType:
1276 if self.settings[x]:
1277 self.env[varname]="true"
1279 self.env[varname]="false"
1280 if self.settings.has_key("makeopts"):
1281 self.env["MAKEOPTS"]=self.settings["makeopts"]
1284 self.chroot_lock.write_lock()
1286 """ Kill any pids in the chroot "" """
1287 self.kill_chroot_pids()
1289 """ Check for mounts right away and abort if we cannot unmount them """
1290 self.mount_safety_check()
1292 if self.settings.has_key("CLEAR_AUTORESUME"):
1293 self.clear_autoresume()
1294 if self.settings.has_key("PURGE"):
1297 for x in self.settings["action_sequence"]:
1298 print "--- Running action sequence: "+x
1301 apply(getattr(self,x))
1303 self.mount_safety_check()
1306 self.chroot_lock.unlock()
1309 if self.settings.has_key("AUTORESUME") \
1310 and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1311 print "Resume point detected, skipping unmerge operation..."
1313 if self.settings.has_key(self.settings["spec_prefix"]+"/unmerge"):
1314 if type(self.settings[self.settings["spec_prefix"]+\
1315 "/unmerge"])==types.StringType:
1316 self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1317 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1319 self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1321 for x in range(0,len(myunmerge)):
1323 Surround args with quotes for passing to bash, allows
1324 things like "<" to remain intact
1326 myunmerge[x]="'"+myunmerge[x]+"'"
1327 myunmerge=string.join(myunmerge)
1329 """ Before cleaning, unmerge stuff """
1331 cmd("/bin/bash "+self.settings["controller_file"]+\
1332 " unmerge "+ myunmerge,"Unmerge script failed.",\
1334 print "unmerge shell script"
1335 except CatalystError:
1338 touch(self.settings["autoresume_path"]+"unmerge")
1340 def target_setup(self):
1341 if self.settings.has_key("AUTORESUME") \
1342 and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1343 print "Resume point detected, skipping target_setup operation..."
1345 print "Setting up filesystems per filesystem type"
1346 cmd("/bin/bash "+self.settings["controller_file"]+\
1347 " target_image_setup "+ self.settings["target_path"],\
1348 "target_image_setup script failed.",env=self.env)
1349 touch(self.settings["autoresume_path"]+"target_setup")
1351 def setup_overlay(self):
1352 if self.settings.has_key("AUTORESUME") \
1353 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1354 print "Resume point detected, skipping setup_overlay operation..."
1356 if self.settings.has_key(self.settings["spec_prefix"]+"/overlay"):
1357 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1358 if os.path.exists(x):
1359 cmd("rsync -a "+x+"/ "+\
1360 self.settings["target_path"],\
1361 self.settings["spec_prefix"]+"overlay: "+x+\
1362 " copy failed.",env=self.env)
1363 touch(self.settings["autoresume_path"]+"setup_overlay")
1365 def create_iso(self):
1366 if self.settings.has_key("AUTORESUME") \
1367 and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1368 print "Resume point detected, skipping create_iso operation..."
1370 """ Create the ISO """
1371 if self.settings.has_key("iso"):
1372 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1373 self.settings["iso"],"ISO creation script failed.",\
1375 self.gen_contents_file(self.settings["iso"])
1376 self.gen_digest_file(self.settings["iso"])
1377 touch(self.settings["autoresume_path"]+"create_iso")
1379 print "WARNING: livecd/iso was not defined."
1380 print "An ISO Image will not be created."
1382 def build_packages(self):
1383 if self.settings.has_key("AUTORESUME") \
1384 and os.path.exists(self.settings["autoresume_path"]+\
1386 print "Resume point detected, skipping build_packages operation..."
1388 if self.settings.has_key(self.settings["spec_prefix"]+"/packages"):
1389 if self.settings.has_key("AUTORESUME") \
1390 and os.path.exists(self.settings["autoresume_path"]+\
1392 print "Resume point detected, skipping build_packages operation..."
1395 list_bashify(self.settings[self.settings["spec_prefix"]\
1398 cmd("/bin/bash "+self.settings["controller_file"]+\
1399 " build_packages "+mypack,\
1400 "Error in attempt to build packages",env=self.env)
1401 touch(self.settings["autoresume_path"]+"build_packages")
1402 except CatalystError:
1404 raise CatalystError,self.settings["spec_prefix"]+\
1405 "build aborting due to error."
1407 def build_kernel(self):
1408 if self.settings.has_key("AUTORESUME") \
1409 and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1410 print "Resume point detected, skipping build_kernel operation..."
1412 if self.settings.has_key("boot/kernel"):
1414 mynames=self.settings["boot/kernel"]
1415 if type(mynames)==types.StringType:
1418 Execute the script that sets up the kernel build environment
1420 cmd("/bin/bash "+self.settings["controller_file"]+\
1421 " pre-kmerge ","Runscript pre-kmerge failed",\
1424 for kname in mynames:
1425 if self.settings.has_key("AUTORESUME") \
1426 and os.path.exists(self.settings["autoresume_path"]\
1427 +"build_kernel_"+kname):
1428 print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1429 else: # TODO: make this not require a kernel config
1431 if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1433 raise CatalystError,\
1434 "Can't find kernel config: "+\
1435 self.settings["boot/kernel/"+kname+\
1439 raise CatalystError,\
1440 "Required value boot/kernel/config not specified"
1443 cmd("cp "+self.settings["boot/kernel/"+kname+\
1445 self.settings["chroot_path"]+"/var/tmp/"+\
1447 "Couldn't copy kernel config: "+\
1448 self.settings["boot/kernel/"+kname+\
1449 "/config"],env=self.env)
1451 except CatalystError:
1455 If we need to pass special options to the bootloader
1456 for this kernel put them into the environment
1458 if self.settings.has_key("boot/kernel/"+kname+\
1460 myopts=self.settings["boot/kernel/"+kname+\
1463 if type(myopts) != types.StringType:
1464 myopts = string.join(myopts)
1465 self.env[kname+"_kernelopts"]=myopts
1468 self.env[kname+"_kernelopts"]=""
1470 if not self.settings.has_key("boot/kernel/"+kname+\
1472 self.settings["boot/kernel/"+kname+\
1475 self.env["clst_kextraversion"]=\
1476 self.settings["boot/kernel/"+kname+\
1479 if self.settings.has_key("boot/kernel/"+kname+\
1480 "/initramfs_overlay"):
1481 if os.path.exists(self.settings["boot/kernel/"+\
1482 kname+"/initramfs_overlay"]):
1483 print "Copying initramfs_overlay dir "+\
1484 self.settings["boot/kernel/"+kname+\
1485 "/initramfs_overlay"]
1488 self.settings["chroot_path"]+\
1489 "/tmp/initramfs_overlay/"+\
1490 self.settings["boot/kernel/"+kname+\
1491 "/initramfs_overlay"],env=self.env)
1493 cmd("cp -R "+self.settings["boot/kernel/"+\
1494 kname+"/initramfs_overlay"]+"/* "+\
1495 self.settings["chroot_path"]+\
1496 "/tmp/initramfs_overlay/"+\
1497 self.settings["boot/kernel/"+kname+\
1498 "/initramfs_overlay"],env=self.env)
1500 """ Execute the script that builds the kernel """
1501 cmd("/bin/bash "+self.settings["controller_file"]+\
1503 "Runscript kernel build failed",env=self.env)
1505 if self.settings.has_key("boot/kernel/"+kname+\
1506 "/initramfs_overlay"):
1507 if os.path.exists(self.settings["chroot_path"]+\
1508 "/tmp/initramfs_overlay/"):
1509 print "Cleaning up temporary overlay dir"
1510 cmd("rm -R "+self.settings["chroot_path"]+\
1511 "/tmp/initramfs_overlay/",env=self.env)
1513 touch(self.settings["autoresume_path"]+\
1514 "build_kernel_"+kname)
1517 Execute the script that cleans up the kernel build
1520 cmd("/bin/bash "+self.settings["controller_file"]+\
1522 "Runscript post-kmerge failed",env=self.env)
1524 touch(self.settings["autoresume_path"]+"build_kernel")
1526 except CatalystError:
1528 raise CatalystError,\
1529 "build aborting due to kernel build error."
1531 def bootloader(self):
1532 if self.settings.has_key("AUTORESUME") \
1533 and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1534 print "Resume point detected, skipping bootloader operation..."
1537 cmd("/bin/bash "+self.settings["controller_file"]+\
1538 " bootloader " + self.settings["target_path"],\
1539 "Bootloader runscript failed.",env=self.env)
1540 touch(self.settings["autoresume_path"]+"bootloader")
1541 except CatalystError:
1543 raise CatalystError,"Runscript aborting due to error."
1545 def livecd_update(self):
1546 if self.settings.has_key("AUTORESUME") \
1547 and os.path.exists(self.settings["autoresume_path"]+\
1549 print "Resume point detected, skipping build_packages operation..."
1552 cmd("/bin/bash "+self.settings["controller_file"]+\
1553 " livecd-update","livecd-update failed.",env=self.env)
1554 touch(self.settings["autoresume_path"]+"livecd_update")
1556 except CatalystError:
1558 raise CatalystError,"build aborting due to livecd_update error."
1560 def clear_chroot(self):
1561 myemp=self.settings["chroot_path"]
1562 if os.path.isdir(myemp):
1563 print "Emptying directory",myemp
1565 stat the dir, delete the dir, recreate the dir and set
1566 the proper perms and ownership
1568 mystat=os.stat(myemp)
1569 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1570 """ There's no easy way to change flags recursively in python """
1571 if os.uname()[0] == "FreeBSD":
1572 os.system("chflags -R noschg "+myemp)
1573 shutil.rmtree(myemp)
1574 os.makedirs(myemp,0755)
1575 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1576 os.chmod(myemp,mystat[ST_MODE])
1578 def clear_packages(self):
1579 if self.settings.has_key("PKGCACHE"):
1580 print "purging the pkgcache ..."
1582 myemp=self.settings["pkgcache_path"]
1583 if os.path.isdir(myemp):
1584 print "Emptying directory",myemp
1586 stat the dir, delete the dir, recreate the dir and set
1587 the proper perms and ownership
1589 mystat=os.stat(myemp)
1590 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1591 shutil.rmtree(myemp)
1592 os.makedirs(myemp,0755)
1593 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1594 os.chmod(myemp,mystat[ST_MODE])
1596 def clear_kerncache(self):
1597 if self.settings.has_key("KERNCACHE"):
1598 print "purging the kerncache ..."
1600 myemp=self.settings["kerncache_path"]
1601 if os.path.isdir(myemp):
1602 print "Emptying directory",myemp
1604 stat the dir, delete the dir, recreate the dir and set
1605 the proper perms and ownership
1607 mystat=os.stat(myemp)
1608 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1609 shutil.rmtree(myemp)
1610 os.makedirs(myemp,0755)
1611 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1612 os.chmod(myemp,mystat[ST_MODE])
1614 def clear_autoresume(self):
1615 """ Clean resume points since they are no longer needed """
1616 if self.settings.has_key("AUTORESUME"):
1617 print "Removing AutoResume Points: ..."
1618 myemp=self.settings["autoresume_path"]
1619 if os.path.isdir(myemp):
1620 if self.settings.has_key("AUTORESUME"):
1621 print "Emptying directory",myemp
1623 stat the dir, delete the dir, recreate the dir and set
1624 the proper perms and ownership
1626 mystat=os.stat(myemp)
1627 if os.uname()[0] == "FreeBSD":
1628 cmd("chflags -R noschg "+myemp,\
1629 "Could not remove immutable flag for file "\
1631 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1632 shutil.rmtree(myemp)
1633 os.makedirs(myemp,0755)
1634 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1635 os.chmod(myemp,mystat[ST_MODE])
1637 def gen_contents_file(self,file):
1638 if os.path.exists(file+".CONTENTS"):
1639 os.remove(file+".CONTENTS")
1640 if self.settings.has_key("contents"):
1641 if os.path.exists(file):
1642 myf=open(file+".CONTENTS","w")
1644 for i in self.settings["contents"].split():
1649 contents=generate_contents(file,contents_function=j,\
1650 verbose=self.settings.has_key("VERBOSE"))
1655 def gen_digest_file(self,file):
1656 if os.path.exists(file+".DIGESTS"):
1657 os.remove(file+".DIGESTS")
1658 if self.settings.has_key("digests"):
1659 if os.path.exists(file):
1660 myf=open(file+".DIGESTS","w")
1662 for i in self.settings["digests"].split():
1666 for f in [file, file+'.CONTENTS']:
1667 if os.path.exists(f):
1669 hash=generate_hash(f,hash_function=j,verbose=\
1670 self.settings.has_key("VERBOSE"))
1675 countdown(10,"Purging Caches ...")
1676 if self.settings.has_key("PURGE"):
1677 print "clearing autoresume ..."
1678 self.clear_autoresume()
1680 print "clearing chroot ..."
1683 print "clearing package cache ..."
1684 self.clear_packages()
1686 print "clearing kerncache ..."
1687 self.clear_kerncache()
1689 # vim: ts=4 sw=4 sta et sts=4 ai