Disable capabilities based on 3PAR licenses

The 3PAR firmware is now reporting which licenses are enabled on the
storage array. The 3PAR drivers will now use this information to
enable/disable standard stat reporting for thin provisioning,
QoS support and replication

DocImpact

Implements: blueprint 3par-license-check
Change-Id: Ib5fb06b1c029d026f6f38fa3fdf7d62c2005c06e
This commit is contained in:
Kurt Martin 2015-12-16 15:37:45 -08:00
parent 9c3cbdd90f
commit 6fddcf6da0
3 changed files with 62 additions and 6 deletions

View File

@ -5211,9 +5211,15 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
config.goodness_function = GOODNESS_FUNCTION
mock_client = self.setup_driver(config=config)
mock_client.getCPG.return_value = self.cpgs[0]
# Purposely left out the Priority Optimization license in
# getStorageSystemInfo to test that QoS_support returns False.
mock_client.getStorageSystemInfo.return_value = {
'id': self.CLIENT_ID,
'serialNumber': '1234'
'serialNumber': '1234',
'licenseInfo': {
'licenses': [{'name': 'Remote Copy'},
{'name': 'Thin Provisioning (102400G)'}]
}
}
# cpg has no limit
@ -5243,6 +5249,7 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
self.assertEqual('FC', stats['storage_protocol'])
self.assertTrue(stats['pools'][0]['thin_provisioning_support'])
self.assertTrue(stats['pools'][0]['thick_provisioning_support'])
self.assertFalse(stats['pools'][0]['QoS_support'])
self.assertEqual(86.0,
stats['pools'][0]['provisioned_capacity_gb'])
self.assertEqual(24.0, stats['pools'][0]['total_capacity_gb'])
@ -5285,6 +5292,7 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
self.assertEqual('FC', stats['storage_protocol'])
self.assertTrue(stats['pools'][0]['thin_provisioning_support'])
self.assertTrue(stats['pools'][0]['thick_provisioning_support'])
self.assertFalse(stats['pools'][0]['QoS_support'])
self.assertEqual(86.0,
stats['pools'][0]['provisioned_capacity_gb'])
self.assertEqual(24.0, stats['pools'][0]['total_capacity_gb'])
@ -5316,6 +5324,7 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
self.assertEqual('FC', stats['storage_protocol'])
self.assertTrue(stats['pools'][0]['thin_provisioning_support'])
self.assertTrue(stats['pools'][0]['thick_provisioning_support'])
self.assertFalse(stats['pools'][0]['QoS_support'])
total_capacity_gb = 8192 * const
self.assertEqual(total_capacity_gb,
stats['pools'][0]['total_capacity_gb'])
@ -5364,9 +5373,16 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
config.goodness_function = GOODNESS_FUNCTION
mock_client = self.setup_driver(config=config, wsapi_version=wsapi)
mock_client.getCPG.return_value = self.cpgs[0]
# Purposely left out the Thin Provisioning license in
# getStorageSystemInfo to test that thin_provisioning_support returns
# False.
mock_client.getStorageSystemInfo.return_value = {
'id': self.CLIENT_ID,
'serialNumber': '1234'
'serialNumber': '1234',
'licenseInfo': {
'licenses': [{'name': 'Remote Copy'},
{'name': 'Priority Optimization'}]
}
}
# cpg has no limit
@ -5383,6 +5399,8 @@ class TestHPE3PARFCDriver(HPE3PARBaseDriver, test.TestCase):
stats = self.driver.get_volume_stats(True)
self.assertEqual('FC', stats['storage_protocol'])
self.assertFalse(stats['pools'][0]['thin_provisioning_support'])
self.assertTrue(stats['pools'][0]['QoS_support'])
self.assertEqual(24.0, stats['pools'][0]['total_capacity_gb'])
self.assertEqual(3.0, stats['pools'][0]['free_capacity_gb'])
self.assertEqual(87.5, stats['pools'][0]['capacity_utilization'])

View File

@ -218,10 +218,11 @@ class HPE3PARCommon(object):
3.0.4 - Adds v2 managed replication support
3.0.5 - Adds v2 unmanaged replication support
3.0.6 - Adding manage/unmanage snapshot support
3.0.7 - Enable standard capabilities based on 3PAR licenses
"""
VERSION = "3.0.6"
VERSION = "3.0.7"
stats = {}
@ -245,6 +246,11 @@ class HPE3PARCommon(object):
EXTRA_SPEC_REP_SYNC_PERIOD = "replication:sync_period"
RC_ACTION_CHANGE_TO_PRIMARY = 7
# License values for reported capabilities
PRIORITY_OPT_LIC = "Priority Optimization"
THIN_PROV_LIC = "Thin Provisioning"
REMOTE_COPY_LIC = "Remote Copy"
# Valid values for volume type extra specs
# The first value in the list is the default value
valid_prov_values = ['thin', 'full', 'dedup']
@ -1148,6 +1154,21 @@ class HPE3PARCommon(object):
pools = []
info = self.client.getStorageSystemInfo()
qos_support = True
thin_support = True
remotecopy_support = True
if 'licenseInfo' in info:
if 'licenses' in info['licenseInfo']:
valid_licenses = info['licenseInfo']['licenses']
qos_support = self._check_license_enabled(
valid_licenses, self.PRIORITY_OPT_LIC,
"QoS_support")
thin_support = self._check_license_enabled(
valid_licenses, self.THIN_PROV_LIC,
"Thin_provisioning_support")
remotecopy_support = self._check_license_enabled(
valid_licenses, self.REMOTE_COPY_LIC,
"Replication")
for cpg_name in self.config.hpe3par_cpg:
try:
@ -1210,8 +1231,8 @@ class HPE3PARCommon(object):
'total_capacity_gb': total_capacity,
'free_capacity_gb': free_capacity,
'provisioned_capacity_gb': provisioned_capacity,
'QoS_support': True,
'thin_provisioning_support': True,
'QoS_support': qos_support,
'thin_provisioning_support': thin_support,
'thick_provisioning_support': True,
'max_over_subscription_ratio': (
self.config.safe_get('max_over_subscription_ratio')),
@ -1234,7 +1255,8 @@ class HPE3PARCommon(object):
'consistencygroup_support': True,
}
if hpe3parclient.version >= MIN_REP_CLIENT_VERSION:
if (hpe3parclient.version >= MIN_REP_CLIENT_VERSION
and remotecopy_support):
pool['replication_enabled'] = self._replication_enabled
pool['replication_type'] = ['sync', 'periodic']
pool['replication_count'] = len(self._replication_targets)
@ -1247,6 +1269,19 @@ class HPE3PARCommon(object):
'volume_backend_name': None,
'pools': pools}
def _check_license_enabled(self, valid_licenses,
license_to_check, capability):
"""Check a license against valid licenses on the array."""
if valid_licenses:
for license in valid_licenses:
if license_to_check in license.get('name'):
return True
LOG.debug(("'%(capability)s' requires a '%(license)s' "
"license which is not installed.") %
{'capability': capability,
'license': license_to_check})
return False
def _get_vlun(self, volume_name, hostname, lun_id=None, nsp=None):
"""find a VLUN on a 3PAR host."""
vluns = self.client.getHostVLUNs(hostname)

View File

@ -0,0 +1,3 @@
---
features:
- Disable standard capabilities based on 3PAR licenses.