summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZuul <zuul@review.opendev.org>2020-10-15 12:06:49 +0000
committerGerrit Code Review <review@openstack.org>2020-10-15 12:06:49 +0000
commitdd8943b5365ebd455ec346c93fe0cb58cf903bad (patch)
treee88b5f7a7acfaa01eaf03d93ecfcf39f19533652
parent2bdf22e7cb59e5cc1889b9b88fb378f9d085d594 (diff)
parent68d4c5e78db61ea401ee89c84a69676e26a636a1 (diff)
downloadhorizon-dd8943b5365ebd455ec346c93fe0cb58cf903bad.tar.gz
Merge "Add custom SSL CA Cert support for api.cinder.get_microversion" into stable/train
-rw-r--r--openstack_dashboard/api/cinder.py52
-rw-r--r--openstack_dashboard/test/test_data/cinder_data.py36
-rw-r--r--openstack_dashboard/test/unit/api/test_cinder.py79
-rw-r--r--releasenotes/notes/cinder-ssl-deployment-e4dcd6fc0027c96a.yaml7
4 files changed, 173 insertions, 1 deletions
diff --git a/openstack_dashboard/api/cinder.py b/openstack_dashboard/api/cinder.py
index 17a9f81c1..dde49a39e 100644
--- a/openstack_dashboard/api/cinder.py
+++ b/openstack_dashboard/api/cinder.py
@@ -30,6 +30,7 @@ from cinderclient import api_versions
from cinderclient import client as cinder_client
from cinderclient import exceptions as cinder_exception
from cinderclient.v2.contrib import list_extensions as cinder_list_extensions
+from six.moves import urllib
from horizon import exceptions
from horizon.utils.memoized import memoized
@@ -253,11 +254,60 @@ def get_microversion(request, features):
version, cinder_url = _find_cinder_url(request)
except exceptions.ServiceCatalogException:
return None
- min_ver, max_ver = cinder_client.get_server_version(cinder_url)
+ min_ver, max_ver = _get_server_version(request, cinder_url)
return microversions.get_microversion_for_features(
'cinder', features, api_versions.APIVersion, min_ver, max_ver)
+# NOTE(amotoki): Borrowed from cinderclient.client.get_server_version()
+# to support custom SSL CA Cert support with cinderclient<5.
+def _get_server_version(request, url):
+ min_version = "2.0"
+ current_version = "2.0"
+ try:
+ u = urllib.parse.urlparse(url)
+ version_url = None
+
+ # NOTE(andreykurilin): endpoint URL has at least 2 formats:
+ # 1. The classic (legacy) endpoint:
+ # http://{host}:{optional_port}/v{2 or 3}/{project-id}
+ # http://{host}:{optional_port}/v{2 or 3}
+ # 3. Under wsgi:
+ # http://{host}:{optional_port}/volume/v{2 or 3}
+ for ver in ['v2', 'v3']:
+ if u.path.endswith(ver) or "/{0}/".format(ver) in u.path:
+ path = u.path[:u.path.rfind(ver)]
+ version_url = '%s://%s%s' % (u.scheme, u.netloc, path)
+ break
+
+ if not version_url:
+ # NOTE(andreykurilin): probably, it is one of the next cases:
+ # * https://volume.example.com/
+ # * https://example.com/volume
+ # leave as is without cropping.
+ version_url = url
+
+ c = cinderclient(request)
+ resp, data = c.client.request(version_url, 'GET')
+
+ versions = data['versions']
+ for version in versions:
+ if '3.' in version['version']:
+ min_version = version['min_version']
+ current_version = version['version']
+ break
+ else:
+ # Set the values, but don't break out the loop here in case v3
+ # comes later
+ min_version = '2.0'
+ current_version = '2.0'
+ except cinder_exception.ClientException as e:
+ LOG.warning("Error in server version query:%s\n"
+ "Returning APIVersion 2.0", e)
+ return (api_versions.APIVersion(min_version),
+ api_versions.APIVersion(current_version))
+
+
def _cinderclient_with_features(request, features,
raise_exc=False, message=False):
version = get_microversion(request, features)
diff --git a/openstack_dashboard/test/test_data/cinder_data.py b/openstack_dashboard/test/test_data/cinder_data.py
index e71e1f755..bcadfbcad 100644
--- a/openstack_dashboard/test/test_data/cinder_data.py
+++ b/openstack_dashboard/test/test_data/cinder_data.py
@@ -36,6 +36,7 @@ from openstack_dashboard.usage import quotas as usage_quotas
def data(TEST):
+ TEST.cinder_versions = utils.TestDataContainer()
TEST.cinder_services = utils.TestDataContainer()
TEST.cinder_volumes = utils.TestDataContainer()
TEST.cinder_volume_backups = utils.TestDataContainer()
@@ -59,6 +60,41 @@ def data(TEST):
TEST.cinder_group_volumes = utils.TestDataContainer()
TEST.cinder_volume_snapshots_with_groups = utils.TestDataContainer()
+ ver2 = {
+ 'id': 'v2.0',
+ 'links': [{'href': 'http://docs.openstack.org/',
+ 'rel': 'describedby',
+ 'type': 'text/html'},
+ {'href': 'http://192.168.50.25/volume/v2/',
+ 'rel': 'self'}],
+ 'media-types': [
+ {'base': 'application/json',
+ 'type': 'application/vnd.openstack.volume+json;version=2'}
+ ],
+ 'min_version': '',
+ 'status': 'DEPRECATED',
+ 'updated': '2014-06-28T12:20:21Z',
+ 'version': '',
+ }
+ ver3 = {
+ 'id': 'v3.0',
+ 'links': [{'href': 'http://docs.openstack.org/',
+ 'rel': 'describedby',
+ 'type': 'text/html'},
+ {'href': 'http://192.168.50.25/volume/v3/',
+ 'rel': 'self'}],
+ 'media-types': [
+ {'base': 'application/json',
+ 'type': 'application/vnd.openstack.volume+json;version=3'}
+ ],
+ 'min_version': '3.0',
+ 'status': 'CURRENT',
+ 'updated': '2016-02-08T12:20:21Z',
+ 'version': '3.16',
+ }
+ TEST.cinder_versions.add(ver2)
+ TEST.cinder_versions.add(ver3)
+
# Services
service_1 = services.Service(services.ServiceManager(None), {
"service": "cinder-scheduler",
diff --git a/openstack_dashboard/test/unit/api/test_cinder.py b/openstack_dashboard/test/unit/api/test_cinder.py
index c25fd5614..46bb5a0c0 100644
--- a/openstack_dashboard/test/unit/api/test_cinder.py
+++ b/openstack_dashboard/test/unit/api/test_cinder.py
@@ -16,6 +16,8 @@ from django.conf import settings
from django.test.utils import override_settings
import cinderclient as cinder_client
+from cinderclient import api_versions
+from cinderclient import exceptions as cinder_exception
import mock
from openstack_dashboard import api
@@ -446,6 +448,83 @@ class CinderApiTests(test.APIMockTestCase):
self.assertEqual(default_volume_type, volume_type)
cinderclient.volume_types.default.assert_called_once()
+ @mock.patch.object(api.cinder, 'cinderclient')
+ def _check_get_server_version_v3(self, volume_url, version_url, expected,
+ mock_cinderclient):
+ versions = {'versions': self.cinder_versions.list()}
+ cinder_client = mock_cinderclient.return_value
+ cinder_client.client.request.return_value = (200, versions)
+
+ versions = api.cinder._get_server_version(self.request, volume_url)
+
+ self.assertEqual(expected, versions)
+ cinder_client.client.request.assert_called_once_with(
+ version_url, 'GET')
+
+ def test_get_server_version_v3_dedicated_port_http(self):
+ volume_url = ('http://192.168.122.127:8776/v3/'
+ 'e5526285ebd741b1819393f772f11fc3')
+ version_url = 'http://192.168.122.127:8776/'
+ expected = (api_versions.APIVersion('3.0'),
+ api_versions.APIVersion('3.16'))
+ self._check_get_server_version_v3(volume_url, version_url, expected)
+
+ def test_get_server_version_v3_dedicated_port_https(self):
+ volume_url = ('https://192.168.122.127:8776/v3/'
+ 'e55285ebd741b1819393f772f11fc3')
+ version_url = 'https://192.168.122.127:8776/'
+ expected = (api_versions.APIVersion('3.0'),
+ api_versions.APIVersion('3.16'))
+ self._check_get_server_version_v3(volume_url, version_url, expected)
+
+ def test_get_server_version_v3_path(self):
+ volume_url = ('http://192.168.122.127/volumes/v3/'
+ 'e5526285ebd741b1819393f772f11fc3')
+ version_url = 'http://192.168.122.127/volumes/'
+ expected = (api_versions.APIVersion('3.0'),
+ api_versions.APIVersion('3.16'))
+ self._check_get_server_version_v3(volume_url, version_url, expected)
+
+ def test_get_server_version_v3_without_project_id(self):
+ volume_url = 'http://192.168.122.127/volumes/v3/'
+ version_url = 'http://192.168.122.127/volumes/'
+ expected = (api_versions.APIVersion('3.0'),
+ api_versions.APIVersion('3.16'))
+ self._check_get_server_version_v3(volume_url, version_url, expected)
+
+ @mock.patch.object(api.cinder, 'cinderclient')
+ def test_get_server_version_v2(self, mock_cinderclient):
+ versions = {'versions': [x for x in self.cinder_versions.list()
+ if x['id'] == 'v2.0']}
+ cinder_client = mock_cinderclient.return_value
+ cinder_client.client.request.return_value = (200, versions)
+
+ versions = api.cinder._get_server_version(
+ self.request,
+ 'http://192.168.122.127:8776/v2/e5526285ebd741b1819393f772f11fc3')
+
+ self.assertEqual((api_versions.APIVersion('2.0'),
+ api_versions.APIVersion('2.0')),
+ versions)
+ cinder_client.client.request.assert_called_once_with(
+ 'http://192.168.122.127:8776/', 'GET')
+
+ @mock.patch.object(api.cinder, 'cinderclient')
+ def test_get_server_version_exception(self, mock_cinderclient):
+ cinder_client = mock_cinderclient.return_value
+ cinder_client.client.request.side_effect = \
+ cinder_exception.ClientException(500)
+
+ versions = api.cinder._get_server_version(
+ self.request,
+ 'http://192.168.122.127:8776/v3/')
+
+ self.assertEqual((api_versions.APIVersion('2.0'),
+ api_versions.APIVersion('2.0')),
+ versions)
+ cinder_client.client.request.assert_called_once_with(
+ 'http://192.168.122.127:8776/', 'GET')
+
class CinderApiVersionTests(test.TestCase):
diff --git a/releasenotes/notes/cinder-ssl-deployment-e4dcd6fc0027c96a.yaml b/releasenotes/notes/cinder-ssl-deployment-e4dcd6fc0027c96a.yaml
new file mode 100644
index 000000000..d429dd333
--- /dev/null
+++ b/releasenotes/notes/cinder-ssl-deployment-e4dcd6fc0027c96a.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ [:bug:`1744670`]
+ Previously when a custom SSL CA is used horizon cannot retrieve volume
+ and snapshot information from cinder. It is fixed now and a custom CA
+ is handled properly in horizon when communicating with cinder.