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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 686 - (show annotations) (download) (as text)
Wed Jun 15 09:15:03 2005 UTC (13 years, 4 months ago) by robbat2
Original Path: trunk/src/GLIArchitectureTemplate.py
File MIME type: text/x-python
File size: 50808 byte(s)
2.4 support (pull version data from /usr/src/linux/Makefile), incl. 'make dep'
call for custom compile. build_mode support for prepare-only and none types
completed. custom compile function chains shell functions in spawned script, to
allow for catching all errors.

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20