Add support for getting volume details with a specified microversion

This allows us to get volume details and pass through a microversion.
This will be used to get a volume with microversion 3.48 where
the shared_targets and service_uuid parameters are in the response.
We will then use that information to determine if we should lock
attach/detach operations on that volume.

Part of blueprint multi-attach-volume

Change-Id: Ief30adfef35eefe03e5a3d3d9623cd48e4d334a4
This commit is contained in:
Matt Riedemann 2017-12-21 12:22:42 -05:00 committed by Ildiko Vancsa
parent afd45295f4
commit de0386ad13
2 changed files with 50 additions and 5 deletions

View File

@ -117,7 +117,7 @@ class CinderApiTestCase(test.NoDBTestCase):
self.api.get(self.ctx, volume_id)
mock_cinderclient.assert_called_once_with(self.ctx)
mock_cinderclient.assert_called_once_with(self.ctx, microversion=None)
mock_volumes.get.assert_called_once_with(volume_id)
@mock.patch('nova.volume.cinder.cinderclient')
@ -144,6 +144,35 @@ class CinderApiTestCase(test.NoDBTestCase):
self.assertRaises(exception.CinderConnectionFailed,
self.api.get, self.ctx, 'id1')
@mock.patch('nova.volume.cinder.cinderclient')
def test_get_with_shared_targets(self, mock_cinderclient):
"""Tests getting a volume at microversion 3.48 which includes the
shared_targets and service_uuid parameters in the volume response body.
"""
mock_volume = mock.MagicMock(
shared_targets=False, service_uuid=uuids.service_uuid)
mock_volumes = mock.MagicMock()
mock_volumes.get.return_value = mock_volume
mock_cinderclient.return_value = mock.MagicMock(volumes=mock_volumes)
vol = self.api.get(self.ctx, uuids.volume_id, microversion='3.48')
mock_cinderclient.assert_called_once_with(
self.ctx, microversion='3.48')
mock_volumes.get.assert_called_once_with(uuids.volume_id)
self.assertIn('shared_targets', vol)
self.assertFalse(vol['shared_targets'])
self.assertEqual(uuids.service_uuid, vol['service_uuid'])
@mock.patch('nova.volume.cinder.cinderclient',
side_effect=exception.CinderAPIVersionNotAvailable(
version='3.48'))
def test_get_microversion_not_supported(self, mock_cinderclient):
"""Tests getting a volume at microversion 3.48 but that version
is not available.
"""
self.assertRaises(exception.CinderAPIVersionNotAvailable,
self.api.get, self.ctx, uuids.volume_id,
microversion='3.48')
@mock.patch('nova.volume.cinder.cinderclient')
def test_create(self, mock_cinderclient):
volume = FakeVolume('id1')
@ -569,7 +598,7 @@ class CinderApiTestCase(test.NoDBTestCase):
self.api.detach(self.ctx, 'id1', instance_uuid='fake_uuid')
mock_cinderclient.assert_called_with(self.ctx)
mock_cinderclient.assert_called_with(self.ctx, microversion=None)
mock_volumes.detach.assert_called_once_with('id1', None)
@mock.patch('nova.volume.cinder.cinderclient')
@ -586,7 +615,7 @@ class CinderApiTestCase(test.NoDBTestCase):
self.api.detach(self.ctx, 'id1', instance_uuid='fake_uuid')
mock_cinderclient.assert_called_with(self.ctx)
mock_cinderclient.assert_called_with(self.ctx, microversion=None)
mock_volumes.detach.assert_called_once_with('id1', 'fakeid')
@mock.patch('nova.volume.cinder.cinderclient')

View File

@ -199,6 +199,13 @@ def _untranslate_volume_summary_view(context, vol):
if hasattr(vol, 'volume_image_metadata'):
d['volume_image_metadata'] = copy.deepcopy(vol.volume_image_metadata)
# The 3.48 microversion exposes a shared_targets boolean and service_uuid
# string parameter which can be used with locks during volume attach
# and detach.
if hasattr(vol, 'shared_targets'):
d['shared_targets'] = vol.shared_targets
d['service_uuid'] = vol.service_uuid
return d
@ -332,8 +339,17 @@ class API(object):
"""API for interacting with the volume manager."""
@translate_volume_exception
def get(self, context, volume_id):
item = cinderclient(context).volumes.get(volume_id)
def get(self, context, volume_id, microversion=None):
"""Get the details about a volume given it's ID.
:param context: the nova request context
:param volume_id: the id of the volume to get
:param microversion: optional string microversion value
:raises: CinderAPIVersionNotAvailable if the specified microversion is
not available.
"""
item = cinderclient(
context, microversion=microversion).volumes.get(volume_id)
return _untranslate_volume_summary_view(context, item)
@translate_cinder_exception