[anaconda:master] RAID related changes for custom spoke.

mulhern amulhern at redhat.com
Thu May 29 18:48:09 UTC 2014


- RAID objects instead of strings are now used everywhere. Previously,
the approach was a bit more hybrid, with strings floating around here
and there.

- Move get_supported_raid_levels to blivet.devicefactory. This method
is supposed to yield the raid levels that blivet supports, not necessarily
those that anaconda allows. The return type is changed to a set of RAID
objects during the move and the return values are somewhat modified.
* btrfs substitutes single for none
* lvm omits none
* RAID adds container and linear

- Currently RAID levels are only offered on the Manual Partitioning screen
if the user has selected RAID. So, the only options that are ever shown are
one that RAID allows. There is little point in having other always invisible
options, so there are none left in the custom.glade file.
Previously there was "none".

- In CustomPartitioningSpoke._validate_mountpoint RAID related validation
tests have been generalized a bit.

- blivet.devices.Device.raidLevel replaces
blivet.devicefactory.get_raid_level.

- In _save_right_side the container raid level validation has been
generalized a bit.

- CustomPartitioningSpoke._raid_level_visible has been generalized to
use raidLevelsSupported().

- CustomPartitiongSpoke._populate_raid has been simplified a bit,
and generalized a bit.

- In on_device_type_changed some general methods are used. Previously the
code sets btrfs's raid_level and passed it to _populate_raid(), but
_populate_raid() never displays any RAID choices for btrfs on manual
partitoning screen, so this code had no effect. Btrfs RAID choices are
shown on the "Configure Volume" screen, reached by pressing the Modify
button. The effectless code is just removed. This leaves a few unused
identifiers, which are also removed.

- "none" is removed from the custom_storage_helpers.glade RAID options for
the "Configure Volume/Configure Volume Group" window, "single" is added
for btrfs, and linear is added for the mdadm RAID options for lvm. This
has the added benefit of giving the user at least one RAID choice that
only requires one disk. "linear" and "single" are the default RAID levels
for this situation.
There is a sense in which "none" should be offered for lvm on RAID, since
if there is only one disk no RAID level is necessary, but that seems unduly
complicated and "linear" will do just as well.

- selectedRaidLevel() is changed so that it returns a RAIDLevel object or
None, rather than a string.

- Several methods are added to custom_storage_helpers.py. They are small
and copiously commented.

- ContainerDialog._raid_level_visible can be simplified by using
containerRaidLevelsSupported(), one of the newly introduced methods.

- ContainerDialog._populate_raid() can also be simplified a bit.

Signed-off-by: mulhern <amulhern at redhat.com>
---
 pyanaconda/storage_utils.py                        |  17 ---
 pyanaconda/ui/gui/spokes/custom.glade              |   4 -
 pyanaconda/ui/gui/spokes/custom.py                 |  88 ++++++------
 .../ui/gui/spokes/lib/custom_storage_helpers.glade |   8 +-
 .../ui/gui/spokes/lib/custom_storage_helpers.py    | 151 +++++++++++++++++----
 5 files changed, 179 insertions(+), 89 deletions(-)

diff --git a/pyanaconda/storage_utils.py b/pyanaconda/storage_utils.py
index 6478282..f353c6d 100644
--- a/pyanaconda/storage_utils.py
+++ b/pyanaconda/storage_utils.py
@@ -40,18 +40,6 @@ from pykickstart.constants import AUTOPART_TYPE_LVM, AUTOPART_TYPE_LVM_THINP
 import logging
 log = logging.getLogger("anaconda")
 
