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