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