/[gli]/branches/overhaul/src/templates/x86ArchitectureTemplate.py
Gentoo

Contents of /branches/overhaul/src/templates/x86ArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1369 - (show annotations) (download) (as text)
Thu Mar 16 19:24:37 2006 UTC (12 years, 6 months ago) by agaffney
Original Path: trunk/src/templates/x86ArchitectureTemplate.py
File MIME type: text/x-python
File size: 34305 byte(s)
  src/templates/x86ArchitectureTemplate.py:
  fail if any filesystems are mounted on the device being partitioned

1 """
2 # Copyright 1999-2005 Gentoo Foundation
3 # This source code is distributed under the terms of version 2 of the GNU
4 # General Public License as published by the Free Software Foundation, a copy
5 # of which can be found in the main directory of this project.
6 Gentoo Linux Installer
7
8 $Id: x86ArchitectureTemplate.py,v 1.116 2006/03/16 19:24:37 agaffney Exp $
9 Copyright 2004 Gentoo Technologies Inc.
10
11
12 This fills in x86 specific functions.
13 """
14
15 import GLIUtility, string, time
16 from GLIArchitectureTemplate import ArchitectureTemplate
17 from GLIException import *
18 import parted
19 import GLIStorageDevice
20
21 MEGABYTE = 1024 * 1024
22
23 class x86ArchitectureTemplate(ArchitectureTemplate):
24 def __init__(self,configuration=None, install_profile=None, client_controller=None):
25 ArchitectureTemplate.__init__(self, configuration, install_profile, client_controller)
26 self._architecture_name = 'x86'
27 self._kernel_bzimage = "arch/i386/boot/bzImage"
28
29 def install_bootloader(self):
30 "Installs and configures bootloader"
31 #
32 # THIS IS ARCHITECTURE DEPENDANT!!!
33 # This is the x86 way.. it uses grub
34
35 bootloader_pkg = self._install_profile.get_boot_loader_pkg()
36
37 # first install bootloader
38 if bootloader_pkg and bootloader_pkg.lower() != "none":
39 exitstatus = self._portage.emerge(bootloader_pkg)
40 # if not GLIUtility.exitsuccess(exitstatus):
41 # raise GLIException("BootLoaderEmergeError", 'fatal', 'install_bootloader', "Could not emerge bootloader!")
42 # else:
43 self._logger.log("Emerged the selected bootloader.")
44
45 # now configure said bootloader
46 # null boot-loader first
47 if bootloader_pkg.lower() == "none":
48 return
49 elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*'
50 self._configure_grub()
51 elif "lilo" in bootloader_pkg:
52 self._configure_lilo()
53 # probably should add in some more bootloaders
54 # dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload
55 else:
56 raise GLIException("BootLoaderError",'fatal','install_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg)
57
58 def _sectors_to_megabytes(self, sectors, sector_bytes=512):
59 return float((float(sectors) * sector_bytes)/ float(MEGABYTE))
60
61 def _add_partition(self, disk, start, end, type, fs):
62 types = { 'primary': parted.PARTITION_PRIMARY, 'extended': parted.PARTITION_EXTENDED, 'logical': parted.PARTITION_LOGICAL }
63 fsTypes = {}
64 fs_type = parted.file_system_type_get_next ()
65 while fs_type:
66 fsTypes[fs_type.name] = fs_type
67 fs_type = parted.file_system_type_get_next (fs_type)
68 fstype = None
69 if fs: fstype = fsTypes[fs]
70 newpart = disk.partition_new(types[type], fstype, start, end)
71 constraint = disk.dev.constraint_any()
72 disk.add_partition(newpart, constraint)
73
74 def partition(self):
75 parts_old = {}
76 tmp_parts_new = self._install_profile.get_partition_tables()
77 parts_new = {}
78 for device in tmp_parts_new:
79 parts_new[device] = tmp_parts_new[device] #.get_install_profile_structure()
80 detected_devices = GLIStorageDevice.detect_devices()
81 for device in detected_devices:
82 tmpdevice = GLIStorageDevice.Device(device, arch=self._client_configuration.get_architecture_template())
83 tmpdevice.set_partitions_from_disk()
84 parts_old[device] = tmpdevice #.get_install_profile_structure()
85
86 self.notify_frontend("progress", (0, "Examining partitioning data"))
87 total_steps = float(len(parts_new) * 3)
88 cur_progress = 0
89 for device in parts_new.keys():
90 # Skip this device in parts_new if device isn't detected on current system
91 if not device in detected_devices:
92 self._logger.log("There is no physical device " + device + " detected to match the entry in the install profile...skipping")
93 continue
94
95 # Check to see if the old and new partition table structures are the same
96 table_changed = 0
97 for part in parts_new[device]:
98 if not part in parts_old[device]:
99 table_changed = 1
100 break
101 oldpart = parts_old[device].get_partition(part)
102 newpart = parts_new[device].get_partition(part)
103 if oldpart.get_type() == newpart.get_type() and oldpart.get_mb() == newpart.get_mb() and newpart.is_resized() and not newpart.get_format():
104 continue
105 else:
106 table_changed = 1
107 break
108 # Skip this device if they are they same
109 if not table_changed:
110 self._logger.log("Partition table for " + device + " is unchanged...skipping")
111 continue
112
113 self._logger.log("partitioning: Processing " + device + "...")
114
115 if GLIUtility.spawn("mount | grep '^" + device + "'", return_output=True)[1].strip():
116 raise GLIException("PartitionsMountedError", 'fatal', 'partition', "Cannot partition " + device + " due to filesystems being mounted")
117
118 # Create pyparted objects for this device
119 parted_dev = parted.PedDevice.get(device)
120 try:
121 parted_disk = parted.PedDisk.new(parted_dev)
122 except:
123 parted_disk = parted_dev.disk_new_fresh(parted.disk_type_get((tmp_parts_new[device].get_disklabel() or GLIStorageDevice.archinfo[self._architecture_name]['disklabel'])))
124 # new_part_list = parts_new[device].keys()
125 # new_part_list.sort()
126 new_part_list = tmp_parts_new[device].get_ordered_partition_list()
127 device_sectors = parted_dev.length
128
129 # Iterate through new partitions and check for 'origminor' and 'format' == False
130 for part in new_part_list:
131 tmppart_new = parts_new[device][part]
132 if not tmppart_new['origminor'] or tmppart_new['format']: continue
133 tmppart_old = parts_old[device][tmppart_new['origminor']]
134 parted_part = parted_disk.get_partition(tmppart_new['origminor'])
135 # This partition in parts_new corresponds with an existing partitions, so we save the start/end sector and flags
136 for flag in range(0, 10):
137 # The 10 is completely arbitrary. If flags seem to be missed, this number should be increased
138 if not parted_part: break
139 if parted_part.is_flag_available(flag) and parted_part.get_flag(flag):
140 if not "flags" in tmppart_new: tmppart_new['flags'] = []
141 tmppart_new['flags'].append(flag)
142 if tmppart_new['resized']:
143 self._logger.log(" Partition " + str(part) + " has origminor " + str(tmppart_new['origminor']) + " and it being resized...saving start sector " + str(tmppart_old['start']))
144 tmppart_new['start'] = tmppart_old['start']
145 tmppart_new['end'] = 0
146 else:
147 self._logger.log(" Partition " + str(part) + " has origminor " + str(tmppart_new['origminor']) + "...saving start sector " + str(tmppart_old['start']) + " and end sector " + str(tmppart_old['end']))
148 tmppart_new['start'] = tmppart_old['start']
149 tmppart_new['end'] = tmppart_old['end']
150
151 # if parts_new[dev][parts_new[dev].keys()[0]]['mb']:
152 # # Change MB/%/* into sectors
153 # total_sectors = parted_dev.length
154 # sector_size = parted_dev.sector_size
155 # total_mb = float(total_sectors * sector_size) / MEGABYTE
156 # start_sector = 0
157 # mb_left = total_mb
158 # for part in parts_new[dev]:
159 # tmppart = parts_new[dev][part]
160 # if tmppart['type'] == "extended": continue
161 # if tmppart['mb'][-1] == "%":
162 # tmppart['mb'] = float(tmppart['mb'][:-1]) / 100 * total_mb
163 # mb_left = mb_left - float(tmppart['mb'])
164 # partlist = parts_new.keys()
165 # partlist.sort()
166 # for part in partlist:
167 # if part > 4: continue
168 # tmppart = parts_new[dev][part]
169 # if tmppart['type'] == "extended":
170 # for part_log in partlist:
171 # if part < 5: continue
172 # tmppart_log = parts_new[dev][part_log]
173 # if not tmppart['start']:
174 # tmppart['start'] = start_sector
175 # if tmppart_log['mb'] == "*":
176 # tmppart_log['mb'] = mb_left
177 # part_bytes = long(tmppart_log['mb'] * MEGABYTE)
178 # part_sectors = round(part_bytes / sector_size)
179 # tmppart_log['start'] = start_sector
180 # tmppart_log['end'] = start_sector + part_sectors - 1
181 # tmppart['end'] = tmppart_log['end']
182 # start_sector = start_sector + part_sectors
183 # continue
184 # if tmppart['mb'] == "*":
185 # tmppart['mb'] = mb_left
186 # part_bytes = long(tmppart['mb'] * MEGABYTE)
187 # part_sectors = round(part_bytes / sector_size)
188 # tmppart['start'] = start_sector
189 # tmppart['end'] = start_sector + part_sectors - 1
190 # start_sector = start_sector + part_sectors
191 # else:
192
193 # First pass to delete old partitions that aren't resized
194 self.notify_frontend("progress", (cur_progress / total_steps, "Deleting partitioning that aren't being resized for " + device))
195 cur_progress += 1
196 for part in parts_old[device]:
197 oldpart = parts_old[device][part]
198 # Replace 'x86' with call function to get arch from CC
199 if (GLIStorageDevice.archinfo['x86']['extended'] and part > 4) or oldpart['type'] == "free": continue
200 delete = 0
201 if oldpart['type'] == "extended":
202 logical_to_resize = 0
203 for part_log in parts_old[device]:
204 if part_log < 5 or parts_old[device][part_log]['type'] == "free": continue
205 delete_log = 0
206 for new_part in parts_new[device]:
207 if new_part < 5: continue
208 tmppart = parts_new[device][new_part]
209 # This partition is unchanged in the new layout
210 if tmppart['origminor'] == part_log and not tmppart['resized']:
211 self._logger.log(" Deleting old minor " + str(part_log) + " to be recreated later")
212 try:
213 parted_disk.delete_partition(parted_disk.get_partition(part_log))
214 except:
215 self._logger.log(" Could not delete partition...ignoring")
216 break
217 # This partition is resized with the data preserved in the new layout
218 if tmppart['origminor'] == part_log and tmppart['resized']:
219 self._logger.log(" Ignoring old minor " + str(part_log) + " to resize later")
220 logical_to_resize = 1
221 break
222 if not logical_to_resize:
223 self._logger.log(" Deleting extended partition with minor " + str(part))
224 parted_disk.delete_partition(parted_disk.get_partition(part))
225 continue
226 for new_part in parts_new[device]:
227 tmppart = parts_new[device][new_part]
228 if tmppart['origminor'] == part and not tmppart['resized']:
229 self._logger.log(" Deleting old minor " + str(part) + " to be recreated later")
230 try:
231 parted_disk.delete_partition(parted_disk.get_partition(part))
232 except:
233 self._logger.log(" Could not delete partition...ignoring")
234 break
235 if tmppart['origminor'] == part and tmppart['resized']:
236 self._logger.log(" Ignoring old minor " + str(part) + " to resize later")
237 break
238 parted_disk.commit()
239
240 # Second pass to resize old partitions that need to be resized
241 self._logger.log("Partitioning: Second pass...")
242 self.notify_frontend("progress", (cur_progress / total_steps, "Resizing remaining partitions for " + device))
243 cur_progress += 1
244 for part in parts_old[device]:
245 oldpart = parts_old[device][part]
246 for new_part in parts_new[device]:
247 tmppart = parts_new[device][new_part]
248 if tmppart['origminor'] == part and tmppart['resized']:
249 type = tmppart['type']
250 minor = part
251 start = tmppart['start']
252 # Replace 512 with code to retrieve bytes per sector for device
253 end = start + (long(tmppart['mb']) * MEGABYTE / 512)
254 tmppart['end'] = end
255 self._logger.log(" Resizing old minor " + str(part) + " from " + str(oldpart['start']) + "-" + str(oldpart['end'])+ " to " + str(tmppart['start']) + "-" + str(tmppart['end']))
256 for i in new_part_list:
257 if i <= new_part: continue
258 if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']:
259 end = parts_new[device][i]['start'] - 1
260 elif end >= device_sectors:
261 end = device_sectors - 1
262 break
263 # sleep a bit first
264 time.sleep(3)
265 # now sleep until it exists
266 while not GLIUtility.is_file(device + str(minor)):
267 self._logger.log("Waiting for device node " + device + str(minor) + " to exist...")
268 time.sleep(1)
269 # one bit of extra sleep is needed, as there is a blip still
270 time.sleep(3)
271 if type == "ext2" or type == "ext3":
272 total_sectors = end - start + 1
273 ret = GLIUtility.spawn("resize2fs " + device + str(minor) + " " + str(total_sectors) + "s", logfile=self._compile_logfile, append_log=True)
274 if not GLIUtility.exitsuccess(ret): # Resize error
275 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
276 elif type == "ntfs":
277 total_sectors = end - start + 1
278 total_bytes = long(total_sectors) * 512
279 ret = GLIUtility.spawn("yes | ntfsresize -v --size " + str(total_bytes) + " " + device + str(minor), logfile=self._compile_logfile, append_log=True)
280 if not GLIUtility.exitsuccess(ret): # Resize error
281 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
282 elif type == "linux-swap" or type == "fat32" or type == "fat16":
283 parted_fs = parted_disk.get_partition(part).geom.file_system_open()
284 resize_constraint = parted_fs.get_resize_constraint()
285 if end < (start + resize_constraint.min_size) or start != resize_constraint.start_range.start:
286 raise GLIException("PartitionError", 'fatal', 'partition', "New size specified for " + device + str(minor) + " is not within allowed boundaries")
287 new_geom = resize_constraint.start_range.duplicate()
288 new_geom.set_start(start)
289 new_geom.set_end(end)
290 try:
291 parted_fs.resize(new_geom)
292 except:
293 raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor))
294 self._logger.log(" Deleting old minor " + str(part) + " to be recreated in 3rd pass")
295 parted_disk.delete_partition(parted_disk.get_partition(part))
296 break
297 parted_disk.delete_all()
298 parted_disk.commit()
299
300 # Third pass to create new partition table
301 self._logger.log("Partitioning: Third pass....creating partitions")
302 self.notify_frontend("progress", (cur_progress / total_steps, "Recreating partition table for " + device))
303 cur_progress += 1
304 start = 0
305 end = 0
306 extended_start = 0
307 extended_end = 0
308 self._logger.log(" Drive has " + str(device_sectors) + " sectors")
309 # for part in parts_new[device]:
310 for part in new_part_list:
311 newpart = parts_new[device][part]
312 self._logger.log(" Partition " + str(part) + " has " + str(newpart['mb']) + "MB")
313 if newpart['start']:
314 self._logger.log(" Old start sector " + str(newpart['start']) + " retrieved")
315 if start != newpart['start']:
316 self._logger.log(" Retrieved start sector is not the same as the calculated next start sector")
317 start = newpart['start']
318 else:
319 self._logger.log(" Start sector calculated to be " + str(start))
320 if (newpart['minor'] < 5 or not GLIStorageDevice.archinfo['x86']['extended']) and start < extended_end:
321 self._logger.log(" Start sector for primary is less than the end sector for previous extended")
322 start = extended_end + 1
323 if newpart['end']:
324 self._logger.log(" Old end sector " + str(newpart['end']) + " retrieved")
325 end = newpart['end']
326 part_sectors = end - start + 1
327 else:
328 part_sectors = long(newpart['mb']) * MEGABYTE / 512
329 end = start + part_sectors
330 self._logger.log(" End sector calculated to be " + str(end))
331 # Make sure end doesn't overlap next partition's existing start sector
332 for i in new_part_list:
333 if i <= part: continue
334 if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']:
335 if not newpart['type'] == "extended" or i <= 4:
336 end = parts_new[device][i]['start'] - 1
337 break
338 # cap to end of device
339 if end >= device_sectors:
340 end = device_sectors - 1
341 # now the actual creation
342 if newpart['type'] == "free":
343 # Nothing to be done for this type
344 pass
345 elif newpart['type'] == "extended":
346 self._logger.log(" Adding extended partition " + str(part) + " from " + str(start) + " to " + str(end))
347 self._add_partition(parted_disk, start, end, "extended", "")
348 extended_start = start
349 extended_end = end
350 elif part < 5 or not GLIStorageDevice.archinfo['x86']['extended']:
351 self._logger.log(" Adding primary partition " + str(part) + " from " + str(start) + " to " + str(end))
352 self._add_partition(parted_disk, start, end, "primary", newpart['type'])
353 elif GLIStorageDevice.archinfo['x86']['extended'] and part > 4:
354 if start >= extended_end:
355 start = extended_start + 1
356 end = start + part_sectors
357 if part == new_part_list[-1] and end > extended_end:
358 end = extended_end
359 self._logger.log(" Adding logical partition " + str(part) + " from " + str(start) + " to " + str(end))
360 self._add_partition(parted_disk, start, end, "logical", newpart['type'])
361 if "flags" in newpart:
362 for flag in newpart['flags']:
363 if parted_disk.get_partition(part).is_flag_available(flag):
364 parted_disk.get_partition(part).set_flag(flag, True)
365 # write to disk
366 parted_disk.commit()
367
368 # force rescan of partition table
369 # Should not be needed with current stuff
370 #ret = GLIUtility.spawn("partprobe "+device, logfile=self._compile_logfile, append_log=True)
371
372 # now format the partition
373 # extended and 'free' partitions should never be formatted
374 if newpart['format'] and newpart['type'] not in ('extended', 'free'):
375 devnode = device + str(int(part))
376 errormsg = "could't create %s filesystem on %s" % (newpart['type'],devnode)
377 # if you need a special command and
378 # some base options, place it here.
379 if newpart['type'] == 'linux-swap':
380 cmdname = 'mkswap'
381 elif newpart['type'] == 'fat16':
382 cmdname = 'mkfs.vfat -F 16'
383 elif newpart['type'] == 'fat32':
384 cmdname = 'mkfs.vfat -F 32'
385 elif newpart['type'] == 'ntfs':
386 cmdname = 'mkntfs'
387 # All of these types need a -f as they
388 # ask for confirmation of format
389 elif newpart['type'] in ('xfs','jfs','reiserfs'):
390 cmdname = 'mkfs.%s -f' % (newpart['type'])
391 # add common partition stuff here
392 elif newpart['type'] in ('ext2','ext3'):
393 cmdname = 'mkfs.%s' % (newpart['type'])
394 else: # this should catch everything else
395 raise GLIException("PartitionFormatError", 'fatal', 'partition',"Unknown partition type "+newpart['type'])
396
397 # force a stat of the device so that it
398 # is created on demand. (At least if I
399 # recall how udev works... - robbat2).
400 # sleep a bit first
401 time.sleep(1)
402 # now sleep until it exists
403 # while not GLIUtility.is_file(devnode):
404 # self._logger.log("Waiting for device node "+devnode+" to exist...")
405 # time.sleep(1)
406 # one bit of extra sleep is needed, as there is a blip still
407 # time.sleep(1)
408
409 tries = 0
410 while tries <= 10:
411 # now the actual command
412 cmd = "%s %s %s" % (cmdname,newpart['mkfsopts'],devnode)
413 self._logger.log(" Formatting partition %s as %s with: %s" % (str(part),newpart['type'],cmd))
414 # If logging is not done, then you get errors:
415 # PartitionFormatError :FATAL: partition: could't create ext2 filesystem on /dev/hda1
416 #if GLIUtility.spawn(cmd):
417 #if GLIUtility.spawn(cmd,append_log=True,logfile='/var/log/install-mkfs.log'):
418 ret = GLIUtility.spawn(cmd, logfile=self._compile_logfile, append_log=True)
419 if not GLIUtility.exitsuccess(ret):
420 tries += 1
421 self._logger.log("Try %d failed formatting partition %s...waiting 5 seconds" % (tries, devnode))
422 time.sleep(5)
423 else:
424 break
425 if tries == 3:
426 raise GLIException("PartitionFormatError", 'fatal', 'partition', errormsg)
427 start = end + 1
428 self.notify_frontend("progress", (cur_progress / total_steps, "Done with partitioning for " + device))
429 # cur_progress += 1
430
431 def _configure_grub(self):
432 self.build_mode = self._install_profile.get_kernel_build_method()
433 self._gather_grub_drive_info()
434 root = self._chroot_dir
435 exitstatus2, kernel_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/kernel-*", return_output=True)
436 self._logger.log("Output of Kernel Names:\n"+kernel_names)
437 if not GLIUtility.exitsuccess(exitstatus2):
438 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the kernels in /boot")
439 if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
440 exitstatus3, initrd_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/init*", return_output=True)
441 self._logger.log("Output of Initrd Names:\n"+initrd_names)
442 if not GLIUtility.exitsuccess(exitstatus3):
443 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the initrds")
444 self._logger.log("Bootloader: the three information gathering commands have been run")
445
446 if not kernel_names[0]:
447 raise GLIException("BootloaderError", 'fatal', '_configure_grub',"Error: We have no kernel in /boot to put in the grub.conf file!")
448
449 #-------------------------------------------------------------
450 #OK, now that we have all the info, let's build that grub.conf
451 newgrubconf = ""
452 newgrubconf += "default 0\ntimeout 30\n"
453 if self.foundboot: #we have a /boot
454 newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/grub/splash.xpm.gz\n"
455 else: #we have / and /boot needs to be included
456 newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/boot/grub/splash.xpm.gz\n"
457 if self._install_profile.get_bootloader_kernel_args():
458 bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
459 else: bootloader_kernel_args = ""
460
461 kernel_names = map(string.strip, kernel_names.strip().split("\n"))
462 initrd_names = map(string.strip, initrd_names.strip().split("\n"))
463 grub_kernel_name = kernel_names[-1].split(root)[-1]
464 if initrd_names: grub_initrd_name = initrd_names[-1].split(root)[-1]
465 # for i in range(len(kernel_names)):
466 # grub_kernel_name = kernel_names[i].split(root)[-1]
467 # for i in range(len(initrd_names)): #this should be okay if blank.
468 # grub_initrd_name = initrd_names[i].split(root)[-1]
469 #i think this means take the last one it finds.. i.e. the newest.
470
471 newgrubconf += "title=Gentoo Linux\n"
472 newgrubconf += "root (" + self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
473 if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel": #using CUSTOM kernel
474 if self.foundboot:
475 newgrubconf += "kernel " + grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
476 else:
477 newgrubconf += "kernel /boot"+ grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
478 else: #using genkernel so it has an initrd.
479 if self.foundboot:
480 newgrubconf += "kernel " + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
481 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
482 newgrubconf += "initrd " + grub_initrd_name[5:] + "\n"
483 else:
484 newgrubconf += "kernel /boot" + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
485 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
486 newgrubconf += "initrd /boot" + grub_initrd_name[5:] + "\n"
487 newgrubconf = self._grub_add_windows(newgrubconf)
488 #now make the grub.conf file
489 file_name = root + "/boot/grub/grub.conf"
490 try:
491 shutil.move(file_name, file_name + ".OLDdefault")
492 except:
493 pass
494 f = open(file_name, 'w')
495 f.writelines(newgrubconf)
496 f.close()
497 self._logger.log("Grub installed and configured. Contents of grub.conf:\n"+newgrubconf)
498 self._logger.log("Grub has not yet been run. If a normal install, it will now be run.")
499
500 def _gather_grub_drive_info(self):
501 self.boot_minor = ""
502 self.boot_device = ""
503 self.root_device = ""
504 self.root_minor = ""
505 self.mbr_device = ""
506 self.grub_root_minor = ""
507 self.grub_boot_minor = ""
508 self.grub_boot_drive = ""
509 self.grub_root_drive = ""
510 self.grub_mbr_drive = ""
511 minornum = 0
512 #Assign root to the root mount point to make lines more readable
513 root = self._chroot_dir
514
515
516 self.foundboot = False
517 parts = self._install_profile.get_partition_tables()
518 for device in parts:
519 tmp_partitions = parts[device].get_install_profile_structure()
520 for partition in tmp_partitions:
521 mountpoint = tmp_partitions[partition]['mountpoint']
522 if (mountpoint == "/boot"):
523 self.foundboot = True
524 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
525 self.boot_minor = str(int(tmp_partitions[partition]['minor']))
526 self.grub_boot_minor = str(int(tmp_partitions[partition]['minor']) - 1)
527 self.boot_device = device
528 self.mbr_device = device
529 if mountpoint == "/":
530 self.root_minor = str(int(tmp_partitions[partition]['minor']))
531 self.grub_root_minor = str(int(tmp_partitions[partition]['minor']) - 1)
532 self.root_device = device
533 #RESET the boot device if one is stored already
534 if self._install_profile.get_boot_device():
535 self.mbr_device = self._install_profile.get_boot_device()
536 self._logger.log("Found a mbr device: " + self.mbr_device)
537
538 self.grub_boot_drive = self._map_device_to_grub_device(self.boot_device)
539 self.grub_root_drive = self._map_device_to_grub_device(self.root_device)
540 self.grub_mbr_drive = self._map_device_to_grub_device(self.mbr_device)
541
542 if (not self.grub_root_drive) or (not self.grub_boot_drive):
543 raise GLIException("BootloaderError", 'fatal', '_gather_grub_drive_info',"Couldn't find the drive num in the list from the device.map")
544
545 def _grub_add_windows(self, newgrubconf):
546 parts = self._install_profile.get_partition_tables()
547 for device in parts:
548 tmp_partitions = parts[device].get_install_profile_structure()
549 for partition in tmp_partitions:
550 if (tmp_partitions[partition]['type'] == "fat32") or (tmp_partitions[partition]['type'] == "ntfs"):
551 grub_dev = self._map_device_to_grub_device(device)
552 newgrubconf += "\ntitle=Possible Windows P"+str(int(tmp_partitions[partition]['minor']))+"\n"
553 newgrubconf += "rootnoverify ("+grub_dev+","+str(int(tmp_partitions[partition]['minor'] -1))+")\n"
554 newgrubconf += "makeactive\nchainloader +1\n\n"
555 return newgrubconf
556
557 def _configure_lilo(self):
558 self.build_mode = self._install_profile.get_kernel_build_method()
559 self._gather_lilo_drive_info()
560 root = self._chroot_dir
561 file_name3 = root + "/boot/kernel_name"
562 root = self._chroot_dir
563 exitstatus0 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3)
564 if (exitstatus0 != 0):
565 raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list kernels in /boot or no kernels found.")
566 if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
567 exitstatus1 = GLIUtility.spawn("ls "+root+"/boot/init* >> "+file_name3)
568 if (exitstatus1 != 0):
569 raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list initrds in /boot")
570 g = open(file_name3)
571 kernel_name = g.readlines()
572 g.close()
573 if not kernel_name[0]:
574 raise GLIException("BootloaderError", 'fatal', '_configure_lilo',"Error: We have no kernel in /boot to put in the grub.conf file!")
575 kernel_name = map(string.strip, kernel_name)
576 kernel_name[0] = kernel_name[0].split(root)[1]
577 kernel_name[1] = kernel_name[1].split(root)[1]
578 if self._install_profile.get_bootloader_kernel_args(): bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
579 else: bootloader_kernel_args = ""
580 #-------------------------------------------------------------
581 #time to build the lilo.conf
582 newliloconf = ""
583 if self._install_profile.get_boot_loader_mbr():
584 newliloconf += "boot="+self.mbr_device+" # Install LILO in the MBR \n"
585 else:
586 newliloconf += "boot="+self.boot_device+self.boot_minor+" # Install LILO in the MBR \n"
587 newliloconf += "prompt # Give the user the chance to select another section\n"
588 newliloconf += "timeout=50 # Wait 5 (five) seconds before booting the default section\n"
589 newliloconf += "default=gentoo # When the timeout has passed, boot the \"gentoo\" section\n"
590 newliloconf += "# Only if you use framebuffer. Otherwise remove the following line:\n"
591 if not self._install_profile.get_kernel_bootsplash():
592 newliloconf += "#"
593 newliloconf += "vga=788 # Framebuffer setting. Adjust to your own will\n"
594 newliloconf += "image=/boot"+kernel_name[0][5:]+" \n"
595 newliloconf += " label=gentoo \n read-only \n"
596 if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel":
597 newliloconf += " root="+self.root_device+self.root_minor+" \n"
598 if bootloader_kernel_args:
599 newliloconf += " append=\""+bootloader_kernel_args+"\" \n"
600 else:
601 newliloconf += " root=/dev/ram0 \n"
602 newliloconf += " append=\"init=/linuxrc ramdisk=8192 real_root="+self.root_device+self.root_minor + " " + bootloader_kernel_args + "\" \n"
603 newliloconf += " initrd=/boot"+kernel_name[1][5:] + "\n\n"
604 newliloconf = self._lilo_add_windows(newliloconf)
605 #now make the lilo.conf file
606 file_name = root + "/etc/lilo.conf"
607 try:
608 shutil.move(file_name, file_name + ".OLDdefault")
609 except:
610 pass
611 f = open(file_name, 'w')
612 f.writelines(newliloconf)
613 f.close()
614 self._logger.log("Lilo installed and configured. Not run yet.")
615
616 def _gather_lilo_drive_info(self):
617 self.boot_device = ""
618 self.boot_minor = ""
619 self.root_device = ""
620 self.root_minor = ""
621 self.mbr_device = ""
622 minornum = 0
623 #Assign root to the root mount point to make lines more readable
624 root = self._chroot_dir
625 self.foundboot = False
626 parts = self._install_profile.get_partition_tables()
627 for device in parts:
628 tmp_partitions = parts[device].get_install_profile_structure()
629 for partition in tmp_partitions:
630 mountpoint = tmp_partitions[partition]['mountpoint']
631 if (mountpoint == "/boot"):
632 self.foundboot = True
633 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
634 self.boot_minor = str(int(tmp_partitions[partition]['minor']))
635 self.boot_device = device
636 self.mbr_device = device
637 if mountpoint == "/":
638 self.root_minor = str(int(tmp_partitions[partition]['minor']))
639 self.root_device = device
640 #RESET the boot device if one is stored already
641 if self._install_profile.get_boot_device():
642 self.mbr_device = self._install_profile.get_boot_device()
643 self._logger.log("Found a mbr device: " + self.mbr_device)
644
645 def _lilo_add_windows(self, newliloconf):
646 parts = self._install_profile.get_partition_tables()
647 for device in parts:
648 tmp_partitions = parts[device].get_install_profile_structure()
649 for partition in tmp_partitions:
650 if (tmp_partitions[partition]['type'] == "fat32") or (tmp_partitions[partition]['type'] == "ntfs"):
651 newliloconf += "other="+device+str(int(tmp_partitions[partition]['minor']))+"\n"
652 newliloconf += "label=Windows_P"+str(int(tmp_partitions[partition]['minor']))+"\n\n"
653 return newliloconf
654
655 def _map_device_to_grub_device(self, device):
656 file_name = self._chroot_dir + "/boot/grub/glidevice.map"
657 #If we can't find it, make it. If we STILL can't find it. die.
658 if not GLIUtility.is_file(file_name):
659 exitstatus1 = GLIUtility.spawn("echo quit | "+ self._chroot_dir+"/sbin/grub --batch --no-floppy --device-map="+file_name, logfile=self._compile_logfile, append_log=True)
660 if not GLIUtility.is_file(file_name):
661 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error making the new device map.")
662 """
663 read the device map. sample looks like this:
664 (fd0) /dev/floppy/0
665 (hd0) /dev/sda
666 (hd1) /dev/hda
667 (hd2) /dev/hdb
668 """
669
670 # Search for the key
671 f = open(file_name) #open the device map
672 file = f.readlines()
673 f.close()
674 for i in range(len(file)):
675 if file[i][6:-1] == device:
676 return file[i][1:4]
677 raise GLIException("BootloaderError", 'fatal', '_map_device_to_grub_device', "ERROR, could not map"+device+" to anything in the device map")
678
679 def setup_and_run_bootloader(self):
680 bootloader_pkg = self._install_profile.get_boot_loader_pkg()
681 if bootloader_pkg.lower() == "none":
682 return
683 elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*'
684 self._setup_grub()
685 elif "lilo" in bootloader_pkg:
686 self._setup_lilo()
687 # probably should add in some more bootloaders
688 # dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload
689 else:
690 raise GLIException("BootLoaderError",'fatal','setup_and_run_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg)
691
692 def _setup_grub(self):
693 #-------------------------------------------------------------
694 #OK, now that the file is built. Install grub.
695 #cp /proc/mounts /etc/mtab
696 #grub-install --root-directory=/boot /dev/hda
697 #shutil.copy("/proc/mounts",root +"/etc/mtab")
698 self._gather_grub_drive_info()
699 grubinstallstring = "echo -en 'root ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
700 if not self._install_profile.get_boot_loader_mbr():
701 grubinstallstring +="setup ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
702 else:
703 grubinstallstring +="setup ("+self.grub_mbr_drive+")\n"
704 grubinstallstring += "quit\n' | "+self._chroot_dir+"/sbin/grub --batch --no-floppy"
705 if self._debug: self._logger.log("DEBUG: _configure_grub(): Grub install string: " + grubinstallstring)
706 exitstatus = GLIUtility.spawn(grubinstallstring, logfile=self._compile_logfile, append_log=True)
707 if not GLIUtility.exitsuccess(exitstatus):
708 raise GLIException("GrubInstallError", 'fatal', '_setup_grub', "Could not install grub!")
709 self._logger.log("Bootloader: grub has been installed!")
710
711 def _setup_lilo(self):
712 #-------------------------------------------------------------
713 #OK, now that the file is built. Install lilo.
714 exitstatus = GLIUtility.spawn("/sbin/lilo",chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
715 if exitstatus != 0:
716 raise GLIException("LiloInstallError", 'fatal', '_setup_lilo', "Running lilo failed!")
717 self._logger.log("Bootloader: lilo has been run/installed!")

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20