[blivet:master 12/14] Refactor mdraid tests.
mulhern
amulhern at redhat.com
Wed Jul 16 16:56:43 UTC 2014
Also, add some mddetail test cases and extend tests for mdremove and mdadd.
Signed-off-by: mulhern <amulhern at redhat.com>
---
tests/devicelibs_test/mdraid_interrogate_test.py | 220 +++++++++++++++++++++++
tests/devicelibs_test/mdraid_test.py | 169 ++++++++---------
2 files changed, 291 insertions(+), 98 deletions(-)
create mode 100755 tests/devicelibs_test/mdraid_interrogate_test.py
diff --git a/tests/devicelibs_test/mdraid_interrogate_test.py b/tests/devicelibs_test/mdraid_interrogate_test.py
new file mode 100755
index 0000000..4399da9
--- /dev/null
+++ b/tests/devicelibs_test/mdraid_interrogate_test.py
@@ -0,0 +1,220 @@
+#!/usr/bin/python
+import unittest
+import time
+import uuid
+
+import blivet.devicelibs.raid as raid
+import blivet.devicelibs.mdraid as mdraid
+
+from . import mdraid_test
+
+
+class MDRaidInterrogateTestCase(mdraid_test.MDRaidAsRootTestCase):
+
+ def _matchNames(self, found, expected, transient=None):
+ """ Match names found against expected names.
+
+ :param found: a list of names found in result
+ :type found: list of str
+ :param expected: a list of expected names
+ :type expected: list of str
+ :param transient: a list of names that only sometimes appear
+ :type transient: list of str
+ """
+ transient = transient or []
+
+ for n in (n for n in expected if n not in transient):
+ self.assertIn(n, found, msg="name '%s' not in info" % n)
+
+ for n in (n for n in found if n not in transient):
+ self.assertIn(n, expected, msg="unexpected name '%s' in info" % n)
+
+
+class MDExamineTestCase(MDRaidInterrogateTestCase):
+
+ def __init__(self, methodName='runTest'):
+ super(MDExamineTestCase, self).__init__(methodName=methodName, deviceSpec=[102400, 102400, 102400])
+
+ names_0 = [
+ 'DEVICE',
+ 'MD_DEVICES',
+ 'MD_EVENTS',
+ 'MD_LEVEL',
+ 'MD_UPDATE_TIME',
+ 'MD_UUID'
+ ]
+
+ names_1 = [
+ 'DEVICE',
+ 'MD_ARRAY_SIZE',
+ 'MD_DEV_UUID',
+ 'MD_DEVICES',
+ 'MD_EVENTS',
+ 'MD_LEVEL',
+ 'MD_METADATA',
+ 'MD_NAME',
+ 'MD_UPDATE_TIME',
+ 'MD_UUID'
+ ]
+
+ names_container = [
+ 'MD_DEVICES',
+ 'MD_LEVEL',
+ 'MD_METADATA',
+ 'MD_UUID'
+ ]
+
+ def testMDExamineMDRaidArray(self):
+ mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices)
+ time.sleep(2) # wait for raid to settle
+
+ # examining the array itself yield no data
+ info = mdraid.mdexamine(self._dev_name)
+ self.assertEqual(info, {})
+
+ def testMDExamineNonMDRaid(self):
+ # invoking mdexamine on a device that is not an array member yields {}
+ info = mdraid.mdexamine(self.loopDevices[0])
+ self.assertEqual(info, {})
+
+ def _testMDExamine(self, names, metadataVersion=None, level=None, spares=0):
+ """ Test mdexamine for a specified metadataVersion.
+
+ :param list names: mdexamine's expected list of names to return
+ :param str metadataVersion: the metadata version for the array
+ :param object level: any valid RAID level descriptor
+ :param int spares: the number of spares in this array
+
+ Verifies that:
+ - exactly the predicted names are returned by mdexamine
+ - RAID level and number of devices are correct
+ - UUIDs have canonical form
+ """
+ level = mdraid.RAID_levels.raidLevel(level or raid.RAID1)
+ mdraid.mdcreate(self._dev_name, level, self.loopDevices, metadataVer=metadataVersion, spares=spares)
+ time.sleep(2) # wait for raid to settle
+
+ info = mdraid.mdexamine(self.loopDevices[0])
+
+ self._matchNames(info.keys(), names)
+
+ # check names with predictable values
+ self.assertEqual(info['MD_DEVICES'], str(len(self.loopDevices) - spares))
+ self.assertEqual(info['MD_LEVEL'], str(level))
+
+ # verify that uuids are in canonical form
+ for name in (k for k in iter(info.keys()) if k.endswith('UUID')):
+ self.assertEqual(str(uuid.UUID(info[name])), info[name])
+
+ def testMDExamineContainerDefault(self):
+ self._testMDExamine(self.names_container, level="container")
+
+ def testMDExamineDefault(self):
+ self._testMDExamine(self.names_1)
+
+ def testMDExamineSpares(self):
+ self._testMDExamine(self.names_1, spares=1)
+
+ def testMDExamine0(self):
+ self._testMDExamine(self.names_0, metadataVersion='0')
+
+ def testMDExamine0_90(self):
+ self._testMDExamine(self.names_0, metadataVersion='0.90')
+
+ def testMDExamine1(self):
+ self._testMDExamine(self.names_1, metadataVersion='1')
+
+ def testMDExamine1_2(self):
+ self._testMDExamine(self.names_1, metadataVersion='1.2')
+
+class MDDetailTestCase(MDRaidInterrogateTestCase):
+
+ def __init__(self, methodName='runTest'):
+ super(MDDetailTestCase, self).__init__(methodName=methodName, deviceSpec=[102400, 102400, 102400])
+
+ names = [
+ 'ACTIVE DEVICES',
+ 'ARRAY SIZE',
+ 'CREATION TIME',
+ 'EVENTS',
+ 'FAILED DEVICES',
+ 'NAME',
+ 'PERSISTENCE',
+ 'RAID DEVICES',
+ 'RAID LEVEL',
+ 'RESYNC STATUS',
+ 'SPARE DEVICES',
+ 'STATE',
+ 'TOTAL DEVICES',
+ 'UPDATE TIME',
+ 'USED DEV SIZE',
+ 'UUID',
+ 'VERSION',
+ 'WORKING DEVICES'
+ ]
+
+ names_0 = [
+ 'ACTIVE DEVICES',
+ 'ARRAY SIZE',
+ 'CREATION TIME',
+ 'EVENTS',
+ 'FAILED DEVICES',
+ 'PERSISTENCE',
+ 'PREFERRED MINOR',
+ 'RAID DEVICES',
+ 'RAID LEVEL',
+ 'RESYNC STATUS',
+ 'SPARE DEVICES',
+ 'STATE',
+ 'TOTAL DEVICES',
+ 'UPDATE TIME',
+ 'USED DEV SIZE',
+ 'UUID',
+ 'VERSION',
+ 'WORKING DEVICES'
+ ]
+
+ def _testMDDetail(self, names, metadataVersion=None, level=None, spares=0):
+ """ Test mddetail for a specified metadataVersion.
+
+ :param list names: mdexamine's expected list of names to return
+ :param str metadataVersion: the metadata version for the array
+ :param object level: any valid RAID level descriptor
+ :param int spares: the number of spares for this array
+
+ Verifies that:
+ - exactly the predicted names are returned by mddetail
+ - UUIDs have canonical form
+ """
+ level = mdraid.RAID_levels.raidLevel(level) if level is not None else raid.RAID1
+
+ mdraid.mdcreate(self._dev_name, level, self.loopDevices, metadataVer=metadataVersion, spares=spares)
+ time.sleep(2) # wait for raid to settle
+
+ info = mdraid.mddetail(self._dev_name)
+
+ # info contains values for exactly names
+ self._matchNames(info.keys(), names, ['RESYNC STATUS'])
+
+ # check names with predictable values
+ self.assertEqual(info['ACTIVE DEVICES'], str(len(self.loopDevices) - spares))
+ self.assertEqual(info['FAILED DEVICES'], '0')
+ self.assertEqual(info['RAID LEVEL'], str(level))
+ self.assertEqual(info['SPARE DEVICES'], str(spares))
+ self.assertEqual(info['TOTAL DEVICES'], str(len(self.loopDevices)))
+ self.assertEqual(info['WORKING DEVICES'], str(len(self.loopDevices)))
+
+ # verify that uuid is in canonical form
+ self.assertEqual(str(uuid.UUID(info['UUID'])), info['UUID'])
+
+ def testMDDetail(self):
+ self._testMDDetail(self.names)
+
+ def testMDDetailSpares(self):
+ self._testMDDetail(self.names, spares=1)
+
+ def testMDDetail0_90(self):
+ self._testMDDetail(self.names_0, metadataVersion='0.90')
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/tests/devicelibs_test/mdraid_test.py b/tests/devicelibs_test/mdraid_test.py
index 107423e..2ed7a2a 100755
--- a/tests/devicelibs_test/mdraid_test.py
+++ b/tests/devicelibs_test/mdraid_test.py
@@ -1,7 +1,6 @@
#!/usr/bin/python
import unittest
import time
-import uuid
import blivet.devicelibs.raid as raid
import blivet.devicelibs.mdraid as mdraid
@@ -49,149 +48,123 @@ class MDRaidTestCase(unittest.TestCase):
version="version"),
mdraid.MD_SUPERBLOCK_SIZE)
-
class MDRaidAsRootTestCase(loopbackedtestcase.LoopBackedTestCase):
- names_0 = [
- 'DEVICE',
- 'MD_DEVICES',
- 'MD_EVENTS',
- 'MD_LEVEL',
- 'MD_UPDATE_TIME',
- 'MD_UUID'
- ]
-
- names_1 = [
- 'DEVICE',
- 'MD_ARRAY_SIZE',
- 'MD_DEV_UUID',
- 'MD_DEVICES',
- 'MD_EVENTS',
- 'MD_LEVEL',
- 'MD_METADATA',
- 'MD_NAME',
- 'MD_UPDATE_TIME',
- 'MD_UUID'
- ]
-
- names_container = [
- 'MD_DEVICES',
- 'MD_LEVEL',
- 'MD_METADATA',
- 'MD_UUID'
- ]
-
- def __init__(self, methodName='runTest'):
- """Set up the structure of the mdraid array."""
- super(MDRaidAsRootTestCase, self).__init__(methodName=methodName)
+ def __init__(self, methodName='runTest', deviceSpec=None):
+ super(MDRaidAsRootTestCase, self).__init__(methodName=methodName, deviceSpec=deviceSpec)
self._dev_name = "/dev/md0"
def tearDown(self):
try:
mdraid.mddeactivate(self._dev_name)
for dev in self.loopDevices:
+ mdraid.mdremove(self._dev_name, dev, fail=True)
mdraid.mddestroy(dev)
except MDRaidError:
pass
super(MDRaidAsRootTestCase, self).tearDown()
- def testMDExamineMDRaidArray(self):
- mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices)
- # wait for raid to settle
- time.sleep(2)
-
- # examining the array itself yield no data
- info = mdraid.mdexamine(self._dev_name)
- self.assertEqual(info, {})
+class RAID0Test(MDRaidAsRootTestCase):
- def testMDExamineNonMDRaid(self):
- # invoking mdexamine on a device that is not an array member yields {}
- info = mdraid.mdexamine(self.loopDevices[0])
- self.assertEqual(info, {})
-
- def _testMDExamine(self, names, metadataVersion=None, level=None):
- """ Test mdexamine for a specified metadataVersion.
-
- :param list names: mdexamine's expected list of names to return
- :param str metadataVersion: the metadata version for the array
- :param object level: any valid RAID level descriptor
+ def __init__(self, methodName='runTest'):
+ super(RAID0Test, self).__init__(methodName=methodName, deviceSpec=[102400, 102400, 102400])
- Verifies that:
- - exactly the predicted names are returned by mdexamine
- - RAID level and number of devices are correct
- - UUIDs have canonical form
- """
- level = mdraid.RAID_levels.raidLevel(level or raid.RAID1)
- mdraid.mdcreate(self._dev_name, level, self.loopDevices, metadataVer=metadataVersion)
- # wait for raid to settle
- time.sleep(2)
+ def testGrow(self):
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID0, self.loopDevices[:2]))
+ time.sleep(2) # wait for raid to settle
- info = mdraid.mdexamine(self.loopDevices[0])
+ # it is not possible to add a managed device to a non-redundant array,
+ # but it can be grown, by specifying the desired number of members
+ self.assertIsNone(mdraid.mdadd(self._dev_name, self.loopDevices[2], raid_devices=3))
- # info contains values for exactly names
- for n in names:
- self.assertIn(n, info, msg="name '%s' not in info" % n)
+ def testGrowRAID1(self):
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices[:2]))
+ time.sleep(2) # wait for raid to settle
- for n in info.keys():
- self.assertIn(n, names, msg="unexpected name '%s' in info" % n)
+ # a RAID1 array can be grown as well as a RAID0 array
+ self.assertIsNone(mdraid.mdadd(self._dev_name, self.loopDevices[2], raid_devices=3))
- # check names with predictable values
- self.assertEqual(info['MD_DEVICES'], '2')
- self.assertEqual(info['MD_LEVEL'], str(level))
+ def testGrowTooBig(self):
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID0, self.loopDevices[:2]))
+ time.sleep(2) # wait for raid to settle
- # verify that uuids are in canonical form
- for name in (k for k in iter(info.keys()) if k.endswith('UUID')):
- self.assertTrue(str(uuid.UUID(info[name])) == info[name])
+ # if more devices are specified than are available after the
+ # addition an error is raised
+ with self.assertRaises(MDRaidError):
+ mdraid.mdadd(self._dev_name, self.loopDevices[2], raid_devices=4)
- def testMDExamineContainerDefault(self):
- self._testMDExamine(self.names_container, level="container")
+ def testGrowSmaller(self):
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID0, self.loopDevices[:2]))
+ time.sleep(2) # wait for raid to settle
- def testMDExamineDefault(self):
- self._testMDExamine(self.names_1)
+ # it is ok to grow an array smaller than its devices
+ self.assertIsNone(mdraid.mdadd(self._dev_name, self.loopDevices[2], raid_devices=2))
- def testMDExamine0(self):
- self._testMDExamine(self.names_0, metadataVersion='0')
+ def testGrowSimple(self):
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID0, self.loopDevices[:2]))
+ time.sleep(2) # wait for raid to settle
- def testMDExamine0_90(self):
- self._testMDExamine(self.names_0, metadataVersion='0.90')
+ # try to simply add a device and things go wrong
+ with self.assertRaises(MDRaidError):
+ mdraid.mdadd(self._dev_name, self.loopDevices[2])
- def testMDExamine1(self):
- self._testMDExamine(self.names_1, metadataVersion='1')
+class SimpleRaidTest(MDRaidAsRootTestCase):
- def testMDExamine1_2(self):
- self._testMDExamine(self.names_1, metadataVersion='1.2')
+ def __init__(self, methodName='runTest'):
+ super(SimpleRaidTest, self).__init__(methodName=methodName, deviceSpec=[102400, 102400, 102400])
def testMDRaidAsRoot(self):
##
## mdcreate
##
# pass
- self.assertEqual(mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices), None)
+ self.assertIsNone(mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices))
+ time.sleep(2) # wait for raid to settle
# fail
with self.assertRaises(MDRaidError):
mdraid.mdcreate("/dev/md1", "raid1", ["/not/existing/dev0", "/not/existing/dev1"])
- ##
- ## mddeactivate
- ##
- # pass
- self.assertEqual(mdraid.mddeactivate(self._dev_name), None)
-
# fail
with self.assertRaises(MDRaidError):
- mdraid.mddeactivate("/not/existing/md")
+ mdraid.mdadd(self._dev_name, "/not/existing/device")
+ time.sleep(2) # wait for raid to settle
+
+ # removing and re-adding a component device should succeed
+ self.assertIsNone(mdraid.mdremove(self._dev_name, self.loopDevices[2], fail=True))
+ time.sleep(2) # wait for raid to settle
+ self.assertIsNone(mdraid.mdadd(self._dev_name, self.loopDevices[2]))
+ time.sleep(3) # wait for raid to settle
+
+ # it is not possible to add a device that has already been added
+ with self.assertRaises(MDRaidError):
+ mdraid.mdadd(self._dev_name, self.loopDevices[2])
+
+ self.assertIsNone(mdraid.mdremove(self._dev_name, self.loopDevices[2], fail=True))
+ time.sleep(2) # wait for raid to settle
+
+ # can not re-add incrementally, because the array is active
+ with self.assertRaises(MDRaidError):
+ mdraid.mdadd(None, self.loopDevices[2], incremental=True)
##
- ## mdadd
+ ## mddeactivate
##
# pass
- # TODO
+ self.assertIsNone(mdraid.mddeactivate(self._dev_name))
+
+ # once the array is deactivated, can add incrementally
+ self.assertIsNone(mdraid.mdadd(None, self.loopDevices[2], incremental=True))
+
+ # but cannot re-add twice
+ with self.assertRaises(MDRaidError):
+ mdraid.mdadd(None, self.loopDevices[2], incremental=True)
# fail
with self.assertRaises(MDRaidError):
- mdraid.mdadd(self._dev_name, "/not/existing/device")
+ mdraid.mddeactivate("/not/existing/md")
+
##
## mdactivate
@@ -207,7 +180,7 @@ class MDRaidAsRootTestCase(loopbackedtestcase.LoopBackedTestCase):
##
# pass
for dev in self.loopDevices:
- self.assertEqual(mdraid.mddestroy(dev), None)
+ self.assertIsNone(mdraid.mddestroy(dev))
# pass
# Note that these should fail because mdadm is unable to locate the
--
1.9.3
More information about the anaconda-patches
mailing list