SF: Handle qos values on extend volume
For the Solidfire cinder driver when volume extend is called on a volume that has a qos with scaledIOPs=True, the values scaleMin, scaleMax, scaleBurst are ignored, thus when a volume grows the iops values stay the same when they should either grow or shrink. To correct the bug _retrieve_qos_setting has a new argument size with a default value of zero. This allows all previous calls to function properly, and saved duplicating code. Extend volume now calls _retrive_qos_settings with the new size argument and then includes that qos with the call to solidfire api ModifyVolume. Closes-Bug: #1783588 Change-Id: I8cb7b1eccbc63ef4077e86324afdd1a11409343d
This commit is contained in:
parent
8b39e1cee6
commit
12a7bf699d
@ -1,4 +1,4 @@
|
||||
|
||||
#
|
||||
# Copyright 2012 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
@ -63,6 +63,8 @@ f_uuid = ['262b9ce2-a71a-4fbe-830c-c20c5596caea',
|
||||
@ddt.ddt
|
||||
class SolidFireVolumeTestCase(test.TestCase):
|
||||
|
||||
EXPECTED_QOS = {'minIOPS': 110, 'burstIOPS': 1530, 'maxIOPS': 1020}
|
||||
|
||||
def setUp(self):
|
||||
self.ctxt = context.get_admin_context()
|
||||
self.configuration = conf.Configuration(None)
|
||||
@ -802,6 +804,58 @@ class SolidFireVolumeTestCase(test.TestCase):
|
||||
return_value=fake_no_volumes):
|
||||
sfv.delete_snapshot(testsnap)
|
||||
|
||||
def fake_ext_qos_issue_api_request(obj, method, params, version='1.0',
|
||||
endpoint=None):
|
||||
EXPECTED_SIZE = 2 << 30 # 2147483648 size + increase
|
||||
|
||||
if method == 'ModifyVolume':
|
||||
response = {'error': {'code': 0,
|
||||
'name': 'Extend Volume',
|
||||
'message': 'extend fail, size/scale-iops'},
|
||||
'id': 1}
|
||||
if params.get('totalSize', None) != EXPECTED_SIZE:
|
||||
msg = ('Error (%s) encountered during '
|
||||
'SolidFire API call.' % response['error']['name'])
|
||||
raise exception.SolidFireAPIException(message=msg)
|
||||
|
||||
if params.get('qos', None) != SolidFireVolumeTestCase.EXPECTED_QOS:
|
||||
msg = ('Error (%s) encountered during '
|
||||
'SolidFire API call.' % response['error']['name'])
|
||||
raise exception.SolidFireAPIException(message=msg)
|
||||
|
||||
return {'result': {}, 'id': 1}
|
||||
|
||||
elif method == 'GetAccountByName' and version == '1.0':
|
||||
results = {'result': {'account':
|
||||
{'accountID': 25,
|
||||
'username': params['username'],
|
||||
'status': 'active',
|
||||
'initiatorSecret': '123456789012',
|
||||
'targetSecret': '123456789012',
|
||||
'attributes': {},
|
||||
'volumes': [6, 7, 20]}},
|
||||
"id": 1}
|
||||
return results
|
||||
|
||||
elif method == 'ListVolumesForAccount' and version == '1.0':
|
||||
test_name = 'OS-VOLID-a720b3c0-d1f0-11e1-9b23-0800200c9a66'
|
||||
result = {'result': {
|
||||
'volumes': [{'volumeID': 5,
|
||||
'name': test_name,
|
||||
'accountID': 25,
|
||||
'sliceCount': 1,
|
||||
'totalSize': 1 * units.Gi,
|
||||
'enable512e': True,
|
||||
'access': "readWrite",
|
||||
'status': "active",
|
||||
'attributes': {},
|
||||
'qos': None,
|
||||
'iqn': test_name}]}}
|
||||
return result
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def test_extend_volume(self):
|
||||
self.mock_object(solidfire.SolidFireDriver,
|
||||
'_issue_api_request',
|
||||
@ -815,6 +869,30 @@ class SolidFireVolumeTestCase(test.TestCase):
|
||||
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
|
||||
sfv.extend_volume(testvol, 2)
|
||||
|
||||
def test_extend_volume_with_scaled_qos(self):
|
||||
size = 1
|
||||
self.mock_object(solidfire.SolidFireDriver,
|
||||
'_issue_api_request',
|
||||
self.fake_issue_api_request)
|
||||
sfv = solidfire.SolidFireDriver(configuration=self.configuration)
|
||||
qos_ref = qos_specs.create(self.ctxt,
|
||||
'qos-specs-1', {'minIOPS': '100',
|
||||
'maxIOPS': '1000',
|
||||
'burstIOPS': '1500',
|
||||
'scaledIOPS': 'True',
|
||||
'scaleMin': '10',
|
||||
'scaleMax': '20',
|
||||
'scaleBurst': '30'})
|
||||
type_ref = volume_types.create(self.ctxt, "type1",
|
||||
{'qos:minIOPS': '1000',
|
||||
'qos:maxIOPS': '10000',
|
||||
'qos:burstIOPS': '20000'})
|
||||
qos_specs.associate_qos_with_type(self.ctxt,
|
||||
qos_ref['id'],
|
||||
type_ref['id'])
|
||||
qos = sfv._set_qos_by_volume_type(self.ctxt, type_ref['id'], size + 1)
|
||||
self.assertEqual(SolidFireVolumeTestCase.EXPECTED_QOS, qos)
|
||||
|
||||
def test_extend_volume_fails_no_volume(self):
|
||||
self.mock_object(solidfire.SolidFireDriver,
|
||||
'_issue_api_request',
|
||||
@ -1347,8 +1425,8 @@ class SolidFireVolumeTestCase(test.TestCase):
|
||||
if 'ListSnapshots'in method:
|
||||
return {'result': {'snapshots': sf_snaps}}
|
||||
|
||||
with mock.patch.object(
|
||||
sfv, '_issue_api_request', side_effect=_fake_issue_api_req):
|
||||
with mock.patch.object(sfv, '_issue_api_request',
|
||||
side_effect=_fake_issue_api_req):
|
||||
volume_updates, snapshot_updates = sfv.update_provider_info(
|
||||
vrefs, snaprefs)
|
||||
self.assertEqual('99 100 53c8be1e-89e2-4f7f-a2e3-7cb84c47e0ec',
|
||||
|
@ -198,10 +198,10 @@ class SolidFireDriver(san.SanISCSIDriver):
|
||||
2.0.10 - Add response to debug on retryable errors
|
||||
2.0.11 - Add ability to failback replicating volumes
|
||||
2.0.12 - Fix bug #1744005
|
||||
|
||||
2.0.14 - Fix bug #1782588 qos settings on extend
|
||||
"""
|
||||
|
||||
VERSION = '2.0.12'
|
||||
VERSION = '2.0.14'
|
||||
|
||||
# ThirdPartySystems wiki page
|
||||
CI_WIKI_NAME = "NetApp_SolidFire_CI"
|
||||
@ -1337,7 +1337,8 @@ class SolidFireDriver(san.SanISCSIDriver):
|
||||
volume)
|
||||
return model, True
|
||||
|
||||
def _retrieve_qos_setting(self, volume):
|
||||
# extended_size > 0 when we are extending a volume
|
||||
def _retrieve_qos_setting(self, volume, extended_size=0):
|
||||
qos = {}
|
||||
if (self.configuration.sf_allow_tenant_qos and
|
||||
volume.get('volume_metadata')is not None):
|
||||
@ -1347,7 +1348,8 @@ class SolidFireDriver(san.SanISCSIDriver):
|
||||
type_id = volume.get('volume_type_id', None)
|
||||
if type_id is not None:
|
||||
qos = self._set_qos_by_volume_type(ctxt, type_id,
|
||||
volume.get('size'))
|
||||
extended_size if extended_size
|
||||
> 0 else volume.get('size'))
|
||||
return qos
|
||||
|
||||
def create_volume(self, volume):
|
||||
@ -1886,10 +1888,11 @@ class SolidFireDriver(san.SanISCSIDriver):
|
||||
"the SolidFire Cluster while attempting "
|
||||
"extend_volume operation!", volume['id'])
|
||||
raise exception.VolumeNotFound(volume_id=volume['id'])
|
||||
|
||||
qos = self._retrieve_qos_setting(volume, new_size)
|
||||
params = {
|
||||
'volumeID': sf_vol['volumeID'],
|
||||
'totalSize': int(new_size * units.Gi)
|
||||
'totalSize': int(new_size * units.Gi),
|
||||
'qos': qos
|
||||
}
|
||||
self._issue_api_request('ModifyVolume',
|
||||
params, version='5.0')
|
||||
|
5
releasenotes/notes/bug-1782588-7e058b379da95309.yaml
Normal file
5
releasenotes/notes/bug-1782588-7e058b379da95309.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Solidfire fix extend volume with qos-Scaling to honor the increased size
|
||||
with increased iops on the extended volume.
|
Loading…
Reference in New Issue
Block a user