From 8d3c2baa5b6f9ad22a398430c68ecfe54d6f4edc Mon Sep 17 00:00:00 2001 From: lin-hua-cheng Date: Wed, 25 Feb 2015 16:51:28 -0800 Subject: [PATCH] Updated parsing of catalog to handle bad format Don't assume that the service catalog is well-formed, added code to safely parsing the catalog. Parsing of region from service catalog has been fixed as well. 'region' has been deprecated in the Keystone V3 catalog in favor of 'region_id'. Fix how region is extracted by checking 'region_id' then fallback to 'region'. Change-Id: I9e027586847b7b7c0276e8c3ff6b73f06a32e2a5 Closes-Bug: #1424825 --- openstack_dashboard/api/base.py | 38 +++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/openstack_dashboard/api/base.py b/openstack_dashboard/api/base.py index c1dfb4ee50..5ac95a7341 100644 --- a/openstack_dashboard/api/base.py +++ b/openstack_dashboard/api/base.py @@ -236,6 +236,8 @@ class QuotaSet(Sequence): def get_service_from_catalog(catalog, service_type): if catalog: for service in catalog: + if 'type' not in service: + continue if service['type'] == service_type: return service return None @@ -260,25 +262,29 @@ ENDPOINT_TYPE_TO_INTERFACE = { def get_url_for_service(service, region, endpoint_type): + if 'type' not in service: + return None + identity_version = get_version_from_service(service) - available_endpoints = [endpoint for endpoint in service['endpoints'] - if region == endpoint['region']] + service_endpoints = service.get('endpoints', []) + available_endpoints = [endpoint for endpoint in service_endpoints + if region == _get_endpoint_region(endpoint)] """if we are dealing with the identity service and there is no endpoint in the current region, it is okay to use the first endpoint for any identity service endpoints and we can assume that it is global """ if service['type'] == 'identity' and not available_endpoints: - available_endpoints = [endpoint for endpoint in service['endpoints']] + available_endpoints = [endpoint for endpoint in service_endpoints] for endpoint in available_endpoints: try: if identity_version < 3: - return endpoint[endpoint_type] + return endpoint.get(endpoint_type) else: interface = \ ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '') - if endpoint['interface'] == interface: - return endpoint['url'] + if endpoint.get('interface') == interface: + return endpoint.get('url') except (IndexError, KeyError): """it could be that the current endpoint just doesn't match the type, continue trying the next one @@ -315,12 +321,26 @@ def is_service_enabled(request, service_type, service_name=None): service_type) if service: region = request.user.services_region - for endpoint in service['endpoints']: + for endpoint in service.get('endpoints', []): + if 'type' not in service: + continue # ignore region for identity if service['type'] == 'identity' or \ - endpoint['region'] == region: + _get_endpoint_region(endpoint) == region: if service_name: - return service['name'] == service_name + return service.get('name') == service_name else: return True return False + + +def _get_endpoint_region(endpoint): + """Common function for getting the region from endpoint. + + In Keystone V3, region has been deprecated in favor of + region_id. + + This method provides a way to get region that works for + both Keystone V2 and V3. + """ + return endpoint.get('region_id') or endpoint.get('region')