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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 874 - (hide annotations) (download) (as text)
Sat Sep 3 05:14:17 2005 UTC (13 years, 1 month ago) by agaffney
Original Path: trunk/src/GLIArchitectureTemplate.py
File MIME type: text/x-python
File size: 60640 byte(s)
install_packages() sends progress update notifications
sub-progress bar in gtkfe

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20