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

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1183 - (show annotations) (download) (as text)
Fri Dec 23 22:39:29 2005 UTC (8 years, 11 months ago) by agaffney
File MIME type: text/x-python
File size: 77575 byte(s)
flipped around a few function args

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20