From f22a12e076782d4e14a6cea69487fdd56da62afa Mon Sep 17 00:00:00 2001 From: Xing Yang Date: Fri, 2 Oct 2015 10:17:40 -0400 Subject: [PATCH] VMAX Truncate Storage Group Name 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 | 29 +++++++++++++++ cinder/volume/drivers/emc/emc_vmax_common.py | 8 ++--- cinder/volume/drivers/emc/emc_vmax_utils.py | 37 ++++++++++++++++++-- 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/cinder/tests/unit/test_emc_vmax.py b/cinder/tests/unit/test_emc_vmax.py index ceee88ec5..49d75f305 100644 --- a/cinder/tests/unit/test_emc_vmax.py +++ b/cinder/tests/unit/test_emc_vmax.py @@ -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 = ( diff --git a/cinder/volume/drivers/emc/emc_vmax_common.py b/cinder/volume/drivers/emc/emc_vmax_common.py index e6f00660e..6b89e4dd0 100644 --- a/cinder/volume/drivers/emc/emc_vmax_common.py +++ b/cinder/volume/drivers/emc/emc_vmax_common.py @@ -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] diff --git a/cinder/volume/drivers/emc/emc_vmax_utils.py b/cinder/volume/drivers/emc/emc_vmax_utils.py index d4b9f0190..f29809ce6 100644 --- a/cinder/volume/drivers/emc/emc_vmax_utils.py +++ b/cinder/volume/drivers/emc/emc_vmax_utils.py @@ -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 -- 2.45.2