From 65aae880159045abe079ad07bd9f7138584a08b6 Mon Sep 17 00:00:00 2001
From: David Lehman <dlehman@redhat.com>
Date: Wed, 27 Jun 2012 11:21:46 -0500
Subject: [PATCH 11/14] Move clearPartitions into Storage.

---
 pyanaconda/kickstart.py            |    3 +-
 pyanaconda/storage/__init__.py     |  117 ++++++++++++++++++++++++++++++++++
 pyanaconda/storage/partitioning.py |  123 +-----------------------------------
 3 files changed, 119 insertions(+), 124 deletions(-)

diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 9b7124e..a3a6c5d 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -24,7 +24,6 @@ from storage.devices import LUKSDevice
 from storage.devicelibs.lvm import getPossiblePhysicalExtents
 from storage.devicelibs.mpath import MultipathConfigWriter, MultipathTopology
 from storage.formats import getFormat
-from storage.partitioning import clearPartitions
 import storage.iscsi
 import storage.fcoe
 import storage.zfcp
@@ -415,7 +414,7 @@ class ClearPart(commands.clearpart.F17_ClearPart):
         if self.initAll:
             storage.config.reinitializeDisks = self.initAll
 
-        clearPartitions(storage)
+        storage.clearPartitions()
 
 class Fcoe(commands.fcoe.F13_Fcoe):
     def parse(self, args):
diff --git a/pyanaconda/storage/__init__.py b/pyanaconda/storage/__init__.py
index 79782a2..612ee7d 100644
--- a/pyanaconda/storage/__init__.py
+++ b/pyanaconda/storage/__init__.py
@@ -810,6 +810,120 @@ class Storage(object):
 
         return True
 
