[rhel7-branch 2/6] Check if device has enough members when setting RAID level (#1202877)

mulkieran installerbot-noreply at redhat.com
Tue Jun 2 22:34:48 UTC 2015


From: mulhern <amulhern at redhat.com>

Related: rhbz#1019685
Related: rhbz#1202877

(cherry picked from commit 08d1d1042adcd9dda535e4681edb2bf10b7e6fad)

RAID levels have minimum member requirements. Level setters now raise a
BTRFSValueError if device does not have enough members to meet the minimum
requirement. However, if the device exists its members may not be known
yet, so the check is omitted.

Also, RaidError is rethrown as BTRFSValueError in level setter if the level
is not valid for its use. Previously the RaidError was just propagated.

Also, self._dataLevel and self._metaDataLevel are explicitly assigned to
in __init__ to avoid need to disable pylint attributed-defined-outside-init
warning in setter function. The assignment is all on one line, because that
is its sole purpose, and with the comment to explain it it still takes up
two lines.

Signed-off-by: mulhern <amulhern at redhat.com>
---
 blivet/devices/btrfs.py | 60 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py
index d1bdf44..9ad45dc 100644
--- a/blivet/devices/btrfs.py
+++ b/blivet/devices/btrfs.py
@@ -161,6 +161,9 @@ def __init__(self, *args, **kwargs):
 
         super(BTRFSVolumeDevice, self).__init__(*args, **kwargs)
 
+        # avoid attribute-defined-outside-init pylint warning
+        self._dataLevel = self._metaDataLevel = None
+
         # assign after constructor to avoid AttributeErrors in setter functions
         self.dataLevel = dataLevel
         self.metaDataLevel = metaDataLevel
@@ -180,6 +183,49 @@ def __init__(self, *args, **kwargs):
 
         self._defaultSubVolumeID = None
 
+    def _validateRaidLevel(self, level):
+        """ Returns an error message if the RAID level is invalid for this
+            device, otherwise None.
+
+            :param level: a RAID level
+            :type level: :class:`~.devicelibs.raid.RAIDLevel`
+            :returns: an error message if the RAID level is invalid, else None
+            :rtype: str or NoneType
+        """
+        if not self.exists and len(self.parents) < level.min_members:
+            return "RAID level %s requires that device have at least %d members, but device has only %d members." % (level, level.min_members, len(self.parents))
+        return None
+
+    def _setLevel(self, value, data):
+        """ Sets a valid level for this device and level type.
+
+            :param object value: value for this RAID level
+            :param bool data: True if for data, False if for metadata
+
+            :returns: a valid level for value, if any, else None
+            :rtype: :class:`~.devicelibs.raid.RAIDLevel` or NoneType
+
+            :raises: :class:`~.errors.BTRFSValueError` if value represents
+            an invalid level.
+        """
+        level = None
+        if value:
+            try:
+                levels = btrfs.RAID_levels if data else btrfs.metadata_levels
+                level = levels.raidLevel(value)
+            except errors.RaidError:
+                data_type_str = "data" if data else "metadata"
+                raise errors.BTRFSValueError("%s is an invalid value for %s RAID level." % (value, data_type_str))
+
+            error_msg = self._validateRaidLevel(level)
+            if error_msg:
+                raise errors.BTRFSValueError(error_msg)
+
+        if data:
+            self._dataLevel = level
+        else:
+            self._metaDataLevel = level
+
     @property
     def dataLevel(self):
         """ Return the RAID level for data.
@@ -193,12 +239,11 @@ def dataLevel(self):
     def dataLevel(self, value):
         """ Set the RAID level for data.
 
-            :param value: new raid level
-            :param type:  a valid raid level descriptor
+            :param object value: new raid level
             :returns:     None
+            :raises: :class:`~.errors.BTRFSValueError`
         """
-        # pylint: disable=attribute-defined-outside-init
-        self._dataLevel = btrfs.RAID_levels.raidLevel(value) if value else None
+        self._setLevel(value, True)
 
     @property
     def metaDataLevel(self):
@@ -213,12 +258,11 @@ def metaDataLevel(self):
     def metaDataLevel(self, value):
         """ Set the RAID level for metadata.
 
-            :param value: new raid level
-            :param type:  a valid raid level descriptor
+            :param object value: new raid level
             :returns:     None
+            :raises: :class:`~.errors.BTRFSValueError`
         """
-        # pylint: disable=attribute-defined-outside-init
-        self._metaDataLevel = btrfs.metadata_levels.raidLevel(value) if value else None
+        self._setLevel(value, False)
 
     @property
     def formatImmutable(self):


-- 
To view this commit on github, visit https://github.com/rhinstaller/blivet/commit/0a8c529b2580d100152b39e94a3b49d9873d0468


More information about the anaconda-patches mailing list