generic_stage_target: default {PORT,PKG,DIST}DIR
[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/*","/usr/portage"]
410
411         def set_snapshot_path(self):
412                 self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
413                         "/snapshots/portage-"+self.settings["snapshot"]+".tar.xz")
414
415                 if os.path.exists(self.settings["snapshot_path"]):
416                         self.settings["snapshot_path_hash"]=\
417                                 generate_hash(self.settings["snapshot_path"],\
418                                 hash_function=self.settings["hash_function"],verbose=False)
419                 else:
420                         self.settings["snapshot_path"]=normpath(self.settings["storedir"]+\
421                                 "/snapshots/portage-"+self.settings["snapshot"]+".tar.bz2")
422
423                         if os.path.exists(self.settings["snapshot_path"]):
424                                 self.settings["snapshot_path_hash"]=\
425                                         generate_hash(self.settings["snapshot_path"],\
426                                         hash_function=self.settings["hash_function"],verbose=False)
427
428         def set_snapcache_path(self):
429                 if "SNAPCACHE" in self.settings:
430                         self.settings["snapshot_cache_path"]=\
431                                 normpath(self.settings["snapshot_cache"]+"/"+\
432                                 self.settings["snapshot"]+"/")
433                         self.snapcache_lock=\
434                                 catalyst_lock.LockDir(self.settings["snapshot_cache_path"])
435                         print "Caching snapshot to "+self.settings["snapshot_cache_path"]
436
437         def set_chroot_path(self):
438                 """
439                 NOTE: the trailing slash is very important!
440                 Things *will* break without it!
441                 """
442                 self.settings["chroot_path"]=normpath(self.settings["storedir"]+\
443                         "/tmp/"+self.settings["target_subpath"]+"/")
444                 self.chroot_lock=catalyst_lock.LockDir(self.settings["chroot_path"])
445
446         def set_autoresume_path(self):
447                 self.settings["autoresume_path"]=normpath(self.settings["storedir"]+\
448                         "/tmp/"+self.settings["rel_type"]+"/"+".autoresume-"+\
449                         self.settings["target"]+"-"+self.settings["subarch"]+"-"+\
450                         self.settings["version_stamp"]+"/")
451                 if "AUTORESUME" in self.settings:
452                         print "The autoresume path is " + self.settings["autoresume_path"]
453                 if not os.path.exists(self.settings["autoresume_path"]):
454                         os.makedirs(self.settings["autoresume_path"],0755)
455
456         def set_controller_file(self):
457                 self.settings["controller_file"]=normpath(self.settings["sharedir"]+\
458                         "/targets/"+self.settings["target"]+"/"+self.settings["target"]+\
459                         "-controller.sh")
460
461         def set_iso_volume_id(self):
462                 if self.settings["spec_prefix"]+"/volid" in self.settings:
463                         self.settings["iso_volume_id"]=\
464                                 self.settings[self.settings["spec_prefix"]+"/volid"]
465                         if len(self.settings["iso_volume_id"])>32:
466                                 raise CatalystError,\
467                                         "ISO volume ID must not exceed 32 characters."
468                 else:
469                         self.settings["iso_volume_id"]="catalyst "+self.settings["snapshot"]
470
471         def set_action_sequence(self):
472                 """ Default action sequence for run method """
473                 self.settings["action_sequence"]=["unpack","unpack_snapshot",\
474                                 "setup_confdir","portage_overlay",\
475                                 "base_dirs","bind","chroot_setup","setup_environment",\
476                                 "run_local","preclean","unbind","clean"]
477 #               if "TARBALL" in self.settings or \
478 #                       "FETCH" not in self.settings:
479                 if "FETCH" not in self.settings:
480                         self.settings["action_sequence"].append("capture")
481                 self.settings["action_sequence"].append("clear_autoresume")
482
483         def set_use(self):
484                 if self.settings["spec_prefix"]+"/use" in self.settings:
485                         self.settings["use"]=\
486                                 self.settings[self.settings["spec_prefix"]+"/use"]
487                         del self.settings[self.settings["spec_prefix"]+"/use"]
488                 if "use" not in self.settings:
489                         self.settings["use"]=""
490                 if type(self.settings["use"])==types.StringType:
491                         self.settings["use"]=self.settings["use"].split()
492
493                 # Force bindist when options ask for it
494                 if "BINDIST" in self.settings:
495                         self.settings["use"].append("bindist")
496
497         def set_stage_path(self):
498                 self.settings["stage_path"]=normpath(self.settings["chroot_path"])
499
500         def set_mounts(self):
501                 pass
502
503         def set_packages(self):
504                 pass
505
506         def set_rm(self):
507                 if self.settings["spec_prefix"]+"/rm" in self.settings:
508                         if type(self.settings[self.settings["spec_prefix"]+\
509                                 "/rm"])==types.StringType:
510                                 self.settings[self.settings["spec_prefix"]+"/rm"]=\
511                                         self.settings[self.settings["spec_prefix"]+"/rm"].split()
512
513         def set_linuxrc(self):
514                 if self.settings["spec_prefix"]+"/linuxrc" in self.settings:
515                         if type(self.settings[self.settings["spec_prefix"]+\
516                                 "/linuxrc"])==types.StringType:
517                                 self.settings["linuxrc"]=\
518                                         self.settings[self.settings["spec_prefix"]+"/linuxrc"]
519                                 del self.settings[self.settings["spec_prefix"]+"/linuxrc"]
520
521         def set_busybox_config(self):
522                 if self.settings["spec_prefix"]+"/busybox_config" in self.settings:
523                         if type(self.settings[self.settings["spec_prefix"]+\
524                                 "/busybox_config"])==types.StringType:
525                                 self.settings["busybox_config"]=\
526                                         self.settings[self.settings["spec_prefix"]+"/busybox_config"]
527                                 del self.settings[self.settings["spec_prefix"]+"/busybox_config"]
528
529         def set_portage_overlay(self):
530                 if "portage_overlay" in self.settings:
531                         if type(self.settings["portage_overlay"])==types.StringType:
532                                 self.settings["portage_overlay"]=\
533                                         self.settings["portage_overlay"].split()
534                         print "portage_overlay directories are set to: \""+\
535                                 string.join(self.settings["portage_overlay"])+"\""
536
537         def set_overlay(self):
538                 if self.settings["spec_prefix"]+"/overlay" in self.settings:
539                         if type(self.settings[self.settings["spec_prefix"]+\
540                                 "/overlay"])==types.StringType:
541                                 self.settings[self.settings["spec_prefix"]+"/overlay"]=\
542                                         self.settings[self.settings["spec_prefix"]+\
543                                         "/overlay"].split()
544
545         def set_root_overlay(self):
546                 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
547                         if type(self.settings[self.settings["spec_prefix"]+\
548                                 "/root_overlay"])==types.StringType:
549                                 self.settings[self.settings["spec_prefix"]+"/root_overlay"]=\
550                                         self.settings[self.settings["spec_prefix"]+\
551                                         "/root_overlay"].split()
552
553         def set_root_path(self):
554                 """ ROOT= variable for emerges """
555                 self.settings["root_path"]="/"
556
557         def set_valid_build_kernel_vars(self,addlargs):
558                 if "boot/kernel" in addlargs:
559                         if type(addlargs["boot/kernel"])==types.StringType:
560                                 loopy=[addlargs["boot/kernel"]]
561                         else:
562                                 loopy=addlargs["boot/kernel"]
563
564                         for x in loopy:
565                                 self.valid_values.append("boot/kernel/"+x+"/aliases")
566                                 self.valid_values.append("boot/kernel/"+x+"/config")
567                                 self.valid_values.append("boot/kernel/"+x+"/console")
568                                 self.valid_values.append("boot/kernel/"+x+"/extraversion")
569                                 self.valid_values.append("boot/kernel/"+x+"/gk_action")
570                                 self.valid_values.append("boot/kernel/"+x+"/gk_kernargs")
571                                 self.valid_values.append("boot/kernel/"+x+"/initramfs_overlay")
572                                 self.valid_values.append("boot/kernel/"+x+"/machine_type")
573                                 self.valid_values.append("boot/kernel/"+x+"/sources")
574                                 self.valid_values.append("boot/kernel/"+x+"/softlevel")
575                                 self.valid_values.append("boot/kernel/"+x+"/use")
576                                 self.valid_values.append("boot/kernel/"+x+"/packages")
577                                 if "boot/kernel/"+x+"/packages" in addlargs:
578                                         if type(addlargs["boot/kernel/"+x+\
579                                                 "/packages"])==types.StringType:
580                                                 addlargs["boot/kernel/"+x+"/packages"]=\
581                                                         [addlargs["boot/kernel/"+x+"/packages"]]
582
583         def set_build_kernel_vars(self):
584                 if self.settings["spec_prefix"]+"/gk_mainargs" in self.settings:
585                         self.settings["gk_mainargs"]=\
586                                 self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
587                         del self.settings[self.settings["spec_prefix"]+"/gk_mainargs"]
588
589         def kill_chroot_pids(self):
590                 print "Checking for processes running in chroot and killing them."
591
592                 """
593                 Force environment variables to be exported so script can see them
594                 """
595                 self.setup_environment()
596
597                 if os.path.exists(self.settings["sharedir"]+\
598                         "/targets/support/kill-chroot-pids.sh"):
599                         cmd("/bin/bash "+self.settings["sharedir"]+\
600                                 "/targets/support/kill-chroot-pids.sh",\
601                                 "kill-chroot-pids script failed.",env=self.env)
602
603         def mount_safety_check(self):
604                 mypath=self.settings["chroot_path"]
605
606                 """
607                 Check and verify that none of our paths in mypath are mounted. We don't
608                 want to clean up with things still mounted, and this allows us to check.
609                 Returns 1 on ok, 0 on "something is still mounted" case.
610                 """
611
612                 if not os.path.exists(mypath):
613                         return
614
615                 for x in self.mounts:
616                         if not os.path.exists(mypath+x):
617                                 continue
618
619                         if ismount(mypath+x):
620                                 """ Something is still mounted "" """
621                                 try:
622                                         print x+" is still mounted; performing auto-bind-umount...",
623                                         """ Try to umount stuff ourselves """
624                                         self.unbind()
625                                         if ismount(mypath+x):
626                                                 raise CatalystError, "Auto-unbind failed for "+x
627                                         else:
628                                                 print "Auto-unbind successful..."
629                                 except CatalystError:
630                                         raise CatalystError, "Unable to auto-unbind "+x
631
632         def unpack(self):
633                 unpack=True
634
635                 clst_unpack_hash=read_from_clst(self.settings["autoresume_path"]+\
636                         "unpack")
637
638                 if "SEEDCACHE" in self.settings:
639                         if os.path.isdir(self.settings["source_path"]):
640                                 """ SEEDCACHE Is a directory, use rsync """
641                                 unpack_cmd="rsync -a --delete "+self.settings["source_path"]+\
642                                         " "+self.settings["chroot_path"]
643                                 display_msg="\nStarting rsync from "+\
644                                         self.settings["source_path"]+"\nto "+\
645                                         self.settings["chroot_path"]+\
646                                         " (This may take some time) ...\n"
647                                 error_msg="Rsync of "+self.settings["source_path"]+" to "+\
648                                         self.settings["chroot_path"]+" failed."
649                         else:
650                                 """ SEEDCACHE is a not a directory, try untar'ing """
651                                 print "Referenced SEEDCACHE does not appear to be a directory, trying to untar..."
652                                 display_msg="\nStarting tar extract from "+\
653                                         self.settings["source_path"]+"\nto "+\
654                                         self.settings["chroot_path"]+\
655                                                 " (This may take some time) ...\n"
656                                 if "bz2" == self.settings["chroot_path"][-3:]:
657                                         unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
658                                                 self.settings["chroot_path"]
659                                 else:
660                                         unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
661                                                 self.settings["chroot_path"]
662                                 error_msg="Tarball extraction of "+\
663                                         self.settings["source_path"]+" to "+\
664                                         self.settings["chroot_path"]+" failed."
665                 else:
666                         """ No SEEDCACHE, use tar """
667                         display_msg="\nStarting tar extract from "+\
668                                 self.settings["source_path"]+"\nto "+\
669                                 self.settings["chroot_path"]+\
670                                 " (This may take some time) ...\n"
671                         if "bz2" == self.settings["chroot_path"][-3:]:
672                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
673                                         self.settings["chroot_path"]
674                         else:
675                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["source_path"]+" -C "+\
676                                         self.settings["chroot_path"]
677                         error_msg="Tarball extraction of "+self.settings["source_path"]+\
678                                 " to "+self.settings["chroot_path"]+" failed."
679
680                 if "AUTORESUME" in self.settings:
681                         if os.path.isdir(self.settings["source_path"]) \
682                                 and os.path.exists(self.settings["autoresume_path"]+"unpack"):
683                                 """ Autoresume is valid, SEEDCACHE is valid """
684                                 unpack=False
685                                 invalid_snapshot=False
686
687                         elif os.path.isfile(self.settings["source_path"]) \
688                                 and self.settings["source_path_hash"]==clst_unpack_hash:
689                                 """ Autoresume is valid, tarball is valid """
690                                 unpack=False
691                                 invalid_snapshot=True
692
693                         elif os.path.isdir(self.settings["source_path"]) \
694                                 and not os.path.exists(self.settings["autoresume_path"]+\
695                                 "unpack"):
696                                 """ Autoresume is invalid, SEEDCACHE """
697                                 unpack=True
698                                 invalid_snapshot=False
699
700                         elif os.path.isfile(self.settings["source_path"]) \
701                                 and self.settings["source_path_hash"]!=clst_unpack_hash:
702                                 """ Autoresume is invalid, tarball """
703                                 unpack=True
704                                 invalid_snapshot=True
705                 else:
706                         """ No autoresume, SEEDCACHE """
707                         if "SEEDCACHE" in self.settings:
708                                 """ SEEDCACHE so let's run rsync and let it clean up """
709                                 if os.path.isdir(self.settings["source_path"]):
710                                         unpack=True
711                                         invalid_snapshot=False
712                                 elif os.path.isfile(self.settings["source_path"]):
713                                         """ Tarball so unpack and remove anything already there """
714                                         unpack=True
715                                         invalid_snapshot=True
716                                 """ No autoresume, no SEEDCACHE """
717                         else:
718                                 """ Tarball so unpack and remove anything already there """
719                                 if os.path.isfile(self.settings["source_path"]):
720                                         unpack=True
721                                         invalid_snapshot=True
722                                 elif os.path.isdir(self.settings["source_path"]):
723                                         """ We should never reach this, so something is very wrong """
724                                         raise CatalystError,\
725                                                 "source path is a dir but seedcache is not enabled"
726
727                 if unpack:
728                         self.mount_safety_check()
729
730                         if invalid_snapshot:
731                                 if "AUTORESUME" in self.settings:
732                                         print "No Valid Resume point detected, cleaning up..."
733
734                                 self.clear_autoresume()
735                                 self.clear_chroot()
736
737                         if not os.path.exists(self.settings["chroot_path"]):
738                                 os.makedirs(self.settings["chroot_path"])
739
740                         if not os.path.exists(self.settings["chroot_path"]+"/tmp"):
741                                 os.makedirs(self.settings["chroot_path"]+"/tmp",1777)
742
743                         if "PKGCACHE" in self.settings:
744                                 if not os.path.exists(self.settings["pkgcache_path"]):
745                                         os.makedirs(self.settings["pkgcache_path"],0755)
746
747                         if "KERNCACHE" in self.settings:
748                                 if not os.path.exists(self.settings["kerncache_path"]):
749                                         os.makedirs(self.settings["kerncache_path"],0755)
750
751                         print display_msg
752                         cmd(unpack_cmd,error_msg,env=self.env)
753
754                         if "source_path_hash" in self.settings:
755                                 myf=open(self.settings["autoresume_path"]+"unpack","w")
756                                 myf.write(self.settings["source_path_hash"])
757                                 myf.close()
758                         else:
759                                 touch(self.settings["autoresume_path"]+"unpack")
760                 else:
761                         print "Resume point detected, skipping unpack operation..."
762
763         def unpack_snapshot(self):
764                 unpack=True
765                 snapshot_hash=read_from_clst(self.settings["autoresume_path"]+\
766                         "unpack_portage")
767
768                 if "SNAPCACHE" in self.settings:
769                         snapshot_cache_hash=\
770                                 read_from_clst(self.settings["snapshot_cache_path"]+\
771                                 "catalyst-hash")
772                         destdir=self.settings["snapshot_cache_path"]
773                         if "bz2" == self.settings["chroot_path"][-3:]:
774                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+destdir
775                         else:
776                                 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+destdir
777                         unpack_errmsg="Error unpacking snapshot"
778                         cleanup_msg="Cleaning up invalid snapshot cache at \n\t"+\
779                                 self.settings["snapshot_cache_path"]+\
780                                 " (This can take a long time)..."
781                         cleanup_errmsg="Error removing existing snapshot cache directory."
782                         self.snapshot_lock_object=self.snapcache_lock
783
784                         if self.settings["snapshot_path_hash"]==snapshot_cache_hash:
785                                 print "Valid snapshot cache, skipping unpack of portage tree..."
786                                 unpack=False
787                 else:
788                         destdir=normpath(self.settings["chroot_path"]+"/usr/portage")
789                         cleanup_errmsg="Error removing existing snapshot directory."
790                         cleanup_msg=\
791                                 "Cleaning up existing portage tree (This can take a long time)..."
792                         if "bz2" == self.settings["chroot_path"][-3:]:
793                                 unpack_cmd="tar -I lbzip2 -xpf "+self.settings["snapshot_path"]+" -C "+\
794                                         self.settings["chroot_path"]+"/usr"
795                         else:
796                                 unpack_cmd="tar xpf "+self.settings["snapshot_path"]+" -C "+\
797                                         self.settings["chroot_path"]+"/usr"
798                         unpack_errmsg="Error unpacking snapshot"
799
800                         if "AUTORESUME" in self.settings \
801                                 and os.path.exists(self.settings["chroot_path"]+\
802                                         "/usr/portage/") \
803                                 and os.path.exists(self.settings["autoresume_path"]\
804                                         +"unpack_portage") \
805                                 and self.settings["snapshot_path_hash"] == snapshot_hash:
806                                         print \
807                                                 "Valid Resume point detected, skipping unpack of portage tree..."
808                                         unpack=False
809
810                 if unpack:
811                         if "SNAPCACHE" in self.settings:
812                                 self.snapshot_lock_object.write_lock()
813                         if os.path.exists(destdir):
814                                 print cleanup_msg
815                                 cleanup_cmd="rm -rf "+destdir
816                                 cmd(cleanup_cmd,cleanup_errmsg,env=self.env)
817                         if not os.path.exists(destdir):
818                                 os.makedirs(destdir,0755)
819
820                         print "Unpacking portage tree (This can take a long time) ..."
821                         cmd(unpack_cmd,unpack_errmsg,env=self.env)
822
823                         if "SNAPCACHE" in self.settings:
824                                 myf=open(self.settings["snapshot_cache_path"]+"catalyst-hash","w")
825                                 myf.write(self.settings["snapshot_path_hash"])
826                                 myf.close()
827                         else:
828                                 print "Setting snapshot autoresume point"
829                                 myf=open(self.settings["autoresume_path"]+"unpack_portage","w")
830                                 myf.write(self.settings["snapshot_path_hash"])
831                                 myf.close()
832
833                         if "SNAPCACHE" in self.settings:
834                                 self.snapshot_lock_object.unlock()
835
836         def config_profile_link(self):
837                 if "AUTORESUME" in self.settings \
838                         and os.path.exists(self.settings["autoresume_path"]+\
839                                 "config_profile_link"):
840                         print \
841                                 "Resume point detected, skipping config_profile_link operation..."
842                 else:
843                         # TODO: zmedico and I discussed making this a directory and pushing
844                         # in a parent file, as well as other user-specified configuration.
845                         print "Configuring profile link..."
846                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.profile",\
847                                         "Error zapping profile link",env=self.env)
848                         cmd("mkdir -p "+self.settings["chroot_path"]+"/etc/portage/")
849                         cmd("ln -sf ../../usr/portage/profiles/"+\
850                                 self.settings["target_profile"]+" "+\
851                                 self.settings["chroot_path"]+"/etc/portage/make.profile",\
852                                 "Error creating profile link",env=self.env)
853                         touch(self.settings["autoresume_path"]+"config_profile_link")
854
855         def setup_confdir(self):
856                 if "AUTORESUME" in self.settings \
857                         and os.path.exists(self.settings["autoresume_path"]+\
858                                 "setup_confdir"):
859                         print "Resume point detected, skipping setup_confdir operation..."
860                 else:
861                         if "portage_confdir" in self.settings:
862                                 print "Configuring /etc/portage..."
863                                 cmd("rsync -a "+self.settings["portage_confdir"]+"/ "+\
864                                         self.settings["chroot_path"]+"/etc/portage/",\
865                                         "Error copying /etc/portage",env=self.env)
866                                 touch(self.settings["autoresume_path"]+"setup_confdir")
867
868         def portage_overlay(self):
869                 """ We copy the contents of our overlays to /usr/local/portage """
870                 if "portage_overlay" in self.settings:
871                         for x in self.settings["portage_overlay"]:
872                                 if os.path.exists(x):
873                                         print "Copying overlay dir " +x
874                                         cmd("mkdir -p "+self.settings["chroot_path"]+\
875                                                 "/usr/local/portage",\
876                                                 "Could not make portage_overlay dir",env=self.env)
877                                         cmd("cp -R "+x+"/* "+self.settings["chroot_path"]+\
878                                                 "/usr/local/portage",\
879                                                 "Could not copy portage_overlay",env=self.env)
880
881         def root_overlay(self):
882                 """ Copy over the root_overlay """
883                 if self.settings["spec_prefix"]+"/root_overlay" in self.settings:
884                         for x in self.settings[self.settings["spec_prefix"]+\
885                                 "/root_overlay"]:
886                                 if os.path.exists(x):
887                                         print "Copying root_overlay: "+x
888                                         cmd("rsync -a "+x+"/ "+\
889                                                 self.settings["chroot_path"],\
890                                                 self.settings["spec_prefix"]+"/root_overlay: "+x+\
891                                                 " copy failed.",env=self.env)
892
893         def base_dirs(self):
894                 pass
895
896         def bind(self):
897                 for x in self.mounts:
898                         if not os.path.exists(self.settings["chroot_path"]+x):
899                                 os.makedirs(self.settings["chroot_path"]+x,0755)
900
901                         if not os.path.exists(self.mountmap[x]):
902                                 if not self.mountmap[x] == "tmpfs":
903                                         os.makedirs(self.mountmap[x],0755)
904
905                         src=self.mountmap[x]
906                         if "SNAPCACHE" in self.settings and x == "/usr/portage":
907                                 self.snapshot_lock_object.read_lock()
908                         if os.uname()[0] == "FreeBSD":
909                                 if src == "/dev":
910                                         retval=os.system("mount -t devfs none "+\
911                                                 self.settings["chroot_path"]+x)
912                                 else:
913                                         retval=os.system("mount_nullfs "+src+" "+\
914                                                 self.settings["chroot_path"]+x)
915                         else:
916                                 if src == "tmpfs":
917                                         if "var_tmpfs_portage" in self.settings:
918                                                 retval=os.system("mount -t tmpfs -o size="+\
919                                                         self.settings["var_tmpfs_portage"]+"G "+src+" "+\
920                                                         self.settings["chroot_path"]+x)
921                                 else:
922                                         retval=os.system("mount --bind "+src+" "+\
923                                                 self.settings["chroot_path"]+x)
924                         if retval!=0:
925                                 self.unbind()
926                                 raise CatalystError,"Couldn't bind mount "+src
927
928         def unbind(self):
929                 ouch=0
930                 mypath=self.settings["chroot_path"]
931                 myrevmounts=self.mounts[:]
932                 myrevmounts.reverse()
933                 """ Unmount in reverse order for nested bind-mounts """
934                 for x in myrevmounts:
935                         if not os.path.exists(mypath+x):
936                                 continue
937
938                         if not ismount(mypath+x):
939                                 continue
940
941                         retval=os.system("umount "+\
942                                 os.path.join(mypath,x.lstrip(os.path.sep)))
943
944                         if retval!=0:
945                                 warn("First attempt to unmount: "+mypath+x+" failed.")
946                                 warn("Killing any pids still running in the chroot")
947
948                                 self.kill_chroot_pids()
949
950                                 retval2=os.system("umount "+mypath+x)
951                                 if retval2!=0:
952                                         ouch=1
953                                         warn("Couldn't umount bind mount: "+mypath+x)
954
955                         if "SNAPCACHE" in self.settings and x == "/usr/portage":
956                                 try:
957                                         """
958                                         It's possible the snapshot lock object isn't created yet.
959                                         This is because mount safety check calls unbind before the
960                                         target is fully initialized
961                                         """
962                                         self.snapshot_lock_object.unlock()
963                                 except:
964                                         pass
965                 if ouch:
966                         """
967                         if any bind mounts really failed, then we need to raise
968                         this to potentially prevent an upcoming bash stage cleanup script
969                         from wiping our bind mounts.
970                         """
971                         raise CatalystError,\
972                                 "Couldn't umount one or more bind-mounts; aborting for safety."
973
974         def chroot_setup(self):
975                 self.makeconf=read_makeconf(self.settings["chroot_path"]+\
976                         "/etc/portage/make.conf")
977                 self.override_cbuild()
978                 self.override_chost()
979                 self.override_cflags()
980                 self.override_cxxflags()
981                 self.override_ldflags()
982                 if "AUTORESUME" in self.settings \
983                         and os.path.exists(self.settings["autoresume_path"]+"chroot_setup"):
984                         print "Resume point detected, skipping chroot_setup operation..."
985                 else:
986                         print "Setting up chroot..."
987
988                         #self.makeconf=read_makeconf(self.settings["chroot_path"]+"/etc/portage/make.conf")
989
990                         cmd("cp /etc/resolv.conf "+self.settings["chroot_path"]+"/etc",\
991                                 "Could not copy resolv.conf into place.",env=self.env)
992
993                         """ Copy over the envscript, if applicable """
994                         if "ENVSCRIPT" in self.settings:
995                                 if not os.path.exists(self.settings["ENVSCRIPT"]):
996                                         raise CatalystError,\
997                                                 "Can't find envscript "+self.settings["ENVSCRIPT"]
998
999                                 print "\nWarning!!!!"
1000                                 print "\tOverriding certain env variables may cause catastrophic failure."
1001                                 print "\tIf your build fails look here first as the possible problem."
1002                                 print "\tCatalyst assumes you know what you are doing when setting"
1003                                 print "\t\tthese variables."
1004                                 print "\tCatalyst Maintainers use VERY minimal envscripts if used at all"
1005                                 print "\tYou have been warned\n"
1006
1007                                 cmd("cp "+self.settings["ENVSCRIPT"]+" "+\
1008                                         self.settings["chroot_path"]+"/tmp/envscript",\
1009                                         "Could not copy envscript into place.",env=self.env)
1010
1011                         """
1012                         Copy over /etc/hosts from the host in case there are any
1013                         specialties in there
1014                         """
1015                         if os.path.exists(self.settings["chroot_path"]+"/etc/hosts"):
1016                                 cmd("mv "+self.settings["chroot_path"]+"/etc/hosts "+\
1017                                         self.settings["chroot_path"]+"/etc/hosts.catalyst",\
1018                                         "Could not backup /etc/hosts",env=self.env)
1019                                 cmd("cp /etc/hosts "+self.settings["chroot_path"]+"/etc/hosts",\
1020                                         "Could not copy /etc/hosts",env=self.env)
1021
1022                         """ Modify and write out make.conf (for the chroot) """
1023                         cmd("rm -f "+self.settings["chroot_path"]+"/etc/portage/make.conf",\
1024                                 "Could not remove "+self.settings["chroot_path"]+\
1025                                 "/etc/portage/make.conf",env=self.env)
1026                         myf=open(self.settings["chroot_path"]+"/etc/portage/make.conf","w")
1027                         myf.write("# These settings were set by the catalyst build script that automatically\n# built this stage.\n")
1028                         myf.write("# Please consult /usr/share/portage/config/make.conf.example for a more\n# detailed example.\n")
1029                         if "CFLAGS" in self.settings:
1030                                 myf.write('CFLAGS="'+self.settings["CFLAGS"]+'"\n')
1031                         if "CXXFLAGS" in self.settings:
1032                                 if self.settings["CXXFLAGS"]!=self.settings["CFLAGS"]:
1033                                         myf.write('CXXFLAGS="'+self.settings["CXXFLAGS"]+'"\n')
1034                                 else:
1035                                         myf.write('CXXFLAGS="${CFLAGS}"\n')
1036                         else:
1037                                 myf.write('CXXFLAGS="${CFLAGS}"\n')
1038
1039                         if "LDFLAGS" in self.settings:
1040                                 myf.write("# LDFLAGS is unsupported.  USE AT YOUR OWN RISK!\n")
1041                                 myf.write('LDFLAGS="'+self.settings["LDFLAGS"]+'"\n')
1042                         if "CBUILD" in self.settings:
1043                                 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")
1044                                 myf.write('CBUILD="'+self.settings["CBUILD"]+'"\n')
1045
1046                         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")
1047                         myf.write('CHOST="'+self.settings["CHOST"]+'"\n')
1048
1049                         """ Figure out what our USE vars are for building """
1050                         myusevars=[]
1051                         if "HOSTUSE" in self.settings:
1052                                 myusevars.extend(self.settings["HOSTUSE"])
1053
1054                         if "use" in self.settings:
1055                                 myusevars.extend(self.settings["use"])
1056
1057                         if myusevars:
1058                                 myf.write("# These are the USE flags that were used in addition to what is provided by the\n# profile used for building.\n")
1059                                 myusevars = sorted(set(myusevars))
1060                                 myf.write('USE="'+string.join(myusevars)+'"\n')
1061                                 if '-*' in myusevars:
1062                                         print "\nWarning!!!  "
1063                                         print "\tThe use of -* in "+self.settings["spec_prefix"]+\
1064                                                 "/use will cause portage to ignore"
1065                                         print "\tpackage.use in the profile and portage_confdir. You've been warned!"
1066
1067                         myf.write('PORTDIR="/usr/portage"\n')
1068                         myf.write('DISTDIR="${PORTDIR}/distfiles"\n')
1069                         myf.write('PKGDIR="${PORTDIR}/packages"\n')
1070
1071                         """ Setup the portage overlay """
1072                         if "portage_overlay" in self.settings:
1073                                 myf.write('PORTDIR_OVERLAY="/usr/local/portage"\n')
1074
1075                         myf.close()
1076                         cmd("cp "+self.settings["chroot_path"]+"/etc/portage/make.conf "+\
1077                                 self.settings["chroot_path"]+"/etc/portage/make.conf.catalyst",\
1078                                 "Could not backup /etc/portage/make.conf",env=self.env)
1079                         touch(self.settings["autoresume_path"]+"chroot_setup")
1080
1081         def fsscript(self):
1082                 if "AUTORESUME" in self.settings \
1083                         and os.path.exists(self.settings["autoresume_path"]+"fsscript"):
1084                         print "Resume point detected, skipping fsscript operation..."
1085                 else:
1086                         if "fsscript" in self.settings:
1087                                 if os.path.exists(self.settings["controller_file"]):
1088                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1089                                                 " fsscript","fsscript script failed.",env=self.env)
1090                                         touch(self.settings["autoresume_path"]+"fsscript")
1091
1092         def rcupdate(self):
1093                 if "AUTORESUME" in self.settings \
1094                         and os.path.exists(self.settings["autoresume_path"]+"rcupdate"):
1095                         print "Resume point detected, skipping rcupdate operation..."
1096                 else:
1097                         if os.path.exists(self.settings["controller_file"]):
1098                                 cmd("/bin/bash "+self.settings["controller_file"]+" rc-update",\
1099                                         "rc-update script failed.",env=self.env)
1100                                 touch(self.settings["autoresume_path"]+"rcupdate")
1101
1102         def clean(self):
1103                 if "AUTORESUME" in self.settings \
1104                         and os.path.exists(self.settings["autoresume_path"]+"clean"):
1105                         print "Resume point detected, skipping clean operation..."
1106                 else:
1107                         for x in self.settings["cleanables"]:
1108                                 print "Cleaning chroot: "+x+"... "
1109                                 cmd("rm -rf "+self.settings["destpath"]+x,"Couldn't clean "+\
1110                                         x,env=self.env)
1111
1112                 """ Put /etc/hosts back into place """
1113                 if os.path.exists(self.settings["chroot_path"]+"/etc/hosts.catalyst"):
1114                         cmd("mv -f "+self.settings["chroot_path"]+"/etc/hosts.catalyst "+\
1115                                 self.settings["chroot_path"]+"/etc/hosts",\
1116                                 "Could not replace /etc/hosts",env=self.env)
1117
1118                 """ Remove our overlay """
1119                 if os.path.exists(self.settings["chroot_path"]+"/usr/local/portage"):
1120                         cmd("rm -rf "+self.settings["chroot_path"]+"/usr/local/portage",\
1121                                 "Could not remove /usr/local/portage",env=self.env)
1122                         cmd("sed -i '/^PORTDIR_OVERLAY/d' "+self.settings["chroot_path"]+\
1123                                 "/etc/portage/make.conf",\
1124                                 "Could not remove PORTDIR_OVERLAY from make.conf",env=self.env)
1125
1126                 """ Clean up old and obsoleted files in /etc """
1127                 if os.path.exists(self.settings["stage_path"]+"/etc"):
1128                         cmd("find "+self.settings["stage_path"]+\
1129                                 "/etc -maxdepth 1 -name \"*-\" | xargs rm -f",\
1130                                 "Could not remove stray files in /etc",env=self.env)
1131
1132                 if os.path.exists(self.settings["controller_file"]):
1133                         cmd("/bin/bash "+self.settings["controller_file"]+" clean",\
1134                                 "clean script failed.",env=self.env)
1135                         touch(self.settings["autoresume_path"]+"clean")
1136
1137         def empty(self):
1138                 if "AUTORESUME" in self.settings \
1139                         and os.path.exists(self.settings["autoresume_path"]+"empty"):
1140                         print "Resume point detected, skipping empty operation..."
1141                 else:
1142                         if self.settings["spec_prefix"]+"/empty" in self.settings:
1143                                 if type(self.settings[self.settings["spec_prefix"]+\
1144                                         "/empty"])==types.StringType:
1145                                         self.settings[self.settings["spec_prefix"]+"/empty"]=\
1146                                                 self.settings[self.settings["spec_prefix"]+\
1147                                                 "/empty"].split()
1148                                 for x in self.settings[self.settings["spec_prefix"]+"/empty"]:
1149                                         myemp=self.settings["destpath"]+x
1150                                         if not os.path.isdir(myemp) or os.path.islink(myemp):
1151                                                 print x,"not a directory or does not exist, skipping 'empty' operation."
1152                                                 continue
1153                                         print "Emptying directory",x
1154                                         """
1155                                         stat the dir, delete the dir, recreate the dir and set
1156                                         the proper perms and ownership
1157                                         """
1158                                         mystat=os.stat(myemp)
1159                                         shutil.rmtree(myemp)
1160                                         os.makedirs(myemp,0755)
1161                                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1162                                         os.chmod(myemp,mystat[ST_MODE])
1163                         touch(self.settings["autoresume_path"]+"empty")
1164
1165         def remove(self):
1166                 if "AUTORESUME" in self.settings \
1167                         and os.path.exists(self.settings["autoresume_path"]+"remove"):
1168                         print "Resume point detected, skipping remove operation..."
1169                 else:
1170                         if self.settings["spec_prefix"]+"/rm" in self.settings:
1171                                 for x in self.settings[self.settings["spec_prefix"]+"/rm"]:
1172                                         """
1173                                         We're going to shell out for all these cleaning
1174                                         operations, so we get easy glob handling.
1175                                         """
1176                                         print "livecd: removing "+x
1177                                         os.system("rm -rf "+self.settings["chroot_path"]+x)
1178                                 try:
1179                                         if os.path.exists(self.settings["controller_file"]):
1180                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1181                                                         " clean","Clean  failed.",env=self.env)
1182                                                 touch(self.settings["autoresume_path"]+"remove")
1183                                 except:
1184                                         self.unbind()
1185                                         raise
1186
1187         def preclean(self):
1188                 if "AUTORESUME" in self.settings \
1189                         and os.path.exists(self.settings["autoresume_path"]+"preclean"):
1190                         print "Resume point detected, skipping preclean operation..."
1191                 else:
1192                         try:
1193                                 if os.path.exists(self.settings["controller_file"]):
1194                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1195                                                 " preclean","preclean script failed.",env=self.env)
1196                                         touch(self.settings["autoresume_path"]+"preclean")
1197
1198                         except:
1199                                 self.unbind()
1200                                 raise CatalystError, "Build failed, could not execute preclean"
1201
1202         def capture(self):
1203                 if "AUTORESUME" in self.settings \
1204                         and os.path.exists(self.settings["autoresume_path"]+"capture"):
1205                         print "Resume point detected, skipping capture operation..."
1206                 else:
1207                         """ Capture target in a tarball """
1208                         mypath=self.settings["target_path"].split("/")
1209                         """ Remove filename from path """
1210                         mypath=string.join(mypath[:-1],"/")
1211
1212                         """ Now make sure path exists """
1213                         if not os.path.exists(mypath):
1214                                 os.makedirs(mypath)
1215
1216                         print "Creating stage tarball..."
1217
1218                         cmd("tar -I lbzip2 -cpf "+self.settings["target_path"]+" -C "+\
1219                                 self.settings["stage_path"]+" .",\
1220                                 "Couldn't create stage tarball",env=self.env)
1221
1222                         self.gen_contents_file(self.settings["target_path"])
1223                         self.gen_digest_file(self.settings["target_path"])
1224
1225                         touch(self.settings["autoresume_path"]+"capture")
1226
1227         def run_local(self):
1228                 if "AUTORESUME" in self.settings \
1229                         and os.path.exists(self.settings["autoresume_path"]+"run_local"):
1230                         print "Resume point detected, skipping run_local operation..."
1231                 else:
1232                         try:
1233                                 if os.path.exists(self.settings["controller_file"]):
1234                                         cmd("/bin/bash "+self.settings["controller_file"]+" run",\
1235                                                 "run script failed.",env=self.env)
1236                                         touch(self.settings["autoresume_path"]+"run_local")
1237
1238                         except CatalystError:
1239                                 self.unbind()
1240                                 raise CatalystError,"Stage build aborting due to error."
1241
1242         def setup_environment(self):
1243                 """
1244                 Modify the current environment. This is an ugly hack that should be
1245                 fixed. We need this to use the os.system() call since we can't
1246                 specify our own environ
1247                 """
1248                 for x in self.settings.keys():
1249                         """ Sanitize var names by doing "s|/-.|_|g" """
1250                         varname="clst_"+string.replace(x,"/","_")
1251                         varname=string.replace(varname,"-","_")
1252                         varname=string.replace(varname,".","_")
1253                         if type(self.settings[x])==types.StringType:
1254                                 """ Prefix to prevent namespace clashes """
1255                                 #os.environ[varname]=self.settings[x]
1256                                 self.env[varname]=self.settings[x]
1257                         elif type(self.settings[x])==types.ListType:
1258                                 #os.environ[varname]=string.join(self.settings[x])
1259                                 self.env[varname]=string.join(self.settings[x])
1260                         elif type(self.settings[x])==types.BooleanType:
1261                                 if self.settings[x]:
1262                                         self.env[varname]="true"
1263                                 else:
1264                                         self.env[varname]="false"
1265                 if "makeopts" in self.settings:
1266                         self.env["MAKEOPTS"]=self.settings["makeopts"]
1267
1268         def run(self):
1269                 self.chroot_lock.write_lock()
1270
1271                 """ Kill any pids in the chroot "" """
1272                 self.kill_chroot_pids()
1273
1274                 """ Check for mounts right away and abort if we cannot unmount them """
1275                 self.mount_safety_check()
1276
1277                 if "CLEAR_AUTORESUME" in self.settings:
1278                         self.clear_autoresume()
1279
1280                 if "PURGETMPONLY" in self.settings:
1281                         self.purge()
1282                         return
1283
1284                 if "PURGEONLY" in self.settings:
1285                         self.purge()
1286                         return
1287
1288                 if "PURGE" in self.settings:
1289                         self.purge()
1290
1291                 for x in self.settings["action_sequence"]:
1292                         print "--- Running action sequence: "+x
1293                         sys.stdout.flush()
1294                         try:
1295                                 apply(getattr(self,x))
1296                         except:
1297                                 self.mount_safety_check()
1298                                 raise
1299
1300                 self.chroot_lock.unlock()
1301
1302         def unmerge(self):
1303                 if "AUTORESUME" in self.settings \
1304                         and os.path.exists(self.settings["autoresume_path"]+"unmerge"):
1305                         print "Resume point detected, skipping unmerge operation..."
1306                 else:
1307                         if self.settings["spec_prefix"]+"/unmerge" in self.settings:
1308                                 if type(self.settings[self.settings["spec_prefix"]+\
1309                                         "/unmerge"])==types.StringType:
1310                                         self.settings[self.settings["spec_prefix"]+"/unmerge"]=\
1311                                                 [self.settings[self.settings["spec_prefix"]+"/unmerge"]]
1312                                 myunmerge=\
1313                                         self.settings[self.settings["spec_prefix"]+"/unmerge"][:]
1314
1315                                 for x in range(0,len(myunmerge)):
1316                                         """
1317                                         Surround args with quotes for passing to bash, allows
1318                                         things like "<" to remain intact
1319                                         """
1320                                         myunmerge[x]="'"+myunmerge[x]+"'"
1321                                 myunmerge=string.join(myunmerge)
1322
1323                                 """ Before cleaning, unmerge stuff """
1324                                 try:
1325                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1326                                                 " unmerge "+ myunmerge,"Unmerge script failed.",\
1327                                                 env=self.env)
1328                                         print "unmerge shell script"
1329                                 except CatalystError:
1330                                         self.unbind()
1331                                         raise
1332                                 touch(self.settings["autoresume_path"]+"unmerge")
1333
1334         def target_setup(self):
1335                 if "AUTORESUME" in self.settings \
1336                         and os.path.exists(self.settings["autoresume_path"]+"target_setup"):
1337                         print "Resume point detected, skipping target_setup operation..."
1338                 else:
1339                         print "Setting up filesystems per filesystem type"
1340                         cmd("/bin/bash "+self.settings["controller_file"]+\
1341                                 " target_image_setup "+ self.settings["target_path"],\
1342                                 "target_image_setup script failed.",env=self.env)
1343                         touch(self.settings["autoresume_path"]+"target_setup")
1344
1345         def setup_overlay(self):
1346                 if "AUTORESUME" in self.settings \
1347                 and os.path.exists(self.settings["autoresume_path"]+"setup_overlay"):
1348                         print "Resume point detected, skipping setup_overlay operation..."
1349                 else:
1350                         if self.settings["spec_prefix"]+"/overlay" in self.settings:
1351                                 for x in self.settings[self.settings["spec_prefix"]+"/overlay"]:
1352                                         if os.path.exists(x):
1353                                                 cmd("rsync -a "+x+"/ "+\
1354                                                         self.settings["target_path"],\
1355                                                         self.settings["spec_prefix"]+"overlay: "+x+\
1356                                                         " copy failed.",env=self.env)
1357                                 touch(self.settings["autoresume_path"]+"setup_overlay")
1358
1359         def create_iso(self):
1360                 if "AUTORESUME" in self.settings \
1361                         and os.path.exists(self.settings["autoresume_path"]+"create_iso"):
1362                         print "Resume point detected, skipping create_iso operation..."
1363                 else:
1364                         """ Create the ISO """
1365                         if "iso" in self.settings:
1366                                 cmd("/bin/bash "+self.settings["controller_file"]+" iso "+\
1367                                         self.settings["iso"],"ISO creation script failed.",\
1368                                         env=self.env)
1369                                 self.gen_contents_file(self.settings["iso"])
1370                                 self.gen_digest_file(self.settings["iso"])
1371                                 touch(self.settings["autoresume_path"]+"create_iso")
1372                         else:
1373                                 print "WARNING: livecd/iso was not defined."
1374                                 print "An ISO Image will not be created."
1375
1376         def build_packages(self):
1377                 if "AUTORESUME" in self.settings \
1378                         and os.path.exists(self.settings["autoresume_path"]+\
1379                                 "build_packages"):
1380                         print "Resume point detected, skipping build_packages operation..."
1381                 else:
1382                         if self.settings["spec_prefix"]+"/packages" in self.settings:
1383                                 if "AUTORESUME" in self.settings \
1384                                         and os.path.exists(self.settings["autoresume_path"]+\
1385                                                 "build_packages"):
1386                                         print "Resume point detected, skipping build_packages operation..."
1387                                 else:
1388                                         mypack=\
1389                                                 list_bashify(self.settings[self.settings["spec_prefix"]\
1390                                                 +"/packages"])
1391                                         try:
1392                                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1393                                                         " build_packages "+mypack,\
1394                                                         "Error in attempt to build packages",env=self.env)
1395                                                 touch(self.settings["autoresume_path"]+"build_packages")
1396                                         except CatalystError:
1397                                                 self.unbind()
1398                                                 raise CatalystError,self.settings["spec_prefix"]+\
1399                                                         "build aborting due to error."
1400
1401         def build_kernel(self):
1402                 "Build all configured kernels"
1403                 if "AUTORESUME" in self.settings \
1404                         and os.path.exists(self.settings["autoresume_path"]+"build_kernel"):
1405                         print "Resume point detected, skipping build_kernel operation..."
1406                 else:
1407                         if "boot/kernel" in self.settings:
1408                                 try:
1409                                         mynames=self.settings["boot/kernel"]
1410                                         if type(mynames)==types.StringType:
1411                                                 mynames=[mynames]
1412                                         """
1413                                         Execute the script that sets up the kernel build environment
1414                                         """
1415                                         cmd("/bin/bash "+self.settings["controller_file"]+\
1416                                                 " pre-kmerge ","Runscript pre-kmerge failed",\
1417                                                 env=self.env)
1418                                         for kname in mynames:
1419                                                 self._build_kernel(kname=kname)
1420                                         touch(self.settings["autoresume_path"]+"build_kernel")
1421                                 except CatalystError:
1422                                         self.unbind()
1423                                         raise CatalystError,\
1424                                                 "build aborting due to kernel build error."
1425
1426         def _build_kernel(self, kname):
1427                 "Build a single configured kernel by name"
1428                 if "AUTORESUME" in self.settings \
1429                         and os.path.exists(self.settings["autoresume_path"]\
1430                                 +"build_kernel_"+kname):
1431                         print "Resume point detected, skipping build_kernel for "+kname+" operation..."
1432                         return
1433                 self._copy_kernel_config(kname=kname)
1434
1435                 """
1436                 If we need to pass special options to the bootloader
1437                 for this kernel put them into the environment
1438                 """
1439                 if "boot/kernel/"+kname+"/kernelopts" in self.settings:
1440                         myopts=self.settings["boot/kernel/"+kname+\
1441                                 "/kernelopts"]
1442
1443                         if type(myopts) != types.StringType:
1444                                 myopts = string.join(myopts)
1445                                 self.env[kname+"_kernelopts"]=myopts
1446
1447                         else:
1448                                 self.env[kname+"_kernelopts"]=""
1449
1450                 if "boot/kernel/"+kname+"/extraversion" not in self.settings:
1451                         self.settings["boot/kernel/"+kname+\
1452                                 "/extraversion"]=""
1453
1454                 self.env["clst_kextraversion"]=\
1455                         self.settings["boot/kernel/"+kname+\
1456                         "/extraversion"]
1457
1458                 self._copy_initramfs_overlay(kname=kname)
1459
1460                 """ Execute the script that builds the kernel """
1461                 cmd("/bin/bash "+self.settings["controller_file"]+\
1462                         " kernel "+kname,\
1463                         "Runscript kernel build failed",env=self.env)
1464
1465                 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1466                         if os.path.exists(self.settings["chroot_path"]+\
1467                                 "/tmp/initramfs_overlay/"):
1468                                 print "Cleaning up temporary overlay dir"
1469                                 cmd("rm -R "+self.settings["chroot_path"]+\
1470                                         "/tmp/initramfs_overlay/",env=self.env)
1471
1472                 touch(self.settings["autoresume_path"]+\
1473                         "build_kernel_"+kname)
1474
1475                 """
1476                 Execute the script that cleans up the kernel build
1477                 environment
1478                 """
1479                 cmd("/bin/bash "+self.settings["controller_file"]+\
1480                         " post-kmerge ",
1481                         "Runscript post-kmerge failed",env=self.env)
1482
1483         def _copy_kernel_config(self, kname):
1484                 if "boot/kernel/"+kname+"/config" in self.settings:
1485                         if not os.path.exists(self.settings["boot/kernel/"+kname+"/config"]):
1486                                 self.unbind()
1487                                 raise CatalystError,\
1488                                         "Can't find kernel config: "+\
1489                                         self.settings["boot/kernel/"+kname+\
1490                                         "/config"]
1491
1492                         try:
1493                                 cmd("cp "+self.settings["boot/kernel/"+kname+\
1494                                         "/config"]+" "+\
1495                                         self.settings["chroot_path"]+"/var/tmp/"+\
1496                                         kname+".config",\
1497                                         "Couldn't copy kernel config: "+\
1498                                         self.settings["boot/kernel/"+kname+\
1499                                         "/config"],env=self.env)
1500
1501                         except CatalystError:
1502                                 self.unbind()
1503
1504         def _copy_initramfs_overlay(self, kname):
1505                 if "boot/kernel/"+kname+"/initramfs_overlay" in self.settings:
1506                         if os.path.exists(self.settings["boot/kernel/"+\
1507                                 kname+"/initramfs_overlay"]):
1508                                 print "Copying initramfs_overlay dir "+\
1509                                         self.settings["boot/kernel/"+kname+\
1510                                         "/initramfs_overlay"]
1511
1512                                 cmd("mkdir -p "+\
1513                                         self.settings["chroot_path"]+\
1514                                         "/tmp/initramfs_overlay/"+\
1515                                         self.settings["boot/kernel/"+kname+\
1516                                         "/initramfs_overlay"],env=self.env)
1517
1518                                 cmd("cp -R "+self.settings["boot/kernel/"+\
1519                                         kname+"/initramfs_overlay"]+"/* "+\
1520                                         self.settings["chroot_path"]+\
1521                                         "/tmp/initramfs_overlay/"+\
1522                                         self.settings["boot/kernel/"+kname+\
1523                                         "/initramfs_overlay"],env=self.env)
1524
1525         def bootloader(self):
1526                 if "AUTORESUME" in self.settings \
1527                         and os.path.exists(self.settings["autoresume_path"]+"bootloader"):
1528                         print "Resume point detected, skipping bootloader operation..."
1529                 else:
1530                         try:
1531                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1532                                         " bootloader " + self.settings["target_path"],\
1533                                         "Bootloader script failed.",env=self.env)
1534                                 touch(self.settings["autoresume_path"]+"bootloader")
1535                         except CatalystError:
1536                                 self.unbind()
1537                                 raise CatalystError,"Script aborting due to error."
1538
1539         def livecd_update(self):
1540                 if "AUTORESUME" in self.settings \
1541                         and os.path.exists(self.settings["autoresume_path"]+\
1542                                 "livecd_update"):
1543                         print "Resume point detected, skipping build_packages operation..."
1544                 else:
1545                         try:
1546                                 cmd("/bin/bash "+self.settings["controller_file"]+\
1547                                         " livecd-update","livecd-update failed.",env=self.env)
1548                                 touch(self.settings["autoresume_path"]+"livecd_update")
1549
1550                         except CatalystError:
1551                                 self.unbind()
1552                                 raise CatalystError,"build aborting due to livecd_update error."
1553
1554         def clear_chroot(self):
1555                 myemp=self.settings["chroot_path"]
1556                 if os.path.isdir(myemp):
1557                         print "Emptying directory",myemp
1558                         """
1559                         stat the dir, delete the dir, recreate the dir and set
1560                         the proper perms and ownership
1561                         """
1562                         mystat=os.stat(myemp)
1563                         #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1564                         """ There's no easy way to change flags recursively in python """
1565                         if os.uname()[0] == "FreeBSD":
1566                                 os.system("chflags -R noschg "+myemp)
1567                         shutil.rmtree(myemp)
1568                         os.makedirs(myemp,0755)
1569                         os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1570                         os.chmod(myemp,mystat[ST_MODE])
1571
1572         def clear_packages(self):
1573                 if "PKGCACHE" in self.settings:
1574                         print "purging the pkgcache ..."
1575
1576                         myemp=self.settings["pkgcache_path"]
1577                         if os.path.isdir(myemp):
1578                                 print "Emptying directory",myemp
1579                                 """
1580                                 stat the dir, delete the dir, recreate the dir and set
1581                                 the proper perms and ownership
1582                                 """
1583                                 mystat=os.stat(myemp)
1584                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1585                                 shutil.rmtree(myemp)
1586                                 os.makedirs(myemp,0755)
1587                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1588                                 os.chmod(myemp,mystat[ST_MODE])
1589
1590         def clear_kerncache(self):
1591                 if "KERNCACHE" in self.settings:
1592                         print "purging the kerncache ..."
1593
1594                         myemp=self.settings["kerncache_path"]
1595                         if os.path.isdir(myemp):
1596                                 print "Emptying directory",myemp
1597                                 """
1598                                 stat the dir, delete the dir, recreate the dir and set
1599                                 the proper perms and ownership
1600                                 """
1601                                 mystat=os.stat(myemp)
1602                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env=self.env)
1603                                 shutil.rmtree(myemp)
1604                                 os.makedirs(myemp,0755)
1605                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1606                                 os.chmod(myemp,mystat[ST_MODE])
1607
1608         def clear_autoresume(self):
1609                 """ Clean resume points since they are no longer needed """
1610                 if "AUTORESUME" in self.settings:
1611                         print "Removing AutoResume Points: ..."
1612                 myemp=self.settings["autoresume_path"]
1613                 if os.path.isdir(myemp):
1614                                 if "AUTORESUME" in self.settings:
1615                                         print "Emptying directory",myemp
1616                                 """
1617                                 stat the dir, delete the dir, recreate the dir and set
1618                                 the proper perms and ownership
1619                                 """
1620                                 mystat=os.stat(myemp)
1621                                 if os.uname()[0] == "FreeBSD":
1622                                         cmd("chflags -R noschg "+myemp,\
1623                                                 "Could not remove immutable flag for file "\
1624                                                 +myemp)
1625                                 #cmd("rm -rf "+myemp, "Could not remove existing file: "+myemp,env-self.env)
1626                                 shutil.rmtree(myemp)
1627                                 os.makedirs(myemp,0755)
1628                                 os.chown(myemp,mystat[ST_UID],mystat[ST_GID])
1629                                 os.chmod(myemp,mystat[ST_MODE])
1630
1631         def gen_contents_file(self,file):
1632                 if os.path.exists(file+".CONTENTS"):
1633                         os.remove(file+".CONTENTS")
1634                 if "contents" in self.settings:
1635                         if os.path.exists(file):
1636                                 myf=open(file+".CONTENTS","w")
1637                                 keys={}
1638                                 for i in self.settings["contents"].split():
1639                                         keys[i]=1
1640                                         array=keys.keys()
1641                                         array.sort()
1642                                 for j in array:
1643                                         contents=generate_contents(file,contents_function=j,\
1644                                                 verbose="VERBOSE" in self.settings)
1645                                         if contents:
1646                                                 myf.write(contents)
1647                                 myf.close()
1648
1649         def gen_digest_file(self,file):
1650                 if os.path.exists(file+".DIGESTS"):
1651                         os.remove(file+".DIGESTS")
1652                 if "digests" in self.settings:
1653                         if os.path.exists(file):
1654                                 myf=open(file+".DIGESTS","w")
1655                                 keys={}
1656                                 for i in self.settings["digests"].split():
1657                                         keys[i]=1
1658                                         array=keys.keys()
1659                                         array.sort()
1660                                 for f in [file, file+'.CONTENTS']:
1661                                         if os.path.exists(f):
1662                                                 if "all" in array:
1663                                                         for k in hash_map.keys():
1664                                                                 hash=generate_hash(f,hash_function=k,verbose=\
1665                                                                         "VERBOSE" in self.settings)
1666                                                                 myf.write(hash)
1667                                                 else:
1668                                                         for j in array:
1669                                                                 hash=generate_hash(f,hash_function=j,verbose=\
1670                                                                         "VERBOSE" in self.settings)
1671                                                                 myf.write(hash)
1672                                 myf.close()
1673
1674         def purge(self):
1675                 countdown(10,"Purging Caches ...")
1676                 if any(k in self.settings for k in ("PURGE","PURGEONLY","PURGETMPONLY")):
1677                         print "clearing autoresume ..."
1678                         self.clear_autoresume()
1679
1680                         print "clearing chroot ..."
1681                         self.clear_chroot()
1682
1683                         if "PURGETMPONLY" not in self.settings:
1684                                 print "clearing package cache ..."
1685                                 self.clear_packages()
1686
1687                         print "clearing kerncache ..."
1688                         self.clear_kerncache()
1689
1690 # vim: ts=4 sw=4 sta et sts=4 ai