]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Update extend_volume API to use versionedobjects
authorThang Pham <thang.g.pham@gmail.com>
Tue, 29 Sep 2015 02:08:03 +0000 (19:08 -0700)
committerThang Pham <thang.g.pham@gmail.com>
Thu, 12 Nov 2015 12:56:23 +0000 (04:56 -0800)
The following patch updates extend_volume API to use
volume versionedobjects.  Changes were made to be
backwards compatible with older RPC clients.  It only
includes changes to the core cinder code.  Changes in
the drivers are left to each driver maintainer to
update.

Note that this patch DOES NOT try to use object dot
notation everywhere, since it would increase the
size of the patch.  Instead, it will be done in
subsequent patches.

Change-Id: I4192b35f8f3e2cd51b94db10b44727f23592ea86
Partial-Implements: blueprint cinder-objects

cinder/tests/unit/test_volume_rpcapi.py
cinder/volume/api.py
cinder/volume/manager.py
cinder/volume/rpcapi.py

index f5479aecd16b1ec403b682d9f52ec4db671a3c89..ccb2f0265a64da95c018f7383dbb355b6018a7a0 100644 (file)
@@ -370,13 +370,27 @@ class VolumeRpcAPITestCase(test.TestCase):
                                           '-8ffd-0800200c9a66',
                               version='1.9')
 
-    def test_extend_volume(self):
+    @mock.patch('oslo_messaging.RPCClient.can_send_version',
+                return_value=True)
+    def test_extend_volume(self, can_send_version):
         self._test_volume_api('extend_volume',
                               rpc_method='cast',
-                              volume=self.fake_volume,
+                              volume=self.fake_volume_obj,
+                              new_size=1,
+                              reservations=self.fake_reservations,
+                              version='1.35')
+        can_send_version.assert_called_once_with('1.35')
+
+    @mock.patch('oslo_messaging.RPCClient.can_send_version',
+                return_value=False)
+    def test_extend_volume_old(self, can_send_version):
+        self._test_volume_api('extend_volume',
+                              rpc_method='cast',
+                              volume=self.fake_volume_obj,
                               new_size=1,
                               reservations=self.fake_reservations,
                               version='1.14')
+        can_send_version.assert_called_once_with('1.35')
 
     def test_migrate_volume(self):
         class FakeHost(object):
index 634b449b1e2e2410edca49c64f313c2cfd5442b6..57a87f7025528277a0fe91b31e07b426a53a70ce 100644 (file)
@@ -1259,27 +1259,27 @@ class API(base.Base):
 
     @wrap_check_policy
     def extend(self, context, volume, new_size):
-        if volume['status'] != 'available':
+        if volume.status != 'available':
             msg = _('Volume %(vol_id)s status must be available '
                     'to extend, but current status is: '
-                    '%(vol_status)s.') % {'vol_id': volume['id'],
-                                          'vol_status': volume['status']}
+                    '%(vol_status)s.') % {'vol_id': volume.id,
+                                          'vol_status': volume.status}
             raise exception.InvalidVolume(reason=msg)
 
-        size_increase = (int(new_size)) - volume['size']
+        size_increase = (int(new_size)) - volume.size
         if size_increase <= 0:
             msg = (_("New size for extend must be greater "
                      "than current size. (current: %(size)s, "
                      "extended: %(new_size)s).") % {'new_size': new_size,
-                                                    'size': volume['size']})
+                                                    'size': volume.size})
             raise exception.InvalidInput(reason=msg)
 
         try:
             reserve_opts = {'gigabytes': size_increase}
             QUOTAS.add_volume_type_opts(context, reserve_opts,
-                                        volume.get('volume_type_id'))
+                                        volume.volume_type_id)
             reservations = QUOTAS.reserve(context,
-                                          project_id=volume['project_id'],
+                                          project_id=volume.project_id,
                                           **reserve_opts)
         except exception.OverQuota as exc:
             usages = exc.kwargs['usages']
index c633d714017a9d9b9c40ad3c2e1579c1d6a0f0af..2bd858c692f46ea2c0f309729310ee95163f04c6 100644 (file)
@@ -190,7 +190,7 @@ def locked_snapshot_operation(f):
 class VolumeManager(manager.SchedulerDependentManager):
     """Manages attachable block storage devices."""
 
-    RPC_API_VERSION = '1.34'
+    RPC_API_VERSION = '1.35'
 
     target = messaging.Target(version=RPC_API_VERSION)
 
