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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 436 - (hide annotations) (download) (as text)
Sun Mar 27 19:07:09 2005 UTC (13 years, 8 months ago) by agaffney
Original Path: trunk/src/GLIArchitectureTemplate.py
File MIME type: text/x-python
File size: 37347 byte(s)
whitespace cleanup

1 samyron 79 """
2     Gentoo Linux Installer
3    
4 agaffney 436 $Id: GLIArchitectureTemplate.py,v 1.76 2005/03/27 19:07:09 agaffney Exp $
5 samyron 79 Copyright 2004 Gentoo Technologies Inc.
6    
7    
8     The ArchitectureTemplate is largely meant to be an abstract class and an
9     interface (yes, it is both at the same time!). The purpose of this is to create
10     subclasses that populate all the methods with working methods for that architecture.
11     The only definitions that are filled in here are architecture independent.
12    
13     """
14    
15 codeman 341 import GLIUtility, GLILogger, os, string, sys, shutil, re
16 agaffney 126 from GLIException import *
17 samyron 79
18     class ArchitectureTemplate:
19 agaffney 108 def __init__(self,configuration=None, install_profile=None, client_controller=None):
20 codeman 200 self._client_configuration = configuration
21 samyron 79 self._install_profile = install_profile
22 agaffney 108 self._cc = client_controller
23 samyron 79
24 samyron 102 # This will get used a lot, so it's probably
25     # better to store it in a variable than to call
26     # this method 100000 times.
27 codeman 200 self._chroot_dir = self._client_configuration.get_root_mount_point()
28 codeman 314 self._logger = GLILogger.Logger(self._client_configuration.get_log_file())
29 agaffney 384 self._compile_logfile = "/tmp/compile_output.log"
30 samyron 102
31 samyron 79 # These must be filled in by the subclass. _steps is a list of
32     # functions, that will carry out the installation. They must be
33     # in order.
34     #
35     # For example, self._steps might be: [preinstall, stage1, stage2, stage3, postinstall],
36     # where each entry is a function (with no arguments) that carries out the desired actions.
37     # Of course, steps will be different depending on the install_profile
38    
39     self._architecture_name = "generic"
40 agaffney 136 self._install_steps = [
41 agaffney 266 (self.partition, "Partition"),
42 agaffney 136 (self.mount_local_partitions, "Mount local partitions"),
43     (self.mount_network_shares, "Mount network (NFS) shares"),
44     (self.unpack_stage_tarball, "Unpack stage tarball"),
45     (self.configure_make_conf, "Configure /etc/make.conf"),
46 codeman 345 (self.prepare_chroot, "Preparing chroot"),
47 agaffney 436 (self.install_portage_tree, "Portage tree voodoo"),
48 agaffney 136 (self.stage1, "Performing bootstrap"),
49     (self.stage2, "Performing 'emerge system'"),
50 codeman 248 (self.set_root_password, "Set the root password"),
51 agaffney 436 (self.set_timezone, "Setting timezone"),
52 agaffney 136 (self.emerge_kernel_sources, "Emerge kernel sources"),
53     (self.build_kernel, "Building kernel"),
54     (self.install_logging_daemon, "Logger"),
55     (self.install_cron_daemon, "Cron daemon"),
56     (self.install_filesystem_tools, "Installing filesystem tools"),
57     (self.setup_network_post, "Configuring post-install networking"),
58     (self.install_bootloader, "Configuring and installing bootloader"),
59     (self.update_config_files, "Updating config files"),
60 codeman 223 (self.configure_rc_conf, "Updating /etc/rc.conf"),
61 agaffney 436 (self.set_services, "Setting up services for startup"),
62     (self.set_users, "Add additional users."),
63     (self.install_packages, "Installing additional packages."),
64     (self.finishing_cleanup, "Cleanup and unmounting local filesystems.")
65 agaffney 136 ]
66 codeman 200
67 samyron 79
68 agaffney 136 def get_install_steps(self):
69     return self._install_steps
70    
71 codeman 201 def notify_frontend(self, type, data):
72     self._cc.addNotification(type, data)
73    
74 samyron 79 # It is possible to override these methods in each Arch Template.
75     # It might be necessary to do so, if the arch needs something 'weird'.
76    
77 codeman 201 def _add_to_runlevel(self, script_name, runlevel="default"):
78     "Adds the script named 'script_name' to the runlevel 'runlevel' in the chroot environement"
79    
80     # Do it
81 agaffney 391 status = GLIUtility.spawn("rc-update add " + script_name + " " + runlevel, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile)
82 codeman 216 if not GLIUtility.exitsuccess(status):
83 codeman 314 raise GLIException("RunlevelAddError", 'fatal', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
84     self._logger.log("Added "+script_name+" to runlevel "+runlevel)
85 codeman 201
86 agaffney 322 def _quickpkg_deps(self, package):
87 agaffney 385 # These need to be changed to pull values from the make.conf stuff
88 agaffney 322 PKGDIR = "/usr/portage/packages"
89     PORTAGE_TMPDIR = "/var/tmp"
90 agaffney 415 make_conf = self._install_profile.get_make_conf()
91     if "PKGDIR" in make_conf: PKGDIR = make_conf['PKGDIR']
92     if "PORTAGE_TMPDIR" in make_conf: PORTAGE_TMPDIR = make_conf['PORTAGE_TMPDIR']
93     GLIUtility.spawn("mkdir -p " + self._chroot_dir + PKGDIR, logfile=self._compile_logfile)
94 agaffney 431 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTAGE_TMPDIR, logfile=self._compile_logfile)
95 agaffney 324 packages = [word for word in GLIUtility.spawn("emerge -p " + package, chroot=self._chroot_dir, return_output=True)[1].split() if "/" in word]
96     for pkg in packages:
97 agaffney 322 if not GLIUtility.is_file(self._chroot_dir + PKGDIR + "/All/" + pkg.split('/')[1] + ".tbz2"):
98 agaffney 401 ret = GLIUtility.spawn("env PKGDIR=" + self._chroot_dir + PKGDIR + " PORTAGE_TMPDIR=" + self._chroot_dir + PORTAGE_TMPDIR + " quickpkg =" + pkg)
99 agaffney 322 if ret:
100     # This package couldn't be quickpkg'd. This may be an error in the future
101     pass
102    
103 agaffney 385 def _get_packages_to_emerge(self, cmd):
104     # cmd = full command to run ('/usr/portage/scripts/bootstrap.sh --pretend' or 'emerge -p system')
105     return GLIUtility.spawn(cmd + r" | grep -e '\[ebuild' | sed -e 's:\[ebuild .\+ \] ::' -e 's: \[.\+\] ::' -e 's: +$::'", chroot=self._chroot_dir, return_output=True).split("\n")
106    
107 codeman 209 def _emerge(self, package, binary=False, binary_only=False):
108 codeman 314 #Error checking of this function is to be handled by the parent function.
109 agaffney 322 if self._install_profile.get_grp_install():
110     self._quickpkg_deps(package)
111 agaffney 391 return GLIUtility.spawn("emerge -k " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile)
112 codeman 201 else:
113 agaffney 322 if binary_only:
114 agaffney 391 return GLIUtility.spawn("emerge -K " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile)
115 agaffney 322 elif binary:
116 agaffney 391 return GLIUtility.spawn("emerge -k " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile)
117 agaffney 322 else:
118 agaffney 391 return GLIUtility.spawn("emerge " + package, display_on_tty8=True, chroot=self._chroot_dir, logfile=self._compile_logfile)
119 codeman 201
120 codeman 209 def _edit_config(self, filename, newvalues, delimeter='=', quotes_around_value=True):
121 codeman 201 """
122     filename = file to be editted
123     newvlaues = a dictionary of VARIABLE:VALUE pairs
124     """
125 codeman 209 if not GLIUtility.is_file(filename):
126     raise GLIException("NoSuchFileError", 'notice','_edit_config',filename + ' does not exist!')
127 codeman 201
128     f = open(filename)
129     file = f.readlines()
130     f.close()
131    
132     for key in newvalues.keys():
133     regexpr = '^\s*#?\s*' + key + '\s*' + delimeter + '.*$'
134     regexpr = re.compile(regexpr)
135    
136     for i in range(0, len(file)):
137     if regexpr.match(file[i]):
138     if not file[i][0] == '#':
139     file[i] = '#' + file[i]
140    
141     file.append('\n# Added by GLI\n')
142     if quotes_around_value:
143     file.append(key + delimeter + '"' + newvalues[key] + '"\n')
144     else:
145     file.append(key + delimeter + newvalues[key]+'\n')
146    
147     f = open(filename,'w')
148     f.writelines(file)
149     f.flush()
150     f.close()
151 codeman 314 self._logger.log("Edited Config file "+filename)
152 codeman 201
153 samyron 79 def stage1(self):
154     "Stage 1 install -- bootstraping"
155    
156     # If we are doing a stage 1 install, then bootstrap
157     if self._install_profile.get_install_stage() == 1:
158 codeman 314 self._logger.mark()
159     self._logger.log("Starting bootstrap.")
160 agaffney 385 pkgs = self._get_packages_to_emerge("/usr/portage/scripts/bootstrap.sh --pretend")
161 agaffney 391 exitstatus = GLIUtility.spawn("/usr/portage/scripts/bootstrap.sh", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile)
162 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
163 samyron 186 raise GLIException("Stage1Error", 'fatal','stage1', "Bootstrapping failed!")
164 codeman 314 self._logger.log("Bootstrap complete.")
165 agaffney 385
166 samyron 79 def stage2(self):
167     # If we are doing a stage 1 or 2 install, then emerge system
168     if self._install_profile.get_install_stage() in [ 1, 2 ]:
169 codeman 314 self._logger.mark()
170     self._logger.log("Starting emerge system.")
171 agaffney 385 pkgs = self._get_packages_to_emerge("emerge -p system")
172 codeman 201 exitstatus = self._emerge("system")
173 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
174 samyron 186 raise GLIException("Stage2Error", 'fatal','stage2', "Building the system failed!")
175 codeman 314 self._logger.log("Emerge system complete.")
176 agaffney 384
177 agaffney 133 def unpack_stage_tarball(self):
178     if not os.path.isdir(self._chroot_dir):
179     os.makedirs(self._chroot_dir)
180 codeman 215 GLIUtility.fetch_and_unpack_tarball(self._install_profile.get_stage_tarball_uri(), self._chroot_dir, temp_directory=self._chroot_dir, keep_permissions=True)
181 codeman 314 self._logger.log(self._install_profile.get_stage_tarball_uri()+" was unpacked.")
182 agaffney 384
183 agaffney 133 def prepare_chroot(self):
184 codeman 215 # Copy resolv.conf to new env
185     try:
186     shutil.copy("/etc/resolv.conf", self._chroot_dir + "/etc/resolv.conf")
187     except:
188     pass
189     ret = GLIUtility.spawn("mount -t proc none "+self._chroot_dir+"/proc")
190 samyron 79 if not GLIUtility.exitsuccess(ret):
191 codeman 215 raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /proc')
192 codeman 216 ret = GLIUtility.spawn("mount -o bind /dev " + self._chroot_dir + "/dev")
193     if not GLIUtility.exitsuccess(ret):
194     raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /dev')
195 agaffney 384 GLIUtility.spawn("mv " + self._compile_logfile + " " + self._chroot_dir + self._compile_logfile + " && ln -s " + self._chroot_dir + self._compile_logfile + " " + self._compile_logfile)
196 codeman 314 self._logger.log("Chroot environment ready.")
197 samyron 79 # Set USE flags here
198     # might want to rewrite/use _edit_config from the GLIInstallTemplate
199     # Then you should be done... at least with the preinstall.
200    
201 samyron 102 def install_packages(self):
202     "Will install any extra software!"
203 codeman 201
204 samyron 102 installpackages = self._install_profile.get_install_packages()
205     for package in installpackages:
206 codeman 201 status = self._emerge(package)
207     if not GLIUtility.exitsuccess(status):
208 codeman 318 self._logger.log("Could not emerge " + package + "!")
209     # raise GLIException("InstallPackagesError", 'warning', 'install_packages', "Could not emerge " + package + "!")
210     else:
211     self._logger.log("Emerged package: "+package)
212 samyron 102
213 codeman 361 def set_services(self):
214     "Will set the list of services to runlevel default. This is a temporary solution!"
215    
216     services = self._install_profile.get_services()
217     for service in services:
218     status = self._add_to_runlevel(service)
219 samyron 102
220     def mount_local_partitions(self):
221     "Mounts all partitions that are on the local machine"
222 codeman 213 #{ 1: { 'end': 1999871, 'format': False, 'mb': 0,
223     #'mountopts': '', 'mountpoint': '', 'start': 63, 'type': 'linux-swap'},
224     #2: { 'end': 240121727, 'format': False, 'mb': 0, 'mountopts': '',
225     #'mountpoint': '', 'start': 1999872, 'type': 'ext3'}}
226 codeman 216
227 codeman 213 parts = self._install_profile.get_partition_tables()
228 codeman 215 parts_to_mount = {}
229 codeman 213 for device in parts:
230     #in parts['/dev/hda']
231     for partition in parts[device]:
232 codeman 214 #print parts[device][partition]
233 codeman 213 mountpoint = parts[device][partition]['mountpoint']
234     mountopts = parts[device][partition]['mountopts']
235     minor = str(parts[device][partition]['minor'])
236     partition_type = parts[device][partition]['type']
237     if mountpoint:
238     if mountopts:
239     mountopts = "-o "+mountopts+" "
240     if partition_type:
241     partition_type = "-t "+partition_type+" "
242 codeman 215 parts_to_mount[mountpoint]= {0: mountopts, 1: partition_type, 2: minor}
243    
244 codeman 213 if partition_type == "linux-swap":
245     ret = GLIUtility.spawn("swapon "+device+minor)
246 agaffney 272 if not GLIUtility.exitsuccess(ret):
247 codeman 318 self._logger.log("ERROR! : Could not activate swap!")
248 codeman 314 # raise GLIException("MountError", 'warning','mount_local_partitions','Could not activate swap')
249 codeman 215 sorted_list = []
250     for key in parts_to_mount.keys(): sorted_list.append(key)
251     sorted_list.sort()
252    
253     for mountpoint in sorted_list:
254     mountopts = parts_to_mount[mountpoint][0]
255     partition_type = parts_to_mount[mountpoint][1]
256     minor = parts_to_mount[mountpoint][2]
257     if not GLIUtility.is_file(self._chroot_dir+mountpoint):
258     exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
259     if exitstatus != 0:
260     raise GLIException("MkdirError", 'fatal','mount_local_partitions', "Making the mount point failed!")
261 agaffney 391 ret = GLIUtility.spawn("mount "+partition_type+mountopts+device+minor+" "+self._chroot_dir+mountpoint, display_on_tty8=True, logfile=self._compile_logfile)
262 codeman 215 if not GLIUtility.exitsuccess(ret):
263 codeman 314 raise GLIException("MountError", 'fatal','mount_local_partitions','Could not mount a partition')
264     self._logger.log("Mounted mountpoint:"+mountpoint)
265 samyron 102 def mount_network_shares(self):
266     "Mounts all network shares to the local machine"
267 codeman 226 """
268     <agaffney> it'll be much easier than mount_local_partitions
269 codeman 248 <agaffney> make sure /etc/init.d/portmap is started
270     <agaffney> then mount each one: mount -t nfs -o <mountopts> <host>:<export> <mountpoint>
271 codeman 226 """
272     nfsmounts = self._install_profile.get_network_mounts()
273     for netmount in nfsmounts:
274 agaffney 266 if netmount['type'] == "NFS" or netmount['type'] == "nfs":
275     mountopts = netmount['mountopts']
276 codeman 226 if mountopts:
277     mountopts = "-o "+mountopts
278 agaffney 266 host = netmount['host']
279     export = netmount['export']
280     mountpoint = netmount['mountpoint']
281 codeman 226 if not GLIUtility.is_file(self._chroot_dir+mountpoint):
282     exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
283     if exitstatus != 0:
284     raise GLIException("MkdirError", 'fatal','mount_network_shares', "Making the mount point failed!")
285 agaffney 391 ret = GLIUtility.spawn("mount -t nfs "+mountopts+" "+host+":"+export+" "+self._chroot_dir+mountpoint, display_on_tty8=True, logfile=self._compile_logfile)
286 codeman 226 if not GLIUtility.exitsuccess(ret):
287 codeman 314 raise GLIException("MountError", 'fatal','mount_network_shares','Could not mount an NFS partition')
288     self._logger.log("Mounted netmount at mountpoint:"+mountpoint)
289    
290 samyron 102 def fetch_sources_from_cd(self):
291     "Gets sources from CD (required for non-network installation)"
292 codeman 314 #WARNING: There will no longer be sources on the future livecds. this will have to change!
293 codeman 216 if not GLIUtility.is_file(self._chroot_dir+"/usr/portage/distfiles"):
294     exitstatus = GLIUtility.spawn("mkdir -p /usr/portage/distfiles",chroot=self._chroot_dir)
295     if exitstatus != 0:
296     raise GLIException("MkdirError", 'fatal','install_portage_tree',"Making the distfiles directory failed.")
297 agaffney 391 exitstatus = GLIUtility.spawn("cp /mnt/cdrom/distfiles/* "+self._chroot_dir+"/usr/portage/distfiles/", display_on_tty8=True, logfile=self._compile_logfile)
298 codeman 216 if exitstatus != 0:
299     raise GLIException("PortageError", 'fatal','install_portage_tree',"Failed to copy the distfiles to the new system")
300 codeman 314 self._logger.log("Distfiles copied from cd.")
301    
302 samyron 102 def fetch_grp_from_cd(self):
303     "Gets grp binary packages from CD (required for non-network binary installation)"
304 codeman 282 # This will not work until we find out how the new GRP format will function.
305 codeman 204 pass
306 codeman 201
307 samyron 102 def configure_make_conf(self):
308     "Configures make.conf"
309 codeman 201
310 samyron 102 # Get make.conf options
311     options = self._install_profile.get_make_conf()
312    
313     # For each configuration option...
314     for key in options.keys():
315    
316     # Add/Edit it into make.conf
317 codeman 222 self._edit_config(self._chroot_dir + "/etc/make.conf", {key: options[key]})
318 codeman 314 self._logger.log("Make.conf configured")
319 samyron 102
320     def install_portage_tree(self):
321     "Get/update the portage tree"
322    
323     # Check the type of portage tree fetching we'll do
324     # If it is custom, follow the path to the custom tarball and unpack it
325     if self._install_profile.get_portage_tree_sync_type() == "custom":
326    
327     # Get portage tree info
328     portage_tree_snapshot_uri = self._install_profile.get_portage_tree_snapshot_uri()
329 codeman 216 if portage_tree_snapshot_uri:
330     # Fetch and unpack the tarball
331     GLIUtility.fetch_and_unpack_tarball(portage_tree_snapshot_uri, self._chroot_dir + "/usr/", self._chroot_dir + "/")
332     # FIXME TEMPORARY FIX FOR NON-GRP SETTING
333     self.fetch_sources_from_cd()
334 codeman 314 self._logger.log("Portage tree install was custom.")
335 samyron 102 # If the type is webrsync, then run emerge-webrsync
336     elif self._install_profile.get_portage_tree_sync_type() == "webrsync":
337 agaffney 391 exitstatus = GLIUtility.spawn("emerge-webrsync", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile)
338 samyron 102 if exitstatus != 0:
339 samyron 186 raise GLIException("EmergeWebRsyncError", 'fatal','install_portage_tre', "Failed to retrieve portage tree!")
340 codeman 314 self._logger.log("Portage tree sync'd using webrsync")
341 samyron 102 # Otherwise, just run emerge sync
342     else:
343     exitstatus = self._emerge("sync")
344     if exitstatus != 0:
345 samyron 186 raise GLIException("EmergeSyncError", 'fatal','install_portage_tree', "Failed to retrieve portage tree!")
346 codeman 314 self._logger.log("Portage tree sync'd")
347    
348 samyron 102 def set_timezone(self):
349     "Sets the timezone for the new environment"
350     # Set symlink
351 codeman 201 if not os.access(self._chroot_dir + "/etc/localtime", os.W_OK):
352     os.symlink(self._chroot_dir + "/usr/share/zoneinfo/" + self._install_profile.get_time_zone(), self._chroot_dir + "/etc/localtime")
353 samyron 102 if not (self._install_profile.get_time_zone() == "UTC"):
354 codeman 216 self._edit_config(self._chroot_dir + "/etc/rc.conf", {"CLOCK":"local"})
355 codeman 314 self._logger.log("Timezone set.")
356 samyron 102
357     def configure_fstab(self):
358     "Configures fstab"
359     newfstab = ""
360 codeman 216 #partitions = self._install_profile.get_fstab()
361     parts = self._install_profile.get_partition_tables()
362     for device in parts:
363     #in parts['/dev/hda']
364     for partition in parts[device]:
365     #print parts[device][partition]
366     mountpoint = parts[device][partition]['mountpoint']
367     minor = str(parts[device][partition]['minor'])
368     partition_type = parts[device][partition]['type']
369     mountopts = parts[device][partition]['mountopts']
370     if mountpoint:
371     if not GLIUtility.is_file(self._chroot_dir+mountpoint):
372 codeman 217 exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
373     if exitstatus != 0:
374     raise GLIException("MkdirError", 'fatal','configure_fstab', "Making the mount point failed!")
375 codeman 216 newfstab += device+minor+"\t "+mountpoint+"\t "+partition_type+"\t "+mountopts+"\t\t "
376     if mountpoint == "/boot":
377     newfstab += "1 2\n"
378     elif mountpoint == "/":
379     newfstab += "0 1\n"
380     else:
381     newfstab += "0 0\n"
382     if partition_type == "linux-swap":
383     newfstab += device+minor+"\t none swap sw 0 0\n"
384 samyron 102 newfstab += "none /proc proc defaults 0 0\n"
385     newfstab += "none /dev/shm tmpfs defaults 0 0\n"
386     if GLIUtility.is_device("/dev/cdroms/cdrom0"):
387     newfstab += "/dev/cdroms/cdrom0 /mnt/cdrom auto noauto,user 0 0\n"
388 agaffney 161
389     for netmount in self._install_profile.get_network_mounts():
390     if netmount['type'] == "nfs":
391     newfstab += netmount['host'] + ":" + netmount['export'] + "\t" + netmount['mountpoint'] + "\tnfs\t" + netmount['mountopts'] + "\t0 0\n"
392 samyron 102
393 codeman 201 file_name = self._chroot_dir + "/etc/fstab"
394 samyron 102 try:
395     shutil.move(file_name, file_name + ".OLDdefault")
396     except:
397     pass
398     f = open(file_name, 'w')
399     f.writelines(newfstab)
400     f.close()
401 codeman 314 self._logger.log("fstab configured.")
402 samyron 102
403     def emerge_kernel_sources(self):
404     "Fetches desired kernel sources"
405 codeman 314 kernel_pkg = self._install_profile.get_kernel_source_pkg()
406 agaffney 401 # if kernel_pkg:
407     if kernel_pkg == "livecd-kernel":
408     PKGDIR = "/usr/portage/packages"
409 agaffney 415 PORTAGE_TMPDIR = "/var/tmp"
410 agaffney 414 make_conf = self._install_profile.get_make_conf()
411     if "PKGDIR" in make_conf: PKGDIR = make_conf['PKGDIR']
412     if "PORTAGE_TMPDIR" in make_conf: PORTAGE_TMPDIR = make_conf['PORTAGE_TMPDIR']
413     GLIUtility.spawn("mkdir -p " + self._chroot_dir + PKGDIR, logfile=self._compile_logfile)
414 codeman 424 GLIUtility.spawn("mkdir -p " + self._chroot_dir + PORTAGE_TMPDIR, logfile=self._compile_logfile)
415 agaffney 401 ret = GLIUtility.spawn("env PKGDIR=" + self._chroot_dir + PKGDIR + " PORTAGE_TMPDIR=" + self._chroot_dir + PORTAGE_TMPDIR + " quickpkg livecd-kernel")
416 agaffney 413 ret = GLIUtility.spawn("env PKGDIR=" + PKGDIR + " emerge -K sys-kernel/livecd-kernel", chroot=self._chroot_dir)
417 codeman 434 else:
418 codeman 314 exitstatus = self._emerge(kernel_pkg)
419     if exitstatus != 0:
420     raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not retrieve kernel sources!")
421     try:
422     os.stat(self._chroot_dir + "/usr/src/linux")
423     except:
424     kernels = os.listdir(self._chroot_dir+"/usr/src")
425     found_a_kernel = False
426     counter = 0
427     while not found_a_kernel:
428     if kernels[counter][0:6]=="linux-":
429     exitstatus = GLIUtility.spawn("ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux",chroot=self._chroot_dir)
430     if exitstatus != 0:
431     raise GLIException("EmergeKernelSourcesError", 'fatal','emerge_kernel_sources',"Could not make a /usr/src/linux symlink")
432     found_a_kernel = True
433     else:
434     counter = counter + 1
435     self._logger.log("Kernel sources:"+kernel_pkg+" emerged and /usr/src/linux symlinked.")
436 samyron 102
437     def build_kernel(self):
438     "Builds kernel"
439 codeman 314 self._logger.mark()
440     self._logger.log("Starting build_kernel")
441 agaffney 401 # No building necessary if using the LiveCD's kernel/initrd
442     if self._install_profile.get_kernel_source_pkg() == "livecd-kernel": return
443 samyron 102 # Get the uri to the kernel config
444     kernel_config_uri = self._install_profile.get_kernel_config_uri()
445 codeman 282 if kernel_config_uri == "": #use genkernel if no specific config
446 samyron 102
447 codeman 282 exitstatus = self._emerge("genkernel")
448     if exitstatus != 0:
449 codeman 314 raise GLIException("EmergeGenKernelError", 'fatal','build_kernel', "Could not emerge genkernel!")
450     self._logger.log("Genkernel emerged. Beginning kernel compile.")
451 codeman 282 # Null the genkernel_options
452     genkernel_options = ""
453    
454     # If the uri for the kernel config is not null, then
455     if kernel_config_uri != "":
456     GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/root/kernel_config")
457     genkernel_options = genkernel_options + " --kernel-config=/root/kernel_config"
458    
459     # Decide whether to use bootsplash or not
460     if self._install_profile.get_kernel_bootsplash():
461     genkernel_options = genkernel_options + " --bootsplash"
462     else:
463     genkernel_options = genkernel_options + " --no-bootsplash"
464     # Run genkernel in chroot
465 codeman 435 #print "genkernel all " + genkernel_options
466 agaffney 391 exitstatus = GLIUtility.spawn("genkernel all " + genkernel_options, chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile)
467 codeman 282 if exitstatus != 0:
468     raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build kernel!")
469 codeman 395
470     exitstatus = self._emerge("hotplug")
471     if exitstatus != 0:
472     raise GLIException("EmergeHotplugError", 'fatal','build_kernel', "Could not emerge hotplug!")
473     self._logger.log("Hotplug emerged.")
474     exitstatus = self._emerge("coldplug")
475     if exitstatus != 0:
476     raise GLIException("EmergeColdplugError", 'fatal','build_kernel', "Could not emerge coldplug!")
477     self._logger.log("Coldplug emerged. Now they should be added to the default runlevel.")
478    
479 codeman 361 self._add_to_runlevel("hotplug")
480     self._add_to_runlevel("coldplug", runlevel="boot")
481 codeman 314 self._logger.log("Genkernel complete.")
482 codeman 282 else: #CUSTOM CONFIG
483     #Copy the kernel .config to the proper location in /usr/src/linux
484     try:
485 codeman 287 GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/root/kernel_config")
486 codeman 282 except:
487     raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not copy kernel config!")
488 samyron 102
489 codeman 287 kernel_compile_script = "#!/bin/bash\n"
490     kernel_compile_script += "cp /root/kernel_config /usr/src/linux/.config\n"
491     kernel_compile_script += "cd /usr/src/linux\n"
492     kernel_compile_script += "make \nmake modules_install \n"
493    
494     #Ok now that it's built, copy it to /boot/kernel-* for bootloader code to find it
495     if self._client_configuration.get_architecture_template() == "x86":
496     kernel_compile_script += "cp /usr/src/linux/arch/i386/boot/bzImage /boot/kernel-custom\n"
497     f = open(self._chroot_dir+"/root/kernel_script", 'w')
498     f.writelines(kernel_compile_script)
499     f.close()
500 codeman 282 #Build the kernel
501 codeman 314 exitstatus1 = GLIUtility.spawn("chmod u+x "+self._chroot_dir+"/root/kernel_script")
502 agaffney 391 exitstatus2 = GLIUtility.spawn("/root/kernel_script", chroot=self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile)
503 codeman 314 if (exitstatus1 != 0) or (exitstatus2 != 0):
504 codeman 282 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build custom kernel!")
505 codeman 287
506 codeman 282 #i'm sure i'm forgetting something here.
507 codeman 288 #cleanup
508     exitstatus = GLIUtility.spawn("rm "+self._chroot_dir+"/root/kernel_script")
509     #it's not important if this fails.
510 codeman 314 self._logger.log("Custom kernel complete")
511    
512 samyron 102 def install_logging_daemon(self):
513     "Installs and sets up logger"
514     # Get loggin daemon info
515     logging_daemon_pkg = self._install_profile.get_logging_daemon_pkg()
516     if logging_daemon_pkg:
517     # Emerge Logging Daemon
518     exitstatus = self._emerge(logging_daemon_pkg)
519     if exitstatus != 0:
520 codeman 318 raise GLIException("LoggingDaemonError", 'fatal','install_logging_daemon', "Could not emerge " + logging_daemon_pkg + "!")
521 samyron 102
522     # Add Logging Daemon to default runlevel
523     self._add_to_runlevel(logging_daemon_pkg)
524 codeman 314 self._logger.log("Logging daemon installed: "+logging_daemon_pkg)
525 samyron 102 def install_cron_daemon(self):
526     "Installs and sets up cron"
527     # Get cron daemon info
528     cron_daemon_pkg = self._install_profile.get_cron_daemon_pkg()
529     if cron_daemon_pkg:
530     # Emerge Cron Daemon
531     exitstatus = self._emerge(cron_daemon_pkg)
532     if exitstatus != 0:
533 codeman 318 raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Could not emerge " + cron_daemon_pkg + "!")
534 samyron 102
535     # Add Cron Daemon to default runlevel
536     self._add_to_runlevel(cron_daemon_pkg)
537    
538     # If the Cron Daemon is not vixie-cron, run crontab
539     if cron_daemon_pkg != "vixie-cron":
540 codeman 345 exitstatus = GLIUtility.spawn("crontab /etc/crontab", chroot=self._chroot_dir, display_on_tty8=True)
541 samyron 102 if exitstatus != 0:
542 codeman 318 raise GLIException("CronDaemonError", 'fatal', 'install_cron_daemon', "Failure making crontab!")
543 codeman 314 self._logger.log("Cron daemon installed and configured: "+cron_daemon_pkg)
544 samyron 102 def install_filesystem_tools(self):
545     "Installs and sets up fstools"
546     # Get the list of file system tools to be installed
547     filesystem_tools = self._install_profile.get_filesystem_tools_pkgs()
548    
549     # If the fstools var is a str, convert it to a list
550     if type(filesystem_tools) == str:
551     filesystem_tools = [ filesystem_tools ]
552    
553     # For each fstool package in the list, install it
554     for package in filesystem_tools:
555     exitstatus = self._emerge(package)
556     if exitstatus != 0:
557 codeman 318 self._logger.log("ERROR! : Could not emerge " + package + "!")
558     # raise GLIException("FilesystemToolsError", 'warning', 'install_filesystem_tools', "Could not emerge " + package + "!")
559     else:
560     self._logger.log("FileSystemTool "+package+" was emerged successfully.")
561 samyron 102
562     def install_rp_pppoe(self):
563     "Installs rp-pppoe"
564     # If user wants us to install rp-pppoe, then do so
565     if self._install_profile.get_install_rp_pppoe():
566     exitstatus = self._emerge("rp-pppoe")
567     if exitstatus != 0:
568 codeman 318 self._logger.log("ERROR! : Could not emerge rp-pppoe!")
569     # raise GLIException("RP_PPPOEError", 'warning', 'install_rp_pppoe', "Could not emerge rp-pppoe!")
570     else:
571     self._logger.log("rp-pppoe emerged but not set up.")
572 samyron 102 # Should we add a section here to automatically configure rp-pppoe?
573     # I think it should go into the setup_network_post section
574     # What do you guys think?
575    
576     def install_pcmcia_cs(self):
577     "Installs and sets up pcmcia-cs"
578     # If user wants us to install pcmcia-cs, then do so
579     if self._install_profile.get_install_pcmcia_cs():
580     exitstatus = self._emerge("pcmcia-cs")
581     if exitstatus != 0:
582 codeman 318 self._logger.log("ERROR! : Could not emerge pcmcia-cs!")
583     # raise GLIException("PCMCIA_CSError", 'warning', 'install_pcmcia_cs', "Could not emerge pcmcia-cs!")
584 samyron 102
585     # Add pcmcia-cs to the default runlevel
586 codeman 318 else:
587     self._add_to_runlevel(pcmcia)
588     self._logger.log("PCMCIA_CS emerged and configured.")
589 samyron 102
590     def update_config_files(self):
591     "Runs etc-update (overwriting all config files), then re-configures the modified ones"
592     # Run etc-update overwriting all config files
593 codeman 345 status = GLIUtility.spawn('echo "-5" | chroot '+self._chroot_dir+' etc-update', display_on_tty8=True)
594 codeman 218 if not GLIUtility.exitsuccess(status):
595 codeman 318 self._logger.log("ERROR! : Could not update the config files!")
596     # raise GLIException("EtcUpdateError", 'warning', 'update_config_files', "Could not update config files!")
597     else:
598     self.configure_make_conf()
599     self.configure_fstab()
600     self.configure_rc_conf()
601     self._logger.log("Config files updated using etc-update. make.conf/fstab/rc.conf restored.")
602 samyron 102
603     def configure_rc_conf(self):
604     "Configures rc.conf"
605     # Get make.conf options
606     options = self._install_profile.get_rc_conf()
607    
608     # For each configuration option...
609     for key in options.keys():
610    
611     # Add/Edit it into rc.conf
612 codeman 222 self._edit_config(self._chroot_dir + "/etc/rc.conf", {key: options[key]})
613 codeman 314 self._logger.log("rc.conf configured.")
614    
615 samyron 102 def setup_network_post(self):
616     "Sets up the network for the first boot"
617     # Get hostname, domainname and nisdomainname
618     hostname = self._install_profile.get_hostname()
619     domainname = self._install_profile.get_domainname()
620     nisdomainname = self._install_profile.get_nisdomainname()
621    
622     # Write the hostname to the hostname file
623 codeman 201 open(self._chroot_dir + "/etc/hostname", "w").write(hostname + "\n")
624 samyron 102
625     # Write the domainname to the nisdomainname file
626     if domainname:
627 codeman 201 open(self._chroot_dir + "/etc/dnsdomainname", "w").write(domainname + "\n")
628 codeman 409 self._add_to_runlevel("domainname")
629 samyron 102
630     # Write the nisdomainname to the nisdomainname file
631     if nisdomainname:
632 codeman 201 open(self._chroot_dir + "/etc/nisdomainname", "w").write(nisdomainname + "\n")
633 codeman 409 self._add_to_runlevel("domainname")
634 samyron 102
635     #
636     # EDIT THE /ETC/HOSTS FILE
637     #
638    
639     # The address we are editing is 127.0.0.1
640     hosts_ip = "127.0.0.1"
641    
642     # If the hostname is localhost
643     if hostname == "localhost":
644     # If a domainname is set
645     if domainname:
646     hosts_line = hostname + "." + domainname + "\t" + hostname
647     else:
648     hosts_line = hostname
649     # If the hostname is not localhost
650     else:
651     # If a domainname is set
652     if domainname:
653     hosts_line = hostname + "." + domainname + "\t" + hostname + "\tlocalhost"
654     else:
655     hosts_line = "localhost\t" + hostname
656    
657     # Write to file
658 codeman 218 self._edit_config(self._chroot_dir + "/etc/hosts", {hosts_ip: hosts_line}, delimeter='\t', quotes_around_value=False)
659 samyron 102
660     #
661     # SET DEFAULT GATEWAY
662     #
663    
664     # Get default gateway
665     default_gateway = self._install_profile.get_default_gateway()
666    
667     # If the default gateway exists, add it
668     if default_gateway:
669 codeman 359 default_gateway_string = default_gateway[0] + "/" + default_gateway[1]
670     self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"gateway": default_gateway_string})
671 samyron 102
672     #
673     # SET RESOLV INFO
674     #
675    
676     # Get dns servers
677     dns_servers = self._install_profile.get_dns_servers()
678    
679     # Clear the list
680     resolv_output = []
681    
682     # If dns servers are set
683     if dns_servers:
684    
685    
686     # Parse each dns server
687     for dns_server in dns_servers:
688     # Add the server to the output
689     resolv_output.append("nameserver " + dns_server +"\n")
690    
691     # If the domainname is set, then also output it
692     if domainname:
693     resolv_output.append("search " + domainname + "\n")
694    
695 codeman 347 # Output to file
696     resolve_conf = open(self._chroot_dir + "/etc/resolv.conf", "w")
697     resolve_conf.writelines(resolv_output)
698     resolve_conf.close()
699 samyron 102
700     #
701     # PARSE INTERFACES
702     #
703    
704     # Fetch interfaces
705     interfaces = self._install_profile.get_network_interfaces()
706 codeman 347 emerge_dhcp = False
707 samyron 102 # Parse each interface
708     for interface in interfaces.keys():
709    
710     # Set what kind of interface it is
711     interface_type = interface[:3]
712    
713     # Check to see if there is a startup script for this interface, if there isn't link to the proper script
714     try:
715 codeman 201 os.stat(self._chroot_dir + "/etc/init.d/net." + interface)
716 samyron 102 except:
717 codeman 201 os.symlink(self._chroot_dir + "/etc/init.d/net." + interface_type + "0", self._chroot_dir + "/etc/init.d/net." + interface)
718 samyron 102
719 codeman 409 # If we are going to load the network at boot...
720     if interfaces[interface][2]:
721    
722     # Add it to the default runlevel
723     self._add_to_runlevel("net."+interface)
724    
725 samyron 102 #
726     # ETHERNET
727     #
728     if interface_type == "eth":
729    
730     #
731     # STATIC IP
732     #
733     # If the post-install device info is not None, then it is a static ip addy
734     if interfaces[interface][1]:
735     ip = interfaces[interface][0]
736     broadcast = interfaces[interface][1]
737     netmask = interfaces[interface][2]
738     # aliases = interfaces[interface][1][3]
739     # alias_ips = []
740     # alias_broadcasts = []
741     # alias_netmasks = []
742    
743     # Write the static ip config to /etc/conf.d/net
744 codeman 217 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: ip + " broadcast " + broadcast + " netmask " + netmask})
745 samyron 102
746     # If aliases are set
747     # if aliases:
748    
749     # Parse aliases to format alias info
750     # for alias in aliases:
751     # alias_ips.append(alias[0])
752     # alias_broadcasts.append(alias[1])
753     # alias_netmasks.append(allias[2])
754    
755     # Once the alias info has been gathered, then write it out
756     # Alias ips first
757 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "alias_" + interface, string.join(alias_ips))
758 samyron 102 # Alias broadcasts next
759 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "broadcast_" + interface, string.join(alias_broadcasts))
760 samyron 102 # Alias netmasks last
761 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "netmask_" + interface, string.join(alias_netmasks))
762 samyron 102
763     #
764     # DHCP IP
765     #
766     else:
767 codeman 217 self._edit_config(self._chroot_dir + "/etc/conf.d/net", {"iface_" + interface: "dhcp"})
768 codeman 347 emerge_dhcp = True
769 codeman 319 if emerge_dhcp:
770     exitstatus = self._emerge("dhcpcd")
771     if exitstatus != 0:
772     self._logger.log("ERROR! : Could not emerge dhcpcd!")
773     else:
774     self._logger.log("dhcpcd emerged.")
775    
776 samyron 102 def set_root_password(self):
777     "Sets the root password"
778 codeman 346 status = GLIUtility.spawn('echo "root:' + self._install_profile.get_root_pass_hash() + '" | chroot '+self._chroot_dir+' chpasswd -e', quiet=True)
779 codeman 237 if not GLIUtility.exitsuccess(status):
780 codeman 318 raise GLIException("SetRootPasswordError", 'fatal', 'set_root_password', "Failure to set root password!")
781 codeman 314 self._logger.log("Root Password set on the new system.")
782    
783 samyron 102 def set_users(self):
784     "Sets up the new users for the system"
785     # Loop for each user
786     for user in self._install_profile.get_users():
787    
788     # Get values from the tuple
789     username = user[0]
790     password_hash = user[1]
791     groups = user[2]
792     shell = user[3]
793     home_dir = user[4]
794     uid = user[5]
795     comment = user[6]
796    
797     options = [ "-m", "-p " + password_hash ]
798    
799     # If the groups are specified
800     if groups:
801    
802     # If just one group is listed as a string, make it a list
803     if groups == str:
804     groups = [ groups ]
805    
806     # If only 1 group is listed
807     if len(groups) == 1:
808     options.append("-G " + groups[0])
809    
810     # If there is more than one group
811     elif len(groups) > 1:
812     options.append('-G "' + string.join(groups, ",") + '"')
813    
814     # If a shell is specified
815     if shell:
816     options.append("-s " + shell)
817    
818     # If a home dir is specified
819     if home_dir:
820     options.append("-d " + home_dir)
821    
822     # If a UID is specified
823     if uid:
824     options.append("-u " + str(uid))
825    
826     # If a comment is specified
827     if comment:
828     options.append('-c "' + comment + '"')
829    
830     # Add the user
831 agaffney 391 exitstatus = GLIUtility.spawn('useradd ' + string.join(options) + ' ' + username, chroot=self._chroot_dir, logfile=self._compile_logfile, display_on_tty8=True)
832 codeman 237 if not GLIUtility.exitsuccess(exitstatus):
833 codeman 318 self._logger.log("ERROR! : Failure to add user " + username)
834     # raise GLIException("AddUserError", 'warning', 'set_users', "Failure to add user " + username)
835     else:
836     self._logger.log("User "+username+"was added.")
837 codeman 314
838 codeman 432 def finishing_cleanup(self):
839     "This function will handle the various cleanup tasks as well as unmounting the filesystems for reboot."
840     #These are temporary until I come up with a nicer idea.
841     #First we copy the log over to the new system.
842     install_logfile = self._client_configuration.get_log_file()
843     try:
844     shutil.copy(install_logfile, self._chroot_dir + install_logfile)
845     except:
846     pass
847     #Now we're done logging as far as the new system is concerned.
848    
849     #Unmount the /proc and /dev that we mounted in prepare_chroot
850     #There really isn't a reason to log errors here.
851     ret = GLIUtility.spawn("umount "+self._chroot_dir+"/proc", display_on_tty8=True, logfile=self._compile_logfile)
852     ret = GLIUtility.spawn("umount "+self._chroot_dir+"/dev", display_on_tty8=True, logfile=self._compile_logfile)
853     #temp hack to unmount the new root.
854     ret = GLIUtility.spawn("umount "+self._chroot_dir, display_on_tty8=True, logfile=self._compile_logfile)
855     #insert code here to unmount the swap partition, if there is one.
856    
857 codeman 213 def install_bootloader(self):
858     "THIS FUNCTION MUST BE DONE BY THE INDIVIDUAL ARCH"
859     pass

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20