[blivet 06/13] Changed devicelibs.mdraid to make use of devicelibs.raid.
mulhern
amulhern at redhat.com
Tue Nov 26 18:47:11 UTC 2013
Added an MDCONTAINER class.
Extended raid.RAIDLevels so that it required that all RAIDLevels define
min_members.
Added an MDCONTAINER object to the RAIDLevels object.
Methods changed are:
* raidLevel
* raidLevelString
* get_raid_min_members
* get_raid_max_spares
* get_member_space
All the raid constants now depend on raid.
Methods added are:
* getRaidLevel
* raidLevelString was modified so that it takes a flag to use nicknames
instead of canonical names and so that it accepts any valid descriptor,
not just a numeric one.
Members removed are:
* isRaid
* raid_descriptors
---
blivet/devicelibs/mdraid.py | 193 +++++++++++++++++++----------------
tests/devicelibs_test/mdraid_test.py | 27 +++--
2 files changed, 117 insertions(+), 103 deletions(-)
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 54b7fcf..66cfe9c 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -25,6 +25,8 @@ import os
from .. import util
from ..errors import *
+from . import raid
+
import gettext
_ = lambda x: gettext.ldgettext("blivet", x)
@@ -35,72 +37,96 @@ log = logging.getLogger("blivet")
MD_SUPERBLOCK_SIZE = 2.0 # MB
MD_CHUNK_SIZE = 0.5 # MB
+class MDRaidLevels(raid.RAIDLevels):
+ @classmethod
+ def isRaidLevel(cls, level):
+ """Every mdraid level must define min_members."""
+ try:
+ min_members = level.min_members
+ return super(MDRaidLevels, cls).isRaidLevel(level) and min_members > 0
+ except AttributeError:
+ return False
+
+_RAID_levels = MDRaidLevels()
+
# raidlevels constants
-RAID10 = 10
-RAID6 = 6
-RAID5 = 5
-RAID4 = 4
-RAID1 = 1
-RAID0 = 0
+RAID10 = _RAID_levels.raidLevel(10).number
+RAID6 = _RAID_levels.raidLevel(6).number
+RAID5 = _RAID_levels.raidLevel(5).number
+RAID4 = _RAID_levels.raidLevel(4).number
+RAID1 = _RAID_levels.raidLevel(1).number
+RAID0 = _RAID_levels.raidLevel(0).number
raid_levels = [ RAID0, RAID1, RAID4, RAID5, RAID6, RAID10 ]
-raid_descriptors = {RAID10: ("raid10", "RAID10", "10", 10),
- RAID6: ("raid6", "RAID6", "6", 6),
- RAID5: ("raid5", "RAID5", "5", 5),
- RAID4: ("raid4", "RAID4", "4", 4),
- RAID1: ("raid1", "mirror", "RAID1", "1", 1),
- RAID0: ("raid0", "stripe", "RAID0", "0", 0)}
+class MDCONTAINER(object):
+ name = "container"
+ names = [name]
+ nick = None
+ min_members = 1
+ def get_recommended_stride(self, member_devices):
+ return None
+ def get_size(self, member_count, smallest_member_size, chunk_size):
+ raise MDRaidError("get_size is not defined for level container.")
+ def get_raw_arraYsize(self, member_count, smallest_member_size):
+ raise MDRaidError("get_raw_array_size is not defined for level container.")
+ def __str__(self):
+ return self.name
+
+MDCONTAINER = MDCONTAINER()
+_RAID_levels.addRaidLevel(MDCONTAINER)
+
+def getRaidLevel(descriptor):
+ """Return an object for this raid level descriptor.
+ Raises an MDRaidError if the descriptor is not valid.
+ """
+ try:
+ return _RAID_levels.raidLevel(descriptor)
+ except RaidError as e:
+ raise MDRaidError(e.message)
def raidLevel(descriptor):
- for level in raid_levels:
- if isRaid(level, descriptor):
- return level
- else:
- raise MDRaidError("invalid raid level descriptor %s" % descriptor)
+ """Return an integer code corresponding to this raid level descriptor.
+ Raises an MDRaidError if the descriptor is not valid or does not
+ have a corresponding numeric code.
+ """
+ try:
+ return _RAID_levels.raidLevel(descriptor).number
+ except RaidError as e:
+ raise MDRaidError(e.message)
+ except ValueError:
+ raise MDRaidError(e.message)
-def raidLevelString(level):
- if level in raid_descriptors.keys():
- return raid_descriptors[level][0]
- else:
- raise MDRaidError("invalid raid level constant %s" % level)
+def raidLevelString(descriptor, use_nick=False):
+ """Returns the canonical name for the descriptor. Raises an
+ MDRaidError if there is no corresponding level for the descriptor.
-def isRaid(raid, raidlevel):
- """Return whether raidlevel is a valid descriptor of raid"""
- if raid in raid_descriptors:
- return raidlevel in raid_descriptors[raid]
- else:
- raise MDRaidError("invalid raid level %d" % raid)
-
-def get_raid_min_members(raidlevel):
- """Return the minimum number of raid members required for raid level"""
- raid_min_members = {RAID10: 4,
- RAID6: 4,
- RAID5: 3,
- RAID4: 3,
- RAID1: 2,
- RAID0: 2}
-
- for raid, min_members in raid_min_members.items():
- if isRaid(raid, raidlevel):
- return min_members
-
- raise MDRaidError("invalid raid level %s" % raidlevel)
-
-def get_raid_max_spares(raidlevel, nummembers):
- """Return the maximum number of raid spares for raidlevel."""
- raid_max_spares = {RAID10: lambda: max(0, nummembers - get_raid_min_members(RAID10)),
- RAID6: lambda: max(0, nummembers - get_raid_min_members(RAID6)),
- RAID5: lambda: max(0, nummembers - get_raid_min_members(RAID5)),
- RAID4: lambda: max(0, nummembers - get_raid_min_members(RAID4)),
- RAID1: lambda: max(0, nummembers - get_raid_min_members(RAID1)),
- RAID0: lambda: 0}
-
- for raid, max_spares_func in raid_max_spares.items():
- if isRaid(raid, raidlevel):
- return max_spares_func()
-
- raise MDRaidError("invalid raid level %d" % raidlevel)
+ Return the nickname if use_nick is True.
+ """
+ try:
+ return _RAID_levels.raidLevelString(descriptor, use_nick)
+ except RaidError as e:
+ raise MDRaidError(e.message)
+
+def get_raid_min_members(descriptor):
+ """Return the minimum number of raid members required for this raid
+ level descriptor. Raises an MDRaidError if the descriptor is
+ invalid.
+ """
+ try:
+ return _RAID_levels.raidLevel(descriptor).min_members
+ except RaidError as e:
+ raise MDRaidError(e.message)
+
+def get_raid_max_spares(descriptor, nummembers):
+ """Return the maximum number of raid spares for the descriptor,
+ given nummembers members in the array. Raises an MDRaidError
+ if the descriptor is invalid.
+ """
+ try:
+ return _RAID_levels.raidLevel(descriptor).get_max_spares(nummembers)
+ except RaidError as e:
+ raise MDRaidError(e.message)
def get_raid_superblock_size(size, version=None):
""" mdadm has different amounts of space reserved for its use depending
@@ -127,37 +153,26 @@ def get_raid_superblock_size(size, version=None):
return headroom
def get_member_space(size, disks, level=None):
- space = 0 # size of *each* member device
-
- if isinstance(level, str):
- level = raidLevel(level)
-
- min_members = get_raid_min_members(level)
- if disks < min_members:
- raise MDRaidError("raid%d requires at least %d disks"
- % (level, min_members))
-
- if level == RAID0:
- # you need the sum of the member sizes to equal your desired capacity
- space = size / disks
- elif level == RAID1:
- # you need each member's size to equal your desired capacity
- space = size
- elif level in (RAID4, RAID5):
- # you need the sum of all but one members' sizes to equal your desired
- # capacity
- space = size / (disks - 1)
- elif level == RAID6:
- # you need the sum of all but two members' sizes to equal your desired
- # capacity
- space = size / (disks - 2)
- elif level == RAID10:
- # you need the sum of the member sizes to equal twice your desired
- # capacity
- space = size / (disks / 2)
-
- space += get_raid_superblock_size(size)
-
+ """Return the total mB required to store size data.
+ The steps are:
+ * Find the size required for each member
+ * Add to that the superblock size
+ * multiply that by the number of disks to get the required total size.
+ :param size: amount of data
+ :type size: natural number
+
+ :param disks: number of disks
+ :type disks: natural number
+
+ Raises and MDRaidError if there is no level correspondign to level
+ or if the number of disks is less than the minimum number required
+ for the raid level.
+ """
+ try:
+ space = _RAID_levels.raidLevel(level).get_base_member_size(size, disks) + \
+ get_raid_superblock_size(size)
+ except RaidError as e:
+ raise MDRaidError(e.message)
return space * disks
def mdadm(args):
diff --git a/tests/devicelibs_test/mdraid_test.py b/tests/devicelibs_test/mdraid_test.py
index f6bb72a..c92a0bd 100755
--- a/tests/devicelibs_test/mdraid_test.py
+++ b/tests/devicelibs_test/mdraid_test.py
@@ -11,6 +11,14 @@ class MDRaidTestCase(unittest.TestCase):
def testMDRaid(self):
+ self.assertEqual(mdraid.getRaidLevel("container").name, "container")
+ self.assertEqual(mdraid.getRaidLevel("stripe").name, "raid0")
+ self.assertEqual(mdraid.getRaidLevel("mirror").name, "raid1")
+ self.assertEqual(mdraid.getRaidLevel("4").name, "raid4")
+ self.assertEqual(mdraid.getRaidLevel(5).name, "raid5")
+ self.assertEqual(mdraid.getRaidLevel("RAID6").name, "raid6")
+ self.assertEqual(mdraid.getRaidLevel("raid10").name, "raid10")
+
##
## get_raid_min_members
##
@@ -81,18 +89,6 @@ class MDRaidTestCase(unittest.TestCase):
mdraid.get_member_space, 1024, 0, 0)
##
- ## isRaid
- ##
- self.assertTrue(mdraid.isRaid(0, "RAID0"))
- self.assertFalse(mdraid.isRaid(6, "RAID0"))
-
- # fail
- # invalid raid
- self.assertRaisesRegexp(errors.MDRaidError,
- "invalid raid level",
- mdraid.isRaid, 7, "RAID")
-
- ##
## raidLevel
##
self.assertEqual(mdraid.raidLevel("RAID0"), 0)
@@ -107,12 +103,15 @@ class MDRaidTestCase(unittest.TestCase):
## raidLevelString
##
self.assertEqual(mdraid.raidLevelString(0), "raid0")
+ self.assertEqual(mdraid.raidLevelString(0, True), "stripe")
+ self.assertEqual(mdraid.raidLevelString(1, True), "mirror")
+ self.assertEqual(mdraid.raidLevelString(6, True), "raid6")
# fail
# invalid constant
self.assertRaisesRegexp(errors.MDRaidError,
- "invalid raid level constant",
- mdraid.raidLevelString, -1)
+ "invalid raid level",
+ mdraid.raidLevelString, -1)
class MDRaidAsRootTestCase(baseclass.DevicelibsTestCase):
--
1.8.3.1
More information about the anaconda-patches
mailing list