Workaround glanceclient bug when CONF.glance.api_servers not set
In certain configurations, like when setting [service_user] config, and not setting [glance]/api_servers, the KSA adapter get endpoint code (new in Queens) will return a versioned URL which glanceclient doesn't handle (due to bug 1707995) so we need to workaround that by parsing the URL to strip the version from the endpoint URL we got from KSA. This is validated in the nova-next CI job which configures a service user token for glance. Change-Id: I363182e916480c734cc37f279e8e89c8f3ec653c Closes-Bug: #1747511 Related-Bug: #1707995
This commit is contained in:
parent
d8079c2e52
commit
62ef6cfcf0
nova
releasenotes/notes
@ -22,6 +22,7 @@ import inspect
|
||||
import itertools
|
||||
import os
|
||||
import random
|
||||
import re
|
||||
import stat
|
||||
import sys
|
||||
import time
|
||||
@ -122,7 +123,14 @@ def get_api_servers(context):
|
||||
nova.conf.glance.DEFAULT_SERVICE_TYPE,
|
||||
ksa_auth=auth, ksa_session=sess,
|
||||
min_version='2.0', max_version='2.latest')
|
||||
api_servers = [utils.get_endpoint(ksa_adap)]
|
||||
endpoint = utils.get_endpoint(ksa_adap)
|
||||
if endpoint:
|
||||
# NOTE(mriedem): Due to python-glanceclient bug 1707995 we have
|
||||
# to massage the endpoint URL otherwise it won't work properly.
|
||||
# We can't use glanceclient.common.utils.strip_version because
|
||||
# of bug 1748009.
|
||||
endpoint = re.sub(r'/v\d+(\.\d+)?/?$', '/', endpoint)
|
||||
api_servers = [endpoint]
|
||||
|
||||
return itertools.cycle(api_servers)
|
||||
|
||||
|
@ -3960,6 +3960,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
|
||||
mock_setup_networks, mock_setup_intance_network, mock_get_bdms,
|
||||
mock_mutate_migration, mock_appy_migration, mock_drop_migration,
|
||||
mock_context_elevated):
|
||||
self.flags(api_servers=['http://localhost/image/v2'], group='glance')
|
||||
instance = fake_instance.fake_instance_obj(self.context)
|
||||
instance.info_cache = None
|
||||
elevated_context = mock.Mock()
|
||||
|
@ -19,6 +19,7 @@ import datetime
|
||||
|
||||
import cryptography
|
||||
from cursive import exception as cursive_exception
|
||||
import ddt
|
||||
import glanceclient.exc
|
||||
from glanceclient.v1 import images
|
||||
import glanceclient.v2.schemas as schemas
|
||||
@ -1601,6 +1602,7 @@ class TestDelete(test.NoDBTestCase):
|
||||
mock.sentinel.image_id)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestGlanceApiServers(test.NoDBTestCase):
|
||||
|
||||
def test_get_api_servers_multiple(self):
|
||||
@ -1615,18 +1617,36 @@ class TestGlanceApiServers(test.NoDBTestCase):
|
||||
self.assertEqual(expected_servers,
|
||||
{next(api_servers) for _ in expected_servers})
|
||||
|
||||
@mock.patch('keystoneauth1.adapter.Adapter.get_endpoint_data')
|
||||
def test_get_api_servers_get_ksa_adapter(self, mock_epd):
|
||||
@ddt.data(['http://158.69.92.100/image/v2/',
|
||||
'http://158.69.92.100/image/'],
|
||||
['http://158.69.92.100/image/v2',
|
||||
'http://158.69.92.100/image/'],
|
||||
['http://158.69.92.100/image/v2.0/',
|
||||
'http://158.69.92.100/image/'],
|
||||
['http://158.69.92.100/image/',
|
||||
'http://158.69.92.100/image/'],
|
||||
['http://158.69.92.100/image',
|
||||
'http://158.69.92.100/image'],
|
||||
['http://158.69.92.100/v2',
|
||||
'http://158.69.92.100/'],
|
||||
['http://thing.novav2.0oh.v2.foo/image/v2/',
|
||||
'http://thing.novav2.0oh.v2.foo/image/'])
|
||||
@ddt.unpack
|
||||
def test_get_api_servers_get_ksa_adapter(self, catalog_url, stripped):
|
||||
"""Test get_api_servers via nova.utils.get_ksa_adapter()."""
|
||||
self.flags(api_servers=None, group='glance')
|
||||
api_servers = glance.get_api_servers(mock.Mock())
|
||||
self.assertEqual(mock_epd.return_value.catalog_url, next(api_servers))
|
||||
# Still get itertools.cycle behavior
|
||||
self.assertEqual(mock_epd.return_value.catalog_url, next(api_servers))
|
||||
mock_epd.assert_called_once_with()
|
||||
with mock.patch('keystoneauth1.adapter.Adapter.'
|
||||
'get_endpoint_data') as mock_epd:
|
||||
mock_epd.return_value.catalog_url = catalog_url
|
||||
api_servers = glance.get_api_servers(mock.Mock())
|
||||
self.assertEqual(stripped, next(api_servers))
|
||||
# Still get itertools.cycle behavior
|
||||
self.assertEqual(stripped, next(api_servers))
|
||||
mock_epd.assert_called_once_with()
|
||||
|
||||
# Now test with endpoint_override - get_endpoint_data is not called.
|
||||
mock_epd.reset_mock()
|
||||
@mock.patch('keystoneauth1.adapter.Adapter.get_endpoint_data')
|
||||
def test_get_api_servers_get_ksa_adapter_endpoint_override(self,
|
||||
mock_epd):
|
||||
self.flags(endpoint_override='foo', group='glance')
|
||||
api_servers = glance.get_api_servers(mock.Mock())
|
||||
self.assertEqual('foo', next(api_servers))
|
||||
|
@ -0,0 +1,11 @@
|
||||
---
|
||||
issues:
|
||||
- |
|
||||
Due to a bug in python-glanceclient:
|
||||
|
||||
https://bugs.launchpad.net/python-glanceclient/+bug/1707995
|
||||
|
||||
If ``[glance]/api_servers`` is not set in nova.conf, and there is a
|
||||
versioned endpoint URL in the service catalog, nova makes a best attempt
|
||||
at parsing and stripping the version from the URL in order to make
|
||||
API requests to the image service.
|
Loading…
x
Reference in New Issue
Block a user