diff --git a/manila/share/drivers/netapp/dataontap/client/client_cmode.py b/manila/share/drivers/netapp/dataontap/client/client_cmode.py
index d6357d19..119a7b7e 100644
--- a/manila/share/drivers/netapp/dataontap/client/client_cmode.py
+++ b/manila/share/drivers/netapp/dataontap/client/client_cmode.py
@@ -66,6 +66,8 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
self.features.add_feature('IPSPACES', supported=ontapi_1_30)
self.features.add_feature('SUBNETS', supported=ontapi_1_30)
self.features.add_feature('CLUSTER_PEER_POLICY', supported=ontapi_1_30)
+ self.features.add_feature('ADVANCED_DISK_PARTITIONING',
+ supported=ontapi_1_30)
def _invoke_vserver_api(self, na_element, vserver):
server = copy.copy(self.connection)
@@ -2367,76 +2369,116 @@ class NetAppCmodeClient(client_base.NetAppBaseClient):
LOG.warning(_LW('Failed to invoke EMS. %s') % e)
@na_utils.trace
- def get_aggregate_raid_types(self, aggregate_names):
- """Get the RAID type of one or more aggregates."""
+ def get_aggregate(self, aggregate_name):
+ """Get aggregate attributes needed for the storage service catalog."""
+
+ if not aggregate_name:
+ return {}
desired_attributes = {
'aggr-attributes': {
'aggregate-name': None,
'aggr-raid-attributes': {
'raid-type': None,
+ 'is-hybrid': None,
},
},
}
- aggr_list = self._get_aggregates(aggregate_names=aggregate_names,
+
+ try:
+ aggrs = self._get_aggregates(aggregate_names=[aggregate_name],
desired_attributes=desired_attributes)
+ except netapp_api.NaApiError:
+ msg = _('Failed to get info for aggregate %s.')
+ LOG.exception(msg % aggregate_name)
+ return {}
- aggr_raid_dict = {}
- for aggr in aggr_list:
- aggr_name = aggr.get_child_content('aggregate-name')
- aggr_raid_attrs = aggr.get_child_by_name('aggr-raid-attributes')
+ if len(aggrs) < 1:
+ return {}
- aggr_raid_dict[aggr_name] = aggr_raid_attrs.get_child_content(
- 'raid-type')
+ aggr_attributes = aggrs[0]
+ aggr_raid_attrs = aggr_attributes.get_child_by_name(
+ 'aggr-raid-attributes') or netapp_api.NaElement('none')
- return aggr_raid_dict
+ aggregate = {
+ 'name': aggr_attributes.get_child_content('aggregate-name'),
+ 'raid-type': aggr_raid_attrs.get_child_content('raid-type'),
+ 'is-hybrid': strutils.bool_from_string(
+ aggr_raid_attrs.get_child_content('is-hybrid')),
+ }
+
+ return aggregate
@na_utils.trace
- def get_aggregate_disk_types(self, aggregate_names):
- """Get the disk type of one or more aggregates."""
+ def get_aggregate_disk_types(self, aggregate_name):
+ """Get the disk type(s) of an aggregate."""
- aggr_disk_type_dict = {}
+ disk_types = set()
+ disk_types.update(self._get_aggregate_disk_types(aggregate_name))
+ if self.features.ADVANCED_DISK_PARTITIONING:
+ disk_types.update(self._get_aggregate_disk_types(aggregate_name,
+ shared=True))
- for aggregate_name in aggregate_names:
+ return list(disk_types) if disk_types else None
- # Only get 1 disk, since apart from hybrid aggregates all disks
- # must be the same type.
- api_args = {
- 'max-records': 1,
- 'query': {
- 'storage-disk-info': {
- 'disk-raid-info': {
- 'disk-aggregate-info': {
- 'aggregate-name': aggregate_name,
- },
- },
- },
- },
- 'desired-attributes': {
- 'storage-disk-info': {
- 'disk-raid-info': {
- 'effective-disk-type': None,
+ @na_utils.trace
+ def _get_aggregate_disk_types(self, aggregate_name, shared=False):
+ """Get the disk type(s) of an aggregate."""
+
+ disk_types = set()
+
+ if shared:
+ disk_raid_info = {
+ 'disk-shared-info': {
+ 'aggregate-list': {
+ 'shared-aggregate-info': {
+ 'aggregate-name': aggregate_name,
},
},
},
}
- result = self.send_request('storage-disk-get-iter', api_args)
+ else:
+ disk_raid_info = {
+ 'disk-aggregate-info': {
+ 'aggregate-name': aggregate_name,
+ },
+ }
- attributes_list = result.get_child_by_name(
- 'attributes-list') or netapp_api.NaElement('none')
- storage_disk_info_list = attributes_list.get_children()
+ api_args = {
+ 'query': {
+ 'storage-disk-info': {
+ 'disk-raid-info': disk_raid_info,
+ },
+ },
+ 'desired-attributes': {
+ 'storage-disk-info': {
+ 'disk-raid-info': {
+ 'effective-disk-type': None,
+ },
+ },
+ },
+ }
+
+ try:
+ result = self.send_iter_request('storage-disk-get-iter', api_args)
+ except netapp_api.NaApiError:
+ msg = _('Failed to get disk info for aggregate %s.')
+ LOG.exception(msg % aggregate_name)
+ return disk_types
+
+ attributes_list = result.get_child_by_name(
+ 'attributes-list') or netapp_api.NaElement('none')
+
+ for storage_disk_info in attributes_list.get_children():
- if len(storage_disk_info_list) >= 1:
- storage_disk_info = storage_disk_info_list[0]
disk_raid_info = storage_disk_info.get_child_by_name(
- 'disk-raid-info')
- if disk_raid_info:
- disk_type = disk_raid_info.get_child_content(
- 'effective-disk-type')
- if disk_type:
- aggr_disk_type_dict[aggregate_name] = disk_type
+ 'disk-raid-info') or netapp_api.NaElement('none')
+ disk_type = disk_raid_info.get_child_content(
+ 'effective-disk-type')
+ if disk_type:
+ disk_types.add(disk_type)
- return aggr_disk_type_dict
+ return disk_types
@na_utils.trace
def check_for_cluster_credentials(self):
diff --git a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_base.py b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_base.py
index 4a5b2169..941d91de 100644
--- a/manila/share/drivers/netapp/dataontap/cluster_mode/lib_base.py
+++ b/manila/share/drivers/netapp/dataontap/cluster_mode/lib_base.py
@@ -278,6 +278,7 @@ class NetAppCmodeFileStorageLibrary(object):
'dedupe': [True, False],
'compression': [True, False],
'thin_provisioning': [True, False],
+ 'netapp_aggregate': aggr_name,
}
# Add storage service catalog data.
@@ -1107,13 +1108,18 @@ class NetAppCmodeFileStorageLibrary(object):
if not self._have_cluster_creds:
return
- raid_types = self._client.get_aggregate_raid_types(aggregate_names)
- for aggregate_name, raid_type in raid_types.items():
- ssc_stats[aggregate_name]['netapp_raid_type'] = raid_type
+ for aggregate_name in aggregate_names:
- disk_types = self._client.get_aggregate_disk_types(aggregate_names)
- for aggregate_name, disk_type in disk_types.items():
- ssc_stats[aggregate_name]['netapp_disk_type'] = disk_type
+ aggregate = self._client.get_aggregate(aggregate_name)
+ hybrid = (six.text_type(aggregate.get('is-hybrid')).lower()
+ if 'is-hybrid' in aggregate else None)
+ disk_types = self._client.get_aggregate_disk_types(aggregate_name)
+
+ ssc_stats[aggregate_name].update({
+ 'netapp_raid_type': aggregate.get('raid-type'),
+ 'netapp_hybrid_aggregate': hybrid,
+ 'netapp_disk_type': disk_types,
+ })
def _find_active_replica(self, replica_list):
# NOTE(ameade): Find current active replica. There can only be one
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/fakes.py b/manila/tests/share/drivers/netapp/dataontap/client/fakes.py
index 8db9ff4f..18f450f6 100644
--- a/manila/tests/share/drivers/netapp/dataontap/client/fakes.py
+++ b/manila/tests/share/drivers/netapp/dataontap/client/fakes.py
@@ -43,6 +43,7 @@ SHARE_AGGREGATE_NAME = 'fake_aggr1'
SHARE_AGGREGATE_NAMES = ('fake_aggr1', 'fake_aggr2')
SHARE_AGGREGATE_RAID_TYPES = ('raid4', 'raid_dp')
SHARE_AGGREGATE_DISK_TYPE = 'FCAL'
+SHARE_AGGREGATE_DISK_TYPES = ['SATA', 'SSD']
SHARE_NAME = 'fake_share'
SHARE_SIZE = '1000000000'
SHARE_NAME_2 = 'fake_share_2'
@@ -1145,6 +1146,127 @@ AGGR_GET_ITER_RESPONSE = etree.XML("""
'aggr2': SHARE_AGGREGATE_NAMES[1],
})
+AGGR_GET_ITER_SSC_RESPONSE = etree.XML("""
+
+
+
+
+
+ false
+
+
+
+ 64_bit
+ 1758646411
+ aggr
+
+
+ 512
+ 30384
+ 96
+ 30384
+ 30384
+ 30384
+ 243191
+ 96
+ 0
+
+
+ 4082368507
+ cluster3-01
+ 4082368507
+ cluster3-01
+
+
+ off
+ 0
+
+
+ active
+ block
+ 3
+ cfo
+ true
+ false
+ true
+ false
+ false
+ false
+ unmirrored
+ online
+ 1
+
+
+ true
+ false
+ /%(aggr1)s/plex0
+ normal,active
+
+
+ block
+ false
+ false
+ false
+ /%(aggr1)s/plex0/rg0
+ 0
+ 0
+
+
+ 0
+
+
+ on
+ 16
+ raid_dp, normal
+ raid_dp
+ online
+
+
+ false
+
+
+ 0
+ 0
+ true
+ true
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+ 245760
+ 0
+ 95
+ 45670400
+ 943718400
+ 898048000
+ 0
+ 898048000
+ 897802240
+
+
+ 1
+ 0
+ 0
+
+ %(aggr1)s
+ 15863632-ea49-49a8-9c88-2bd2d57c6d7a
+
+ cluster3-01
+
+ unknown
+
+
+ 1
+
+""" % {'aggr1': SHARE_AGGREGATE_NAMES[0]})
+
VOLUME_GET_NAME_RESPONSE = etree.XML("""
@@ -1476,13 +1598,34 @@ STORAGE_DISK_GET_ITER_RESPONSE = etree.XML("""
cluster3-01:v5.19
- %s
+ %(type0)s
+
+
+
+ cluster3-01:v5.20
+
+ %(type0)s
+
+
+
+ cluster3-01:v5.20
+
+ %(type1)s
+
+
+
+ cluster3-01:v5.20
+
+ %(type1)s
- 1
+ 4
-""" % SHARE_AGGREGATE_DISK_TYPE)
+""" % {
+ 'type0': SHARE_AGGREGATE_DISK_TYPES[0],
+ 'type1': SHARE_AGGREGATE_DISK_TYPES[1],
+})
STORAGE_DISK_GET_ITER_RESPONSE_PAGE_1 = etree.XML("""
diff --git a/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py b/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
index 2f03fff9..3055a265 100644
--- a/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
+++ b/manila/tests/share/drivers/netapp/dataontap/client/test_client_cmode.py
@@ -189,7 +189,7 @@ class NetAppClientCmodeTestCase(test.TestCase):
max_page_length=10)
num_records = result.get_child_content('num-records')
- self.assertEqual('1', num_records)
+ self.assertEqual('4', num_records)
args = copy.deepcopy(storage_disk_get_iter_args)
args['max-records'] = 10
@@ -4184,90 +4184,185 @@ class NetAppClientCmodeTestCase(test.TestCase):
mock.call('ems-autosupport-log', fake.EMS_MESSAGE)])
self.assertEqual(1, client_cmode.LOG.warning.call_count)
- def test_get_aggregate_raid_types(self):
+ def test_get_aggregate_none_specified(self):
- api_response = netapp_api.NaElement(fake.AGGR_GET_RAID_TYPE_RESPONSE)
+ result = self.client.get_aggregate('')
+
+ self.assertEqual({}, result)
+
+ def test_get_aggregate(self):
+
+ api_response = netapp_api.NaElement(
+ fake.AGGR_GET_ITER_SSC_RESPONSE).get_child_by_name(
+ 'attributes-list').get_children()
self.mock_object(self.client,
- 'send_iter_request',
+ '_get_aggregates',
mock.Mock(return_value=api_response))
- result = self.client.get_aggregate_raid_types(
- fake.SHARE_AGGREGATE_NAMES)
+ result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME)
- aggr_get_iter_args = {
- 'query': {
- 'aggr-attributes': {
- 'aggregate-name': '|'.join(fake.SHARE_AGGREGATE_NAMES),
- }
+ desired_attributes = {
+ 'aggr-attributes': {
+ 'aggregate-name': None,
+ 'aggr-raid-attributes': {
+ 'raid-type': None,
+ 'is-hybrid': None,
+ },
},
- 'desired-attributes': {
- 'aggr-attributes': {
- 'aggregate-name': None,
- 'aggr-raid-attributes': {
- 'raid-type': None,
- }
- }
- }
}
+ self.client._get_aggregates.assert_has_calls([
+ mock.call(
+ aggregate_names=[fake.SHARE_AGGREGATE_NAME],
+ desired_attributes=desired_attributes)])
expected = {
- fake.SHARE_AGGREGATE_NAMES[0]:
- fake.SHARE_AGGREGATE_RAID_TYPES[0],
- fake.SHARE_AGGREGATE_NAMES[1]:
- fake.SHARE_AGGREGATE_RAID_TYPES[1]
+ 'name': fake.SHARE_AGGREGATE_NAME,
+ 'raid-type': 'raid_dp',
+ 'is-hybrid': False,
}
+ self.assertEqual(expected, result)
- self.client.send_iter_request.assert_has_calls([
- mock.call('aggr-get-iter', aggr_get_iter_args)])
- self.assertDictEqual(expected, result)
-
- def test_get_aggregate_raid_types_not_found(self):
+ def test_get_aggregate_not_found(self):
api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
self.mock_object(self.client,
- 'send_iter_request',
+ 'send_request',
mock.Mock(return_value=api_response))
- result = self.client.get_aggregate_raid_types(
- fake.SHARE_AGGREGATE_NAMES)
+ result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME)
- self.assertDictEqual({}, result)
+ self.assertEqual({}, result)
- def test_get_aggregate_disk_types(self):
+ def test_get_aggregate_api_error(self):
+
+ self.mock_object(self.client,
+ 'send_request',
+ mock.Mock(side_effect=self._mock_api_error()))
+
+ result = self.client.get_aggregate(fake.SHARE_AGGREGATE_NAME)
+
+ self.assertEqual({}, result)
+
+ @ddt.data({'types': {'FCAL'}, 'expected': ['FCAL']},
+ {'types': {'SATA', 'SSD'}, 'expected': ['SATA', 'SSD']},)
+ @ddt.unpack
+ def test_get_aggregate_disk_types(self, types, expected):
+
+ mock_get_aggregate_disk_types = self.mock_object(
+ self.client, '_get_aggregate_disk_types',
+ mock.Mock(return_value=types))
+
+ result = self.client.get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME)
+
+ self.assertItemsEqual(expected, result)
+ mock_get_aggregate_disk_types.assert_called_once_with(
+ fake.SHARE_AGGREGATE_NAME)
+
+ def test_get_aggregate_disk_types_not_found(self):
+
+ mock_get_aggregate_disk_types = self.mock_object(
+ self.client, '_get_aggregate_disk_types',
+ mock.Mock(return_value=set()))
+
+ result = self.client.get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME)
+
+ self.assertIsNone(result)
+ mock_get_aggregate_disk_types.assert_called_once_with(
+ fake.SHARE_AGGREGATE_NAME)
+
+ def test_get_aggregate_disk_types_shared(self):
+
+ self.client.features.add_feature('ADVANCED_DISK_PARTITIONING')
+ mock_get_aggregate_disk_types = self.mock_object(
+ self.client, '_get_aggregate_disk_types',
+ mock.Mock(side_effect=[set(['SSD']), set(['SATA'])]))
+
+ result = self.client.get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME)
+
+ self.assertIsInstance(result, list)
+ self.assertItemsEqual(['SATA', 'SSD'], result)
+ mock_get_aggregate_disk_types.assert_has_calls([
+ mock.call(fake.SHARE_AGGREGATE_NAME),
+ mock.call(fake.SHARE_AGGREGATE_NAME, shared=True),
+ ])
+
+ @ddt.data({
+ 'shared': False,
+ 'query_disk_raid_info': {
+ 'disk-aggregate-info': {
+ 'aggregate-name': fake.SHARE_AGGREGATE_NAME,
+ },
+ },
+ }, {
+ 'shared': True,
+ 'query_disk_raid_info': {
+ 'disk-shared-info': {
+ 'aggregate-list': {
+ 'shared-aggregate-info': {
+ 'aggregate-name':
+ fake.SHARE_AGGREGATE_NAME,
+ },
+ },
+ },
+ },
+ })
+ @ddt.unpack
+ def test__get_aggregate_disk_types_ddt(self, shared, query_disk_raid_info):
api_response = netapp_api.NaElement(
fake.STORAGE_DISK_GET_ITER_RESPONSE)
self.mock_object(self.client,
- 'send_request',
+ 'send_iter_request',
mock.Mock(return_value=api_response))
- result = self.client.get_aggregate_disk_types(
- fake.SHARE_AGGREGATE_NAMES)
+ result = self.client._get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME, shared=shared)
- expected = {
- fake.SHARE_AGGREGATE_NAMES[0]:
- fake.SHARE_AGGREGATE_DISK_TYPE,
- fake.SHARE_AGGREGATE_NAMES[1]:
- fake.SHARE_AGGREGATE_DISK_TYPE
+ storage_disk_get_iter_args = {
+ 'query': {
+ 'storage-disk-info': {
+ 'disk-raid-info': query_disk_raid_info,
+ },
+ },
+ 'desired-attributes': {
+ 'storage-disk-info': {
+ 'disk-raid-info': {
+ 'effective-disk-type': None,
+ },
+ },
+ },
}
+ self.client.send_iter_request.assert_called_once_with(
+ 'storage-disk-get-iter', storage_disk_get_iter_args)
- self.assertEqual(len(fake.SHARE_AGGREGATE_NAMES),
- self.client.send_request.call_count)
- self.assertDictEqual(expected, result)
+ expected = set(fake.SHARE_AGGREGATE_DISK_TYPES)
+ self.assertEqual(expected, result)
- def test_get_aggregate_disk_types_not_found(self):
+ def test__get_aggregate_disk_types_not_found(self):
api_response = netapp_api.NaElement(fake.NO_RECORDS_RESPONSE)
self.mock_object(self.client,
- 'send_request',
+ 'send_iter_request',
mock.Mock(return_value=api_response))
- result = self.client.get_aggregate_disk_types(
- fake.SHARE_AGGREGATE_NAMES)
+ result = self.client._get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME)
- self.assertEqual(len(fake.SHARE_AGGREGATE_NAMES),
- self.client.send_request.call_count)
- self.assertDictEqual({}, result)
+ self.assertEqual(set(), result)
+
+ def test__get_aggregate_disk_types_api_error(self):
+
+ self.mock_object(self.client,
+ 'send_iter_request',
+ mock.Mock(side_effect=self._mock_api_error()))
+
+ result = self.client._get_aggregate_disk_types(
+ fake.SHARE_AGGREGATE_NAME)
+
+ self.assertEqual(set([]), result)
def test_check_for_cluster_credentials(self):
diff --git a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_base.py b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_base.py
index 7a18724d..a7c03cc4 100644
--- a/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_base.py
+++ b/manila/tests/share/drivers/netapp/dataontap/cluster_mode/test_lib_base.py
@@ -378,27 +378,28 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
self.assertListEqual(fake.POOLS, result)
- @ddt.data(
- {
- 'capacities': fake.AGGREGATE_CAPACITIES,
- 'pools': fake.POOLS,
- },
- {
- 'capacities': fake.AGGREGATE_CAPACITIES_VSERVER_CREDS,
- 'pools': fake.POOLS_VSERVER_CREDS
- }
- )
- @ddt.unpack
- def test_get_pools(self, capacities, pools):
+ def test_get_pools(self):
- self.mock_object(self.library,
- '_get_aggregate_space',
- mock.Mock(return_value=capacities))
+ self.mock_object(
+ self.library, '_get_aggregate_space',
+ mock.Mock(return_value=fake.AGGREGATE_CAPACITIES))
+ self.library._have_cluster_creds = True
self.library._ssc_stats = fake.SSC_INFO
result = self.library._get_pools()
- self.assertListEqual(pools, result)
+ self.assertListEqual(fake.POOLS, result)
+
+ def test_get_pools_vserver_creds(self):
+
+ self.mock_object(
+ self.library, '_get_aggregate_space',
+ mock.Mock(return_value=fake.AGGREGATE_CAPACITIES_VSERVER_CREDS))
+ self.library._have_cluster_creds = False
+
+ result = self.library._get_pools()
+
+ self.assertListEqual(fake.POOLS_VSERVER_CREDS, result)
def test_handle_ems_logging(self):
@@ -2048,35 +2049,58 @@ class NetAppFileStorageLibraryTestCase(test.TestCase):
def test_update_ssc_aggr_info(self):
self.library._have_cluster_creds = True
- self.mock_object(self.client,
- 'get_aggregate_raid_types',
- mock.Mock(return_value=fake.SSC_RAID_TYPES))
- self.mock_object(self.client,
- 'get_aggregate_disk_types',
- mock.Mock(return_value=fake.SSC_DISK_TYPES))
+ mock_get_aggregate = self.mock_object(
+ self.client, 'get_aggregate',
+ mock.Mock(side_effect=fake.SSC_AGGREGATES))
+ mock_get_aggregate_disk_types = self.mock_object(
+ self.client, 'get_aggregate_disk_types',
+ mock.Mock(side_effect=fake.SSC_DISK_TYPES))
ssc_stats = {
fake.AGGREGATES[0]: {},
- fake.AGGREGATES[1]: {}
+ fake.AGGREGATES[1]: {},
}
self.library._update_ssc_aggr_info(fake.AGGREGATES, ssc_stats)
self.assertDictEqual(fake.SSC_INFO, ssc_stats)
+ mock_get_aggregate.assert_has_calls([
+ mock.call(fake.AGGREGATES[0]),
+ mock.call(fake.AGGREGATES[1]),
+ ])
+ mock_get_aggregate_disk_types.assert_has_calls([
+ mock.call(fake.AGGREGATES[0]),
+ mock.call(fake.AGGREGATES[1]),
+ ])
def test_update_ssc_aggr_info_not_found(self):
self.library._have_cluster_creds = True
self.mock_object(self.client,
- 'get_aggregate_raid_types',
+ 'get_aggregate',
mock.Mock(return_value={}))
self.mock_object(self.client,
'get_aggregate_disk_types',
- mock.Mock(return_value={}))
- ssc_stats = {}
+ mock.Mock(return_value=None))
+ ssc_stats = {
+ fake.AGGREGATES[0]: {},
+ fake.AGGREGATES[1]: {},
+ }
self.library._update_ssc_aggr_info(fake.AGGREGATES, ssc_stats)
- self.assertDictEqual({}, ssc_stats)
+ expected = {
+ fake.AGGREGATES[0]: {
+ 'netapp_raid_type': None,
+ 'netapp_disk_type': None,
+ 'netapp_hybrid_aggregate': None,
+ },
+ fake.AGGREGATES[1]: {
+ 'netapp_raid_type': None,
+ 'netapp_disk_type': None,
+ 'netapp_hybrid_aggregate': None,
+ }
+ }
+ self.assertDictEqual(expected, ssc_stats)
def test_update_ssc_aggr_info_no_cluster_creds(self):
diff --git a/manila/tests/share/drivers/netapp/dataontap/fakes.py b/manila/tests/share/drivers/netapp/dataontap/fakes.py
index b59da1aa..d57b2f92 100644
--- a/manila/tests/share/drivers/netapp/dataontap/fakes.py
+++ b/manila/tests/share/drivers/netapp/dataontap/fakes.py
@@ -493,16 +493,19 @@ AGGREGATE_CAPACITIES_VSERVER_CREDS = {
SSC_INFO = {
AGGREGATES[0]: {
'netapp_raid_type': 'raid4',
- 'netapp_disk_type': 'FCAL'
+ 'netapp_disk_type': 'FCAL',
+ 'netapp_hybrid_aggregate': 'false',
},
AGGREGATES[1]: {
'netapp_raid_type': 'raid_dp',
- 'netapp_disk_type': 'SSD'
+ 'netapp_disk_type': ['SATA', 'SSD'],
+ 'netapp_hybrid_aggregate': 'true',
}
}
POOLS = [
{'pool_name': AGGREGATES[0],
+ 'netapp_aggregate': AGGREGATES[0],
'total_capacity_gb': 3.3,
'free_capacity_gb': 1.1,
'allocated_capacity_gb': 2.2,
@@ -512,9 +515,11 @@ POOLS = [
'compression': [True, False],
'thin_provisioning': [True, False],
'netapp_raid_type': 'raid4',
- 'netapp_disk_type': 'FCAL'
+ 'netapp_disk_type': 'FCAL',
+ 'netapp_hybrid_aggregate': 'false',
},
{'pool_name': AGGREGATES[1],
+ 'netapp_aggregate': AGGREGATES[1],
'total_capacity_gb': 6.0,
'free_capacity_gb': 2.0,
'allocated_capacity_gb': 4.0,
@@ -524,12 +529,14 @@ POOLS = [
'compression': [True, False],
'thin_provisioning': [True, False],
'netapp_raid_type': 'raid_dp',
- 'netapp_disk_type': 'SSD'
+ 'netapp_disk_type': ['SATA', 'SSD'],
+ 'netapp_hybrid_aggregate': 'true',
},
]
POOLS_VSERVER_CREDS = [
{'pool_name': AGGREGATES[0],
+ 'netapp_aggregate': AGGREGATES[0],
'total_capacity_gb': 'unknown',
'free_capacity_gb': 1.1,
'allocated_capacity_gb': 0.0,
@@ -538,10 +545,9 @@ POOLS_VSERVER_CREDS = [
'dedupe': [True, False],
'compression': [True, False],
'thin_provisioning': [True, False],
- 'netapp_raid_type': 'raid4',
- 'netapp_disk_type': 'FCAL'
},
{'pool_name': AGGREGATES[1],
+ 'netapp_aggregate': AGGREGATES[1],
'total_capacity_gb': 'unknown',
'free_capacity_gb': 2.0,
'allocated_capacity_gb': 0.0,
@@ -550,20 +556,23 @@ POOLS_VSERVER_CREDS = [
'dedupe': [True, False],
'compression': [True, False],
'thin_provisioning': [True, False],
- 'netapp_raid_type': 'raid_dp',
- 'netapp_disk_type': 'SSD'
},
]
-SSC_RAID_TYPES = {
- AGGREGATES[0]: 'raid4',
- AGGREGATES[1]: 'raid_dp'
-}
+SSC_AGGREGATES = [
+ {
+ 'name': AGGREGATES[0],
+ 'raid-type': 'raid4',
+ 'is-hybrid': False,
+ },
+ {
+ 'name': AGGREGATES[1],
+ 'raid-type': 'raid_dp',
+ 'is-hybrid': True,
+ },
+]
-SSC_DISK_TYPES = {
- AGGREGATES[0]: 'FCAL',
- AGGREGATES[1]: 'SSD'
-}
+SSC_DISK_TYPES = ['FCAL', ['SATA', 'SSD']]
def get_config_cmode():
diff --git a/releasenotes/notes/hybrid-aggregates-in-netapp-cdot-drivers-e7c90fb62426c281.yaml b/releasenotes/notes/hybrid-aggregates-in-netapp-cdot-drivers-e7c90fb62426c281.yaml
new file mode 100644
index 00000000..b3bfba0f
--- /dev/null
+++ b/releasenotes/notes/hybrid-aggregates-in-netapp-cdot-drivers-e7c90fb62426c281.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - Add support for hybrid aggregates to the NetApp cDOT drivers.
+