]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
VMAX Truncate Storage Group Name
authorXing Yang <xing.yang@emc.com>
Fri, 2 Oct 2015 14:17:40 +0000 (10:17 -0400)
committerXing Yang <xing.yang@emc.com>
Fri, 2 Oct 2015 15:07:56 +0000 (11:07 -0400)
In the VMAX driver, it generates a storage group name using
the short host name, pool name, etc. However the storage
group name has an upper limit of 64 characters. So it fails
if the length of the name exceeds the limit. This patch
fixes it by truncating the name to fix within the limit.

Change-Id: I18258933591a389691a7b33af2d30a40bb34f09c
Closes-Bug: #1501925

cinder/tests/unit/test_emc_vmax.py
cinder/volume/drivers/emc/emc_vmax_common.py
cinder/volume/drivers/emc/emc_vmax_utils.py

index ceee88ec5681a09df0f972597218428fd3a66a1a..49d75f305f9ea651565d40cf655ddf02f5dcccf0 100644 (file)
@@ -1803,6 +1803,35 @@ class EMCVMAXISCSIDriverNoFastTestCase(test.TestCase):
     def fake_is_v3(self, conn, serialNumber):
         return False
 
+    def test_generate_unique_trunc_pool(self):
+        pool_under_16_chars = 'pool_under_16'
+        pool1 = self.driver.utils.generate_unique_trunc_pool(
+            pool_under_16_chars)
+        self.assertEqual(pool_under_16_chars, pool1)
+
+        pool_over_16_chars = (
+            'pool_over_16_pool_over_16')
+        # Should generate truncated string first 8 chars and
+        # last 7 chars
+        pool2 = self.driver.utils.generate_unique_trunc_pool(
+            pool_over_16_chars)
+        self.assertEqual('pool_ove_over_16', pool2)
+
+    def test_generate_unique_trunc_host(self):
+        host_under_38_chars = 'host_under_38_chars'
+        host1 = self.driver.utils.generate_unique_trunc_host(
+            host_under_38_chars)
+        self.assertEqual(host_under_38_chars, host1)
+
+        host_over_38_chars = (
+            'host_over_38_chars_host_over_38_chars_host_over_38_chars')
+        # Check that the same md5 value is retrieved from multiple calls
+        host2 = self.driver.utils.generate_unique_trunc_host(
+            host_over_38_chars)
+        host3 = self.driver.utils.generate_unique_trunc_host(
+            host_over_38_chars)
+        self.assertEqual(host2, host3)
+
     def test_find_device_number(self):
         host = 'myhost'
         data = (
index e6f00660ebb7d7527090b7e82186f1dc01cd94f9..6b89e4dd067c5dc96f92b12a22ab460608597275 100644 (file)
@@ -1726,7 +1726,7 @@ class EMCVMAXCommon(object):
         """
         maskingViewDict = {}
         hostName = connector['host']
-        poolName = extraSpecs[POOL]
+        uniqueName = self.utils.generate_unique_trunc_pool(extraSpecs[POOL])
         isV3 = extraSpecs[ISV3]
         maskingViewDict['isV3'] = isV3
         protocol = self.utils.get_short_protocol_type(self.protocol)
@@ -1736,18 +1736,18 @@ class EMCVMAXCommon(object):
             workload = extraSpecs[WORKLOAD]
             maskingViewDict['slo'] = slo
             maskingViewDict['workload'] = workload
-            maskingViewDict['pool'] = poolName
+            maskingViewDict['pool'] = uniqueName
             prefix = (
                 ("OS-%(shortHostName)s-%(poolName)s-%(slo)s-%(workload)s"
                  % {'shortHostName': shortHostName,
-                    'poolName': poolName,
+                    'poolName': uniqueName,
                     'slo': slo,
                     'workload': workload}))
         else:
             prefix = (
                 ("OS-%(shortHostName)s-%(poolName)s-%(protocol)s"
                  % {'shortHostName': shortHostName,
-                    'poolName': poolName,
+                    'poolName': uniqueName,
                     'protocol': protocol}))
             maskingViewDict['fastPolicy'] = extraSpecs[FASTPOLICY]
 
index d4b9f0190d9b1e96655d2818f738194b4a154ed9..f29809ce6c1238877266e85bde8ab399b985b12d 100644 (file)
@@ -14,6 +14,7 @@
 #    under the License.
 
 import datetime
+import hashlib
 import random
 import re
 from xml.dom import minidom
@@ -629,12 +630,12 @@ class EMCVMAXUtils(object):
         shortHostName = None
 
         hostArray = hostName.split('.')
-        if len(hostArray) > 2:
+        if len(hostArray) > 1:
             shortHostName = hostArray[0]
         else:
             shortHostName = hostName
 
-        return shortHostName
+        return self.generate_unique_trunc_host(shortHostName)
 
     def get_instance_name(self, classname, bindings):
         """Get the instance from the classname and bindings.
@@ -2343,3 +2344,35 @@ class EMCVMAXUtils(object):
                       {'volume': volumeInstance.path, 'rc': rc, 'ret': ret})
             memberVolumes = ret['OutElements']
         return memberVolumes
+
+    def generate_unique_trunc_host(self, hostName):
+        """Create a unique short host name under 40 chars
+
+        :param sgName: long storage group name
+        :returns: truncated storage group name
+        """
+        if hostName and len(hostName) > 38:
+            hostName = hostName.lower()
+            m = hashlib.md5()
+            m.update(hostName.encode('utf-8'))
+            uuid = m.hexdigest()
+            return(
+                ("%(host)s%(uuid)s"
+                 % {'host': hostName[-6:],
+                    'uuid': uuid}))
+        else:
+            return hostName
+
+    def generate_unique_trunc_pool(self, poolName):
+        """Create a unique pool name under 16 chars
+
+        :param poolName: long pool name
+        :returns: truncated pool name
+        """
+        if poolName and len(poolName) > 16:
+            return (
+                ("%(first)s_%(last)s"
+                 % {'first': poolName[:8],
+                    'last': poolName[-7:]}))
+        else:
+            return poolName