Merge "Region selector enabling multi-region support."
This commit is contained in:
commit
9e2a8173ba
@ -32,5 +32,23 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% with num_of_regions=request.user.available_services_regions|length %}
|
||||
{% if num_of_regions > 1 %}
|
||||
<div id="services_region_switcher" class="dropdown switcher_bar" tabindex="1">
|
||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#services_region_switcher">
|
||||
<h4>{% trans "Managing Region" %}</h4>
|
||||
<h3>{{ request.user.services_region }}</h3>
|
||||
</a>
|
||||
|
||||
<ul id="services_regions_list" class="dropdown-menu">
|
||||
<li class='divider'></li>
|
||||
{% for region in request.user.available_services_regions %}
|
||||
<li><a href="{% url 'switch_services_region' region %}?next={{ request.horizon.panel.get_absolute_url }}">{{ region }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
{% horizon_dashboard_nav %}
|
||||
</div>
|
||||
|
@ -97,7 +97,7 @@ class APIDictWrapper(object):
|
||||
dictionary, in addition to attribute accesses.
|
||||
|
||||
Attribute access is the preferred method of access, to be
|
||||
consistent with api resource objects from novclient.
|
||||
consistent with api resource objects from novaclient.
|
||||
"""
|
||||
def __init__(self, apidict):
|
||||
self._apidict = apidict
|
||||
@ -198,18 +198,21 @@ ENDPOINT_TYPE_TO_INTERFACE = {
|
||||
}
|
||||
|
||||
|
||||
def get_url_for_service(service, endpoint_type):
|
||||
def get_url_for_service(service, region, endpoint_type):
|
||||
identity_version = get_version_from_service(service)
|
||||
for endpoint in service['endpoints']:
|
||||
try:
|
||||
if identity_version < 3:
|
||||
return endpoint[endpoint_type]
|
||||
else:
|
||||
interface = ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
|
||||
if endpoint['interface'] == interface:
|
||||
return endpoint['url']
|
||||
except (IndexError, KeyError):
|
||||
pass
|
||||
# ignore region for identity
|
||||
if service['type'] == 'identity' or region == endpoint['region']:
|
||||
try:
|
||||
if identity_version < 3:
|
||||
return endpoint[endpoint_type]
|
||||
else:
|
||||
interface = \
|
||||
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
|
||||
if endpoint['interface'] == interface:
|
||||
return endpoint['url']
|
||||
except (IndexError, KeyError):
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
@ -222,9 +225,13 @@ def url_for(request, service_type, endpoint_type=None):
|
||||
catalog = request.user.service_catalog
|
||||
service = get_service_from_catalog(catalog, service_type)
|
||||
if service:
|
||||
url = get_url_for_service(service, endpoint_type)
|
||||
url = get_url_for_service(service,
|
||||
request.user.services_region,
|
||||
endpoint_type)
|
||||
if not url and fallback_endpoint_type:
|
||||
url = get_url_for_service(service, fallback_endpoint_type)
|
||||
url = get_url_for_service(service,
|
||||
request.user.services_region,
|
||||
fallback_endpoint_type)
|
||||
if url:
|
||||
return url
|
||||
raise exceptions.ServiceCatalogException(service_type)
|
||||
@ -233,7 +240,14 @@ def url_for(request, service_type, endpoint_type=None):
|
||||
def is_service_enabled(request, service_type, service_name=None):
|
||||
service = get_service_from_catalog(request.user.service_catalog,
|
||||
service_type)
|
||||
if service and service_name:
|
||||
return service['name'] == service_name
|
||||
else:
|
||||
return service is not None
|
||||
if service:
|
||||
region = request.user.services_region
|
||||
for endpoint in service['endpoints']:
|
||||
# ignore region for identity
|
||||
if service['type'] == 'identity' or \
|
||||
endpoint['region'] == region:
|
||||
if service_name:
|
||||
return service['name'] == service_name
|
||||
else:
|
||||
return True
|
||||
return False
|
||||
|
@ -77,12 +77,17 @@ class Service(base.APIDictWrapper):
|
||||
""" Wrapper for a dict based on the service data from keystone. """
|
||||
_attrs = ['id', 'type', 'name']
|
||||
|
||||
def __init__(self, service, *args, **kwargs):
|
||||
def __init__(self, service, region, *args, **kwargs):
|
||||
super(Service, self).__init__(service, *args, **kwargs)
|
||||
self.url = service['endpoints'][0]['internalURL']
|
||||
self.host = urlparse.urlparse(self.url).hostname
|
||||
self.region = service['endpoints'][0]['region']
|
||||
self.public_url = base.get_url_for_service(service, region,
|
||||
'publicURL')
|
||||
self.url = base.get_url_for_service(service, region, 'internalURL')
|
||||
if self.url:
|
||||
self.host = urlparse.urlparse(self.url).hostname
|
||||
else:
|
||||
self.host = None
|
||||
self.disabled = None
|
||||
self.region = region
|
||||
|
||||
def __unicode__(self):
|
||||
if(self.type == "identity"):
|
||||
|
@ -63,7 +63,10 @@ def get_enabled(service, reverse=False):
|
||||
options = ["Enabled", "Disabled"]
|
||||
if reverse:
|
||||
options.reverse()
|
||||
return options[0] if not service.disabled else options[1]
|
||||
# if not configured in this region, neither option makes sense
|
||||
if service.host:
|
||||
return options[0] if not service.disabled else options[1]
|
||||
return None
|
||||
|
||||
|
||||
class ServicesTable(tables.DataTable):
|
||||
|
@ -54,7 +54,8 @@ class ServicesTab(tabs.TableTab):
|
||||
services = []
|
||||
for i, service in enumerate(request.user.service_catalog):
|
||||
service['id'] = i
|
||||
services.append(keystone.Service(service))
|
||||
services.append(
|
||||
keystone.Service(service, request.user.services_region))
|
||||
return services
|
||||
|
||||
|
||||
|
@ -20,10 +20,6 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import tables
|
||||
|
||||
|
||||
def get_endpoint(service):
|
||||
return service.endpoints[0]['publicURL']
|
||||
|
||||
|
||||
def pretty_service_names(name):
|
||||
name = name.replace('-', ' ')
|
||||
if name in ['ec2', 's3']:
|
||||
@ -53,7 +49,7 @@ class EndpointsTable(tables.DataTable):
|
||||
api_name = tables.Column('type',
|
||||
verbose_name=_("Service"),
|
||||
filters=(pretty_service_names,))
|
||||
api_endpoint = tables.Column(get_endpoint,
|
||||
api_endpoint = tables.Column('public_url',
|
||||
verbose_name=_("Service Endpoint"))
|
||||
|
||||
class Meta:
|
||||
|
@ -117,7 +117,9 @@ class APIAccessTab(tabs.TableTab):
|
||||
services = []
|
||||
for i, service in enumerate(self.request.user.service_catalog):
|
||||
service['id'] = i
|
||||
services.append(keystone.Service(service))
|
||||
services.append(
|
||||
keystone.Service(service, self.request.user.services_region))
|
||||
|
||||
return services
|
||||
|
||||
|
||||
|
@ -140,3 +140,25 @@ class ApiHelperTests(test.TestCase):
|
||||
'Select a new nonexistent service catalog key')
|
||||
with self.assertRaises(exceptions.ServiceCatalogException):
|
||||
url = api_base.url_for(self.request, 'notAnApi')
|
||||
|
||||
self.request.user.services_region = "RegionTwo"
|
||||
url = api_base.url_for(self.request, 'compute')
|
||||
self.assertEqual(url, 'http://public.nova2.example.com:8774/v2')
|
||||
|
||||
self.request.user.services_region = "RegionTwo"
|
||||
url = api_base.url_for(self.request, 'compute',
|
||||
endpoint_type='adminURL')
|
||||
self.assertEqual(url, 'http://admin.nova2.example.com:8774/v2')
|
||||
|
||||
self.request.user.services_region = "RegionTwo"
|
||||
with self.assertRaises(exceptions.ServiceCatalogException):
|
||||
url = api_base.url_for(self.request, 'image')
|
||||
|
||||
self.request.user.services_region = "bogus_value"
|
||||
url = api_base.url_for(self.request, 'identity',
|
||||
endpoint_type='adminURL')
|
||||
self.assertEqual(url, 'http://admin.keystone.example.com:35357/v2.0')
|
||||
|
||||
self.request.user.services_region = "bogus_value"
|
||||
with self.assertRaises(exceptions.ServiceCatalogException):
|
||||
url = api_base.url_for(self.request, 'image')
|
||||
|
@ -91,10 +91,28 @@ class ServiceAPITests(test.APITestCase):
|
||||
catalog = self.service_catalog
|
||||
identity_data = api.base.get_service_from_catalog(catalog, "identity")
|
||||
identity_data['id'] = 1
|
||||
service = api.keystone.Service(identity_data)
|
||||
region = identity_data["endpoints"][0]["region"]
|
||||
service = api.keystone.Service(identity_data, region)
|
||||
self.assertEqual(unicode(service), u"identity (native backend)")
|
||||
self.assertEqual(service.region,
|
||||
identity_data["endpoints"][0]["region"])
|
||||
self.assertEqual(service.url,
|
||||
"http://int.keystone.example.com:5000/v2.0")
|
||||
self.assertEqual(service.public_url,
|
||||
"http://public.keystone.example.com:5000/v2.0")
|
||||
self.assertEqual(service.host, "int.keystone.example.com")
|
||||
|
||||
def test_service_wrapper_service_in_region(self):
|
||||
catalog = self.service_catalog
|
||||
compute_data = api.base.get_service_from_catalog(catalog, "compute")
|
||||
compute_data['id'] = 1
|
||||
region = compute_data["endpoints"][1]["region"]
|
||||
service = api.keystone.Service(compute_data, region)
|
||||
self.assertEqual(unicode(service), u"compute")
|
||||
self.assertEqual(service.region,
|
||||
compute_data["endpoints"][1]["region"])
|
||||
self.assertEqual(service.url,
|
||||
"http://int.nova2.example.com:8774/v2")
|
||||
self.assertEqual(service.public_url,
|
||||
"http://public.nova2.example.com:8774/v2")
|
||||
self.assertEqual(service.host, "int.nova2.example.com")
|
||||
|
@ -40,12 +40,20 @@ SERVICE_CATALOG = [
|
||||
{"region": "RegionOne",
|
||||
"adminURL": "http://admin.nova.example.com:8774/v2",
|
||||
"internalURL": "http://int.nova.example.com:8774/v2",
|
||||
"publicURL": "http://public.nova.example.com:8774/v2"}]},
|
||||
"publicURL": "http://public.nova.example.com:8774/v2"},
|
||||
{"region": "RegionTwo",
|
||||
"adminURL": "http://admin.nova2.example.com:8774/v2",
|
||||
"internalURL": "http://int.nova2.example.com:8774/v2",
|
||||
"publicURL": "http://public.nova2.example.com:8774/v2"}]},
|
||||
{"type": "volume",
|
||||
"name": "nova",
|
||||
"endpoints_links": [],
|
||||
"endpoints": [
|
||||
{"region": "RegionOne",
|
||||
"adminURL": "http://admin.nova.example.com:8776/v1",
|
||||
"internalURL": "http://int.nova.example.com:8776/v1",
|
||||
"publicURL": "http://public.nova.example.com:8776/v1"},
|
||||
{"region": "RegionTwo",
|
||||
"adminURL": "http://admin.nova.example.com:8776/v1",
|
||||
"internalURL": "http://int.nova.example.com:8776/v1",
|
||||
"publicURL": "http://public.nova.example.com:8776/v1"}]},
|
||||
|
Loading…
x
Reference in New Issue
Block a user