| 1 |
samyron |
148 |
""" |
| 2 |
|
|
Gentoo Linux Installer |
| 3 |
|
|
|
| 4 |
robbat2 |
740 |
$Id: x86ArchitectureTemplate.py,v 1.52 2005/07/07 07:58:15 robbat2 Exp $ |
| 5 |
samyron |
148 |
Copyright 2004 Gentoo Technologies Inc. |
| 6 |
|
|
|
| 7 |
|
|
|
| 8 |
|
|
This fills in x86 specific functions. |
| 9 |
|
|
""" |
| 10 |
|
|
|
| 11 |
codeman |
730 |
import GLIUtility, string, time |
| 12 |
samyron |
148 |
from GLIArchitectureTemplate import ArchitectureTemplate |
| 13 |
|
|
from GLIException import * |
| 14 |
agaffney |
225 |
import parted |
| 15 |
agaffney |
497 |
import GLIStorageDevice |
| 16 |
robbat2 |
651 |
|
| 17 |
|
|
MEGABYTE = 1024 * 1024 |
| 18 |
samyron |
148 |
|
| 19 |
|
|
class x86ArchitectureTemplate(ArchitectureTemplate): |
| 20 |
agaffney |
497 |
def __init__(self,configuration=None, install_profile=None, client_controller=None): |
| 21 |
samyron |
148 |
ArchitectureTemplate.__init__(self, configuration, install_profile, client_controller) |
| 22 |
|
|
self._architecture_name = 'x86' |
| 23 |
codeman |
282 |
self._kernel_bzimage = "arch/i386/boot/bzImage" |
| 24 |
samyron |
148 |
|
| 25 |
codeman |
201 |
def install_bootloader(self): |
| 26 |
|
|
"Installs and configures bootloader" |
| 27 |
|
|
# |
| 28 |
|
|
# THIS IS ARCHITECTURE DEPENDANT!!! |
| 29 |
|
|
# This is the x86 way.. it uses grub |
| 30 |
robbat2 |
740 |
|
| 31 |
|
|
bootloader_pkg = self._install_profile.get_boot_loader_pkg() |
| 32 |
|
|
|
| 33 |
|
|
# first install bootloader |
| 34 |
|
|
if bootloader_pkg and bootloader_pkg.lower() != "none": |
| 35 |
|
|
exitstatus = self._emerge(bootloader_pkg) |
| 36 |
codeman |
201 |
if exitstatus != 0: |
| 37 |
|
|
raise GLIException("BootLoaderEmergeError", 'fatal', 'install_bootloader', "Could not emerge bootloader!") |
| 38 |
robbat2 |
740 |
else: |
| 39 |
|
|
self._logger.log("Emerged the selected bootloader.") |
| 40 |
codeman |
201 |
|
| 41 |
robbat2 |
740 |
# now configure said bootloader |
| 42 |
|
|
# null boot-loader first |
| 43 |
|
|
if bootloader_pkg.lower() == "none": |
| 44 |
|
|
return |
| 45 |
|
|
elif "grub" in bootloader_pkg: # this catches 'grub-static' as well as '=sys-boot/grub-0.95*' |
| 46 |
|
|
self._configure_grub() |
| 47 |
|
|
elif "lilo" in bootloader_pkg: |
| 48 |
|
|
self._configure_lilo() |
| 49 |
|
|
# probably should add in some more bootloaders |
| 50 |
|
|
# dvhtool, raincoat, netboot, gnu-efi, cromwell, syslinux, psoload |
| 51 |
codeman |
201 |
else: |
| 52 |
robbat2 |
740 |
raise GLIException("BootLoaderError",'fatal','install_bootloader',"Don't know how to configure this bootloader: "+bootloader_pkg) |
| 53 |
codeman |
201 |
|
| 54 |
agaffney |
220 |
def _sectors_to_megabytes(self, sectors, sector_bytes=512): |
| 55 |
robbat2 |
651 |
return float((float(sectors) * sector_bytes)/ float(MEGABYTE)) |
| 56 |
agaffney |
220 |
|
| 57 |
agaffney |
225 |
def _add_partition(self, disk, start, end, type, fs): |
| 58 |
|
|
types = { 'primary': parted.PARTITION_PRIMARY, 'extended': parted.PARTITION_EXTENDED, 'logical': parted.PARTITION_LOGICAL } |
| 59 |
|
|
fsTypes = {} |
| 60 |
|
|
fs_type = parted.file_system_type_get_next () |
| 61 |
|
|
while fs_type: |
| 62 |
|
|
fsTypes[fs_type.name] = fs_type |
| 63 |
|
|
fs_type = parted.file_system_type_get_next (fs_type) |
| 64 |
|
|
fstype = None |
| 65 |
|
|
if fs: fstype = fsTypes[fs] |
| 66 |
|
|
newpart = disk.partition_new(types[type], fstype, start, end) |
| 67 |
|
|
constraint = disk.dev.constraint_any() |
| 68 |
|
|
disk.add_partition(newpart, constraint) |
| 69 |
agaffney |
220 |
|
| 70 |
agaffney |
225 |
def partition(self): |
| 71 |
agaffney |
220 |
parts_old = {} |
| 72 |
agaffney |
596 |
tmp_parts_new = self._install_profile.get_partition_tables() |
| 73 |
|
|
parts_new = {} |
| 74 |
|
|
for device in tmp_parts_new: |
| 75 |
|
|
parts_new[device] = tmp_parts_new[device].get_install_profile_structure() |
| 76 |
agaffney |
497 |
detected_devices = GLIStorageDevice.detect_devices() |
| 77 |
|
|
for device in detected_devices: |
| 78 |
|
|
tmpdevice = GLIStorageDevice.Device(device) |
| 79 |
|
|
tmpdevice.set_partitions_from_disk() |
| 80 |
|
|
parts_old[device] = tmpdevice.get_install_profile_structure() |
| 81 |
agaffney |
220 |
|
| 82 |
agaffney |
497 |
for device in parts_new.keys(): |
| 83 |
|
|
# Skip this device in parts_new if device isn't detected on current system |
| 84 |
|
|
if not device in detected_devices: |
| 85 |
|
|
self._logger.log("There is no physical device " + device + " detected to match the entry in the install profile...skipping") |
| 86 |
agaffney |
225 |
continue |
| 87 |
agaffney |
497 |
|
| 88 |
|
|
# Check to see if the old and new partition table structures are the same |
| 89 |
|
|
table_changed = 0 |
| 90 |
|
|
for part in parts_new[device]: |
| 91 |
agaffney |
501 |
if not part in parts_old[device]: |
| 92 |
|
|
table_changed = 1 |
| 93 |
|
|
break |
| 94 |
agaffney |
497 |
oldpart = parts_old[device][part] |
| 95 |
|
|
newpart = parts_new[device][part] |
| 96 |
|
|
if oldpart['type'] == newpart['type'] and oldpart['start'] == newpart['start'] and oldpart['end'] == newpart['end'] and newpart['format'] == False: |
| 97 |
agaffney |
377 |
continue |
| 98 |
agaffney |
497 |
else: |
| 99 |
|
|
table_changed = 1 |
| 100 |
|
|
break |
| 101 |
|
|
# Skip this device if they are they same |
| 102 |
|
|
if not table_changed: |
| 103 |
|
|
self._logger.log("Partition table for " + device + " is unchanged...skipping") |
| 104 |
|
|
continue |
| 105 |
|
|
|
| 106 |
|
|
# Create pyparted objects for this device |
| 107 |
|
|
parted_dev = parted.PedDevice.get(device) |
| 108 |
agaffney |
691 |
try: |
| 109 |
|
|
parted_disk = parted.PedDisk.new(parted_dev) |
| 110 |
|
|
except: |
| 111 |
|
|
parted_disk = parted_dev.disk_new_fresh(parted.disk_type_get((tmp_parts_new[device].get_disklabel() or GLIStorageDevice.archinfo[self._architecture_name]['disklabel']))) |
| 112 |
agaffney |
497 |
new_part_list = parts_new[device].keys() |
| 113 |
|
|
new_part_list.sort() |
| 114 |
|
|
device_sectors = parted_dev.length |
| 115 |
|
|
|
| 116 |
|
|
# Iterate through new partitions and check for 'origminor' and 'format' == False |
| 117 |
|
|
for part in parts_new[device].keys(): |
| 118 |
|
|
tmppart_new = parts_new[device][part] |
| 119 |
|
|
if not tmppart_new['origminor'] or tmppart_new['format']: continue |
| 120 |
agaffney |
498 |
tmppart_old = parts_old[device][tmppart_new['origminor']] |
| 121 |
agaffney |
497 |
# This partition in parts_new corresponds with an existing partitions, so we save the start/end sector and flags |
| 122 |
|
|
for flag in range(0, 10): |
| 123 |
|
|
# The 10 is completely arbitrary. If flags seem to be missed, this number should be increased |
| 124 |
|
|
parted_part = parted_disk.get_partition(part) |
| 125 |
|
|
if not parted_part: break |
| 126 |
|
|
if parted_part.is_flag_available(flag) and parted_part.get_flag(flag): |
| 127 |
|
|
if not "flags" in tmppart_new: tmppart_new['flags'] = [] |
| 128 |
|
|
tmppart_new['flags'].append(flag) |
| 129 |
|
|
if tmppart_old['mb'] == tmppart_new['mb']: |
| 130 |
|
|
tmppart_new['start'] = tmppart_old['start'] |
| 131 |
|
|
tmppart_new['end'] = tmppart_old['end'] |
| 132 |
|
|
else: |
| 133 |
|
|
tmppart_new['start'] = tmppart_old['start'] |
| 134 |
|
|
tmppart_new['end'] = 0 |
| 135 |
|
|
|
| 136 |
|
|
# if parts_new[dev][parts_new[dev].keys()[0]]['mb']: |
| 137 |
|
|
# # Change MB/%/* into sectors |
| 138 |
|
|
# total_sectors = parted_dev.length |
| 139 |
|
|
# sector_size = parted_dev.sector_size |
| 140 |
|
|
# total_mb = float(total_sectors * sector_size) / MEGABYTE |
| 141 |
|
|
# start_sector = 0 |
| 142 |
|
|
# mb_left = total_mb |
| 143 |
|
|
# for part in parts_new[dev]: |
| 144 |
|
|
# tmppart = parts_new[dev][part] |
| 145 |
|
|
# if tmppart['type'] == "extended": continue |
| 146 |
|
|
# if tmppart['mb'][-1] == "%": |
| 147 |
|
|
# tmppart['mb'] = float(tmppart['mb'][:-1]) / 100 * total_mb |
| 148 |
|
|
# mb_left = mb_left - float(tmppart['mb']) |
| 149 |
|
|
# partlist = parts_new.keys() |
| 150 |
|
|
# partlist.sort() |
| 151 |
|
|
# for part in partlist: |
| 152 |
|
|
# if part > 4: continue |
| 153 |
|
|
# tmppart = parts_new[dev][part] |
| 154 |
|
|
# if tmppart['type'] == "extended": |
| 155 |
|
|
# for part_log in partlist: |
| 156 |
|
|
# if part < 5: continue |
| 157 |
|
|
# tmppart_log = parts_new[dev][part_log] |
| 158 |
|
|
# if not tmppart['start']: |
| 159 |
|
|
# tmppart['start'] = start_sector |
| 160 |
|
|
# if tmppart_log['mb'] == "*": |
| 161 |
|
|
# tmppart_log['mb'] = mb_left |
| 162 |
agaffney |
639 |
# part_bytes = long(tmppart_log['mb'] * MEGABYTE) |
| 163 |
agaffney |
497 |
# part_sectors = round(part_bytes / sector_size) |
| 164 |
|
|
# tmppart_log['start'] = start_sector |
| 165 |
|
|
# tmppart_log['end'] = start_sector + part_sectors - 1 |
| 166 |
|
|
# tmppart['end'] = tmppart_log['end'] |
| 167 |
|
|
# start_sector = start_sector + part_sectors |
| 168 |
|
|
# continue |
| 169 |
|
|
# if tmppart['mb'] == "*": |
| 170 |
|
|
# tmppart['mb'] = mb_left |
| 171 |
agaffney |
639 |
# part_bytes = long(tmppart['mb'] * MEGABYTE) |
| 172 |
agaffney |
497 |
# part_sectors = round(part_bytes / sector_size) |
| 173 |
|
|
# tmppart['start'] = start_sector |
| 174 |
|
|
# tmppart['end'] = start_sector + part_sectors - 1 |
| 175 |
|
|
# start_sector = start_sector + part_sectors |
| 176 |
|
|
# else: |
| 177 |
|
|
|
| 178 |
agaffney |
220 |
# First pass to delete old partitions that aren't resized |
| 179 |
agaffney |
497 |
self._logger.log("partitioning: Processing " + device + "...") |
| 180 |
|
|
for part in parts_old[device]: |
| 181 |
|
|
oldpart = parts_old[device][part] |
| 182 |
|
|
# Replace 'x86' with call function to get arch from CC |
| 183 |
|
|
if (GLIStorageDevice.archinfo['x86']['extended'] and part > 4) or oldpart['type'] == "free": continue |
| 184 |
agaffney |
278 |
delete = 0 |
| 185 |
agaffney |
228 |
if oldpart['type'] == "extended": |
| 186 |
|
|
logical_to_resize = 0 |
| 187 |
agaffney |
497 |
for part_log in parts_old[device]: |
| 188 |
|
|
if part_log < 5 or parts_old[device][part_log]['type'] == "free": continue |
| 189 |
agaffney |
278 |
delete_log = 0 |
| 190 |
agaffney |
497 |
for new_part in parts_new[device]: |
| 191 |
agaffney |
228 |
if new_part < 5: continue |
| 192 |
agaffney |
497 |
tmppart = parts_new[device][new_part] |
| 193 |
|
|
# This partition is unchanged in the new layout |
| 194 |
|
|
if tmppart['origminor'] == part_log and tmppart['start'] and tmppart['end']: |
| 195 |
codeman |
427 |
self._logger.log(" Deleting old minor " + str(part_log) + " to be recreated later") |
| 196 |
agaffney |
278 |
delete_log = 1 |
| 197 |
agaffney |
228 |
break |
| 198 |
agaffney |
497 |
# This partition is resized with the data preserved in the new layout |
| 199 |
|
|
if tmppart['origminor'] == part_log and tmppart['start'] and not tmppart['end']: |
| 200 |
codeman |
427 |
self._logger.log(" Ignoring old minor " + str(part_log) + " to resize later") |
| 201 |
agaffney |
278 |
logical_to_resize = 1 |
| 202 |
agaffney |
228 |
break |
| 203 |
agaffney |
497 |
if delete_log: |
| 204 |
codeman |
427 |
self._logger.log(" No match found...deleting partition " + str(part_log)) |
| 205 |
agaffney |
228 |
parted_disk.delete_partition(parted_disk.get_partition(part_log)) |
| 206 |
|
|
if not logical_to_resize: |
| 207 |
agaffney |
497 |
self._logger.log(" Deleting extended partition with minor " + str(part)) |
| 208 |
agaffney |
228 |
parted_disk.delete_partition(parted_disk.get_partition(part)) |
| 209 |
|
|
continue |
| 210 |
agaffney |
497 |
for new_part in parts_new[device]: |
| 211 |
|
|
tmppart = parts_new[device][new_part] |
| 212 |
|
|
if tmppart['origminor'] == part and tmppart['start'] and tmppart['end']: |
| 213 |
codeman |
427 |
self._logger.log(" Deleting old minor " + str(part) + " to be recreated later") |
| 214 |
agaffney |
278 |
delete = 1 |
| 215 |
agaffney |
220 |
break |
| 216 |
agaffney |
497 |
if tmppart['origminor'] == part and tmppart['start'] and not tmppart['end']: |
| 217 |
codeman |
427 |
self._logger.log(" Ignoring old minor " + str(part) + " to resize later") |
| 218 |
agaffney |
220 |
break |
| 219 |
agaffney |
497 |
if delete: |
| 220 |
codeman |
427 |
self._logger.log(" No match found...deleting partition " + str(part)) |
| 221 |
agaffney |
225 |
parted_disk.delete_partition(parted_disk.get_partition(part)) |
| 222 |
|
|
parted_disk.commit() |
| 223 |
agaffney |
497 |
|
| 224 |
agaffney |
220 |
# Second pass to resize old partitions that need to be resized |
| 225 |
codeman |
427 |
self._logger.log("Partitioning: Second pass...") |
| 226 |
agaffney |
497 |
for part in parts_old[device]: |
| 227 |
|
|
oldpart = parts_old[device][part] |
| 228 |
|
|
for new_part in parts_new[device]: |
| 229 |
|
|
tmppart = parts_new[device][new_part] |
| 230 |
|
|
if tmppart['origminor'] == part and tmppart['start'] and not tmppart['end']: |
| 231 |
codeman |
427 |
self._logger.log(" Resizing old minor " + str(part) + " from " + str(oldpart['start']) + "-" + str(oldpart['end'])+ " to " + str(tmppart['start']) + "-" + str(tmppart['end'])) |
| 232 |
agaffney |
220 |
type = tmppart['type'] |
| 233 |
|
|
minor = part |
| 234 |
agaffney |
230 |
start = tmppart['start'] |
| 235 |
agaffney |
497 |
# Replace 512 with code to retrieve bytes per sector for device |
| 236 |
agaffney |
639 |
end = start + (long(tmppart['mb']) * MEGABYTE / 512) |
| 237 |
agaffney |
497 |
for i in new_part_list: |
| 238 |
|
|
if i <= new_part: continue |
| 239 |
|
|
if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']: |
| 240 |
|
|
end = parts_new[device][i]['start'] - 1 |
| 241 |
|
|
elif end >= device_sectors: |
| 242 |
|
|
end = device_sectors - 1 |
| 243 |
|
|
break |
| 244 |
agaffney |
220 |
if type == "ext2" or type == "ext3": |
| 245 |
|
|
total_sectors = end - start + 1 |
| 246 |
agaffney |
231 |
ret = GLIUtility.spawn("resize2fs " + device + str(minor) + " " + str(total_sectors) + "s") |
| 247 |
|
|
if ret: # Resize error |
| 248 |
agaffney |
497 |
raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor)) |
| 249 |
agaffney |
220 |
elif type == "ntfs": |
| 250 |
|
|
total_sectors = end - start + 1 |
| 251 |
agaffney |
639 |
total_bytes = long(total_sectors) * 512 |
| 252 |
agaffney |
231 |
ret = GLIUtility.spawn("ntfsresize --size " + str(total_bytes) + " " + device + str(minor)) |
| 253 |
|
|
if ret: # Resize error |
| 254 |
agaffney |
497 |
raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor)) |
| 255 |
|
|
elif type == "linux-swap" or type == "fat32": |
| 256 |
agaffney |
230 |
parted_fs = parted_disk.get_partition(part).geom.file_system_open() |
| 257 |
|
|
resize_constraint = parted_fs.get_resize_constraint() |
| 258 |
|
|
if end < (start + resize_constraint.min_size) or start != resize_constraint.start_range.start: |
| 259 |
agaffney |
497 |
raise GLIException("PartitionError", 'fatal', 'partition', "New size specified for " + device + str(minor) + " is not within allowed boundaries") |
| 260 |
agaffney |
230 |
new_geom = resize_constraint.start_range.duplicate() |
| 261 |
|
|
new_geom.set_start(start) |
| 262 |
|
|
new_geom.set_end(end) |
| 263 |
agaffney |
231 |
try: |
| 264 |
|
|
parted_fs.resize(new_geom) |
| 265 |
|
|
except: |
| 266 |
agaffney |
497 |
raise GLIException("PartitionResizeError", 'fatal', 'partition', "could not resize " + device + str(minor)) |
| 267 |
codeman |
427 |
self._logger.log(" Deleting old minor " + str(part) + " to be recreated in 3rd pass") |
| 268 |
agaffney |
225 |
parted_disk.delete_partition(parted_disk.get_partition(part)) |
| 269 |
agaffney |
220 |
break |
| 270 |
agaffney |
229 |
parted_disk.delete_all() |
| 271 |
agaffney |
225 |
parted_disk.commit() |
| 272 |
agaffney |
497 |
|
| 273 |
agaffney |
220 |
# Third pass to create new partition table |
| 274 |
agaffney |
497 |
self._logger.log("Partitioning: Third pass....creating partitions") |
| 275 |
|
|
start = 0 |
| 276 |
agaffney |
507 |
end = 0 |
| 277 |
agaffney |
506 |
extended_start = 0 |
| 278 |
agaffney |
497 |
extended_end = 0 |
| 279 |
agaffney |
501 |
self._logger.log(" Drive has " + str(device_sectors) + " sectors") |
| 280 |
agaffney |
506 |
# for part in parts_new[device]: |
| 281 |
|
|
for part in new_part_list: |
| 282 |
agaffney |
497 |
newpart = parts_new[device][part] |
| 283 |
agaffney |
501 |
self._logger.log(" Partition " + str(part) + " has " + str(newpart['mb']) + "MB") |
| 284 |
agaffney |
639 |
part_sectors = long(newpart['mb']) * MEGABYTE / 512 |
| 285 |
agaffney |
507 |
end = start + part_sectors |
| 286 |
agaffney |
497 |
for i in new_part_list: |
| 287 |
|
|
if i <= part: continue |
| 288 |
|
|
if parts_new[device][i]['start'] and end >= parts_new[device][i]['start']: |
| 289 |
|
|
end = parts_new[device][i]['start'] - 1 |
| 290 |
|
|
break |
| 291 |
agaffney |
639 |
# cap to end of device |
| 292 |
agaffney |
503 |
if end >= device_sectors: |
| 293 |
|
|
end = device_sectors - 1 |
| 294 |
agaffney |
639 |
# now the actual creation |
| 295 |
agaffney |
497 |
if newpart['type'] == "free": |
| 296 |
|
|
# Nothing to be done for this type |
| 297 |
|
|
pass |
| 298 |
|
|
elif newpart['type'] == "extended": |
| 299 |
agaffney |
501 |
self._logger.log(" Adding extended partition " + str(part) + " from " + str(start) + " to " + str(end)) |
| 300 |
|
|
self._add_partition(parted_disk, start, end, "extended", "") |
| 301 |
agaffney |
506 |
extended_start = start |
| 302 |
|
|
extended_end = end |
| 303 |
agaffney |
505 |
elif part < 5 or not GLIStorageDevice.archinfo['x86']['extended']: |
| 304 |
agaffney |
501 |
self._logger.log(" Adding primary partition " + str(part) + " from " + str(start) + " to " + str(end)) |
| 305 |
|
|
self._add_partition(parted_disk, start, end, "primary", newpart['type']) |
| 306 |
agaffney |
497 |
elif GLIStorageDevice.archinfo['x86']['extended'] and part > 4: |
| 307 |
agaffney |
506 |
if start >= extended_end: |
| 308 |
|
|
start = extended_start + 1 |
| 309 |
agaffney |
507 |
end = start + part_sectors |
| 310 |
agaffney |
497 |
if part == new_part_list[-1] and end > extended_end: |
| 311 |
|
|
end = extended_end |
| 312 |
agaffney |
508 |
self._logger.log(" Adding logical partition " + str(part) + " from " + str(start) + " to " + str(end)) |
| 313 |
agaffney |
501 |
self._add_partition(parted_disk, start, end, "logical", newpart['type']) |
| 314 |
agaffney |
497 |
if "flags" in newpart: |
| 315 |
agaffney |
589 |
for flag in newpart['flags']: |
| 316 |
|
|
if parted_disk.get_partition(part).is_flag_available(flag): |
| 317 |
|
|
parted_disk.get_partition(part).set_flag(flag) |
| 318 |
agaffney |
639 |
# write to disk |
| 319 |
agaffney |
264 |
parted_disk.commit() |
| 320 |
robbat2 |
740 |
|
| 321 |
|
|
# force rescan of partition table |
| 322 |
|
|
# Should not be needed with current stuff |
| 323 |
|
|
#ret = GLIUtility.spawn("partprobe "+device, logfile=self._compile_logfile, append_log=True) |
| 324 |
|
|
|
| 325 |
agaffney |
639 |
# now format the partition |
| 326 |
agaffney |
691 |
# extended and 'free' partitions should never be formatted |
| 327 |
|
|
if newpart['format'] and newpart['type'] not in ('extended', 'free'): |
| 328 |
agaffney |
724 |
devnode = device + str(int(part)) |
| 329 |
robbat2 |
648 |
errormsg = "could't create %s filesystem on %s" % (newpart['type'],devnode) |
| 330 |
|
|
# if you need a special command and |
| 331 |
robbat2 |
649 |
# some base options, place it here. |
| 332 |
|
|
if newpart['type'] == 'linux-swap': |
| 333 |
|
|
cmdname = 'mkswap' |
| 334 |
|
|
elif newpart['type'] == 'fat32': |
| 335 |
|
|
cmdname = 'mkfs.vfat -F 32' |
| 336 |
|
|
elif newpart['type'] == 'ntfs': |
| 337 |
|
|
cmdname = 'mkntfs' |
| 338 |
|
|
# All of these types need a -f as they |
| 339 |
|
|
# ask for confirmation of format |
| 340 |
|
|
elif newpart['type'] in ('xfs','jfs','reiserfs'): |
| 341 |
|
|
cmdname = 'mkfs.%s -f' % (newpart['type']) |
| 342 |
|
|
# add common partition stuff here |
| 343 |
|
|
elif newpart['type'] in ('ext2','ext3'): |
| 344 |
|
|
cmdname = 'mkfs.%s' % (newpart['type']) |
| 345 |
robbat2 |
648 |
else: # this should catch everything else |
| 346 |
robbat2 |
649 |
raise GLIException("PartitionFormatError", 'fatal', 'partition',"Unknown partition type "+newpart['type']) |
| 347 |
codeman |
730 |
#TEMP UGLY HACK!!! Command executes before the filesystem has time to update to show the new device. Must sleep |
| 348 |
|
|
time.sleep(5) |
| 349 |
robbat2 |
648 |
# now the actual command |
| 350 |
|
|
cmd = "%s %s %s" % (cmdname,newpart['mkfsopts'],devnode) |
| 351 |
|
|
self._logger.log(" Formatting partition %s as %s with: %s" % (str(part),newpart['type'],cmd)) |
| 352 |
|
|
# If logging is not done, then you get errors: |
| 353 |
|
|
# PartitionFormatError :FATAL: partition: could't create ext2 filesystem on /dev/hda1 |
| 354 |
|
|
#if GLIUtility.spawn(cmd): |
| 355 |
|
|
#if GLIUtility.spawn(cmd,append_log=True,logfile='/var/log/install-mkfs.log'): |
| 356 |
codeman |
725 |
ret = GLIUtility.spawn(cmd, logfile=self._compile_logfile, append_log=True) |
| 357 |
agaffney |
724 |
if not GLIUtility.exitsuccess(ret): |
| 358 |
robbat2 |
648 |
raise GLIException("PartitionFormatError", 'fatal', 'partition', errormsg) |
| 359 |
agaffney |
501 |
start = end + 1 |
| 360 |
agaffney |
264 |
|
| 361 |
robbat2 |
740 |
def _configure_grub(self): |
| 362 |
codeman |
734 |
build_mode = self._install_profile.get_kernel_build_method() |
| 363 |
codeman |
235 |
boot_device = "" |
| 364 |
|
|
boot_minor = "" |
| 365 |
|
|
root_device = "" |
| 366 |
|
|
root_minor = "" |
| 367 |
|
|
grub_root_minor = "" |
| 368 |
|
|
grub_boot_minor = "" |
| 369 |
|
|
grub_boot_drive = "" |
| 370 |
|
|
grub_root_drive = "" |
| 371 |
|
|
minornum = 0 |
| 372 |
|
|
#Assign root to the root mount point to make lines more readable |
| 373 |
|
|
root = self._chroot_dir |
| 374 |
|
|
file_name2 = root + "/boot/grub/device.map" |
| 375 |
|
|
file_name3 = root + "/boot/grub/kernel_name" |
| 376 |
codeman |
286 |
file_name4 = root + "/boot/grub/initrd_name" |
| 377 |
codeman |
235 |
foundboot = False |
| 378 |
|
|
parts = self._install_profile.get_partition_tables() |
| 379 |
|
|
for device in parts: |
| 380 |
agaffney |
601 |
tmp_partitions = parts[device].get_install_profile_structure() |
| 381 |
|
|
for partition in tmp_partitions: |
| 382 |
|
|
mountpoint = tmp_partitions[partition]['mountpoint'] |
| 383 |
codeman |
235 |
if (mountpoint == "/boot"): |
| 384 |
|
|
foundboot = True |
| 385 |
|
|
if (( (mountpoint == "/") and (not foundboot) ) or (mountpoint == "/boot")): |
| 386 |
agaffney |
601 |
boot_minor = str(int(tmp_partitions[partition]['minor'])) |
| 387 |
|
|
grub_boot_minor = str(int(tmp_partitions[partition]['minor']) - 1) |
| 388 |
codeman |
235 |
boot_device = device |
| 389 |
|
|
if mountpoint == "/": |
| 390 |
agaffney |
601 |
root_minor = str(int(tmp_partitions[partition]['minor'])) |
| 391 |
|
|
grub_root_minor = str(int(tmp_partitions[partition]['minor']) - 1) |
| 392 |
codeman |
235 |
root_device = device |
| 393 |
codeman |
286 |
if GLIUtility.is_file(root+file_name2): |
| 394 |
|
|
exitstatus = GLIUtility.spawn("rm "+root+file_name2) |
| 395 |
|
|
exitstatus1 = GLIUtility.spawn("echo quit | "+ root+"/sbin/grub --device-map="+file_name2) |
| 396 |
|
|
exitstatus2 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3) |
| 397 |
codeman |
734 |
if build_mode == "genkernel": |
| 398 |
|
|
exitstatus3 = GLIUtility.spawn("ls "+root+"/boot/initramfs-* > "+file_name4) |
| 399 |
|
|
else: |
| 400 |
|
|
exitstatus3 = GLIUtility.spawn("touch "+file_name4) |
| 401 |
codeman |
286 |
if (exitstatus1 != 0) or (exitstatus2 != 0) or (exitstatus3 != 0): |
| 402 |
robbat2 |
740 |
raise GLIException("BootloaderError", 'fatal', '_configure_grub', "Error in one of THE THREE run commands") |
| 403 |
codeman |
427 |
self._logger.log("Bootloader: the three information gathering commands have been run") |
| 404 |
codeman |
235 |
""" |
| 405 |
|
|
read the device map. sample looks like this: |
| 406 |
|
|
(fd0) /dev/floppy/0 |
| 407 |
|
|
(hd0) /dev/ide/host2/bus0/target0/lun0/disc |
| 408 |
|
|
(hd1) /dev/ide/host0/bus0/target0/lun0/disc |
| 409 |
|
|
(hd2) /dev/ide/host0/bus0/target1/lun0/disc |
| 410 |
|
|
""" |
| 411 |
|
|
|
| 412 |
|
|
# Search for the key |
| 413 |
codeman |
286 |
f = open(file_name2) #open the device map |
| 414 |
codeman |
235 |
file = f.readlines() |
| 415 |
|
|
f.close() |
| 416 |
|
|
for i in range(len(file)): |
| 417 |
codeman |
286 |
if file[i][6:-1] == boot_device: |
| 418 |
codeman |
235 |
#eurika we found the drivenum |
| 419 |
|
|
grub_boot_drive = file[i][1:4] |
| 420 |
codeman |
286 |
if file[i][6:-1] == root_device: |
| 421 |
codeman |
235 |
grub_root_drive = file[i][1:4] |
| 422 |
|
|
if (not grub_root_drive) or (not grub_boot_drive): |
| 423 |
robbat2 |
740 |
raise GLIException("BootloaderError", 'fatal', '_configure_grub',"Couldn't find the drive num in the list from the device.map") |
| 424 |
codeman |
235 |
|
| 425 |
|
|
g = open(file_name3) |
| 426 |
codeman |
286 |
h = open(file_name4) |
| 427 |
|
|
initrd_name = h.readlines() |
| 428 |
codeman |
235 |
kernel_name = g.readlines() |
| 429 |
|
|
g.close() |
| 430 |
codeman |
286 |
h.close() |
| 431 |
codeman |
235 |
if not kernel_name[0]: |
| 432 |
robbat2 |
740 |
raise GLIException("BootloaderError", 'fatal', '_configure_grub',"Error: We have no kernel in /boot to put in the grub.conf file!") |
| 433 |
codeman |
235 |
kernel_name = map(string.strip, kernel_name) |
| 434 |
codeman |
286 |
initrd_name = map(string.strip, initrd_name) |
| 435 |
|
|
for i in range(len(kernel_name)): |
| 436 |
|
|
grub_kernel_name = kernel_name[i].split(root)[1] |
| 437 |
|
|
for i in range(len(initrd_name)): |
| 438 |
|
|
grub_initrd_name = initrd_name[i].split(root)[1] |
| 439 |
codeman |
235 |
#------------------------------------------------------------- |
| 440 |
|
|
#OK, now that we have all the info, let's build that grub.conf |
| 441 |
|
|
newgrubconf = "" |
| 442 |
|
|
newgrubconf += "default 0\ntimeout 30\n" |
| 443 |
agaffney |
461 |
if self._install_profile.get_bootloader_kernel_args(): bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args() |
| 444 |
|
|
else: bootloader_kernel_args = "" |
| 445 |
codeman |
235 |
if foundboot: #we have a /boot |
| 446 |
|
|
newgrubconf += "splashimage=(" + grub_boot_drive + "," + grub_boot_minor + ")/grub/splash.xpm.gz\n" |
| 447 |
|
|
else: #we have / and /boot needs to be included |
| 448 |
|
|
newgrubconf += "splashimage=(" + grub_boot_drive + "," + grub_boot_minor + ")/boot/grub/splash.xpm.gz\n" |
| 449 |
agaffney |
225 |
|
| 450 |
codeman |
235 |
newgrubconf += "title=Gentoo Linux\n" |
| 451 |
|
|
newgrubconf += "root (" + grub_boot_drive + "," + grub_boot_minor + ")\n" |
| 452 |
codeman |
734 |
if build_mode != "genkernel": #using CUSTOM kernel |
| 453 |
codeman |
286 |
if foundboot: |
| 454 |
|
|
newgrubconf += "kernel " + grub_kernel_name[5:] + " root="+root_device+root_minor+"\n" |
| 455 |
|
|
else: |
| 456 |
|
|
newgrubconf += "kernel /boot"+ grub_kernel_name[5:] + " root="+root_device+root_minor+"\n" |
| 457 |
codeman |
734 |
else: #using genkernel so it has an initrd. |
| 458 |
codeman |
286 |
if foundboot: |
| 459 |
|
|
newgrubconf += "kernel " + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root=" |
| 460 |
agaffney |
461 |
newgrubconf += root_device + root_minor + " " + bootloader_kernel_args + "\n" |
| 461 |
codeman |
286 |
newgrubconf += "initrd " + grub_initrd_name[5:] + "\n" |
| 462 |
|
|
else: |
| 463 |
|
|
newgrubconf += "kernel /boot" + grub_kernel_name[5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root=" |
| 464 |
agaffney |
461 |
newgrubconf += root_device + root_minor + " " + bootloader_kernel_args + "\n" |
| 465 |
codeman |
286 |
newgrubconf += "initrd /boot" + grub_initrd_name[5:] + "\n" |
| 466 |
codeman |
235 |
|
| 467 |
|
|
#------------------------------------------------------------- |
| 468 |
|
|
#OK, now that the file is built. Install grub. |
| 469 |
|
|
#cp /proc/mounts /etc/mtab |
| 470 |
|
|
#grub-install --root-directory=/boot /dev/hda |
| 471 |
|
|
#shutil.copy("/proc/mounts",root +"/etc/mtab") |
| 472 |
|
|
grubinstallstring = "echo -en 'root ("+grub_boot_drive + "," + grub_boot_minor + ")\n" |
| 473 |
|
|
if not self._install_profile.get_boot_loader_mbr(): |
| 474 |
|
|
grubinstallstring +="setup ("+grub_boot_drive + "," + grub_boot_minor + ")\n" |
| 475 |
|
|
else: |
| 476 |
|
|
grubinstallstring +="setup ("+grub_boot_drive+")\n" |
| 477 |
|
|
grubinstallstring += "quit\n' | "+root+"/sbin/grub" |
| 478 |
|
|
#print grubinstallstring |
| 479 |
codeman |
390 |
exitstatus = GLIUtility.spawn(grubinstallstring) |
| 480 |
codeman |
235 |
if exitstatus != 0: |
| 481 |
robbat2 |
740 |
raise GLIException("GrubInstallError", 'fatal', '_configure_grub', "Could not install grub!") |
| 482 |
codeman |
427 |
self._logger.log("Bootloader: grub has been installed!") |
| 483 |
codeman |
235 |
#now make the grub.conf file |
| 484 |
|
|
file_name = root + "/boot/grub/grub.conf" |
| 485 |
|
|
try: |
| 486 |
|
|
shutil.move(file_name, file_name + ".OLDdefault") |
| 487 |
|
|
except: |
| 488 |
|
|
pass |
| 489 |
|
|
f = open(file_name, 'w') |
| 490 |
|
|
f.writelines(newgrubconf) |
| 491 |
|
|
f.close() |
| 492 |
codeman |
314 |
self._logger.log("Grub installed and configured.") |
| 493 |
codeman |
235 |
|
| 494 |
robbat2 |
740 |
def _configure_lilo(self): |
| 495 |
codeman |
235 |
boot_device = "" |
| 496 |
|
|
boot_minor = "" |
| 497 |
|
|
root_device = "" |
| 498 |
|
|
root_minor = "" |
| 499 |
|
|
minornum = 0 |
| 500 |
|
|
#Assign root to the root mount point to make lines more readable |
| 501 |
|
|
root = self._chroot_dir |
| 502 |
|
|
file_name3 = root + "/boot/grub/kernel_name" |
| 503 |
|
|
foundboot = False |
| 504 |
|
|
parts = self._install_profile.get_partition_tables() |
| 505 |
|
|
for device in parts: |
| 506 |
agaffney |
601 |
tmp_partitions = parts[device] |
| 507 |
|
|
for partition in tmp_partitions: |
| 508 |
|
|
mountpoint = tmp_partitions[partition]['mountpoint'] |
| 509 |
codeman |
235 |
if (mountpoint == "/boot"): |
| 510 |
|
|
foundboot = True |
| 511 |
|
|
if (( (mountpoint == "/") and (not foundboot) ) or (mountpoint == "/boot")): |
| 512 |
agaffney |
601 |
boot_minor = str(int(tmp_partitions[partition]['minor'])) |
| 513 |
codeman |
235 |
boot_device = device |
| 514 |
|
|
if mountpoint == "/": |
| 515 |
agaffney |
601 |
root_minor = str(int(tmp_partitions[partition]['minor'])) |
| 516 |
codeman |
235 |
root_device = device |
| 517 |
|
|
exitstatus0 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3) |
| 518 |
|
|
exitstatus1 = GLIUtility.spawn("ls "+root+"/boot/initrd-* >> "+file_name3) |
| 519 |
|
|
if (exitstatus0 != 0) or (exitstatus1 != 0): |
| 520 |
robbat2 |
740 |
raise GLIException("BootloaderError", 'fatal', '_configure_lilo', "Error in one of THE TWO run commands") |
| 521 |
codeman |
235 |
g = open(file_name3) |
| 522 |
|
|
kernel_name = g.readlines() |
| 523 |
|
|
g.close() |
| 524 |
|
|
if not kernel_name[0]: |
| 525 |
robbat2 |
740 |
raise GLIException("BootloaderError", 'fatal', '_configure_lilo',"Error: We have no kernel in /boot to put in the grub.conf file!") |
| 526 |
codeman |
235 |
kernel_name = map(string.strip, kernel_name) |
| 527 |
|
|
kernel_name[0] = kernel_name[0].split(root)[1] |
| 528 |
|
|
kernel_name[1] = kernel_name[1].split(root)[1] |
| 529 |
agaffney |
461 |
if self._install_profile.get_bootloader_kernel_args(): bootloader_kernel_args = self._install_profile.get_bootloader_kernel_args() |
| 530 |
|
|
else: bootloader_kernel_args = "" |
| 531 |
codeman |
235 |
#------------------------------------------------------------- |
| 532 |
|
|
#time to build the lilo.conf |
| 533 |
|
|
newliloconf = "" |
| 534 |
|
|
if self._install_profile.get_boot_loader_mbr(): |
| 535 |
|
|
newliloconf += "boot="+boot_device+" # Install LILO in the MBR \n" |
| 536 |
|
|
else: |
| 537 |
codeman |
237 |
newliloconf += "boot="+boot_device+boot_minor+" # Install LILO in the MBR \n" |
| 538 |
codeman |
235 |
newliloconf += "prompt # Give the user the chance to select another section\n" |
| 539 |
|
|
newliloconf += "timeout=50 # Wait 5 (five) seconds before booting the default section\n" |
| 540 |
|
|
newliloconf += "default=gentoo # When the timeout has passed, boot the \"gentoo\" section\n" |
| 541 |
|
|
newliloconf += "# Only if you use framebuffer. Otherwise remove the following line:\n" |
| 542 |
|
|
if not self._install_profile.get_kernel_bootsplash(): |
| 543 |
|
|
newliloconf += "#" |
| 544 |
|
|
newliloconf += "vga=788 # Framebuffer setting. Adjust to your own will\n" |
| 545 |
codeman |
237 |
newliloconf += "image=/boot"+kernel_name[0][5:]+" \n" |
| 546 |
codeman |
235 |
newliloconf += " label=gentoo \n read-only \n root=/dev/ram0 \n" |
| 547 |
agaffney |
461 |
newliloconf += " append=\"init=/linuxrc ramdisk=8192 real_root="+root_device+root_minor + " " + bootloader_kernel_args + "\" \n" |
| 548 |
codeman |
248 |
newliloconf += " initrd=/boot"+kernel_name[1][5:] + "\n\n" |
| 549 |
|
|
newliloconf = self._lilo_add_windows(newliloconf) |
| 550 |
codeman |
235 |
#now make the lilo.conf file |
| 551 |
|
|
file_name = root + "/etc/lilo.conf" |
| 552 |
|
|
try: |
| 553 |
|
|
shutil.move(file_name, file_name + ".OLDdefault") |
| 554 |
|
|
except: |
| 555 |
|
|
pass |
| 556 |
|
|
f = open(file_name, 'w') |
| 557 |
|
|
f.writelines(newliloconf) |
| 558 |
|
|
f.close() |
| 559 |
|
|
#------------------------------------------------------------- |
| 560 |
|
|
#OK, now that the file is built. Install lilo. |
| 561 |
|
|
exitstatus = GLIUtility.spawn("/sbin/lilo",chroot=self._chroot_dir) |
| 562 |
|
|
if exitstatus != 0: |
| 563 |
robbat2 |
740 |
raise GLIException("LiloInstallError", 'fatal', '_configure_lilo', "Running lilo failed!") |
| 564 |
codeman |
314 |
self._logger.log("Lilo installed, configured, and run.") |
| 565 |
|
|
|
| 566 |
codeman |
248 |
def _lilo_add_windows(self, newliloconf): |
| 567 |
|
|
parts = self._install_profile.get_partition_tables() |
| 568 |
|
|
for device in parts: |
| 569 |
agaffney |
601 |
tmp_partitions = parts[device] |
| 570 |
|
|
for partition in tmp_partitions: |
| 571 |
|
|
if (tmp_partitions[partition]['type'] == "vfat") or (tmp_partitions[partition]['type'] == "ntfs"): |
| 572 |
|
|
newliloconf += "other="+device+str(int(tmp_partitions[partition]['minor']))+"\n" |
| 573 |
|
|
newliloconf += "label=Windows_P"+str(int(tmp_partitions[partition]['minor']))+"\n\n" |
| 574 |
codeman |
263 |
return newliloconf |