/[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 1404 - (show annotations) (download) (as text)
Sun Apr 2 19:10:54 2006 UTC (12 years, 3 months ago) by agaffney
Original Path: trunk/src/templates/x86ArchitectureTemplate.py
File MIME type: text/x-python
File size: 33989 byte(s)
more minor changes for new partitioning code

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20