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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1808 - (show annotations) (download) (as text)
Sun Mar 18 20:45:40 2007 UTC (7 years, 9 months ago) by agaffney
File MIME type: text/x-python
File size: 71967 byte(s)
add ability to specify runlevel with service
1 """
2 # Copyright 1999-2005 Gentoo Foundation
3 # This source code is distributed under the terms of version 2 of the GNU
4 # General Public License as published by the Free Software Foundation, a copy
5 # of which can be found in the main directory of this project.
6 Gentoo Linux Installer
7
8 $Id: GLIArchitectureTemplate.py,v 1.297 2006/09/15 16:37:11 agaffney Exp $
9
10 The ArchitectureTemplate is largely meant to be an abstract class and an
11 interface (yes, it is both at the same time!). The purpose of this is to create
12 subclasses that populate all the methods with working methods for that architecture.
13 The only definitions that are filled in here are architecture independent.
14
15 """
16
17 import GLIUtility, GLILogger, os, string, sys, shutil, re, time
18 import GLIPortage
19 from GLIException import *
20 import Partitioning
21
22 MEGABYTE = 1024 * 1024
23 LOGFILE = '/var/log/installer.log'
24 COMPILE_LOGFILE = '/tmp/compile_output.log'
25
26 class ArchitectureTemplate:
27 ##
28 # Initialization of the ArchitectureTemplate. Called from some other arch template.
29 # @param install_profile=None An Install Profile
30 # @param client_controller=None Client Controller. not same as configuration.
31 def __init__(self,install_profile=None, client_controller=None):
32 self._install_profile = install_profile
33 self._cc = client_controller
34
35 # This will get used a lot, so it's probably
36 # better to store it in a variable than to call
37 # this method 100000 times.
38 self._chroot_dir = self._install_profile.get_root_mount_point()
39 self._logger = GLILogger.Logger(LOGFILE)
40 self._compile_logfile = COMPILE_LOGFILE
41 self._debug = self._install_profile.get_verbose()
42
43 self._portage = GLIPortage.GLIPortage(self._chroot_dir, self._logger, self._debug, self._cc, self._compile_logfile)
44
45 # This will cleanup the logfile if it's a dead link (pointing
46 # to the chroot logfile when partitions aren't mounted, else
47 # no action needs to be taken
48
49 if os.path.islink(self._compile_logfile) and not os.path.exists(self._compile_logfile):
50 os.unlink(self._compile_logfile)
51
52 # cache the list of successfully mounted devices and swap devices here
53 self._mounted_devices = []
54 self._swap_devices = []
55
56 # These must be filled in by the subclass. _steps is a list of
57 # functions, that will carry out the installation. They must be
58 # in order.
59 #
60 # For example, self._steps might be: [preinstall, stage1, stage2, stage3, postinstall],
61 # where each entry is a function (with no arguments) that carries out the desired actions.
62 # Of course, steps will be different depending on the install_profile
63
64 self._architecture_name = "generic"
65 self._install_steps = {
66 'do_recommended_partitioning': "Automatically partition the drive",
67 'mount_local_partitions': "Mount local partitions",
68 'mount_network_shares': "Mount network (NFS) shares",
69 'unpack_stage_tarball': "Unpack stage tarball",
70 'update_config_files': "Updating config files",
71 'configure_make_conf': "Configure /etc/make.conf",
72 'prepare_chroot': "Preparing chroot",
73 'install_portage_tree': "Syncing the Portage tree",
74 'stage1': "Performing bootstrap",
75 'stage2': "Performing 'emerge system'",
76 'set_root_password': "Set the root password",
77 'set_timezone': "Setting timezone",
78 'emerge_kernel_sources': "Emerge kernel sources",
79 'build_kernel': "Building kernel",
80 'install_distcc': "Install distcc",
81 'install_mta': "Installing MTA",
82 'install_logging_daemon': "Installing system logger",
83 'install_cron_daemon': "Installing Cron daemon",
84 'install_filesystem_tools': "Installing filesystem tools",
85 'setup_network_post': "Configuring post-install networking",
86 'install_bootloader': "Configuring and installing bootloader",
87 'setup_and_run_bootloader': "Setting up and running bootloader",
88 # 'update_config_files': "Re-Updating config files", #second run.
89 'set_users': "Add additional users.",
90 'install_packages': "Installing additional packages.",
91 # services for startup need to come after installing extra packages
92 # otherwise some of the scripts will not exist.
93 'set_services': "Setting up services for startup",
94 'run_post_install_script': "Running custom post-install script",
95 'finishing_cleanup': "Cleanup and unmounting local filesystems.",
96 'install_failed_cleanup': "Cleaning up after a failed install"
97 }
98
99 ##
100 # Returns the steps and their comments in an array
101 def get_install_steps(self):
102 return self._install_steps
103
104 ##
105 # Tells the frontend something
106 # @param type type of data
107 # @param data the data itself. usually a number.
108 def notify_frontend(self, type, data):
109 self._cc.addNotification(type, data)
110
111 # It is possible to override these methods in each Arch Template.
112 # It might be necessary to do so, if the arch needs something 'weird'.
113
114 ######################## Private Functions ########################
115 ##
116 # Private function to add a /etc/init.d/ script to the given runlevel in the chroot environement
117 # @param script_name the script to be added
118 # @param runlevel="default" the runlevel to add to
119 def _add_to_runlevel(self, script_name, runlevel="default"):
120 if not GLIUtility.is_file(self._chroot_dir + '/etc/init.d/' + script_name):
121 #raise GLIException("RunlevelAddError", 'fatal', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
122 #This is not a fatal error. If the init script is important it will exist.
123 self._logger.log("ERROR! Failure adding " + script_name + " to runlevel " + runlevel + " because it was not found!")
124 if self._debug: self._logger.log("DEBUG: running rc-update add " + script_name + " " + runlevel + " in chroot.")
125 status = GLIUtility.spawn("rc-update add " + script_name + " " + runlevel, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
126 if not GLIUtility.exitsuccess(status):
127 #raise GLIException("RunlevelAddError", 'fatal', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
128 #Again, an error here will not prevent a new system from booting. But it is important to log the error.
129 self._logger.log("ERROR! Could not add " + script_name + " to runlevel " + runlevel + ". returned a bad status code.")
130 else:
131 self._logger.log("Added "+script_name+" to runlevel "+runlevel)
132
133 ##
134 # Private Function. Will return a list of packages to be emerged for a given command. Not yet used.
135 # @param cmd full command to run ('/usr/portage/scripts/bootstrap.sh --pretend' or 'emerge -p system')
136 def _get_packages_to_emerge(self, cmd):
137 if self._debug: self._logger.log("DEBUG: _get_packages_to_emerge() called with '%s'" % cmd)
138 return GLIUtility.spawn(cmd + r" 2>/dev/null | grep -e '\[ebuild' | sed -e 's:\[ebuild .\+ \] ::' -e 's: \[.\+\] ::' -e 's: \+$::'", chroot=self._chroot_dir, return_output=True)[1].strip().split("\n")
139
140 ##
141 # Private Function. Will emerge a given package in the chroot environment.
142 # @param package package to be emerged
143 # @param binary=False defines whether to try a binary emerge (if GRP this gets ignored either way)
144 # @param binary_only=False defines whether to only allow binary emerges.
145 def _emerge(self, package, binary=True, binary_only=False):
146 #Error checking of this function is to be handled by the parent function.
147 # self._logger.log("_emerge() called with: package='%s', binary='%s', binary_only='%s', grp_install='%s'" % (package, str(binary), str(binary_only), str(self._install_profile.get_grp_install())))
148 # now short-circuit for GRP
149 if self._install_profile.get_grp_install():
150 cmd="emerge -k " + package
151 # now normal installs
152 else:
153 if binary_only:
154 cmd="emerge -K " + package
155 elif binary:
156 cmd="emerge -k " + package
157 else:
158 cmd="emerge " + package
159
160 self._logger.log("Calling emerge: "+cmd)
161 return GLIUtility.spawn(cmd, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
162
163 ##
164 # Private Function. Will edit a config file and insert a value or two overwriting the previous value
165 # (actually it only just comments out the old one)
166 # @param filename file to be edited
167 # @param newvalues a dictionary of VARIABLE:VALUE pairs
168 # @param delimeter='=' what is between the key and the value
169 # @param quotes_around_value=True whether there are quotes around the value or not (ex. "local" vs. localhost)
170 # @param only_value=False Ignore the keys and output only a value.
171 # @param create_file=True Create the file if it does not exist.
172 def _edit_config(self, filename, newvalues, delimeter='=', quotes_around_value=True, only_value=False,create_file=True):
173 # don't use 'file' as a normal variable as it conflicts with the __builtin__.file
174 newvalues = newvalues.copy()
175 if self._debug: self._logger.log("DEBUG: _edit_config() called with " + str(newvalues)+" and flags: "+delimeter + "quotes: "+str(quotes_around_value)+" value: "+str(only_value))
176 if GLIUtility.is_file(filename):
177 f = open(filename)
178 contents = f.readlines()
179 f.close()
180 elif create_file:
181 contents = []
182 else:
183 raise GLIException("NoSuchFileError", 'notice','_edit_config',filename + ' does not exist!')
184
185 for key in newvalues.keys():
186 newline = ""
187 if key == "SPACER":
188 newline = "\n"
189 elif key == "COMMENT":
190 newline = '# ' + newvalues[key] + "\n"
191 elif newvalues[key] == "##comment##" or newvalues[key] == "##commented##":
192 newline = '#' + key + delimeter + '""' + "\n"
193 else:
194 if quotes_around_value:
195 newvalues[key] = '"' + newvalues[key] + '"'
196 #Only the printing of values is required.
197 if only_value:
198 newline = newvalues[key] + "\n"
199 else:
200 newline = key + delimeter + newvalues[key] + "\n"
201 add_at_line = len(contents)
202 for i in range(len(contents)):
203 if newline == contents[i]:
204 break
205 if contents[i].startswith(key + delimeter):
206 contents[i] = "#" + contents[i]
207 add_at_line = i + 1
208 else:
209 contents.insert(add_at_line, newline)
210 if self._debug: self._logger.log("DEBUG: Contents of file "+filename+": "+str(contents))
211 f = open(filename,'w')
212 f.writelines(contents)
213 f.flush()
214 f.close()
215 self._logger.log("Edited Config file "+filename)
216
217 ##
218 # Configures /etc/fstab on the new envorinment
219 def _configure_fstab(self):
220 newfstab = ""
221 mounts = self._install_profile.get_mounts()
222 for mount in mounts:
223 if mount['type'] == "linux-swap":
224 newfstab += mount['devnode']+"\t none swap sw 0 0\n"
225 continue #Stop here and move on.
226 if not mount['mountopts'].strip(): mount['mountopts'] = "defaults"
227 if mount['mountpoint']:
228 if not GLIUtility.is_file(self._chroot_dir+mount['mountpoint']):
229 if self._debug: self._logger.log("DEBUG: making mountpoint: "+mount['mountpoint'])
230 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mount['mountpoint'])
231 if not GLIUtility.exitsuccess(exitstatus):
232 raise GLIException("MkdirError", 'fatal','configure_fstab', "Making the mount point failed!")
233 newfstab += mount['devnode']+"\t "+mount['mountpoint']+"\t "+mount['type']+"\t "+mount['mountopts']+"\t\t "
234 #Now figure out the last 2 numbers depending on the mountpoint.
235 if mount['mountpoint'] == "/boot":
236 newfstab += "1 2\n"
237 elif mount['mountpoint'] == "/":
238 newfstab += "0 1\n"
239 else:
240 newfstab += "0 0\n"
241
242 newfstab += "none /proc proc defaults 0 0\n"
243 newfstab += "none /dev/shm tmpfs defaults 0 0\n"
244 if GLIUtility.is_device("/dev/cdroms/cdrom0"):
245 newfstab += "/dev/cdroms/cdrom0 /mnt/cdrom auto noauto,user 0 0\n"
246
247 for netmount in self._install_profile.get_network_mounts():
248 if netmount['type'] == "nfs":
249 newfstab += netmount['host'] + ":" + netmount['export'] + "\t" + netmount['mountpoint'] + "\tnfs\t" + netmount['mountopts'] + "\t0 0\n"
250
251 file_name = self._chroot_dir + "/etc/fstab"
252 try:
253 if self._debug: self._logger.log("DEBUG: backing up original fstab")
254 shutil.move(file_name, file_name + ".OLDdefault")
255 except:
256 self._logger.log("ERROR: could not backup original fstab.")
257 if self._debug: self._logger.log("DEBUG: Contents of new fstab: "+newfstab)
258 f = open(file_name, 'w')
259 f.writelines(newfstab)
260 f.close()
261 self._logger.log("fstab configured.")
262
263 #####################################################################
264 #####################################################################
265 ########################## Installation Functions ###################
266
267 ##
268 # Will automatically partition the hard drive if both paramaters
269 # in the install_profile are correctly set. This in turn will
270 # appropriately set the mountpoints for the rest of the install.
271 # This function is to be called only for fully-automated installs.
272 def do_recommended_partitioning(self):
273 drive = self._install_profile.get_do_recommended_partitioning() #returns drive name.
274 second_check = self._install_profile.get_yes_iam_sure()
275 if drive and second_check:
276 try:
277 self._logger.log("Creating the drive object for drive %s for do_recommended" % drive)
278 driveobject = Partitioning.Device(drive, self._architecture_name, self._install_profile)
279 self._logger.log("Running do_recommended!")
280 driveobject.do_recommended()
281 self._logger.log("do_recommended complete! mountpoints should now be set.")
282 except:
283 raise GLIException("DoRecommendedError", 'fatal','do_recommended_partitioning', "An Error occurred while trying to run do_recommended!")
284
285
286 ##
287 # Will grab partition info from the profile and mount all partitions with a specified mountpoint (and swap too)
288 def mount_local_partitions(self):
289 #Temporary hack here to update the debug value.
290 self._debug = self._install_profile.get_verbose()
291
292 mounts = self._install_profile.get_mounts()
293 mount_progress = 1
294 self.notify_frontend("progress", (float(mount_progress) / (len(mounts)+1), "Generating mount list"))
295 parts_to_mount = {}
296 for mount in mounts:
297 Partitioning.wait_for_device_node(mount['devnode'])
298 mountpoint = mount['mountpoint']
299 mountopts = mount['mountopts']
300 partition_type = mount['type']
301 if not mountpoint:
302 continue #Skip this. Probably should be an error. but should NEVER happen.
303 if mountopts:
304 mountopts = "-o " + mountopts + " "
305 if partition_type in ("linux-swap", "swap"):
306 mount_progress += 1
307 self.notify_frontend("progress", (float(mount_progress) / (len(mounts)+1), "Activating swap on " + mount['devnode']))
308 ret = GLIUtility.spawn("swapon " + mount['devnode'])
309 if not GLIUtility.exitsuccess(ret):
310 self._logger.log("ERROR! : Could not activate swap (" + mount['devnode'] + ")!")
311 else:
312 self._swap_devices.append(mount['devnode'])
313 continue
314 elif partition_type:
315 if partition_type == "fat32" or partition_type == "fat16":
316 partition_type = "vfat"
317 partition_type = "-t " + partition_type + " "
318 else: #Unknown partition type!!!
319 self._logger.log("ERROR! : Unknown partition type for mountpoint %s which is device %s" % (mountpoint, mount['devnode']))
320 parts_to_mount[mountpoint] = (mountopts, partition_type, mount['devnode'])
321
322 sorted_list = parts_to_mount.keys()
323 sorted_list.sort()
324
325 if not GLIUtility.is_file(self._chroot_dir):
326 if self._debug: self._logger.log("DEBUG: making the chroot dir")
327 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir)
328 if not GLIUtility.exitsuccess(exitstatus):
329 raise GLIException("MkdirError", 'fatal','mount_local_partitions', "Making the ROOT mount point failed!")
330 else:
331 self._logger.log("Created root mount point")
332 for i, mountpoint in enumerate(sorted_list):
333 mountopts = parts_to_mount[mountpoint][0]
334 partition_type = parts_to_mount[mountpoint][1]
335 partition = parts_to_mount[mountpoint][2]
336 mount_progress += 1
337 self.notify_frontend("progress", (float(mount_progress) / (len(mounts)+1), "Mounting %s at %s" % (partition, mountpoint)))
338 if not GLIUtility.is_file(self._chroot_dir + mountpoint):
339 if self._debug: self._logger.log("DEBUG: making mountpoint: "+mountpoint)
340 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
341 if not GLIUtility.exitsuccess(exitstatus):
342 raise GLIException("MkdirError", 'fatal','mount_local_partitions', "Making the mount point failed!")
343 else:
344 self._logger.log("Created mountpoint " + mountpoint)
345 if self._debug: self._logger.log("DEBUG: running mount "+ partition_type + mountopts + partition + " " + self._chroot_dir + mountpoint)
346 ret = GLIUtility.spawn("mount " + partition_type + mountopts + partition + " " + self._chroot_dir + mountpoint, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
347 if not GLIUtility.exitsuccess(ret):
348 raise GLIException("MountError", 'fatal','mount_local_partitions','Could not mount a partition')
349 else:
350 self._mounted_devices.append(mountpoint)
351 # double check in /proc/mounts
352 # This current code doesn't work and needs to be fixed, because there is a case that it is needed for - robbat2
353 #ret, output = GLIUtility.spawn('awk \'$2 == "%s" { print "Found" }\' /proc/mounts | head -n1' % (self._chroot_dir + mountpoint), display_on_tty8=True, return_output=True)
354 #if output.strip() != "Found":
355 # raise GLIException("MountError", 'fatal','mount_local_partitions','Could not mount a partition (failed in double-check)')
356 self._logger.log("Mounted mountpoint: " + mountpoint)
357 if self._debug: self._logger.log("DEBUG: mounted_devices is %s" % str(self._mounted_devices))
358 ##
359 # Mounts all network shares to the local machine
360 def mount_network_shares(self):
361 """
362 <agaffney> it'll be much easier than mount_local_partitions
363 <agaffney> make sure /etc/init.d/portmap is started
364 <agaffney> then mount each one: mount -t nfs -o <mountopts> <host>:<export> <mountpoint>
365 """
366 nfsmounts = self._install_profile.get_network_mounts()
367 for netmount in nfsmounts:
368 if netmount['type'] == "NFS" or netmount['type'] == "nfs":
369 mountopts = netmount['mountopts']
370 if mountopts:
371 mountopts = "-o " + mountopts
372 host = netmount['host']
373 export = netmount['export']
374 mountpoint = netmount['mountpoint']
375 if not GLIUtility.is_file(self._chroot_dir + mountpoint):
376 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
377 if not GLIUtility.exitsuccess(exitstatus):
378 raise GLIException("MkdirError", 'fatal','mount_network_shares', "Making the mount point failed!")
379 else:
380 if self._debug: self._logger.log("DEBUG: mounting nfs mount")
381 ret = GLIUtility.spawn("mount -t nfs " + mountopts + " " + host + ":" + export + " " + self._chroot_dir + mountpoint, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
382 if not GLIUtility.exitsuccess(ret):
383 raise GLIException("MountError", 'fatal','mount_network_shares','Could not mount an NFS partition')
384 else:
385 self._logger.log("Mounted netmount at mountpoint: " + mountpoint)
386 self._mounted_devices.append(mountpoint)
387 else:
388 self._logger.log("Netmount type " + netmount['type'] + " not supported...skipping " + netmount['mountpoint'])
389
390 ##
391 # Unpacks the stage tarball that has been specified in the profile (it better be there!)
392 def unpack_stage_tarball(self):
393 if not os.path.isdir(self._chroot_dir):
394 if self._debug: self._logger.log("DEBUG: making the chroot dir:"+self._chroot_dir)
395 os.makedirs(self._chroot_dir)
396 if self._install_profile.get_install_stage() == 3 and self._install_profile.get_dynamic_stage3():
397 # stage3 generation code here
398 if not GLIUtility.is_file("/usr/livecd/systempkgs.txt"):
399 raise GLIException("CreateStage3Error", "fatal", "unpack_stage_tarball", "Required file /usr/livecd/systempkgs.txt does not exist")
400 try:
401 syspkgs = open("/usr/livecd/systempkgs.txt", "r")
402 systempkgs = [line for line in syspkgs.readlines() if line.strip()]
403 syspkgs.close()
404 except:
405 raise GLIException("CreateStage3Error", "fatal", "unpack_stage_tarball", "Could not open /usr/livecd/systempkgs.txt")
406
407 # Pre-create /lib (and possibly /lib32 and /lib64)
408 for libdir in ("/lib", "/usr/lib"):
409 if os.path.islink(libdir) and os.readlink(libdir).endswith("64"):
410 if self._debug: self._logger.log("DEBUG: unpack_stage_tarball(): precreating " + libdir + "64 dir and " + libdir + " -> lib64 symlink because glibc/portage sucks")
411 if not GLIUtility.exitsuccess(GLIUtility.spawn("mkdir -p " + self._chroot_dir + libdir + "64 && ln -sf lib64 " + self._chroot_dir + libdir)):
412 raise GLIException("CreateStage3Error", "fatal", "unpack_stage_tarball", "Could not precreate " + libdir + "64 dir and " + libdir + " -> lib64 symlink")
413
414 syspkglen = len(systempkgs)
415 for i, pkg in enumerate(systempkgs):
416 pkg = pkg.strip()
417 self.notify_frontend("progress", (float(i) / (syspkglen+1), "Copying " + pkg + " (" + str(i+1) + "/" + str(syspkglen) + ")"))
418 self._portage.copy_pkg_to_chroot(pkg, True, ignore_missing=True)
419 self.notify_frontend("progress", (float(syspkglen) / (syspkglen+1), "Finishing"))
420 GLIUtility.spawn("cp /etc/make.conf " + self._chroot_dir + "/etc/make.conf")
421 GLIUtility.spawn("ln -s `readlink /etc/make.profile` " + self._chroot_dir + "/etc/make.profile")
422 GLIUtility.spawn("cp -f /etc/inittab.old " + self._chroot_dir + "/etc/inittab")
423
424 # Nasty, nasty, nasty hack because vapier is a tool
425 for tmpfile in ("/etc/passwd", "/etc/group", "/etc/shadow"):
426 GLIUtility.spawn("grep -ve '^gentoo' " + tmpfile + " > " + self._chroot_dir + tmpfile)
427
428 chrootscript = r"""
429 #!/bin/bash
430 source /etc/make.conf
431 export LDPATH="/usr/lib/gcc-lib/${CHOST}/$(cd /usr/lib/gcc-lib/${CHOST} && ls -1 | head -n 1)"
432 ldconfig $LDPATH
433 gcc-config 1
434 env-update
435 source /etc/profile
436 modules-update
437 [ -f /usr/bin/binutils-config ] && binutils-config 1
438 source /etc/profile
439 cd /dev
440 rm console null
441 mknod console c 5 1
442 mknod null c 1 3
443 mkdir -m 755 /mnt
444 mkdir -m 700 /mnt/cdrom
445 mkdir -m 700 /mnt/floppy
446 [ -f /usr/sbin/create-cracklib-dict ] && /usr/sbin/create-cracklib-dict /usr/share/dict/* > /dev/null
447 # [ -f /lib/udev-state/devices.tar.bz2 ] && tar -C /dev -xjf /lib/udev-state/devices.tar.bz2
448 """
449
450 script = open(self._chroot_dir + "/tmp/extrastuff.sh", "w")
451 script.write(chrootscript)
452 script.close()
453 GLIUtility.spawn("chmod 755 /tmp/extrastuff.sh && /tmp/extrastuff.sh", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
454 GLIUtility.spawn("rm -rf /var/tmp/portage/* /usr/portage /tmp/*", chroot=self._chroot_dir)
455 self.notify_frontend("progress", (1, "Done"))
456 self._logger.log("Stage3 was generated successfully")
457 else:
458 self._logger.log("Fetching and unpacking tarball: "+self._install_profile.get_stage_tarball_uri())
459 GLIUtility.fetch_and_unpack_tarball(self._install_profile.get_stage_tarball_uri(), self._chroot_dir, temp_directory=self._chroot_dir, keep_permissions=True, cc=self._cc)
460 self._logger.log(self._install_profile.get_stage_tarball_uri()+" was fetched and unpacked.")
461
462 ##
463 # This runs etc-update and then re-overwrites the files by running the configure_*'s to keep our values.
464 def update_config_files(self):
465 "Runs etc-update (overwriting all config files), then re-configures the modified ones"
466 # Run etc-update overwriting all config files
467 if self._debug: self._logger.log("DEBUG: update_config_files(): running: "+'echo "-5" | chroot '+self._chroot_dir+' etc-update')
468 status = GLIUtility.spawn('echo "-5" | chroot '+self._chroot_dir+' etc-update', display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
469 if not GLIUtility.exitsuccess(status):
470 self._logger.log("ERROR! : Could not update the config files!")
471 else:
472 self._configure_fstab()
473 etc_files = self._install_profile.get_etc_files()
474 for etc_file in etc_files:
475 # Skip entries with blank filenames
476 if not etc_file: continue
477 if self._debug: self._logger.log("DEBUG: update_config_files(): updating config file: "+etc_file)
478 if isinstance(etc_files[etc_file], dict):
479 self._edit_config(self._chroot_dir + "/etc/" + etc_file, etc_files[etc_file])
480 else:
481 for entry in etc_files[etc_file]:
482 # Skip blank entries
483 if not entry: continue
484 self._edit_config(self._chroot_dir + "/etc/" + etc_file, { "0": entry }, only_value=True)
485 self._logger.log("Config files updated using etc-update. make.conf/fstab/rc.conf restored.")
486
487 ##
488 # Configures the new /etc/make.conf
489 def configure_make_conf(self):
490 # Get make.conf options
491 make_conf = self._install_profile.get_make_conf()
492
493 # For each configuration option...
494 filename = self._chroot_dir + "/etc/make.conf"
495 # self._edit_config(filename, {"COMMENT": "GLI additions ===>"})
496 for key in make_conf.keys():
497 # Add/Edit it into make.conf
498 self._edit_config(filename, {key: make_conf[key]})
499 # self._edit_config(filename, {"COMMENT": "<=== End GLI additions"})
500
501 self._logger.log("Make.conf configured")
502 # now make any directories that emerge needs, otherwise it will fail
503 # this must take place before ANY calls to emerge.
504 # otherwise emerge will fail (for PORTAGE_TMPDIR anyway)
505 # defaults first
506 # this really should use portageq or something.
507 PKGDIR = '/usr/portage/packages'
508 PORTAGE_TMPDIR = '/var/tmp'
509 PORT_LOGDIR = None
510 PORTDIR_OVERLAY = None
511 # now other stuff
512 if 'PKGDIR' in make_conf: PKGDIR = make_conf['PKGDIR']
513 if 'PORTAGE_TMPDIR' in make_conf: PORTAGE_TMPDIR = make_conf['PORTAGE_TMPDIR']
514 if 'PORT_LOGDIR' in make_conf: PORT_LOGDIR = make_conf['PORT_LOGDIR']
515 if 'PORTDIR_OVERLAY' in make_conf: PORTDIR_OVERLAY = make_conf['PORTDIR_OVERLAY']
516 if self._debug: self._logger.log("DEBUG: making PKGDIR if necessary: "+PKGDIR)
517 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PKGDIR, logfile=self._compile_logfile, append_log=True)
518 if self._debug: self._logger.log("DEBUG: making PORTAGE_TMPDIR if necessary: "+PORTAGE_TMPDIR)
519 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTAGE_TMPDIR, logfile=self._compile_logfile, append_log=True)
520 if PORT_LOGDIR != None:
521 if self._debug: self._logger.log("DEBUG: making PORT_LOGDIR if necessary: "+PORT_LOGDIR)
522 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORT_LOGDIR, logfile=self._compile_logfile, append_log=True)
523 if PORTDIR_OVERLAY != None:
524 if self._debug: self._logger.log("DEBUG: making PORTDIR_OVERLAY if necessary "+PORTDIR_OVERLAY)
525 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTDIR_OVERLAY, logfile=self._compile_logfile, append_log=True)
526
527 ##
528 # Prepares the Chroot environment by copying /etc/resolv.conf and mounting proc and dev
529 def prepare_chroot(self):
530 # Copy resolv.conf to new env
531 try:
532 if self._debug: self._logger.log("DEBUG: copying /etc/resolv.conf over.")
533 shutil.copy("/etc/resolv.conf", self._chroot_dir + "/etc/resolv.conf")
534 except:
535 pass
536 if self._debug: self._logger.log("DEBUG: mounting proc")
537 if not os.path.isdir(self._chroot_dir+"/proc"):
538 if self._debug: self._logger.log("DEBUG: making the proc dir in chroot")
539 os.makedirs(self._chroot_dir+"/proc")
540 ret = GLIUtility.spawn("mount -t proc none "+self._chroot_dir+"/proc")
541 if not GLIUtility.exitsuccess(ret):
542 raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /proc')
543 else:
544 self._mounted_devices.append("/proc")
545 bind_mounts = [ '/dev' ]
546 uname = os.uname()
547 if uname[0] == 'Linux' and uname[2].split('.')[1] == '6':
548 bind_mounts.append('/sys')
549 if self._debug: self._logger.log("DEBUG: bind-mounting " + ", ".join(bind_mounts))
550 for mount in bind_mounts:
551 if not os.path.isdir(self._chroot_dir+mount):
552 if self._debug: self._logger.log("DEBUG: making the %s dir in chroot" % mount)
553 os.makedirs(self._chroot_dir+mount)
554 ret = GLIUtility.spawn('mount -o bind %s %s%s' % (mount,self._chroot_dir,mount))
555 if not GLIUtility.exitsuccess(ret):
556 raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount '+mount)
557 else:
558 self._mounted_devices.append(mount)
559 if self._debug: self._logger.log("DEBUG: copying logfile to new system!")
560 GLIUtility.spawn("mv " + self._compile_logfile + " " + self._chroot_dir + self._compile_logfile + " && ln -s " + self._chroot_dir + self._compile_logfile + " " + self._compile_logfile)
561 self._logger.log("Chroot environment ready.")
562
563 ##
564 # This will get/update the portage tree. If you want to snapshot or mount /usr/portage use "custom".
565 def install_portage_tree(self):
566 # Check the type of portage tree fetching we'll do
567 # If it is custom, follow the path to the custom tarball and unpack it
568
569 sync_type = self._install_profile.get_portage_tree_sync_type()
570 if sync_type == "snapshot" or sync_type == "custom": # Until this is finalized
571
572 # Get portage tree info
573 portage_tree_snapshot_uri = self._install_profile.get_portage_tree_snapshot_uri()
574 if portage_tree_snapshot_uri:
575 # Fetch and unpack the tarball
576 if self._debug: self._logger.log("DEBUG: grabbing custom snapshot uri: "+portage_tree_snapshot_uri)
577 GLIUtility.fetch_and_unpack_tarball(portage_tree_snapshot_uri, self._chroot_dir + "/usr/", self._chroot_dir + "/", cc=self._cc)
578 if GLIUtility.is_file("/usr/livecd/metadata.tar.bz2"):
579 GLIUtility.fetch_and_unpack_tarball("/usr/livecd/metadata.tar.bz2", self._chroot_dir + "/", self._chroot_dir + "/", cc=self._cc)
580 self._logger.log("Portage tree install was custom.")
581 if sync_type == "sync":
582 if self._debug: self._logger.log("DEBUG: starting emerge sync")
583 exitstatus = GLIUtility.spawn("emerge sync", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
584 if not GLIUtility.exitsuccess(exitstatus):
585 self._logger.log("ERROR! Could not sync the portage tree using emerge sync. Falling back to emerge-webrsync as a backup.")
586 sync_type = "webrsync"
587 else:
588 self._logger.log("Portage tree sync'd")
589 # If the type is webrsync, then run emerge-webrsync
590 if sync_type == "webrsync":
591 if self._debug: self._logger.log("DEBUG: starting emerge webrsync")
592 exitstatus = GLIUtility.spawn("emerge-webrsync", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
593 if not GLIUtility.exitsuccess(exitstatus):
594 raise GLIException("EmergeWebRsyncError", 'fatal','install_portage_tree', "Failed to retrieve portage tree using webrsync!")
595 self._logger.log("Portage tree sync'd using webrsync")
596 # Otherwise, spit out a message because its probably a bad thing.
597 #else:
598 # self._logger.log("NOTICE! No valid portage tree sync method was selected. This will most likely result in a failed installation unless the tree is mounted.")
599
600
601 ##
602 # Stage 1 install -- bootstraping the system
603 # If we are doing a stage 1 install, then bootstrap
604 def stage1(self):
605 if self._install_profile.get_install_stage() == 1:
606 self._logger.mark()
607 self._logger.log("Starting bootstrap.")
608 pkgs = self._get_packages_to_emerge("/usr/portage/scripts/bootstrap.sh --pretend")
609 if self._debug: self._logger.log("DEBUG: Packages to emerge: "+str(pkgs)+". Now running bootstrap.sh")
610 exitstatus = GLIUtility.spawn("env-update && source /etc/profile && /usr/portage/scripts/bootstrap.sh", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
611 if not GLIUtility.exitsuccess(exitstatus):
612 raise GLIException("Stage1Error", 'fatal','stage1', "Bootstrapping failed!")
613 self._logger.log("Bootstrap complete.")
614
615 ##
616 # Stage 2 install -- emerge -e system
617 # If we are doing a stage 1 or 2 install, then emerge system
618 def stage2(self):
619 if self._install_profile.get_install_stage() in [ 1, 2 ]:
620 self._logger.mark()
621 self._logger.log("Starting emerge system.")
622 pkgs = self._get_packages_to_emerge("emerge -p system") #currently quite the useless
623 if self._debug: self._logger.log("DEBUG: Packages to emerge: "+str(pkgs)+"/ Now running emerge --emptytree system")
624 # exitstatus = self._emerge("--emptytree system")
625 exitstatus = GLIUtility.spawn("env-update && source /etc/profile && emerge -e system", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
626 if not GLIUtility.exitsuccess(exitstatus):
627 raise GLIException("Stage2Error", 'fatal','stage2', "Building the system failed!")
628 self._logger.log("Emerge system complete.")
629
630 ##
631 # Sets the root password
632 def set_root_password(self):
633 if self._debug: self._logger.log("DEBUG: set_root_password(): running: "+ 'echo \'root:' + self._install_profile.get_root_pass_hash() + '\' | chroot '+self._chroot_dir+' chpasswd -e')
634 status = GLIUtility.spawn('echo \'root:' + self._install_profile.get_root_pass_hash() + '\' | chroot '+self._chroot_dir+' chpasswd -e')
635 if not GLIUtility.exitsuccess(status):
636 raise GLIException("SetRootPasswordError", 'fatal', 'set_root_password', "Failure to set root password!")
637 self._logger.log("Root Password set on the new system.")
638
639 ##
640 # Sets the timezone for the new environment
641 def set_timezone(self):
642
643 # Set symlink
644 if os.access(self._chroot_dir + "/etc/localtime", os.W_OK):
645 if self._debug: self._logger.log("DEBUG: /etc/localtime already exists, removing it so it can be symlinked")
646 GLIUtility.spawn("rm "+self._chroot_dir + "/etc/localtime")
647 if self._debug: self._logger.log("DEBUG: running ln -s ../usr/share/zoneinfo/" + self._install_profile.get_time_zone() + " /etc/localtime")
648 GLIUtility.spawn("ln -s ../usr/share/zoneinfo/" + self._install_profile.get_time_zone() + " /etc/localtime", chroot=self._chroot_dir)
649 if not (self._install_profile.get_time_zone() == "UTC"):
650 if self._debug: self._logger.log("DEBUG: timezone was not UTC, setting CLOCK to local. This may be overwritten later.")
651 self._edit_config(self._chroot_dir + "/etc/conf.d/clock", {"CLOCK":"local"})
652 self._logger.log("Timezone set.")
653
654 ##
655 # Fetches desired kernel sources, unless you're using a livecd-kernel in which case it does freaky stuff.
656 def emerge_kernel_sources(self):
657 kernel_pkg = self._install_profile.get_kernel_source_pkg()
658 self._logger.log("Starting emerge_kernel, package is %s" % kernel_pkg)
659 # if kernel_pkg:
660 # Special case, no kernel installed
661 if kernel_pkg == "none":
662 return
663 # Special case, livecd kernel
664 elif kernel_pkg == "livecd-kernel":
665 if self._debug: self._logger.log("DEBUG: starting livecd-kernel setup")
666 self.notify_frontend("progress", (0, "Determining files to copy"))
667 GLIUtility.spawn(r"find /var/db/pkg -type f -name CONTENTS | xargs awk '/^obj \/lib\/modules\// { print $2; }' > /tmp/kernel_modules")
668 files = GLIUtility.spawn('ls -1 --color=no /boot/System* /boot/kernel* /boot/initr* $(for i in $(find "/lib/modules/" -type f); do grep --quiet "^${i}$" /tmp/kernel_modules || echo ${i}; done); rm /tmp/kernel_modules 2>/dev/null', return_output=True)[1].strip().split("\n")
669 if not files:
670 raise GLIException("LiveCDKernelError", 'fatal','emerge_kernel_sources', "Could not determine files to copy for livecd-kernel")
671 self.notify_frontend("progress", (0.25, "Copying kernel, initramfs, and modules"))
672 # self._portage.copy_pkg_to_chroot(self._portage.get_best_version_vdb("livecd-kernel"))
673 if not GLIUtility.exitsuccess(GLIUtility.spawn("cp -p --parents %s %s/" % (" ".join(files), self._chroot_dir), logfile=self._compile_logfile, append_log=True)):
674 raise GLIException("LiveCDKernelError", 'fatal','emerge_kernel_sources', "Could not copy kernel, initramfs, or modules")
675 self.notify_frontend("progress", (0.5, "Gathering portage configuration"))
676 portage_info = {}
677 for line in GLIUtility.spawn(r"emerge --info 2>/dev/null | grep '^[A-Z0-9_]\+=' | sed -e 's:\" \([A-Z]\):\"\n\1:g'", chroot=self._chroot_dir, return_output=True)[1].strip().split("\n"):
678 parts = line.split("=", 1)
679 portage_info[parts[0]] = parts[1].strip("'\"")
680 arch = portage_info["ACCEPT_KEYWORDS"].split(" ")[0].strip("~")
681 values = {
682 'CATEGORY': "sys-kernel",
683 'CBUILD': portage_info['CHOST'],
684 'CFLAGS': portage_info['CFLAGS'],
685 'CHOST': portage_info['CHOST'],
686 'CONTENTS': "",
687 # 'COUNTER': "0",
688 'CXXFLAGS': portage_info.get("CXXFLAGS", ""),
689 'DEPEND': "",
690 'DESCRIPTION': "LiveCD kernel as installed by GLI",
691 'EAPI': "0",
692 'FEATURES': "",
693 'HOMEPAGE': "http://www.gentoo.org/proj/en/releng/installer/",
694 'INHERITED': "eutils",
695 'KEYWORDS': arch,
696 'LICENSE': "",
697 'NEEDED': "",
698 'PDEPEND': "",
699 'PF': "livecd-kernel-1",
700 'PROVIDE': "virtual/alsa",
701 'RDEPEND': "",
702 'SLOT': "0",
703 'USE': arch
704 }
705 self.notify_frontend("progress", (0.75, "Creating VDB entry for livecd-kernel"))
706 vdbdir = self._chroot_dir + "/var/db/pkg/sys-kernel/livecd-kernel-1"
707 os.mkdir(vdbdir)
708 for tmpfile in values:
709 fileout = open(vdbdir + "/" + tmpfile, "w")
710 fileout.write(values[tmpfile] + "\n")
711 fileout.close()
712 fileout = open(vdbdir + "/livecd-kernel-1.ebuild", "w")
713 fileout.write("inherit eutils\n\nDESCRIPTION=\"LiveCD kernel as installed by GLI\"\nHOMEPAGE=\"http://www.gentoo.org/proj/en/releng/installer/\"\nSRC_URI=\nLICENSE=\nSLOT=0\nKEYWORDS=\"%s\"\nIUSE=\nDEPEND=\nPROVIDE=virtual/alsa\n" % arch)
714 fileout.close()
715 counter = self._portage.update_counter()
716 counter_f = open(self._chroot_dir + "/var/db/pkg/sys-kernel/livecd-kernel-1/COUNTER", "w")
717 counter_f.write(str(counter))
718 counter_f.close()
719 self.notify_frontend("progress", (1, "Done copying livecd-kernel to chroot"))
720
721 # exitstatus = self._portage.emerge("coldplug", self._install_profile.get_grp_install())
722 # self._logger.log("Coldplug emerged. Now they should be added to the boot runlevel.")
723 # self._add_to_runlevel("coldplug", runlevel="boot")
724
725 if self._install_profile.get_kernel_bootsplash():
726 self._logger.log("Bootsplash enabled for livecd-kernel...this is currently broken, so we're skipping the package install")
727 # self._logger.log("Bootsplash enabled...emerging necessary packages")
728 # self._portage.emerge(["splashutils", "splash-themes-livecd"])
729
730 # Extra modules from kernelpkgs.txt...disabled until I can figure out why it sucks
731 # try:
732 # kernpkgs = open("/usr/livecd/kernelpkgs.txt", "r")
733 # pkgs = ""
734 # for line in kernpkgs.readlines():
735 # pkgs += line.strip() + " "
736 # kernpkgs.close()
737 # except:
738 # raise GLIException("EmergeColdplugError", 'fatal','build_kernel', "Could not read kernelpkgs.txt")
739 # exitstatus = self._emerge(pkgs)
740 # if not GLIUtility.exitsuccess(exitstatus):
741 # raise GLIException("EmergeExtraKernelModulesError", 'fatal','build_kernel', "Could not emerge extra kernel packages")
742 # self._logger.log("Extra kernel packages emerged.")
743
744 # normal case
745 else:
746 exitstatus = self._portage.emerge(kernel_pkg, self._install_profile.get_grp_install())
747 # if not GLIUtility.exitsuccess(exitstatus):
748 # raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not retrieve kernel sources!")
749 try:
750 os.stat(self._chroot_dir + "/usr/src/linux")
751 except:
752 kernels = os.listdir(self._chroot_dir+"/usr/src")
753 if self._debug: self._logger.log("DEBUG: no /usr/src/linux found. found kernels: "+kernels)
754 found_a_kernel = False
755 counter = 0
756 while not found_a_kernel:
757 if (len(kernels[counter]) > 6) and (kernels[counter][0:6]=="linux-"):
758 if self._debug: self._logger.log("DEBUG: found one. linking it. running: ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux in the chroot.")
759 exitstatus = GLIUtility.spawn("ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux",chroot=self._chroot_dir)
760 if not GLIUtility.exitsuccess(exitstatus):
761 raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not make a /usr/src/linux symlink")
762 found_a_kernel = True
763 else:
764 counter = counter + 1
765 self._logger.log("Kernel sources:"+kernel_pkg+" emerged and /usr/src/linux symlinked.")
766
767 ##
768 # Builds the kernel using genkernel or regularly if given a custom .config file in the profile
769 def build_kernel(self):
770 self._logger.mark()
771 self._logger.log("Starting build_kernel")
772
773 build_mode = self._install_profile.get_kernel_build_method()
774
775 # No building necessary if using the LiveCD's kernel/initrd
776 # or using the 'none' kernel bypass
777 if self._install_profile.get_kernel_source_pkg() in ["livecd-kernel","none"]:
778 if self._debug: self._logger.log("DEBUG: using "+self._install_profile.get_kernel_source_pkg()+ " so skipping this function.")
779 return
780 # Get the uri to the kernel config
781 kernel_config_uri = self._install_profile.get_kernel_config_uri()
782
783 # is there an easier way to do this?
784 if self._debug: self._logger.log("DEBUG: running command: awk '/^PATCHLEVEL/{print $3}' /usr/src/linux/Makefile in chroot.")
785 ret, kernel_major = GLIUtility.spawn("awk '/^PATCHLEVEL/{print $3}' /usr/src/linux/Makefile",chroot=self._chroot_dir,return_output=True)
786 # 6 == 2.6 kernel, 4 == 2.4 kernel
787 kernel_major = int(kernel_major)
788 if self._debug: self._logger.log("DEBUG: kernel major version is: "+str(kernel_major))
789 #Copy the kernel .config to the proper location in /usr/src/linux
790 if kernel_config_uri != '':
791 try:
792 if self._debug: self._logger.log("DEBUG: grabbing kernel config from "+kernel_config_uri+" and putting it in "+self._chroot_dir + "/var/tmp/kernel_config")
793 GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/var/tmp/kernel_config")
794 except:
795 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not copy kernel config!")
796
797 # the && stuff is important so that we can catch any errors.
798 kernel_compile_script = "#!/bin/bash\n"
799 kernel_compile_script += "cp /var/tmp/kernel_config /usr/src/linux/.config && "
800 kernel_compile_script += "cd /usr/src/linux && "
801 # required for 2.[01234] etc kernels
802 if kernel_major in [0,1,2,3,4]:
803 kernel_compile_script += " yes 'n' | make oldconfig && make symlinks && make dep"
804 # not strictly needed, but recommended by upstream
805 else: #elif kernel_major in [5,6]:
806 kernel_compile_script += "make prepare"
807
808 # bypass to install a kernel, but not compile it
809 if build_mode == "none":
810 return
811 # this mode is used to install kernel sources, and have then configured
812 # but not actually build the kernel. This is needed for netboot
813 # situations when you have packages that require kernel sources
814 # to build.
815 elif build_mode == "prepare-only":
816 if self._debug: self._logger.log("DEBUG: writing kernel script with contents: "+kernel_compile_script)
817 f = open(self._chroot_dir+"/var/tmp/kernel_script", 'w')
818 f.writelines(kernel_compile_script)
819 f.close()
820 #Build the kernel
821 if self._debug: self._logger.log("DEBUG: running: chmod u+x "+self._chroot_dir+"/var/tmp/kernel_script")
822 exitstatus1 = GLIUtility.spawn("chmod u+x "+self._chroot_dir+"/var/tmp/kernel_script")
823 if self._debug: self._logger.log("DEBUG: running: /var/tmp/kernel_script in chroot.")
824 exitstatus2 = GLIUtility.spawn("/var/tmp/kernel_script", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
825 if not GLIUtility.exitsuccess(exitstatus1):
826 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not handle prepare-only build! died on chmod.")
827 if not GLIUtility.exitsuccess(exitstatus2):
828 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not handle prepare-only build! died on running of kernel script.")
829 #i'm sure i'm forgetting something here.
830 #cleanup
831 exitstatus = GLIUtility.spawn("rm -f "+self._chroot_dir+"/var/tmp/kernel_script "+self._chroot_dir+"/var/tmp/kernel_config")
832 #it's not important if this fails.
833 self._logger.log("prepare-only build complete")
834 # Genkernel mode, including custom kernel_config. Initrd always on.
835 elif build_mode == "genkernel":
836 if self._debug: self._logger.log("DEBUG: build_kernel(): starting emerge genkernel")
837 exitstatus = self._portage.emerge("genkernel", self._install_profile.get_grp_install())
838 # if not GLIUtility.exitsuccess(exitstatus):
839 # raise GLIException("EmergeGenKernelError", 'fatal','build_kernel', "Could not emerge genkernel!")
840 self._logger.log("Genkernel emerged. Beginning kernel compile.")
841 # Null the genkernel_options
842 genkernel_options = ""
843
844 # If the uri for the kernel config is not null, then
845 if kernel_config_uri != "":
846 if self._debug: self._logger.log("DEBUG: build_kernel(): getting kernel config "+kernel_config_uri)
847 GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/var/tmp/kernel_config")
848 genkernel_options = genkernel_options + " --kernel-config=/var/tmp/kernel_config"
849
850 # Decide whether to use bootsplash or not
851 if self._install_profile.get_kernel_bootsplash():
852 genkernel_options = genkernel_options + " --gensplash"
853 else:
854 genkernel_options = genkernel_options + " --no-gensplash"
855 # Run genkernel in chroot
856 #print "genkernel all " + genkernel_options
857 self.notify_frontend("progress", (0, "Compiling kernel. Please be patient!"))
858 if self._debug: self._logger.log("DEBUG: build_kernel(): running: genkernel all " + genkernel_options + " in chroot.")
859 exitstatus = GLIUtility.spawn("genkernel all " + genkernel_options, chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
860 if not GLIUtility.exitsuccess(exitstatus):
861 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build kernel!")
862
863 # exitstatus = self._emerge("hotplug")
864 # if not GLIUtility.exitsuccess(exitstatus):
865 # raise GLIException("EmergeHotplugError", 'fatal','build_kernel', "Could not emerge hotplug!")
866 # self._logger.log("Hotplug emerged.")
867 # exitstatus = self._portage.emerge("coldplug", self._install_profile.get_grp_install())
868 # if not GLIUtility.exitsuccess(exitstatus):
869 # raise GLIException("EmergeColdplugError", 'fatal','build_kernel', "Could not emerge coldplug!")
870 self._logger.log("Coldplug emerged. Now they should be added to the default runlevel.")
871
872 # self._add_to_runlevel("hotplug")
873 # self._add_to_runlevel("coldplug", runlevel="boot")
874
875 if self._install_profile.get_kernel_bootsplash():
876 self._logger.log("Bootsplash enabled...emerging necessary packages")
877 self._portage.emerge(["splashutils", "splash-themes-livecd"], self._install_profile.get_grp_install())
878
879 self._logger.log("Genkernel complete.")
880 elif build_mode == "custom": #CUSTOM CONFIG
881
882 kernel_compile_script += " && make && make modules && make modules_install"
883
884 #Ok now that it's built, copy it to /boot/kernel-* for bootloader code to find it
885 if self._architecture_name == "x86":
886 kernel_compile_script += " && cp /usr/src/linux/arch/i386/boot/bzImage /boot/kernel-custom\n"
887 elif self._architecture_name == "amd64":
888 kernel_compile_script += " && cp /usr/src/linux/arch/x86_64/boot/bzImage /boot/kernel-custom\n"
889 elif self._architecture_name == "ppc":
890 kernel_compile_script += " && cp /usr/src/linux/vmlinux /boot/kernel-custom\n"
891 if self._debug: self._logger.log("DEBUG: build_kernel(): writing custom kernel script: "+kernel_compile_script)
892 f = open(self._chroot_dir+"/var/tmp/kernel_script", 'w')
893 f.writelines(kernel_compile_script)
894 f.close()
895 #Build the kernel
896 if self._debug: self._logger.log("DEBUG: build_kernel(): running: chmod u+x "+self._chroot_dir+"/var/tmp/kernel_script")
897 exitstatus1 = GLIUtility.spawn("chmod u+x "+self._chroot_dir+"/var/tmp/kernel_script")
898 if self._debug: self._logger.log("DEBUG: build_kernel(): running: /var/tmp/kernel_script in chroot")
899 exitstatus2 = GLIUtility.spawn("/var/tmp/kernel_script", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
900 if not GLIUtility.exitsuccess(exitstatus1):
901 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build custom kernel! died on chmod.")
902 if not GLIUtility.exitsuccess(exitstatus2):
903 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build custom kernel! died on running of kernel script.")
904
905 #i'm sure i'm forgetting something here.
906 #cleanup
907 exitstatus = GLIUtility.spawn("rm -f "+self._chroot_dir+"/var/tmp/kernel_script "+self._chroot_dir+"/var/tmp/kernel_config")
908 #it's not important if this fails.
909
910 if self._install_profile.get_kernel_bootsplash():
911 self._logger.log("Bootsplash enabled...emerging necessary packages")
912 self._portage.emerge(["splashutils", "splash-themes-livecd"], self._install_profile.get_grp_install())
913
914 self._logger.log("Custom kernel complete")
915
916 ##
917 # Installs and starts up distccd if the user has it set, so that it will get used for the rest of the install
918 def install_distcc(self):
919 if self._install_profile.get_install_distcc():
920 if self._debug: self._logger.log("DEBUG: install_distcc(): we ARE installing distcc")
921 if self._debug: self._logger.log("DEBUG: install_distcc(): running: USE='-*' emerge --nodeps sys-devel/distcc in chroot.")
922 exitstatus = GLIUtility.spawn("USE='-*' emerge --nodeps sys-devel/distcc", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
923 if not GLIUtility.exitsuccess(exitstatus):
924 self._logger.log("ERROR! : Could not emerge distcc!")
925 else:
926 self._logger.log("distcc emerged.")
927
928 ##
929 # Installs mail MTA. Does not put into runlevel, as this is not simple with MTAs.
930 def install_mta(self):
931 # Get MTA info
932 mta_pkg = self._install_profile.get_mta_pkg()
933 if mta_pkg:
934 # Emerge MTA
935 if self._debug: self._logger.log("DEBUG: install_mta(): installing mta: "+mta_pkg)
936 exitstatus = self._portage.emerge(mta_pkg, self._install_profile.get_grp_install())
937 # if not GLIUtility.exitsuccess(exitstatus):
938 # raise GLIException("MTAError", 'fatal','install_mta', "Could not emerge " + mta_pkg + "!")
939 self._logger.log("MTA installed: "+mta_pkg)
940 else:
941 installpackages = self._install_profile.get_install_packages()
942 if installpackages:
943 for pkg in installpackages:
944 if pkg in ['esmtp', 'exim', 'msmtp', 'nbsmtp', 'nullmailer', 'sendmail', 'ssmtp', 'xmail']:
945 self._logger.log("Found an mta in the package list: "+pkg+". Installing early.")
946 exitstatus = self._portage.emerge(pkg, self._install_profile.get_grp_install())
947 self._logger.log("MTA installed.")
948 break # We only want to install one
949
950 ##
951 # Installs and sets up logging daemon on the new system. adds to runlevel too.
952 def install_logging_daemon(self):
953 # Get loggin daemon info
954 logging_daemon_pkg = self._install_profile.get_logging_daemon_pkg()
955 if logging_daemon_pkg:
956 # Emerge Logging Daemon
957 if self._debug: self._logger.log("DEBUG: install_logging_daemon: emerging "+logging_daemon_pkg)
958 exitstatus = self._portage.emerge(logging_daemon_pkg, self._install_profile.get_grp_install())
959 # if not GLIUtility.exitsuccess(exitstatus):
960 # raise GLIException("LoggingDaemonError", 'fatal','install_logging_daemon', "Could not emerge " + logging_daemon_pkg + "!")
961
962 # Add Logging Daemon to default runlevel
963 # After we find the name of it's initscript
964 # This current code is a hack, and should be better.
965 initscript = logging_daemon_pkg[(logging_daemon_pkg.find('/')+1):]
966 if self._debug: self._logger.log("DEBUG: install_logging_daemon: adding "+initscript+" to runlevel")
967 self._add_to_runlevel(initscript)
968 self._logger.log("Logging daemon installed: "+logging_daemon_pkg)
969 ##
970 # Installs and sets up cron package.
971 def install_cron_daemon(self):
972 # Get cron daemon info
973 cron_daemon_pkg = self._install_profile.get_cron_daemon_pkg()
974 if cron_daemon_pkg:
975 if cron_daemon_pkg in ("none", "None"):
976 self._logger.log("Skipping installation of cron daemon")
977 else:
978 # Emerge Cron Daemon
979 if self._debug: self._logger.log("DEBUG: install_cron_daemon: emerging "+cron_daemon_pkg)
980 exitstatus = self._portage.emerge(cron_daemon_pkg, self._install_profile.get_grp_install())
981 # if not GLIUtility.exitsuccess(exitstatus):
982 # raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Could not emerge " + cron_daemon_pkg + "!")
983
984 # Add Cron Daemon to default runlevel
985 # After we find the name of it's initscript
986 # This current code is a hack, and should be better.
987 initscript = cron_daemon_pkg[(cron_daemon_pkg.find('/')+1):]
988 if self._debug: self._logger.log("DEBUG: install_cron_daemon: adding "+initscript+" to runlevel")
989 self._add_to_runlevel(initscript)
990
991 # If the Cron Daemon is not vixie-cron, run crontab
992 if cron_daemon_pkg != "vixie-cron":
993 if self._debug: self._logger.log("DEBUG: install_cron_daemon: running: crontab /etc/crontab in chroot.")
994 exitstatus = GLIUtility.spawn("crontab /etc/crontab", chroot=self._chroot_dir, display_on_tty8=True)
995 if not GLIUtility.exitsuccess(exitstatus):
996 raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Failure making crontab!")
997 self._logger.log("Cron daemon installed and configured: "+cron_daemon_pkg)
998
999 ##
1000 # This will parse the partitions looking for types that require fstools and emerge them if found.
1001 def install_filesystem_tools(self):
1002 "Installs and sets up fstools"
1003 # Get the list of file system tools to be installed
1004 mounts = self._install_profile.get_mounts()
1005 # don't use an array, use a set instead
1006 filesystem_types = []
1007 for mount in mounts:
1008 partition_type = mount['type'].lower()
1009 if mount['mountpoint'] and partition_type not in filesystem_types:
1010 filesystem_types.append(partition_type)
1011
1012 package_list = []
1013 for filesystem in filesystem_types:
1014 if filesystem == 'xfs':
1015 package_list.append('sys-fs/xfsprogs')
1016 elif filesystem == 'reiserfs':
1017 package_list.append('sys-fs/reiserfsprogs')
1018 elif filesystem == 'jfs':
1019 package_list.append('sys-fs/jfsutils')
1020 elif filesystem == 'ntfs':
1021 package_list.append('sys-fs/ntfsprogs')
1022 elif filesystem in ['fat','vfat', 'msdos', 'umsdos']:
1023 package_list.append('sys-fs/dosfstools')
1024 elif filesystem == 'hfs':
1025 # should check with the PPC guys on this
1026 package_list.append('sys-fs/hfsutils')
1027 package_list.append('sys-fs/hfsplusutils')
1028 #else:
1029 # should be code here for every FS type!
1030 failed_list = []
1031 for package in package_list:
1032 if self._debug: self._logger.log("DEBUG: install_filesystem_tools(): emerging "+package)
1033 exitstatus = self._portage.emerge(package, self._install_profile.get_grp_install())
1034 # if not GLIUtility.exitsuccess(exitstatus):
1035 # self._logger.log("ERROR! : Could not emerge "+package+"!")
1036 # failed_list.append(package)
1037 # else:
1038 self._logger.log("FileSystemTool "+package+" was emerged successfully.")
1039 # error checking is important!
1040 if len(failed_list) > 0:
1041 raise GLIException("InstallFileSystemToolsError", 'warning', 'install_filesystem_tools', "Could not emerge " + failed_list + "!")
1042
1043
1044 ##
1045 # Installs and sets up pcmcia-cs if selected in the profile IS THIS USED AT ALL????
1046 def install_pcmcia_cs(self):
1047 if self._debug: self._logger.log("DEBUG: install_pcmcia_cs(): emerging pcmcia-cs")
1048 exitstatus = self._portage.emerge("pcmcia-cs", self._install_profile.get_grp_install())
1049 # if not GLIUtility.exitsuccess(exitstatus):
1050 # self._logger.log("ERROR! : Could not emerge pcmcia-cs!")
1051
1052 # Add pcmcia-cs to the default runlevel
1053 # else:
1054 self._add_to_runlevel('pcmcia')
1055 self._logger.log("PCMCIA_CS emerged and configured.")
1056
1057
1058 ##
1059 # Sets up the network for the first boot
1060 def setup_network_post(self):
1061 if self._debug: self._logger.log("DEBUG: setup_network_post(): starting network configuration")
1062 # Get hostname, domainname and nisdomainname
1063 hostname = self._install_profile.get_hostname()
1064 domainname = self._install_profile.get_domainname()
1065 nisdomainname = self._install_profile.get_nisdomainname()
1066
1067 # Write the hostname to the hostname file
1068 #open(self._chroot_dir + "/etc/hostname", "w").write(hostname + "\n")
1069 self._edit_config(self._chroot_dir + "/etc/conf.d/hostname", {"HOSTNAME": hostname})
1070
1071 # Write the domainname to the nisdomainname file
1072 if domainname:
1073 #open(self._chroot_dir + "/etc/dnsdomainname", "w").write(domainname + "\n")
1074 self._edit_config(self._chroot_dir + "/etc/conf.d/domainname", {"DNSDOMAIN": domainname})
1075 self._add_to_runlevel("domainname")
1076
1077 # Write the nisdomainname to the nisdomainname file
1078 if nisdomainname:
1079 #open(self._chroot_dir + "/etc/nisdomainname", "w").write(nisdomainname + "\n")
1080 self._edit_config(self._chroot_dir + "/etc/conf.d/domainname", {"NISDOMAIN": nisdomainname})
1081 self._add_to_runlevel("domainname")
1082
1083 #
1084 # EDIT THE /ETC/HOSTS FILE
1085 #
1086
1087 # The address we are editing is 127.0.0.1
1088 hosts_ip = "127.0.0.1"
1089
1090 # If the hostname is localhost
1091 if hostname == "localhost":
1092 # If a domainname is set
1093 if domainname:
1094 hosts_line = hostname + "." + domainname + "\t" + hostname
1095 else:
1096 hosts_line = hostname
1097 # If the hostname is not localhost
1098 else:
1099 # If a domainname is set
1100 if domainname:
1101 hosts_line = hostname + "." + domainname + "\t" + hostname + "\tlocalhost"
1102 else:
1103 hosts_line = "localhost\t" + hostname
1104
1105 # Write to file
1106 self._edit_config(self._chroot_dir + "/etc/hosts", {hosts_ip: hosts_line}, delimeter='\t', quotes_around_value=False)
1107
1108 #
1109 # SET DEFAULT GATEWAY
1110 #
1111
1112 # Get default gateway
1113 default_gateway = self._install_profile.get_default_gateway()
1114
1115 # If the default gateway exists, add it
1116 if default_gateway:
1117 default_gateway_string = '( "default via ' + default_gateway[1] + '" )'
1118 if self._debug: self._logger.log("DEBUG: setup_network_post(): found gateway. adding to confing. "+default_gateway_string)
1119 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"routes_"+default_gateway[0]: default_gateway_string}, quotes_around_value=False)
1120
1121 #
1122 # SET RESOLV INFO
1123 #
1124
1125 # Get dns servers
1126 dns_servers = self._install_profile.get_dns_servers()
1127
1128 # Clear the list
1129 resolv_output = []
1130
1131 # If dns servers are set
1132 if dns_servers:
1133
1134
1135 # Parse each dns server
1136 for dns_server in dns_servers:
1137 # Add the server to the output
1138 resolv_output.append("nameserver " + dns_server +"\n")
1139
1140 # If the domainname is set, then also output it
1141 if domainname:
1142 resolv_output.append("search " + domainname + "\n")
1143
1144 # Output to file
1145 if self._debug: self._logger.log("DEBUG: setup_network_post(): writing resolv.conf with contents: " + str(resolv_output))
1146 resolve_conf = open(self._chroot_dir + "/etc/resolv.conf", "w")
1147 resolve_conf.writelines(resolv_output)
1148 resolve_conf.close()
1149
1150 #
1151 # PARSE INTERFACES
1152 #
1153
1154 # Fetch interfaces
1155 interfaces = self._install_profile.get_network_interfaces()
1156 emerge_dhcp = False
1157 # Parse each interface
1158 for interface in interfaces.keys():
1159 if self._debug: self._logger.log("DEBUG: setup_network_post(): configuring interface: "+ interface)
1160 # Set what kind of interface it is
1161 interface_type = interface[:3]
1162
1163 # Check to see if there is a startup script for this interface, if there isn't link to the proper script
1164 try:
1165 os.stat(self._chroot_dir + "/etc/init.d/net." + interface)
1166 except:
1167 if self._debug: self._logger.log("DEBUG: setup_network_post(): /etc/init.d/net." + interface + " didn't exist, symlinking it.")
1168 os.symlink("net." + interface_type + "0", self._chroot_dir + "/etc/init.d/net." + interface)
1169
1170 # If we are going to load the network at boot...
1171 #if interfaces[interface][2]: #THIS FEATURE NO LONGER EXISTS
1172
1173 # Add it to the default runlevel
1174 if self._debug: self._logger.log("DEBUG: setup_network_post(): adding net."+interface+" to runlevel.")
1175 self._add_to_runlevel("net."+interface) # moved a bit <-- for indentation
1176
1177 #
1178 # ETHERNET
1179 #
1180 if interface_type == "eth":
1181
1182 #
1183 # STATIC IP
1184 #
1185 # If the post-install device info is not None, then it is a static ip addy
1186 if interfaces[interface][0] != "dhcp":
1187 ip = interfaces[interface][0]
1188 broadcast = interfaces[interface][1]
1189 netmask = interfaces[interface][2]
1190 # aliases = interfaces[interface][1][3]
1191 # alias_ips = []
1192 # alias_broadcasts = []
1193 # alias_netmasks = []
1194
1195 # Write the static ip config to /etc/conf.d/net
1196 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: ip + " broadcast " + broadcast + " netmask " + netmask})
1197
1198 # If aliases are set
1199 # if aliases:
1200
1201 # Parse aliases to format alias info
1202 # for alias in aliases:
1203 # alias_ips.append(alias[0])
1204 # alias_broadcasts.append(alias[1])
1205 # alias_netmasks.append(allias[2])
1206
1207 # Once the alias info has been gathered, then write it out
1208 # Alias ips first
1209 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "alias_" + interface, string.join(alias_ips))
1210 # Alias broadcasts next
1211 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "broadcast_" + interface, string.join(alias_broadcasts))
1212 # Alias netmasks last
1213 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "netmask_" + interface, string.join(alias_netmasks))
1214
1215 #
1216 # DHCP IP
1217 #
1218 else:
1219 dhcpcd_options = interfaces[interface][1]
1220 if not dhcpcd_options:
1221 dhcpcd_options = ""
1222 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: "dhcp", "dhcpcd_" + interface: dhcpcd_options})
1223 emerge_dhcp = True
1224 if emerge_dhcp:
1225 if self._debug: self._logger.log("DEBUG: setup_network_post(): emerging dhcpcd.")
1226 exitstatus = self._portage.emerge("dhcpcd", self._install_profile.get_grp_install())
1227 # if not GLIUtility.exitsuccess(exitstatus):
1228 # self._logger.log("ERROR! : Could not emerge dhcpcd!")
1229 # else:
1230 self._logger.log("dhcpcd emerged.")
1231
1232
1233 ##
1234 # This is a stub function to be done by the individual arch. I don't think it's even needed here.
1235 # but it's nice having it just incase.
1236 def install_bootloader(self):
1237 "THIS FUNCTION MUST BE DONE BY THE INDIVIDUAL ARCH"
1238 pass
1239
1240 ##
1241 # Sets up the new users for the system
1242 def set_users(self):
1243 # Loop for each user
1244 for user in self._install_profile.get_users():
1245
1246 # Get values from the tuple
1247 username = user[0]
1248 password_hash = user[1]
1249 groups = user[2]
1250 shell = user[3]
1251 home_dir = user[4]
1252 uid = user[5]
1253 comment = user[6]
1254
1255 options = [ "-m", "-p '" + password_hash + "'" ]
1256
1257 # If the groups are specified
1258 if groups:
1259
1260 # If just one group is listed as a string, make it a list
1261 if groups == str:
1262 groups = [ groups ]
1263
1264 # If only 1 group is listed
1265 if len(groups) == 1:
1266 options.append("-G " + groups[0])
1267
1268 # If there is more than one group
1269 elif len(groups) > 1:
1270 options.append('-G "' + string.join(groups, ",") + '"')
1271
1272 # Attempt to add the group (will return success when group exists)
1273 for group in groups:
1274 if not group: continue
1275 # Add the user
1276 if self._debug: self._logger.log("DEBUG: set_users(): adding user to groups with (in chroot): "+'groupadd -f ' + group)
1277 exitstatus = GLIUtility.spawn('groupadd -f ' + group, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True, display_on_tty8=True)
1278 if not GLIUtility.exitsuccess(exitstatus):
1279 self._logger.log("ERROR! : Failure to add group " + group+" and it wasn't that the group already exists!")
1280
1281
1282 # If a shell is specified
1283 if shell:
1284 options.append("-s " + shell)
1285
1286 # If a home dir is specified
1287 if home_dir:
1288 options.append("-d " + home_dir)
1289
1290 # If a UID is specified
1291 if uid:
1292 options.append("-u " + str(uid))
1293
1294 # If a comment is specified
1295 if comment:
1296 options.append('-c "' + comment + '"')
1297
1298 # Add the user
1299 if self._debug: self._logger.log("DEBUG: set_users(): adding user with (in chroot): "+'useradd ' + string.join(options) + ' ' + username)
1300 exitstatus = GLIUtility.spawn('useradd ' + string.join(options) + ' ' + username, chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True, display_on_tty8=True)
1301 if not GLIUtility.exitsuccess(exitstatus):
1302 self._logger.log("ERROR! : Failure to add user " + username)
1303 # raise GLIException("AddUserError", 'warning', 'set_users', "Failure to add user " + username)
1304 else:
1305 self._logger.log("User " + username + " was added.")
1306
1307 ##
1308 # Installs a list of packages specified in the profile. Will install any extra software!
1309 # In the future this function will lead to better things. It may even wipe your ass for you.
1310 def install_packages(self):
1311 installpackages = self._install_profile.get_install_packages()
1312 if installpackages:
1313 # pkglist = self._portage.get_deps(" ".join(installpackages))
1314 # if self._debug: self._logger.log("install_packages(): pkglist is " + str(pkglist))
1315 # for i, pkg in enumerate(pkglist):
1316 # if self._debug: self._logger.log("install_packages(): processing package " + pkg)
1317 # self.notify_frontend("progress", (float(i) / len(pkglist), "Emerging " + pkg + " (" + str(i) + "/" + str(len(pkglist)) + ")"))
1318 # if not self._portage.get_best_version_vdb("=" + pkg):
1319 # status = self._emerge("=" + pkg)
1320 # if not GLIUtility.exitsuccess(status):
1321 # raise GLIException("ExtraPackagesError", "fatal", "install_packages", "Could not emerge " + pkg + "!")
1322 # else:
1323 # try:
1324 # self._portage.copy_pkg_to_chroot(pkg)
1325 # except:
1326 # raise GLIException("ExtraPackagesError", "fatal", "install_packages", "Could not emerge " + pkg + "!")
1327 self._portage.emerge(installpackages, self._install_profile.get_grp_install())
1328
1329 if GLIUtility.is_file(self._chroot_dir + "/etc/X11"):
1330 # Copy the xorg.conf from the LiveCD if they installed xorg-x11
1331 exitstatus = GLIUtility.spawn("cp /etc/X11/xorg.conf " + self._chroot_dir + "/etc/X11/xorg.conf")
1332 if not GLIUtility.exitsuccess(exitstatus):
1333 self._logger.log("Could NOT copy the xorg configuration from the livecd to the new system!")
1334 else:
1335 self._logger.log("xorg.conf copied to new system. X should be ready to roll!")
1336 if GLIUtility.is_file(self._chroot_dir + "/etc/X11/gdm/gdm.conf"):
1337 GLIUtility.spawn("cp -f /etc/X11/gdm/gdm.conf.old " + self._chroot_dir + "/etc/X11/gdm/gdm.conf")
1338 if GLIUtility.is_file(self._chroot_dir + "/etc/X11/gdm/custom.conf"):
1339 GLIUtility.spawn("cp -f /etc/X11/gdm/custom.conf.old " + self._chroot_dir + "/etc/X11/gdm/custom.conf")
1340
1341 ##
1342 # Will set the list of services to runlevel default. This is a temporary solution!
1343 def set_services(self):
1344 services = self._install_profile.get_services()
1345 for service in services:
1346 if service:
1347 runlevel = "default"
1348 if "|" in service:
1349 service, runlevel = service.split("|", 1)
1350 self._add_to_runlevel(service, runlevel)
1351
1352 ##
1353 # Will execute any arbritraially defined script here for post-install customization.
1354 def run_post_install_script(self):
1355 if self._install_profile.get_post_install_script_uri():
1356 try:
1357 if self._debug: self._logger.log("DEBUG: run_post_install_script(): getting script: "+self._install_profile.get_post_install_script_uri())
1358 GLIUtility.get_uri(self._install_profile.get_post_install_script_uri(), self._chroot_dir + "/var/tmp/post-install")
1359 if self._debug: self._logger.log("DEBUG: run_post_install_script(): running: chmod a+x /var/tmp/post-install && /var/tmp/post-install in chroot")
1360 GLIUtility.spawn("chmod a+x /var/tmp/post-install && /var/tmp/post-install", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile, append_log=True)
1361 except:
1362 raise GLIException("RunPostInstallScriptError", 'fatal', 'run_post_install_script', "Failed to retrieve and/or execute post-install script")
1363
1364
1365 ##
1366 # This function will handle the various cleanup tasks as well as unmounting the filesystems for reboot.
1367 def finishing_cleanup(self):
1368 #These are temporary until I come up with a nicer idea.
1369 #get rid of the compile_output file so the symlink doesn't get screwed up.
1370
1371 #we copy the log over to the new system.
1372 install_logfile = LOGFILE
1373 try:
1374 if self._debug: self._logger.log("DEBUG: finishing_cleanup(): copying logfile over to new system's root.")
1375 shutil.copy(install_logfile, self._chroot_dir + install_logfile)
1376 except:
1377 if self._debug: self._logger.log("DEBUG: finishing_cleanup(): ERROR! could not copy logfile over to /root.")
1378 #Now we're done logging as far as the new system is concerned.
1379 GLIUtility.spawn("cp /tmp/installprofile.xml " + self._chroot_dir + "/root/installprofile.xml")
1380
1381
1382 #Unmount mounted fileystems in preparation for reboot
1383 #mounts = GLIUtility.spawn(r"mount | sed -e 's:^.\+ on \(.\+\) type .\+$:\1:' | grep -e '^" + self._chroot_dir + "' | sort -r", return_output=True)[1].split("\n")
1384 if self._debug: self._logger.log("DEBUG: mounted_devices is %s" % str(self._mounted_devices))
1385 mounted_devices = self._mounted_devices
1386 mounted_devices.sort()
1387 mounted_devices.reverse()
1388 for mount in mounted_devices:
1389 if self._debug: self._logger.log("DEBUG: finishing_cleanup(): running: umount -l " + mount)
1390 ret = GLIUtility.spawn("umount -l " + self._chroot_dir + mount)
1391 if not GLIUtility.exitsuccess(ret):
1392 self._logger.log("ERROR! : Could not unmount mountpoint %s" % mount)
1393
1394 # now turn off all swap as well.
1395 # we need to find the swap devices
1396 for swap_device in self._swap_devices:
1397 if self._debug: self._logger.log("DEBUG: finishing_cleanup(): running: swapoff "+swap_device)
1398 ret = GLIUtility.spawn("swapoff "+swap_device)
1399 if not GLIUtility.exitsuccess(ret):
1400 self._logger.log("ERROR! : Could not deactivate swap ("+swap_device+")!")
1401
1402 GLIUtility.spawn("rm /tmp/compile_output.log && rm " + install_logfile)
1403
1404
1405
1406 ##
1407 # This function should only be called in the event of an install failure. It performs
1408 # general cleanup to prepare the system for another installer run.
1409 def install_failed_cleanup(self):
1410 steps = len(self._mounted_devices) + len(self._swap_devices) + 2
1411
1412 if self._debug: self._logger.log("DEBUG: install_failed_cleanup(): running: mv /tmp/compile_output.log /tmp/compile_output.log.failed")
1413 self.notify_frontend("progress", (float(1) / (steps), "Moving compile output logfile"))
1414 GLIUtility.spawn("cp " + self._compile_logfile + " " + self._compile_logfile + ".failed && rm " + self._compile_logfile)
1415 self.notify_frontend("progress", (float(2) / (steps), "Moving install logfile"))
1416 GLIUtility.spawn("mv " + LOGFILE + " " + LOGFILE + ".failed")
1417 cur_step = 2
1418
1419 if self._debug: self._logger.log("DEBUG: install_failed_cleanup(): gathering mounts to unmount")
1420 #mounts = GLIUtility.spawn(r"mount | sed -e 's:^.\+ on \(.\+\) type .\+$:\1:' | grep -e '^" + self._chroot_dir + "' | sort -r", return_output=True)[1].split("\n")
1421 if self._debug: self._logger.log("DEBUG: mounted_devices is %s" % str(self._mounted_devices))
1422 mounted_devices = self._mounted_devices
1423 mounted_devices.sort()
1424 mounted_devices.reverse()
1425 for mount in mounted_devices:
1426 cur_step += 1
1427 self.notify_frontend("progress", (float(cur_step) / (steps), "Unmounting " + mount))
1428 if self._debug: self._logger.log("DEBUG: install_failed_cleanup(): running: umount -l " + mount)
1429 ret = GLIUtility.spawn("umount -l " + self._chroot_dir + mount)
1430 if not GLIUtility.exitsuccess(ret):
1431 self._logger.log("ERROR! : Could not unmount mountpoint %s" % mount)
1432
1433 # now turn off all swap as well.
1434 # we need to find the swap devices
1435 for swap_device in self._swap_devices:
1436 cur_step += 1
1437 self.notify_frontend("progress", (float(cur_step) / (steps), "Deactivating swap on " + swap_device))
1438 if self._debug: self._logger.log("DEBUG: install_failed_cleanup(): running: swapoff "+swap_device)
1439 ret = GLIUtility.spawn("swapoff "+swap_device)
1440 if not GLIUtility.exitsuccess(ret):
1441 self._logger.log("ERROR! : Could not deactivate swap ("+swap_device+")!")

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20