diff --git a/pyanaconda/bootloader.py b/pyanaconda/bootloader.py index 9d9d794..6243792 100644 --- a/pyanaconda/bootloader.py +++ b/pyanaconda/bootloader.py @@ -27,6 +27,7 @@ import struct from pyanaconda import iutil from pyanaconda.storage.devicelibs import mdraid +from pyanaconda.storage.formats import getFormat from pyanaconda.isys import sync from pyanaconda.product import productName from pyanaconda.flags import flags @@ -175,6 +176,55 @@ class LinuxBootLoaderImage(BootLoaderImage): return filename +class Constraint(object): + def __init__(self, device_types=None, format_types=None, mountpoints=None, + disklabel_types=None, raid_levels=None): + self.device_types = device_types + self.format_types = format_types + self.mountpoints = mountpoints + self.disklabel_types = disklabel_types + self.raid_levels = raid_levels + + def check_device_type(self, device): + ret = False + if "disk" in self.device_types: + ret = device.isDisk + + if not ret: + ret = device.type in self.device_types + + return ret + + def satisfied(self, device): + if not self.check_device_type(device): + return False + + if (self.raid_levels and device.type == "mdarray" and + device.level not in self.raid_levels): + return False + + if self.format_types and device.format.type not in self.format_types: + return False + + if device.format.minSize and device.size < device.format.minSize: + return False + + if device.format.maxSize and device.size > device.format.maxSize: + return False + + if (self.mountpoints and + getattr(device.format, "mountpoint", None) not in self.mountpoints): + return False + + if self.disklabel_types: + for disk in device.disks: + if (disk.format.type != "disklabel" or + disk.format.labelType not in self.disklabel_types): + return False + + return True + + class BootLoader(object): """TODO: - simplify choices to (mbr|boot device)? @@ -208,25 +258,15 @@ class BootLoader(object): image_label_attr = "label" # requirements for bootloader target devices - target_device_types = [] - target_device_raid_levels = [] - target_device_format_types = [] - target_device_disklabel_types = [] - target_device_mountpoints = [] - target_device_min_size = None - target_device_max_size = None + _stage1_constraints = [] # for UI use, eg: "mdarray": N_("RAID Device") target_descriptions = {} # requirements for boot devices - boot_device_types = [] - boot_device_raid_levels = [] - boot_device_format_types = ["ext4", "ext3", "ext2"] - boot_device_mountpoints = ["/boot", "/"] - boot_device_min_size = 50 - boot_device_max_size = None - non_linux_boot_device_format_types = [] + stage2_constraints = [] + + non_linux_constraints = [] # this is so stupid... global_preserve_args = ["speakup_synth", "apic", "noapic", "apm", "ide", @@ -261,28 +301,38 @@ class BootLoader(object): self._default_image = None # the device the bootloader will be installed on - self._target_device = None + self._stage1_device = None + + # the "boot drive", meaning the drive we prefer stage1 be on + self.stage1_drive = None self._update_only = False # - # target device access + # stage1 device access # @property def stage1_device(self): """ Stage1 target device. """ - if not self._target_device: - self.stage1_device = self.target_devices[0] + if not self._stage1_device: + try: + self.stage1_device = self.stage1_devices[0] + except IndexError: + pass - return self._target_device + return self._stage1_device @stage1_device.setter def stage1_device(self, device): - if not self._is_valid_target_device(device): - raise ValueError("%s is not a valid target device" % device.name) + if device is not None and not self._is_valid_stage1_device(device): + raise ValueError("%s is not a valid stage1 device" % device.name) - log.debug("new bootloader stage1 device: %s" % device.name) - self._target_device = device + log.debug("new bootloader stage1 device: %s" % getattr(device, + "name", None)) + if device: + self.stage1_drive = device.disks[0] + + self._stage1_device = device @property def stage2_device(self): @@ -332,6 +382,10 @@ class BootLoader(object): # XXX requiring partitioned may break clearpart drives = [d for d in self.storage.disks if d.partitioned] self._drives = self._sort_drives(drives) + + # set "boot drive" + self.stage1_drive = self._drives[0] + return self._drives # @@ -399,45 +453,27 @@ class BootLoader(object): # # target/stage1 device access # - def _device_type_index(self, device, types): - """ Return the index of the matching type in types to device's type. - - Return None if no match is found. """ - index = None - try: - index = types.index(device.type) - except ValueError: - if "disk" in types and device.isDisk: - index = types.index("disk") - - return index - - def _device_type_match(self, device, types): - """ Return True if device is of one of the types in the list types. """ - return self._device_type_index(device, types) is not None + def _constraint_match(self, device, constraints): + for (i, c) in enumerate(constraints): + if c.satisfied(device): + return i - def device_description(self, device): - idx = self._device_type_index(device, self.target_device_types) + def stage1_device_description(self, device): + idx = self._constraint_match(device, self.stage1_constraints) if idx is None: raise ValueError("'%s' not a valid stage1 type" % device.type) - return self.target_descriptions[self.target_device_types[idx]] - - def set_preferred_stage2_type(self, preferred): - """ Set a preferred type of stage1 device. + return self.target_descriptions[device.type] - XXX should this reorder the list or remove everything else? """ - if preferred == "mbr": - preferred = "disk" + def set_preferred_stage1_type(self, preferred): + """ Set a preferred type of stage1 device. """ + raise BootLoaderError("I forgot how to set preferred stage1 type") - try: - index = self.target_device_types.index(preferred) - except ValueError: - raise ValueError("'%s' not a valid stage1 device type" % preferred) - - self.target_device_types.insert(0, self.target_device_types.pop(index)) + @property + def stage1_constraints(self): + return self._stage1_constraints - def _is_valid_target_device(self, device): + def _is_valid_stage1_device(self, device): """ Return True if the device is a valid stage1 target device. The criteria for being a valid stage1 target device vary from @@ -446,15 +482,13 @@ class BootLoader(object): a special device. Some examples of these special devices are EFI system partitions on EFI machines, PReP boot partitions on iSeries, and Apple bootstrap partitions on Mac. """ - if not self._device_type_match(device, self.target_device_types): - return False - - if (self.target_device_min_size is not None and - device.size < self.target_device_min_size): - return False + match = False + for constraint in self.stage1_constraints: + if constraint.satisfied(device): + match = True + break - if (self.target_device_max_size is not None and - device.size > self.target_device_max_size): + if not match: return False if not getattr(device, "bootable", True) or \ @@ -465,61 +499,53 @@ class BootLoader(object): if getattr(device.format, "label", None) == "ANACONDA": return False - if self.target_device_format_types and \ - device.format.type not in self.target_device_format_types: - return False - - if self.target_device_disklabel_types: - for disk in device.disks: - label_type = disk.format.labelType - if label_type not in self.target_device_disklabel_types: - return False - - if self.target_device_mountpoints and \ - hasattr(device.format, "mountpoint") and \ - device.format.mountpoint not in self.target_device_mountpoints: - return False - return True @property - def target_devices(self): + def stage1_devices(self): """ A list of valid stage1 target devices. - The list self.target_device_types is ordered, so we return a list + The list stage1_constraints is ordered, so we return a list of all valid target devices, sorted by device type, then sorted according to our drive ordering. """ - slots = [[] for t in self.target_device_types] + slots = [[] for t in self.stage1_constraints] for device in self.storage.devices: - idx = self._device_type_index(device, self.target_device_types) + idx = self._constraint_match(device, self.stage1_constraints) if idx is None: continue - if self._is_valid_target_device(device): + if self._is_valid_stage1_device(device): slots[idx].append(device) devices = [] for slot in slots: devices.extend(slot) - return self._sort_drives(devices) + # sort the devices by drive order + devices = self._sort_drives(devices) + + # if a boot drive has been chosen put it, and devices on it, first + if self.stage1_drive: + indices = [devices.index(d) for d in devices + if self.stage1_drive in d.disks] + for idx in reversed(indices): + devices.insert(0, devices.pop(idx)) + + return devices # # boot/stage2 device access # - def _is_valid_boot_device(self, device, linux=True, non_linux=False): + def _is_valid_stage2_device(self, device, linux=True, non_linux=False): """ Return True if the specified device might contain an OS image. """ - if not self._device_type_match(device, self.boot_device_types): - return False - - if device.type == "mdarray" and \ - device.level not in self.boot_device_raid_levels: - # TODO: also check metadata version, as ridiculous as that is - return False + # XXX FIXME: linux -v- non-linux + for constraint in self.stage2_constraints: + if not constraint.satisfied(device): + return False - if not self.target_devices: + if not self.stage1_devices: # XXX is this really a dealbreaker? return False @@ -801,24 +827,24 @@ class GRUB(BootLoader): can_dual_boot = True can_update = True - # list of strings representing options for bootloader target device types - target_device_types = ["disk", "partition", "mdarray"] - target_device_raid_levels = [mdraid.RAID1] - target_device_format_types = [] - target_device_format_mountpoints = ["/boot", "/"] - target_device_disklabel_types = ["msdos", "gpt"] # gpt? + _stage1_constraints = [Constraint(device_types=["disk"], + disklabel_types=["msdos"]), + Constraint(device_types=["partition"], + disklabel_types=["gpt"], + format_types=["biosboot"])] - # XXX account for disklabel type since mbr means nothing on gpt target_descriptions = {"disk": N_("Master Boot Record"), "partition": N_("First sector of boot partition"), "mdarray": N_("RAID Device")} # list of strings representing options for boot device types - boot_device_types = ["partition", "mdarray"] - boot_device_raid_levels = [mdraid.RAID1] + stage2_constraints = [Constraint(device_types=["partition", "mdarray"], + disklabel_types=["msdos", "gpt"], + raid_levels=[mdraid.RAID1], + mountpoints=["/boot", "/"])] # XXX hpfs, if reported by blkid/udev, will end up with a type of None - non_linux_device_format_types = ["vfat", "ntfs", "hpfs"] + non_linux_constraints = [Constraint(format_types=["vfat", "ntfs", "hpfs"])] packages = ["grub"] @@ -826,6 +852,35 @@ class GRUB(BootLoader): super(GRUB, self).__init__(storage) self.encrypt_password = False + @property + def stage2_constraint(self): + device = self.stage2_device + if device: + if device.isDisk: + device_type = "disk" + else: + device_type = device.type + + mountpoints = getattr(device.format, "mountpoint", None) + if mountpoints: + # it must be a list, but [None] must be avoided. + mountpoints = [mountpoints] + + return DeviceConstraintSet(device_types=[device_type], + mountpoints=mountpoints, + format_types=[device.format.type]) + + @property + def stage1_constraints(self): + constraints = self._stage1_constraints[:] + + # with grub, stage2 device is acceptable as a stage1 target + stage2 = self.stage2_constraint + if stage2: + constraints.append(stage2) + + return constraints + # # grub-related conveniences # @@ -1134,19 +1189,19 @@ class EFIGRUB(GRUB): can_dual_boot = False _config_dir = "efi/EFI/redhat" - # bootloader target device types - target_device_types = ["partition", "mdarray"] - target_device_raid_levels = [mdraid.RAID1] - target_device_format_types = ["efi"] - target_device_mountpoints = ["/boot/efi"] - target_device_disklabel_types = ["gpt"] - target_device_min_size = 50 - target_device_max_size = 256 + _stage1_constraints = [Constraint(device_types=["partition"], + format_types=["efi"], + disklabel_types=["gpt"], + mountpoints=["/boot/efi"])] target_descriptions = {"partition": N_("EFI System Partition"), "mdarray": N_("RAID Device")} - non_linux_boot_device_format_types = [] + non_linux_constraints = [] + + def __init__(self, *args, **kwargs): + super(EFIGRUB, self).__init__(*args, **kwargs) + self.stage2_constraint = None # stage2 is not valid stage1 on EFI def efibootmgr(self, *args, **kwargs): if kwargs.pop("capture", False): @@ -1262,11 +1317,17 @@ class GRUB2(GRUB): can_update = True # requirements for bootloader target devices - target_device_types = ["disk", "partition", "mdarray"] - target_device_raid_levels = [mdraid.RAID1] - target_device_format_types = [] - target_device_disklabel_types = ["msdos", "gpt"] - target_device_mountpoints = ["/boot", "/"] + _stage1_constraints = [Constraint(device_types=["disk"], + disklabel_types=["msdos"]), + Constraint(device_types=["partition"], + disklabel_types=["gpt"], + format_types=["biosboot"])] + + # list of strings representing options for boot device types + stage2_constraints = [Constraint(device_types=["partition", "mdarray", + "lvmlv"], + disklabel_types=["msdos", "gpt"], + mountpoints=["/boot", "/"])] # for UI use, eg: "mdarray": N_("RAID Device") target_descriptions = {"msdos": N_("Master Boot Record"), @@ -1277,16 +1338,6 @@ class GRUB2(GRUB): partition_descriptions = {"msdos": N_("First sector of boot partition"), "gpt": N_("BIOS boot partition")} - # requirements for boot devices - boot_device_types = ["partition", "mdarray", "lvmlv"] - boot_device_raid_levels = [mdraid.RAID4, mdraid.RAID1, mdraid.RAID4, - mdraid.RAID5, mdraid.RAID6, mdraid.RAID10] - boot_device_format_types = ["ext4", "ext3", "ext2"] - boot_device_mountpoints = ["/boot", "/"] - boot_device_min_size = 50 - boot_device_max_size = None - non_linux_boot_device_format_types = [] - # # grub-related conveniences # @@ -1312,8 +1363,8 @@ class GRUB2(GRUB): name += ")" return name - def device_description(self, device): - idx = self._device_type_index(device, self.target_device_types) + def stage1_device_description(self, device): + idx = self._constraint_match(device, self.stage1_constraints) if idx is None: raise ValueError("'%s' not a valid stage1 type" % device.type) @@ -1323,7 +1374,7 @@ class GRUB2(GRUB): elif device.type == "partition": desc = self.partition_descriptions[label_type] else: - desc = super(GRUB2, self).device_description(device) + desc = super(GRUB2, self).stage1_device_description(device) return desc @@ -1431,16 +1482,6 @@ class Yaboot(YabootSILOBase): image_label_attr = "short_label" packages = ["yaboot"] - # list of strings representing options for bootloader target device types - target_device_types = ["partition", "mdarray"] - target_device_raid_levels = [mdraid.RAID1] - target_device_format_types = ["appleboot", "prepboot"] - - # boot device requirements - boot_device_types = ["partition", "mdarray"] - boot_device_raid_levels = [mdraid.RAID1] - non_linux_boot_device_format_types = ["hfs", "hfs+"] - def __init__(self, storage): BootLoader.__init__(self, storage) @@ -1524,14 +1565,17 @@ class Yaboot(YabootSILOBase): class IPSeriesYaboot(Yaboot): prog = "mkofboot" - target_device_format_types = ["prepboot"] - target_device_disklabel_types = ["msdos"] - target_device_min_size = 4 - target_device_max_size = 10 + _stage1_constraints = [Constraint(device_types=["partition"], + format_types=["prepboot"], + disklabel_types=["msdos"])] target_descriptions = {"partition": N_("PReP Boot Partition"), "mdarray": N_("RAID Device")} + stage2_constraints = [Constraint(device_types=["partition", "mdarray"], + mountpoints=["/boot", "/"], + disklabel_types=["msdos"])] + # # configuration # @@ -1543,16 +1587,22 @@ class IPSeriesYaboot(Yaboot): class MacYaboot(Yaboot): prog = "mkofboot" - can_dual_boot = True - target_device_format_types = ["appleboot"] - target_device_disklabel_types = ["mac"] - target_device_min_size = 800.00 / 1024.00 - target_device_max_size = 1 + + _stage1_constraints = [Constraint(device_types=["partition"], + format_types=["appleboot"], + disklabel_types=["mac"])] target_descriptions = {"partition": N_("Apple Bootstrap Partition"), "mdarray": N_("RAID Device")} + stage2_constraints = [Constraint(device_types=["partition", "mdarray"], + mountpoints=["/boot", "/"], + raid_levels=[mdraid.RAID1], + disklabel_types=["mac"])] + + non_linux_constraints = [Constraint(format_types=["hfs", "hfs+"])] + # # configuration # @@ -1573,13 +1623,14 @@ class ZIPL(BootLoader): config_file = "/etc/zipl.conf" packages = ["zipl"] - # list of strings representing options for bootloader target device types - target_device_types = ["disk", "partition"] - target_device_disklabel_types = ["msdos", "dasd"] + _stage1_constraints = [Constraint(device_types=["disk"], + disklabel_types=["msdos", "dasd"])] - # list of strings representing options for boot device types - boot_device_types = ["partition", "mdarray", "lvmlv"] - boot_device_raid_levels = [mdraid.RAID1] + stage2_constraints = [Constraint(device_types=["partition", "mdarray", + "lvmlv"], + mountpoints=["/boot", "/"], + raid_levels=[mdraid.RAID1], + disklabel_types=["msdos", "dasd"])] packages = ["s390utils"] # is this bootloader or platform? image_label_attr = "short_label" @@ -1650,12 +1701,12 @@ class SILO(YabootSILOBase): _config_file = "silo.conf" message_file = "/etc/silo.message" - # list of strings representing options for bootloader target device types - target_device_types = ["partition"] - target_device_disklabel_types = ["sun"] + _stage1_constraints = [Constraint(device_types=["disk"], + disklabel_types=["sun"])] - # list of strings representing options for boot device types - boot_device_types = ["partition"] + stage2_constraints = [Constraint(device_types=["partition"], + mountpoints=["/boot"], + disklabel_types=["sun"])] packages = ["silo"] diff --git a/pyanaconda/iw/bootloader_main_gui.py b/pyanaconda/iw/bootloader_main_gui.py index 29d88cc..4a53dc2 100644 --- a/pyanaconda/iw/bootloader_main_gui.py +++ b/pyanaconda/iw/bootloader_main_gui.py @@ -98,7 +98,7 @@ class MainBootloaderWindow(InstallWindow): # XXX for md stage1, should we show md, first member disk, or first # disk? stage1 = anaconda.platform.bootLoaderDevice - stage1_desc = anaconda.bootloader.device_description(stage1) + stage1_desc = anaconda.bootloader.stage1_device_description(stage1) choices = {"mbr": (stage1, stage1_desc)} stage2 = anaconda.platform.bootDevice diff --git a/pyanaconda/iw/cleardisks_gui.py b/pyanaconda/iw/cleardisks_gui.py index cd685e8..36453a4 100644 --- a/pyanaconda/iw/cleardisks_gui.py +++ b/pyanaconda/iw/cleardisks_gui.py @@ -62,7 +62,7 @@ class ClearDisksWindow (InstallWindow): cleardisks.sort(self.anaconda.storage.compareDisks) self.anaconda.storage.config.clearPartDisks = cleardisks - self.anaconda.bootloader.stage1_device = bootDisk + self.anaconda.bootloader.stage1_drive = bootDisk def getScreen (self, anaconda): # We can't just use exclusiveDisks here because of kickstart. First, @@ -76,6 +76,7 @@ class ClearDisksWindow (InstallWindow): # Skip this screen as well if there's only one disk to use. if len(disks) == 1: anaconda.storage.config.clearPartDisks = [disks[0].name] + anaconda.bootloader.stage1_drive = disks[0] return None (xml, self.vbox) = gui.getGladeWidget("cleardisks.glade", "vbox") diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py index 9c8683b..b63e721 100644 --- a/pyanaconda/kickstart.py +++ b/pyanaconda/kickstart.py @@ -262,7 +262,7 @@ class Bootloader(commands.bootloader.F15_Bootloader): self.anaconda.bootloader.encrypt_password = self.isCrypted if location != None: - self.anaconda.bootloader.set_preferred_stage2_type(location) + self.anaconda.bootloader.set_preferred_stage1_type(location) if self.timeout: self.anaconda.bootloader.timeout = self.timeout diff --git a/pyanaconda/platform.py b/pyanaconda/platform.py index 1105b05..e4f938a 100644 --- a/pyanaconda/platform.py +++ b/pyanaconda/platform.py @@ -19,6 +19,7 @@ # # Authors: Chris Lumens # +import parted from pyanaconda import bootloader @@ -72,16 +73,31 @@ class Platform(object): @property def diskLabelTypes(self): """A list of valid disklabel types for this architecture.""" - return self.bootloader.target_device_disklabel_types + return self.bootloader.stage1_device_disklabel_types @property def defaultDiskLabelType(self): """The default disklabel type for this architecture.""" return self.diskLabelTypes[0] - def diskLabelType(self, device_type): - """The default disklabel type for the specified device type.""" - return self.defaultDiskLabelType + def requiredDiskLabelType(self, device_type): + return None + + def bestDiskLabelType(self, device): + """Required disklabel type for the specified device.""" + # if there's a required type for this device type, use that + labelType = self.requiredDiskLabelType(device.partedDevice.type) + if not labelType: + # otherwise, use the first supported type for this platform + # that is large enough to address the whole device + labelType = self.defaultDiskLabelType + for lt in self.diskLabelTypes: + l = parted.Disk(device=device.partedDevice, ty=lt) + if l.maxPartitionStartSector < device.partedDevice.length: + labelType = lt + break + + return labelType def checkDiskLabel(self, req): """Check the disk containing req for the correct disklabel type. @@ -150,7 +166,11 @@ class Platform(object): Returns a list of error strings. """ - return self.checkDiskLabel(self.bootLoaderDevice) + req = self.bootLoaderDevice + if not req: + return [_("you have not created a bootloader target device")] + + return self.checkDiskLabel(req) @property def minimumSector(self, disk): @@ -194,6 +214,22 @@ class Platform(object): class X86(Platform): _bootloaderClass = bootloader.GRUB + def setDefaultPartitioning(self): + """Return the default platform-specific partitioning information.""" + from storage.partspec import PartSpec + ret = Platform.setDefaultPartitioning(self) + ret.append(PartSpec(fstype="biosboot", size=1, + weight=self.weight(fstype="biosboot")] + + def weight(self, fstype=None, mountpoint=None): + score = Platform.weight(self, fstype=fstype, mountpoint=mountpoint) + if score: + return score + elif fstype == "biosboot": + return 5000 + else: + return 0 + class EFI(Platform): _bootloaderClass = bootloader.EFIGRUB @@ -298,12 +334,12 @@ class S390(Platform): weight=self.weight(mountpoint="/boot"), asVol=True, singlePV=True)] - def diskLabelType(self, device_type): - """The default disklabel type for the specified device type.""" + def requiredDiskLabelType(self, device_type): + """Required disklabel type for the specified device type.""" if device_type == "dasd": return "dasd" - return self.defaultDiskLabelType + return super(S390, self).requiredDiskLabelType(device_type) class Sparc(Platform): _bootloaderClass = bootloader.SILO diff --git a/pyanaconda/storage/devicetree.py b/pyanaconda/storage/devicetree.py index 72da38c..a085f8d 100644 --- a/pyanaconda/storage/devicetree.py +++ b/pyanaconda/storage/devicetree.py @@ -167,6 +167,7 @@ class DeviceTree(object): self.reinitializeDisks = getattr(conf, "reinitializeDisks", False) self.iscsi = iscsi self.dasd = dasd + self.platform = pyanaconda.platform.Platform(None) self.diskImages = {} images = getattr(conf, "diskImages", {}) @@ -1097,15 +1098,19 @@ class DeviceTree(object): initcb = lambda: self.intf.questionInitializeDisk(bypath, description, device.size) + labelType = self.platform.bestDiskLabelType(device) + try: format = getFormat("disklabel", device=device.path, + labelType=labelType, exists=not initlabel) except InvalidDiskLabelError: # if we have a cb function use it. else we ignore the device. if initcb is not None and initcb(): format = getFormat("disklabel", device=device.path, + labelType=labelType, exists=False) else: self._removeDevice(device) diff --git a/pyanaconda/storage/formats/disklabel.py b/pyanaconda/storage/formats/disklabel.py index e986b5e..20c01aa 100644 --- a/pyanaconda/storage/formats/disklabel.py +++ b/pyanaconda/storage/formats/disklabel.py @@ -26,7 +26,6 @@ import copy from pyanaconda.anaconda_log import log_method_call import parted import _ped -from pyanaconda import platform from ..errors import * from ..udev import udev_settle from . import DeviceFormat, register_device_format @@ -50,6 +49,7 @@ class DiskLabel(DeviceFormat): Keyword Arguments: + labelType -- type of disklabel to create device -- path to the underlying device exists -- indicates whether this is an existing format @@ -57,6 +57,10 @@ class DiskLabel(DeviceFormat): log_method_call(self, *args, **kwargs) DeviceFormat.__init__(self, *args, **kwargs) + self._labelType = kwargs.get("labelType") + if not self.exists and not self._labelType: + raise ValueError("disklabel ctor needs a label type arg") + self._size = None self._partedDevice = None @@ -120,9 +124,8 @@ class DiskLabel(DeviceFormat): def freshPartedDisk(self): """ Return a new, empty parted.Disk instance for this device. """ log_method_call(self, device=self.device) - platf = platform.getPlatform(None) - labelType = platf.diskLabelType(self.partedDevice.type) - return parted.freshDisk(device=self.partedDevice, ty=labelType) + log.debug("new %s disklabel on %s" % (self._labelType, self.device)) + return parted.freshDisk(device=self.partedDevice, ty=self._labelType) @property def partedDisk(self): diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py index 30aee90..12e9e3a 100644 --- a/pyanaconda/storage/partitioning.py +++ b/pyanaconda/storage/partitioning.py @@ -93,11 +93,15 @@ def _schedulePartitions(storage, disks): if request.fstype is None: request.fstype = storage.defaultFSType - elif request.fstype in ("prepboot", "efi") and \ - storage.platform.bootDevice: + elif request.fstype in ("prepboot", "efi", "biosboot") and \ + storage.platform.bootLoaderDevice: # there should never be a need for more than one of these # partitions, so skip them. continue + elif request.fstype == "biosboot" and \ + storage.platform.bootloader.stage1_drive.format.labelType != "gpt": + # biosboot is only needed for gpt disklabels on non-efi x86 + continue # This is a little unfortunate but let the backend dictate the rootfstype # so that things like live installs can do the right thing @@ -399,7 +403,9 @@ def clearPartitions(storage, bootloader=None): devices.remove(leaf) destroy_action = ActionDestroyFormat(disk) - newLabel = getFormat("disklabel", device=disk.path) + labelType = storage.platform.bestDiskLabelType(disk) + newLabel = getFormat("disklabel", device=disk.path, + labelType=labelType) create_action = ActionCreateFormat(disk, format=newLabel) storage.devicetree.registerAction(destroy_action) storage.devicetree.registerAction(create_action) @@ -410,10 +416,11 @@ def clearPartitions(storage, bootloader=None): # make sure that the the boot device has the correct disklabel type if # we're going to completely clear it. for disk in storage.partitioned: - if not bootloader or not bootloader.stage1_device: + if not bootloader or not bootloader.stage1_drive: break - if disk in bootloader.stage1_device.disks: + # if this is not the boot disk, skip it. + if disk != bootloader.stage1_drive: continue if storage.config.clearPartType != CLEARPART_TYPE_ALL or \ @@ -429,7 +436,7 @@ def clearPartitions(storage, bootloader=None): if filter(lambda p: p.dependsOn(disk), storage.protectedDevices): continue - nativeLabelType = storage.platform.diskLabelType(disk.partedDevice.type) + nativeLabelType = storage.platform.bestDiskLabelType(disk) if disk.format.labelType == nativeLabelType: continue @@ -444,7 +451,8 @@ def clearPartitions(storage, bootloader=None): storage.devicetree._removeDevice(part, moddisk=False) destroy_action = ActionDestroyFormat(disk) - newLabel = getFormat("disklabel", device=disk.path) + newLabel = getFormat("disklabel", device=disk.path, + labelType=nativeLabelType) create_action = ActionCreateFormat(disk, format=newLabel) storage.devicetree.registerAction(destroy_action) storage.devicetree.registerAction(create_action) @@ -961,7 +969,7 @@ def allocatePartitions(storage, disks, partitions, freespace, bootloader=None): req_disks.sort(key=lambda d: d.name, cmp=storage.compareDisks) boot_index = None for disk in req_disks: - if bootloader and disk == bootloader.stage1_device.disks[0]: + if bootloader and disk == bootloader.stage1_drive: boot_index = req_disks.index(disk) if boot_index is not None and len(req_disks) > 1: