[blivet:master 24/26] Make all devicefactory classes uses RAID objects instead of strings.

mulhern amulhern at redhat.com
Thu May 29 18:47:42 UTC 2014


Also, since LinearRAID now exists, do not have to special case 'single',
do not have to special case it in DeviceFactory.configure().

Add a constructor for MDFactory that raises an error if there is no raid level
specified.

Fix up associated tests.

Signed-off-by: mulhern <amulhern at redhat.com>
---
 blivet/devicefactory.py            | 67 ++++++++++++++++++++++++++++++--------
 tests/devicefactory_test.py        | 20 ++++++++----
 tests/devicelibs_test/raid_test.py |  8 ++---
 3 files changed, 70 insertions(+), 25 deletions(-)

diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index 5dcebd3..a42622e 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -27,6 +27,7 @@ from .formats import getFormat
 from .devicelibs import btrfs
 from .devicelibs import mdraid
 from .devicelibs import lvm
+from .devicelibs import raid
 from .partitioning import SameSizeSet
 from .partitioning import TotalSizeSet
 from .partitioning import doPartitioning
@@ -234,8 +235,8 @@ class DeviceFactory(object):
             :keyword label: filesystem label text
             :type label: str
 
-            :keyword raid_level: raid level string, eg: "raid1"
-            :type raid_level: str
+            :keyword raid_level: raid level descriptor
+            :type raid_level: any valid RAID level descriptor
             :keyword encrypted: whether to encrypt (boolean)
             :type encrypted: bool
             :keyword name: name of requested device
@@ -253,7 +254,7 @@ class DeviceFactory(object):
             :keyword container_name: name of requested container
             :type container_name: str
             :keyword container_raid_level: raid level for container
-            :type container_raid_level: str
+            :type container_raid_level: any valid RAID level descriptor
             :keyword container_encrypted: whether to encrypt the container
             :type container_encrypted: bool
             :keyword container_size: requested container size
@@ -304,6 +305,41 @@ class DeviceFactory(object):
         self.__names = []
         self.__roots = []
 
+    @property
+    def raid_level(self):
+        return self._raid_level
+
+    @raid_level.setter
+    def raid_level(self, value):
+        """ Sets the RAID level for the factory.
+
+            :param value: new RAID level
+            :param type: a valid RAID level descriptor
+            :returns: None
+        """
+        # pylint: disable=attribute-defined-outside-init
+        if value is None:
+            self._raid_level = None
+        else:
+            self._raid_level = raid.ALL_LEVELS.raidLevel(value)
+
+    @property
+    def container_raid_level(self):
+        return self._container_raid_level
+
+    @container_raid_level.setter
+    def container_raid_level(self, value):
+        """ Sets the RAID level for the factory.
+
+            :param value: new RAID level
+            :param type: a valid RAID level descriptor
+            :returns: None
+        """
+        # pylint: disable=attribute-defined-outside-init
+        if value is None:
+            self._container_raid_level = None
+        else:
+            self._container_raid_level = raid.ALL_LEVELS.raidLevel(value)
     #
     # methods related to device size and disk space requirements
     #
@@ -756,12 +792,11 @@ class DeviceFactory(object):
         # device or container raid level.
         for level_attr in ["raid_level", "container_raid_level"]:
             level = getattr(self, level_attr, None)
-            if level in [None, "single"]:
+            if level is None:
                 continue
 
-            min_disks = mdraid.RAID_levels.raidLevel(level).min_members
             disks = set(d for m in self._get_member_devices() for d in m.disks)
-            if len(disks) < min_disks:
+            if len(disks) < level.min_members:
                 raise DeviceFactoryError("Not enough disks for %s" % level)
 
         # Configure any type-specific container device. The obvious example of
@@ -1534,10 +1569,14 @@ class MDFactory(DeviceFactory):
     child_factory_fstype = "mdmember"
     size_set_class = SameSizeSet
 
+    def __init__(self, storage, size, disks, **kwargs):
+        super(MDFactory, self).__init__(storage, size, disks, **kwargs)
+        if not self.raid_level:
+            raise DeviceFactoryError("MDFactory class must have some RAID level.")
+
     def _get_device_space(self):
         member_count = len(self._get_member_devices())
-        raid_level = mdraid.RAID_levels.raidLevel(self.raid_level)
-        size_per_member = raid_level.get_base_member_size(self.size, member_count)
+        size_per_member = self.raid_level.get_base_member_size(self.size, member_count)
         size_per_member += mdraid.get_raid_superblock_size(self.size)
         return size_per_member * member_count
 
@@ -1579,11 +1618,11 @@ class BTRFSFactory(DeviceFactory):
             log.info("overriding encryption setting for btrfs factory")
             self.encrypted = False
 
-        self.container_raid_level = self.container_raid_level or "single"
-        if self.container_raid_level == "single":
-            self.size_set_class = TotalSizeSet
-        else:
+        self.container_raid_level = self.container_raid_level or btrfs.RAID_levels.raidLevel("single")
+        if self.container_raid_level.is_uniform:
             self.size_set_class = SameSizeSet
+        else:
+            self.size_set_class = TotalSizeSet
 
     def _handle_no_size(self):
         """ Set device size so that it grows to the largest size possible. """
@@ -1618,9 +1657,9 @@ class BTRFSFactory(DeviceFactory):
 
     def _get_device_space(self):
         # until we get/need something better
-        if self.container_raid_level in ("single", "raid0"):
+        if self.container_raid_level in (raid.Single, raid.RAID0):
             return self.size
-        elif self.container_raid_level in ("raid1", "raid10"):
+        elif self.container_raid_level in (raid.RAID1, raid.RAID10):
             return self.size * len(self._get_member_devices())
 
     @property
diff --git a/tests/devicefactory_test.py b/tests/devicefactory_test.py
index d4746dd..4b0e315 100644
--- a/tests/devicefactory_test.py
+++ b/tests/devicefactory_test.py
@@ -5,6 +5,7 @@ import unittest
 import blivet
 
 from blivet import devicefactory
+from blivet.devicelibs import raid
 from blivet.errors import RaidError
 from blivet.size import Size
 
@@ -18,7 +19,8 @@ class MDFactoryTestCase(unittest.TestCase):
         self.b = blivet.Blivet()
         self.factory1 = devicefactory.get_device_factory(self.b,
            devicefactory.DEVICE_TYPE_MD,
-           Size("1 GiB"))
+           Size("1 GiB"),
+           raid_level=raid.RAID1)
 
         self.factory2 = devicefactory.get_device_factory(self.b,
            devicefactory.DEVICE_TYPE_MD,
@@ -26,22 +28,26 @@ class MDFactoryTestCase(unittest.TestCase):
            raid_level=0)
 
     def testMDFactory(self):
+        self.assertRaisesRegexp(devicefactory.DeviceFactoryError,
+           "must have some RAID level",
+           devicefactory.get_device_factory,
+           self.b,
+           devicefactory.DEVICE_TYPE_MD,
+           Size("1 GiB"))
+
         self.assertRaisesRegexp(RaidError,
-           "invalid RAID level",
+           "requires at least",
            self.factory1._get_device_space)
 
         self.assertRaisesRegexp(RaidError,
-           "invalid RAID level",
+           "requires at least",
            self.factory1._configure)
 
         self.assertEqual(self.factory1.container_list, [])
 
         self.assertIsNone(self.factory1.get_container())
 
-        self.assertRaisesRegexp(RaidError,
-           "invalid RAID level",
-           self.factory1._get_new_device,
-           parents=[])
+        self.assertIsNotNone(self.factory1._get_new_device(parents=[]))
 
         self.assertRaisesRegexp(RaidError,
            "requires at least",
diff --git a/tests/devicelibs_test/raid_test.py b/tests/devicelibs_test/raid_test.py
index 4d65b39..35c912a 100644
--- a/tests/devicelibs_test/raid_test.py
+++ b/tests/devicelibs_test/raid_test.py
@@ -113,19 +113,19 @@ class RaidTestCase(unittest.TestCase):
         ## size
         ##
         sizes = [Size("32MiB"), Size("128MiB"), Size("128MiB"), Size("64MiB")]
-        for r in [l for l in raid.ALL_LEVELS if l is not raid.Container]:
+        for r in [l for l in raid.ALL_LEVELS if l not in (raid.Container, raid.Dup)]:
             self.assertEqual(r.get_size(sizes, 4, Size("1MiB"), lambda x: Size(0)),
                r.get_net_array_size(4, Size("32MiB")) if isinstance(r, raid.RAIDn) else sum(sizes))
 
-        for r in [l for l in raid.ALL_LEVELS if l is not raid.Container]:
+        for r in [l for l in raid.ALL_LEVELS if l not in (raid.Container, raid.Dup)]:
             self.assertEqual(r.get_size(sizes, 5, Size("1MiB"), lambda x: Size(0)),
                r.get_net_array_size(5, Size("32MiB")) if isinstance(r, raid.RAIDn) else sum(sizes))
 
-        for r in [l for l in raid.ALL_LEVELS if l is not raid.Container]:
+        for r in [l for l in raid.ALL_LEVELS if l not in (raid.Container, raid.Dup)]:
             self.assertEqual(r.get_size(sizes, 4, Size("1MiB"), lambda x: Size("32MiB")),
                0 if isinstance(r, raid.RAIDn) else (sum(sizes) - 4 * Size("32MiB")))
 
-        for r in [l for l in raid.ALL_LEVELS if l is not raid.Container]:
+        for r in [l for l in raid.ALL_LEVELS if l not in (raid.Container, raid.Dup)]:
             if isinstance(r, raid.RAIDn):
                 if r not in (raid.RAID1, raid.RAID10):
                     self.assertEqual(r.get_size(sizes, 4, Size("2MiB"), lambda x: Size("31MiB")), 0)
-- 
1.8.3.1



More information about the anaconda-patches mailing list