[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