Handle old status-less placement service
Older versions of placement didn't include the status field in their version discovery documents. This was fixed in placement in https://review.opendev.org/575117, but there are clouds out there in the wild running this version and SDK bombs out trying to talk to them. Change-Id: I152f0c626b358328cedd404c8fc8d0bee46d2991
This commit is contained in:
parent
f34d399f52
commit
6f80554807
@ -321,6 +321,10 @@ class CloudRegion(object):
|
||||
else:
|
||||
return 'unknown'
|
||||
|
||||
def set_service_value(self, key, service_type, value):
|
||||
key = _make_key(key, service_type)
|
||||
self.config[key] = value
|
||||
|
||||
def set_session_constructor(self, session_constructor):
|
||||
"""Sets the Session constructor."""
|
||||
self._session_constructor = session_constructor
|
||||
@ -645,7 +649,7 @@ class CloudRegion(object):
|
||||
self.get_interface(service_type), {})
|
||||
return interface_versions.get(service_type, [])
|
||||
|
||||
def _get_hardcoded_endpoint(self, service_type, constructor):
|
||||
def _get_endpoint_from_catalog(self, service_type, constructor):
|
||||
adapter = constructor(
|
||||
session=self.get_session(),
|
||||
service_type=self.get_service_type(service_type),
|
||||
@ -653,7 +657,11 @@ class CloudRegion(object):
|
||||
interface=self.get_interface(service_type),
|
||||
region_name=self.get_region_name(service_type),
|
||||
)
|
||||
endpoint = adapter.get_endpoint()
|
||||
return adapter.get_endpoint()
|
||||
|
||||
def _get_hardcoded_endpoint(self, service_type, constructor):
|
||||
endpoint = self._get_endpoint_from_catalog(
|
||||
service_type, constructor)
|
||||
if not endpoint.rstrip().rsplit('/')[-1] == 'v2.0':
|
||||
if not endpoint.endswith('/'):
|
||||
endpoint += '/'
|
||||
|
@ -89,13 +89,38 @@ class ServiceDescription(object):
|
||||
# The keystone proxy has a method called get_endpoint
|
||||
# that is about managing keystone endpoints. This is
|
||||
# unfortunate.
|
||||
endpoint = proxy_mod.Proxy.get_endpoint(proxy)
|
||||
try:
|
||||
endpoint = proxy_mod.Proxy.get_endpoint(proxy)
|
||||
except IndexError:
|
||||
# It's best not to look to closely here. This is
|
||||
# to support old placement.
|
||||
# There was a time when it had no status entry
|
||||
# in its version discovery doc (OY) In this case,
|
||||
# no endpoints get through version discovery
|
||||
# filtering. In order to deal with that, catch
|
||||
# the IndexError thrown by keystoneauth and
|
||||
# set an endpoint_override for the user to the
|
||||
# url in the catalog and try again.
|
||||
self._set_override_from_catalog(instance.config)
|
||||
proxy = self._make_proxy(instance)
|
||||
endpoint = proxy_mod.Proxy.get_endpoint(proxy)
|
||||
if instance._strict_proxies:
|
||||
self._validate_proxy(proxy, endpoint)
|
||||
proxy._connection = instance
|
||||
instance._proxies[self.service_type] = proxy
|
||||
return instance._proxies[self.service_type]
|
||||
|
||||
def _set_override_from_catalog(self, config):
|
||||
override = config._get_endpoint_from_catalog(
|
||||
self.service_type,
|
||||
proxy_mod.Proxy,
|
||||
)
|
||||
config.set_service_value(
|
||||
'endpoint_override',
|
||||
self.service_type,
|
||||
override,
|
||||
)
|
||||
|
||||
def _validate_proxy(self, proxy, endpoint):
|
||||
exc = None
|
||||
service_url = getattr(proxy, 'skip_discovery', None)
|
||||
|
@ -532,9 +532,10 @@ class TestCase(base.TestCase):
|
||||
uri=compute_discovery_url,
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
|
||||
def get_placement_discovery_mock_dict(self):
|
||||
def get_placement_discovery_mock_dict(
|
||||
self, discovery_fixture='placement.json'):
|
||||
discovery_fixture = os.path.join(
|
||||
self.fixtures_directory, "placement.json")
|
||||
self.fixtures_directory, discovery_fixture)
|
||||
return dict(method='GET', uri="https://placement.example.com/",
|
||||
text=open(discovery_fixture, 'r').read())
|
||||
|
||||
@ -580,9 +581,9 @@ class TestCase(base.TestCase):
|
||||
self.__do_register_uris([
|
||||
self.get_cinder_discovery_mock_dict()])
|
||||
|
||||
def use_placement(self):
|
||||
def use_placement(self, **kwargs):
|
||||
self.__do_register_uris([
|
||||
self.get_placement_discovery_mock_dict()])
|
||||
self.get_placement_discovery_mock_dict(**kwargs)])
|
||||
|
||||
def use_designate(self):
|
||||
# NOTE(slaweq): This method is only meant to be used in "setUp"
|
||||
|
10
openstack/tests/unit/fixtures/bad-placement.json
Normal file
10
openstack/tests/unit/fixtures/bad-placement.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"versions": [
|
||||
{
|
||||
"id": "v1.0",
|
||||
"links": [{"href": "", "rel": "self"}],
|
||||
"max_version": "1.17",
|
||||
"min_version": "1.0"
|
||||
}
|
||||
]
|
||||
}
|
@ -69,3 +69,35 @@ class TestPlacementRest(base.TestCase):
|
||||
(1, 17),
|
||||
self.cloud.placement.get_endpoint_data().max_microversion)
|
||||
self.assert_calls()
|
||||
|
||||
|
||||
class TestBadPlacementRest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBadPlacementRest, self).setUp()
|
||||
# The bad-placement.json is for older placement that was
|
||||
# missing the status field from its discovery doc. This
|
||||
# lets us show that we can talk to such a placement.
|
||||
self.use_placement(discovery_fixture='bad-placement.json')
|
||||
|
||||
def _register_uris(self, status_code=None):
|
||||
uri = dict(
|
||||
method='GET',
|
||||
uri=self.get_mock_url(
|
||||
'placement', 'public', append=['allocation_candidates']),
|
||||
json={})
|
||||
if status_code is not None:
|
||||
uri['status_code'] = status_code
|
||||
self.register_uris([uri])
|
||||
|
||||
def _validate_resp(self, resp, status_code):
|
||||
self.assertEqual(status_code, resp.status_code)
|
||||
self.assertEqual(
|
||||
'https://placement.example.com/allocation_candidates',
|
||||
resp.url)
|
||||
self.assert_calls()
|
||||
|
||||
def test_discovery(self):
|
||||
self._register_uris()
|
||||
rs = self.cloud.placement.get('/allocation_candidates')
|
||||
self._validate_resp(rs, 200)
|
||||
|
6
releasenotes/notes/old-placement-4b3c34abb8fe7b81.yaml
Normal file
6
releasenotes/notes/old-placement-4b3c34abb8fe7b81.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Workaround an issue using openstacksdk with older versions of
|
||||
the placement service that are missing a status field in
|
||||
their version discovery doc.
|
Loading…
Reference in New Issue
Block a user