diff --git a/nova/tests/unit/volume/test_cinder.py b/nova/tests/unit/volume/test_cinder.py index fbc1fde60721..43646e658ff6 100644 --- a/nova/tests/unit/volume/test_cinder.py +++ b/nova/tests/unit/volume/test_cinder.py @@ -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') diff --git a/nova/volume/cinder.py b/nova/volume/cinder.py index d2de9efbd529..8c9a6f0ebbd6 100644 --- a/nova/volume/cinder.py +++ b/nova/volume/cinder.py @@ -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