790e4da2498466806dbecb26d9422fd064de64c3
[catalyst.git] / modules / generic_stage_target.py
1 import os,string,imp,types,shutil
2 from catalyst_support import *
3 from generic_target import *
4 from stat import *
5 import catalyst_lock
6
7
8 PORT_LOGDIR_CLEAN = \
9         'find "${PORT_LOGDIR}" -type f ! -name "summary.log*" -mtime +30 -delete'
10
11 TARGET_MOUNTS_DEFAULTS = {
12         "ccache": "/var/tmp/ccache",
13         "dev": "/dev",
14         "devpts": "/dev/pts",
15         "distdir": "/usr/portage/distfiles",
16         "icecream": "/usr/lib/icecc/bin",
17         "kerncache": "/tmp/kerncache",
18         "packagedir": "/usr/portage/packages",
19         "portdir": "/usr/portage",
20         "port_tmpdir": "/var/tmp/portage",
21         "port_logdir": "/var/log/portage",
22         "proc": "/proc",
23         }
24
25 SOURCE_MOUNTS_DEFAULTS = {
26         "dev": "/dev",
27         "devpts": "/dev/pts",
28         "distdir": "/usr/portage/distfiles",
29         "portdir": "/usr/portage",
30         "port_tmpdir": "tmpfs",
31         "proc": "/proc",
32         }
33
34
35 class generic_stage_target(generic_target):
36         """
37         This class does all of the chroot setup, copying of files, etc. It is
38         the driver class for pretty much everything that Catalyst does.
39         """
40         def __init__(self,myspec,addlargs):
41                 self.required_values.extend(["version_stamp","target","subarch",\
42                         "rel_type","profile","snapshot","source_subpath"])
43
44                 self.valid_values.extend(["version_stamp","target","subarch",\
45                         "rel_type","profile","snapshot","source_subpath","portage_confdir",\
46                         "cflags","cxxflags","ldflags","cbuild","hostuse","portage_overlay",\
47                         "distcc_hosts","makeopts","pkgcache_path","kerncache_path"])
48
49                 self.set_valid_build_kernel_vars(addlargs)
50                 generic_target.__init__(self,myspec,addlargs)
51
52                 """
53                 The semantics of subarchmap and machinemap changed a bit in 2.0.3 to
54                 work better with vapier's CBUILD stuff. I've removed the "monolithic"
55                 machinemap from this file and split up its contents amongst the
56                 various arch/foo.py files.
57
58                 When register() is called on each module in the arch/ dir, it now
59                 returns a tuple instead of acting on the subarchmap dict that is
60                 passed to it. The tuple contains the values that were previously
61                 added to subarchmap as well as a new list of CHOSTs that go along
62                 with that arch. This allows us to build machinemap on the fly based
63                 on the keys in subarchmap and the values of the 2nd list returned
64                 (tmpmachinemap).
65
66                 Also, after talking with vapier. I have a slightly better idea of what
67                 certain variables are used for and what they should be set to. Neither
68                 'buildarch' or 'hostarch' are used directly, so their value doesn't
69                 really matter. They are just compared to determine if we are
70                 cross-compiling. Because of this, they are just set to the name of the
71                 module in arch/ that the subarch is part of to make things simpler.
72                 The entire build process is still based off of 'subarch' like it was
73                 previously. -agaffney
74                 """
75
76                 self.archmap = {}
77                 self.subarchmap = {}
78                 machinemap = {}
79                 for x in [x[:-3] for x in os.listdir(self.settings["sharedir"]+\
80                         "/arch/") if x.endswith(".py")]:
81                         try:
82                                 fh=open(self.settings["sharedir"]+"/arch/"+x+".py")
83                                 """
84                                 This next line loads the plugin as a module and assigns it to
85                                 archmap[x]
86                                 """
87                                 self.archmap[x]=imp.load_module(x,fh,"arch/"+x+\
88                                         ".py",(".py","r",imp.PY_SOURCE))
89                                 """
90                                 This next line registers all the subarches supported in the
91                                 plugin
92                                 """
93                                 tmpsubarchmap, tmpmachinemap = self.archmap[x].register()
94                                 self.subarchmap.update(tmpsubarchmap)
95                                 for machine in tmpmachinemap:
96                                         machinemap[machine] = x
97                                 for subarch in tmpsubarchmap:
98                                         machinemap[subarch] = x
99                                 fh.close()
100                         except IOError:
101                                 """
102                                 This message should probably change a bit, since everything in
103                                 the dir should load just fine. If it doesn't, it's probably a
104                                 syntax error in the module
105                                 """
106                                 msg("Can't find/load "+x+".py plugin in "+\
107                                         self.settings["sharedir"]+"/arch/")
108
109                 if "chost" in self.settings:
110                         hostmachine = self.settings["chost"].split("-")[0]
111                         if hostmachine not in machinemap:
112                                 raise CatalystError, "Unknown host machine type "+hostmachine
113                         self.settings["hostarch"]=machinemap[hostmachine]
114                 else:
115                         hostmachine = self.settings["subarch"]
116                         if hostmachine in machinemap:
117                                 hostmachine = machinemap[hostmachine]
118                         self.settings["hostarch"]=hostmachine
119                 if "cbuild" in self.settings:
120                         buildmachine = self.settings["cbuild"].split("-")[0]
121                 else:
122                         buildmachine = os.uname()[4]
123                 if buildmachine not in machinemap:
124                         raise CatalystError, "Unknown build machine type "+buildmachine
125                 self.settings["buildarch"]=machinemap[buildmachine]
126                 self.settings["crosscompile"]=(self.settings["hostarch"]!=\
127                         self.settings["buildarch"])
128
129                 """ Call arch constructor, pass our settings """
130                 try:
131                         self.arch=self.subarchmap[self.settings["subarch"]](self.settings)
132                 except KeyError:
133                         print "Invalid subarch: "+self.settings["subarch"]
134                         print "Choose one of the following:",
135                         for x in self.subarchmap:
136                                 print x,
137                         print
138                         sys.exit(2)
139
140                 print "Using target:",self.settings["target"]
141                 """ Print a nice informational message """
142                 if self.settings["buildarch"]==self.settings["hostarch"]:
143                         print "Building natively for",self.settings["hostarch"]
144                 elif self.settings["crosscompile"]:
145                         print "Cross-compiling on",self.settings["buildarch"],\
146                                 "for different machine type",self.settings["hostarch"]
147                 else:
148                         print "Building on",self.settings["buildarch"],\
149                                 "for alternate personality type",self.settings["hostarch"]
150
151                 """ This must be set first as other set_ options depend on this """
152                 self.set_spec_prefix()
153
154                 """ Define all of our core variables """
155                 self.set_target_profile()
156                 self.set_target_subpath()
157                 self.set_source_subpath()
158
159                 """ Set paths """
160                 self.set_snapshot_path()
161                 self.set_root_path()
162                 self.set_source_path()
163                 self.set_snapcache_path()
164                 self.set_chroot_path()
165                 self.set_autoresume_path()
166                 self.set_dest_path()
167                 self.set_stage_path()
168                 self.set_target_path()
169
170                 self.set_controller_file()
171                 self.set_action_sequence()
172                 self.set_use()
173                 self.set_cleanables()
174                 self.set_iso_volume_id()
175                 self.set_build_kernel_vars()
176                 self.set_fsscript()
177                 self.set_install_mask()
178                 self.set_rcadd()
179                 self.set_rcdel()
180                 self.set_cdtar()
181                 self.set_fstype()
182                 self.set_fsops()
183                 self.set_iso()
184                 self.set_packages()
185                 self.set_rm()
186                 self.set_linuxrc()
187                 self.set_busybox_config()
188                 self.set_overlay()
189                 self.set_portage_overlay()
190                 self.set_root_overlay()
191
192                 """
193                 This next line checks to make sure that the specified variables exist
194                 on disk.
195                 """
196                 #pdb.set_trace()
197                 file_locate(self.settings,["source_path","snapshot_path","distdir"],\
198                         expand=0)
199                 """ If we are using portage_confdir, check that as well. """
200                 if "portage_confdir" in self.settings:
201                         file_locate(self.settings,["portage_confdir"],expand=0)
202
203                 """ Setup our mount points """
204                 # initialize our target mounts.
205                 self.target_mounts = TARGET_MOUNTS_DEFAULTS.copy()
206
207                 self.mounts = ["proc", "dev", "portdir", "distdir", "port_tmpdir"]
208                 # initialize our source mounts
209                 self.mountmap = SOURCE_MOUNTS_DEFAULTS.copy()
210                 # update them from settings
211                 self.mountmap["distdir"] = self.settings["distdir"]
212                 self.mountmap["portdir"] = normpath("/".join([
213                         self.settings["snapshot_cache_path"],
214                         self.settings["repo_name"],
215                         ]))
216                 if "SNAPCACHE" not in self.settings:
217                         self.mounts.remove("portdir")
218                         #self.mountmap["portdir"] = None
219                 if os.uname()[0] == "Linux":
220                         self.mounts.append("devpts")
221
222                 self.set_mounts()
223
224                 """
225                 Configure any user specified options (either in catalyst.conf or on
226                 the command line).
227                 """
228                 if "PKGCACHE" in self.settings:
229                         self.set_pkgcache_path()
230                         print "Location of the package cache is "+\
231                                 self.settings["pkgcache_path"]
232                         self.mounts.append("packagedir")
233                         self.mountmap["packagedir"] = self.settings["pkgcache_path"]
234
235                 if "KERNCACHE" in self.settings:
236                         self.set_kerncache_path()
237                         print "Location of the kerncache is "+\
238                                 self.settings["kerncache_path"]
239                         self.mounts.append("kerncache")
240                         self.mountmap["kerncache"] = self.settings["kerncache_path"]
241
242                 if "CCACHE" in self.settings:
243                         if "CCACHE_DIR" in os.environ:
244                                 ccdir=os.environ["CCACHE_DIR"]
245                                 del os.environ["CCACHE_DIR"]
246                         else:
247                                 ccdir="/root/.ccache"
248                         if not os.path.isdir(ccdir):
249                                 raise CatalystError,\
250                                         "Compiler cache support can't be enabled (can't find "+\
251                                         ccdir+")"
252                         self.mounts.append("ccache")
253                         self.mountmap["ccache"] = ccdir
254                         """ for the chroot: """
255                         self.env["CCACHE_DIR"] = self.target_mounts["ccache"]
256
257                 if "ICECREAM" in self.settings:
258                         self.mounts.append("icecream")
259                         self.mountmap["icecream"] = self.settings["icecream"]
260                         self.env["PATH"] = self.target_mounts["icecream"] + ":" + \
261                                 self.env["PATH"]
262
263                 if "port_logdir" in self.settings:
264                         self.mounts.append("port_logdir")
265                         self.mountmap["port_logdir"] = self.settings["port_logdir"]
266                         self.env["PORT_LOGDIR"] = self.settings["port_logdir"]
267                         self.env["PORT_LOGDIR_CLEAN"] = PORT_LOGDIR_CLEAN
268
269         def override_cbuild(self):
270                 if "CBUILD" in self.makeconf:
271                         self.settings["CBUILD"]=self.makeconf["CBUILD"]
272
273         def override_chost(self):
274                 if "CHOST" in self.makeconf:
275                         self.settings["CHOST"]=self.makeconf["CHOST"]
276
277         def override_cflags(self):
278                 if "CFLAGS" in self.makeconf:
279                         self.settings["CFLAGS"]=self.makeconf["CFLAGS"]
280
281         def override_cxxflags(self):
282                 if "CXXFLAGS" in self.makeconf:
283                         self.settings["CXXFLAGS"]=self.makeconf["CXXFLAGS"]
284
285         def override_ldflags(self):
286                 if "LDFLAGS" in self.makeconf:
287                         self.settings["LDFLAGS"]=self.makeconf["LDFLAGS"]
288
289         def set_install_mask(self):
290                 if "install_mask" in self.settings:
291                         if type(self.settings["install_mask"])!=types.StringType:
292                                 self.settings["install_mask"]=\
293                                         string.join(self.settings["install_mask"])
294
295         def set_spec_prefix(self):
296                 self.settings["spec_prefix"]=self.settings["target"]
297
298         def set_target_profile(self):
299                 self.settings["target_profile"]=self.settings["profile"]
300
301         def set_target_subpath(self):
302                 self.settings["target_subpath"]=self.settings["rel_type"]+"/"+\
303                                 self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
304                                 self.settings["version_stamp"]
305
306         def set_source_subpath(self):
307                 if type(self.settings["source_subpath"])!=types.StringType:
308                         raise CatalystError,\
309                                 "source_subpath should have been a string. Perhaps you have something wrong in your spec file?"
310
311         def set_pkgcache_path(self):
312                 if "pkgcache_path" in self.settings:
313                         if type(self.settings["pkgcache_path"])!=types.StringType:
314                                 self.settings["pkgcache_path"]=\
315                                         normpath(string.join(self.settings["pkgcache_path"]))
316                 else:
317                         self.settings["pkgcache_path"]=\
318                                 normpath(self.settings["storedir"]+"/packages/"+\
319                                 self.settings["target_subpath"]+"/")
320
321         def set_kerncache_path(self):
322                 if "kerncache_path" in self.settings:
323                         if type(self.settings["kerncache_path"])!=types.StringType:
324                                 self.settings["kerncache_path"]=\
325                                         normpath(string.join(self.settings["kerncache_path"]))
326                 else:
327                         self.settings["kerncache_path"]=normpath(self.settings["storedir"]+\
328                                 "/kerncache/"+self.settings["target_subpath"]+"/")
329
330         def set_target_path(self):
331                 self.settings["target_path"]=normpath(self.settings["storedir"]+\
332                         "/builds/"+self.settings["target_subpath"]+".tar.bz2")
333                 if "AUTORESUME" in self.settings\
334                         and os.path.exists(self.settings["autoresume_path"]+\
335                                 "setup_target_path"):
336                         print \
337                                 "Resume point detected, skipping target path setup operation..."
338                 else:
339                         """ First clean up any existing target stuff """
340                         # XXX WTF are we removing the old tarball before we start building the
341                         # XXX new one? If the build fails, you don't want to be left with
342                         # XXX nothing at all
343 #                       if os.path.isfile(self.settings["target_path"]):
344 #                               cmd("rm -f "+self.settings["target_path"],\
345 #                                       "Could not remove existing file: "\
346 #                                       +self.settings["target_path"],env=self.env)
347                         touch(self.settings["autoresume_path"]+"setup_target_path")
348
349                         if not os.path.exists(self.settings["storedir"]+"/builds/"):
350                                 os.makedirs(self.settings["storedir"]+"/builds/")
351
352         def set_fsscript(self):
353                 if self.settings["spec_prefix"]+"/fsscript" in self.settings:
354                         self.settings["fsscript"]=\
355                                 self.settings[self.settings["spec_prefix"]+"/fsscript"]
356                         del self.settings[self.settings["spec_prefix"]+"/fsscript"]
357
358         def set_rcadd(self):
359                 if self.settings["spec_prefix"]+"/rcadd" in self.settings:
360                         self.settings["rcadd"]=\
361                                 self.settings[self.settings["spec_prefix"]+"/rcadd"]
362                         del self.settings[self.settings["spec_prefix"]+"/rcadd"]
363
364         def set_rcdel(self):
365                 if self.settings["spec_prefix"]+"/rcdel" in self.settings:
366                         self.settings["rcdel"]=\
367                                 self.settings[self.settings["spec_prefix"]+"/rcdel"]
368                         del self.settings[self.settings["spec_prefix"]+"/rcdel"]
369
370         def set_cdtar(self):
371                 if self.settings["spec_prefix"]+"/cdtar" in self.settings:
372                         self.settings["cdtar"]=\
373                                 normpath(self.settings[self.settings["spec_prefix"]+"/cdtar"])
374                         del self.settings[self.settings["spec_prefix"]+"/cdtar"]
375
376         def set_iso(self):
377                 if self.settings["spec_prefix"]+"/iso" in self.settings:
378                         if self.settings[self.settings["spec_prefix"]+"/iso"].startswith('/'):
379                                 self.settings["iso"]=\
380                                         normpath(self.settings[self.settings["spec_prefix"]+"/iso"])
381                         else:
382                                 # This automatically prepends the build dir to the ISO output path
383                                 # if it doesn't start with a /
384                                 self.settings["iso"] = normpath(self.settings["storedir"] + \
385                                         "/builds/" + self.settings["rel_type"] + "/" + \
386                                         self.settings[self.settings["spec_prefix"]+"/iso"])
387                         del self.settings[self.settings["spec_prefix"]+"/iso"]
388
389         def set_fstype(self):
390                 if self.settings["spec_prefix"]+"/fstype" in self.settings:
391                         self.settings["fstype"]=\
392                                 self.settings[self.settings["spec_prefix"]+"/fstype"]
393                         del self.settings[self.settings["spec_prefix"]+"/fstype"]
394
395                 if "fstype" not in self.settings:
396                         self.settings["fstype"]="normal"
397                         for x in self.valid_values:
398                                 if x ==  self.settings["spec_prefix"]+"/fstype":
399                                         print "\n"+self.settings["spec_prefix"]+\
400                                                 "/fstype is being set to the default of \"normal\"\n"
401
402         def set_fsops(self):
403                 if "fstype" in self.settings:
404                         self.valid_values.append("fsops")
405                         if self.settings["spec_prefix"]+"/fsops" in self.settings:
406                                 self.settings["fsops"]=\
407                                         self.settings[self.settings["spec_prefix"]+"/fsops"]
408                                 del self.settings[self.settings["spec_prefix"]+"/fsops"]
409
410         def set_source_path(self):
411                 if "SEEDCACHE" in self.settings\
412                         and os.path.isdir(normpath(self.settings["storedir"]+"/tmp/"+\
413                                 self.settings["source_subpath"]+"/")):
414                         self.settings["source_path"]=normpath(self.settings["storedir"]+\
415                                 "/tmp/"+self.settings["source_subpath"]+"/")
416                 else:
417                         self.settings["source_path"]=normpath(self.settings["storedir"]+\
418                                 "/builds/"+self.settings["source_subpath"]+".tar.bz2")
419                         if os.path.isfile(self.settings["source_path"]):
420                                 # XXX: Is this even necessary if the previous check passes?
421                                 if os.path.exists(self.settings["source_path"]):
422                                         self.settings["source_path_hash"]=\
423                                                 generate_hash(self.settings["source_path"],\
424                                                 hash_function=self.settings["hash_function"],\
425                                                 verbose=False)
426                 print "Source path set to "+self.settings["source_path"]
427                 if os.path.isdir(self.settings["source_path"]):
428                         print "\tIf this is not desired, remove this directory or turn off"
429                         print "\tseedcache in the options of catalyst.conf the source path"
430                         print "\twill then be "+\
431                                 normpath(self.settings["storedir"]+"/builds/"+\
432                                 self.settings["source_subpath"]+".tar.bz2\n")
433
434         def set_dest_path(self):
435                 if "root_path" in self.settings:
436                         self.settings["destpath"]=normpath(self.settings["chroot_path"]+\
437                                 self.settings["root_path"])
438                 else:
439                         self.settings["destpath"]=normpath(self.settings["chroot_path"])
440
441         def set_cleanables(self):
442                 self.settings["cleanables"]=["/etc/resolv.conf","/var/tmp/*","/tmp/*",\
443                         "/root/*", self.settings["portdir"]]
444
445         def set_snapshot_path(self):
446                 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
447                         "/snapshots/" + self.settings["snapshot_name"] +
448                         self.settings["snapshot"] + ".tar.xz")
449
450                 if os.path.exists(self.settings["snapshot_path"]):
451                         self.settings["snapshot_path_hash"]=\
452                                 generate_hash(self.settings["snapshot_path"],\
453                                 hash_function=self.settings["hash_function"],verbose=False)
454                 else:
455                         self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
456                                 "/snapshots/" + self.settings["snapshot_name"] +
457                                 self.settings["snapshot"] + ".tar.bz2")
458
459                         if os.path.exists(self.settings["snapshot_path"]):
460                                 self.settings["snapshot_path_hash"]=\
461                                         generate_hash(self.settings["snapshot_path"],\
462                                         hash_function=self.settings["hash_function"],verbose=False)
463
464         def set_snapcache_path(self):
465                 if "SNAPCACHE" in self.settings:
466                         self.settings["snapshot_cache_path"]=\
467                                 normpath(self.settings["snapshot_cache"]+"/"+\
468                                 self.settings["snapshot"]+"/")
469                         self.snapcache_lock=\
470                                 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
471                         print "Caching snapshot to "+self.settings["snapshot_cache_path"]
472
473         def set_chroot_path(self):
474                 """
475                 NOTE: the trailing slash is very important!
476                 Things *will* break without it!
477                 """
478                 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
479                         "/tmp/"+self.settings["target_subpath"]+"/")
480                 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
481
482         def set_autoresume_path(self):
483                 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
484                         "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
485                         self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
486                         self.settings["version_stamp"]+"/")
487                 if "AUTORESUME" in self.settings:
488                         print "The autoresume path is " + self.settings["autoresume_path"]
489                 if not os.path.exists(self.settings["autoresume_path"]):
490                         os.makedirs(self.settings["autoresume_path"],0755)
491
492         def set_controller_file(self):
493                 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
494                         "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
495                         "-controller.sh")
496
497         def set_iso_volume_id(self):
498                 if self.settings["spec_prefix"]+"/volid" in self.settings:
499                         self.settings["iso_volume_id"]=\
500                                 self.settings[self.settings["spec_prefix"]+"/volid"]
501                         if len(self.settings["iso_volume_id"])>32:
502                                 raise CatalystError,\
503                                         "ISO volume ID must not exceed 32 characters."
504                 else:
505                         self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
506
507         def set_action_sequence(self):
508                 """ Default action sequence for run method """
509                 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
510                                 "setup_confdir","portage_overlay",\
511                                 "base_dirs","bind","chroot_setup","setup_environment",\
512                                 "run_local","preclean","unbind","clean"]
513 #               if "TARBALL" in self.settings or \
514 #                       "FETCH" not in self.settings:
515                 if "FETCH" not in self.settings:
516                         self.settings["action_sequence"].append("capture")
517                 self.settings["action_sequence"].append("clear_autoresume")
518
519         def set_use(self):
520                 if self.settings["spec_prefix"]+"/use" in self.settings:
521                         self.settings["use"]=\
522                                 self.settings[self.settings["spec_prefix"]+"/use"]
523                         del self.settings[self.settings["spec_prefix"]+"/use"]
524                 if "use" not in self.settings:
525                         self.settings["use"]=""
526                 if type(self.settings["use"])==types.StringType:
527                         self.settings["use"]=self.settings["use"].split()
528
529                 # Force bindist when options ask for it
530                 if "BINDIST" in self.settings:
531                         self.settings["use"].append("bindist")
532
533         def set_stage_path(self):
534                 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
535
536         def set_mounts(self):
537                 pass
538
539         def set_packages(self):
540                 pass
541
542         def set_rm(self):
543                 if self.settings["spec_prefix"]+"/rm" in self.settings:
544                         if type(self.settings[self.settings["spec_prefix"]+\
545                                 "/rm"])==types.StringType:
546                                 self.settings[self.settings["spec_prefix"]+"/rm"]=\
547                                         self.settings[self.settings["spec_prefix"]+"/rm"].split()
548
549         def set_linuxrc(self):
550                 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
551                         if type(self.settings[self.settings["spec_prefix"]+\
552                                 "/linuxrc"])==types.StringType:
553                                 self.settings["linuxrc"]=\
554                                         self.settings[self.settings["spec_prefix"]+"/linuxrc"]
555                                 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
556
557         def set_busybox_config(self):
558                 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
559                         if type(self.settings[self.settings["spec_prefix"]+\
560                                 "/busybox_config"])==types.StringType:
561                                 self.settings["busybox_config"]=\
562                                         self.settings[self.settings["spec_prefix"]+"/busybox_config"]
563                                 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
564
565         def set_portage_overlay(self):
566                 if "portage_overlay" in self.settings:
567                         if type(self.settings["portage_overlay"])==types.StringType:
568                                 self.settings["portage_overlay"]=\
569                                         self.settings["portage_overlay"].split()
570                         print "portage_overlay directories are set to: \""+\
571                                 string.join(self.settings["portage_overlay"])+"\""
572
573         def set_overlay(self):
574                 if self.settings["spec_prefix"]+"/overlay" in self.settings:
575                         if type(self.settings[self.settings["spec_prefix"]+\
576                                 "/overlay"])==types.StringType:
577                                 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
578                                         self.settings[self.settings["spec_prefix"]+\
579                                         "/overlay"].split()
580
581         def set_root_overlay(self):
582                 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
583                         if type(self.settings[self.settings["spec_prefix"]+\
584                                 "/root_overlay"])==types.StringType:
585                                 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
586                                         self.settings[self.settings["spec_prefix"]+\
587                                         "/root_overlay"].split()
588
589         def set_root_path(self):
590                 """ ROOT= variable for emerges """
591                 self.settings["root_path"]="/"
592
593         def set_valid_build_kernel_vars(self,addlargs):
594                 if "boot/kernel" in addlargs:
595                         if type(addlargs["boot/kernel"])==types.StringType:
596                                 loopy=[addlargs["boot/kernel"]]
597                         else:
598                                 loopy=addlargs["boot/kernel"]
599
600                         for x in loopy:
601                                 self.valid_values.append("boot/kernel/"+x+"/aliases")
602                                 self.valid_values.append("boot/kernel/"+x+"/config")
603                                 self.valid_values.append("boot/kernel/"+x+"/console")
604                                 self.valid_values.append("boot/kernel/"+x+"/extraversion")
605                                 self.valid_values.append("boot/kernel/"+x+"/gk_action")
606                                 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
607                                 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
608                                 self.valid_values.append("boot/kernel/"+x+"/machine_type")
609                                 self.valid_values.append("boot/kernel/"+x+"/sources")
610                                 self.valid_values.append("boot/kernel/"+x+"/softlevel")
611                                 self.valid_values.append("boot/kernel/"+x+"/use")
612                                 self.valid_values.append("boot/kernel/"+x+"/packages")
613                                 if "boot/kernel/"+x+"/packages" in addlargs:
614                                         if type(addlargs["boot/kernel/"+x+\
615                                                 "/packages"])==types.StringType:
616                                                 addlargs["boot/kernel/"+x+"/packages"]=\
617                                                         [addlargs["boot/kernel/"+x+"/packages"]]
618
619         def set_build_kernel_vars(self):
620                 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
621                         self.settings["gk_mainargs"]=\
622                                 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
623                         del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
624
625         def kill_chroot_pids(self):
626                 print "Checking for processes running in chroot and killing them."
627
628                 """
629                 Force environment variables to be exported so script can see them
630                 """
631                 self.setup_environment()
632
633                 if os.path.exists(self.settings["sharedir"]+\
634                         "/targets/support/kill-chroot-pids.sh"):
635                         cmd("/bin/bash "+self.settings["sharedir"]+\
636                                 "/targets/support/kill-chroot-pids.sh",\
637                                 "kill-chroot-pids script failed.",env=self.env)
638
639         def mount_safety_check(self):
640                 """
641                 Check and verify that none of our paths in mypath are mounted. We don't
642                 want to clean up with things still mounted, and this allows us to check.
643                 Returns 1 on ok, 0 on "something is still mounted" case.
644                 """
645
646                 if not os.path.exists(self.settings["chroot_path"]):
647                         return
648
649                 print "self.mounts =", self.mounts
650                 for x in self.mounts:
651                         target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
652                         print "mount_safety_check() x =", x, target
653                         if not os.path.exists(target):
654                                 continue
655
656                         if ismount(target):
657                                 """ Something is still mounted "" """
658                                 try:
659                                         print target + " is still mounted; performing auto-bind-umount...",
660                                         """ Try to umount stuff ourselves """
661                                         self.unbind()
662                                         if ismount(target):
663                                                 raise CatalystError, "Auto-unbind failed for " + target
664                                         else:
665                                                 print "Auto-unbind successful..."
666                                 except CatalystError:
667                                         raise CatalystError, "Unable to auto-unbind " + target
668
669         def unpack(self):
670                 unpack=True
671
672                 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
673                         "unpack")
674
675                 if "SEEDCACHE" in self.settings:
676                         if os.path.isdir(self.settings["source_path"]):
677                                 """ SEEDCACHE Is a directory, use rsync """
678                                 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
679                                         " "+self.settings["chroot_path"]
680                                 display_msg="\nStarting rsync from "+\
681                                         self.settings["source_path"]+"\nto "+\
682                                         self.settings["chroot_path"]+\
683                                         " (This may take some time) ...\n"
684                                 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
685                                         self.settings["chroot_path"]+" failed."
686                         else:
687                                 """ SEEDCACHE is a not a directory, try untar'ing """
688                                 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
689                                 display_msg="\nStarting tar extract from "+\
690                                         self.settings["source_path"]+"\nto "+\
691                                         self.settings["chroot_path"]+\
692                                                 " (This may take some time) ...\n"
693                                 if "bz2" == self.settings["chroot_path"][-3:]:
694                                         unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
695                                                 self.settings["chroot_path"]
696                                 else:
697                                         unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
698                                                 self.settings["chroot_path"]
699                                 error_msg="Tarball extraction of "+\
700                                         self.settings["source_path"]+" to "+\
701                                         self.settings["chroot_path"]+" failed."
702                 else:
703                         """ No SEEDCACHE, use tar """
704                         display_msg="\nStarting tar extract from "+\
705                                 self.settings["source_path"]+"\nto "+\
706                                 self.settings["chroot_path"]+\
707                                 " (This may take some time) ...\n"
708                         if "bz2" == self.settings["chroot_path"][-3:]:
709                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
710                                         self.settings["chroot_path"]
711                         else:
712                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
713                                         self.settings["chroot_path"]
714                         error_msg="Tarball extraction of "+self.settings["source_path"]+\
715                                 " to "+self.settings["chroot_path"]+" failed."
716
717                 if "AUTORESUME" in self.settings:
718                         if os.path.isdir(self.settings["source_path"]) \
719                                 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
720                                 """ Autoresume is valid, SEEDCACHE is valid """
721                                 unpack=False
722                                 invalid_snapshot=False
723
724                         elif os.path.isfile(self.settings["source_path"]) \
725                                 and self.settings["source_path_hash"]==clst_unpack_hash:
726                                 """ Autoresume is valid, tarball is valid """
727                                 unpack=False
728                                 invalid_snapshot=True
729
730                         elif os.path.isdir(self.settings["source_path"]) \
731                                 and not os.path.exists(self.settings["autoresume_path"]+\
732                                 "unpack"):
733                                 """ Autoresume is invalid, SEEDCACHE """
734                                 unpack=True
735                                 invalid_snapshot=False
736
737                         elif os.path.isfile(self.settings["source_path"]) \
738                                 and self.settings["source_path_hash"]!=clst_unpack_hash:
739                                 """ Autoresume is invalid, tarball """
740                                 unpack=True
741                                 invalid_snapshot=True
742                 else:
743                         """ No autoresume, SEEDCACHE """
744                         if "SEEDCACHE" in self.settings:
745                                 """ SEEDCACHE so let's run rsync and let it clean up """
746                                 if os.path.isdir(self.settings["source_path"]):
747                                         unpack=True
748                                         invalid_snapshot=False
749                                 elif os.path.isfile(self.settings["source_path"]):
750                                         """ Tarball so unpack and remove anything already there """
751                                         unpack=True
752                                         invalid_snapshot=True
753                                 """ No autoresume, no SEEDCACHE """
754                         else:
755                                 """ Tarball so unpack and remove anything already there """
756                                 if os.path.isfile(self.settings["source_path"]):
757                                         unpack=True
758                                         invalid_snapshot=True
759                                 elif os.path.isdir(self.settings["source_path"]):
760                                         """ We should never reach this, so something is very wrong """
761                                         raise CatalystError,\
762                                                 "source path is a dir but seedcache is not enabled"
763
764                 if unpack:
765                         self.mount_safety_check()
766
767                         if invalid_snapshot:
768                                 if "AUTORESUME" in self.settings:
769                                         print "No Valid Resume point detected, cleaning up..."
770
771                                 self.clear_autoresume()
772                                 self.clear_chroot()
773
774                         if not os.path.exists(self.settings["chroot_path"]):
775                                 os.makedirs(self.settings["chroot_path"])
776
777                         if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
778                                 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
779
780                         if "PKGCACHE" in self.settings:
781                                 if not os.path.exists(self.settings["pkgcache_path"]):
782                                         os.makedirs(self.settings["pkgcache_path"],0755)
783
784                         if "KERNCACHE" in self.settings:
785                                 if not os.path.exists(self.settings["kerncache_path"]):
786                                         os.makedirs(self.settings["kerncache_path"],0755)
787
788                         print display_msg
789                         cmd(unpack_cmd,error_msg,env=self.env)
790
791                         if "source_path_hash" in self.settings:
792                                 myf=open(self.settings["autoresume_path"]+"unpack","w")
793                                 myf.write(self.settings["source_path_hash"])
794                                 myf.close()
795                         else:
796                                 touch(self.settings["autoresume_path"]+"unpack")
797                 else:
798                         print "Resume point detected, skipping unpack operation..."
799
800         def unpack_snapshot(self):
801                 unpack=True
802                 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
803                         "unpack_portage")
804
805                 if "SNAPCACHE" in self.settings:
806                         snapshot_cache_hash=\
807                                 read_from_clst(self.settings["snapshot_cache_path"]+\
808                                 "catalyst-hash")
809                         destdir=self.settings["snapshot_cache_path"]
810                         if "bz2" == self.settings["chroot_path"][-3:]:
811                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
812                         else:
813                                 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
814                         unpack_errmsg="Error unpacking snapshot"
815                         cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
816                                 self.settings["snapshot_cache_path"]+\
817                                 " (This can take a long time)..."
818                         cleanup_errmsg="Error removing existing snapshot cache directory."
819                         self.snapshot_lock_object=self.snapcache_lock
820
821                         if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
822                                 print "Valid snapshot cache, skipping unpack of portage tree..."
823                                 unpack=False
824                 else:
825                         destdir = normpath(self.settings["chroot_path"] + self.settings["portdir"])
826                         cleanup_errmsg="Error removing existing snapshot directory."
827                         cleanup_msg=\
828                                 "Cleaning up existing portage tree (This can take a long time)..."
829                         if "bz2" == self.settings["chroot_path"][-3:]:
830                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
831                                         self.settings["chroot_path"]+"/usr"
832                         else:
833                                 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
834                                         self.settings["chroot_path"]+"/usr"
835                         unpack_errmsg="Error unpacking snapshot"
836
837                         if "AUTORESUME" in self.settings \
838                                 and os.path.exists(self.settings["chroot_path"]+\
839                                         self.settings["portdir"]) \
840                                 and os.path.exists(self.settings["autoresume_path"]\
841                                         +"unpack_portage") \
842                                 and self.settings["snapshot_path_hash"] == snapshot_hash:
843                                         print \
844                                                 "Valid Resume point detected, skipping unpack of portage tree..."
845                                         unpack=False
846
847                 if unpack:
848                         if "SNAPCACHE" in self.settings:
849                                 self.snapshot_lock_object.write_lock()
850                         if os.path.exists(destdir):
851                                 print cleanup_msg
852                                 cleanup_cmd="rm -rf "+destdir
853                                 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
854                         if not os.path.exists(destdir):
855                                 os.makedirs(destdir,0755)
856
857                         print "Unpacking portage tree (This can take a long time) ..."
858                         cmd(unpack_cmd,unpack_errmsg,env=self.env)
859
860                         if "SNAPCACHE" in self.settings:
861                                 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
862                                 myf.write(self.settings["snapshot_path_hash"])
863                                 myf.close()
864                         else:
865                                 print "Setting snapshot autoresume point"
866                                 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
867                                 myf.write(self.settings["snapshot_path_hash"])
868                                 myf.close()
869
870                         if "SNAPCACHE" in self.settings:
871                                 self.snapshot_lock_object.unlock()
872
873         def config_profile_link(self):
874                 if "AUTORESUME" in self.settings \
875                         and os.path.exists(self.settings["autoresume_path"]+\
876                                 "config_profile_link"):
877                         print \
878                                 "Resume point detected, skipping config_profile_link operation..."
879                 else:
880                         # TODO: zmedico and I discussed making this a directory and pushing
881                         # in a parent file, as well as other user-specified configuration.
882                         print "Configuring profile link..."
883                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
884                                         "Error zapping profile link",env=self.env)
885                         cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
886                         cmd("ln -sf ../.." + self.settings["portdir"] + "/profiles/" + \
887                                 self.settings["target_profile"]+" "+\
888                                 self.settings["chroot_path"]+"/etc/portage/make.profile",\
889                                 "Error creating profile link",env=self.env)
890                         touch(self.settings["autoresume_path"]+"config_profile_link")
891
892         def setup_confdir(self):
893                 if "AUTORESUME" in self.settings \
894                         and os.path.exists(self.settings["autoresume_path"]+\
895                                 "setup_confdir"):
896                         print "Resume point detected, skipping setup_confdir operation..."
897                 else:
898                         if "portage_confdir" in self.settings:
899                                 print "Configuring /etc/portage..."
900                                 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
901                                         self.settings["chroot_path"]+"/etc/portage/",\
902                                         "Error copying /etc/portage",env=self.env)
903                                 touch(self.settings["autoresume_path"]+"setup_confdir")
904
905         def portage_overlay(self):
906                 """ We copy the contents of our overlays to /usr/local/portage """
907                 if "portage_overlay" in self.settings:
908                         for x in self.settings["portage_overlay"]:
909                                 if os.path.exists(x):
910                                         print "Copying overlay dir " +x
911                                         cmd("mkdir -p "+self.settings["chroot_path"]+\
912                                                 self.settings["local_overlay"],\
913                                                 "Could not make portage_overlay dir",env=self.env)
914                                         cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
915                                                 self.settings["local_overlay"],\
916                                                 "Could not copy portage_overlay",env=self.env)
917
918         def root_overlay(self):
919                 """ Copy over the root_overlay """
920                 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
921                         for x in self.settings[self.settings["spec_prefix"]+\
922                                 "/root_overlay"]:
923                                 if os.path.exists(x):
924                                         print "Copying root_overlay: "+x
925                                         cmd("rsync -a "+x+"/ "+\
926                                                 self.settings["chroot_path"],\
927                                                 self.settings["spec_prefix"]+"/root_overlay: "+x+\
928                                                 " copy failed.",env=self.env)
929
930         def base_dirs(self):
931                 pass
932
933         def bind(self):
934                 for x in self.mounts:
935                         #print "bind(); x =", x
936                         target = normpath(self.settings["chroot_path"] + self.target_mounts[x])
937                         if not os.path.exists(target):
938                                 os.makedirs(target, 0755)
939
940                         if not os.path.exists(self.mountmap[x]):
941                                 if not self.mountmap[x] == "tmpfs":
942                                         os.makedirs(self.mountmap[x], 0755)
943
944                         src=self.mountmap[x]
945                         #print "bind(); src =", src
946                         if "SNAPCACHE" in self.settings and x == "portdir":
947                                 self.snapshot_lock_object.read_lock()
948                         if os.uname()[0] == "FreeBSD":
949                                 if src == "/dev":
950                                         cmd = "mount -t devfs none " + target
951                                         retval=os.system(cmd)
952                                 else:
953                                         cmd = "mount_nullfs " + src + " " + target
954                                         retval=os.system(cmd)
955                         else:
956                                 if src == "tmpfs":
957                                         if "var_tmpfs_portage" in self.settings:
958                                                 cmd = "mount -t tmpfs -o size=" + \
959                                                         self.settings["var_tmpfs_portage"] + "G " + \
960                                                         src + " " + target
961                                                 retval=os.system(cmd)
962                                 else:
963                                         cmd = "mount --bind " + src + " " + target
964                                         #print "bind(); cmd =", cmd
965                                         retval=os.system(cmd)
966                         if retval!=0:
967                                 self.unbind()
968                                 raise CatalystError,"Couldn't bind mount " + src
969
970         def unbind(self):
971                 ouch=0
972                 mypath=self.settings["chroot_path"]
973                 myrevmounts=self.mounts[:]
974                 myrevmounts.reverse()
975                 """ Unmount in reverse order for nested bind-mounts """
976                 for x in myrevmounts:
977                         target = normpath(mypath + self.target_mounts[x])
978                         if not os.path.exists(target):
979                                 continue
980
981                         if not ismount(target):
982                                 continue
983
984                         retval=os.system("umount " + target)
985
986                         if retval!=0:
987                                 warn("First attempt to unmount: " + target + " failed.")
988                                 warn("Killing any pids still running in the chroot")
989
990                                 self.kill_chroot_pids()
991
992                                 retval2 = os.system("umount " + target)
993                                 if retval2!=0:
994                                         ouch=1
995                                         warn("Couldn't umount bind mount: " + target)
996
997                         if "SNAPCACHE" in self.settings and x == "/usr/portage":
998                                 try:
999                                         """
1000                                         It's possible the snapshot lock object isn't created yet.
1001                                         This is because mount safety check calls unbind before the
1002                                         target is fully initialized
1003                                         """
1004                                         self.snapshot_lock_object.unlock()
1005                                 except:
1006                                         pass
1007                 if ouch:
1008                         """
1009                         if any bind mounts really failed, then we need to raise
1010                         this to potentially prevent an upcoming bash stage cleanup script
1011                         from wiping our bind mounts.
1012                         """
1013                         raise CatalystError,\
1014                                 "Couldn't umount one or more bind-mounts; aborting for safety."
1015
1016         def chroot_setup(self):
1017                 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
1018                         "/etc/portage/make.conf")
1019                 self.override_cbuild()
1020                 self.override_chost()
1021                 self.override_cflags()
1022                 self.override_cxxflags()
1023                 self.override_ldflags()
1024                 if "AUTORESUME" in self.settings \
1025                         and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
1026                         print "Resume point detected, skipping chroot_setup operation..."
1027                 else:
1028                         print "Setting up chroot..."
1029
1030                         #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
1031
1032                         cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
1033                                 "Could not copy resolv.conf into place.",env=self.env)
1034
1035                         """ Copy over the envscript, if applicable """
1036                         if "ENVSCRIPT" in self.settings:
1037                                 if not os.path.exists(self.settings["ENVSCRIPT"]):
1038                                         raise CatalystError,\
1039                                                 "Can't find envscript "+self.settings["ENVSCRIPT"]
1040
1041                                 print "\nWarning!!!!"
1042                                 print "\tOverriding certain env variables may cause catastrophic failure."
1043                                 print "\tIf your build fails look here first as the possible problem."
1044                                 print "\tCatalyst assumes you know what you are doing when setting"
1045                                 print "\t\tthese variables."
1046                                 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1047                                 print "\tYou have been warned\n"
1048
1049                                 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1050                                         self.settings["chroot_path"]+"/tmp/envscript",\
1051                                         "Could not copy envscript into place.",env=self.env)
1052
1053                         """
1054                         Copy over /etc/hosts from the host in case there are any
1055                         specialties in there
1056                         """
1057                         if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1058                                 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1059                                         self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1060                                         "Could not backup /etc/hosts",env=self.env)
1061                                 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1062                                         "Could not copy /etc/hosts",env=self.env)
1063
1064                         """ Modify and write out make.conf (for the chroot) """
1065                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1066                                 "Could not remove "+self.settings["chroot_path"]+\
1067                                 "/etc/portage/make.conf",env=self.env)
1068                         myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1069                         myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1070                         myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1071                         if "CFLAGS" in self.settings:
1072                                 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1073                         if "CXXFLAGS" in self.settings:
1074                                 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1075                                         myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1076                                 else:
1077                                         myf.write('CXXFLAGS="${CFLAGS}"\n')
1078                         else:
1079                                 myf.write('CXXFLAGS="${CFLAGS}"\n')
1080
1081                         if "LDFLAGS" in self.settings:
1082                                 myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
1083                                 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1084                         if "CBUILD" in self.settings:
1085                                 myf.write("# This should not be changed unless you know exactly what you are doing.  You\n# should probably be using a different stage, instead.\n")
1086                                 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1087
1088                         myf.write("# WARNING: Changing your CHOST is not something that should be done lightly.\n# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.\n")
1089                         myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1090
1091                         """ Figure out what our USE vars are for building """
1092                         myusevars=[]
1093                         if "HOSTUSE" in self.settings:
1094                                 myusevars.extend(self.settings["HOSTUSE"])
1095
1096                         if "use" in self.settings:
1097                                 myusevars.extend(self.settings["use"])
1098
1099                         if myusevars:
1100                                 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1101                                 myusevars = sorted(set(myusevars))
1102                                 myf.write('USE="'+string.join(myusevars)+'"\n')
1103                                 if '-*' in myusevars:
1104                                         print "\nWarning!!!  "
1105                                         print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1106                                                 "/use will cause portage to ignore"
1107                                         print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1108
1109                         myf.write('PORTDIR="%s"\n' % self.settings['portdir'])
1110                         myf.write('DISTDIR="%s"\n' % self.settings['distdir'])
1111                         myf.write('PKGDIR="%s"\n' % self.settings['packagedir'])
1112
1113                         """ Setup the portage overlay """
1114                         if "portage_overlay" in self.settings:
1115                                 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1116
1117                         myf.close()
1118                         cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1119                                 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1120                                 "Could not backup /etc/portage/make.conf",env=self.env)
1121                         touch(self.settings["autoresume_path"]+"chroot_setup")
1122
1123         def fsscript(self):
1124                 if "AUTORESUME" in self.settings \
1125                         and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1126                         print "Resume point detected, skipping fsscript operation..."
1127                 else:
1128                         if "fsscript" in self.settings:
1129                                 if os.path.exists(self.settings["controller_file"]):
1130                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1131                                                 " fsscript","fsscript script failed.",env=self.env)
1132                                         touch(self.settings["autoresume_path"]+"fsscript")
1133
1134         def rcupdate(self):
1135                 if "AUTORESUME" in self.settings \
1136                         and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1137                         print "Resume point detected, skipping rcupdate operation..."
1138                 else:
1139                         if os.path.exists(self.settings["controller_file"]):
1140                                 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1141                                         "rc-update script failed.",env=self.env)
1142                                 touch(self.settings["autoresume_path"]+"rcupdate")
1143
1144         def clean(self):
1145                 if "AUTORESUME" in self.settings \
1146                         and os.path.exists(self.settings["autoresume_path"]+"clean"):
1147                         print "Resume point detected, skipping clean operation..."
1148                 else:
1149                         for x in self.settings["cleanables"]:
1150                                 print "Cleaning chroot: "+x+"... "
1151                                 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1152                                         x,env=self.env)
1153
1154                 """ Put /etc/hosts back into place """
1155                 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1156                         cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1157                                 self.settings["chroot_path"]+"/etc/hosts",\
1158                                 "Could not replace /etc/hosts",env=self.env)
1159
1160                 """ Remove our overlay """
1161                 if os.path.exists(self.settings["chroot_path"] + self.settings["local_overlay"]):
1162                         cmd("rm -rf " + self.settings["chroot_path"] + self.settings["local_overlay"],
1163                                 "Could not remove " + self.settings["local_overlay"], env=self.env)
1164                         cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1165                                 "/etc/portage/make.conf",\
1166                                 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1167
1168                 """ Clean up old and obsoleted files in /etc """
1169                 if os.path.exists(self.settings["stage_path"]+"/etc"):
1170                         cmd("find "+self.settings["stage_path"]+\
1171                                 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1172                                 "Could not remove stray files in /etc",env=self.env)
1173
1174                 if os.path.exists(self.settings["controller_file"]):
1175                         cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1176                                 "clean script failed.",env=self.env)
1177                         touch(self.settings["autoresume_path"]+"clean")
1178
1179         def empty(self):
1180                 if "AUTORESUME" in self.settings \
1181                         and os.path.exists(self.settings["autoresume_path"]+"empty"):
1182                         print "Resume point detected, skipping empty operation..."
1183                 else:
1184                         if self.settings["spec_prefix"]+"/empty" in self.settings:
1185                                 if type(self.settings[self.settings["spec_prefix"]+\
1186                                         "/empty"])==types.StringType:
1187                                         self.settings[self.settings["spec_prefix"]+"/empty"]=\
1188                                                 self.settings[self.settings["spec_prefix"]+\
1189                                                 "/empty"].split()
1190                                 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1191                                         myemp=self.settings["destpath"]+x
1192                                         if not os.path.isdir(myemp) or os.path.islink(myemp):
1193                                                 print x,"not a directory or does not exist, skipping 'empty' operation."
1194                                                 continue
1195                                         print "Emptying directory",x
1196                                         """
1197                                         stat the dir, delete the dir, recreate the dir and set
1198                                         the proper perms and ownership
1199                                         """
1200                                         mystat=os.stat(myemp)
1201                                         shutil.rmtree(myemp)
1202                                         os.makedirs(myemp,0755)
1203                                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1204                                         os.chmod(myemp,mystat[ST_MODE])
1205                         touch(self.settings["autoresume_path"]+"empty")
1206
1207         def remove(self):
1208                 if "AUTORESUME" in self.settings \
1209                         and os.path.exists(self.settings["autoresume_path"]+"remove"):
1210                         print "Resume point detected, skipping remove operation..."
1211                 else:
1212                         if self.settings["spec_prefix"]+"/rm" in self.settings:
1213                                 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1214                                         """
1215                                         We're going to shell out for all these cleaning
1216                                         operations, so we get easy glob handling.
1217                                         """
1218                                         print "livecd: removing "+x
1219                                         os.system("rm -rf "+self.settings["chroot_path"]+x)
1220                                 try:
1221                                         if os.path.exists(self.settings["controller_file"]):
1222                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1223                                                         " clean","Clean  failed.",env=self.env)
1224                                                 touch(self.settings["autoresume_path"]+"remove")
1225                                 except:
1226                                         self.unbind()
1227                                         raise
1228
1229         def preclean(self):
1230                 if "AUTORESUME" in self.settings \
1231                         and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1232                         print "Resume point detected, skipping preclean operation..."
1233                 else:
1234                         try:
1235                                 if os.path.exists(self.settings["controller_file"]):
1236                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1237                                                 " preclean","preclean script failed.",env=self.env)
1238                                         touch(self.settings["autoresume_path"]+"preclean")
1239
1240                         except:
1241                                 self.unbind()
1242                                 raise CatalystError, "Build failed, could not execute preclean"
1243
1244         def capture(self):
1245                 if "AUTORESUME" in self.settings \
1246                         and os.path.exists(self.settings["autoresume_path"]+"capture"):
1247                         print "Resume point detected, skipping capture operation..."
1248                 else:
1249                         """ Capture target in a tarball """
1250                         mypath=self.settings["target_path"].split("/")
1251                         """ Remove filename from path """
1252                         mypath=string.join(mypath[:-1],"/")
1253
1254                         """ Now make sure path exists """
1255                         if not os.path.exists(mypath):
1256                                 os.makedirs(mypath)
1257
1258                         print "Creating stage tarball..."
1259
1260                         cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1261                                 self.settings["stage_path"]+" .",\
1262                                 "Couldn't create stage tarball",env=self.env)
1263
1264                         self.gen_contents_file(self.settings["target_path"])
1265                         self.gen_digest_file(self.settings["target_path"])
1266
1267                         touch(self.settings["autoresume_path"]+"capture")
1268
1269         def run_local(self):
1270                 if "AUTORESUME" in self.settings \
1271                         and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1272                         print "Resume point detected, skipping run_local operation..."
1273                 else:
1274                         try:
1275                                 if os.path.exists(self.settings["controller_file"]):
1276                                         cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1277                                                 "run script failed.",env=self.env)
1278                                         touch(self.settings["autoresume_path"]+"run_local")
1279
1280                         except CatalystError:
1281                                 self.unbind()
1282                                 raise CatalystError,"Stage build aborting due to error."
1283
1284         def setup_environment(self):
1285                 """
1286                 Modify the current environment. This is an ugly hack that should be
1287                 fixed. We need this to use the os.system() call since we can't
1288                 specify our own environ
1289                 """
1290                 for x in self.settings.keys():
1291                         """ Sanitize var names by doing "s|/-.|_|g" """
1292                         varname="clst_"+string.replace(x,"/","_")
1293                         varname=string.replace(varname,"-","_")
1294                         varname=string.replace(varname,".","_")
1295                         if type(self.settings[x])==types.StringType:
1296                                 """ Prefix to prevent namespace clashes """
1297                                 #os.environ[varname]=self.settings[x]
1298                                 self.env[varname]=self.settings[x]
1299                         elif type(self.settings[x])==types.ListType:
1300                                 #os.environ[varname]=string.join(self.settings[x])
1301                                 self.env[varname]=string.join(self.settings[x])
1302                         elif type(self.settings[x])==types.BooleanType:
1303                                 if self.settings[x]:
1304                                         self.env[varname]="true"
1305                                 else:
1306                                         self.env[varname]="false"
1307                 if "makeopts" in self.settings:
1308                         self.env["MAKEOPTS"]=self.settings["makeopts"]
1309
1310         def run(self):
1311                 self.chroot_lock.write_lock()
1312
1313                 """ Kill any pids in the chroot "" """
1314                 self.kill_chroot_pids()
1315
1316                 """ Check for mounts right away and abort if we cannot unmount them """
1317                 self.mount_safety_check()
1318
1319                 if "CLEAR_AUTORESUME" in self.settings:
1320                         self.clear_autoresume()
1321
1322                 if "PURGETMPONLY" in self.settings:
1323                         self.purge()
1324                         return
1325
1326                 if "PURGEONLY" in self.settings:
1327                         self.purge()
1328                         return
1329
1330                 if "PURGE" in self.settings:
1331                         self.purge()
1332
1333                 for x in self.settings["action_sequence"]:
1334                         print "--- Running action sequence: "+x
1335                         sys.stdout.flush()
1336                         try:
1337                                 apply(getattr(self,x))
1338                         except:
1339                                 self.mount_safety_check()
1340                                 raise
1341
1342                 self.chroot_lock.unlock()
1343
1344         def unmerge(self):
1345                 if "AUTORESUME" in self.settings \
1346                         and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1347                         print "Resume point detected, skipping unmerge operation..."
1348                 else:
1349                         if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1350                                 if type(self.settings[self.settings["spec_prefix"]+\
1351                                         "/unmerge"])==types.StringType:
1352                                         self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1353                                                 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1354                                 myunmerge=\
1355                                         self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1356
1357                                 for x in range(0,len(myunmerge)):
1358                                         """
1359                                         Surround args with quotes for passing to bash, allows
1360                                         things like "<" to remain intact
1361                                         """
1362                                         myunmerge[x]="'"+myunmerge[x]+"'"
1363                                 myunmerge=string.join(myunmerge)
1364
1365                                 """ Before cleaning, unmerge stuff """
1366                                 try:
1367                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1368                                                 " unmerge "+ myunmerge,"Unmerge script failed.",\
1369                                                 env=self.env)
1370                                         print "unmerge shell script"
1371                                 except CatalystError:
1372                                         self.unbind()
1373                                         raise
1374                                 touch(self.settings["autoresume_path"]+"unmerge")
1375
1376         def target_setup(self):
1377                 if "AUTORESUME" in self.settings \
1378                         and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1379                         print "Resume point detected, skipping target_setup operation..."
1380                 else:
1381                         print "Setting up filesystems per filesystem type"
1382                         cmd("/bin/bash "+self.settings["controller_file"]+\
1383                                 " target_image_setup "+ self.settings["target_path"],\
1384                                 "target_image_setup script failed.",env=self.env)
1385                         touch(self.settings["autoresume_path"]+"target_setup")
1386
1387         def setup_overlay(self):
1388                 if "AUTORESUME" in self.settings \
1389                 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1390                         print "Resume point detected, skipping setup_overlay operation..."
1391                 else:
1392                         if self.settings["spec_prefix"]+"/overlay" in self.settings:
1393                                 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1394                                         if os.path.exists(x):
1395                                                 cmd("rsync -a "+x+"/ "+\
1396                                                         self.settings["target_path"],\
1397                                                         self.settings["spec_prefix"]+"overlay: "+x+\
1398                                                         " copy failed.",env=self.env)
1399                                 touch(self.settings["autoresume_path"]+"setup_overlay")
1400
1401         def create_iso(self):
1402                 if "AUTORESUME" in self.settings \
1403                         and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1404                         print "Resume point detected, skipping create_iso operation..."
1405                 else:
1406                         """ Create the ISO """
1407                         if "iso" in self.settings:
1408                                 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1409                                         self.settings["iso"],"ISO creation script failed.",\
1410                                         env=self.env)
1411                                 self.gen_contents_file(self.settings["iso"])
1412                                 self.gen_digest_file(self.settings["iso"])
1413                                 touch(self.settings["autoresume_path"]+"create_iso")
1414                         else:
1415                                 print "WARNING: livecd/iso was not defined."
1416                                 print "An ISO Image will not be created."
1417
1418         def build_packages(self):
1419                 if "AUTORESUME" in self.settings \
1420                         and os.path.exists(self.settings["autoresume_path"]+\
1421                                 "build_packages"):
1422                         print "Resume point detected, skipping build_packages operation..."
1423                 else:
1424                         if self.settings["spec_prefix"]+"/packages" in self.settings:
1425                                 if "AUTORESUME" in self.settings \
1426                                         and os.path.exists(self.settings["autoresume_path"]+\
1427                                                 "build_packages"):
1428                                         print "Resume point detected, skipping build_packages operation..."
1429                                 else:
1430                                         mypack=\
1431                                                 list_bashify(self.settings[self.settings["spec_prefix"]\
1432                                                 +"/packages"])
1433                                         try:
1434                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1435                                                         " build_packages "+mypack,\
1436                                                         "Error in attempt to build packages",env=self.env)
1437                                                 touch(self.settings["autoresume_path"]+"build_packages")
1438                                         except CatalystError:
1439                                                 self.unbind()
1440                                                 raise CatalystError,self.settings["spec_prefix"]+\
1441                                                         "build aborting due to error."
1442
1443         def build_kernel(self):
1444                 "Build all configured kernels"
1445                 if "AUTORESUME" in self.settings \
1446                         and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1447                         print "Resume point detected, skipping build_kernel operation..."
1448                 else:
1449                         if "boot/kernel" in self.settings:
1450                                 try:
1451                                         mynames=self.settings["boot/kernel"]
1452                                         if type(mynames)==types.StringType:
1453                                                 mynames=[mynames]
1454                                         """
1455                                         Execute the script that sets up the kernel build environment
1456                                         """
1457                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1458                                                 " pre-kmerge ","Runscript pre-kmerge failed",\
1459                                                 env=self.env)
1460                                         for kname in mynames:
1461                                                 self._build_kernel(kname=kname)
1462                                         touch(self.settings["autoresume_path"]+"build_kernel")
1463                                 except CatalystError:
1464                                         self.unbind()
1465                                         raise CatalystError,\
1466                                                 "build aborting due to kernel build error."
1467
1468         def _build_kernel(self, kname):
1469                 "Build a single configured kernel by name"
1470                 if "AUTORESUME" in self.settings \
1471                         and os.path.exists(self.settings["autoresume_path"]\
1472                                 +"build_kernel_"+kname):
1473                         print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1474                         return
1475                 self._copy_kernel_config(kname=kname)
1476
1477                 """
1478                 If we need to pass special options to the bootloader
1479                 for this kernel put them into the environment
1480                 """
1481                 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1482                         myopts=self.settings["boot/kernel/"+kname+\
1483                                 "/kernelopts"]
1484
1485                         if type(myopts) != types.StringType:
1486                                 myopts = string.join(myopts)
1487                                 self.env[kname+"_kernelopts"]=myopts
1488
1489                         else:
1490                                 self.env[kname+"_kernelopts"]=""
1491
1492                 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1493                         self.settings["boot/kernel/"+kname+\
1494                                 "/extraversion"]=""
1495
1496                 self.env["clst_kextraversion"]=\
1497                         self.settings["boot/kernel/"+kname+\
1498                         "/extraversion"]
1499
1500                 self._copy_initramfs_overlay(kname=kname)
1501
1502                 """ Execute the script that builds the kernel """
1503                 cmd("/bin/bash "+self.settings["controller_file"]+\
1504                         " kernel "+kname,\
1505                         "Runscript kernel build failed",env=self.env)
1506
1507                 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1508                         if os.path.exists(self.settings["chroot_path"]+\
1509                                 "/tmp/initramfs_overlay/"):
1510                                 print "Cleaning up temporary overlay dir"
1511                                 cmd("rm -R "+self.settings["chroot_path"]+\
1512                                         "/tmp/initramfs_overlay/",env=self.env)
1513
1514                 touch(self.settings["autoresume_path"]+\
1515                         "build_kernel_"+kname)
1516
1517                 """
1518                 Execute the script that cleans up the kernel build
1519                 environment
1520                 """
1521                 cmd("/bin/bash "+self.settings["controller_file"]+\
1522                         " post-kmerge ",
1523                         "Runscript post-kmerge failed",env=self.env)
1524
1525         def _copy_kernel_config(self, kname):
1526                 if "boot/kernel/"+kname+"/config" in self.settings:
1527                         if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1528                                 self.unbind()
1529                                 raise CatalystError,\
1530                                         "Can't find kernel config: "+\
1531                                         self.settings["boot/kernel/"+kname+\
1532                                         "/config"]
1533
1534                         try:
1535                                 cmd("cp "+self.settings["boot/kernel/"+kname+\
1536                                         "/config"]+" "+\
1537                                         self.settings["chroot_path"]+"/var/tmp/"+\
1538                                         kname+".config",\
1539                                         "Couldn't copy kernel config: "+\
1540                                         self.settings["boot/kernel/"+kname+\
1541                                         "/config"],env=self.env)
1542
1543                         except CatalystError:
1544                                 self.unbind()
1545
1546         def _copy_initramfs_overlay(self, kname):
1547                 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1548                         if os.path.exists(self.settings["boot/kernel/"+\
1549                                 kname+"/initramfs_overlay"]):
1550                                 print "Copying initramfs_overlay dir "+\
1551                                         self.settings["boot/kernel/"+kname+\
1552                                         "/initramfs_overlay"]
1553
1554                                 cmd("mkdir -p "+\
1555                                         self.settings["chroot_path"]+\
1556                                         "/tmp/initramfs_overlay/"+\
1557                                         self.settings["boot/kernel/"+kname+\
1558                                         "/initramfs_overlay"],env=self.env)
1559
1560                                 cmd("cp -R "+self.settings["boot/kernel/"+\
1561                                         kname+"/initramfs_overlay"]+"/* "+\
1562                                         self.settings["chroot_path"]+\
1563                                         "/tmp/initramfs_overlay/"+\
1564                                         self.settings["boot/kernel/"+kname+\
1565                                         "/initramfs_overlay"],env=self.env)
1566
1567         def bootloader(self):
1568                 if "AUTORESUME" in self.settings \
1569                         and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1570                         print "Resume point detected, skipping bootloader operation..."
1571                 else:
1572                         try:
1573                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1574                                         " bootloader " + self.settings["target_path"],\
1575                                         "Bootloader script failed.",env=self.env)
1576                                 touch(self.settings["autoresume_path"]+"bootloader")
1577                         except CatalystError:
1578                                 self.unbind()
1579                                 raise CatalystError,"Script aborting due to error."
1580
1581         def livecd_update(self):
1582                 if "AUTORESUME" in self.settings \
1583                         and os.path.exists(self.settings["autoresume_path"]+\
1584                                 "livecd_update"):
1585                         print "Resume point detected, skipping build_packages operation..."
1586                 else:
1587                         try:
1588                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1589                                         " livecd-update","livecd-update failed.",env=self.env)
1590                                 touch(self.settings["autoresume_path"]+"livecd_update")
1591
1592                         except CatalystError:
1593                                 self.unbind()
1594                                 raise CatalystError,"build aborting due to livecd_update error."
1595
1596         def clear_chroot(self):
1597                 myemp=self.settings["chroot_path"]
1598                 if os.path.isdir(myemp):
1599                         print "Emptying directory",myemp
1600                         """
1601                         stat the dir, delete the dir, recreate the dir and set
1602                         the proper perms and ownership
1603                         """
1604                         mystat=os.stat(myemp)
1605                         #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1606                         """ There's no easy way to change flags recursively in python """
1607                         if os.uname()[0] == "FreeBSD":
1608                                 os.system("chflags -R noschg "+myemp)
1609                         shutil.rmtree(myemp)
1610                         os.makedirs(myemp,0755)
1611                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1612                         os.chmod(myemp,mystat[ST_MODE])
1613
1614         def clear_packages(self):
1615                 if "PKGCACHE" in self.settings:
1616                         print "purging the pkgcache ..."
1617
1618                         myemp=self.settings["pkgcache_path"]
1619                         if os.path.isdir(myemp):
1620                                 print "Emptying directory",myemp
1621                                 """
1622                                 stat the dir, delete the dir, recreate the dir and set
1623                                 the proper perms and ownership
1624                                 """
1625                                 mystat=os.stat(myemp)
1626                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1627                                 shutil.rmtree(myemp)
1628                                 os.makedirs(myemp,0755)
1629                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1630                                 os.chmod(myemp,mystat[ST_MODE])
1631
1632         def clear_kerncache(self):
1633                 if "KERNCACHE" in self.settings:
1634                         print "purging the kerncache ..."
1635
1636                         myemp=self.settings["kerncache_path"]
1637                         if os.path.isdir(myemp):
1638                                 print "Emptying directory",myemp
1639                                 """
1640                                 stat the dir, delete the dir, recreate the dir and set
1641                                 the proper perms and ownership
1642                                 """
1643                                 mystat=os.stat(myemp)
1644                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1645                                 shutil.rmtree(myemp)
1646                                 os.makedirs(myemp,0755)
1647                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1648                                 os.chmod(myemp,mystat[ST_MODE])
1649
1650         def clear_autoresume(self):
1651                 """ Clean resume points since they are no longer needed """
1652                 if "AUTORESUME" in self.settings:
1653                         print "Removing AutoResume Points: ..."
1654                 myemp=self.settings["autoresume_path"]
1655                 if os.path.isdir(myemp):
1656                                 if "AUTORESUME" in self.settings:
1657                                         print "Emptying directory",myemp
1658                                 """
1659                                 stat the dir, delete the dir, recreate the dir and set
1660                                 the proper perms and ownership
1661                                 """
1662                                 mystat=os.stat(myemp)
1663                                 if os.uname()[0] == "FreeBSD":
1664                                         cmd("chflags -R noschg "+myemp,\
1665                                                 "Could not remove immutable flag for file "\
1666                                                 +myemp)
1667                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1668                                 shutil.rmtree(myemp)
1669                                 os.makedirs(myemp,0755)
1670                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1671                                 os.chmod(myemp,mystat[ST_MODE])
1672
1673         def gen_contents_file(self,file):
1674                 if os.path.exists(file+".CONTENTS"):
1675                         os.remove(file+".CONTENTS")
1676                 if "contents" in self.settings:
1677                         if os.path.exists(file):
1678                                 myf=open(file+".CONTENTS","w")
1679                                 keys={}
1680                                 for i in self.settings["contents"].split():
1681                                         keys[i]=1
1682                                         array=keys.keys()
1683                                         array.sort()
1684                                 for j in array:
1685                                         contents=generate_contents(file,contents_function=j,\
1686                                                 verbose="VERBOSE" in self.settings)
1687                                         if contents:
1688                                                 myf.write(contents)
1689                                 myf.close()
1690
1691         def gen_digest_file(self,file):
1692                 if os.path.exists(file+".DIGESTS"):
1693                         os.remove(file+".DIGESTS")
1694                 if "digests" in self.settings:
1695                         if os.path.exists(file):
1696                                 myf=open(file+".DIGESTS","w")
1697                                 keys={}
1698                                 for i in self.settings["digests"].split():
1699                                         keys[i]=1
1700                                         array=keys.keys()
1701                                         array.sort()
1702                                 for f in [file, file+'.CONTENTS']:
1703                                         if os.path.exists(f):
1704                                                 if "all" in array:
1705                                                         for k in hash_map.keys():
1706                                                                 hash=generate_hash(f,hash_function=k,verbose=\
1707                                                                         "VERBOSE" in self.settings)
1708                                                                 myf.write(hash)
1709                                                 else:
1710                                                         for j in array:
1711                                                                 hash=generate_hash(f,hash_function=j,verbose=\
1712                                                                         "VERBOSE" in self.settings)
1713                                                                 myf.write(hash)
1714                                 myf.close()
1715
1716         def purge(self):
1717                 countdown(10,"Purging Caches ...")
1718                 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1719                         print "clearing autoresume ..."
1720                         self.clear_autoresume()
1721
1722                         print "clearing chroot ..."
1723                         self.clear_chroot()
1724
1725                         if "PURGETMPONLY" not in self.settings:
1726                                 print "clearing package cache ..."
1727                                 self.clear_packages()
1728
1729                         print "clearing kerncache ..."
1730                         self.clear_kerncache()
1731
1732 # vim: ts=4 sw=4 sta et sts=4 ai