+    def recursiveRemove(self, device):
+        log.debug("removing %s" % device.name)
+
+        # XXX is there any argument for not removing incomplete devices?
+        #       -- maybe some RAID devices
+        devices = self.deviceDeps(device)
+        while devices:
+            log.debug("devices to remove: %s" % ([d.name for d in devices],))
+            leaves = [d for d in devices if d.isleaf]
+            log.debug("leaves to remove: %s" % ([d.name for d in leaves],))
+            for leaf in leaves:
+                self.destroyDevice(leaf)
+                devices.remove(leaf)
+
+        if device.isDisk:
+            self.destroyFormat(device)
+        else:
+            self.destroyDevice(device)
+
+    def clearPartitions(self):
+        """ Clear partitions and dependent devices from disks.
+
+            Arguments:
+
+                None
+
+            NOTES:
+
+                - Needs some error handling
+
+        """
+        if self.config.clearPartType in (None, CLEARPART_TYPE_NONE):
+            # not much to do
+            return
+
+        # XXX FIXME: We can still clear partitions. What we can't do is create
+        #            appropriately-typed disklabels.
+        if not hasattr(self.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 self.partitions if p.exists]
+        # Sort partitions by descending partition number to minimize confusing
+        # things like multiple "destroy sda5" actions due to parted renumbering
+        # partitions. This can still happen through the UI but it makes sense to
+        # avoid it where possible.
+        partitions.sort(key=lambda p: p.partedPartition.number, reverse=True)
+        for part in partitions:
+            log.debug("clearpart: looking at %s" % part.name)
+            if not self.shouldClear(part):
+                continue
+
+            self.recursiveRemove(part)
+            log.debug("partitions: %s" % [p.getDeviceNodeName() for p in part.partedPartition.disk.partitions])
+
+        # now remove any empty extended partitions
+        self.removeEmptyExtendedPartitions()
+
+        # make sure that the the boot device has the correct disklabel type if
+        # we're going to completely clear it.
+        # also handles clearpart --initlabel
+        boot_disk = self.bootDisk
+        for disk in self.partitioned:
+            if not boot_disk and not self.config.reinitializeDisks:
+                break
+
+            if not self.config.reinitializeDisks and \
+               (boot_disk is not None and disk != boot_disk):
+                continue
+
+            if not self.shouldClear(disk):
+                continue
+
+            # don't reinitialize the disklabel if the disk contains install media
+            # or pvs from inconsistent vgs
+            if filter(lambda p: p.dependsOn(disk), self.protectedDevices):
+                continue
+
+            if disk.format.labelType == self.platform.bestDiskLabelType(disk):
+                continue
+
+            magic_partitions = {"mac": 1, "sun": 3}
+            if disk.format.labelType in magic_partitions:
+                number = magic_partitions[disk.format.labelType]
+                # remove the magic partition
+                for part in storage.partitions:
+                    if part.disk == disk and part.partedPartition.number == number:
+                        log.debug("removing %s" % part.name)
+                        # We can't schedule the magic partition for removal
+                        # because parted will not allow us to remove it from the
+                        # disk. Still, we need it out of the devicetree.
+                        self.devicetree._removeDevice(part, moddisk=False)
+
+            destroy_action = ActionDestroyFormat(disk)
+            newLabel = getFormat("disklabel", device=disk.path,
+                                 labelType=nativeLabelType)
+            create_action = ActionCreateFormat(disk, format=newLabel)
+            self.devicetree.registerAction(destroy_action)
+            self.devicetree.registerAction(create_action)
+
+        self.updateBootLoaderDiskList()
+
+    def removeEmptyExtendedPartitions(self):
+        for disk in self.partitioned:
+            log.debug("checking whether disk %s has an empty extended" % disk.name)
+            extended = disk.format.extendedPartition
+            logical_parts = disk.format.logicalPartitions
+            log.debug("extended is %s ; logicals is %s" % (extended, [p.getDeviceNodeName() for p in logical_parts]))
+            if extended and not logical_parts:
+                log.debug("removing empty extended partition from %s" % disk.name)
+                extended_name = devicePathToName(extended.getDeviceNodeName())
+                extended = self.devicetree.getDeviceByName(extended_name)
+                self.destroyDevice(extended)
+
     def getFreeSpace(self, disks=None, clearPartType=None):
         """ Return a dict with free space info for each disk.
 
@@ -1608,6 +1722,9 @@ class Storage(object):
         return self._bootloader
 
     def updateBootLoaderDiskList(self):
+        if not self.bootloader:
+            return
+
         boot_disks = [d for d in self.disks if d.partitioned]
         boot_disks.sort(cmp=self.compareDisks, key=lambda d: d.name)
         self.bootloader.set_disk_list(boot_disks)
diff --git a/pyanaconda/storage/partitioning.py b/pyanaconda/storage/partitioning.py
index 43f77a7..b77f499 100644
--- a/pyanaconda/storage/partitioning.py
+++ b/pyanaconda/storage/partitioning.py
@@ -296,7 +296,7 @@ def doAutoPartition(storage, data):
 
     if storage.doAutoPart:
         scheduleShrinkActions(storage)
-        clearPartitions(storage)
+        storage.clearPartitions()
 
         disks = _getCandidateDisks(storage)
         devs = _scheduleImplicitPartitions(storage, disks)
@@ -341,127 +341,6 @@ def doAutoPartition(storage, data):
             storage.reset()
             raise exn
 
-def recursiveRemove(storage, device):
-    log.debug("clearing %s" % device.name)
-
-    # XXX is there any argument for not removing incomplete devices?
-    #       -- maybe some RAID devices
-    devices = storage.deviceDeps(device)
-    while devices:
-        log.debug("devices to remove: %s" % ([d.name for d in devices],))
-        leaves = [d for d in devices if d.isleaf]
-        log.debug("leaves to remove: %s" % ([d.name for d in leaves],))
-        for leaf in leaves:
-            storage.destroyDevice(leaf)
-            devices.remove(leaf)
-
-    if device.isDisk:
-        storage.destroyFormat(device)
-    else:
-        storage.destroyDevice(device)
-
-def clearPartitions(storage):
-    """ Clear partitions and dependent devices from disks.
-
-        Arguments:
-
-            storage -- a storage.Storage instance
-
-        Keyword arguments:
-
-            None
-
-        NOTES:
-
-            - Needs some error handling, especially for the parted bits.
-
-    """
-    if storage.config.clearPartType in (None, CLEARPART_TYPE_NONE):
-        # not much to do
-        return
-
-    if not hasattr(storage.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
-    # things like multiple "destroy sda5" actions due to parted renumbering
-    # partitions. This can still happen through the UI but it makes sense to
-    # avoid it where possible.
-    partitions.sort(key=lambda p: p.partedPartition.number, reverse=True)
-    for part in partitions:
-        log.debug("clearpart: looking at %s" % part.name)
-        if not storage.shouldClear(part):
-            continue
-
-        recursiveRemove(storage, part)
-        log.debug("partitions: %s" % [p.getDeviceNodeName() for p in part.partedPartition.disk.partitions])
-
-    # now remove any empty extended partitions
-    removeEmptyExtendedPartitions(storage)
-
-    # make sure that the the boot device has the correct disklabel type if
-    # we're going to completely clear it.
-    # also handles clearpart --initlabel
-    boot_disk = storage.bootDisk
-    for disk in storage.partitioned:
-        if not boot_disk and not storage.config.reinitializeDisks:
-            break
-
-        if not storage.config.reinitializeDisks and \
-           (boot_disk is not None and disk != boot_disk):
-            continue
-
-        if storage.config.clearPartType != CLEARPART_TYPE_ALL or \
-           (storage.config.clearPartDisks and
-            disk.name not in storage.config.clearPartDisks):
-            continue
-
-        # don't reinitialize the disklabel if the disk contains install media
-        # or pvs from inconsistent vgs
-        if filter(lambda p: p.dependsOn(disk), storage.protectedDevices):
-            continue
-
-        nativeLabelType = storage.platform.bestDiskLabelType(disk)
-        if disk.format.labelType == nativeLabelType:
-            continue
-
-        magic_partitions = {"mac": 1, "sun": 3}
-        if disk.format.labelType in magic_partitions:
-            number = magic_partitions[disk.format.labelType]
-            # remove the magic partition
-            for part in storage.partitions:
-                if part.disk == disk and part.partedPartition.number == number:
-                    log.debug("clearing %s" % part.name)
-                    # We can't schedule the magic partition for removal
-                    # because parted will not allow us to remove it from the
-                    # disk. Still, we need it out of the devicetree.
-                    storage.devicetree._removeDevice(part, moddisk=False)
-
-        destroy_action = ActionDestroyFormat(disk)
-        newLabel = getFormat("disklabel", device=disk.path,
-                             labelType=nativeLabelType)
-        create_action = ActionCreateFormat(disk, format=newLabel)
-        storage.devicetree.registerAction(destroy_action)
-        storage.devicetree.registerAction(create_action)
-
-    if storage.bootloader:
-        storage.updateBootLoaderDiskList()
-
-def removeEmptyExtendedPartitions(storage):
-    for disk in storage.partitioned:
-        log.debug("checking whether disk %s has an empty extended" % disk.name)
-        extended = disk.format.extendedPartition
-        logical_parts = disk.format.logicalPartitions
-        log.debug("extended is %s ; logicals is %s" % (extended, [p.getDeviceNodeName() for p in logical_parts]))
-        if extended and not logical_parts:
-            log.debug("removing empty extended partition from %s" % disk.name)
-            extended_name = devicePathToName(extended.getDeviceNodeName())
-            extended = storage.devicetree.getDeviceByName(extended_name)
-            storage.destroyDevice(extended)
-            #disk.partedDisk.removePartition(extended.partedPartition)
-
 def partitionCompare(part1, part2):
     """ More specifically defined partitions come first.
 
-- 
1.7.7.6

