[blivet:master 13/14] Change mdadm() so that it raises an exception when the command fails

mulhern amulhern at redhat.com
Wed Jul 16 16:56:44 UTC 2014


Now mdexamine() and mddetail() raise an MDRaidError if called on an
inappropriate device, instead of silently failing to parse error output.
---
 blivet/devicelibs/mdraid.py                      | 31 +++++++++++++++---------
 tests/devicelibs_test/mdraid_interrogate_test.py | 28 ++++++++++++++++-----
 2 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 83f87cf..7563dc1 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -80,17 +80,19 @@ def get_raid_superblock_size(size, version=None):
     return headroom
 
 def mdadm(args, capture=False):
-    if capture:
-        exec_func = util.capture_output
-    else:
-        exec_func = util.run_program
+    """ Run mdadm with specified arguments.
 
+        :param bool capture: if True, return the output of the command
+        :returns: the output of the command or None
+        :rtype: list of str or NoneType
+        :raises: MDRaidError if command fails
+    """
     argv = ["mdadm"] + args
-
-    ret = exec_func(argv)
-    if ret and not capture:
+    (ret, out) = util.run_program_and_capture_output(argv)
+    if ret:
         raise MDRaidError(ret)
-    return ret
+    if capture:
+        return out
 
 def mdcreate(device, level, disks, spares=0, metadataVer=None, bitmap=False):
     """ Create an mdarray from a list of devices.
@@ -253,8 +255,11 @@ def mdexamine(device):
         :rtype: a dict of strings
         :returns: a dict containing labels and values extracted from output
     """
-    _vars = mdadm(["--examine", "--export", device], capture=True).split()
-    _bvars = mdadm(["--examine", "--brief", device], capture=True).split()
+    try:
+        _vars = mdadm(["--examine", "--export", device], capture=True).split()
+        _bvars = mdadm(["--examine", "--brief", device], capture=True).split()
+    except MDRaidError as e:
+        raise MDRaidError("mdexamine failed for %s: %s" % (device, e))
 
     info = {}
     if len(_bvars) > 1 and _bvars[1].startswith("/dev/md"):
@@ -300,7 +305,11 @@ def mddetail(device):
        :rtype: a dict of strings
        :returns: a dict containing labels and values extracted from output
     """
-    lines = mdadm(["--detail", device], capture=True).split("\n")
+    try:
+        lines = mdadm(["--detail", device], capture=True).split("\n")
+    except MDRaidError as e:
+        raise MDRaidError("mddetail failed for %s: %s" % (device, e))
+
     info = {}
     for (name, colon, value) in (line.strip().partition(":") for line in lines):
         value = value.strip()
diff --git a/tests/devicelibs_test/mdraid_interrogate_test.py b/tests/devicelibs_test/mdraid_interrogate_test.py
index 4399da9..9b1bbdc 100755
--- a/tests/devicelibs_test/mdraid_interrogate_test.py
+++ b/tests/devicelibs_test/mdraid_interrogate_test.py
@@ -8,6 +8,8 @@ import blivet.devicelibs.mdraid as mdraid
 
 from . import mdraid_test
 
+from blivet.errors import MDRaidError
+
 
 class MDRaidInterrogateTestCase(mdraid_test.MDRaidAsRootTestCase):
 
@@ -68,14 +70,14 @@ class MDExamineTestCase(MDRaidInterrogateTestCase):
         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, {})
+        # invoking mdexamine on the array itself raises an error
+        with self.assertRaisesRegexp(MDRaidError, "mdexamine failed"):
+            mdraid.mdexamine(self._dev_name)
 
     def testMDExamineNonMDRaid(self):
-        # invoking mdexamine on a device that is not an array member yields {}
-        info = mdraid.mdexamine(self.loopDevices[0])
-        self.assertEqual(info, {})
+        # invoking mdexamine on any non-array member raises an error
+        with self.assertRaisesRegexp(MDRaidError, "mdexamine failed"):
+            mdraid.mdexamine(self.loopDevices[0])
 
     def _testMDExamine(self, names, metadataVersion=None, level=None, spares=0):
         """ Test mdexamine for a specified metadataVersion.
@@ -216,5 +218,19 @@ class MDDetailTestCase(MDRaidInterrogateTestCase):
     def testMDDetail0_90(self):
         self._testMDDetail(self.names_0, metadataVersion='0.90')
 
+    def testMDDetailMDDevice(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 testMDExamineNonMDRaid(self):
+        # invoking mdexamine on any non-array member raises an error
+        with self.assertRaisesRegexp(MDRaidError, "mdexamine failed"):
+            mdraid.mdexamine(self.loopDevices[0])
+
+
 if __name__ == "__main__":
     unittest.main()
-- 
1.9.3



More information about the anaconda-patches mailing list