[blivet:master 3/5] Use new RaidDevice class in appropriate Device subclasses.
mulhern
amulhern at redhat.com
Mon Oct 6 13:14:50 UTC 2014
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/devices/btrfs.py | 57 +++++++++++++++++--------------------------------
blivet/devices/md.py | 45 +++++++++++++++++++-------------------
2 files changed, 43 insertions(+), 59 deletions(-)
diff --git a/blivet/devices/btrfs.py b/blivet/devices/btrfs.py
index 16d0970..e2039d9 100644
--- a/blivet/devices/btrfs.py
+++ b/blivet/devices/btrfs.py
@@ -37,6 +37,7 @@ log = logging.getLogger("blivet")
from .storage import StorageDevice
from .container import ContainerDevice
+from .raid import RaidDevice
class BTRFSDevice(StorageDevice):
""" Base class for BTRFS volume and sub-volume devices. """
@@ -165,8 +166,15 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
self._dataLevel = self._metaDataLevel = None
# assign after constructor to avoid AttributeErrors in setter functions
- self.dataLevel = dataLevel
- self.metaDataLevel = metaDataLevel
+ try:
+ self.dataLevel = dataLevel
+ self.metaDataLevel = metaDataLevel
+ except errors.BTRFSValueError as e:
+ # Could not set the levels, so set loose the parents that were
+ # added in superclass constructor.
+ for dev in self.parents:
+ dev.removeChild()
+ raise e
self.subvolumes = []
self.size_policy = self.size
@@ -183,19 +191,6 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
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.
@@ -210,16 +205,11 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
"""
level = None
if value:
+ levels = btrfs.RAID_levels if data else btrfs.metadata_levels
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)
+ level = self._getLevel(value, levels)
+ except ValueError as e:
+ raise errors.BTRFSValueError(e)
if data:
self._dataLevel = level
@@ -291,18 +281,11 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
return size
def _removeParent(self, member):
- """ Raises a DeviceError if the device has a raid level and the
- resulting number of parents would be fewer than the minimum
- number required by the raid level.
-
- Note: btrfs does not permit degrading an array.
- """
- levels = [l for l in [self.dataLevel, self.metaDataLevel] if l]
- if levels:
- min_level = min(levels, key=lambda l: l.min_members)
- min_members = min_level.min_members
- if len(self.parents) - 1 < min_members:
- raise errors.DeviceError("device %s requires at least %d membersfor raid level %s" % (self.name, min_members, min_level))
+ levels = (l for l in (self.dataLevel, self.metaDataLevel) if l)
+ for l in levels:
+ error_msg = self._validateParentRemoval(l, member)
+ if error_msg:
+ raise errors.DeviceError(error_msg)
super(BTRFSVolumeDevice, self)._removeParent(member)
def _addSubVolume(self, vol):
@@ -454,7 +437,7 @@ class BTRFSVolumeDevice(BTRFSDevice, ContainerDevice):
data.devices = ["btrfs.%d" % p.id for p in self.parents]
data.preexist = self.exists
-class BTRFSSubVolumeDevice(BTRFSDevice):
+class BTRFSSubVolumeDevice(BTRFSDevice, RaidDevice):
""" A btrfs subvolume pseudo-device. """
_type = "btrfs subvolume"
_formatImmutable = True
diff --git a/blivet/devices/md.py b/blivet/devices/md.py
index dd4b726..d5ee365 100644
--- a/blivet/devices/md.py
+++ b/blivet/devices/md.py
@@ -29,15 +29,15 @@ from ..flags import flags
from ..storage_log import log_method_call
from .. import udev
from ..size import Size
-from ..i18n import P_
import logging
log = logging.getLogger("blivet")
from .storage import StorageDevice
from .container import ContainerDevice
+from .raid import RaidDevice
-class MDRaidArrayDevice(ContainerDevice):
+class MDRaidArrayDevice(ContainerDevice, RaidDevice):
""" An mdraid (Linux RAID) device. """
_type = "mdarray"
_packages = ["mdadm"]
@@ -88,16 +88,18 @@ class MDRaidArrayDevice(ContainerDevice):
if level == "container":
self._type = "mdcontainer"
- self.level = level
- # For new arrays check if we have enough members
- if (not exists and parents and len(parents) < self.level.min_members):
+ # avoid attribute-defined-outside-init pylint warning
+ self._level = None
+
+ try:
+ self.level = level
+ except errors.DeviceError as e:
+ # Could not set the level, so set loose the parents that were
+ # added in superclass constructor.
for dev in self.parents:
dev.removeChild()
- raise errors.DeviceError(P_("A %(raidLevel)s set requires at least %(minMembers)d member",
- "A %(raidLevel)s set requires at least %(minMembers)d members",
- self.level.min_members) % \
- {"raidLevel": self.level, "minMembers": self.level.min_members})
+ raise e
self.uuid = uuid
self._totalDevices = util.numeric_type(totalDevices)
@@ -136,10 +138,17 @@ class MDRaidArrayDevice(ContainerDevice):
""" Set the RAID level and enforce restrictions based on it.
:param value: new raid level
- :param type: a valid raid level descriptor
+ :param type: object
+ :raises: :class:`~.errors.DeviceError` if value does not describe
+ a valid RAID level
:returns: None
"""
- self._level = mdraid.RAID_levels.raidLevel(value) # pylint: disable=attribute-defined-outside-init
+ try:
+ level = self._getLevel(value, mdraid.RAID_levels)
+ except ValueError as e:
+ raise errors.DeviceError(e)
+
+ self._level = level
@property
def createBitmap(self):
@@ -305,17 +314,9 @@ class MDRaidArrayDevice(ContainerDevice):
self.memberDevices += 1
def _removeParent(self, member):
- """ If this is a raid array that is not actually redundant and it
- appears to have formatting and therefore probably data on it,
- removing one of its devices is a bad idea.
- """
- try:
- if not self.level.has_redundancy() and self.exists and member.format.exists:
- raise errors.DeviceError("cannot remove members from existing %s array" % self.level)
- except errors.RaidError:
- # If the concept of redundancy is meaningless for this device's
- # raid level, then it is OK to remove a parent device.
- pass
+ error_msg = self._validateParentRemoval(self.level, member)
+ if error_msg:
+ raise errors.DeviceError(error_msg)
super(MDRaidArrayDevice, self)._removeParent(member)
self.memberDevices -= 1
--
1.9.3
More information about the anaconda-patches
mailing list