allow file_check to proceed if key is not in use
[catalyst.git] / catalyst
1 #!/usr/bin/python
2 # Copyright 1999-2005 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header: /var/cvsroot/gentoo/src/catalyst/catalyst,v 1.91 2005/10/06 15:45:28 rocket Exp $
5
6 # Maintained in full by:
7 # Eric Edgar <rocket@gentoo.org>
8 # Chris Gianelloni <wolf31o2@gentoo.org>
9
10 import os,sys,imp,string,getopt
11 import pdb
12 __maintainer__="Chris Gianelloni <wolf31o2@gentoo.org>"
13 __version__="2.0._pre20050930"
14
15 conf_values={}
16
17 def usage():
18         print "Usage catalyst [options] [-C variable=value...] [ -s identifier]"
19         print " -a --clear-autoresume   clear autoresume flags"
20         print " -c --config             use specified configuration file"
21         print " -C --cli                catalyst commandline (MUST BE LAST OPTION)"
22         print " -d --debug              enable debugging"
23         print " -f --file               read specfile"
24         print " -F --fetchonly          fetch files only"
25         print " -h --help               print this help message"
26         print " -p --purge              clear tmp dirs,package cache and autoresume flags"
27         print " -s --snapshot           generate a Portage snapshot"
28         print " -v --version            display version information"
29         print " -V --verbose            verbose output"
30         print
31         print "Usage examples:"
32         print
33         print "Using the commandline option (-C, --cli) to build a Portage snapshot:"
34         print "catalyst -C target=snapshot version_stamp=my_date"
35         print
36         print "Using the snapshot option (-s, --snapshot) to build a Portage snapshot:"
37         print "catalyst -s 2005.0"
38         print
39         print "Using the specfile option (-f, --file) to build a stage target:"
40         print "catalyst -f stage1-specfile.spec"
41
42 def version():
43         print "Gentoo Catalyst, version "+__version__
44         print "Copyright 2003-2005 The Gentoo Foundation"
45         print "Distributed under the GNU General Public License version 2\n"
46         
47
48 def parse_config(myconfig):
49         # search a couple of different areas for the main config file
50         myconf={}
51         config_file=""
52
53         confdefaults={ "storedir":"/var/tmp/catalyst",\
54                 "sharedir":"/usr/share/catalyst","distdir":"/usr/portage/distfiles",\
55                 "portdir":"/usr/portage","options":"",\
56                 "snapshot_cache":"/var/tmp/catalyst/snapshot_cache" }
57                 
58         # first, try the one passed (presumably from the cmdline)
59         if myconfig:
60                 if os.path.exists(myconfig):
61                         print "Using command line specified Catalyst configuration file, "+myconfig
62                         config_file=myconfig
63
64                 else:
65                         print "!!! catalyst: Could not use specified configuration file "+\
66                                 myconfig
67                         sys.exit(1)
68         
69         # next, try the default location
70         elif os.path.exists("/etc/catalyst/catalyst.conf"):
71                 print "Using default Catalyst configuration file, /etc/catalyst/catalyst.conf"
72                 config_file="/etc/catalyst/catalyst.conf"
73         
74         # can't find a config file (we are screwed), so bail out
75         else:
76                 print "!!! catalyst: Could not find a suitable configuration file"
77                 sys.exit(1)
78
79         # now, try and parse the config file "config_file"
80         try:
81                 execfile(config_file, myconf, myconf)
82         
83         except:
84                 print "!!! catalyst: Unable to parse configuration file, "+myconfig
85                 sys.exit(1)
86         
87         # now, load up the values into conf_values so that we can use them
88         for x in confdefaults.keys():
89                 if myconf.has_key(x):
90                         print "Setting",x,"to config file value \""+myconf[x]+"\""
91                         conf_values[x]=myconf[x]
92                 else:
93                         print "Setting",x,"to default value \""+confdefaults[x]+"\""
94                         conf_values[x]=confdefaults[x]
95
96         # parse out the rest of the options from the config file
97         if "ccache" in string.split(conf_values["options"]):
98                 print "Compiler cache support enabled."
99                 conf_values["CCACHE"]="1"
100
101         if "pkgcache" in string.split(conf_values["options"]):
102                 print "Package cache support enabled."
103                 conf_values["PKGCACHE"]="1"
104         
105         if "snapcache" in string.split(conf_values["options"]):
106                 print "Snapshot cache support enabled."
107                 conf_values["SNAPCACHE"]="1"
108         
109         if "seedcache" in string.split(conf_values["options"]):
110                 print "Seed cache support enabled."
111                 conf_values["SEEDCACHE"]="1"
112
113         if "kerncache" in string.split(conf_values["options"]):
114                 print "Kernel cache support enabled."
115                 conf_values["KERNCACHE"]="1"
116         
117         if "distcc" in string.split(conf_values["options"]):
118                 print "Distcc support enabled."
119                 conf_values["DISTCC"]="1"
120
121         if "autoresume" in string.split(conf_values["options"]):
122                 print "Autoresuming support enabled."
123                 conf_values["AUTORESUME"]="1"
124
125         if "purge" in string.split(conf_values["options"]):
126                 print "Purge support enabled."
127                 conf_values["PURGE"]="1"
128         
129         if "clear-autoresume" in string.split(conf_values["options"]):
130                 print "Cleaning autoresume flags support enabled."
131                 conf_values["CLEAR_AUTORESUME"]="1"
132         
133         if myconf.has_key("envscript"):
134                 print "Envscript support enabled."
135                 conf_values["ENVSCRIPT"]=myconf["envscript"]
136
137 def import_modules():
138         # import catalyst's own modules (i.e. catalyst_support and the arch modules)
139         targetmap={}
140         
141         try:
142                 for x in required_build_targets:
143                         try:
144                                 fh=open(conf_values["sharedir"]+"/modules/"+x+".py")
145                                 module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE))
146                                 fh.close()
147                 
148                         except IOError:
149                                 raise CatalystError,"Can't find "+x+".py plugin in "+\
150                                         conf_values.settings["sharedir"]+"/modules/"
151
152                 for x in valid_build_targets:
153                         try:
154                                 fh=open(conf_values["sharedir"]+"/modules/"+x+".py")
155                                 module=imp.load_module(x,fh,"modules/"+x+".py",(".py","r",imp.PY_SOURCE))
156                                 module.register(targetmap)
157                                 fh.close()
158                 
159                         except IOError:
160                                 raise CatalystError,"Can't find "+x+".py plugin in "+\
161                                         conf_values.settings["sharedir"]+"/modules/"
162
163         except ImportError:
164                 print "!!! catalyst: Python modules not found in "+\
165                         conf_values["sharedir"]+"/modules; exiting."
166                 sys.exit(1)
167
168         return targetmap
169
170 def do_spec(myspecfile):
171         try:
172                 addlargs=read_spec(myspecfile)
173         except:
174                 sys.exit(1)
175                 
176         return addlargs
177
178 def do_cli(cmdline):
179         try:
180                 return arg_parse(cmdline)
181         
182         except CatalystError:
183                 print "!!! catalyst: Could not parse commandline, exiting."
184                 sys.exit(1)
185         
186 def build_target(addlargs, targetmap):
187         try:
188                 if not targetmap.has_key(addlargs["target"]):
189                         raise CatalystError,"Target \""+addlargs["target"]+"\" not available."
190                 
191                 mytarget=targetmap[addlargs["target"]](conf_values, addlargs)
192         
193                 # Kill any pids in the chroot 
194                 mytarget.kill_chroot_pids()
195
196                 # Check for mounts right away and abort if we cannot unmount them.
197                 mytarget.mount_safety_check()
198
199                 if conf_values.has_key("CLEAR_AUTORESUME"):
200                     mytarget.clear_autoresume()
201                 
202                 if conf_values.has_key("PURGE"):
203                     mytarget.purge()
204                 
205                 mytarget.run()
206
207         except CatalystError:
208                 try:
209                     mytarget.mount_safety_check()
210                 except:
211                     pass
212                 sys.exit(1)
213         
214 if __name__ == "__main__":
215         targetmap={}
216         
217         version()
218         if os.getuid() != 0:
219                 # catalyst cannot be run as a normal user due to chroots, mounts, etc
220                 print "!!! catalyst: This script requires root privileges to operate"
221                 sys.exit(2)
222
223         # we need some options in order to work correctly
224         if len(sys.argv) < 2:
225                 usage()
226                 sys.exit(2)
227
228         # parse out the command line arguments
229         try:
230                 opts,args = getopt.getopt(sys.argv[1:], "apxhvdc:C:f:FVs:", ["purge","help", "version", "debug",\
231                         "clear_autoresume", "config=", "cli=", "file=", "fetch", "verbose","snapshot="])
232         
233         except getopt.GetoptError:
234                 usage()
235                 sys.exit(2)
236         
237         # defaults for commandline opts
238         debug=False
239         verbose=False
240         fetch=False
241         myconfig=""
242         myspecfile=""
243         mycmdline=[]
244         myopts=[]
245
246         # check preconditions
247         if len(opts) == 0:
248                 print "!!! catalyst: please specify one of either -f or -C\n"
249                 usage()
250                 sys.exit(2)
251         run=0   
252         for o, a in opts:
253                 if o in ("-h", "--help"):
254                         usage()
255                         sys.exit(1)
256                 
257                 if o in ("-v", "--version"):
258                         print "Catalyst version "+__version__
259                         sys.exit(1)
260
261                 if o in ("-d", "--debug"):
262                         if len(sys.argv) < 3:
263                                 print "!!! catalyst: please specify one of either -f or -C\n"
264                                 usage()
265                                 sys.exit(2)
266                         else:
267                                 conf_values["DEBUG"]="1"
268
269                 if o in ("-c", "--config"):
270                         if len(sys.argv) < 3:
271                                 print "!!! catalyst: please specify one of either -f or -C\n"
272                                 usage()
273                                 sys.exit(2)
274                         else:
275                                 myconfig=a
276
277                 if o in ("-C", "--cli"):
278                         run=1   
279                         x=sys.argv.index(o)+1
280                         while x < len(sys.argv):
281                                 mycmdline.append(sys.argv[x])
282                                 x=x+1
283                         
284                 if o in ("-f", "--file"):
285                         run=1   
286                         myspecfile=a
287
288                 if o in ("-F", "--fetchonly"):
289                         if len(sys.argv) < 3:
290                                 print "!!! catalyst: please specify one of either -f or -C\n"
291                                 usage()
292                                 sys.exit(2)
293                         else:
294                                 conf_values["FETCH"]="1"
295                         
296                 if o in ("-V", "--verbose"):
297                         if len(sys.argv) < 3:
298                                 print "!!! catalyst: please specify one of either -f or -C\n"
299                                 usage()
300                                 sys.exit(2)
301                         else:
302                                 conf_values["VERBOSE"]="1"
303
304                 if o in ("-s", "--snapshot"):
305                         if len(sys.argv) < 3:
306                                 print "!!! catalyst: missing snapshot identifier\n"
307                                 usage()
308                                 sys.exit(2)
309                         else:
310                                 run=1
311                                 mycmdline.append("target=snapshot")
312                                 mycmdline.append("version_stamp="+a)
313                 
314                 if o in ("-p", "--purge"):
315                         if len(sys.argv) < 3:
316                                 print "!!! catalyst: please specify one of either -f or -C\n"
317                                 usage()
318                                 sys.exit(2)
319                         else:
320                                 conf_values["PURGE"]="1"
321                 if o in ("-a", "--clear-autoresume"):
322                         if len(sys.argv) < 3:
323                                 print "!!! catalyst: please specify one of either -f or -C\n"
324                                 usage()
325                                 sys.exit(2)
326                         else:
327                                 conf_values["CLEAR_AUTORESUME"]="1"
328         if run != 1:
329                 print "!!! catalyst: please specify one of either -f or -C\n"
330                 usage()
331                 sys.exit(2)
332
333         # import configuration file and import our main module using those settings
334         parse_config(myconfig)
335         sys.path.append(conf_values["sharedir"]+"/modules")
336         from catalyst_support import *
337                 
338         # import the rest of the catalyst modules
339         targetmap=import_modules()
340
341         addlargs={}
342         
343         if myspecfile:
344                 addlargs.update(do_spec(myspecfile))
345         
346         if mycmdline:
347                 addlargs.update(do_cli(mycmdline))
348         
349         if not addlargs.has_key("target"):
350                 raise CatalystError, "Required value \"target\" not specified."
351
352         # everything is setup, so the build is a go
353         try:
354                 build_target(addlargs, targetmap)
355         
356         except CatalystError:
357                 print
358                 print "Catalyst aborting...."
359                 sys.exit(2)
360         except KeyboardInterrupt:
361                 print "\nCatalyst build aborted due to user interrupt ( Ctrl-C )"
362                 print
363                 print "Catalyst aborting...."
364         except KeyError:
365                 print "\nproblem with command line or spec file ( Key Error )"
366                 print "Key: "+str(sys.exc_value)+" was not found"
367                 print "Catalyst aborting...."
368                 sys.exit(2)
369         except UnboundLocalError:
370                 print
371                 print "UnboundLocalError: "+str(sys.exc_value)+" was not found"
372                 raise
373                 print
374                 print "Catalyst aborting...."
375                 sys.exit(2)
376         except LockInUse:
377                 print "Catalyst aborting...."
378                 sys.exit(2)
379         except:
380                 print "Catalyst aborting...."
381                 raise
382                 sys.exit(2)