more weirdness
[catalyst.git] / catalyst
1 #!/usr/bin/python
2
3 import os,sys,imp,string
4
5 def die(msg=None):
6         if msg:
7                 print "catalyst: "+msg
8         sys.exit(1)
9
10 def warn(msg):
11         print "catalyst: "+msg
12
13 def usage():
14         print "usage: meep!"
15
16 if len(sys.argv)==1 or sys.argv[1] in ["-h","--help"]:
17         usage()
18         sys.exit(1)
19 elif os.getuid()!=0:
20         #non-root callers can still get -h and --help to work.
21         die("This script requires root privileges to operate.") 
22
23 """
24 Program flow:
25
26 * catalyst starts
27 * it detects what machine type it is running on
28 * it determines what machine targets it can build for (amd64 can build for 
29   x86 *and* amd64, for example.)
30 * it loads the appropriate plugins from the arch/ directory, as modules
31 * it registers each modules' classes with the main program so it can get
32   to all the subarch classes supported by each module.
33
34 todo:
35
36 * it parses an incomplete spec file provided by the user
37 * it generates a complete spec file and writes it to disk
38 * it creates an instance of the appropriate subarch object, and passes the
39   spec to the subarch so that it can build. (?)
40 * the subarch ("builder") class does all building, snapshotting, etc.
41
42
43 Classes are to be used to reduce code duplication *and* help maintainability.
44 That's about it.
45
46 Class heirarchy (preliminary):
47
48 generic_builder (in arch/generic_builder.py)
49         x86_generic_builder (in arch/x86.py)
50                 x86_builder (in arch/x86.py)
51                 pentium4_builder (in arch/x86.py)
52                 pentium4_builder.stage1()
53                 pentium4_builder.stage2()
54                 pentium4_builder.stage3()
55                 pentium4_builder.snapshot()
56
57 stage1, stage2 and stage3 have almost identical set-up and break-down. What is
58 different is what happens in the middle. steps are:
59
60 * check for existing bind mounts at location (safety check)
61 * clean chroot dir
62 * chroot dir setup
63 * unpack tarball to chroot dir 
64 * do bind mounts
65 * chroot
66 * execute script (bash)
67 * exit chroot
68 * umount bind mounts
69 * grab goodies (variant: which goodies to grab and how (grp and livecds differ)
70
71 purpose of builder modules:
72         have code specific to each arch in its own file
73         have common code in a generic parent class as much as possible
74         (these both make maintenance easier)
75
76 purpose of target modules:
77         each target is going to need specific tweaks to various parts of the build process
78         having a target module allows us to store these customizations in an organized way
79
80 special things for targets:
81         specify auxilliary mount points and where to mount them (for GRP packages)
82         specify requirements?
83
84 """
85
86
87 #This allows plugins to import modules in the /modules dir
88 sys.path.append(os.getcwd()+"/modules")
89
90 #map current machine information from uname() to the mainarch we are running
91 #under
92
93 machinemap={    "i386" : "x86",
94                 "i486" : "x86",
95                 "i586" : "x86",
96                 "i686" : "x86",
97                 "x86_64" : "amd64"
98         }
99
100 # map the mainarch we are running under to the mainarches we support for
101 # building stages and LiveCDs. (for example, on amd64, we can build stages for
102 # x86 or amd64.
103
104 targetmap={     "x86" : ["x86"],
105                 "amd64" : ["x86","amd64"]
106         }
107                 
108 mymachine=os.uname()[4]
109 if not machinemap.has_key(mymachine):
110         print "Unknown machine type:",mymachine
111         sys.exit(1)
112 hostarch=machinemap[mymachine]
113 print "Host architecture:",hostarch
114 print "Supported architectures for targets:",string.join(targetmap[hostarch])
115 print "Loading plugins:",
116 archmap={}
117 subarchmap={}
118 for x in targetmap[hostarch]:
119         fh=open("arch/"+x+".py")
120         #this next line loads the plugin as a module and assigns it to archmap[x]
121         archmap[x]=imp.load_module(x,fh,"arch/"+x+".py",(".py","r",imp.PY_SOURCE))
122         #this next line registers all the subarches supported in the plugin
123         archmap[x].register(subarchmap)
124         fh.close()      
125         print x,
126 print
127 print "Sub-architectures:",string.join(subarchmap.keys())
128
129 import targets
130 targetmap={}
131 targets.register(targetmap)
132 print "Available targets:",string.join(targetmap.keys())