Merge "Add IOPS limits that scale per-GB"

This commit is contained in:
Jenkins 2017-04-20 18:50:45 +00:00 committed by Gerrit Code Review
commit 9447e46ca5
2 changed files with 76 additions and 0 deletions

View File

@ -31,6 +31,8 @@ from cinder.tests.unit import fake_volume
from cinder.tests.unit import utils as tests_utils
from cinder.tests.unit import volume as base
import cinder.volume
import cinder.volume.targets
import cinder.volume.targets.iscsi
@ddt.ddt
@ -162,6 +164,63 @@ class VolumeConnectionTestCase(base.BaseVolumeTestCase):
self.context, fake_volume_obj, connector)
self.assertIsNone(conn_info['data']['qos_specs'])
@mock.patch.object(cinder.volume.targets.iscsi.ISCSITarget,
'_get_target_chap_auth')
@mock.patch.object(db, 'volume_admin_metadata_get')
@mock.patch.object(db.sqlalchemy.api, 'volume_get')
@mock.patch.object(db, 'volume_update')
def test_initialize_connection_qos_per_gb(self,
_mock_volume_update,
_mock_volume_get,
_mock_volume_admin_metadata_get,
mock_get_target):
"""Make sure initialize_connection returns correct information."""
_fake_admin_meta = [{'key': 'fake-key', 'value': 'fake-value'}]
_fake_volume = {'size': 3,
'volume_type_id': fake.VOLUME_TYPE_ID,
'name': 'fake_name',
'host': 'fake_host',
'id': fake.VOLUME_ID,
'volume_admin_metadata': _fake_admin_meta}
fake_volume_obj = fake_volume.fake_volume_obj(self.context,
**_fake_volume)
_mock_volume_get.return_value = _fake_volume
_mock_volume_update.return_value = _fake_volume
_mock_volume_admin_metadata_get.return_value = {
'fake-key': 'fake-value'}
connector = {'ip': 'IP', 'initiator': 'INITIATOR'}
qos_values = {'consumer': 'front-end',
'specs': {
'write_iops_sec_per_gb': 5,
'read_iops_sec_per_gb': 7700,
'total_iops_sec_per_gb': 300000}
}
with mock.patch.object(cinder.volume.volume_types,
'get_volume_type_qos_specs') as type_qos, \
mock.patch.object(cinder.tests.fake_driver.FakeLoggingVolumeDriver,
'initialize_connection') as driver_init:
type_qos.return_value = dict(qos_specs=qos_values)
driver_init.return_value = {'data': {}}
mock_get_target.return_value = None
qos_specs_expected = {'write_iops_sec': 15,
'read_iops_sec': 23100,
'total_iops_sec': 900000}
# initialize_connection() passes qos_specs that is designated to
# be consumed by front-end or both front-end and back-end
conn_info = self.volume.initialize_connection(
self.context, fake_volume_obj, connector,)
self.assertDictEqual(qos_specs_expected,
conn_info['data']['qos_specs'])
qos_values.update({'consumer': 'both'})
conn_info = self.volume.initialize_connection(
self.context, fake_volume_obj, connector)
self.assertDictEqual(qos_specs_expected,
conn_info['data']['qos_specs'])
@mock.patch.object(fake_driver.FakeLoggingVolumeDriver, 'create_export')
def test_initialize_connection_export_failure(self,
_mock_create_export):

View File

@ -1409,6 +1409,23 @@ class VolumeManager(manager.CleanableManager,
if qos and qos.get('consumer') in ['front-end', 'both']:
specs = qos.get('specs')
if specs is not None:
# Compute fixed IOPS values for per-GB keys
if 'write_iops_sec_per_gb' in specs:
specs['write_iops_sec'] = (
int(specs['write_iops_sec_per_gb']) * int(volume.size))
specs.pop('write_iops_sec_per_gb')
if 'read_iops_sec_per_gb' in specs:
specs['read_iops_sec'] = (
int(specs['read_iops_sec_per_gb']) * int(volume.size))
specs.pop('read_iops_sec_per_gb')
if 'total_iops_sec_per_gb' in specs:
specs['total_iops_sec'] = (
int(specs['total_iops_sec_per_gb']) * int(volume.size))
specs.pop('total_iops_sec_per_gb')
qos_spec = dict(qos_specs=specs)
conn_info['data'].update(qos_spec)