/[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 1396 - (show annotations) (download) (as text)
Fri Mar 31 01:10:57 2006 UTC (12 years, 7 months ago) by agaffney
Original Path: trunk/src/templates/x86ArchitectureTemplate.py
File MIME type: text/x-python
File size: 33901 byte(s)
check for origminor

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.129 2006/03/31 01:10:57 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 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 if not self._check_keeping_any_existing: wipe drive, use the default disklabel for arch, and jump to pass 3
316 if only formatting existing partitions, jump straight to pass 3
317 skip fixed partitions in all passes (in GLISD maybe?)
318 """
319 parts_old = {}
320 parts_new = self._install_profile.get_partition_tables()
321 for device in GLIStorageDevice.detect_devices():
322 parts_old[device] = GLIStorageDevice.Device(device, arch=self._client_configuration.get_architecture_template())
323 parts_old[device].set_partitions_from_disk()
324
325 self.notify_frontend("progress", (0, "Examining partitioning data"))
326 total_steps = float(len(parts_new) * 4) # 4 for the number of passes over each device
327 cur_progress = 0
328 for device in parts_new:
329 # Skip this device in parts_new if device isn't detected on current system
330 if not device in parts_old:
331 self._logger.log("There is no physical device " + device + " detected to match the entry in the install profile...skipping")
332 continue
333
334 # This just makes things simpler in the code
335 newparts = parts_new[device]
336 oldparts = parts_old[device]
337
338 # Check to see if the old and new partition table structures are the same...skip if they are
339 if not self._check_table_changed(oldparts, newparts):
340 self._logger.log("Partition table for " + device + " is unchanged...skipping")
341 continue
342
343 self._logger.log("partition(): Processing " + device + "...")
344
345 # Commit ritual sepuku if there are any mounted filesystems on this device
346 if GLIUtility.spawn("mount | grep '^" + device + "'", return_output=True)[1].strip():
347 raise GLIException("PartitionsMountedError", 'fatal', 'partition', "Cannot partition " + device + " due to filesystems being mounted")
348
349 # We also can't handle "unknown" partitions
350 for part in newparts:
351 if newparts[part]['type'] == "unknown":
352 raise GLIException("UnknownPartitionTypeError", 'fatal', 'partition', "Refusing to partition this drive due to the presence of an unknown type of partition")
353
354 # Create pyparted objects for this device
355 parted_dev = parted.PedDevice.get(device)
356 try:
357 parted_disk = parted.PedDisk.new(parted_dev)
358 except:
359 if self._debug: self._logger.log("partition(): could not load existing disklabel...creating new one")
360 parted_disk = parted_dev.disk_new_fresh(parted.disk_type_get((newparts.get_disklabel() or GLIStorageDevice.archinfo[self._architecture_name])))
361 device_sectors = parted_dev.length
362 # This will go away
363 new_part_list = parts_new[device].get_ordered_partition_list()
364
365 # Iterate through new partitions and check for 'origminor' and 'format' == False
366 for part in newparts:
367 tmppart_new = newparts[part]
368 if not tmppart_new['origminor'] or tmppart_new['format']: continue
369 if not tmppart_new['origminor'] in oldparts:
370 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.")
371 tmppart_old = oldparts[tmppart_new['origminor']]
372 if tmppart_new['resized']:
373 # Partition is being resized in the new layout
374 self._logger.log(" Partition " + str(part) + " has origminor " + str(tmppart_new['origminor']) + " and it being resized...saving start sector " + str(tmppart_old['start']))
375 tmppart_new['start'] = tmppart_old['start']
376 tmppart_new['end'] = 0
377 else:
378 # Partition is untouched in the new layout
379 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']))
380 tmppart_new['start'] = tmppart_old['start']
381 tmppart_new['end'] = tmppart_old['end']
382
383 if self._check_table_layout_changed(parts_old[device], parts_new[device]):
384 # First pass to delete old partitions that aren't resized
385 self.notify_frontend("progress", (cur_progress / total_steps, "Deleting partitioning that aren't being resized for " + device))
386 cur_progress += 1
387 self._partition_delete_step(parted_disk, oldparts, newparts)
388
389 # Second pass to resize old partitions that need to be resized
390 self._logger.log("Partitioning: Second pass...")
391 self.notify_frontend("progress", (cur_progress / total_steps, "Resizing remaining partitions for " + device))
392 cur_progress += 1
393 self._partition_resize_step(parted_disk, device, oldparts, newparts)
394
395 # Third pass to create new partition table
396 self._logger.log("Partitioning: Third pass....creating partitions")
397 self.notify_frontend("progress", (cur_progress / total_steps, "Recreating partition table for " + device))
398 cur_progress += 1
399 self._partition_recreate_step(parted_disk, newparts)
400 else:
401 cur_progress += 3
402
403 # Fourth pass to format partitions
404 self._logger.log("Partitioning: formatting partitions")
405 self.notify_frontend("progress", (cur_progress / total_steps, "Formatting partitions for " + device))
406 cur_progress += 1
407 self._partition_format_step(parted_disk, device, newparts)
408
409 # All done for this device
410 self.notify_frontend("progress", (cur_progress / total_steps, "Done with partitioning for " + device))
411 cur_progress += 1
412
413 def _configure_grub(self):
414 self.build_mode = self._install_profile.get_kernel_build_method()
415 self._gather_grub_drive_info()
416 root = self._chroot_dir
417 exitstatus2, kernel_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/kernel-*", return_output=True)
418 self._logger.log("Output of Kernel Names:\n"+kernel_names)
419 if not GLIUtility.exitsuccess(exitstatus2):
420 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the kernels in /boot")
421 if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
422 exitstatus3, initrd_names = GLIUtility.spawn("ls -1 --color=no " + root + "/boot/init*", return_output=True)
423 self._logger.log("Output of Initrd Names:\n"+initrd_names)
424 if not GLIUtility.exitsuccess(exitstatus3):
425 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error listing the initrds")
426 self._logger.log("Bootloader: the three information gathering commands have been run")
427
428 if not kernel_names[0]:
429 raise GLIException("BootloaderError", 'fatal', '_configure_grub',"Error: We have no kernel in /boot to put in the grub.conf file!")
430
431 #-------------------------------------------------------------
432 #OK, now that we have all the info, let's build that grub.conf
433 newgrubconf = ""
434 newgrubconf += "default 0\ntimeout 30\n"
435 if self.foundboot: #we have a /boot
436 newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/grub/splash.xpm.gz\n"
437 else: #we have / and /boot needs to be included
438 newgrubconf += "splashimage=(" + self.grub_boot_drive + "," + self.grub_boot_minor + ")/boot/grub/splash.xpm.gz\n"
439 if self._install_profile.get_bootloader_kernel_args():
440 bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
441 else: bootloader_kernel_args = ""
442
443 kernel_names = map(string.strip, kernel_names.strip().split("\n"))
444 initrd_names = map(string.strip, initrd_names.strip().split("\n"))
445 grub_kernel_name = kernel_names[-1].split(root)[-1]
446 if initrd_names: grub_initrd_name = initrd_names[-1].split(root)[-1]
447 # for i in range(len(kernel_names)):
448 # grub_kernel_name = kernel_names[i].split(root)[-1]
449 # for i in range(len(initrd_names)): #this should be okay if blank.
450 # grub_initrd_name = initrd_names[i].split(root)[-1]
451 #i think this means take the last one it finds.. i.e. the newest.
452
453 newgrubconf += "title=Gentoo Linux\n"
454 newgrubconf += "root (" + self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
455 if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel": #using CUSTOM kernel
456 if self.foundboot:
457 newgrubconf += "kernel " + grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
458 else:
459 newgrubconf += "kernel /boot"+ grub_kernel_name[5:] + " root="+self.root_device+self.root_minor+"\n"
460 else: #using genkernel so it has an initrd.
461 if self.foundboot:
462 newgrubconf += "kernel " + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
463 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
464 newgrubconf += "initrd " + grub_initrd_name[5:] + "\n"
465 else:
466 newgrubconf += "kernel /boot" + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
467 newgrubconf += self.root_device + self.root_minor + " " + bootloader_kernel_args + "\n"
468 newgrubconf += "initrd /boot" + grub_initrd_name[5:] + "\n"
469 newgrubconf = self._grub_add_windows(newgrubconf)
470 #now make the grub.conf file
471 file_name = root + "/boot/grub/grub.conf"
472 try:
473 shutil.move(file_name, file_name + ".OLDdefault")
474 except:
475 pass
476 f = open(file_name, 'w')
477 f.writelines(newgrubconf)
478 f.close()
479 self._logger.log("Grub installed and configured. Contents of grub.conf:\n"+newgrubconf)
480 self._logger.log("Grub has not yet been run. If a normal install, it will now be run.")
481
482 def _gather_grub_drive_info(self):
483 self.boot_minor = ""
484 self.boot_device = ""
485 self.root_device = ""
486 self.root_minor = ""
487 self.mbr_device = ""
488 self.grub_root_minor = ""
489 self.grub_boot_minor = ""
490 self.grub_boot_drive = ""
491 self.grub_root_drive = ""
492 self.grub_mbr_drive = ""
493 minornum = 0
494 #Assign root to the root mount point to make lines more readable
495 root = self._chroot_dir
496
497
498 self.foundboot = False
499 parts = self._install_profile.get_partition_tables()
500 for device in parts:
501 tmp_partitions = parts[device].get_install_profile_structure()
502 for partition in tmp_partitions:
503 mountpoint = tmp_partitions[partition]['mountpoint']
504 if (mountpoint == "/boot"):
505 self.foundboot = True
506 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
507 self.boot_minor = str(int(tmp_partitions[partition]['minor']))
508 self.grub_boot_minor = str(int(tmp_partitions[partition]['minor']) - 1)
509 self.boot_device = device
510 self.mbr_device = device
511 if mountpoint == "/":
512 self.root_minor = str(int(tmp_partitions[partition]['minor']))
513 self.grub_root_minor = str(int(tmp_partitions[partition]['minor']) - 1)
514 self.root_device = device
515 #RESET the boot device if one is stored already
516 if self._install_profile.get_boot_device():
517 self.mbr_device = self._install_profile.get_boot_device()
518 self._logger.log("Found a mbr device: " + self.mbr_device)
519
520 self.grub_boot_drive = self._map_device_to_grub_device(self.boot_device)
521 self.grub_root_drive = self._map_device_to_grub_device(self.root_device)
522 self.grub_mbr_drive = self._map_device_to_grub_device(self.mbr_device)
523
524 if (not self.grub_root_drive) or (not self.grub_boot_drive):
525 raise GLIException("BootloaderError", 'fatal', '_gather_grub_drive_info',"Couldn't find the drive num in the list from the device.map")
526
527 def _grub_add_windows(self, newgrubconf):
528 parts = self._install_profile.get_partition_tables()
529 for device in parts:
530 tmp_partitions = parts[device].get_install_profile_structure()
531 for partition in tmp_partitions:
532 if (tmp_partitions[partition]['type'] == "fat32") or (tmp_partitions[partition]['type'] == "ntfs"):
533 grub_dev = self._map_device_to_grub_device(device)
534 newgrubconf += "\ntitle=Possible Windows P"+str(int(tmp_partitions[partition]['minor']))+"\n"
535 newgrubconf += "rootnoverify ("+grub_dev+","+str(int(tmp_partitions[partition]['minor'] -1))+")\n"
536 newgrubconf += "makeactive\nchainloader +1\n\n"
537 return newgrubconf
538
539 def _configure_lilo(self):
540 self.build_mode = self._install_profile.get_kernel_build_method()
541 self._gather_lilo_drive_info()
542 root = self._chroot_dir
543 file_name3 = root + "/boot/kernel_name"
544 root = self._chroot_dir
545 exitstatus0 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3)
546 if (exitstatus0 != 0):
547 raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list kernels in /boot or no kernels found.")
548 if self.build_mode == "genkernel" or self._install_profile.get_kernel_source_pkg() == "livecd-kernel":
549 exitstatus1 = GLIUtility.spawn("ls "+root+"/boot/init* >> "+file_name3)
550 if (exitstatus1 != 0):
551 raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Could not list initrds in /boot")
552 g = open(file_name3)
553 kernel_name = g.readlines()
554 g.close()
555 if not kernel_name[0]:
556 raise GLIException("BootloaderError", 'fatal', '_configure_lilo',"Error: We have no kernel in /boot to put in the grub.conf file!")
557 kernel_name = map(string.strip, kernel_name)
558 kernel_name[0] = kernel_name[0].split(root)[1]
559 kernel_name[1] = kernel_name[1].split(root)[1]
560 if self._install_profile.get_bootloader_kernel_args(): bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args()
561 else: bootloader_kernel_args = ""
562 #-------------------------------------------------------------
563 #time to build the lilo.conf
564 newliloconf = ""
565 if self._install_profile.get_boot_loader_mbr():
566 newliloconf += "boot="+self.mbr_device+" # Install LILO in the MBR \n"
567 else:
568 newliloconf += "boot="+self.boot_device+self.boot_minor+" # Install LILO in the MBR \n"
569 newliloconf += "prompt # Give the user the chance to select another section\n"
570 newliloconf += "timeout=50 # Wait 5 (five) seconds before booting the default section\n"
571 newliloconf += "default=gentoo # When the timeout has passed, boot the \"gentoo\" section\n"
572 newliloconf += "# Only if you use framebuffer. Otherwise remove the following line:\n"
573 if not self._install_profile.get_kernel_bootsplash():
574 newliloconf += "#"
575 newliloconf += "vga=788 # Framebuffer setting. Adjust to your own will\n"
576 newliloconf += "image=/boot"+kernel_name[0][5:]+" \n"
577 newliloconf += " label=gentoo \n read-only \n"
578 if self.build_mode != "genkernel" and self._install_profile.get_kernel_source_pkg() != "livecd-kernel":
579 newliloconf += " root="+self.root_device+self.root_minor+" \n"
580 if bootloader_kernel_args:
581 newliloconf += " append=\""+bootloader_kernel_args+"\" \n"
582 else:
583 newliloconf += " root=/dev/ram0 \n"
584 newliloconf += " append=\"init=/linuxrc ramdisk=8192 real_root="+self.root_device+self.root_minor + " " + bootloader_kernel_args + "\" \n"
585 newliloconf += " initrd=/boot"+kernel_name[1][5:] + "\n\n"
586 newliloconf = self._lilo_add_windows(newliloconf)
587 #now make the lilo.conf file
588 file_name = root + "/etc/lilo.conf"
589 try:
590 shutil.move(file_name, file_name + ".OLDdefault")
591 except:
592 pass
593 f = open(file_name, 'w')
594 f.writelines(newliloconf)
595 f.close()
596 self._logger.log("Lilo installed and configured. Not run yet.")
597
598 def _gather_lilo_drive_info(self):
599 self.boot_device = ""
600 self.boot_minor = ""
601 self.root_device = ""
602 self.root_minor = ""
603 self.mbr_device = ""
604 minornum = 0
605 #Assign root to the root mount point to make lines more readable
606 root = self._chroot_dir
607 self.foundboot = False
608 parts = self._install_profile.get_partition_tables()
609 for device in parts:
610 tmp_partitions = parts[device].get_install_profile_structure()
611 for partition in tmp_partitions:
612 mountpoint = tmp_partitions[partition]['mountpoint']
613 if (mountpoint == "/boot"):
614 self.foundboot = True
615 if (( (mountpoint == "/") and (not self.foundboot) ) or (mountpoint == "/boot")):
616 self.boot_minor = str(int(tmp_partitions[partition]['minor']))
617 self.boot_device = device
618 self.mbr_device = device
619 if mountpoint == "/":
620 self.root_minor = str(int(tmp_partitions[partition]['minor']))
621 self.root_device = device
622 #RESET the boot device if one is stored already
623 if self._install_profile.get_boot_device():
624 self.mbr_device = self._install_profile.get_boot_device()
625 self._logger.log("Found a mbr device: " + self.mbr_device)
626
627 def _lilo_add_windows(self, newliloconf):
628 parts = self._install_profile.get_partition_tables()
629 for device in parts:
630 tmp_partitions = parts[device].get_install_profile_structure()
631 for partition in tmp_partitions:
632 if (tmp_partitions[partition]['type'] == "fat32") or (tmp_partitions[partition]['type'] == "ntfs"):
633 newliloconf += "other="+device+str(int(tmp_partitions[partition]['minor']))+"\n"
634 newliloconf += "label=Windows_P"+str(int(tmp_partitions[partition]['minor']))+"\n\n"
635 return newliloconf
636
637 def _map_device_to_grub_device(self, device):
638 file_name = self._chroot_dir + "/boot/grub/glidevice.map"
639 #If we can't find it, make it. If we STILL can't find it. die.
640 if not GLIUtility.is_file(file_name):
641 exitstatus1 = GLIUtility.spawn("echo quit | "+ self._chroot_dir+"/sbin/grub --batch --no-floppy --device-map="+file_name, logfile=self._compile_logfile, append_log=True)
642 if not GLIUtility.is_file(file_name):
643 raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error making the new device map.")
644 """
645 read the device map. sample looks like this:
646 (fd0) /dev/floppy/0
647 (hd0) /dev/sda
648 (hd1) /dev/hda
649 (hd2) /dev/hdb
650 """
651
652 # Search for the key
653 f = open(file_name) #open the device map
654 file = f.readlines()
655 f.close()
656 for i in range(len(file)):
657 if file[i][6:-1] == device:
658 return file[i][1:4]
659 raise GLIException("BootloaderError", 'fatal', '_map_device_to_grub_device', "ERROR, could not map"+device+" to anything in the device map")
660
661 def setup_and_run_bootloader(self):
662 bootloader_pkg = self._install_profile.get_boot_loader_pkg()
663 if bootloader_pkg.lower() == "none":
664 return
665 elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*'
666 self._setup_grub()
667 elif "lilo" in bootloader_pkg:
668 self._setup_lilo()
669 # probably should add in some more bootloaders
670 # dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload
671 else:
672 raise GLIException("BootLoaderError",'fatal','setup_and_run_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg)
673
674 def _setup_grub(self):
675 #-------------------------------------------------------------
676 #OK, now that the file is built. Install grub.
677 #cp /proc/mounts /etc/mtab
678 #grub-install --root-directory=/boot /dev/hda
679 #shutil.copy("/proc/mounts",root +"/etc/mtab")
680 self._gather_grub_drive_info()
681 grubinstallstring = "echo -en 'root ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
682 if not self._install_profile.get_boot_loader_mbr():
683 grubinstallstring +="setup ("+self.grub_boot_drive + "," + self.grub_boot_minor + ")\n"
684 else:
685 grubinstallstring +="setup ("+self.grub_mbr_drive+")\n"
686 grubinstallstring += "quit\n' | "+self._chroot_dir+"/sbin/grub --batch --no-floppy"
687 if self._debug: self._logger.log("DEBUG: _configure_grub(): Grub install string: " + grubinstallstring)
688 exitstatus = GLIUtility.spawn(grubinstallstring, logfile=self._compile_logfile, append_log=True)
689 if not GLIUtility.exitsuccess(exitstatus):
690 raise GLIException("GrubInstallError", 'fatal', '_setup_grub', "Could not install grub!")
691 self._logger.log("Bootloader: grub has been installed!")
692
693 def _setup_lilo(self):
694 #-------------------------------------------------------------
695 #OK, now that the file is built. Install lilo.
696 exitstatus = GLIUtility.spawn("/sbin/lilo",chroot=self._chroot_dir, logfile=self._compile_logfile, append_log=True)
697 if exitstatus != 0:
698 raise GLIException("LiloInstallError", 'fatal', '_setup_lilo', "Running lilo failed!")
699 self._logger.log("Bootloader: lilo has been run/installed!")

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20