[blivet:master/rhel7 2/9] Add mddetail2 method.
mulhern
amulhern at redhat.com
Thu Dec 11 22:29:22 UTC 2014
It calls mdadm with --detail --export flag, which gives very different
information from just with --detail flag.
Also, add some basic tests.
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/devicelibs/mdraid.py | 25 ++++++++++
tests/devicelibs_test/mdraid_interrogate_test.py | 63 ++++++++++++++++++++++++
2 files changed, 88 insertions(+)
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 11e06d7..1db090d 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -343,6 +343,31 @@ def mddetail(device):
return info
+def mddetail2(device):
+ """Run mdadm --detail --export in order to read information about an array.
+
+ Running --detail with the export flag yields all new information.
+
+ :param str device: path of the array device
+ :rtype: a dict of strings
+ :returns: a dict containing labels and values extracted from output
+ """
+ try:
+ lines = mdadm(["--detail", "--export", device], capture=True).split()
+ except MDRaidError as e:
+ raise MDRaidError("mddetail2 failed for %s: %s" % (device, e))
+
+ info = {}
+ for (name, equal, value) in (line.strip().partition("=") for line in lines):
+ value = value.strip()
+ name = name.strip().upper()
+ if equal and value and name:
+ info[name] = value
+
+ process_UUIDS(info, ('MD_UUID',))
+
+ return info
+
def md_node_from_name(name):
named_path = "/dev/md/" + name
try:
diff --git a/tests/devicelibs_test/mdraid_interrogate_test.py b/tests/devicelibs_test/mdraid_interrogate_test.py
index 49388b8..3ed7ae5 100755
--- a/tests/devicelibs_test/mdraid_interrogate_test.py
+++ b/tests/devicelibs_test/mdraid_interrogate_test.py
@@ -227,5 +227,68 @@ class MDDetailTestCase(MDRaidInterrogateTestCase):
def testMDDetailContainerDefault(self):
self._testMDDetail(self.names_container, level="container")
+class MDDetail2TestCase(MDRaidInterrogateTestCase):
+
+ names = [
+ "MD_DEVICES",
+ "MD_LEVEL",
+ "MD_METADATA",
+ "MD_UUID",
+ ]
+
+ def __init__(self, methodName='runTest'):
+ super(MDDetail2TestCase, self).__init__(methodName=methodName, deviceSpec=[Size("100 MiB") for _ in range(3)])
+
+ def _testMDDetail2(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:
+ - at least the predicted names are returned by mddetail
+ - 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.mddetail2(self._dev_name)
+
+ self._matchNames(info.keys(), names)
+
+ # check names with predictable values
+ self.assertEqual(info['MD_LEVEL'], str(level))
+ self.assertEqual(info['MD_DEVICES'], str(len(self.loopDevices) - spares))
+ if metadataVersion is not None:
+ self.assertEqual(info['MD_METADATA'], metadataVersion)
+
+ # verify that uuids are in canonical form
+ for name in (k for k in iter(info.keys()) if k.endswith('MD_UUID')):
+ self.assertEqual(str(uuid.UUID(info[name])), info[name])
+
+ def testMDDetail2(self):
+ self._testMDDetail2(self.names)
+
+ def testMDDetail2Spares(self):
+ self._testMDDetail2(self.names, spares=1)
+
+ def testMDDetail2_0_90(self):
+ self._testMDDetail2(self.names, metadataVersion='0.90')
+
+ def testMDDetail2MDDevice(self):
+ mdraid.mdcreate(self._dev_name, raid.RAID1, self.loopDevices)
+ time.sleep(2) # wait for raid to settle
+
+ # invoking mddetail on a device raises an error
+ with self.assertRaisesRegexp(MDRaidError, "mddetail failed"):
+ mdraid.mddetail(self.loopDevices[0])
+
+ def testMDDetail2ContainerDefault(self):
+ self._testMDDetail2(self.names, level="container")
+
if __name__ == "__main__":
unittest.main()
--
1.9.3
More information about the anaconda-patches
mailing list