Merge "Add custom SSL CA Cert support for api.cinder.get_microversion" into stable/train

This commit is contained in:
Zuul 2020-10-15 12:06:49 +00:00 committed by Gerrit Code Review
commit dd8943b536
4 changed files with 173 additions and 1 deletions

View File

@ -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)

View File

@ -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",

View File

@ -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):

View File

@ -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.