Merge "ScaleIO - Make compatible with next SIO version"

This commit is contained in:
Jenkins 2017-06-19 22:57:45 +00:00 committed by Gerrit Code Review
commit db8e25a3e0
3 changed files with 105 additions and 23 deletions

View File

@ -65,11 +65,13 @@ class TestScaleIODriver(test.TestCase):
Valid='0',
Invalid='1',
BadStatus='2',
ValidVariant='3',
))
__RESPONSE_MODE_NAMES = {
'0': 'Valid',
'1': 'Invalid',
'2': 'BadStatus',
'3': 'ValidVariant',
}
BAD_STATUS_RESPONSE = mocks.MockHTTPSResponse(

View File

@ -154,6 +154,55 @@ class TestMisc(scaleio.TestScaleIODriver):
self.driver.storage_pools = self.STORAGE_POOLS
self.driver.get_volume_stats(True)
def _setup_valid_variant_property(self, property):
"""Setup valid response that returns a variety of property name
"""
self.HTTPS_MOCK_RESPONSES = {
self.RESPONSE_MODE.ValidVariant: {
'types/Domain/instances/getByName::' +
self.domain_name_enc: '"{}"'.format(self.DOMAIN_NAME).encode(
'ascii',
'ignore'
),
'types/Pool/instances/getByName::{},{}'.format(
self.DOMAIN_NAME,
self.POOL_NAME
): '"{}"'.format(self.POOL_NAME).encode('ascii', 'ignore'),
'types/StoragePool/instances/action/querySelectedStatistics': {
'"{}"'.format(self.POOL_NAME): {
'capacityAvailableForVolumeAllocationInKb': 5000000,
'capacityLimitInKb': 16000000,
'spareCapacityInKb': 6000000,
'thickCapacityInUseInKb': 266,
property: 0,
},
},
'instances/Volume::{}/action/setVolumeName'.format(
self.volume['provider_id']):
self.new_volume['provider_id'],
'instances/Volume::{}/action/setVolumeName'.format(
self.new_volume['provider_id']):
self.volume['provider_id'],
'version': '"{}"'.format('2.0.1'),
}
}
def test_get_volume_stats_with_varying_properties(self):
"""Test getting volume stats with various property names
In SIO 3.0, a property was renamed.
The change is backwards compatible for now but this tests
ensures that the driver is tolerant of that change
"""
self.driver.storage_pools = self.STORAGE_POOLS
self._setup_valid_variant_property("thinCapacityAllocatedInKb")
self.set_https_response_mode(self.RESPONSE_MODE.ValidVariant)
self.driver.get_volume_stats(True)
self._setup_valid_variant_property("nonexistentProperty")
self.set_https_response_mode(self.RESPONSE_MODE.ValidVariant)
self.driver.get_volume_stats(True)
@mock.patch(
'cinder.volume.drivers.dell_emc.scaleio.driver.ScaleIODriver.'
'_rename_volume',

View File

@ -141,6 +141,8 @@ class ScaleIODriver(driver.VolumeDriver):
self.server_password = self.configuration.san_password
self.server_token = None
self.server_api_version = self.configuration.sio_server_api_version
# list of statistics/properties to query from SIO
self.statisticProperties = None
self.verify_server_certificate = (
self.configuration.sio_verify_server_certificate)
self.server_certificate_path = None
@ -264,6 +266,39 @@ class ScaleIODriver(driver.VolumeDriver):
"deprecated and will be removed in a future version"))
versionutils.report_deprecated_feature(LOG, msg)
def _get_queryable_statistics(self, sio_type, sio_id):
if self.statisticProperties is None:
self.statisticProperties = [
"capacityAvailableForVolumeAllocationInKb",
"capacityLimitInKb", "spareCapacityInKb",
"thickCapacityInUseInKb"]
# version 2.0 of SIO introduced thin volumes
if self._version_greater_than_or_equal(
self._get_server_api_version(),
"2.0.0"):
# check to see if thinCapacityAllocatedInKb is valid
# needed due to non-backwards compatible API
req_vars = {'server_ip': self.server_ip,
'server_port': self.server_port,
'sio_type': sio_type}
request = ("https://%(server_ip)s:%(server_port)s"
"/api/types/%(sio_type)s/instances/action/"
"querySelectedStatistics") % req_vars
params = {'ids': [sio_id],
'properties': ["thinCapacityAllocatedInKb"]}
r, response = self._execute_scaleio_post_request(params,
request)
if r.status_code == http_client.OK:
# is it valid, use it
self.statisticProperties.append(
"thinCapacityAllocatedInKb")
else:
# it is not valid, assume use of thinCapacityAllocatedInKm
self.statisticProperties.append(
"thinCapacityAllocatedInKm")
return self.statisticProperties
def _find_storage_pool_id_from_storage_type(self, storage_type):
# Default to what was configured in configuration file if not defined.
return storage_type.get(STORAGE_POOL_ID,
@ -922,20 +957,9 @@ class ScaleIODriver(driver.VolumeDriver):
request = ("https://%(server_ip)s:%(server_port)s"
"/api/types/StoragePool/instances/action/"
"querySelectedStatistics") % req_vars
# SIO version 2+ added a property...
if self._version_greater_than_or_equal(
self._get_server_api_version(),
"2.0.0"):
# The 'Km' in thinCapacityAllocatedInKm is a bug in REST API
params = {'ids': [pool_id], 'properties': [
"capacityAvailableForVolumeAllocationInKb",
"capacityLimitInKb", "spareCapacityInKb",
"thickCapacityInUseInKb", "thinCapacityAllocatedInKm"]}
else:
params = {'ids': [pool_id], 'properties': [
"capacityAvailableForVolumeAllocationInKb",
"capacityLimitInKb", "spareCapacityInKb",
"thickCapacityInUseInKb"]}
props = self._get_queryable_statistics("StoragePool", pool_id)
params = {'ids': [pool_id], 'properties': props}
r, response = self._execute_scaleio_post_request(params, request)
LOG.info("Query capacity stats response: %s.", response)
@ -949,16 +973,23 @@ class ScaleIODriver(driver.VolumeDriver):
# to 8 GB granularity in backend
free_capacity_gb = (
res['capacityAvailableForVolumeAllocationInKb'] / units.Mi)
thin_capacity_allocated = 0
# some versions of the API had a typo in the response
try:
thin_capacity_allocated = res['thinCapacityAllocatedInKm']
except (TypeError, KeyError):
pass
# some versions of the API respond without a typo
try:
thin_capacity_allocated = res['thinCapacityAllocatedInKb']
except (TypeError, KeyError):
pass
# Divide by two because ScaleIO creates a copy for each volume
if self._version_greater_than_or_equal(
self._get_server_api_version(),
"2.0.0"):
provisioned_capacity = (
((res['thickCapacityInUseInKb'] +
res['thinCapacityAllocatedInKm']) / 2) / units.Mi)
else:
provisioned_capacity = (
(res['thickCapacityInUseInKb'] / 2) / units.Mi)
provisioned_capacity = (
((res['thickCapacityInUseInKb'] +
thin_capacity_allocated) / 2) / units.Mi)
LOG.info("free capacity of pool %(pool)s is: %(free)s, "
"total capacity: %(total)s, "
"provisioned capacity: %(prov)s",