[PATCH 11/11] Add support for most device editing functions.

David Lehman dlehman at redhat.com
Thu Aug 16 21:48:50 UTC 2012


Changing label, fstype, size all mostly work.

Changing device type between lvm and partition should mostly work.

RAID options are completely untested, as is changing to a device
type of RAID.

Changing to and from a device type of BTRFS should probably work,
but there's a SIGABRT from btrfs at filesystem/volume create time
that will prevent you from actually using it.
---
 pyanaconda/ui/gui/spokes/custom.py |  129 +++++++++++++++++++++++++++++++++++-
 1 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index fe356a0..71beec2 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -499,15 +499,140 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
             return ""
 
     def _save_right_side(self, selector):
+        """ Save settings from RHS and apply changes to the device.
+
+            This method must never trigger a call to self._do_refresh.
+        """
         if not selector:
             return
 
         labelEntry = self.builder.get_object("labelEntry")
 
         device = selector._device
+        if device not in self._devices:
+            # just-removed device
+            return
+
+        log.info("ui: saving changes to device %s" % device.name)
+
+        # TODO: encryption, raid, member type
+
+        size = self.builder.get_object("sizeSpinner").get_value()
+        log.debug("new size: %s" % size)
+        log.debug("old size: %s" % device.size)
+
+        device_type = self.builder.get_object("deviceTypeCombo").get_active()
+        device_type_map = {DEVICE_TYPE_PARTITION: AUTOPART_TYPE_PLAIN,
+                           DEVICE_TYPE_BTRFS: AUTOPART_TYPE_BTRFS,
+                           DEVICE_TYPE_LVM: AUTOPART_TYPE_LVM,
+                           DEVICE_TYPE_MD: None}
+        device_type = device_type_map[device_type]
+        log.debug("new device type: %s" % device_type)
+
+        fs_type_combo = self.builder.get_object("fileSystemTypeCombo")
+        fs_type_index = fs_type_combo.get_active()
+        fs_type = fs_type_combo.get_model()[fs_type_index][0]
+        log.debug("new fs type: %s" % fs_type)
+
+        encrypted = self.builder.get_object("encryptCheckbox").get_active()
+        log.debug("new encryption setting: %s" % encrypted)
+
+        # TODO: get mountpoint, disks
+        label = self.builder.get_object("labelEntry").get_text()
+
+        # FIXME: shouldn't we be getting this from the ui somehow instead?
+        mountpoint = getattr(device.format, "mountpoint", None)
 
-        if labelEntry.get_text() and hasattr(device.format, "label"):
-            device.format.label = labelEntry.get_text()
+        with ui_storage_logger():
+            # create a new factory using the appropriate size and type
+            # XXX ignoring raid, encryption for now
+            factory = self.__storage.getDeviceFactory(device_type, size,
+                                                      disks=device.disks)
+
+        # for raid settings, we'll need to adjust the member set and container,
+        # and possibly also its devices
+
+        # for member type, we'll have to adjust the member set.
+        # XXX not going to worry about this for now
+
+        # for device type, we'll need to save the device's format, remove the
+        # current device, then create a device of the requested type.
+        device_types = {"partition": AUTOPART_TYPE_PLAIN,
+                        "lvmlv": AUTOPART_TYPE_LVM,
+                        "btrfs subvolume": AUTOPART_TYPE_BTRFS}
+        current_device_type = device_types.get(device.type)
+        if current_device_type != device_type:
+            # remove the current device
+            root = self._current_selector._root
+            self._remove_from_root(root, device)
+            self._destroy_device(device)
+
+            with ui_storage_logger():
+                # XXX skipping encryption, raid for now
+                # Use any disks with space in addition to any disks used by
+                # a defined container.
+                disks = [d for d in self._clearpartDevices
+                            if getattr(d.format, "free", 0) > 500]
+                container = self.__storage.getContainer(factory)
+                if container:
+                    disks = list(set(disks).union(container.disks))
+                log.debug("disks: %s" % [d.name for d in disks])
+                self.__storage.newDevice(device_type, size, fstype=fs_type,
+                                         disks=disks,
+                                         mountpoint=mountpoint, label=label)
+                self._devices = self.__storage.devices
+
+            # newest device should be the one with the highest id
+            max_id = max([d.id for d in self._devices])
+
+            # update the selector with the new device and its size
+            selector._device = self.__storage.devicetree.getDeviceByID(max_id)
+            selector.props.size = str(Size(spec="%f MB" % device.size)).upper()
+            self._updateSpaceDisplay()
+            return
+
+        # new size means resize for existing devices and adjust for new ones
+        if int(size) != int(device.size):
+            if device.exists and device.resizable:
+                with ui_storage_logger():
+                    self.__storage.resizeDevice(device, size)
+                    log.debug("%r" % device)
+                    log.debug("new size: %s" % device.size)
+                    log.debug("target size: %s" % device.targetSize)
+            else:
+                with ui_storage_logger():
+                    self.__storage.newDevice(device_type, size,
+                                             device=device,
+                                             disks=device.disks)
+
+            log.debug("updating selector size to '%s'"
+                       % str(Size(spec="%f MB" % device.size)).upper())
+            # update the selector's size property
+            selector.props.size = str(Size(spec="%f MB" % device.size)).upper()
+            self._updateSpaceDisplay()
+
+        # for fstype we'll need to instantiate a new DeviceFormat and schedule
+        # creation of it
+        if fs_type != device.format.type:
+            with ui_storage_logger():
+                new_format = getFormat(fs_type,
+                                       mountpoint=mountpoint, label=label,
+                                       device=device.path)
+                self.__storage.formatDevice(device, new_format)
+
+        # for encryption, I'm not sure if we'll want to modify the
+        # container/device or just create a new one
+
+        #
+        # Set various attributes that do not require actions.
+        #
+        #
+        if label and getattr(device.format, "label", label) != label:
+            device.format.label = label
+
+        if mountpoint and \
+           getattr(device.format, "mountpoint", mountpoint) != mountpoint:
+            device.format.mountpoint = mountpoint
 
     def _populate_right_side(self, selector):
         log.debug("populate_right_side: %s" % selector._device)
-- 
1.7.7.6



More information about the anaconda-patches mailing list