Allow the use of GPT for disks larger than 2TB on non-UEFI systems. Based on patch cc388b628aa912d7 from master. --- platform.py | 61 +++++++++++++++++++++++++++++------------ storage/devicetree.py | 6 ++++ storage/formats/disklabel.py | 16 ++++++++--- storage/partitioning.py | 15 +++++++--- 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/platform.py b/platform.py index 22dbb03..434dd8f 100644 --- a/platform.py +++ b/platform.py @@ -40,7 +40,7 @@ class Platform(object): architecture quirks in one place to avoid lots of platform checks throughout anaconda.""" _bootFSTypes = ["ext3"] - _diskLabelType = "msdos" + _disklabel_types = ["msdos"] _isEfi = iutil.isEfi() _minimumSector = 0 _packages = [] @@ -143,9 +143,34 @@ class Platform(object): return errors - def diskLabelType(self, deviceType): - """Return the disk label type as a string.""" - return self._diskLabelType + @property + def diskLabelTypes(self): + """A list of valid disklabel types for this architecture.""" + return self._disklabel_types + + @property + def defaultDiskLabelType(self): + """The default disklabel type for this architecture.""" + return self.diskLabelTypes[0] + + def requiredDiskLabelType(self, device_type): + return None + + def bestDiskLabelType(self, device): + """The best 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.freshDisk(device=device.partedDevice, ty=lt) + if l.maxPartitionStartSector < device.partedDevice.length: + labelType = lt + break + + return labelType @property def isEfi(self): @@ -203,7 +228,7 @@ class Platform(object): class EFI(Platform): _bootFSTypes = ["ext4", "ext3", "ext2"] - _diskLabelType = "gpt" + _disklabel_types = ["gpt"] _minBootPartSize = 50 def bootDevice(self): @@ -264,7 +289,7 @@ class EFI(Platform): # Check that we've got a correct disk label. for p in partitions: partedDisk = p.disk.format.partedDisk - labelType = self.diskLabelType(partedDisk.device.type) + labelType = self.defaultDiskLabelType # Allow using gpt with x86, but not msdos with EFI if partedDisk.type != labelType and partedDisk.type != "gpt": errors.append(_("%s must have a %s disk label.") @@ -287,7 +312,7 @@ class EFI(Platform): return 0 class Alpha(Platform): - _diskLabelType = "bsd" + _disklabel_types = ["bsd"] def checkBootRequest(self, req): errors = Platform.checkBootRequest(self, req) @@ -298,7 +323,7 @@ class Alpha(Platform): disk = req.disk.format.partedDisk # Check that we're a BSD disk label - if not disk.type == self._diskLabelType.name: + if not disk.type in self.diskLabelTypes: errors.append(_("%s must have a bsd disk label.") % req.disk.name) # The first free space should start at the beginning of the drive and @@ -399,7 +424,7 @@ class IPSeriesPPC(PPC): return 0 class NewWorldPPC(PPC): - _diskLabelType = "mac" + _disklabel_types = ["mac"] _minBootPartSize = (800.00 / 1024.00) _maxBootPartSize = 1 @@ -441,7 +466,7 @@ class NewWorldPPC(PPC): disk = req.disk.format.partedDisk # Check that we're a Mac disk label - if not disk.type == self._diskLabelType.name: + if not disk.type in self.diskLabelTypes: errors.append(_("%s must have a mac disk label.") % req.disk.name) # All of the above just checks the appleboot partitions. We still @@ -471,7 +496,7 @@ class NewWorldPPC(PPC): return 0 class PS3(PPC): - _diskLabelType = "msdos" + _disklabel_types = ["msdos"] def __init__(self, anaconda): PPC.__init__(self, anaconda) @@ -484,12 +509,12 @@ class S390(Platform): def __init__(self, anaconda): Platform.__init__(self, anaconda) - def diskLabelType(self, deviceType): - """Return the disk label type as a string.""" + def requiredDiskLabelType(self, device_type): + """The required disklabel type for the specified device type.""" if deviceType == parted.DEVICE_DASD: return "dasd" - else: - return Platform.diskLabelType(self, deviceType) + + return super(S390, self).requiredDiskLabelType(device_type) def setDefaultPartitioning(self): """Return the default platform-specific partitioning information.""" @@ -504,7 +529,7 @@ class S390(Platform): return 0 class Sparc(Platform): - _diskLabelType = "sun" + _disklabel_types = ["sun"] @property def minimumSector(self, disk): @@ -522,9 +547,9 @@ class X86(EFI): EFI.__init__(self, anaconda) if self.isEfi: - self._diskLabelType = "gpt" + self._disklabel_types = ["gpt"] else: - self._diskLabelType = "msdos" + self._disklabel_types = ["msdos", "gpt"] def bootDevice(self): if self.isEfi: diff --git a/storage/devicetree.py b/storage/devicetree.py index 723cab5..4d11304 100644 --- a/storage/devicetree.py +++ b/storage/devicetree.py @@ -38,6 +38,7 @@ import devicelibs.mpath from udev import * from .storage_log import log_method_call import iutil +import platform import parted import _ped @@ -170,6 +171,7 @@ class DeviceTree(object): self.reinitializeDisks = reinitializeDisks self.iscsi = iscsi self.dasd = dasd + self.platform = platform.getPlatform(None) self.mpathFriendlyNames = mpathFriendlyNames # protected device specs as provided by the user @@ -1431,15 +1433,19 @@ class DeviceTree(object): device.size, details) + 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/storage/formats/disklabel.py b/storage/formats/disklabel.py index f1fb1f0..c6927ec 100644 --- a/storage/formats/disklabel.py +++ b/storage/formats/disklabel.py @@ -50,6 +50,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 +58,11 @@ class DiskLabel(DeviceFormat): log_method_call(self, *args, **kwargs) DeviceFormat.__init__(self, *args, **kwargs) + if not self.exists: + self._labelType = kwargs.get("labelType", "msdos") + else: + self._labelType = None + self._size = None self._partedDevice = None @@ -119,10 +125,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_method_call(self, device=self.device, labelType=self._labelType) + return parted.freshDisk(device=self.partedDevice, ty=self._labelType) @property def partedDisk(self): @@ -140,6 +144,10 @@ class DiskLabel(DeviceFormat): # same as if the device had no label (cause it really # doesn't). raise InvalidDiskLabelError() + + # here's where we correct the ctor-supplied disklabel type for + # preexisting disklabels if the passed type was wrong + self._labelType = self._partedDisk.type else: self._partedDisk = self.freshPartedDisk() diff --git a/storage/partitioning.py b/storage/partitioning.py index dc06920..b9ab4c2 100644 --- a/storage/partitioning.py +++ b/storage/partitioning.py @@ -385,6 +385,11 @@ def clearPartitions(storage): # not much to do return + _platform = storage.anaconda.platform + + if not hasattr(_platform, "diskLabelTypes"): + raise StorageError("can't clear partitions without platform data") + # we are only interested in partitions that physically exist partitions = [p for p in storage.partitions if p.exists] # Sort partitions by descending partition number to minimize confusing @@ -416,8 +421,6 @@ def clearPartitions(storage): # now remove any empty extended partitions removeEmptyExtendedPartitions(storage) - _platform = storage.anaconda.platform - # 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: @@ -439,7 +442,7 @@ def clearPartitions(storage): if filter(lambda p: p.dependsOn(disk), storage.protectedDevices): continue - nativeLabelType = _platform.diskLabelType(disk.partedDevice.type) + nativeLabelType = _platform.bestDiskLabelType(disk) if disk.format.labelType == nativeLabelType: continue @@ -454,7 +457,8 @@ def clearPartitions(storage): 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) @@ -854,6 +858,9 @@ def doPartitioning(storage, exclusiveDisks=None): """ anaconda = storage.anaconda + if not hasattr(anaconda.platform, "diskLabelTypes"): + raise StorageError("can't allocate partitions without platform data") + disks = storage.partitioned if exclusiveDisks: disks = [d for d in disks if d.name in exclusiveDisks] -- 1.7.1 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list