/[gli]/trunk/src/GLIArchitectureTemplate.py
Gentoo

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1214 - (show annotations) (download) (as text)
Tue Jan 3 02:31:38 2006 UTC (12 years, 1 month ago) by agaffney
File MIME type: text/x-python
File size: 70930 byte(s)
call copy_pkg_to_chroot() directly for livecd-kernel

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20