[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[PATCH] Use GPT on non-UEFI for disks larger than 2TB (#671230)



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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]