Last time there was just one patch.
mulhern (2): Give mdadm format uuids to the outside world (#1155151) Add testing for MDRaidArrayDevice.mdadmFormatUUID (#1155151)
blivet/devicelibs/mdraid.py | 29 +++++++++++++++++++++++++++++ blivet/devices.py | 33 +++++++++++++++++++++++++-------- tests/devicelibs_test/mdraid_test.py | 9 ++++++++- tests/devices_test.py | 23 +++++++++++++++++++++++ 4 files changed, 85 insertions(+), 9 deletions(-)
Resolves: rhbz#1155151
We need our uuids obtained from mdadm to be the canonical format internally, as we need to compare them to other UUIDs obtained from other sources, which are in canonical form.
But the outside world needs to see mdadm's own format UUIDs.
Hence, we need a conversion function to convert from canonical UUIDs to mdadm format UUIDs.
There is an MDRaidArrayDevice property, mdadmFormatUUID, which invokes the conversion function. It returns None if the uuid is unconvertable.
This property is substituted for uuid wherever appropriate. If some checking was done for presence of UUID in these contexts, do appropriate checking for availability of formattedUUID. Where no checking was done previously, do not insert checking.
In one location, use context manager for writing to a file, for neatness, since the code has to be touched anyway.
Signed-off-by: mulhern amulhern@redhat.com --- blivet/devicelibs/mdraid.py | 29 +++++++++++++++++++++++++++++ blivet/devices.py | 33 +++++++++++++++++++++++++-------- tests/devicelibs_test/mdraid_test.py | 9 ++++++++- 3 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py index f4ed875..e9a8bcb 100644 --- a/blivet/devicelibs/mdraid.py +++ b/blivet/devicelibs/mdraid.py @@ -22,6 +22,7 @@
import os import re +import string
from .. import util from ..errors import MDRaidError @@ -360,3 +361,31 @@ def name_from_md_node(node):
log.debug("returning %s", name) return name + +def mduuid_from_canonical(a_uuid): + """ Change a canonicalized uuid to mdadm's preferred format. + + :param str a_uuid: a string representing a UUID. + + :returns: a UUID in mdadm's preferred format + :rtype: str + + :raises MDRaidError: if it can not do the conversion + + mdadm's UUIDs are actual 128 bit uuids, but it formats them strangely. + This converts a uuid from canonical form to mdadm's form. + Example: + mdadm UUID: '3386ff85:f5012621:4a435f06:1eb47236' + canonical UUID: '3386ff85-f501-2621-4a43-5f061eb47236' + """ + NUM_DIGITS = 32 + a_uuid = a_uuid.replace('-', '') + + if len(a_uuid) != NUM_DIGITS: + raise MDRaidError("Missing digits in stripped UUID %s." % a_uuid) + + if any(c not in string.hexdigits for c in a_uuid): + raise MDRaidError("Non-hex digits in stripped UUID %s." % a_uuid) + + CHUNK_LEN = 8 + return ":".join(a_uuid[n:n+CHUNK_LEN] for n in range(0, NUM_DIGITS, CHUNK_LEN)) diff --git a/blivet/devices.py b/blivet/devices.py index 59a3879..43c918d 100644 --- a/blivet/devices.py +++ b/blivet/devices.py @@ -3826,11 +3826,11 @@ class MDRaidArrayDevice(ContainerDevice): self._size = self.currentSize self._type = "mdbiosraidarray"
- if self.exists and self.uuid and not flags.testing: + if self.exists and self.mdadmFormatUUID and not flags.testing: # this is a hack to work around mdadm's insistence on giving # really high minors to arrays it has no config entry for - open("/etc/mdadm.conf", "a").write("ARRAY %s UUID=%s\n" - % (self.path, self.uuid)) + with open("/etc/mdadm.conf", "a") as c: + c.write("ARRAY %s UUID=%s\n" % (self.path, self.mdadmFormatUUID))
def _verifyMemberFormat(self, member): if member.type == "mdcontainer": @@ -3839,6 +3839,23 @@ class MDRaidArrayDevice(ContainerDevice): return super(MDRaidArrayDevice, self)._verifyMemberFormat(member)
@property + def mdadmFormatUUID(self): + """ This array's UUID, formatted for external use. + + :returns: the array's UUID in mdadm format, if available + :rtype: str or NoneType + """ + formatted_uuid = None + + if self.uuid is not None: + try: + formatted_uuid = mdraid.mduuid_from_canonical(self.uuid) + except errors.MDRaidError: + pass + + return formatted_uuid + + @property def level(self): """ Return the raid level
@@ -3940,16 +3957,16 @@ class MDRaidArrayDevice(ContainerDevice): @property def mdadmConfEntry(self): """ This array's mdadm.conf entry. """ - if self.memberDevices is None or not self.uuid: + if self.memberDevices is None or not self.mdadmFormatUUID: raise errors.DeviceError("array is not fully defined", self.name)
# containers and the sets within must only have a UUID= parameter if self.type == "mdcontainer" or self.type == "mdbiosraidarray": fmt = "ARRAY %s UUID=%s\n" - return fmt % (self.path, self.uuid) + return fmt % (self.path, self.mdadmFormatUUID)
fmt = "ARRAY %s level=%s num-devices=%d UUID=%s\n" - return fmt % (self.path, self.level, self.memberDevices, self.uuid) + return fmt % (self.path, self.level, self.memberDevices, self.mdadmFormatUUID)
@property def totalDevices(self): @@ -4161,7 +4178,7 @@ class MDRaidArrayDevice(ContainerDevice):
mdraid.mdactivate(self.path, members=disks, - array_uuid=self.uuid) + array_uuid=self.mdadmFormatUUID)
def _postTeardown(self, recursive=False): super(MDRaidArrayDevice, self)._postTeardown(recursive=recursive) @@ -4286,7 +4303,7 @@ class MDRaidArrayDevice(ContainerDevice): return self.type == "mdbiosraidarray"
def dracutSetupArgs(self): - return set(["rd.md.uuid=%s" % self.uuid]) + return set(["rd.md.uuid=%s" % self.mdadmFormatUUID])
def populateKSData(self, data): if self.isDisk: diff --git a/tests/devicelibs_test/mdraid_test.py b/tests/devicelibs_test/mdraid_test.py index e6fdf55..11f5569 100755 --- a/tests/devicelibs_test/mdraid_test.py +++ b/tests/devicelibs_test/mdraid_test.py @@ -48,6 +48,13 @@ class MDRaidTestCase(unittest.TestCase): version="version"), mdraid.MD_SUPERBLOCK_SIZE)
+ def testMisc(self): + """ Miscellaneous testing. """ + self.assertEqual( + mdraid.mduuid_from_canonical('3386ff85-f501-2621-4a43-5f061eb47236'), + '3386ff85:f5012621:4a435f06:1eb47236' + ) + class MDRaidAsRootTestCase(loopbackedtestcase.LoopBackedTestCase):
def __init__(self, methodName='runTest', deviceSpec=None): @@ -184,7 +191,7 @@ class SimpleRaidTest(MDRaidAsRootTestCase): with self.assertRaises(MDRaidError): mdraid.mdactivate("/dev/md1")
- self.assertIsNone(mdraid.mdactivate(self._dev_name, array_uuid=info_pre['UUID'])) + self.assertIsNone(mdraid.mdactivate(self._dev_name, array_uuid=mdraid.mduuid_from_canonical(info_pre['UUID']))) time.sleep(2) info_post = mdraid.mddetail(self._dev_name)
On Thu, Oct 23, 2014 at 08:48:03AM -0400, mulhern wrote:
@property
- def mdadmFormatUUID(self):
I'd call it md_uuid or mdadm_uuid, but I'm not going to quibble about a name :)
Ack
Related: rhbz#1155151
Signed-off-by: mulhern amulhern@redhat.com --- tests/devices_test.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+)
diff --git a/tests/devices_test.py b/tests/devices_test.py index 51da84c..1ec9379 100644 --- a/tests/devices_test.py +++ b/tests/devices_test.py @@ -24,6 +24,7 @@ from blivet.devices import OpticalDevice from blivet.devices import StorageDevice from blivet.devices import ParentList from blivet.devicelibs import btrfs +from blivet.devicelibs import mdraid from blivet.size import Size
from blivet.formats import getFormat @@ -82,6 +83,7 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase): "level" : self.assertIsNone, "major" : lambda x, m: self.assertEqual(x, 0, m), "maxSize" : lambda x, m: self.assertEqual(x, Size(0), m), + "mdadmFormatUUID" : self.assertIsNone, "mediaPresent" : self.assertFalse, "metadataVersion" : lambda x, m: self.assertEqual(x, "default", m), "minor" : lambda x, m: self.assertEqual(x, 0, m), @@ -232,6 +234,18 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase): "format": getFormat("mdmember")})], totalDevices=5)
+ self.dev19 = MDRaidArrayDevice( + "dev19", + level="raid1", + uuid='3386ff85-f501-2621-4a43-5f061eb47236' + ) + + self.dev20 = MDRaidArrayDevice( + "dev20", + level="raid1", + uuid='Just-pretending' + ) +
def testMDRaidArrayDeviceInit(self): """Tests the state of a MDRaidArrayDevice after initialization. @@ -371,6 +385,15 @@ class MDRaidArrayDeviceTestCase(DeviceStateTestCase): spares=lambda x, m: self.assertEqual(x, 1, m), totalDevices=lambda x, m: self.assertEqual(x, 5, m))
+ self.stateCheck(self.dev19, + level=lambda x, m: self.assertEqual(x.number, 1, m), + mdadmFormatUUID=lambda x, m: self.assertEqual(x, mdraid.mduuid_from_canonical(self.dev19.uuid), m), + uuid=lambda x, m: self.assertEqual(x, self.dev19.uuid, m)) + + self.stateCheck(self.dev20, + level=lambda x, m: self.assertEqual(x.number, 1, m), + uuid=lambda x, m: self.assertEqual(x, self.dev20.uuid, m)) + with self.assertRaisesRegexp(RaidError, "invalid RAID level"): MDRaidArrayDevice("dev")
anaconda-patches@lists.fedorahosted.org