NetApp: Report hybrid aggregates in volume stats
NetApp cDOT controllers can mix SSDs and spinning disks in the same aggregate, where the SSDs are used for a cache. This commit reports the hybrid aggregate attribute to the scheduler for each pool for use in extra specs matching. This commit also ensures that all aggregate values reported to the Cinder scheduler correctly include a vendor-specific prefix. Implements: blueprint netapp-report-cdot-hybrid-aggrs Change-Id: I8fbfbe3ffaad5fe89db03d2a4e567e9b35e59d5b
This commit is contained in:
parent
0cd9b10c0a
commit
7cc95f8054
@ -622,7 +622,7 @@ AGGR_GET_NODE_RESPONSE = etree.XML("""
|
||||
'node': NODE_NAME,
|
||||
})
|
||||
|
||||
AGGR_RAID_TYPE = 'raid_dp'
|
||||
AGGREGATE_RAID_TYPE = 'raid_dp'
|
||||
AGGR_GET_ITER_SSC_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes-list>
|
||||
@ -639,17 +639,19 @@ AGGR_GET_ITER_SSC_RESPONSE = etree.XML("""
|
||||
</plex-attributes>
|
||||
</plexes>
|
||||
<raid-type>%(raid)s</raid-type>
|
||||
<is-hybrid>true</is-hybrid>
|
||||
</aggr-raid-attributes>
|
||||
<aggregate-name>%(aggr)s</aggregate-name>
|
||||
</aggr-attributes>
|
||||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
</results>
|
||||
""" % {'aggr': VOLUME_AGGREGATE_NAME, 'raid': AGGR_RAID_TYPE})
|
||||
""" % {'aggr': VOLUME_AGGREGATE_NAME, 'raid': AGGREGATE_RAID_TYPE})
|
||||
|
||||
AGGR_INFO_SSC = {
|
||||
'name': VOLUME_AGGREGATE_NAME,
|
||||
'raid-type': AGGR_RAID_TYPE,
|
||||
'raid-type': AGGREGATE_RAID_TYPE,
|
||||
'is-hybrid': True,
|
||||
}
|
||||
|
||||
AGGR_SIZE_TOTAL = 107374182400
|
||||
@ -911,20 +913,41 @@ STORAGE_DISK_GET_ITER_RESPONSE_PAGE_3 = etree.XML("""
|
||||
</results>
|
||||
""")
|
||||
|
||||
AGGR_DISK_TYPE = 'FCAL'
|
||||
AGGREGATE_DISK_TYPES = ['SATA', 'SSD']
|
||||
STORAGE_DISK_GET_ITER_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
<attributes-list>
|
||||
<storage-disk-info>
|
||||
<disk-name>cluster3-01:v5.19</disk-name>
|
||||
<disk-raid-info>
|
||||
<effective-disk-type>%s</effective-disk-type>
|
||||
<effective-disk-type>%(type0)s</effective-disk-type>
|
||||
</disk-raid-info>
|
||||
</storage-disk-info>
|
||||
<storage-disk-info>
|
||||
<disk-name>cluster3-01:v5.20</disk-name>
|
||||
<disk-raid-info>
|
||||
<effective-disk-type>%(type0)s</effective-disk-type>
|
||||
</disk-raid-info>
|
||||
</storage-disk-info>
|
||||
<storage-disk-info>
|
||||
<disk-name>cluster3-01:v5.20</disk-name>
|
||||
<disk-raid-info>
|
||||
<effective-disk-type>%(type1)s</effective-disk-type>
|
||||
</disk-raid-info>
|
||||
</storage-disk-info>
|
||||
<storage-disk-info>
|
||||
<disk-name>cluster3-01:v5.20</disk-name>
|
||||
<disk-raid-info>
|
||||
<effective-disk-type>%(type1)s</effective-disk-type>
|
||||
</disk-raid-info>
|
||||
</storage-disk-info>
|
||||
</attributes-list>
|
||||
<num-records>1</num-records>
|
||||
<num-records>4</num-records>
|
||||
</results>
|
||||
""" % AGGR_DISK_TYPE)
|
||||
""" % {
|
||||
'type0': AGGREGATE_DISK_TYPES[0],
|
||||
'type1': AGGREGATE_DISK_TYPES[1],
|
||||
})
|
||||
|
||||
SYSTEM_USER_CAPABILITY_GET_ITER_RESPONSE = etree.XML("""
|
||||
<results status="passed">
|
||||
|
@ -173,7 +173,7 @@ class NetAppCmodeClientTestCase(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
|
||||
@ -1681,6 +1681,7 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||
'aggregate-name': None,
|
||||
'aggr-raid-attributes': {
|
||||
'raid-type': None,
|
||||
'is-hybrid': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1692,6 +1693,7 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||
expected = {
|
||||
'name': fake_client.VOLUME_AGGREGATE_NAME,
|
||||
'raid-type': 'raid_dp',
|
||||
'is-hybrid': True,
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
@ -1716,19 +1718,64 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||
|
||||
self.assertEqual({}, result)
|
||||
|
||||
def test_get_aggregate_disk_type(self):
|
||||
@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_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
self.assertItemsEqual(expected, result)
|
||||
mock_get_aggregate_disk_types.assert_called_once_with(
|
||||
fake_client.VOLUME_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_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
self.assertIsNone(result)
|
||||
mock_get_aggregate_disk_types.assert_called_once_with(
|
||||
fake_client.VOLUME_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_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
self.assertIsInstance(result, list)
|
||||
self.assertItemsEqual(['SATA', 'SSD'], result)
|
||||
mock_get_aggregate_disk_types.assert_has_calls([
|
||||
mock.call(fake_client.VOLUME_AGGREGATE_NAME),
|
||||
mock.call(fake_client.VOLUME_AGGREGATE_NAME, shared=True),
|
||||
])
|
||||
|
||||
def test__get_aggregate_disk_types(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
fake_client.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_type(
|
||||
result = self.client._get_aggregate_disk_types(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
storage_disk_get_iter_args = {
|
||||
'max-records': 1,
|
||||
'query': {
|
||||
'storage-disk-info': {
|
||||
'disk-raid-info': {
|
||||
@ -1747,34 +1794,76 @@ class NetAppCmodeClientTestCase(test.TestCase):
|
||||
},
|
||||
},
|
||||
}
|
||||
self.client.send_request.assert_called_once_with(
|
||||
self.client.send_iter_request.assert_called_once_with(
|
||||
'storage-disk-get-iter', storage_disk_get_iter_args,
|
||||
enable_tunneling=False)
|
||||
self.assertEqual(fake_client.AGGR_DISK_TYPE, result)
|
||||
|
||||
@ddt.data(fake_client.NO_RECORDS_RESPONSE, fake_client.INVALID_RESPONSE)
|
||||
def test_get_aggregate_disk_type_not_found(self, response):
|
||||
expected = set(fake_client.AGGREGATE_DISK_TYPES)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
api_response = netapp_api.NaElement(response)
|
||||
def test__get_aggregate_disk_types_shared(self):
|
||||
|
||||
api_response = netapp_api.NaElement(
|
||||
fake_client.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_type(
|
||||
result = self.client._get_aggregate_disk_types(
|
||||
fake_client.VOLUME_AGGREGATE_NAME, shared=True)
|
||||
|
||||
storage_disk_get_iter_args = {
|
||||
'query': {
|
||||
'storage-disk-info': {
|
||||
'disk-raid-info': {
|
||||
'disk-shared-info': {
|
||||
'aggregate-list': {
|
||||
'shared-aggregate-info': {
|
||||
'aggregate-name':
|
||||
fake_client.VOLUME_AGGREGATE_NAME,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'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,
|
||||
enable_tunneling=False)
|
||||
|
||||
expected = set(fake_client.AGGREGATE_DISK_TYPES)
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test__get_aggregate_disk_types_not_found(self):
|
||||
|
||||
api_response = netapp_api.NaElement(fake_client.NO_RECORDS_RESPONSE)
|
||||
self.mock_object(self.client,
|
||||
'send_iter_request',
|
||||
mock.Mock(return_value=api_response))
|
||||
|
||||
result = self.client._get_aggregate_disk_types(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
self.assertEqual('unknown', result)
|
||||
self.assertEqual(set(), result)
|
||||
|
||||
def test_get_aggregate_disk_type_api_error(self):
|
||||
def test__get_aggregate_disk_types_api_error(self):
|
||||
|
||||
self.mock_object(self.client,
|
||||
'send_request',
|
||||
'send_iter_request',
|
||||
mock.Mock(side_effect=self._mock_api_error()))
|
||||
|
||||
result = self.client.get_aggregate_disk_type(
|
||||
result = self.client._get_aggregate_disk_types(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
self.assertEqual('unknown', result)
|
||||
self.assertEqual(set([]), result)
|
||||
|
||||
def test_get_aggregate_capacities(self):
|
||||
|
||||
|
@ -45,13 +45,13 @@ class PerformanceCmodeLibraryTestCase(test.TestCase):
|
||||
|
||||
self.fake_volumes = {
|
||||
'pool1': {
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
},
|
||||
'pool2': {
|
||||
'aggregate': 'aggr2',
|
||||
'netapp_aggregate': 'aggr2',
|
||||
},
|
||||
'pool3': {
|
||||
'aggregate': 'aggr2',
|
||||
'netapp_aggregate': 'aggr2',
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -302,7 +302,7 @@ class NetAppBlockStorageCmodeLibraryTestCase(test.TestCase):
|
||||
'netapp_compression': 'false',
|
||||
'netapp_mirrored': 'false',
|
||||
'netapp_dedup': 'true',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD',
|
||||
},
|
||||
@ -349,7 +349,7 @@ class NetAppBlockStorageCmodeLibraryTestCase(test.TestCase):
|
||||
'total_capacity_gb': 10.0,
|
||||
'free_capacity_gb': 2.0,
|
||||
'provisioned_capacity_gb': 8.0,
|
||||
'aggregate_used_percent': 45,
|
||||
'netapp_aggregate_used_percent': 45,
|
||||
'utilization': 30.0,
|
||||
'filter_function': 'filter',
|
||||
'goodness_function': 'goodness',
|
||||
@ -359,7 +359,7 @@ class NetAppBlockStorageCmodeLibraryTestCase(test.TestCase):
|
||||
'netapp_compression': 'false',
|
||||
'netapp_mirrored': 'false',
|
||||
'netapp_dedup': 'true',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD',
|
||||
}]
|
||||
|
@ -93,7 +93,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
'netapp_compression': 'false',
|
||||
'netapp_mirrored': 'false',
|
||||
'netapp_dedup': 'true',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD',
|
||||
},
|
||||
@ -146,7 +146,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
'total_capacity_gb': total_capacity_gb,
|
||||
'free_capacity_gb': free_capacity_gb,
|
||||
'provisioned_capacity_gb': provisioned_capacity_gb,
|
||||
'aggregate_used_percent': 45,
|
||||
'netapp_aggregate_used_percent': 45,
|
||||
'utilization': 30.0,
|
||||
'filter_function': 'filter',
|
||||
'goodness_function': 'goodness',
|
||||
@ -156,7 +156,7 @@ class NetAppCmodeNfsDriverTestCase(test.TestCase):
|
||||
'netapp_compression': 'false',
|
||||
'netapp_mirrored': 'false',
|
||||
'netapp_dedup': 'true',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD',
|
||||
}]
|
||||
|
@ -30,24 +30,26 @@ SSC = {
|
||||
'thick_provisioning_support': True,
|
||||
'thin_provisioning_support': False,
|
||||
'netapp_thin_provisioned': 'false',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
'netapp_compression': 'false',
|
||||
'netapp_dedup': 'true',
|
||||
'netapp_mirrored': 'false',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'SSD',
|
||||
'netapp_hybrid_aggregate': False,
|
||||
'pool_name': 'volume1',
|
||||
},
|
||||
'volume2': {
|
||||
'thick_provisioning_support': False,
|
||||
'thin_provisioning_support': True,
|
||||
'netapp_thin_provisioned': 'true',
|
||||
'aggregate': 'aggr2',
|
||||
'netapp_aggregate': 'aggr2',
|
||||
'netapp_compression': 'true',
|
||||
'netapp_dedup': 'true',
|
||||
'netapp_mirrored': 'true',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_disk_type': 'FCAL',
|
||||
'netapp_hybrid_aggregate': True,
|
||||
'pool_name': 'volume2',
|
||||
},
|
||||
}
|
||||
@ -57,13 +59,13 @@ SSC_FLEXVOL_INFO = {
|
||||
'thick_provisioning_support': True,
|
||||
'thin_provisioning_support': False,
|
||||
'netapp_thin_provisioned': 'false',
|
||||
'aggregate': 'aggr1',
|
||||
'netapp_aggregate': 'aggr1',
|
||||
},
|
||||
'volume2': {
|
||||
'thick_provisioning_support': False,
|
||||
'thin_provisioning_support': True,
|
||||
'netapp_thin_provisioned': 'true',
|
||||
'aggregate': 'aggr2',
|
||||
'netapp_aggregate': 'aggr2',
|
||||
},
|
||||
}
|
||||
|
||||
@ -91,9 +93,11 @@ SSC_AGGREGATE_INFO = {
|
||||
'volume1': {
|
||||
'netapp_disk_type': 'SSD',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_hybrid_aggregate': False,
|
||||
},
|
||||
'volume2': {
|
||||
'netapp_disk_type': 'FCAL',
|
||||
'netapp_raid_type': 'raid_dp',
|
||||
'netapp_hybrid_aggregate': True,
|
||||
},
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
||||
'netapp_thin_provisioned': 'true',
|
||||
'thick_provisioning_support': False,
|
||||
'thin_provisioning_support': True,
|
||||
'aggregate': 'fake_aggr1',
|
||||
'netapp_aggregate': 'fake_aggr1',
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
self.zapi_client.get_flexvol.assert_called_once_with(
|
||||
@ -198,7 +198,7 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
||||
'netapp_thin_provisioned': 'false',
|
||||
'thick_provisioning_support': lun_space_guarantee,
|
||||
'thin_provisioning_support': not lun_space_guarantee,
|
||||
'aggregate': 'fake_aggr1',
|
||||
'netapp_aggregate': 'fake_aggr1',
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
self.zapi_client.get_flexvol.assert_called_once_with(
|
||||
@ -223,7 +223,7 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
||||
'netapp_thin_provisioned': 'true',
|
||||
'thick_provisioning_support': False,
|
||||
'thin_provisioning_support': True,
|
||||
'aggregate': 'fake_aggr1',
|
||||
'netapp_aggregate': 'fake_aggr1',
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
self.zapi_client.get_flexvol.assert_called_once_with(
|
||||
@ -251,7 +251,7 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
||||
'netapp_thin_provisioned': 'false',
|
||||
'thick_provisioning_support': not nfs_sparsed_volumes,
|
||||
'thin_provisioning_support': nfs_sparsed_volumes,
|
||||
'aggregate': 'fake_aggr1',
|
||||
'netapp_aggregate': 'fake_aggr1',
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
self.zapi_client.get_flexvol.assert_called_once_with(
|
||||
@ -291,25 +291,45 @@ class CapabilitiesLibraryTestCase(test.TestCase):
|
||||
|
||||
def test_get_ssc_aggregate_info(self):
|
||||
|
||||
self.mock_object(
|
||||
self.ssc_library.zapi_client, 'get_aggregate_disk_type',
|
||||
mock.Mock(return_value=fake_client.AGGR_DISK_TYPE))
|
||||
self.mock_object(
|
||||
self.ssc_library.zapi_client, 'get_aggregate',
|
||||
mock.Mock(return_value=fake_client.AGGR_INFO_SSC))
|
||||
self.mock_object(
|
||||
self.ssc_library.zapi_client, 'get_aggregate_disk_types',
|
||||
mock.Mock(return_value=fake_client.AGGREGATE_DISK_TYPES))
|
||||
|
||||
result = self.ssc_library._get_ssc_aggregate_info(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
expected = {
|
||||
'netapp_disk_type': fake_client.AGGR_DISK_TYPE,
|
||||
'netapp_raid_type': fake_client.AGGR_RAID_TYPE,
|
||||
'netapp_disk_type': fake_client.AGGREGATE_DISK_TYPES,
|
||||
'netapp_raid_type': fake_client.AGGREGATE_RAID_TYPE,
|
||||
'netapp_hybrid_aggregate': 'true',
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
self.zapi_client.get_aggregate_disk_type.assert_called_once_with(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
self.zapi_client.get_aggregate.assert_called_once_with(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
self.zapi_client.get_aggregate_disk_types.assert_called_once_with(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
def test_get_ssc_aggregate_info_not_found(self):
|
||||
|
||||
self.mock_object(
|
||||
self.ssc_library.zapi_client, 'get_aggregate',
|
||||
mock.Mock(return_value={}))
|
||||
self.mock_object(
|
||||
self.ssc_library.zapi_client, 'get_aggregate_disk_types',
|
||||
mock.Mock(return_value=None))
|
||||
|
||||
result = self.ssc_library._get_ssc_aggregate_info(
|
||||
fake_client.VOLUME_AGGREGATE_NAME)
|
||||
|
||||
expected = {
|
||||
'netapp_disk_type': None,
|
||||
'netapp_raid_type': None,
|
||||
'netapp_hybrid_aggregate': None,
|
||||
}
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
def test_get_matching_flexvols_for_extra_specs(self):
|
||||
|
||||
|
@ -251,9 +251,9 @@ class NetAppBlockStorageCmodeLibrary(block_base.NetAppBlockStorageLibrary):
|
||||
pool['provisioned_capacity_gb'] = round(
|
||||
pool['total_capacity_gb'] - pool['free_capacity_gb'], 2)
|
||||
|
||||
aggregate_name = ssc_vol_info.get('aggregate')
|
||||
aggregate_name = ssc_vol_info.get('netapp_aggregate')
|
||||
aggr_capacity = aggr_capacities.get(aggregate_name, {})
|
||||
pool['aggregate_used_percent'] = aggr_capacity.get(
|
||||
pool['netapp_aggregate_used_percent'] = aggr_capacity.get(
|
||||
'percent-used', 0)
|
||||
|
||||
# Add utilization data
|
||||
|
@ -67,6 +67,8 @@ class Client(client_base.Client):
|
||||
self.features.add_feature('FAST_CLONE_DELETE', supported=ontapi_1_30)
|
||||
self.features.add_feature('SYSTEM_CONSTITUENT_METRICS',
|
||||
supported=ontapi_1_30)
|
||||
self.features.add_feature('ADVANCED_DISK_PARTITIONING',
|
||||
supported=ontapi_1_30)
|
||||
self.features.add_feature('BACKUP_CLONE_PARAM', supported=ontapi_1_100)
|
||||
|
||||
def _invoke_vserver_api(self, na_element, vserver):
|
||||
@ -1093,6 +1095,7 @@ class Client(client_base.Client):
|
||||
'aggregate-name': None,
|
||||
'aggr-raid-attributes': {
|
||||
'raid-type': None,
|
||||
'is-hybrid': None,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -1115,25 +1118,50 @@ class Client(client_base.Client):
|
||||
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
|
||||
|
||||
def get_aggregate_disk_type(self, aggregate_name):
|
||||
"""Get the disk type of an aggregate."""
|
||||
def get_aggregate_disk_types(self, aggregate_name):
|
||||
"""Get the disk type(s) of an aggregate."""
|
||||
|
||||
# Note(cknight): 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': {
|
||||
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))
|
||||
|
||||
return list(disk_types) if disk_types else None
|
||||
|
||||
def _get_aggregate_disk_types(self, aggregate_name, shared=False):
|
||||
"""Get the disk type(s) of an aggregate (may be a list)."""
|
||||
|
||||
disk_types = set()
|
||||
|
||||
if shared:
|
||||
disk_raid_info = {
|
||||
'disk-shared-info': {
|
||||
'aggregate-list': {
|
||||
'shared-aggregate-info': {
|
||||
'aggregate-name': aggregate_name,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
else:
|
||||
disk_raid_info = {
|
||||
'disk-aggregate-info': {
|
||||
'aggregate-name': aggregate_name,
|
||||
},
|
||||
}
|
||||
|
||||
api_args = {
|
||||
'query': {
|
||||
'storage-disk-info': {
|
||||
'disk-raid-info': disk_raid_info,
|
||||
},
|
||||
},
|
||||
'desired-attributes': {
|
||||
'storage-disk-info': {
|
||||
@ -1143,29 +1171,28 @@ class Client(client_base.Client):
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
try:
|
||||
result = self.send_request('storage-disk-get-iter', api_args,
|
||||
enable_tunneling=False)
|
||||
result = self.send_iter_request(
|
||||
'storage-disk-get-iter', api_args, enable_tunneling=False)
|
||||
except netapp_api.NaApiError:
|
||||
msg = _LE('Failed to get disk info for aggregate %s.')
|
||||
LOG.exception(msg, aggregate_name)
|
||||
return 'unknown'
|
||||
|
||||
if self._get_record_count(result) != 1:
|
||||
return 'unknown'
|
||||
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():
|
||||
|
||||
disk_raid_info = storage_disk_info.get_child_by_name(
|
||||
'disk-raid-info') or netapp_api.NaElement('none')
|
||||
disk_type = disk_raid_info.get_child_content(
|
||||
'effective-disk-type') or 'unknown'
|
||||
return disk_type
|
||||
disk_raid_info = storage_disk_info.get_child_by_name(
|
||||
'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 'unknown'
|
||||
return disk_types
|
||||
|
||||
def get_aggregate_capacities(self, aggregate_names):
|
||||
"""Gets capacity info for multiple aggregates."""
|
||||
|
@ -208,9 +208,9 @@ class NetAppCmodeNfsDriver(nfs_base.NetAppNfsDriver):
|
||||
capacity = self._get_share_capacity_info(nfs_share)
|
||||
pool.update(capacity)
|
||||
|
||||
aggregate_name = ssc_vol_info.get('aggregate')
|
||||
aggregate_name = ssc_vol_info.get('netapp_aggregate')
|
||||
aggr_capacity = aggr_capacities.get(aggregate_name, {})
|
||||
pool['aggregate_used_percent'] = aggr_capacity.get(
|
||||
pool['netapp_aggregate_used_percent'] = aggr_capacity.get(
|
||||
'percent-used', 0)
|
||||
|
||||
# Add utilization data
|
||||
|
@ -97,7 +97,7 @@ class PerformanceCmodeLibrary(perf_base.PerformanceLibrary):
|
||||
# Update pool utilization map atomically
|
||||
pool_utilization = {}
|
||||
for pool_name, pool_info in ssc_pools.items():
|
||||
aggr_name = pool_info.get('aggregate', 'unknown')
|
||||
aggr_name = pool_info.get('netapp_aggregate', 'unknown')
|
||||
node_name = aggr_node_map.get(aggr_name)
|
||||
if node_name:
|
||||
pool_utilization[pool_name] = node_utilization.get(
|
||||
@ -118,7 +118,7 @@ class PerformanceCmodeLibrary(perf_base.PerformanceLibrary):
|
||||
|
||||
aggr_names = set()
|
||||
for pool_name, pool_info in ssc_pools.items():
|
||||
aggr_names.add(pool_info.get('aggregate'))
|
||||
aggr_names.add(pool_info.get('netapp_aggregate'))
|
||||
return aggr_names
|
||||
|
||||
def _get_nodes_for_aggregates(self, aggr_names):
|
||||
|
@ -98,8 +98,8 @@ class CapabilitiesLibrary(object):
|
||||
|
||||
aggregates = set()
|
||||
for __, flexvol_info in self.ssc.items():
|
||||
if 'aggregate' in flexvol_info:
|
||||
aggregates.add(flexvol_info['aggregate'])
|
||||
if 'netapp_aggregate' in flexvol_info:
|
||||
aggregates.add(flexvol_info['netapp_aggregate'])
|
||||
return list(aggregates)
|
||||
|
||||
def update_ssc(self, flexvol_map):
|
||||
@ -126,7 +126,7 @@ class CapabilitiesLibrary(object):
|
||||
ssc_volume.update(self._get_ssc_mirror_info(flexvol_name))
|
||||
|
||||
# Get aggregate info
|
||||
aggregate_name = ssc_volume.get('aggregate')
|
||||
aggregate_name = ssc_volume.get('netapp_aggregate')
|
||||
ssc_volume.update(self._get_ssc_aggregate_info(aggregate_name))
|
||||
|
||||
ssc[flexvol_name] = ssc_volume
|
||||
@ -147,7 +147,7 @@ class CapabilitiesLibrary(object):
|
||||
'netapp_thin_provisioned': six.text_type(not netapp_thick).lower(),
|
||||
'thick_provisioning_support': thick,
|
||||
'thin_provisioning_support': not thick,
|
||||
'aggregate': volume_info.get('aggregate'),
|
||||
'netapp_aggregate': volume_info.get('aggregate'),
|
||||
}
|
||||
|
||||
def _get_thick_provisioning_support(self, netapp_thick):
|
||||
@ -190,14 +190,15 @@ class CapabilitiesLibrary(object):
|
||||
def _get_ssc_aggregate_info(self, aggregate_name):
|
||||
"""Gather aggregate info and recast into SSC-style volume stats."""
|
||||
|
||||
disk_type = self.zapi_client.get_aggregate_disk_type(aggregate_name)
|
||||
aggr_info = self.zapi_client.get_aggregate(aggregate_name)
|
||||
|
||||
raid_type = aggr_info.get('raid-type')
|
||||
aggregate = self.zapi_client.get_aggregate(aggregate_name)
|
||||
hybrid = (six.text_type(aggregate.get('is-hybrid')).lower()
|
||||
if 'is-hybrid' in aggregate else None)
|
||||
disk_types = self.zapi_client.get_aggregate_disk_types(aggregate_name)
|
||||
|
||||
return {
|
||||
'netapp_disk_type': disk_type,
|
||||
'netapp_raid_type': raid_type,
|
||||
'netapp_raid_type': aggregate.get('raid-type'),
|
||||
'netapp_hybrid_aggregate': hybrid,
|
||||
'netapp_disk_type': disk_types,
|
||||
}
|
||||
|
||||
def get_matching_flexvols_for_extra_specs(self, extra_specs):
|
||||
|
@ -0,0 +1,4 @@
|
||||
---
|
||||
features:
|
||||
- Add support for hybrid aggregates to the NetApp cDOT drivers.
|
||||
|
Loading…
Reference in New Issue
Block a user