Merge "Region selector enabling multi-region support."

This commit is contained in:
Jenkins 2013-06-24 10:44:15 +00:00 committed by Gerrit Code Review
commit 9e2a8173ba
10 changed files with 118 additions and 31 deletions

View File

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

View File

@ -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']:
# 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, '')
interface = \
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
if endpoint['interface'] == interface:
return endpoint['url']
except (IndexError, KeyError):
pass
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:
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 service is not None
return True
return False

View File

@ -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.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
self.region = service['endpoints'][0]['region']
else:
self.host = None
self.disabled = None
self.region = region
def __unicode__(self):
if(self.type == "identity"):

View File

@ -63,7 +63,10 @@ def get_enabled(service, reverse=False):
options = ["Enabled", "Disabled"]
if reverse:
options.reverse()
# 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):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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