Merge "Support standard Manila capability flags in NetApp cDOT driver"
This commit is contained in:
commit
8ffa0fc227
manila
share
tests/share
@ -63,6 +63,12 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
'netapp:language': 'language',
|
||||
'netapp:max_files': 'max_files',
|
||||
}
|
||||
# Maps standard extra spec keys to legacy NetApp keys
|
||||
STANDARD_BOOLEAN_EXTRA_SPECS_MAP = {
|
||||
'thin_provisioning': 'netapp:thin_provisioned',
|
||||
'dedupe': 'netapp:dedup',
|
||||
'compression': 'netapp:compression',
|
||||
}
|
||||
|
||||
def __init__(self, driver_name, **kwargs):
|
||||
na_utils.validate_driver_instantiation(**kwargs)
|
||||
@ -256,6 +262,9 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
'allocated_capacity_gb': allocated_capacity_gb,
|
||||
'QoS_support': 'False',
|
||||
'reserved_percentage': 0,
|
||||
'dedupe': [True, False],
|
||||
'compression': [True, False],
|
||||
'thin_provisioning': [True, False],
|
||||
}
|
||||
|
||||
# Add storage service catalog data.
|
||||
@ -366,6 +375,7 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
raise exception.InvalidHost(reason=msg)
|
||||
|
||||
extra_specs = share_types.get_extra_specs_from_share(share)
|
||||
extra_specs = self._remap_standard_boolean_extra_specs(extra_specs)
|
||||
self._check_extra_specs_validity(share, extra_specs)
|
||||
provisioning_options = self._get_provisioning_options(extra_specs)
|
||||
|
||||
@ -377,6 +387,18 @@ class NetAppCmodeFileStorageLibrary(object):
|
||||
share['size'],
|
||||
**provisioning_options)
|
||||
|
||||
@na_utils.trace
|
||||
def _remap_standard_boolean_extra_specs(self, extra_specs):
|
||||
"""Replace standard boolean extra specs with NetApp-specific ones."""
|
||||
specs = copy.deepcopy(extra_specs)
|
||||
for (key, netapp_key) in self.STANDARD_BOOLEAN_EXTRA_SPECS_MAP.items():
|
||||
if key in specs:
|
||||
bool_value = share_types.parse_boolean_extra_spec(key,
|
||||
specs[key])
|
||||
specs[netapp_key] = 'true' if bool_value else 'false'
|
||||
del specs[key]
|
||||
return specs
|
||||
|
||||
@na_utils.trace
|
||||
def _check_extra_specs_validity(self, share, extra_specs):
|
||||
"""Check if the extra_specs have valid values."""
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
"""Built-in share type properties."""
|
||||
|
||||
import re
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_db import exception as db_exception
|
||||
@ -318,3 +319,28 @@ def share_types_diff(context, share_type_id1, share_type_id2):
|
||||
def get_extra_specs_from_share(share):
|
||||
type_id = share.get('share_type_id', None)
|
||||
return get_share_type_extra_specs(type_id)
|
||||
|
||||
|
||||
def parse_boolean_extra_spec(extra_spec_key, extra_spec_value):
|
||||
"""Parse extra spec values of the form '<is> True' or '<is> False'
|
||||
|
||||
This method returns the boolean value of an extra spec value. If
|
||||
the value does not conform to the standard boolean pattern, it raises
|
||||
an InvalidExtraSpec exception.
|
||||
"""
|
||||
|
||||
try:
|
||||
if not isinstance(extra_spec_value, six.string_types):
|
||||
raise ValueError
|
||||
|
||||
match = re.match(r'^<is>\s*(?P<value>True|False)$',
|
||||
extra_spec_value.strip(),
|
||||
re.IGNORECASE)
|
||||
if not match:
|
||||
raise ValueError
|
||||
else:
|
||||
return strutils.bool_from_string(match.group('value'), strict=True)
|
||||
except ValueError:
|
||||
msg = (_('Invalid boolean extra spec %(key)s : %(value)s') %
|
||||
{'key': extra_spec_key, 'value': extra_spec_value})
|
||||
raise exception.InvalidExtraSpec(reason=msg)
|
||||
|
@ -554,7 +554,9 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
return_value=fake.POOL_NAME))
|
||||
self.mock_object(share_types, 'get_extra_specs_from_share',
|
||||
mock.Mock(return_value=fake.EXTRA_SPEC))
|
||||
|
||||
mock_remap_standard_boolean_extra_specs = self.mock_object(
|
||||
self.library, '_remap_standard_boolean_extra_specs',
|
||||
mock.Mock(return_value=fake.EXTRA_SPEC))
|
||||
self.mock_object(self.library, '_check_boolean_extra_specs_validity')
|
||||
self.mock_object(self.library, '_get_boolean_provisioning_options',
|
||||
mock.Mock(return_value=fake.PROVISIONING_OPTIONS))
|
||||
@ -568,6 +570,16 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
|
||||
thin_provisioned=True, snapshot_policy='default',
|
||||
language='en-US', dedup_enabled=True,
|
||||
compression_enabled=False, max_files=5000)
|
||||
mock_remap_standard_boolean_extra_specs.assert_called_once_with(
|
||||
fake.EXTRA_SPEC)
|
||||
|
||||
def test_remap_standard_boolean_extra_specs(self):
|
||||
|
||||
extra_specs = copy.deepcopy(fake.OVERLAPPING_EXTRA_SPEC)
|
||||
|
||||
result = self.library._remap_standard_boolean_extra_specs(extra_specs)
|
||||
|
||||
self.assertDictEqual(fake.REMAPPED_OVERLAPPING_EXTRA_SPEC, result)
|
||||
|
||||
def test_allocate_container_no_pool_name(self):
|
||||
self.mock_object(self.library, '_get_valid_share_name', mock.Mock(
|
||||
|
@ -191,6 +191,21 @@ SHARE_TYPE = {
|
||||
'extra_specs': EXTRA_SPEC
|
||||
}
|
||||
|
||||
OVERLAPPING_EXTRA_SPEC = {
|
||||
'compression': '<is> True',
|
||||
'netapp:compression': 'true',
|
||||
'dedupe': '<is> True',
|
||||
'netapp:dedup': 'false',
|
||||
'thin_provisioning': '<is> False',
|
||||
'netapp:thin_provisioned': 'true',
|
||||
}
|
||||
|
||||
REMAPPED_OVERLAPPING_EXTRA_SPEC = {
|
||||
'netapp:compression': 'true',
|
||||
'netapp:dedup': 'true',
|
||||
'netapp:thin_provisioned': 'false',
|
||||
}
|
||||
|
||||
EXTRA_SPEC_SHARE = copy.deepcopy(SHARE)
|
||||
EXTRA_SPEC_SHARE['share_type_id'] = SHARE_TYPE_ID
|
||||
|
||||
@ -424,6 +439,9 @@ POOLS = [
|
||||
'allocated_capacity_gb': 2.2,
|
||||
'QoS_support': 'False',
|
||||
'reserved_percentage': 0,
|
||||
'dedupe': [True, False],
|
||||
'compression': [True, False],
|
||||
'thin_provisioning': [True, False],
|
||||
'netapp_raid_type': 'raid4',
|
||||
'netapp_disk_type': 'FCAL'
|
||||
},
|
||||
@ -433,6 +451,9 @@ POOLS = [
|
||||
'allocated_capacity_gb': 4.0,
|
||||
'QoS_support': 'False',
|
||||
'reserved_percentage': 0,
|
||||
'dedupe': [True, False],
|
||||
'compression': [True, False],
|
||||
'thin_provisioning': [True, False],
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD'
|
||||
},
|
||||
@ -445,6 +466,9 @@ POOLS_VSERVER_CREDS = [
|
||||
'allocated_capacity_gb': 0.0,
|
||||
'QoS_support': 'False',
|
||||
'reserved_percentage': 0,
|
||||
'dedupe': [True, False],
|
||||
'compression': [True, False],
|
||||
'thin_provisioning': [True, False],
|
||||
'netapp_raid_type': 'raid4',
|
||||
'netapp_disk_type': 'FCAL'
|
||||
},
|
||||
@ -454,6 +478,9 @@ POOLS_VSERVER_CREDS = [
|
||||
'allocated_capacity_gb': 0.0,
|
||||
'QoS_support': 'False',
|
||||
'reserved_percentage': 0,
|
||||
'dedupe': [True, False],
|
||||
'compression': [True, False],
|
||||
'thin_provisioning': [True, False],
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD'
|
||||
},
|
||||
|
@ -256,3 +256,23 @@ class ShareTypesTestCase(test.TestCase):
|
||||
self.assertRaises(exception.InvalidShareType,
|
||||
share_types.remove_share_type_access,
|
||||
'fake', None, 'fake')
|
||||
|
||||
@ddt.data({'spec_value': '<is> True', 'expected': True},
|
||||
{'spec_value': '<is>true', 'expected': True},
|
||||
{'spec_value': '<is> False', 'expected': False},
|
||||
{'spec_value': '<is>false', 'expected': False},
|
||||
{'spec_value': u' <is> FaLsE ', 'expected': False})
|
||||
@ddt.unpack
|
||||
def test_parse_boolean_extra_spec(self, spec_value, expected):
|
||||
|
||||
result = share_types.parse_boolean_extra_spec('fake_key', spec_value)
|
||||
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
@ddt.data('True', 'False', '<isnt> True', '<is> Wrong', None, 5)
|
||||
def test_parse_boolean_extra_spec_invalid(self, spec_value):
|
||||
|
||||
self.assertRaises(exception.InvalidExtraSpec,
|
||||
share_types.parse_boolean_extra_spec,
|
||||
'fake_key',
|
||||
spec_value)
|
||||
|
Loading…
x
Reference in New Issue
Block a user