]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Implement retype in SolidFire driver
authorJohn Griffith <john.griffith@solidfire.com>
Thu, 6 Feb 2014 06:33:58 +0000 (23:33 -0700)
committerjohn-griffith <john.griffith@solidfire.com>
Fri, 7 Feb 2014 04:09:03 +0000 (21:09 -0700)
This just adds the ability to modify the
type of an existing SolidFire volume to
another type suppported on the same backend.

Main use case for this is changing QoS settings
for a volume on-demand.

Also updates the internal attributes to store the
deltas between the old-type and new-type.

Change-Id: I65a4c34cbec17d0f3987c1d964e6ad1bafea3601
Implements: blueprint retype-support-for-solidfire-driver

cinder/tests/test_solidfire.py
cinder/volume/drivers/solidfire.py

index 1a46bc5f58b0969fa78068782708b55c8a8cf115..1505538edf6303ec9364f87ef379d6d61442401e 100644 (file)
@@ -124,7 +124,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                              'enable512e': True,
                              'access': "readWrite",
                              'status': "active",
-                             'attributes': None,
+                             'attributes': {},
                              'qos': None,
                              'iqn': test_name}]}}
             return result
@@ -221,7 +221,7 @@ class SolidFireVolumeTestCase(test.TestCase):
                     'created_at': timeutils.utcnow()}
 
         sfv = SolidFireDriver(configuration=self.configuration)
-        model_update = sfv.create_volume(testvol)
+        sfv.create_volume(testvol)
         sfv.create_snapshot(testsnap)
 
     def test_create_clone(self):
@@ -479,3 +479,75 @@ class SolidFireVolumeTestCase(test.TestCase):
         self.assertEqual(qos, {'minIOPS': 100,
                                'maxIOPS': 200,
                                'burstIOPS': 300})
+
+    def test_retype(self):
+        sfv = SolidFireDriver(configuration=self.configuration)
+        self.stubs.Set(SolidFireDriver, '_issue_api_request',
+                       self.fake_issue_api_request)
+        type_ref = volume_types.create(self.ctxt,
+                                       "type1", {"qos:minIOPS": "500",
+                                                 "qos:burstIOPS": "2000",
+                                                 "qos:maxIOPS": "1000"})
+        diff = {'encryption': {}, 'qos_specs': {},
+                'extra_specs': {'qos:burstIOPS': ('10000', u'2000'),
+                                'qos:minIOPS': ('1000', u'500'),
+                                'qos:maxIOPS': ('10000', u'1000')}}
+        host = None
+        testvol = {'project_id': 'testprjid',
+                   'name': 'test_volume',
+                   'size': 1,
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
+        sfv = SolidFireDriver(configuration=self.configuration)
+        self.assertTrue(sfv.retype(self.ctxt,
+                                   testvol,
+                                   type_ref, diff, host))
+
+    def test_retype_with_qos_spec(self):
+        test_type = {'name': 'sf-1',
+                     'qos_specs_id': 'fb0576d7-b4b5-4cad-85dc-ca92e6a497d1',
+                     'deleted': False,
+                     'created_at': '2014-02-06 04:58:11',
+                     'updated_at': None,
+                     'extra_specs': {},
+                     'deleted_at': None,
+                     'id': 'e730e97b-bc7d-4af3-934a-32e59b218e81'}
+
+        test_qos_spec = {'id': 'asdfafdasdf',
+                         'specs': {'minIOPS': '1000',
+                                   'maxIOPS': '2000',
+                                   'burstIOPS': '3000'}}
+
+        qos_specs
+
+        def _fake_get_volume_type(ctxt, type_id):
+            return test_type
+
+        def _fake_get_qos_spec(ctxt, spec_id):
+            return test_qos_spec
+
+        self.stubs.Set(SolidFireDriver, '_issue_api_request',
+                       self.fake_issue_api_request)
+        self.stubs.Set(volume_types, 'get_volume_type',
+                       _fake_get_volume_type)
+        self.stubs.Set(qos_specs, 'get_qos_specs',
+                       _fake_get_qos_spec)
+
+        sfv = SolidFireDriver(configuration=self.configuration)
+
+        diff = {'encryption': {}, 'extra_specs': {},
+                'qos_specs': {'burstIOPS': ('10000', '2000'),
+                              'minIOPS': ('1000', '500'),
+                              'maxIOPS': ('10000', '1000')}}
+        host = None
+        testvol = {'project_id': 'testprjid',
+                   'name': 'test_volume',
+                   'size': 1,
+                   'id': 'a720b3c0-d1f0-11e1-9b23-0800200c9a66',
+                   'created_at': timeutils.utcnow()}
+
+        sfv = SolidFireDriver(configuration=self.configuration)
+        self.assertTrue(sfv.retype(self.ctxt,
+                                   testvol,
+                                   test_type, diff, host))
index ed79444d2a10b467f1cab1b784cbf0a0a1f424d1..a50877eec292ea69002e925555466c2e21d87a74 100644 (file)
@@ -769,3 +769,41 @@ class SolidFireDriver(SanISCSIDriver):
             raise exception.SolidFireAPIDataException(data=data)
 
         LOG.debug(_("Leaving SolidFire transfer volume"))
+
+    def retype(self, ctxt, volume, new_type, diff, host):
+        """Convert the volume to be of the new type.
+
+        Returns a boolean indicating whether the retype occurred.
+
+        :param ctxt: Context
+        :param volume: A dictionary describing the volume to migrate
+        :param new_type: A dictionary describing the volume type to convert to
+        :param diff: A dictionary with the difference between the two types
+        :param host: A dictionary describing the host to migrate to, where
+                     host['host'] is its name, and host['capabilities'] is a
+                     dictionary of its reported capabilities (Not Used).
+
+        """
+        qos = {}
+        attributes = {}
+
+        sfaccount = self._get_sfaccount(volume['project_id'])
+        params = {'accountID': sfaccount['accountID']}
+        sf_vol = self._get_sf_volume(volume['id'], params)
+
+        if sf_vol is None:
+            raise exception.VolumeNotFound(volume_id=volume['id'])
+
+        attributes = sf_vol['attributes']
+        attributes['retyped_at'] = timeutils.strtime()
+        params = {'volumeID': sf_vol['volumeID']}
+        qos = self._set_qos_by_volume_type(ctxt, new_type['id'])
+
+        if qos:
+            params['qos'] = qos
+            for k, v in qos.items():
+                attributes[k] = str(v)
+            params['attributes'] = attributes
+
+        self._issue_api_request('ModifyVolume', params)
+        return True