From a95a462bdacf4fd418a776f0a72e01fb1b514061 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Cuong Date: Thu, 18 May 2017 11:23:03 +0700 Subject: [PATCH] Support cinder API version 3 Cinder v2 is deprecated and will be removed in the future Related-Bug: #1680157 Change-Id: I5395a93e9f4312fb9468b16aaabd54a4964b0078 --- sahara/tests/unit/service/test_volumes.py | 20 +++++++++++++ sahara/tests/unit/utils/test_cinder.py | 27 +++++++++++++---- sahara/utils/openstack/cinder.py | 36 ++++++++++++++++------- 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/sahara/tests/unit/service/test_volumes.py b/sahara/tests/unit/service/test_volumes.py index 848af611..f5c6e852 100644 --- a/sahara/tests/unit/service/test_volumes.py +++ b/sahara/tests/unit/service/test_volumes.py @@ -15,6 +15,7 @@ from cinderclient.v1 import volumes as vol_v1 from cinderclient.v2 import volumes as vol_v2 +from cinderclient.v3 import volumes as vol_v3 import mock from sahara import exceptions as ex @@ -77,6 +78,25 @@ class TestAttachVolume(base.SaharaWithDbTestCase): self.assertIsNone( volumes.detach_from_instance(instance)) + @mock.patch('sahara.conductor.manager.ConductorManager.cluster_get') + @mock.patch('cinderclient.v3.volumes.Volume.delete') + @mock.patch('cinderclient.v3.volumes.Volume.detach') + @mock.patch('sahara.utils.openstack.cinder.get_volume') + def test_detach_volumes_v3(self, p_get_volume, p_detach, p_delete, p_cond): + class Instance(object): + def __init__(self): + self.instance_id = '123454321' + self.volumes = [123] + self.instance_name = 'spam' + + instance = Instance() + p_get_volume.return_value = vol_v3.Volume(None, {'id': '123', 'status': + 'available'}) + p_detach.return_value = None + p_delete.return_value = None + self.assertIsNone( + volumes.detach_from_instance(instance)) + def _get_instance(self): inst_remote = mock.MagicMock() inst_remote.execute_command.return_value = 0 diff --git a/sahara/tests/unit/utils/test_cinder.py b/sahara/tests/unit/utils/test_cinder.py index 2d66addb..5bed8c4c 100644 --- a/sahara/tests/unit/utils/test_cinder.py +++ b/sahara/tests/unit/utils/test_cinder.py @@ -32,31 +32,48 @@ class TestCinder(test_base.SaharaTestCase): **kwargs): self.override_config('os_region_name', 'RegionOne') - # Fake service_catalog with both volume and volumev2 services available + # Fake service_catalog with both volumev2 + # and volumev3 services available service_catalog = '''[ { "type": "volumev2", "endpoints": [ { "region": "RegionOne", - "internalURL": "http://localhost/" } ] } ]''' + "internalURL": "http://localhost/" } ] }, + { "type": "volumev3", + "endpoints": [ { "region": "RegionOne", + "internalURL": "http://localhost/" } ] }]''' super(TestCinder, self).setup_context( username=username, tenant_id=tenant_id, token=token, tenant_name=tenant_name, service_catalog=service_catalog, **kwargs) @mock.patch('sahara.utils.openstack.keystone.auth') + @mock.patch('cinderclient.v3.client.Client') @mock.patch('cinderclient.v2.client.Client') - def test_get_cinder_client_api_v2(self, patched, auth): + def test_get_cinder_client_api_v2(self, patched2, patched3, auth): self.override_config('api_version', 2, group='cinder') - patched.return_value = FakeCinderClient(2) + patched2.return_value = FakeCinderClient(2) + patched3.return_value = FakeCinderClient(3) client = cinder.client() self.assertEqual(2, client.client.api_version) + @mock.patch('sahara.utils.openstack.keystone.auth') + @mock.patch('cinderclient.v3.client.Client') + @mock.patch('cinderclient.v2.client.Client') + def test_get_cinder_client_api_v3(self, patched2, patched3, auth): + self.override_config('api_version', 3, group='cinder') + patched2.return_value = FakeCinderClient(2) + patched3.return_value = FakeCinderClient(3) + + client = cinder.client() + self.assertEqual(3, client.client.api_version) + def test_cinder_bad_api_version(self): self.override_config('api_version', 1, group='cinder') cinder.validate_config() # Check bad version falls back to latest supported version - self.assertEqual(2, main.CONF.cinder.api_version) + self.assertEqual(3, main.CONF.cinder.api_version) @mock.patch('sahara.utils.openstack.base.url_for') def test_check_cinder_exists(self, mock_url_for): diff --git a/sahara/utils/openstack/cinder.py b/sahara/utils/openstack/cinder.py index c9fafd21..328484a2 100644 --- a/sahara/utils/openstack/cinder.py +++ b/sahara/utils/openstack/cinder.py @@ -16,6 +16,7 @@ # limitations under the License. from cinderclient.v2 import client as cinder_client_v2 +from cinderclient.v3 import client as cinder_client_v3 from keystoneauth1 import exceptions as keystone_exceptions from oslo_config import cfg from oslo_log import log as logging @@ -30,7 +31,7 @@ LOG = logging.getLogger(__name__) opts = [ - cfg.IntOpt('api_version', default=2, + cfg.IntOpt('api_version', default=3, help='Version of the Cinder API to use.', deprecated_name='cinder_api_version'), cfg.BoolOpt('api_insecure', @@ -53,27 +54,40 @@ CONF.register_opts(opts, group=cinder_group) def validate_config(): - if CONF.cinder.api_version != 2: - LOG.warning('Unsupported Cinder API version: {bad}. Please set a ' + if CONF.cinder.api_version == 2: + LOG.warning('The Cinder v2 API is deprecated. You should set ' + 'cinder.api_version=3 in your sahara.conf file.') + elif CONF.cinder.api_version != 3: + LOG.warning('Unsupported Cinder API version: {bad}. Please set a ' 'correct value for cinder.api_version in your ' 'sahara.conf file (currently supported versions are: ' - '{supported}). Falling back to Cinder API version 2.' + '{supported}). Falling back to Cinder API version 3.' .format(bad=CONF.cinder.api_version, - supported=[2])) - CONF.set_override('api_version', 2, group='cinder') + supported=[2, 3])) + CONF.set_override('api_version', 3, group='cinder') def client(): session = sessions.cache().get_session(sessions.SESSION_TYPE_CINDER) - cinder = cinder_client_v2.Client( - session=session, auth=keystone.auth(), - endpoint_type=CONF.cinder.endpoint_type, - region_name=CONF.os_region_name) + auth = keystone.auth() + if CONF.cinder.api_version == 2: + cinder = cinder_client_v2.Client( + session=session, auth=auth, + endpoint_type=CONF.cinder.endpoint_type, + region_name=CONF.os_region_name) + else: + cinder = cinder_client_v3.Client( + session=session, auth=auth, + endpoint_type=CONF.cinder.endpoint_type, + region_name=CONF.os_region_name) return cinder def check_cinder_exists(): - service_type = 'volumev2' + if CONF.cinder.api_version == 2: + service_type = 'volumev2' + else: + service_type = 'volumev3' try: base.url_for(context.current().service_catalog, service_type, endpoint_type=CONF.cinder.endpoint_type)