/[gli]/branches/overhaul/src/GLIArchitectureTemplate.py
Gentoo

Contents of /branches/overhaul/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 476 - (hide annotations) (download) (as text)
Sun Apr 3 03:56:45 2005 UTC (13 years, 8 months ago) by codeman
Original Path: trunk/src/GLIArchitectureTemplate.py
File MIME type: text/x-python
File size: 39114 byte(s)
added hotplug/coldplug for livecd-kernel
  added --emptytree to stage2.

1 samyron 79 """
2     Gentoo Linux Installer
3    
4 codeman 476 $Id: GLIArchitectureTemplate.py,v 1.86 2005/04/03 03:56:45 codeman Exp $
5 samyron 79 Copyright 2004 Gentoo Technologies Inc.
6    
7     The ArchitectureTemplate is largely meant to be an abstract class and an
8     interface (yes, it is both at the same time!). The purpose of this is to create
9     subclasses that populate all the methods with working methods for that architecture.
10     The only definitions that are filled in here are architecture independent.
11    
12     """
13    
14 codeman 341 import GLIUtility, GLILogger, os, string, sys, shutil, re
15 agaffney 126 from GLIException import *
16 samyron 79
17     class ArchitectureTemplate:
18 agaffney 108 def __init__(self,configuration=None, install_profile=None, client_controller=None):
19 codeman 200 self._client_configuration = configuration
20 samyron 79 self._install_profile = install_profile
21 agaffney 108 self._cc = client_controller
22 samyron 79
23 samyron 102 # This will get used a lot, so it's probably
24     # better to store it in a variable than to call
25     # this method 100000 times.
26 codeman 200 self._chroot_dir = self._client_configuration.get_root_mount_point()
27 codeman 314 self._logger = GLILogger.Logger(self._client_configuration.get_log_file())
28 agaffney 384 self._compile_logfile = "/tmp/compile_output.log"
29 samyron 102
30 samyron 79 # These must be filled in by the subclass. _steps is a list of
31     # functions, that will carry out the installation. They must be
32     # in order.
33     #
34     # For example, self._steps might be: [preinstall, stage1, stage2, stage3, postinstall],
35     # where each entry is a function (with no arguments) that carries out the desired actions.
36     # Of course, steps will be different depending on the install_profile
37    
38     self._architecture_name = "generic"
39 agaffney 136 self._install_steps = [
40 agaffney 266 (self.partition, "Partition"),
41 agaffney 136 (self.mount_local_partitions, "Mount local partitions"),
42     (self.mount_network_shares, "Mount network (NFS) shares"),
43     (self.unpack_stage_tarball, "Unpack stage tarball"),
44     (self.configure_make_conf, "Configure /etc/make.conf"),
45 codeman 345 (self.prepare_chroot, "Preparing chroot"),
46 agaffney 436 (self.install_portage_tree, "Portage tree voodoo"),
47 agaffney 136 (self.stage1, "Performing bootstrap"),
48     (self.stage2, "Performing 'emerge system'"),
49 codeman 248 (self.set_root_password, "Set the root password"),
50 agaffney 436 (self.set_timezone, "Setting timezone"),
51 agaffney 136 (self.emerge_kernel_sources, "Emerge kernel sources"),
52     (self.build_kernel, "Building kernel"),
53     (self.install_logging_daemon, "Logger"),
54     (self.install_cron_daemon, "Cron daemon"),
55     (self.install_filesystem_tools, "Installing filesystem tools"),
56     (self.setup_network_post, "Configuring post-install networking"),
57     (self.install_bootloader, "Configuring and installing bootloader"),
58     (self.update_config_files, "Updating config files"),
59 codeman 223 (self.configure_rc_conf, "Updating /etc/rc.conf"),
60 agaffney 436 (self.set_services, "Setting up services for startup"),
61     (self.set_users, "Add additional users."),
62     (self.install_packages, "Installing additional packages."),
63     (self.finishing_cleanup, "Cleanup and unmounting local filesystems.")
64 agaffney 136 ]
65 codeman 200
66 samyron 79
67 agaffney 136 def get_install_steps(self):
68     return self._install_steps
69    
70 codeman 201 def notify_frontend(self, type, data):
71     self._cc.addNotification(type, data)
72    
73 samyron 79 # It is possible to override these methods in each Arch Template.
74     # It might be necessary to do so, if the arch needs something 'weird'.
75    
76 codeman 201 def _add_to_runlevel(self, script_name, runlevel="default"):
77     "Adds the script named 'script_name' to the runlevel 'runlevel' in the chroot environement"
78    
79     # Do it
80 agaffney 451 status = GLIUtility.spawn("rc-update add " + script_name + " " + runlevel, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
81 codeman 216 if not GLIUtility.exitsuccess(status):
82 codeman 314 raise GLIException("RunlevelAddError", 'fatal', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
83     self._logger.log("Added "+script_name+" to runlevel "+runlevel)
84 codeman 201
85 agaffney 322 def _quickpkg_deps(self, package):
86 agaffney 385 # These need to be changed to pull values from the make.conf stuff
87 agaffney 322 PKGDIR = "/usr/portage/packages"
88     PORTAGE_TMPDIR = "/var/tmp"
89 agaffney 415 make_conf = self._install_profile.get_make_conf()
90     if "PKGDIR" in make_conf: PKGDIR = make_conf['PKGDIR']
91     if "PORTAGE_TMPDIR" in make_conf: PORTAGE_TMPDIR = make_conf['PORTAGE_TMPDIR']
92 agaffney 451 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PKGDIR, logfile=self._compile_logfile, append_log=True)
93     GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTAGE_TMPDIR, logfile=self._compile_logfile, append_log=True)
94 agaffney 324 packages = [word for word in GLIUtility.spawn("emerge -p " + package, chroot=self._chroot_dir, return_output=True)[1].split() if "/" in word]
95     for pkg in packages:
96 agaffney 322 if not GLIUtility.is_file(self._chroot_dir + PKGDIR + "/All/" + pkg.split('/')[1] + ".tbz2"):
97 agaffney 401 ret = GLIUtility.spawn("env PKGDIR=" + self._chroot_dir + PKGDIR + " PORTAGE_TMPDIR=" + self._chroot_dir + PORTAGE_TMPDIR + " quickpkg =" + pkg)
98 agaffney 322 if ret:
99     # This package couldn't be quickpkg'd. This may be an error in the future
100     pass
101    
102 agaffney 385 def _get_packages_to_emerge(self, cmd):
103     # cmd = full command to run ('/usr/portage/scripts/bootstrap.sh --pretend' or 'emerge -p system')
104     return GLIUtility.spawn(cmd + r" | grep -e '\[ebuild' | sed -e 's:\[ebuild .\+ \] ::' -e 's: \[.\+\] ::' -e 's: +$::'", chroot=self._chroot_dir, return_output=True).split("\n")
105    
106 codeman 209 def _emerge(self, package, binary=False, binary_only=False):
107 codeman 314 #Error checking of this function is to be handled by the parent function.
108 agaffney 322 if self._install_profile.get_grp_install():
109     self._quickpkg_deps(package)
110 agaffney 451 return GLIUtility.spawn("emerge -k " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
111 codeman 201 else:
112 agaffney 322 if binary_only:
113 agaffney 451 return GLIUtility.spawn("emerge -K " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
114 agaffney 322 elif binary:
115 agaffney 451 return GLIUtility.spawn("emerge -k " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
116 agaffney 322 else:
117 agaffney 451 return GLIUtility.spawn("emerge " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
118 codeman 201
119 codeman 209 def _edit_config(self, filename, newvalues, delimeter='=', quotes_around_value=True):
120 codeman 201 """
121     filename = file to be editted
122     newvlaues = a dictionary of VARIABLE:VALUE pairs
123     """
124 codeman 209 if not GLIUtility.is_file(filename):
125     raise GLIException("NoSuchFileError", 'notice','_edit_config',filename + ' does not exist!')
126 codeman 201
127     f = open(filename)
128     file = f.readlines()
129     f.close()
130    
131     for key in newvalues.keys():
132     regexpr = '^\s*#?\s*' + key + '\s*' + delimeter + '.*$'
133     regexpr = re.compile(regexpr)
134    
135     for i in range(0, len(file)):
136     if regexpr.match(file[i]):
137     if not file[i][0] == '#':
138     file[i] = '#' + file[i]
139    
140     file.append('\n# Added by GLI\n')
141     if quotes_around_value:
142     file.append(key + delimeter + '"' + newvalues[key] + '"\n')
143     else:
144     file.append(key + delimeter + newvalues[key]+'\n')
145    
146     f = open(filename,'w')
147     f.writelines(file)
148     f.flush()
149     f.close()
150 codeman 314 self._logger.log("Edited Config file "+filename)
151 codeman 201
152 samyron 79 def stage1(self):
153     "Stage 1 install -- bootstraping"
154    
155     # If we are doing a stage 1 install, then bootstrap
156     if self._install_profile.get_install_stage() == 1:
157 codeman 314 self._logger.mark()
158     self._logger.log("Starting bootstrap.")
159 agaffney 385 pkgs = self._get_packages_to_emerge("/usr/portage/scripts/bootstrap.sh --pretend")
160 agaffney 451 exitstatus = GLIUtility.spawn("/usr/portage/scripts/bootstrap.sh", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
161 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
162 samyron 186 raise GLIException("Stage1Error", 'fatal','stage1', "Bootstrapping failed!")
163 codeman 314 self._logger.log("Bootstrap complete.")
164 agaffney 385
165 samyron 79 def stage2(self):
166     # If we are doing a stage 1 or 2 install, then emerge system
167     if self._install_profile.get_install_stage() in [ 1, 2 ]:
168 codeman 314 self._logger.mark()
169     self._logger.log("Starting emerge system.")
170 agaffney 385 pkgs = self._get_packages_to_emerge("emerge -p system")
171 codeman 476 exitstatus = self._emerge("--emptytree system")
172 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
173 samyron 186 raise GLIException("Stage2Error", 'fatal','stage2', "Building the system failed!")
174 codeman 314 self._logger.log("Emerge system complete.")
175 agaffney 384
176 agaffney 133 def unpack_stage_tarball(self):
177     if not os.path.isdir(self._chroot_dir):
178     os.makedirs(self._chroot_dir)
179 codeman 215 GLIUtility.fetch_and_unpack_tarball(self._install_profile.get_stage_tarball_uri(), self._chroot_dir, temp_directory=self._chroot_dir, keep_permissions=True)
180 codeman 314 self._logger.log(self._install_profile.get_stage_tarball_uri()+" was unpacked.")
181 agaffney 384
182 agaffney 133 def prepare_chroot(self):
183 codeman 215 # Copy resolv.conf to new env
184     try:
185     shutil.copy("/etc/resolv.conf", self._chroot_dir + "/etc/resolv.conf")
186     except:
187     pass
188     ret = GLIUtility.spawn("mount -t proc none "+self._chroot_dir+"/proc")
189 samyron 79 if not GLIUtility.exitsuccess(ret):
190 codeman 215 raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /proc')
191 codeman 216 ret = GLIUtility.spawn("mount -o bind /dev " + self._chroot_dir + "/dev")
192     if not GLIUtility.exitsuccess(ret):
193     raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /dev')
194 agaffney 384 GLIUtility.spawn("mv " + self._compile_logfile + " " + self._chroot_dir + self._compile_logfile + " && ln -s " + self._chroot_dir + self._compile_logfile + " " + self._compile_logfile)
195 codeman 314 self._logger.log("Chroot environment ready.")
196 samyron 79 # Set USE flags here
197     # might want to rewrite/use _edit_config from the GLIInstallTemplate
198     # Then you should be done... at least with the preinstall.
199    
200 samyron 102 def install_packages(self):
201     "Will install any extra software!"
202 codeman 201
203 samyron 102 installpackages = self._install_profile.get_install_packages()
204     for package in installpackages:
205 codeman 201 status = self._emerge(package)
206     if not GLIUtility.exitsuccess(status):
207 codeman 318 self._logger.log("Could not emerge " + package + "!")
208     # raise GLIException("InstallPackagesError", 'warning', 'install_packages', "Could not emerge " + package + "!")
209     else:
210     self._logger.log("Emerged package: "+package)
211 samyron 102
212 codeman 361 def set_services(self):
213     "Will set the list of services to runlevel default. This is a temporary solution!"
214    
215     services = self._install_profile.get_services()
216     for service in services:
217     status = self._add_to_runlevel(service)
218 samyron 102
219     def mount_local_partitions(self):
220     "Mounts all partitions that are on the local machine"
221 codeman 213 #{ 1: { 'end': 1999871, 'format': False, 'mb': 0,
222     #'mountopts': '', 'mountpoint': '', 'start': 63, 'type': 'linux-swap'},
223     #2: { 'end': 240121727, 'format': False, 'mb': 0, 'mountopts': '',
224     #'mountpoint': '', 'start': 1999872, 'type': 'ext3'}}
225 codeman 216
226 codeman 213 parts = self._install_profile.get_partition_tables()
227 codeman 215 parts_to_mount = {}
228 codeman 213 for device in parts:
229     #in parts['/dev/hda']
230     for partition in parts[device]:
231 codeman 214 #print parts[device][partition]
232 codeman 213 mountpoint = parts[device][partition]['mountpoint']
233     mountopts = parts[device][partition]['mountopts']
234     minor = str(parts[device][partition]['minor'])
235     partition_type = parts[device][partition]['type']
236     if mountpoint:
237     if mountopts:
238     mountopts = "-o "+mountopts+" "
239     if partition_type:
240     partition_type = "-t "+partition_type+" "
241 codeman 215 parts_to_mount[mountpoint]= {0: mountopts, 1: partition_type, 2: minor}
242    
243 codeman 213 if partition_type == "linux-swap":
244     ret = GLIUtility.spawn("swapon "+device+minor)
245 agaffney 272 if not GLIUtility.exitsuccess(ret):
246 codeman 318 self._logger.log("ERROR! : Could not activate swap!")
247 codeman 314 # raise GLIException("MountError", 'warning','mount_local_partitions','Could not activate swap')
248 codeman 215 sorted_list = []
249     for key in parts_to_mount.keys(): sorted_list.append(key)
250     sorted_list.sort()
251    
252     for mountpoint in sorted_list:
253     mountopts = parts_to_mount[mountpoint][0]
254     partition_type = parts_to_mount[mountpoint][1]
255     minor = parts_to_mount[mountpoint][2]
256     if not GLIUtility.is_file(self._chroot_dir+mountpoint):
257     exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
258     if exitstatus != 0:
259     raise GLIException("MkdirError", 'fatal','mount_local_partitions', "Making the mount point failed!")
260 agaffney 451 ret = GLIUtility.spawn("mount "+partition_type+mountopts+device+minor+" "+self._chroot_dir+mountpoint, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
261 codeman 215 if not GLIUtility.exitsuccess(ret):
262 codeman 314 raise GLIException("MountError", 'fatal','mount_local_partitions','Could not mount a partition')
263     self._logger.log("Mounted mountpoint:"+mountpoint)
264 samyron 102 def mount_network_shares(self):
265     "Mounts all network shares to the local machine"
266 codeman 226 """
267     <agaffney> it'll be much easier than mount_local_partitions
268 codeman 248 <agaffney> make sure /etc/init.d/portmap is started
269     <agaffney> then mount each one: mount -t nfs -o <mountopts> <host>:<export> <mountpoint>
270 codeman 226 """
271     nfsmounts = self._install_profile.get_network_mounts()
272     for netmount in nfsmounts:
273 agaffney 266 if netmount['type'] == "NFS" or netmount['type'] == "nfs":
274     mountopts = netmount['mountopts']
275 codeman 226 if mountopts:
276     mountopts = "-o "+mountopts
277 agaffney 266 host = netmount['host']
278     export = netmount['export']
279     mountpoint = netmount['mountpoint']
280 codeman 226 if not GLIUtility.is_file(self._chroot_dir+mountpoint):
281     exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
282     if exitstatus != 0:
283     raise GLIException("MkdirError", 'fatal','mount_network_shares', "Making the mount point failed!")
284 agaffney 451 ret = GLIUtility.spawn("mount -t nfs "+mountopts+" "+host+":"+export+" "+self._chroot_dir+mountpoint, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
285 codeman 226 if not GLIUtility.exitsuccess(ret):
286 codeman 314 raise GLIException("MountError", 'fatal','mount_network_shares','Could not mount an NFS partition')
287     self._logger.log("Mounted netmount at mountpoint:"+mountpoint)
288    
289 samyron 102 def fetch_sources_from_cd(self):
290     "Gets sources from CD (required for non-network installation)"
291 codeman 314 #WARNING: There will no longer be sources on the future livecds. this will have to change!
292 codeman 216 if not GLIUtility.is_file(self._chroot_dir+"/usr/portage/distfiles"):
293     exitstatus = GLIUtility.spawn("mkdir -p /usr/portage/distfiles",chroot=self._chroot_dir)
294     if exitstatus != 0:
295     raise GLIException("MkdirError", 'fatal','install_portage_tree',"Making the distfiles directory failed.")
296 agaffney 451 exitstatus = GLIUtility.spawn("cp /mnt/cdrom/distfiles/* "+self._chroot_dir+"/usr/portage/distfiles/", display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
297 codeman 216 if exitstatus != 0:
298     raise GLIException("PortageError", 'fatal','install_portage_tree',"Failed to copy the distfiles to the new system")
299 codeman 314 self._logger.log("Distfiles copied from cd.")
300    
301 samyron 102 def fetch_grp_from_cd(self):
302     "Gets grp binary packages from CD (required for non-network binary installation)"
303 codeman 282 # This will not work until we find out how the new GRP format will function.
304 codeman 204 pass
305 codeman 201
306 samyron 102 def configure_make_conf(self):
307     "Configures make.conf"
308 codeman 201
309 samyron 102 # Get make.conf options
310     options = self._install_profile.get_make_conf()
311    
312     # For each configuration option...
313     for key in options.keys():
314    
315     # Add/Edit it into make.conf
316 codeman 222 self._edit_config(self._chroot_dir + "/etc/make.conf", {key: options[key]})
317 codeman 314 self._logger.log("Make.conf configured")
318 samyron 102
319     def install_portage_tree(self):
320     "Get/update the portage tree"
321    
322     # Check the type of portage tree fetching we'll do
323     # If it is custom, follow the path to the custom tarball and unpack it
324     if self._install_profile.get_portage_tree_sync_type() == "custom":
325    
326     # Get portage tree info
327     portage_tree_snapshot_uri = self._install_profile.get_portage_tree_snapshot_uri()
328 codeman 216 if portage_tree_snapshot_uri:
329     # Fetch and unpack the tarball
330     GLIUtility.fetch_and_unpack_tarball(portage_tree_snapshot_uri, self._chroot_dir + "/usr/", self._chroot_dir + "/")
331     # FIXME TEMPORARY FIX FOR NON-GRP SETTING
332     self.fetch_sources_from_cd()
333 codeman 314 self._logger.log("Portage tree install was custom.")
334 samyron 102 # If the type is webrsync, then run emerge-webrsync
335     elif self._install_profile.get_portage_tree_sync_type() == "webrsync":
336 agaffney 451 exitstatus = GLIUtility.spawn("emerge-webrsync", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
337 samyron 102 if exitstatus != 0:
338 samyron 186 raise GLIException("EmergeWebRsyncError", 'fatal','install_portage_tre', "Failed to retrieve portage tree!")
339 codeman 314 self._logger.log("Portage tree sync'd using webrsync")
340 samyron 102 # Otherwise, just run emerge sync
341     else:
342     exitstatus = self._emerge("sync")
343     if exitstatus != 0:
344 samyron 186 raise GLIException("EmergeSyncError", 'fatal','install_portage_tree', "Failed to retrieve portage tree!")
345 codeman 314 self._logger.log("Portage tree sync'd")
346    
347 samyron 102 def set_timezone(self):
348     "Sets the timezone for the new environment"
349     # Set symlink
350 codeman 475 if os.access(self._chroot_dir + "/etc/localtime", os.W_OK):
351     GLIUtility.spawn("rm "+self._chroot_dir + "/etc/localtime", quiet=True)
352     os.symlink(self._chroot_dir + "/usr/share/zoneinfo/" + self._install_profile.get_time_zone(), self._chroot_dir + "/etc/localtime")
353 samyron 102 if not (self._install_profile.get_time_zone() == "UTC"):
354 codeman 216 self._edit_config(self._chroot_dir + "/etc/rc.conf", {"CLOCK":"local"})
355 codeman 314 self._logger.log("Timezone set.")
356 samyron 102
357     def configure_fstab(self):
358     "Configures fstab"
359     newfstab = ""
360 codeman 216 #partitions = self._install_profile.get_fstab()
361     parts = self._install_profile.get_partition_tables()
362     for device in parts:
363     #in parts['/dev/hda']
364     for partition in parts[device]:
365     #print parts[device][partition]
366     mountpoint = parts[device][partition]['mountpoint']
367     minor = str(parts[device][partition]['minor'])
368     partition_type = parts[device][partition]['type']
369 agaffney 474 mountopts = parts[device][partition]['mountopts'] or "defaults"
370 codeman 216 if mountpoint:
371     if not GLIUtility.is_file(self._chroot_dir+mountpoint):
372 codeman 217 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
373     if exitstatus != 0:
374     raise GLIException("MkdirError", 'fatal','configure_fstab', "Making the mount point failed!")
375 codeman 216 newfstab += device+minor+"\t "+mountpoint+"\t "+partition_type+"\t "+mountopts+"\t\t "
376     if mountpoint == "/boot":
377     newfstab += "1 2\n"
378     elif mountpoint == "/":
379     newfstab += "0 1\n"
380     else:
381     newfstab += "0 0\n"
382     if partition_type == "linux-swap":
383     newfstab += device+minor+"\t none swap sw 0 0\n"
384 samyron 102 newfstab += "none /proc proc defaults 0 0\n"
385     newfstab += "none /dev/shm tmpfs defaults 0 0\n"
386     if GLIUtility.is_device("/dev/cdroms/cdrom0"):
387     newfstab += "/dev/cdroms/cdrom0 /mnt/cdrom auto noauto,user 0 0\n"
388 agaffney 161
389     for netmount in self._install_profile.get_network_mounts():
390     if netmount['type'] == "nfs":
391     newfstab += netmount['host'] + ":" + netmount['export'] + "\t" + netmount['mountpoint'] + "\tnfs\t" + netmount['mountopts'] + "\t0 0\n"
392 samyron 102
393 codeman 201 file_name = self._chroot_dir + "/etc/fstab"
394 samyron 102 try:
395     shutil.move(file_name, file_name + ".OLDdefault")
396     except:
397     pass
398     f = open(file_name, 'w')
399     f.writelines(newfstab)
400     f.close()
401 codeman 314 self._logger.log("fstab configured.")
402 samyron 102
403     def emerge_kernel_sources(self):
404     "Fetches desired kernel sources"
405 codeman 314 kernel_pkg = self._install_profile.get_kernel_source_pkg()
406 agaffney 401 # if kernel_pkg:
407     if kernel_pkg == "livecd-kernel":
408     PKGDIR = "/usr/portage/packages"
409 agaffney 415 PORTAGE_TMPDIR = "/var/tmp"
410 agaffney 414 make_conf = self._install_profile.get_make_conf()
411     if "PKGDIR" in make_conf: PKGDIR = make_conf['PKGDIR']
412     if "PORTAGE_TMPDIR" in make_conf: PORTAGE_TMPDIR = make_conf['PORTAGE_TMPDIR']
413 agaffney 451 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PKGDIR, logfile=self._compile_logfile, append_log=True)
414     GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTAGE_TMPDIR, logfile=self._compile_logfile, append_log=True)
415 agaffney 401 ret = GLIUtility.spawn("env PKGDIR=" + self._chroot_dir + PKGDIR + " PORTAGE_TMPDIR=" + self._chroot_dir + PORTAGE_TMPDIR + " quickpkg livecd-kernel")
416 agaffney 413 ret = GLIUtility.spawn("env PKGDIR=" + PKGDIR + " emerge -K sys-kernel/livecd-kernel", chroot=self._chroot_dir)
417 codeman 476
418     #these are the hotplug/coldplug steps from build_kernel copied over here. they will NOT be run there.
419     exitstatus = self._emerge("hotplug")
420     if exitstatus != 0:
421     raise GLIException("EmergeHotplugError", 'fatal','build_kernel', "Could not emerge hotplug!")
422     self._logger.log("Hotplug emerged.")
423     exitstatus = self._emerge("coldplug")
424     if exitstatus != 0:
425     raise GLIException("EmergeColdplugError", 'fatal','build_kernel', "Could not emerge coldplug!")
426     self._logger.log("Coldplug emerged. Now they should be added to the default runlevel.")
427    
428     self._add_to_runlevel("hotplug")
429     self._add_to_runlevel("coldplug", runlevel="boot")
430 codeman 434 else:
431 codeman 314 exitstatus = self._emerge(kernel_pkg)
432     if exitstatus != 0:
433     raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not retrieve kernel sources!")
434     try:
435     os.stat(self._chroot_dir + "/usr/src/linux")
436     except:
437     kernels = os.listdir(self._chroot_dir+"/usr/src")
438     found_a_kernel = False
439     counter = 0
440     while not found_a_kernel:
441     if kernels[counter][0:6]=="linux-":
442     exitstatus = GLIUtility.spawn("ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux",chroot=self._chroot_dir)
443     if exitstatus != 0:
444     raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not make a /usr/src/linux symlink")
445     found_a_kernel = True
446     else:
447     counter = counter + 1
448     self._logger.log("Kernel sources:"+kernel_pkg+" emerged and /usr/src/linux symlinked.")
449 samyron 102
450     def build_kernel(self):
451     "Builds kernel"
452 codeman 314 self._logger.mark()
453     self._logger.log("Starting build_kernel")
454 agaffney 401 # No building necessary if using the LiveCD's kernel/initrd
455     if self._install_profile.get_kernel_source_pkg() == "livecd-kernel": return
456 samyron 102 # Get the uri to the kernel config
457     kernel_config_uri = self._install_profile.get_kernel_config_uri()
458 codeman 282 if kernel_config_uri == "": #use genkernel if no specific config
459 samyron 102
460 codeman 282 exitstatus = self._emerge("genkernel")
461     if exitstatus != 0:
462 codeman 314 raise GLIException("EmergeGenKernelError", 'fatal','build_kernel', "Could not emerge genkernel!")
463     self._logger.log("Genkernel emerged. Beginning kernel compile.")
464 codeman 282 # Null the genkernel_options
465     genkernel_options = ""
466    
467     # If the uri for the kernel config is not null, then
468     if kernel_config_uri != "":
469     GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/root/kernel_config")
470     genkernel_options = genkernel_options + " --kernel-config=/root/kernel_config"
471    
472     # Decide whether to use bootsplash or not
473     if self._install_profile.get_kernel_bootsplash():
474     genkernel_options = genkernel_options + " --bootsplash"
475     else:
476     genkernel_options = genkernel_options + " --no-bootsplash"
477     # Run genkernel in chroot
478 codeman 435 #print "genkernel all " + genkernel_options
479 agaffney 451 exitstatus = GLIUtility.spawn("genkernel all " + genkernel_options, chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
480 codeman 282 if exitstatus != 0:
481     raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build kernel!")
482 codeman 395
483     exitstatus = self._emerge("hotplug")
484     if exitstatus != 0:
485     raise GLIException("EmergeHotplugError", 'fatal','build_kernel', "Could not emerge hotplug!")
486     self._logger.log("Hotplug emerged.")
487     exitstatus = self._emerge("coldplug")
488     if exitstatus != 0:
489     raise GLIException("EmergeColdplugError", 'fatal','build_kernel', "Could not emerge coldplug!")
490     self._logger.log("Coldplug emerged. Now they should be added to the default runlevel.")
491    
492 codeman 361 self._add_to_runlevel("hotplug")
493     self._add_to_runlevel("coldplug", runlevel="boot")
494 codeman 314 self._logger.log("Genkernel complete.")
495 codeman 282 else: #CUSTOM CONFIG
496     #Copy the kernel .config to the proper location in /usr/src/linux
497     try:
498 codeman 287 GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/root/kernel_config")
499 codeman 282 except:
500     raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not copy kernel config!")
501 samyron 102
502 codeman 287 kernel_compile_script = "#!/bin/bash\n"
503     kernel_compile_script += "cp /root/kernel_config /usr/src/linux/.config\n"
504     kernel_compile_script += "cd /usr/src/linux\n"
505     kernel_compile_script += "make \nmake modules_install \n"
506    
507     #Ok now that it's built, copy it to /boot/kernel-* for bootloader code to find it
508     if self._client_configuration.get_architecture_template() == "x86":
509     kernel_compile_script += "cp /usr/src/linux/arch/i386/boot/bzImage /boot/kernel-custom\n"
510     f = open(self._chroot_dir+"/root/kernel_script", 'w')
511     f.writelines(kernel_compile_script)
512     f.close()
513 codeman 282 #Build the kernel
514 codeman 314 exitstatus1 = GLIUtility.spawn("chmod u+x "+self._chroot_dir+"/root/kernel_script")
515 agaffney 451 exitstatus2 = GLIUtility.spawn("/root/kernel_script", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
516 codeman 314 if (exitstatus1 != 0) or (exitstatus2 != 0):
517 codeman 282 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build custom kernel!")
518 codeman 287
519 codeman 282 #i'm sure i'm forgetting something here.
520 codeman 288 #cleanup
521     exitstatus = GLIUtility.spawn("rm "+self._chroot_dir+"/root/kernel_script")
522     #it's not important if this fails.
523 codeman 314 self._logger.log("Custom kernel complete")
524    
525 samyron 102 def install_logging_daemon(self):
526     "Installs and sets up logger"
527     # Get loggin daemon info
528     logging_daemon_pkg = self._install_profile.get_logging_daemon_pkg()
529     if logging_daemon_pkg:
530     # Emerge Logging Daemon
531     exitstatus = self._emerge(logging_daemon_pkg)
532     if exitstatus != 0:
533 codeman 318 raise GLIException("LoggingDaemonError", 'fatal','install_logging_daemon', "Could not emerge " + logging_daemon_pkg + "!")
534 samyron 102
535     # Add Logging Daemon to default runlevel
536     self._add_to_runlevel(logging_daemon_pkg)
537 codeman 314 self._logger.log("Logging daemon installed: "+logging_daemon_pkg)
538 samyron 102 def install_cron_daemon(self):
539     "Installs and sets up cron"
540     # Get cron daemon info
541     cron_daemon_pkg = self._install_profile.get_cron_daemon_pkg()
542     if cron_daemon_pkg:
543     # Emerge Cron Daemon
544     exitstatus = self._emerge(cron_daemon_pkg)
545     if exitstatus != 0:
546 codeman 318 raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Could not emerge " + cron_daemon_pkg + "!")
547 samyron 102
548     # Add Cron Daemon to default runlevel
549     self._add_to_runlevel(cron_daemon_pkg)
550    
551     # If the Cron Daemon is not vixie-cron, run crontab
552     if cron_daemon_pkg != "vixie-cron":
553 codeman 345 exitstatus = GLIUtility.spawn("crontab /etc/crontab", chroot=self._chroot_dir, display_on_tty8=True)
554 samyron 102 if exitstatus != 0:
555 codeman 318 raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Failure making crontab!")
556 codeman 314 self._logger.log("Cron daemon installed and configured: "+cron_daemon_pkg)
557 samyron 102 def install_filesystem_tools(self):
558     "Installs and sets up fstools"
559     # Get the list of file system tools to be installed
560 codeman 443 parts = self._install_profile.get_partition_tables()
561 codeman 445 filesystem_tools = []
562 codeman 443 for device in parts:
563     #in parts['/dev/hda']
564     for partition in parts[device]:
565     #print parts[device][partition]
566     partition_type = parts[device][partition]['type']
567     if partition_type not in filesystem_tools:
568     filesystem_tools.append(partition_type)
569     for filesystem in filesystem_tools:
570     if filesystem.lower() == "xfs":
571     exitstatus = self._emerge("xfsprogs")
572     if exitstatus != 0:
573     self._logger.log("ERROR! : Could not emerge xfsprogs!")
574     else:
575     self._logger.log("FileSystemTool xfsprogs was emerged successfully.")
576     if filesystem.lower() == "reiserfs":
577     exitstatus = self._emerge("reiserfsprogs")
578     if exitstatus != 0:
579     self._logger.log("ERROR! : Could not emerge reiserfsprogs!")
580     else:
581     self._logger.log("FileSystemTool reiserfsprogs was emerged successfully.")
582     if filesystem.lower() == "jfs":
583     exitstatus = self._emerge("jfsutils")
584     if exitstatus != 0:
585     self._logger.log("ERROR! : Could not emerge jfsutils!")
586     else:
587     self._logger.log("FileSystemTool jfsutils was emerged successfully.")
588    
589 samyron 102 def install_rp_pppoe(self):
590     "Installs rp-pppoe"
591     # If user wants us to install rp-pppoe, then do so
592     if self._install_profile.get_install_rp_pppoe():
593     exitstatus = self._emerge("rp-pppoe")
594     if exitstatus != 0:
595 codeman 318 self._logger.log("ERROR! : Could not emerge rp-pppoe!")
596     # raise GLIException("RP_PPPOEError", 'warning', 'install_rp_pppoe', "Could not emerge rp-pppoe!")
597     else:
598     self._logger.log("rp-pppoe emerged but not set up.")
599 samyron 102 # Should we add a section here to automatically configure rp-pppoe?
600     # I think it should go into the setup_network_post section
601     # What do you guys think?
602    
603     def install_pcmcia_cs(self):
604     "Installs and sets up pcmcia-cs"
605     # If user wants us to install pcmcia-cs, then do so
606     if self._install_profile.get_install_pcmcia_cs():
607     exitstatus = self._emerge("pcmcia-cs")
608     if exitstatus != 0:
609 codeman 318 self._logger.log("ERROR! : Could not emerge pcmcia-cs!")
610     # raise GLIException("PCMCIA_CSError", 'warning', 'install_pcmcia_cs', "Could not emerge pcmcia-cs!")
611 samyron 102
612     # Add pcmcia-cs to the default runlevel
613 codeman 318 else:
614     self._add_to_runlevel(pcmcia)
615     self._logger.log("PCMCIA_CS emerged and configured.")
616 samyron 102
617     def update_config_files(self):
618     "Runs etc-update (overwriting all config files), then re-configures the modified ones"
619     # Run etc-update overwriting all config files
620 codeman 345 status = GLIUtility.spawn('echo "-5" | chroot '+self._chroot_dir+' etc-update', display_on_tty8=True)
621 codeman 218 if not GLIUtility.exitsuccess(status):
622 codeman 318 self._logger.log("ERROR! : Could not update the config files!")
623     # raise GLIException("EtcUpdateError", 'warning', 'update_config_files', "Could not update config files!")
624     else:
625     self.configure_make_conf()
626     self.configure_fstab()
627     self.configure_rc_conf()
628     self._logger.log("Config files updated using etc-update. make.conf/fstab/rc.conf restored.")
629 samyron 102
630     def configure_rc_conf(self):
631     "Configures rc.conf"
632     # Get make.conf options
633     options = self._install_profile.get_rc_conf()
634    
635     # For each configuration option...
636     for key in options.keys():
637    
638     # Add/Edit it into rc.conf
639 codeman 222 self._edit_config(self._chroot_dir + "/etc/rc.conf", {key: options[key]})
640 codeman 314 self._logger.log("rc.conf configured.")
641    
642 samyron 102 def setup_network_post(self):
643     "Sets up the network for the first boot"
644     # Get hostname, domainname and nisdomainname
645     hostname = self._install_profile.get_hostname()
646     domainname = self._install_profile.get_domainname()
647     nisdomainname = self._install_profile.get_nisdomainname()
648    
649     # Write the hostname to the hostname file
650 codeman 201 open(self._chroot_dir + "/etc/hostname", "w").write(hostname + "\n")
651 samyron 102
652     # Write the domainname to the nisdomainname file
653     if domainname:
654 codeman 201 open(self._chroot_dir + "/etc/dnsdomainname", "w").write(domainname + "\n")
655 codeman 409 self._add_to_runlevel("domainname")
656 samyron 102
657     # Write the nisdomainname to the nisdomainname file
658     if nisdomainname:
659 codeman 201 open(self._chroot_dir + "/etc/nisdomainname", "w").write(nisdomainname + "\n")
660 codeman 409 self._add_to_runlevel("domainname")
661 samyron 102
662     #
663     # EDIT THE /ETC/HOSTS FILE
664     #
665    
666     # The address we are editing is 127.0.0.1
667     hosts_ip = "127.0.0.1"
668    
669     # If the hostname is localhost
670     if hostname == "localhost":
671     # If a domainname is set
672     if domainname:
673     hosts_line = hostname + "." + domainname + "\t" + hostname
674     else:
675     hosts_line = hostname
676     # If the hostname is not localhost
677     else:
678     # If a domainname is set
679     if domainname:
680     hosts_line = hostname + "." + domainname + "\t" + hostname + "\tlocalhost"
681     else:
682     hosts_line = "localhost\t" + hostname
683    
684     # Write to file
685 codeman 218 self._edit_config(self._chroot_dir + "/etc/hosts", {hosts_ip: hosts_line}, delimeter='\t', quotes_around_value=False)
686 samyron 102
687     #
688     # SET DEFAULT GATEWAY
689     #
690    
691     # Get default gateway
692     default_gateway = self._install_profile.get_default_gateway()
693    
694     # If the default gateway exists, add it
695     if default_gateway:
696 codeman 359 default_gateway_string = default_gateway[0] + "/" + default_gateway[1]
697     self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"gateway": default_gateway_string})
698 samyron 102
699     #
700     # SET RESOLV INFO
701     #
702    
703     # Get dns servers
704     dns_servers = self._install_profile.get_dns_servers()
705    
706     # Clear the list
707     resolv_output = []
708    
709     # If dns servers are set
710     if dns_servers:
711    
712    
713     # Parse each dns server
714     for dns_server in dns_servers:
715     # Add the server to the output
716     resolv_output.append("nameserver " + dns_server +"\n")
717    
718     # If the domainname is set, then also output it
719     if domainname:
720     resolv_output.append("search " + domainname + "\n")
721    
722 codeman 347 # Output to file
723     resolve_conf = open(self._chroot_dir + "/etc/resolv.conf", "w")
724     resolve_conf.writelines(resolv_output)
725     resolve_conf.close()
726 samyron 102
727     #
728     # PARSE INTERFACES
729     #
730    
731     # Fetch interfaces
732     interfaces = self._install_profile.get_network_interfaces()
733 codeman 347 emerge_dhcp = False
734 samyron 102 # Parse each interface
735     for interface in interfaces.keys():
736    
737     # Set what kind of interface it is
738     interface_type = interface[:3]
739    
740     # Check to see if there is a startup script for this interface, if there isn't link to the proper script
741     try:
742 codeman 201 os.stat(self._chroot_dir + "/etc/init.d/net." + interface)
743 samyron 102 except:
744 codeman 201 os.symlink(self._chroot_dir + "/etc/init.d/net." + interface_type + "0", self._chroot_dir + "/etc/init.d/net." + interface)
745 samyron 102
746 codeman 409 # If we are going to load the network at boot...
747     if interfaces[interface][2]:
748    
749     # Add it to the default runlevel
750     self._add_to_runlevel("net."+interface)
751    
752 samyron 102 #
753     # ETHERNET
754     #
755     if interface_type == "eth":
756    
757     #
758     # STATIC IP
759     #
760     # If the post-install device info is not None, then it is a static ip addy
761     if interfaces[interface][1]:
762     ip = interfaces[interface][0]
763     broadcast = interfaces[interface][1]
764     netmask = interfaces[interface][2]
765     # aliases = interfaces[interface][1][3]
766     # alias_ips = []
767     # alias_broadcasts = []
768     # alias_netmasks = []
769    
770     # Write the static ip config to /etc/conf.d/net
771 codeman 217 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: ip + " broadcast " + broadcast + " netmask " + netmask})
772 samyron 102
773     # If aliases are set
774     # if aliases:
775    
776     # Parse aliases to format alias info
777     # for alias in aliases:
778     # alias_ips.append(alias[0])
779     # alias_broadcasts.append(alias[1])
780     # alias_netmasks.append(allias[2])
781    
782     # Once the alias info has been gathered, then write it out
783     # Alias ips first
784 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "alias_" + interface, string.join(alias_ips))
785 samyron 102 # Alias broadcasts next
786 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "broadcast_" + interface, string.join(alias_broadcasts))
787 samyron 102 # Alias netmasks last
788 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "netmask_" + interface, string.join(alias_netmasks))
789 samyron 102
790     #
791     # DHCP IP
792     #
793     else:
794 codeman 217 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: "dhcp"})
795 codeman 347 emerge_dhcp = True
796 codeman 319 if emerge_dhcp:
797     exitstatus = self._emerge("dhcpcd")
798     if exitstatus != 0:
799     self._logger.log("ERROR! : Could not emerge dhcpcd!")
800     else:
801     self._logger.log("dhcpcd emerged.")
802    
803 samyron 102 def set_root_password(self):
804     "Sets the root password"
805 agaffney 472 status = GLIUtility.spawn('echo \'root:' + self._install_profile.get_root_pass_hash() + '\' | chroot '+self._chroot_dir+' chpasswd -e', quiet=True)
806 codeman 237 if not GLIUtility.exitsuccess(status):
807 codeman 318 raise GLIException("SetRootPasswordError", 'fatal', 'set_root_password', "Failure to set root password!")
808 codeman 314 self._logger.log("Root Password set on the new system.")
809    
810 samyron 102 def set_users(self):
811     "Sets up the new users for the system"
812     # Loop for each user
813     for user in self._install_profile.get_users():
814    
815     # Get values from the tuple
816     username = user[0]
817     password_hash = user[1]
818     groups = user[2]
819     shell = user[3]
820     home_dir = user[4]
821     uid = user[5]
822     comment = user[6]
823    
824 agaffney 473 options = [ "-m", "-p '" + password_hash + "'" ]
825 samyron 102
826     # If the groups are specified
827     if groups:
828    
829     # If just one group is listed as a string, make it a list
830     if groups == str:
831     groups = [ groups ]
832    
833     # If only 1 group is listed
834     if len(groups) == 1:
835     options.append("-G " + groups[0])
836    
837     # If there is more than one group
838     elif len(groups) > 1:
839     options.append('-G "' + string.join(groups, ",") + '"')
840    
841     # If a shell is specified
842     if shell:
843     options.append("-s " + shell)
844    
845     # If a home dir is specified
846     if home_dir:
847     options.append("-d " + home_dir)
848    
849     # If a UID is specified
850     if uid:
851     options.append("-u " + str(uid))
852    
853     # If a comment is specified
854     if comment:
855     options.append('-c "' + comment + '"')
856    
857     # Add the user
858 agaffney 451 exitstatus = GLIUtility.spawn('useradd ' + string.join(options) + ' ' + username, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True, display_on_tty8=True)
859 codeman 237 if not GLIUtility.exitsuccess(exitstatus):
860 codeman 318 self._logger.log("ERROR! : Failure to add user " + username)
861     # raise GLIException("AddUserError", 'warning', 'set_users', "Failure to add user " + username)
862     else:
863     self._logger.log("User "+username+"was added.")
864 codeman 314
865 codeman 432 def finishing_cleanup(self):
866     "This function will handle the various cleanup tasks as well as unmounting the filesystems for reboot."
867     #These are temporary until I come up with a nicer idea.
868 codeman 443
869     #get rid of the compile_output file so the symlink doesn't get screwed up.
870    
871     #we copy the log over to the new system.
872 codeman 432 install_logfile = self._client_configuration.get_log_file()
873     try:
874     shutil.copy(install_logfile, self._chroot_dir + install_logfile)
875     except:
876     pass
877     #Now we're done logging as far as the new system is concerned.
878    
879     #Unmount the /proc and /dev that we mounted in prepare_chroot
880     #There really isn't a reason to log errors here.
881 agaffney 451 ret = GLIUtility.spawn("umount "+self._chroot_dir+"/proc", display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
882     ret = GLIUtility.spawn("umount "+self._chroot_dir+"/dev", display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
883 codeman 432 #temp hack to unmount the new root.
884 agaffney 451 ret = GLIUtility.spawn("umount "+self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
885 codeman 432 #insert code here to unmount the swap partition, if there is one.
886 agaffney 453
887     GLIUtility.spawn("rm /tmp/compile_output.log && rm " + install_logfile)
888 codeman 432
889 codeman 213 def install_bootloader(self):
890     "THIS FUNCTION MUST BE DONE BY THE INDIVIDUAL ARCH"
891     pass

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20