/[gli]/trunk/src/templates/x86ArchitectureTemplate.py
Gentoo

Contents of /trunk/src/templates/x86ArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20