-# should this and the get_supported_raid_levels go to blivet.devicefactory???
-SUPPORTED_RAID_LEVELS = {DEVICE_TYPE_LVM: {"none", "raid0", "raid1"},
-                         DEVICE_TYPE_LVM_THINP: {"none", "raid0", "raid1"},
-                         DEVICE_TYPE_MD: {"raid0", "raid1", "raid4", "raid5",
-                                          "raid6", "raid10"},
-                         DEVICE_TYPE_BTRFS: {"none", "raid0", "raid1",
-                                             "raid10"},
-                         # no device type for LVM VG
-                         # VG: {"none", "raid0", "raid1", "raid4",
-                         #      "raid5", "raid6", "raid10"},
-                        }
-
 # TODO: all those constants and mappings should go to blivet
 DEVICE_TEXT_LVM = N_("LVM")
 DEVICE_TEXT_LVM_THINP = N_("LVM Thin Provisioning")
@@ -114,11 +102,6 @@ def size_from_input(input_str):
 
     return size
 
-def get_supported_raid_levels(device_type):
-    """Get supported RAID levels for the given device type."""
-
-    return SUPPORTED_RAID_LEVELS.get(device_type, set())
-
 def device_type_from_autopart(autopart_type):
     """Get device type matching the given autopart type."""
 
diff --git a/pyanaconda/ui/gui/spokes/custom.glade b/pyanaconda/ui/gui/spokes/custom.glade
index 859712b..4a4900a 100644
--- a/pyanaconda/ui/gui/spokes/custom.glade
+++ b/pyanaconda/ui/gui/spokes/custom.glade
@@ -59,10 +59,6 @@
     </columns>
     <data>
       <row>
-        <col id="0" translatable="yes">None</col>
-        <col id="1">none</col>
-      </row>
-      <row>
         <col id="0" translatable="yes">RAID0 &lt;span foreground="grey"&gt;(Performance)&lt;/span&gt;</col>
         <col id="1">raid0</col>
       </row>
diff --git a/pyanaconda/ui/gui/spokes/custom.py b/pyanaconda/ui/gui/spokes/custom.py
index 328cf61..6f7aa52 100644
--- a/pyanaconda/ui/gui/spokes/custom.py
+++ b/pyanaconda/ui/gui/spokes/custom.py
@@ -50,7 +50,6 @@ from blivet.devicefactory import DEVICE_TYPE_PARTITION
 from blivet.devicefactory import DEVICE_TYPE_MD
 from blivet.devicefactory import DEVICE_TYPE_DISK
 from blivet.devicefactory import DEVICE_TYPE_LVM_THINP
-from blivet.devicefactory import get_raid_level
 from blivet.devicefactory import SIZE_POLICY_AUTO
 from blivet import findExistingInstallations
 from blivet.partitioning import doAutoPartition
@@ -60,11 +59,11 @@ from blivet.errors import NotEnoughFreeSpaceError
 from blivet.errors import SanityError
 from blivet.errors import SanityWarning
 from blivet.errors import LUKSDeviceWithoutKeyError
-from blivet.devicelibs import mdraid
+from blivet.devicelibs import raid
 from blivet.devices import LUKSDevice
 
-from pyanaconda.storage_utils import get_supported_raid_levels, ui_storage_logger, device_type_from_autopart
-from pyanaconda.storage_utils import DEVICE_TEXT_PARTITION, DEVICE_TEXT_MD, DEVICE_TEXT_MAP
+from pyanaconda.storage_utils import ui_storage_logger, device_type_from_autopart
+from pyanaconda.storage_utils import DEVICE_TEXT_PARTITION, DEVICE_TEXT_MAP
 from pyanaconda.storage_utils import PARTITION_ONLY_FORMAT_TYPES, MOUNTPOINT_DESCRIPTIONS
 from pyanaconda.storage_utils import NAMED_DEVICE_TYPES, CONTAINER_DEVICE_TYPES
 
@@ -78,7 +77,8 @@ from pyanaconda.ui.gui.spokes.lib.refresh import RefreshDialog
 from pyanaconda.ui.gui.spokes.lib.summary import ActionSummaryDialog
 
 from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import size_from_entry