@@ -1984,7 +1984,14 @@ class VolumeManager(manager.SchedulerDependentManager):
                     context, snapshot, event_suffix,
                     extra_usage_info=extra_usage_info, host=self.host)
 
-    def extend_volume(self, context, volume_id, new_size, reservations):
+    def extend_volume(self, context, volume_id, new_size, reservations,
+                      volume=None):
+        # FIXME(thangp): Remove this in v2.0 of RPC API.
+        if volume is None:
+            # For older clients, mimic the old behavior and look up the volume
+            # by its volume_id.
+            volume = objects.Volume.get_by_id(context, volume_id)
+
         try:
             # NOTE(flaper87): Verify the driver is enabled
             # before going forward. The exception will be caught
@@ -1992,12 +1999,11 @@ class VolumeManager(manager.SchedulerDependentManager):
             utils.require_driver_initialized(self.driver)
         except exception.DriverNotInitialized:
             with excutils.save_and_reraise_exception():
-                self.db.volume_update(context, volume_id,
-                                      {'status': 'error_extending'})
+                volume.status = 'error_extending'
+                volume.save()
 
-        volume = self.db.volume_get(context, volume_id)
-        project_id = volume['project_id']
-        size_increase = (int(new_size)) - volume['size']
+        project_id = volume.project_id
+        size_increase = (int(new_size)) - volume.size
         self._notify_about_volume_usage(context, volume, "resize.start")
         try:
             self.driver.extend_volume(volume, new_size)
@@ -2005,26 +2011,24 @@ class VolumeManager(manager.SchedulerDependentManager):
             LOG.exception(_LE("Extend volume failed."),
                           resource=volume)
             try:
-                self.db.volume_update(context, volume['id'],
+                self.db.volume_update(context, volume.id,
                                       {'status': 'error_extending'})
                 raise exception.CinderException(_("Volume %s: Error trying "
                                                   "to extend volume") %
-                                                volume_id)
+                                                volume.id)
             finally:
                 QUOTAS.rollback(context, reservations, project_id=project_id)
                 return
 
         QUOTAS.commit(context, reservations, project_id=project_id)
-        volume = self.db.volume_update(context,
-                                       volume['id'],
-                                       {'size': int(new_size),
-                                        'status': 'available'})
-        pool = vol_utils.extract_host(volume['host'], 'pool')
+        volume.update({'size': int(new_size), 'status': 'available'})
+        volume.save()
+        pool = vol_utils.extract_host(volume.host, 'pool')
         if pool is None:
             # Legacy volume, put them into default pool
             pool = self.driver.configuration.safe_get(
                 'volume_backend_name') or vol_utils.extract_host(
-                    volume['host'], 'pool', True)
+                    volume.host, 'pool', True)
 
         try:
             self.stats['pools'][pool]['allocated_capacity_gb'] += size_increase
index d3e4d71d43c5ec65878edb998e937d41b083b114..c81e78341be1ed8a8f2dbeb69ae230f57741650d 100644 (file)
@@ -82,6 +82,7 @@ class VolumeAPI(object):
         1.32 - Adds support for sending objects over RPC in create_volume().
         1.33 - Adds support for sending objects over RPC in delete_volume().
         1.34 - Adds support for sending objects over RPC in retype().
+        1.35 - Adds support for sending objects over RPC in extend_volume().
     """
 
     BASE_RPC_API_VERSION = '1.0'
@@ -231,10 +232,18 @@ class VolumeAPI(object):
                           new_user=new_user, new_project=new_project)
 
     def extend_volume(self, ctxt, volume, new_size, reservations):
-        new_host = utils.extract_host(volume['host'])
-        cctxt = self.client.prepare(server=new_host, version='1.14')
-        cctxt.cast(ctxt, 'extend_volume', volume_id=volume['id'],
-                   new_size=new_size, reservations=reservations)
+        new_host = utils.extract_host(volume.host)
+
+        msg_args = {'volume_id': volume.id, 'new_size': new_size,
+                    'reservations': reservations}
+        if self.client.can_send_version('1.35'):
+            version = '1.35'
+            msg_args['volume'] = volume
+        else:
+            version = '1.14'
+
+        cctxt = self.client.prepare(server=new_host, version=version)
+        cctxt.cast(ctxt, 'extend_volume', **msg_args)
 
     def migrate_volume(self, ctxt, volume, dest_host, force_host_copy):
         new_host = utils.extract_host(volume['host'])