From f14dcb79c8767a4a17c19db4adbab44bb55f2218 Mon Sep 17 00:00:00 2001 From: John Griffith Date: Fri, 20 Dec 2013 17:33:23 -0700 Subject: [PATCH] Add qos_specs support to solidfire driver We've added a new qos_specs object to Cinder that allows creation and management of qos settings separate from volume-types. Now instead of embedding the qos info in the extra-specs of the volume-type we associate the desired qos-spec to a volume-type. This change implements the capability of the SolidFire driver to take advantage of that feature. Change-Id: I215bd0cff0c0a91c106de27eea9ec2b91689a46e Implements: blueprint add-qosspecs-support-to-solidfire-driver --- cinder/tests/test_solidfire.py | 51 ++++++++++++++++++++++++++++++ cinder/volume/drivers/solidfire.py | 13 +++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/cinder/tests/test_solidfire.py b/cinder/tests/test_solidfire.py index b22850988..48f8ef241 100644 --- a/cinder/tests/test_solidfire.py +++ b/cinder/tests/test_solidfire.py @@ -17,6 +17,7 @@ import mox +from cinder import context from cinder import exception from cinder.openstack.common import log as logging from cinder.openstack.common import timeutils @@ -24,6 +25,8 @@ from cinder import test from cinder import units from cinder.volume import configuration as conf from cinder.volume.drivers.solidfire import SolidFireDriver +from cinder.volume import qos_specs +from cinder.volume import volume_types LOG = logging.getLogger(__name__) @@ -37,6 +40,7 @@ def create_configuration(): class SolidFireVolumeTestCase(test.TestCase): def setUp(self): + self.ctxt = context.get_admin_context() self._mox = mox.Mox() self.configuration = mox.MockObject(conf.Configuration) self.configuration.sf_allow_tenant_qos = True @@ -48,6 +52,10 @@ class SolidFireVolumeTestCase(test.TestCase): self.stubs.Set(SolidFireDriver, '_issue_api_request', self.fake_issue_api_request) + self.expected_qos_results = {'minIOPS': 1000, + 'maxIOPS': 10000, + 'burstIOPS': 20000} + def fake_issue_api_request(obj, method, params, version='1.0'): if method is 'GetClusterCapacity' and version == '1.0': LOG.info('Called Fake GetClusterCapacity...') @@ -429,3 +437,46 @@ class SolidFireVolumeTestCase(test.TestCase): self.assertRaises(exception.SolidFireAccountNotFound, sfv.extend_volume, testvol, 2) + + def test_set_by_qos_spec_with_scoping(self): + sfv = SolidFireDriver(configuration=self.configuration) + qos_ref = qos_specs.create(self.ctxt, + 'qos-specs-1', {'qos:minIOPS': '1000', + 'qos:maxIOPS': '10000', + 'qos:burstIOPS': '20000'}) + type_ref = volume_types.create(self.ctxt, + "type1", {"qos:minIOPS": "100", + "qos:burstIOPS": "300", + "qos:maxIOPS": "200"}) + 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']) + self.assertEqual(qos, self.expected_qos_results) + + def test_set_by_qos_spec(self): + sfv = SolidFireDriver(configuration=self.configuration) + qos_ref = qos_specs.create(self.ctxt, + 'qos-specs-1', {'minIOPS': '1000', + 'maxIOPS': '10000', + 'burstIOPS': '20000'}) + type_ref = volume_types.create(self.ctxt, + "type1", {"qos:minIOPS": "100", + "qos:burstIOPS": "300", + "qos:maxIOPS": "200"}) + 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']) + self.assertEqual(qos, self.expected_qos_results) + + def test_set_by_qos_by_type_only(self): + sfv = SolidFireDriver(configuration=self.configuration) + type_ref = volume_types.create(self.ctxt, + "type1", {"qos:minIOPS": "100", + "qos:burstIOPS": "300", + "qos:maxIOPS": "200"}) + qos = sfv._set_qos_by_volume_type(self.ctxt, type_ref['id']) + self.assertEqual(qos, {'minIOPS': 100, + 'maxIOPS': 200, + 'burstIOPS': 300}) diff --git a/cinder/volume/drivers/solidfire.py b/cinder/volume/drivers/solidfire.py index d86204862..71fb48be2 100644 --- a/cinder/volume/drivers/solidfire.py +++ b/cinder/volume/drivers/solidfire.py @@ -32,6 +32,7 @@ from cinder import exception from cinder.openstack.common import log as logging from cinder.openstack.common import timeutils from cinder.volume.drivers.san.san import SanISCSIDriver +from cinder.volume import qos_specs from cinder.volume import volume_types LOG = logging.getLogger(__name__) @@ -432,8 +433,18 @@ class SolidFireDriver(SanISCSIDriver): def _set_qos_by_volume_type(self, ctxt, type_id): qos = {} volume_type = volume_types.get_volume_type(ctxt, type_id) + qos_specs_id = volume_type.get('qos_specs_id') specs = volume_type.get('extra_specs') - for key, value in specs.iteritems(): + + # NOTE(jdg): We prefer the qos_specs association + # and over-ride any existing + # extra-specs settings if present + if qos_specs_id is not None: + kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs'] + else: + kvs = specs + + for key, value in kvs.iteritems(): if ':' in key: fields = key.split(':') key = fields[1] -- 2.45.2