-from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import validate_label, validate_mountpoint, selectedRaidLevel
+from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import validate_label, validate_mountpoint
+from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import selectedRaidLevel, raidLevelSelection, defaultRaidLevel, requiresRaidSelection, containerRaidLevelsSupported, raidLevelsSupported
 from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import get_container_type_name, RAID_NOT_ENOUGH_DISKS
 from pyanaconda.ui.gui.spokes.lib.custom_storage_helpers import AddDialog, ConfirmDeleteDialog, DisksDialog, ContainerDialog, HelpDialog
 
@@ -609,6 +609,16 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
 
     def _validate_mountpoint(self, mountpoint, device, device_type, new_fs_type,
                             reformat, encrypted, raid_level):
+        """ Validate various aspects of a mountpoint.
+
+            :param str mountpoint: the mountpoint
+            :param device: blivet.devices.Device instance
+            :param int device_type: one of an enumeration of device types
+            :param str new_fs_type: string representing the new filesystem type
+            :param bool reformat: whether the device is to be reformatted
+            :param bool encrypted: whether the device is to be encrypted
+            :param raid_level: instance of blivet.devicelibs.raid.RAIDLevel or None
+        """
         error = None
         if device_type != DEVICE_TYPE_PARTITION and mountpoint == "/boot/efi":
             error = (_("/boot/efi must be on a device of type %s")
@@ -623,14 +633,17 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
             error = _("%s cannot be encrypted") % new_fs_type
         elif mountpoint == "/" and device.format.exists and not reformat:
             error = _("You must create a new filesystem on the root device.")
-        elif device_type == DEVICE_TYPE_MD and raid_level in (None, "single"):
-            error = _("Devices of type %s require a valid RAID level selection.") % _(DEVICE_TEXT_MD)
 
-        if not error and raid_level not in (None, "single"):
-            md_level = mdraid.getRaidLevel(raid_level)
-            min_disks = md_level.min_members
+        if not error and raid_level is None and requiresRaidSelection(device_type):
+            error = _("Devices of type %s require a valid RAID level selection.") % _(DEVICE_TEXT_MAP[device_type])
+
+        if not error and raid_level is not None and raid_level not in raidLevelsSupported(device_type):
+            error = _("Device of type %s does not support RAID level selection %s.") % (_(DEVICE_TEXT_MAP[device_type]), raid_level)
+
+        if not error and raid_level is not None:
+            min_disks = raid_level.min_members
             if len(self._device_disks) < min_disks:
-                error = _(RAID_NOT_ENOUGH_DISKS) % {"level": md_level,
+                error = _(RAID_NOT_ENOUGH_DISKS) % {"level": raid_level,
                                                     "min" : min_disks,
                                                     "count": len(self._device_disks)}
 
@@ -962,7 +975,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
 
         # RAID LEVEL
         raid_level = selectedRaidLevel(self._raidLevelCombo)
-        old_raid_level = get_raid_level(device)
+        old_raid_level = device.raidLevel
         changed_raid_level = (old_device_type == device_type and
                               device_type in (DEVICE_TYPE_MD,
                                               DEVICE_TYPE_BTRFS) and
@@ -1014,7 +1027,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
             if old_container:
                 old_container_name = old_container.name
                 old_container_encrypted = old_container.encrypted
-                old_container_raid_level = get_raid_level(old_container)
+                old_container_raid_level = old_container.raidLevel
                 old_container_size = getattr(old_container, "size_policy",
                                                             old_container.size)
 
@@ -1031,7 +1044,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
         changed_container_encrypted = (container_encrypted != old_container_encrypted)
 
         container_raid_level = self._device_container_raid_level
-        if container_raid_level == "single" and device_type != DEVICE_TYPE_BTRFS:
+        if container_raid_level is not None and container_raid_level not in containerRaidLevelsSupported(device_type):
             container_raid_level = None
 
         old_device_info["container_raid_level"] = old_container_raid_level
@@ -1175,26 +1188,28 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
 
     def _raid_level_visible(self, model, itr, user_data):
         device_type = self._get_current_device_type()
-        raid_level = model[itr][1]
-        return raid_level in get_supported_raid_levels(device_type)
+        raid_level = raid.ALL_LEVELS.raidLevel(model[itr][1])
+        return raid_level in raidLevelsSupported(device_type)
 
     def _populate_raid(self, raid_level):
-        """ Set up the raid-specific portion of the device details. """
+        """ Set up the raid-specific portion of the device details.
+
+            :param raid_level: RAID level
+            :type raid_level: instance of blivet.devicelibs.raid.RAIDLevel or None
+        """
         device_type = self._get_current_device_type()
         log.debug("populate_raid: %s, %s", device_type, raid_level)
 
-        if device_type == DEVICE_TYPE_MD:
-            base_level = "raid1"
-        else:
+        if not raidLevelsSupported(device_type):
             map(really_hide, [self._raidLevelLabel, self._raidLevelCombo])
             return
 
-        if not raid_level:
-            raid_level = base_level
+        raid_level = raid_level or defaultRaidLevel(device_type)
+        raid_level_name = raidLevelSelection(raid_level)
 
         # Set a default RAID level in the combo.
         for (i, row) in enumerate(self._raidLevelCombo.get_model()):
-            if row[1] == raid_level:
+            if row[1] == raid_level_name:
                 self._raidLevelCombo.set_active(i)
                 break
 
@@ -1211,13 +1226,13 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
     def _update_container_info(self, use_dev):
         if hasattr(use_dev, "vg"):
             self._device_container_name = use_dev.vg.name
-            self._device_container_raid_level = get_raid_level(use_dev.vg)
+            self._device_container_raid_level = use_dev.vg.raidLevel
             self._device_container_encrypted = use_dev.vg.encrypted
             self._device_container_size = use_dev.vg.size_policy
         elif hasattr(use_dev, "volume") or hasattr(use_dev, "subvolumes"):
             volume = getattr(use_dev, "volume", use_dev)
             self._device_container_name = volume.name
-            self._device_container_raid_level = get_raid_level(volume)
+            self._device_container_raid_level = volume.raidLevel
             self._device_container_encrypted = volume.encrypted
             self._device_container_size = volume.size_policy
         else:
@@ -1410,8 +1425,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
         else:
             self._sizeEntry.set_tooltip_text(_("This file system may not be resized."))
 
-        raid_level = devicefactory.get_raid_level(device)
-        self._populate_raid(raid_level)
+        self._populate_raid(device.raidLevel)
         self._populate_container(device=use_dev)
         # do this last in case this was set sensitive in on_device_type_changed
         if use_dev.exists or use_dev.type == "btrfs volume":
@@ -1534,7 +1548,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
             # don't override user-initiated changes to a defined container
             dev_info["disks"] = container.disks
             dev_info.update({"container_encrypted": container.encrypted,
-                             "container_raid_level": get_raid_level(container),
+                             "container_raid_level": container.raidLevel,
                              "container_size": getattr(container, "size_policy",
                                                        container.size)})
 
@@ -1555,7 +1569,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
                 # don't override user-initiated changes to a defined container
                 dev_info["disks"] = container.disks
                 dev_info.update({"container_encrypted": container.encrypted,
-                                 "container_raid_level": get_raid_level(container),
+                                 "container_raid_level": container.raidLevel,
                                  "container_size": getattr(container, "size_policy",
                                                                container.size),
                                  "container_name": container.name})
@@ -1722,7 +1736,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
            self._storage_playground.devicetree.getChildren(container) and \
            container.size_policy == SIZE_POLICY_AUTO:
             cont_encrypted = container.encrypted
-            cont_raid = get_raid_level(container)
+            cont_raid = container.raidLevel
             cont_size = container.size_policy
             cont_name = container.name
             factory = devicefactory.get_device_factory(self._storage_playground,
@@ -2042,7 +2056,7 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
         container_exists = getattr(container, "exists", False)    # might not be in the tree
 
         if container:
-            self._device_container_raid_level = get_raid_level(container)
+            self._device_container_raid_level = container.raidLevel
             self._device_container_encrypted = container.encrypted
             self._device_container_size = getattr(container, "size_policy",
                                                              container.size)
@@ -2379,18 +2393,8 @@ class CustomPartitioningSpoke(NormalSpoke, StorageChecker):
             test_fmt = getFormat("btrfs")
             should_be_btrfs = test_fmt.supported and test_fmt.formattable
             fs_type_sensitive = False
-            with ui_storage_logger():
-                factory = devicefactory.get_device_factory(self._storage_playground,
-                                                         DEVICE_TYPE_BTRFS, 0)
-                container = factory.get_container()
-
-            if container:
-                raid_level = container.dataLevel or "single"
-            else:
-                # here I suppose we could alter the default based on disk count
-                raid_level = "single"
         elif new_type == DEVICE_TYPE_MD:
-            raid_level = "raid1"
+            raid_level = defaultRaidLevel(new_type)
 
         # lvm uses the RHS to set disk set. no foolish minds here.
         exists = self._current_selector and self._current_selector.device.exists
diff --git a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.glade b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.glade
index ecec01e..fa23c6c 100644
--- a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.glade
+++ b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.glade
@@ -21,8 +21,12 @@
     </columns>
     <data>
       <row>
-        <col id="0" translatable="yes">None</col>
-        <col id="1">none</col>
+        <col id="0" translatable="yes">Linear &lt;span foreground="grey"&gt;(No Redundancy, No Striping)&lt;/span&gt;</col>
+        <col id="1">linear</col>
+      </row>
+      <row>
+        <col id="0" translatable="yes">Single &lt;span foreground="grey"&gt;(No Redundancy, No Striping)&lt;/span&gt;</col>
+        <col id="1">single</col>
       </row>
       <row>
         <col id="0" translatable="yes">RAID0 &lt;span foreground="grey"&gt;(Performance)&lt;/span&gt;</col>
diff --git a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
index ed5774d..3d3efa2 100644
--- a/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
+++ b/pyanaconda/ui/gui/spokes/lib/custom_storage_helpers.py
@@ -24,7 +24,9 @@
 """Helper functions and classes for custom partitioning."""
 
 __all__ = ["size_from_entry", "populate_mountpoint_store", "validate_label",
-           "validate_mountpoint", "selectedRaidLevel", "get_container_type_name",
+           "validate_mountpoint", "selectedRaidLevel", "raidLevelSelection",
+           "defaultRaidLevel", "requiresRaidSelection",
+           "containerRaidLevelsSupported", "raidLevelsSupported", "get_container_type_name",
            "AddDialog", "ConfirmDeleteDialog", "DisksDialog", "ContainerDialog",
            "HelpDialog"]
 
@@ -32,7 +34,7 @@ import re
 
 from pyanaconda.product import productName
 from pyanaconda.iutil import lowerASCII
-from pyanaconda.storage_utils import size_from_input, get_supported_raid_levels
+from pyanaconda.storage_utils import size_from_input
 from pyanaconda.ui.helpers import InputCheck
 from pyanaconda.ui.gui import GUIObject
 from pyanaconda.ui.gui.helpers import GUIDialogInputCheckHandler
@@ -45,10 +47,13 @@ from blivet.formats import getFormat
 from blivet.devicefactory import SIZE_POLICY_AUTO
 from blivet.devicefactory import SIZE_POLICY_MAX
 from blivet.devicefactory import DEVICE_TYPE_LVM
-from blivet.devicefactory import DEVICE_TYPE_MD
 from blivet.devicefactory import DEVICE_TYPE_BTRFS
 from blivet.devicefactory import DEVICE_TYPE_LVM_THINP
+from blivet.devicefactory import DEVICE_TYPE_MD
+from blivet.devicefactory import get_supported_raid_levels
+from blivet.devicelibs import btrfs
 from blivet.devicelibs import mdraid
+from blivet.devicelibs import raid
 
 import logging
 log = logging.getLogger("anaconda")
@@ -139,7 +144,11 @@ def validate_mountpoint(mountpoint, used_mountpoints, strict=True):
         return ""
 
 def selectedRaidLevel(raidLevelCombo):
-    """Interpret the selection of a RAID level combo box."""
+    """Interpret the selection of a RAID level combo box.
+
+       :returns: the selected raid level, None if none selected
+       :rtype: instance of blivet.devicelibs.raid.RaidLevel or NoneType
+    """
     if not raidLevelCombo.get_property("visible"):
         # the combo is hidden when raid level isn't applicable
         return None
@@ -154,7 +163,106 @@ def selectedRaidLevel(raidLevelCombo):
     if selected_level == "none":
         return None
     else:
-        return selected_level
+        return raid.ALL_LEVELS.raidLevel(selected_level)
+
+def raidLevelSelection(raid_level):
+    """ Returns a string corresponding to the RAID level.
+
+        :param raid_level: a raid level
+        :type raid_level: instance of blivet.devicelibs.raid.RAID or None
+        :returns: a string corresponding to this raid level
+        :rtype: str
+    """
+    return raid_level.name if raid_level else "none"
+
+def containerDeviceType(device_type):
+    """ Returns the container device type used to select RAID options.
+
+        Generally this is the same as the device type, except that anaconda
+        supports lvm on RAID, so that lvm's container device type is actually
+        that for RAID.
+
+        :param int device_type: an int representing the device_type
+        :returns: the device type for choosing container raid level
+        :rtype: an int representing a device type
+    """
+    if device_type in (DEVICE_TYPE_LVM, DEVICE_TYPE_LVM_THINP):
+        return DEVICE_TYPE_MD
+    else:
+        return device_type
+
+def defaultRaidLevel(device_type):
+    """ Returns the default RAID level for this device type.
+
+        :param int device_type: an int representing the device_type
+        :returns: the default RAID level for this device type or None
+        :rtype: blivet.devicelibs.raid.RAIDLevel or NoneType
+    """
+    if device_type == DEVICE_TYPE_BTRFS:
+        return btrfs.RAID_levels.raidLevel("single")
+
+    if device_type == DEVICE_TYPE_MD:
+        return mdraid.RAID_levels.raidLevel("raid1")
+
+    return None
+
+def defaultContainerRaidLevel(device_type):
+    """ Returns the default RAID level for this device type's container type.
+
+        :param int device_type: an int representing the device_type
+        :returns: the default RAID level for this device type's container or None
+        :rtype: blivet.devicelibs.raid.RAIDLevel or NoneType
+    """
+    container_device_type = containerDeviceType(device_type)
+
+    if container_device_type == DEVICE_TYPE_BTRFS:
+        return btrfs.RAID_levels.raidLevel("single")
+
+    if container_device_type == DEVICE_TYPE_MD:
+        return mdraid.RAID_levels.raidLevel("linear")
+
+    return None
+
+def requiresRaidSelection(device_type):
+    """ Whether GUI requires a RAID level be selected for this device type."""
+    return device_type == DEVICE_TYPE_MD
+
+def raidLevelsSupported(device_type):
+    """ The raid levels anaconda supports for this device type.
+
+        It supports all RAID levels that blivet supports for a type,
+        minus those it doesn't like.
+
+        Since anaconda only ever allows the user to choose RAID levels for
+        device type DEVICE_TYPE_MD, hiding the RAID menu for all other device
+        types, the function only returns a non-empty set for this device type.
+        If this changes, then so should this function, but at this time it
+        is not clear what RAID levels should be offered for other device types.
+
+        :param int device_type: one of an enumeration of device types
+        :returns: a set of supported raid levels
+        :rtype: a set of instances of blivet.devicelibs.raid.RAIDLevel
+    """
+    if device_type == DEVICE_TYPE_MD:
+        unsupported = set(raid.RAIDLevels(["container", "linear"]))
+        return get_supported_raid_levels(device_type).difference(unsupported)
+    else:
+        return set()
+
+def containerRaidLevelsSupported(device_type):
+    """ The raid levels anaconda supports for a container for this
+        device_type.
+
+        It supports the RAID levels that blivet supports minus some that
+        it does not like.
+
+        :param int device_type: one of an enumeration of device types
+        :returns: a set of supported raid levels
+        :rtype: a set of instances of blivet.devicelibs.raid.RAIDLevel
+    """
+    container_device_type = containerDeviceType(device_type)
+    unsupported = set(raid.RAIDLevels(["container"]))
+    return get_supported_raid_levels(container_device_type).difference(unsupported)
 
 def get_container_type_name(device_type):
     return CONTAINER_TYPE_NAMES.get(device_type, _("container"))
@@ -429,10 +537,9 @@ class ContainerDialog(GUIObject, GUIDialogInputCheckHandler):
 
         raid_level = selectedRaidLevel(self._raidLevelCombo)
         if raid_level:
-            md_level = mdraid.getRaidLevel(raid_level)
-            min_disks = md_level.min_members
+            min_disks = raid_level.min_members
             if len(paths) < min_disks:
-                self._error = (_(RAID_NOT_ENOUGH_DISKS) % {"level" : md_level,
+                self._error = (_(RAID_NOT_ENOUGH_DISKS) % {"level" : raid_level,
                                                            "min" : min_disks,
                                                            "count" : len(paths)})
                 self._error_label.set_text(self._error)
@@ -484,32 +591,28 @@ class ContainerDialog(GUIObject, GUIDialogInputCheckHandler):
         else:
             self._sizeEntry.set_sensitive(True)
 
-    def _raid_level_visible(self, model, itr, user_data):
-        raid_level = model[itr][1]
 
-        # This is weird because for lvm's container-wide raid we use md.
-        if self.device_type in (DEVICE_TYPE_LVM, DEVICE_TYPE_LVM_THINP):
-            # no RAID is an option for LVM(ThP) as well
-            return (raid_level == "none" or
-                    raid_level in get_supported_raid_levels(DEVICE_TYPE_MD))
-        else:
-            return raid_level in get_supported_raid_levels(self.device_type)
+    def _raid_level_visible(self, model, itr, user_data):
+        raid_level = raid.ALL_LEVELS.raidLevel(model[itr][1])
+        return raid_level in containerRaidLevelsSupported(self.device_type)
 
     def _populate_raid(self):
-        """ Set up the raid-specific portion of the device details. """
-        if not get_supported_raid_levels(self.device_type):
-            # no supported raid levels for this device type
+        """ Set up the raid-specific portion of the device details.
+
+            Hide the RAID level menu if this device type does not support RAID.
+            Choose a default RAID level.
+        """
+        if not containerRaidLevelsSupported(self.device_type):
             map(really_hide, [self._raidLevelLabel, self._raidLevelCombo])
             return
 
-        raid_level = self.raid_level
-        if not raid_level or raid_level == "single":
-            raid_level = "none"
+        raid_level = self.raid_level or defaultContainerRaidLevel(self.device_type)
+        raid_level_name = raidLevelSelection(raid_level)
 
         # Set a default RAID level in the combo.
         for (i, row) in enumerate(self._raidLevelCombo.get_model()):
             log.debug("container dialog: raid level %s", row[1])
-            if row[1] == raid_level:
+            if row[1] == raid_level_name:
                 self._raidLevelCombo.set_active(i)
                 break
 
-- 
1.8.3.1



More information about the anaconda-patches mailing list