Remove Keystone v2 related code
Kyestone V2 support was removed in Train, so it's safe to do such cleanup. * Functions which just return horizon settings are dropped and the settings are referred directly now. * The service catalog in the sample test data is updated to match the format of the keystone API v3. * Related to the above change of the sample service catalog, openstack_dashboard.test.unit.api.test_keystone.ServiceAPITests is updated to specify the region name explicitly because 'RegionTwo' endpoint is no longer the second entry of the endpoint list in the keystone API v3. Co-Authored-By: Akihiro Motoki <amotoki@gmail.com> Change-Id: Ib60f360c96341fa5c618595f4a9bfdfe7ec5ae83
This commit is contained in:
parent
50837618bd
commit
ee6fa9a245
@ -100,7 +100,7 @@ class Login(django_auth_forms.AuthenticationForm):
|
|||||||
|
|
||||||
# if websso is enabled and keystone version supported
|
# if websso is enabled and keystone version supported
|
||||||
# prepend the websso_choices select input to the form
|
# prepend the websso_choices select input to the form
|
||||||
if utils.is_websso_enabled():
|
if settings.WEBSSO_ENABLED:
|
||||||
initial = settings.WEBSSO_INITIAL_CHOICE
|
initial = settings.WEBSSO_INITIAL_CHOICE
|
||||||
self.fields['auth_type'] = forms.ChoiceField(
|
self.fields['auth_type'] = forms.ChoiceField(
|
||||||
label=_("Authenticate using"),
|
label=_("Authenticate using"),
|
||||||
|
@ -967,7 +967,6 @@ class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, test.TestCase):
|
|||||||
(settings.OPENSTACK_KEYSTONE_URL, protocol, origin))
|
(settings.OPENSTACK_KEYSTONE_URL, protocol, origin))
|
||||||
|
|
||||||
url = reverse('login')
|
url = reverse('login')
|
||||||
|
|
||||||
# POST to the page and redirect to keystone.
|
# POST to the page and redirect to keystone.
|
||||||
response = self.client.get(url)
|
response = self.client.get(url)
|
||||||
self.assertRedirects(response, redirect_url, status_code=302,
|
self.assertRedirects(response, redirect_url, status_code=302,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ if utils.allow_expired_passowrd_change():
|
|||||||
name='password')
|
name='password')
|
||||||
)
|
)
|
||||||
|
|
||||||
if utils.is_websso_enabled():
|
if settings.WEBSSO_ENABLED:
|
||||||
urlpatterns += [
|
urlpatterns += [
|
||||||
url(r"^websso/$", views.websso, name='websso'),
|
url(r"^websso/$", views.websso, name='websso'),
|
||||||
url(r"^error/$",
|
url(r"^error/$",
|
||||||
|
@ -187,8 +187,7 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
|
|||||||
|
|
||||||
.. attribute:: password_expires_at
|
.. attribute:: password_expires_at
|
||||||
|
|
||||||
Password expiration date. This attribute could be None when using
|
Password expiration date.
|
||||||
keystone version < 3.0 or if the feature is not enabled in keystone.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -136,33 +136,6 @@ def allow_expired_passowrd_change():
|
|||||||
return getattr(settings, 'ALLOW_USERS_CHANGE_EXPIRED_PASSWORD', True)
|
return getattr(settings, 'ALLOW_USERS_CHANGE_EXPIRED_PASSWORD', True)
|
||||||
|
|
||||||
|
|
||||||
def is_websso_enabled():
|
|
||||||
"""Websso is supported in Keystone version 3."""
|
|
||||||
return settings.WEBSSO_ENABLED
|
|
||||||
|
|
||||||
|
|
||||||
def is_websso_default_redirect():
|
|
||||||
"""Checks if the websso default redirect is available.
|
|
||||||
|
|
||||||
As with websso, this is only supported in Keystone version 3.
|
|
||||||
"""
|
|
||||||
websso_default_redirect = settings.WEBSSO_DEFAULT_REDIRECT
|
|
||||||
keystonev3_plus = (get_keystone_version() >= 3)
|
|
||||||
return websso_default_redirect and keystonev3_plus
|
|
||||||
|
|
||||||
|
|
||||||
def get_websso_default_redirect_protocol():
|
|
||||||
return settings.WEBSSO_DEFAULT_REDIRECT_PROTOCOL
|
|
||||||
|
|
||||||
|
|
||||||
def get_websso_default_redirect_region():
|
|
||||||
return settings.WEBSSO_DEFAULT_REDIRECT_REGION
|
|
||||||
|
|
||||||
|
|
||||||
def get_websso_default_redirect_logout():
|
|
||||||
return settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT
|
|
||||||
|
|
||||||
|
|
||||||
def build_absolute_uri(request, relative_url):
|
def build_absolute_uri(request, relative_url):
|
||||||
"""Ensure absolute_uri are relative to WEBROOT."""
|
"""Ensure absolute_uri are relative to WEBROOT."""
|
||||||
webroot = settings.WEBROOT
|
webroot = settings.WEBROOT
|
||||||
|
@ -56,10 +56,10 @@ def login(request):
|
|||||||
|
|
||||||
# If the user enabled websso and the default redirect
|
# If the user enabled websso and the default redirect
|
||||||
# redirect to the default websso url
|
# redirect to the default websso url
|
||||||
if (request.method == 'GET' and utils.is_websso_enabled and
|
if (request.method == 'GET' and settings.WEBSSO_ENABLED and
|
||||||
utils.is_websso_default_redirect()):
|
settings.WEBSSO_DEFAULT_REDIRECT):
|
||||||
protocol = utils.get_websso_default_redirect_protocol()
|
protocol = settings.WEBSSO_DEFAULT_REDIRECT_PROTOCOL
|
||||||
region = utils.get_websso_default_redirect_region()
|
region = settings.WEBSSO_DEFAULT_REDIRECT_REGION
|
||||||
origin = utils.build_absolute_uri(request, '/auth/websso/')
|
origin = utils.build_absolute_uri(request, '/auth/websso/')
|
||||||
url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
|
url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
|
||||||
(region, protocol, origin))
|
(region, protocol, origin))
|
||||||
@ -70,7 +70,7 @@ def login(request):
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
auth_type = request.POST.get('auth_type', 'credentials')
|
auth_type = request.POST.get('auth_type', 'credentials')
|
||||||
request.session['auth_type'] = auth_type
|
request.session['auth_type'] = auth_type
|
||||||
if utils.is_websso_enabled() and auth_type != 'credentials':
|
if settings.WEBSSO_ENABLED and auth_type != 'credentials':
|
||||||
region_id = request.POST.get('region')
|
region_id = request.POST.get('region')
|
||||||
auth_url = getattr(settings, 'WEBSSO_KEYSTONE_URL', None)
|
auth_url = getattr(settings, 'WEBSSO_KEYSTONE_URL', None)
|
||||||
if auth_url is None:
|
if auth_url is None:
|
||||||
@ -105,7 +105,7 @@ def login(request):
|
|||||||
extra_context = {
|
extra_context = {
|
||||||
'redirect_field_name': auth.REDIRECT_FIELD_NAME,
|
'redirect_field_name': auth.REDIRECT_FIELD_NAME,
|
||||||
'csrf_failure': request.GET.get('csrf_failure'),
|
'csrf_failure': request.GET.get('csrf_failure'),
|
||||||
'show_sso_opts': utils.is_websso_enabled() and len(choices) > 1,
|
'show_sso_opts': settings.WEBSSO_ENABLED and len(choices) > 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.is_ajax():
|
if request.is_ajax():
|
||||||
@ -171,7 +171,7 @@ def websso(request):
|
|||||||
request.user = auth.authenticate(request, auth_url=auth_url,
|
request.user = auth.authenticate(request, auth_url=auth_url,
|
||||||
token=token)
|
token=token)
|
||||||
except exceptions.KeystoneAuthException as exc:
|
except exceptions.KeystoneAuthException as exc:
|
||||||
if utils.is_websso_default_redirect():
|
if settings.WEBSSO_DEFAULT_REDIRECT:
|
||||||
res = django_http.HttpResponseRedirect(settings.LOGIN_ERROR)
|
res = django_http.HttpResponseRedirect(settings.LOGIN_ERROR)
|
||||||
else:
|
else:
|
||||||
msg = 'Login failed: %s' % exc
|
msg = 'Login failed: %s' % exc
|
||||||
@ -202,11 +202,11 @@ def logout(request, login_url=None, **kwargs):
|
|||||||
LOG.info(msg)
|
LOG.info(msg)
|
||||||
|
|
||||||
""" Securely logs a user out. """
|
""" Securely logs a user out. """
|
||||||
if (utils.is_websso_enabled and utils.is_websso_default_redirect() and
|
if (settings.WEBSSO_ENABLED and settings.WEBSSO_DEFAULT_REDIRECT and
|
||||||
utils.get_websso_default_redirect_logout()):
|
settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT):
|
||||||
auth_user.unset_session_user_variables(request)
|
auth_user.unset_session_user_variables(request)
|
||||||
return django_http.HttpResponseRedirect(
|
return django_http.HttpResponseRedirect(
|
||||||
utils.get_websso_default_redirect_logout())
|
settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT)
|
||||||
else:
|
else:
|
||||||
return django_auth_views.logout_then_login(request,
|
return django_auth_views.logout_then_login(request,
|
||||||
login_url=login_url,
|
login_url=login_url,
|
||||||
|
@ -293,17 +293,9 @@ def get_service_from_catalog(catalog, service_type):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_version_from_service(service):
|
|
||||||
if service and service.get('endpoints'):
|
|
||||||
endpoint = service['endpoints'][0]
|
|
||||||
if 'interface' in endpoint:
|
|
||||||
return 3
|
|
||||||
else:
|
|
||||||
return 2.0
|
|
||||||
return 2.0
|
|
||||||
|
|
||||||
|
|
||||||
# Mapping of V2 Catalog Endpoint_type to V3 Catalog Interfaces
|
# Mapping of V2 Catalog Endpoint_type to V3 Catalog Interfaces
|
||||||
|
# TODO(e0ne): remove this mapping once OPENSTACK_ENDPOINT_TYPE config option
|
||||||
|
# will be removed.
|
||||||
ENDPOINT_TYPE_TO_INTERFACE = {
|
ENDPOINT_TYPE_TO_INTERFACE = {
|
||||||
'publicURL': 'public',
|
'publicURL': 'public',
|
||||||
'internalURL': 'internal',
|
'internalURL': 'internal',
|
||||||
@ -315,31 +307,25 @@ def get_url_for_service(service, region, endpoint_type):
|
|||||||
if 'type' not in service:
|
if 'type' not in service:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
identity_version = get_version_from_service(service)
|
|
||||||
service_endpoints = service.get('endpoints', [])
|
service_endpoints = service.get('endpoints', [])
|
||||||
available_endpoints = [endpoint for endpoint in service_endpoints
|
available_endpoints = [endpoint for endpoint in service_endpoints
|
||||||
if region == _get_endpoint_region(endpoint)]
|
if region == _get_endpoint_region(endpoint)]
|
||||||
"""if we are dealing with the identity service and there is no 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
|
# 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
|
# identity service endpoints and we can assume that it is global
|
||||||
"""
|
|
||||||
if service['type'] == 'identity' and not available_endpoints:
|
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:
|
for endpoint in available_endpoints:
|
||||||
try:
|
try:
|
||||||
if identity_version < 3:
|
interface = \
|
||||||
return endpoint.get(endpoint_type)
|
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
|
||||||
else:
|
if endpoint['interface'] == interface:
|
||||||
interface = \
|
return endpoint['url']
|
||||||
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
|
except KeyError:
|
||||||
if endpoint.get('interface') == interface:
|
|
||||||
return endpoint.get('url')
|
|
||||||
except (IndexError, KeyError):
|
|
||||||
# it could be that the current endpoint just doesn't match the
|
# it could be that the current endpoint just doesn't match the
|
||||||
# type, continue trying the next one
|
# type, continue trying the next one
|
||||||
pass
|
pass
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def url_for(request, service_type, endpoint_type=None, region=None):
|
def url_for(request, service_type, endpoint_type=None, region=None):
|
||||||
|
@ -146,7 +146,7 @@ def keystoneclient(request, admin=False):
|
|||||||
user = request.user
|
user = request.user
|
||||||
token_id = user.token.id
|
token_id = user.token.id
|
||||||
|
|
||||||
if is_multi_domain_enabled():
|
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
|
||||||
is_domain_context_specified = bool(
|
is_domain_context_specified = bool(
|
||||||
request.session.get("domain_context"))
|
request.session.get("domain_context"))
|
||||||
|
|
||||||
@ -274,8 +274,7 @@ def get_default_domain(request, get_name=True):
|
|||||||
"""
|
"""
|
||||||
domain_id = request.session.get("domain_context", None)
|
domain_id = request.session.get("domain_context", None)
|
||||||
domain_name = request.session.get("domain_context_name", None)
|
domain_name = request.session.get("domain_context_name", None)
|
||||||
# if running in Keystone V3 or later
|
if domain_id is None:
|
||||||
if VERSIONS.active >= 3 and domain_id is None:
|
|
||||||
# if no domain context set, default to user's domain
|
# if no domain context set, default to user's domain
|
||||||
domain_id = request.user.user_domain_id
|
domain_id = request.user.user_domain_id
|
||||||
domain_name = request.user.user_domain_name
|
domain_name = request.user.user_domain_name
|
||||||
@ -861,15 +860,6 @@ def get_version():
|
|||||||
return VERSIONS.active
|
return VERSIONS.active
|
||||||
|
|
||||||
|
|
||||||
def is_multi_domain_enabled():
|
|
||||||
return (VERSIONS.active >= 3 and
|
|
||||||
settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT)
|
|
||||||
|
|
||||||
|
|
||||||
def is_federation_management_enabled():
|
|
||||||
return settings.OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT
|
|
||||||
|
|
||||||
|
|
||||||
def identity_provider_create(request, idp_id, description=None,
|
def identity_provider_create(request, idp_id, description=None,
|
||||||
enabled=False, remote_ids=None):
|
enabled=False, remote_ids=None):
|
||||||
manager = keystoneclient(request, admin=True).federation.identity_providers
|
manager = keystoneclient(request, admin=True).federation.identity_providers
|
||||||
|
@ -24,10 +24,6 @@ class ApplicationCredentialsPanel(horizon.Panel):
|
|||||||
slug = 'application_credentials'
|
slug = 'application_credentials'
|
||||||
policy_rules = (('identity', 'identity:list_application_credentials'),)
|
policy_rules = (('identity', 'identity:list_application_credentials'),)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_register():
|
|
||||||
return keystone.VERSIONS.active >= 3
|
|
||||||
|
|
||||||
def can_access(self, context):
|
def can_access(self, context):
|
||||||
request = context['request']
|
request = context['request']
|
||||||
keystone_version = keystone.get_identity_api_version(request)
|
keystone_version = keystone.get_identity_api_version(request)
|
||||||
|
@ -16,8 +16,6 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
|
|
||||||
from openstack_dashboard.api import keystone
|
|
||||||
|
|
||||||
|
|
||||||
class Domains(horizon.Panel):
|
class Domains(horizon.Panel):
|
||||||
name = _("Domains")
|
name = _("Domains")
|
||||||
@ -25,10 +23,6 @@ class Domains(horizon.Panel):
|
|||||||
policy_rules = (("identity", "identity:get_domain"),
|
policy_rules = (("identity", "identity:get_domain"),
|
||||||
("identity", "identity:list_domains"))
|
("identity", "identity:list_domains"))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_register():
|
|
||||||
return keystone.VERSIONS.active >= 3
|
|
||||||
|
|
||||||
def can_access(self, context):
|
def can_access(self, context):
|
||||||
request = context['request']
|
request = context['request']
|
||||||
domain_token = request.session.get('domain_token')
|
domain_token = request.session.get('domain_token')
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
@ -24,12 +25,8 @@ class Groups(horizon.Panel):
|
|||||||
slug = 'groups'
|
slug = 'groups'
|
||||||
policy_rules = (("identity", "identity:list_groups"),)
|
policy_rules = (("identity", "identity:list_groups"),)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_register():
|
|
||||||
return keystone.VERSIONS.active >= 3
|
|
||||||
|
|
||||||
def can_access(self, context):
|
def can_access(self, context):
|
||||||
if keystone.is_multi_domain_enabled() \
|
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
|
||||||
and not keystone.is_domain_admin(context['request']):
|
not keystone.is_domain_admin(context['request'])):
|
||||||
return False
|
return False
|
||||||
return super(Groups, self).can_access(context)
|
return super(Groups, self).can_access(context)
|
||||||
|
@ -243,15 +243,10 @@ class GroupsViewTests(test.BaseAdminViewTests):
|
|||||||
|
|
||||||
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
group.id)
|
group.id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_get_effective_domain_id.assert_called_once_with(
|
||||||
self.mock_get_effective_domain_id.assert_called_once_with(
|
test.IsHttpRequest())
|
||||||
test.IsHttpRequest())
|
self.mock_user_list.assert_called_once_with(
|
||||||
self.mock_user_list.assert_called_once_with(
|
test.IsHttpRequest(), group=group.id, domain=domain_id)
|
||||||
test.IsHttpRequest(), group=group.id, domain=domain_id)
|
|
||||||
else:
|
|
||||||
self.mock_get_effective_domain_id.assert_not_called()
|
|
||||||
self.mock_user_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), group=group.id)
|
|
||||||
|
|
||||||
@test.create_mocks({api.keystone: ('get_effective_domain_id',
|
@test.create_mocks({api.keystone: ('get_effective_domain_id',
|
||||||
'user_list',
|
'user_list',
|
||||||
@ -271,15 +266,10 @@ class GroupsViewTests(test.BaseAdminViewTests):
|
|||||||
self.assertRedirectsNoFollow(res, GROUP_MANAGE_URL)
|
self.assertRedirectsNoFollow(res, GROUP_MANAGE_URL)
|
||||||
self.assertMessageCount(success=1)
|
self.assertMessageCount(success=1)
|
||||||
|
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_get_effective_domain_id.assert_called_once_with(
|
||||||
self.mock_get_effective_domain_id.assert_called_once_with(
|
test.IsHttpRequest())
|
||||||
test.IsHttpRequest())
|
self.mock_user_list.assert_called_once_with(
|
||||||
self.mock_user_list.assert_called_once_with(
|
test.IsHttpRequest(), group=group.id, domain=domain_id)
|
||||||
test.IsHttpRequest(), group=group.id, domain=domain_id)
|
|
||||||
else:
|
|
||||||
self.mock_get_effective_domain_id.assert_not_called()
|
|
||||||
self.mock_user_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), group=group.id)
|
|
||||||
|
|
||||||
self.mock_remove_group_user.assert_called_once_with(
|
self.mock_remove_group_user.assert_called_once_with(
|
||||||
test.IsHttpRequest(),
|
test.IsHttpRequest(),
|
||||||
|
@ -12,12 +12,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
|
|
||||||
from openstack_dashboard.api import keystone
|
|
||||||
|
|
||||||
|
|
||||||
class IdentityProviders(horizon.Panel):
|
class IdentityProviders(horizon.Panel):
|
||||||
name = _("Identity Providers")
|
name = _("Identity Providers")
|
||||||
@ -26,5 +25,4 @@ class IdentityProviders(horizon.Panel):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_register():
|
def can_register():
|
||||||
return (keystone.VERSIONS.active >= 3 and
|
return settings.OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT
|
||||||
keystone.is_federation_management_enabled())
|
|
||||||
|
@ -12,12 +12,11 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
|
|
||||||
from openstack_dashboard.api import keystone
|
|
||||||
|
|
||||||
|
|
||||||
class Mappings(horizon.Panel):
|
class Mappings(horizon.Panel):
|
||||||
name = _("Mappings")
|
name = _("Mappings")
|
||||||
@ -26,5 +25,4 @@ class Mappings(horizon.Panel):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def can_register():
|
def can_register():
|
||||||
return (keystone.VERSIONS.active >= 3 and
|
return settings.OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT
|
||||||
keystone.is_federation_management_enabled())
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.template import defaultfilters as filters
|
from django.template import defaultfilters as filters
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.http import urlencode
|
from django.utils.http import urlencode
|
||||||
@ -62,7 +63,7 @@ class UpdateMembersLink(tables.LinkAction):
|
|||||||
return "?".join([base_url, param])
|
return "?".join([base_url, param])
|
||||||
|
|
||||||
def allowed(self, request, project):
|
def allowed(self, request, project):
|
||||||
if api.keystone.is_multi_domain_enabled():
|
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
|
||||||
# domain admin or cloud admin = True
|
# domain admin or cloud admin = True
|
||||||
# project admin or member = False
|
# project admin or member = False
|
||||||
return api.keystone.is_domain_admin(request)
|
return api.keystone.is_domain_admin(request)
|
||||||
@ -79,7 +80,7 @@ class UpdateGroupsLink(tables.LinkAction):
|
|||||||
policy_rules = (("identity", "identity:list_groups"),)
|
policy_rules = (("identity", "identity:list_groups"),)
|
||||||
|
|
||||||
def allowed(self, request, project):
|
def allowed(self, request, project):
|
||||||
if api.keystone.is_multi_domain_enabled():
|
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
|
||||||
# domain admin or cloud admin = True
|
# domain admin or cloud admin = True
|
||||||
# project admin or member = False
|
# project admin or member = False
|
||||||
return api.keystone.is_domain_admin(request)
|
return api.keystone.is_domain_admin(request)
|
||||||
@ -114,7 +115,7 @@ class CreateProject(tables.LinkAction):
|
|||||||
policy_rules = (('identity', 'identity:create_project'),)
|
policy_rules = (('identity', 'identity:create_project'),)
|
||||||
|
|
||||||
def allowed(self, request, project):
|
def allowed(self, request, project):
|
||||||
if api.keystone.is_multi_domain_enabled():
|
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
|
||||||
# domain admin or cloud admin = True
|
# domain admin or cloud admin = True
|
||||||
# project admin or member = False
|
# project admin or member = False
|
||||||
return api.keystone.is_domain_admin(request)
|
return api.keystone.is_domain_admin(request)
|
||||||
@ -132,7 +133,7 @@ class UpdateProject(policy.PolicyTargetMixin, tables.LinkAction):
|
|||||||
policy_target_attrs = (("target.project.domain_id", "domain_id"),)
|
policy_target_attrs = (("target.project.domain_id", "domain_id"),)
|
||||||
|
|
||||||
def allowed(self, request, project):
|
def allowed(self, request, project):
|
||||||
if api.keystone.is_multi_domain_enabled():
|
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
|
||||||
# domain admin or cloud admin = True
|
# domain admin or cloud admin = True
|
||||||
# project admin or member = False
|
# project admin or member = False
|
||||||
return api.keystone.is_domain_admin(request)
|
return api.keystone.is_domain_admin(request)
|
||||||
@ -180,8 +181,8 @@ class DeleteTenantsAction(policy.PolicyTargetMixin, tables.DeleteAction):
|
|||||||
policy_target_attrs = (("target.project.domain_id", "domain_id"),)
|
policy_target_attrs = (("target.project.domain_id", "domain_id"),)
|
||||||
|
|
||||||
def allowed(self, request, project):
|
def allowed(self, request, project):
|
||||||
if api.keystone.is_multi_domain_enabled() \
|
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
|
||||||
and not api.keystone.is_domain_admin(request):
|
not api.keystone.is_domain_admin(request)):
|
||||||
return False
|
return False
|
||||||
return api.keystone.keystone_can_edit_project()
|
return api.keystone.keystone_can_edit_project()
|
||||||
|
|
||||||
@ -220,11 +221,8 @@ class TenantsTable(tables.DataTable):
|
|||||||
widget=forms.Textarea(attrs={'rows': 4}),
|
widget=forms.Textarea(attrs={'rows': 4}),
|
||||||
required=False))
|
required=False))
|
||||||
id = tables.Column('id', verbose_name=_('Project ID'))
|
id = tables.Column('id', verbose_name=_('Project ID'))
|
||||||
|
domain_name = tables.Column(
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
'domain_name', verbose_name=_('Domain Name'))
|
||||||
domain_name = tables.Column(
|
|
||||||
'domain_name', verbose_name=_('Domain Name'))
|
|
||||||
|
|
||||||
enabled = tables.Column('enabled', verbose_name=_('Enabled'), status=True,
|
enabled = tables.Column('enabled', verbose_name=_('Enabled'), status=True,
|
||||||
filters=(filters.yesno, filters.capfirst),
|
filters=(filters.yesno, filters.capfirst),
|
||||||
form_field=forms.BooleanField(
|
form_field=forms.BooleanField(
|
||||||
|
@ -41,28 +41,24 @@ class OverviewTab(tabs.Tab):
|
|||||||
|
|
||||||
def _get_domain_name(self, project):
|
def _get_domain_name(self, project):
|
||||||
domain_name = ''
|
domain_name = ''
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
try:
|
||||||
try:
|
if policy.check((("identity", "identity:get_domain"),),
|
||||||
if policy.check((("identity", "identity:get_domain"),),
|
self.request):
|
||||||
self.request):
|
domain = api.keystone.domain_get(
|
||||||
domain = api.keystone.domain_get(
|
self.request, project.domain_id)
|
||||||
self.request, project.domain_id)
|
domain_name = domain.name
|
||||||
domain_name = domain.name
|
else:
|
||||||
else:
|
domain = api.keystone.get_default_domain(self.request)
|
||||||
domain = api.keystone.get_default_domain(self.request)
|
domain_name = domain.get('name')
|
||||||
domain_name = domain.get('name')
|
except Exception:
|
||||||
except Exception:
|
exceptions.handle(self.request,
|
||||||
exceptions.handle(self.request,
|
_('Unable to retrieve project domain.'))
|
||||||
_('Unable to retrieve project domain.'))
|
|
||||||
return domain_name
|
return domain_name
|
||||||
|
|
||||||
def _get_extras(self, project):
|
def _get_extras(self, project):
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
extra_info = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
extra_info = settings.PROJECT_TABLE_EXTRA_INFO
|
return dict((display_key, getattr(project, key, ''))
|
||||||
return dict((display_key, getattr(project, key, ''))
|
for key, display_key in extra_info.items())
|
||||||
for key, display_key in extra_info.items())
|
|
||||||
else:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
class UsersTab(tabs.TableTab):
|
class UsersTab(tabs.TableTab):
|
||||||
|
@ -541,15 +541,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
'role_list',
|
'role_list',
|
||||||
'role_assignments_list')})
|
'role_assignments_list')})
|
||||||
def test_update_project_get(self):
|
def test_update_project_get(self):
|
||||||
keystone_api_version = api.keystone.VERSIONS.active
|
|
||||||
|
|
||||||
project = self.tenants.first()
|
project = self.tenants.first()
|
||||||
default_role = self.roles.first()
|
default_role = self.roles.first()
|
||||||
domain_id = project.domain_id
|
domain_id = project.domain_id
|
||||||
users = self._get_all_users(domain_id)
|
users = self._get_all_users(domain_id)
|
||||||
groups = self._get_all_groups(domain_id)
|
groups = self._get_all_groups(domain_id)
|
||||||
roles = self.roles.list()
|
roles = self.roles.list()
|
||||||
proj_users = self._get_proj_users(project.id)
|
|
||||||
role_assignments = self._get_proj_role_assignment(project.id)
|
role_assignments = self._get_proj_role_assignment(project.id)
|
||||||
|
|
||||||
self.mock_tenant_get.return_value = project
|
self.mock_tenant_get.return_value = project
|
||||||
@ -564,13 +561,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
self.mock_role_list.return_value = roles
|
self.mock_role_list.return_value = roles
|
||||||
self.mock_group_list.return_value = groups
|
self.mock_group_list.return_value = groups
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
self.mock_role_assignments_list.return_value = role_assignments
|
||||||
self.mock_role_assignments_list.return_value = role_assignments
|
|
||||||
else:
|
|
||||||
retvals_user_list.append(proj_users)
|
|
||||||
expected_user_list.append(
|
|
||||||
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
|
||||||
self.mock_roles_for_user.return_value = roles
|
|
||||||
|
|
||||||
url = reverse('horizon:identity:projects:update',
|
url = reverse('horizon:identity:projects:update',
|
||||||
args=[self.tenant.id])
|
args=[self.tenant.id])
|
||||||
@ -609,16 +600,10 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
self.mock_group_list.assert_called_once_with(
|
self.mock_group_list.assert_called_once_with(
|
||||||
test.IsHttpRequest(), domain=domain_id)
|
test.IsHttpRequest(), domain=domain_id)
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_role_assignments_list, 2,
|
||||||
self.mock_role_assignments_list, 2,
|
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
||||||
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
self.mock_roles_for_user.assert_not_called()
|
||||||
self.mock_roles_for_user.assert_not_called()
|
|
||||||
else:
|
|
||||||
self.mock_roles_for_user.assert_has_calls(
|
|
||||||
[mock.call(test.IsHttpRequest(), user.id, self.tenant.id)
|
|
||||||
for user in proj_users])
|
|
||||||
self.mock_role_assignments_list.assert_not_called()
|
|
||||||
|
|
||||||
@test.create_mocks({api.keystone: ('tenant_get',
|
@test.create_mocks({api.keystone: ('tenant_get',
|
||||||
'domain_get',
|
'domain_get',
|
||||||
@ -636,13 +621,10 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
'role_list',
|
'role_list',
|
||||||
'role_assignments_list')})
|
'role_assignments_list')})
|
||||||
def test_update_project_save(self):
|
def test_update_project_save(self):
|
||||||
keystone_api_version = api.keystone.VERSIONS.active
|
|
||||||
|
|
||||||
project = self.tenants.first()
|
project = self.tenants.first()
|
||||||
default_role = self.roles.first()
|
default_role = self.roles.first()
|
||||||
domain_id = project.domain_id
|
domain_id = project.domain_id
|
||||||
users = self._get_all_users(domain_id)
|
users = self._get_all_users(domain_id)
|
||||||
proj_users = self._get_proj_users(project.id)
|
|
||||||
groups = self._get_all_groups(domain_id)
|
groups = self._get_all_groups(domain_id)
|
||||||
roles = self.roles.list()
|
roles = self.roles.list()
|
||||||
role_assignments = self._get_proj_role_assignment(project.id)
|
role_assignments = self._get_proj_role_assignment(project.id)
|
||||||
@ -670,16 +652,6 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
expected_roles_for_user = []
|
expected_roles_for_user = []
|
||||||
self.mock_roles_for_user.side_effect = retvals_roles_for_user
|
self.mock_roles_for_user.side_effect = retvals_roles_for_user
|
||||||
|
|
||||||
if keystone_api_version < 3:
|
|
||||||
retvals_user_list.append(proj_users)
|
|
||||||
expected_user_list.append(
|
|
||||||
mock.call(test.IsHttpRequest(),
|
|
||||||
project=self.tenant.id))
|
|
||||||
for user in proj_users:
|
|
||||||
retvals_roles_for_user.append(roles)
|
|
||||||
expected_roles_for_user.append(
|
|
||||||
mock.call(test.IsHttpRequest(), user.id, self.tenant.id))
|
|
||||||
|
|
||||||
workflow_data[USER_ROLE_PREFIX + "1"] = ['3'] # admin role
|
workflow_data[USER_ROLE_PREFIX + "1"] = ['3'] # admin role
|
||||||
workflow_data[USER_ROLE_PREFIX + "2"] = ['2'] # member role
|
workflow_data[USER_ROLE_PREFIX + "2"] = ['2'] # member role
|
||||||
# Group assignment form data
|
# Group assignment form data
|
||||||
@ -716,95 +688,67 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
expected_remove_group_role = []
|
expected_remove_group_role = []
|
||||||
self.mock_remove_group_role.side_effect = retvals_remove_group_role
|
self.mock_remove_group_role.side_effect = retvals_remove_group_role
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
# admin role with attempt to remove current admin, results in
|
||||||
# admin role with attempt to remove current admin, results in
|
# warning message
|
||||||
# warning message
|
workflow_data[USER_ROLE_PREFIX + "1"] = ['3']
|
||||||
workflow_data[USER_ROLE_PREFIX + "1"] = ['3']
|
|
||||||
|
|
||||||
# member role
|
# member role
|
||||||
workflow_data[USER_ROLE_PREFIX + "2"] = ['1', '3']
|
workflow_data[USER_ROLE_PREFIX + "2"] = ['1', '3']
|
||||||
|
|
||||||
# admin role
|
# admin role
|
||||||
workflow_data[GROUP_ROLE_PREFIX + "1"] = ['2', '3']
|
workflow_data[GROUP_ROLE_PREFIX + "1"] = ['2', '3']
|
||||||
|
|
||||||
# member role
|
# member role
|
||||||
workflow_data[GROUP_ROLE_PREFIX + "2"] = ['1', '2', '3']
|
workflow_data[GROUP_ROLE_PREFIX + "2"] = ['1', '2', '3']
|
||||||
self.mock_role_assignments_list.return_value = role_assignments
|
self.mock_role_assignments_list.return_value = role_assignments
|
||||||
# Give user 1 role 2
|
# Give user 1 role 2
|
||||||
retvals_add_tenant_user_role.append(None)
|
retvals_add_tenant_user_role.append(None)
|
||||||
expected_add_tenant_user_role.append(
|
expected_add_tenant_user_role.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
project=self.tenant.id,
|
project=self.tenant.id,
|
||||||
user='1',
|
user='1',
|
||||||
role='2',))
|
role='2',))
|
||||||
# remove role 2 from user 2
|
# remove role 2 from user 2
|
||||||
retvals_remove_tenant_user_role.append(None)
|
retvals_remove_tenant_user_role.append(None)
|
||||||
expected_remove_tenant_user_role.append(
|
expected_remove_tenant_user_role.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
project=self.tenant.id,
|
project=self.tenant.id,
|
||||||
user='2',
|
user='2',
|
||||||
role='2'))
|
role='2'))
|
||||||
|
|
||||||
# Give user 3 role 1
|
# Give user 3 role 1
|
||||||
retvals_add_tenant_user_role.append(None)
|
retvals_add_tenant_user_role.append(None)
|
||||||
expected_add_tenant_user_role.append(
|
expected_add_tenant_user_role.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
project=self.tenant.id,
|
project=self.tenant.id,
|
||||||
user='3',
|
user='3',
|
||||||
role='1'))
|
role='1'))
|
||||||
retvals_group_list.append(groups)
|
retvals_group_list.append(groups)
|
||||||
expected_group_list.append(
|
expected_group_list.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
domain=self.domain.id,
|
domain=self.domain.id,
|
||||||
project=self.tenant.id))
|
project=self.tenant.id))
|
||||||
retvals_roles_for_group.append(roles)
|
retvals_roles_for_group.append(roles)
|
||||||
expected_roles_for_group.append(
|
expected_roles_for_group.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
group='1',
|
group='1',
|
||||||
project=self.tenant.id))
|
project=self.tenant.id))
|
||||||
retvals_remove_group_role.append(None)
|
retvals_remove_group_role.append(None)
|
||||||
expected_remove_group_role.append(
|
expected_remove_group_role.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
project=self.tenant.id,
|
project=self.tenant.id,
|
||||||
group='1',
|
group='1',
|
||||||
role='1'))
|
role='1'))
|
||||||
retvals_roles_for_group.append(roles)
|
retvals_roles_for_group.append(roles)
|
||||||
expected_roles_for_group.append(
|
expected_roles_for_group.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
group='2',
|
group='2',
|
||||||
project=self.tenant.id))
|
project=self.tenant.id))
|
||||||
retvals_roles_for_group.append(roles)
|
retvals_roles_for_group.append(roles)
|
||||||
expected_roles_for_group.append(
|
expected_roles_for_group.append(
|
||||||
mock.call(test.IsHttpRequest(),
|
mock.call(test.IsHttpRequest(),
|
||||||
group='3',
|
group='3',
|
||||||
project=self.tenant.id))
|
project=self.tenant.id))
|
||||||
else:
|
|
||||||
retvals_user_list.append(proj_users)
|
|
||||||
expected_user_list.append(
|
|
||||||
mock.call(test.IsHttpRequest(),
|
|
||||||
project=self.tenant.id))
|
|
||||||
|
|
||||||
# admin user - try to remove all roles on current project, warning
|
|
||||||
retvals_roles_for_user.append(roles)
|
|
||||||
expected_roles_for_group.append(
|
|
||||||
mock.call(test.IsHttpRequest(), '1', self.tenant.id))
|
|
||||||
|
|
||||||
# member user 1 - has role 1, will remove it
|
|
||||||
retvals_roles_for_user.append((roles[1],))
|
|
||||||
expected_roles_for_group.append(
|
|
||||||
mock.call(test.IsHttpRequest(), '2', self.tenant.id))
|
|
||||||
|
|
||||||
# member user 3 - has role 2
|
|
||||||
retvals_roles_for_user.append((roles[0],))
|
|
||||||
expected_roles_for_group.append(
|
|
||||||
mock.call(test.IsHttpRequest(), '3', self.tenant.id))
|
|
||||||
# add role 2
|
|
||||||
retvals_add_tenant_user_role.append(self.exceptions.keystone)
|
|
||||||
expected_add_tenant_user_role.append(
|
|
||||||
mock.call(test.IsHttpRequest(),
|
|
||||||
project=self.tenant.id,
|
|
||||||
user='3',
|
|
||||||
role='2'))
|
|
||||||
|
|
||||||
# submit form data
|
# submit form data
|
||||||
project_data = {"domain_id": project._info["domain_id"],
|
project_data = {"domain_id": project._info["domain_id"],
|
||||||
@ -859,12 +803,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
_check_mock_calls(self.mock_remove_group_role,
|
_check_mock_calls(self.mock_remove_group_role,
|
||||||
expected_remove_group_role)
|
expected_remove_group_role)
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_role_assignments_list, 3,
|
||||||
self.mock_role_assignments_list, 3,
|
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
||||||
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
|
||||||
else:
|
|
||||||
self.mock_role_assignments_list.assert_not_called()
|
|
||||||
|
|
||||||
@test.create_mocks({api.keystone: ('tenant_get',)})
|
@test.create_mocks({api.keystone: ('tenant_get',)})
|
||||||
def test_update_project_get_error(self):
|
def test_update_project_get_error(self):
|
||||||
@ -895,8 +836,6 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
'role_list',
|
'role_list',
|
||||||
'role_assignments_list')})
|
'role_assignments_list')})
|
||||||
def test_update_project_tenant_update_error(self):
|
def test_update_project_tenant_update_error(self):
|
||||||
keystone_api_version = api.keystone.VERSIONS.active
|
|
||||||
|
|
||||||
project = self.tenants.first()
|
project = self.tenants.first()
|
||||||
default_role = self.roles.first()
|
default_role = self.roles.first()
|
||||||
domain_id = project.domain_id
|
domain_id = project.domain_id
|
||||||
@ -925,16 +864,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
expected_roles_for_user = []
|
expected_roles_for_user = []
|
||||||
self.mock_roles_for_user.side_effect = retvals_roles_for_user
|
self.mock_roles_for_user.side_effect = retvals_roles_for_user
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
self.mock_role_assignments_list.return_value = role_assignments
|
||||||
self.mock_role_assignments_list.return_value = role_assignments
|
|
||||||
else:
|
|
||||||
retvals_user_list.append(proj_users)
|
|
||||||
expected_roles_for_user.append(
|
|
||||||
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
|
||||||
for user in proj_users:
|
|
||||||
retvals_roles_for_user.append(roles)
|
|
||||||
expected_roles_for_user.append(
|
|
||||||
mock.call(test.IsHttpRequest(), user.id, self.tenant.id))
|
|
||||||
|
|
||||||
role_ids = [role.id for role in roles]
|
role_ids = [role.id for role in roles]
|
||||||
for user in proj_users:
|
for user in proj_users:
|
||||||
@ -992,12 +922,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
|
|||||||
self.assertEqual(len(expected_roles_for_user),
|
self.assertEqual(len(expected_roles_for_user),
|
||||||
self.mock_roles_for_user.call_count)
|
self.mock_roles_for_user.call_count)
|
||||||
|
|
||||||
if keystone_api_version >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_role_assignments_list, 2,
|
||||||
self.mock_role_assignments_list, 2,
|
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
||||||
mock.call(test.IsHttpRequest(), project=self.tenant.id))
|
|
||||||
else:
|
|
||||||
self.mock_role_assignments_list.assert_not_called()
|
|
||||||
|
|
||||||
self.mock_get_effective_domain_id.assert_called_once_with(
|
self.mock_get_effective_domain_id.assert_called_once_with(
|
||||||
test.IsHttpRequest())
|
test.IsHttpRequest())
|
||||||
|
@ -131,10 +131,9 @@ class IndexView(tables.DataTableView):
|
|||||||
_("Insufficient privilege level to view project information.")
|
_("Insufficient privilege level to view project information.")
|
||||||
messages.info(self.request, msg)
|
messages.info(self.request, msg)
|
||||||
|
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
domain_lookup = api.keystone.domain_lookup(self.request)
|
||||||
domain_lookup = api.keystone.domain_lookup(self.request)
|
for t in tenants:
|
||||||
for t in tenants:
|
t.domain_name = domain_lookup.get(t.domain_id)
|
||||||
t.domain_name = domain_lookup.get(t.domain_id)
|
|
||||||
|
|
||||||
return tenants
|
return tenants
|
||||||
|
|
||||||
@ -182,28 +181,27 @@ class UpdateProjectView(workflows.WorkflowView):
|
|||||||
for field in PROJECT_INFO_FIELDS:
|
for field in PROJECT_INFO_FIELDS:
|
||||||
initial[field] = getattr(project_info, field, None)
|
initial[field] = getattr(project_info, field, None)
|
||||||
|
|
||||||
if keystone.VERSIONS.active >= 3:
|
# get extra columns info
|
||||||
# get extra columns info
|
ex_info = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
ex_info = settings.PROJECT_TABLE_EXTRA_INFO
|
for ex_field in ex_info:
|
||||||
for ex_field in ex_info:
|
initial[ex_field] = getattr(project_info, ex_field, None)
|
||||||
initial[ex_field] = getattr(project_info, ex_field, None)
|
|
||||||
|
|
||||||
# Retrieve the domain name where the project belong
|
# Retrieve the domain name where the project belong
|
||||||
try:
|
try:
|
||||||
if policy.check((("identity", "identity:get_domain"),),
|
if policy.check((("identity", "identity:get_domain"),),
|
||||||
self.request):
|
self.request):
|
||||||
domain = api.keystone.domain_get(self.request,
|
domain = api.keystone.domain_get(self.request,
|
||||||
initial["domain_id"])
|
initial["domain_id"])
|
||||||
initial["domain_name"] = domain.name
|
initial["domain_name"] = domain.name
|
||||||
|
|
||||||
else:
|
else:
|
||||||
domain = api.keystone.get_default_domain(self.request)
|
domain = api.keystone.get_default_domain(self.request)
|
||||||
initial["domain_name"] = domain.name
|
initial["domain_name"] = domain.name
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve project domain.'),
|
_('Unable to retrieve project domain.'),
|
||||||
redirect=reverse(INDEX_URL))
|
redirect=reverse(INDEX_URL))
|
||||||
except Exception:
|
except Exception:
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve project details.'),
|
_('Unable to retrieve project details.'),
|
||||||
|
@ -43,7 +43,6 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
INDEX_URL = "horizon:identity:projects:index"
|
INDEX_URL = "horizon:identity:projects:index"
|
||||||
ADD_USER_URL = "horizon:identity:projects:create_user"
|
ADD_USER_URL = "horizon:identity:projects:create_user"
|
||||||
PROJECT_GROUP_ENABLED = keystone.VERSIONS.active >= 3
|
|
||||||
PROJECT_USER_MEMBER_SLUG = "update_members"
|
PROJECT_USER_MEMBER_SLUG = "update_members"
|
||||||
PROJECT_GROUP_MEMBER_SLUG = "update_group_members"
|
PROJECT_GROUP_MEMBER_SLUG = "update_group_members"
|
||||||
COMMON_HORIZONTAL_TEMPLATE = "identity/projects/_common_horizontal_form.html"
|
COMMON_HORIZONTAL_TEMPLATE = "identity/projects/_common_horizontal_form.html"
|
||||||
@ -232,12 +231,10 @@ class CreateProjectInfoAction(workflows.Action):
|
|||||||
super(CreateProjectInfoAction, self).__init__(request,
|
super(CreateProjectInfoAction, self).__init__(request,
|
||||||
*args,
|
*args,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
# For keystone V3, display the two fields in read-only
|
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
||||||
if keystone.VERSIONS.active >= 3:
|
self.fields["domain_id"].widget = readonlyInput
|
||||||
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
self.fields["domain_name"].widget = readonlyInput
|
||||||
self.fields["domain_id"].widget = readonlyInput
|
self.add_extra_fields()
|
||||||
self.fields["domain_name"].widget = readonlyInput
|
|
||||||
self.add_extra_fields()
|
|
||||||
|
|
||||||
def add_extra_fields(self):
|
def add_extra_fields(self):
|
||||||
# add extra column defined by setting
|
# add extra column defined by setting
|
||||||
@ -263,9 +260,8 @@ class CreateProjectInfo(workflows.Step):
|
|||||||
|
|
||||||
def __init__(self, workflow):
|
def __init__(self, workflow):
|
||||||
super(CreateProjectInfo, self).__init__(workflow)
|
super(CreateProjectInfo, self).__init__(workflow)
|
||||||
if keystone.VERSIONS.active >= 3:
|
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
self.contributes += tuple(EXTRA_INFO.keys())
|
||||||
self.contributes += tuple(EXTRA_INFO.keys())
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateProjectMembersAction(workflows.MembershipAction):
|
class UpdateProjectMembersAction(workflows.MembershipAction):
|
||||||
@ -478,10 +474,9 @@ class CreateProject(workflows.Workflow):
|
|||||||
|
|
||||||
def __init__(self, request=None, context_seed=None, entry_point=None,
|
def __init__(self, request=None, context_seed=None, entry_point=None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
if PROJECT_GROUP_ENABLED:
|
self.default_steps = (CreateProjectInfo,
|
||||||
self.default_steps = (CreateProjectInfo,
|
UpdateProjectMembers,
|
||||||
UpdateProjectMembers,
|
UpdateProjectGroups)
|
||||||
UpdateProjectGroups)
|
|
||||||
super(CreateProject, self).__init__(request=request,
|
super(CreateProject, self).__init__(request=request,
|
||||||
context_seed=context_seed,
|
context_seed=context_seed,
|
||||||
entry_point=entry_point,
|
entry_point=entry_point,
|
||||||
@ -499,11 +494,8 @@ class CreateProject(workflows.Workflow):
|
|||||||
domain_id = data['domain_id']
|
domain_id = data['domain_id']
|
||||||
try:
|
try:
|
||||||
# add extra information
|
# add extra information
|
||||||
if keystone.VERSIONS.active >= 3:
|
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
||||||
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
|
||||||
else:
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
desc = data['description']
|
desc = data['description']
|
||||||
self.object = api.keystone.tenant_create(request,
|
self.object = api.keystone.tenant_create(request,
|
||||||
@ -545,10 +537,7 @@ class CreateProject(workflows.Workflow):
|
|||||||
users_added += 1
|
users_added += 1
|
||||||
users_to_add -= users_added
|
users_to_add -= users_added
|
||||||
except Exception:
|
except Exception:
|
||||||
if PROJECT_GROUP_ENABLED:
|
group_msg = _(", add project groups")
|
||||||
group_msg = _(", add project groups")
|
|
||||||
else:
|
|
||||||
group_msg = ""
|
|
||||||
exceptions.handle(request,
|
exceptions.handle(request,
|
||||||
_('Failed to add %(users_to_add)s project '
|
_('Failed to add %(users_to_add)s project '
|
||||||
'members%(group_msg)s and set project quotas.')
|
'members%(group_msg)s and set project quotas.')
|
||||||
@ -591,8 +580,7 @@ class CreateProject(workflows.Workflow):
|
|||||||
return False
|
return False
|
||||||
project_id = project.id
|
project_id = project.id
|
||||||
self._update_project_members(request, data, project_id)
|
self._update_project_members(request, data, project_id)
|
||||||
if PROJECT_GROUP_ENABLED:
|
self._update_project_groups(request, data, project_id)
|
||||||
self._update_project_groups(request, data, project_id)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@ -640,9 +628,8 @@ class UpdateProjectInfo(workflows.Step):
|
|||||||
|
|
||||||
def __init__(self, workflow):
|
def __init__(self, workflow):
|
||||||
super(UpdateProjectInfo, self).__init__(workflow)
|
super(UpdateProjectInfo, self).__init__(workflow)
|
||||||
if keystone.VERSIONS.active >= 3:
|
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
self.contributes += tuple(EXTRA_INFO.keys())
|
||||||
self.contributes += tuple(EXTRA_INFO.keys())
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateProject(workflows.Workflow):
|
class UpdateProject(workflows.Workflow):
|
||||||
@ -657,10 +644,9 @@ class UpdateProject(workflows.Workflow):
|
|||||||
|
|
||||||
def __init__(self, request=None, context_seed=None, entry_point=None,
|
def __init__(self, request=None, context_seed=None, entry_point=None,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
if PROJECT_GROUP_ENABLED:
|
self.default_steps = (UpdateProjectInfo,
|
||||||
self.default_steps = (UpdateProjectInfo,
|
UpdateProjectMembers,
|
||||||
UpdateProjectMembers,
|
UpdateProjectGroups)
|
||||||
UpdateProjectGroups)
|
|
||||||
|
|
||||||
super(UpdateProject, self).__init__(request=request,
|
super(UpdateProject, self).__init__(request=request,
|
||||||
context_seed=context_seed,
|
context_seed=context_seed,
|
||||||
@ -685,11 +671,8 @@ class UpdateProject(workflows.Workflow):
|
|||||||
project_id = data['project_id']
|
project_id = data['project_id']
|
||||||
|
|
||||||
# add extra information
|
# add extra information
|
||||||
if keystone.VERSIONS.active >= 3:
|
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
|
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
||||||
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
|
||||||
else:
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
return api.keystone.tenant_update(
|
return api.keystone.tenant_update(
|
||||||
request,
|
request,
|
||||||
@ -832,10 +815,7 @@ class UpdateProject(workflows.Workflow):
|
|||||||
users_to_modify -= users_added
|
users_to_modify -= users_added
|
||||||
return True
|
return True
|
||||||
except Exception:
|
except Exception:
|
||||||
if PROJECT_GROUP_ENABLED:
|
group_msg = _(", update project groups")
|
||||||
group_msg = _(", update project groups")
|
|
||||||
else:
|
|
||||||
group_msg = ""
|
|
||||||
exceptions.handle(request,
|
exceptions.handle(request,
|
||||||
_('Failed to modify %(users_to_modify)s'
|
_('Failed to modify %(users_to_modify)s'
|
||||||
' project members%(group_msg)s and '
|
' project members%(group_msg)s and '
|
||||||
@ -935,10 +915,9 @@ class UpdateProject(workflows.Workflow):
|
|||||||
if not ret:
|
if not ret:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if PROJECT_GROUP_ENABLED:
|
ret = self._update_project_groups(request, data,
|
||||||
ret = self._update_project_groups(request, data,
|
project_id, domain_id)
|
||||||
project_id, domain_id)
|
if not ret:
|
||||||
if not ret:
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
@ -25,11 +26,7 @@ class Roles(horizon.Panel):
|
|||||||
policy_rules = (("identity", "identity:list_roles"),)
|
policy_rules = (("identity", "identity:list_roles"),)
|
||||||
|
|
||||||
def can_access(self, context):
|
def can_access(self, context):
|
||||||
if keystone.is_multi_domain_enabled() \
|
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
|
||||||
and not keystone.is_domain_admin(context['request']):
|
not keystone.is_domain_admin(context['request'])):
|
||||||
return False
|
return False
|
||||||
return super(Roles, self).can_access(context)
|
return super(Roles, self).can_access(context)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def can_register():
|
|
||||||
return keystone.VERSIONS.active >= 3
|
|
||||||
|
@ -35,7 +35,6 @@ from horizon.utils import validators
|
|||||||
from openstack_dashboard import api
|
from openstack_dashboard import api
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
PROJECT_REQUIRED = api.keystone.VERSIONS.active < 3
|
|
||||||
|
|
||||||
|
|
||||||
class PasswordMixin(forms.SelfHandlingForm):
|
class PasswordMixin(forms.SelfHandlingForm):
|
||||||
@ -72,12 +71,8 @@ class BaseUserForm(forms.SelfHandlingForm):
|
|||||||
default_project_id = kwargs['initial'].get('project', None)
|
default_project_id = kwargs['initial'].get('project', None)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
projects, has_more = api.keystone.tenant_list(
|
||||||
projects, has_more = api.keystone.tenant_list(
|
request, domain=domain_id)
|
||||||
request, domain=domain_id)
|
|
||||||
else:
|
|
||||||
projects, has_more = api.keystone.tenant_list(
|
|
||||||
request, user=user_id)
|
|
||||||
|
|
||||||
for project in sorted(projects, key=lambda p: p.name.lower()):
|
for project in sorted(projects, key=lambda p: p.name.lower()):
|
||||||
if project.enabled:
|
if project.enabled:
|
||||||
@ -96,14 +91,13 @@ class BaseUserForm(forms.SelfHandlingForm):
|
|||||||
|
|
||||||
class AddExtraColumnMixIn(object):
|
class AddExtraColumnMixIn(object):
|
||||||
def add_extra_fields(self, ordering=None):
|
def add_extra_fields(self, ordering=None):
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
# add extra column defined by setting
|
||||||
# add extra column defined by setting
|
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
|
for key, value in EXTRA_INFO.items():
|
||||||
for key, value in EXTRA_INFO.items():
|
self.fields[key] = forms.CharField(label=value,
|
||||||
self.fields[key] = forms.CharField(label=value,
|
required=False)
|
||||||
required=False)
|
if ordering:
|
||||||
if ordering:
|
ordering.append(key)
|
||||||
ordering.append(key)
|
|
||||||
|
|
||||||
|
|
||||||
ADD_PROJECT_URL = "horizon:identity:projects:create"
|
ADD_PROJECT_URL = "horizon:identity:projects:create"
|
||||||
@ -126,10 +120,10 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
|
|||||||
label=_("Email"),
|
label=_("Email"),
|
||||||
required=False)
|
required=False)
|
||||||
project = forms.ThemableDynamicChoiceField(label=_("Primary Project"),
|
project = forms.ThemableDynamicChoiceField(label=_("Primary Project"),
|
||||||
required=PROJECT_REQUIRED,
|
required=False,
|
||||||
add_item_link=ADD_PROJECT_URL)
|
add_item_link=ADD_PROJECT_URL)
|
||||||
role_id = forms.ThemableChoiceField(label=_("Role"),
|
role_id = forms.ThemableChoiceField(label=_("Role"),
|
||||||
required=PROJECT_REQUIRED)
|
required=False)
|
||||||
enabled = forms.BooleanField(label=_("Enabled"),
|
enabled = forms.BooleanField(label=_("Enabled"),
|
||||||
required=False,
|
required=False,
|
||||||
initial=True)
|
initial=True)
|
||||||
@ -155,13 +149,9 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
|
|||||||
self.fields['role_id'].choices = role_choices
|
self.fields['role_id'].choices = role_choices
|
||||||
|
|
||||||
# For keystone V3, display the two fields in read-only
|
# For keystone V3, display the two fields in read-only
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
||||||
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
self.fields["domain_id"].widget = readonlyInput
|
||||||
self.fields["domain_id"].widget = readonlyInput
|
self.fields["domain_name"].widget = readonlyInput
|
||||||
self.fields["domain_name"].widget = readonlyInput
|
|
||||||
# For keystone V2.0, hide description field
|
|
||||||
else:
|
|
||||||
self.fields["description"].widget = forms.HiddenInput()
|
|
||||||
|
|
||||||
# We have to protect the entire "data" dict because it contains the
|
# We have to protect the entire "data" dict because it contains the
|
||||||
# password and confirm_password strings.
|
# password and confirm_password strings.
|
||||||
@ -175,11 +165,8 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
|
|||||||
data['email'] = data['email'] or None
|
data['email'] = data['email'] or None
|
||||||
|
|
||||||
# add extra information
|
# add extra information
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
|
||||||
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
|
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
||||||
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
|
|
||||||
else:
|
|
||||||
kwargs = {}
|
|
||||||
|
|
||||||
if "lock_password" in data:
|
if "lock_password" in data:
|
||||||
kwargs.update({'options':
|
kwargs.update({'options':
|
||||||
@ -240,7 +227,7 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
|
|||||||
label=_("Email"),
|
label=_("Email"),
|
||||||
required=False)
|
required=False)
|
||||||
project = forms.ThemableChoiceField(label=_("Primary Project"),
|
project = forms.ThemableChoiceField(label=_("Primary Project"),
|
||||||
required=PROJECT_REQUIRED)
|
required=False)
|
||||||
|
|
||||||
lock_password = forms.BooleanField(label=_("Lock password"),
|
lock_password = forms.BooleanField(label=_("Lock password"),
|
||||||
required=False,
|
required=False,
|
||||||
@ -252,14 +239,9 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
|
|||||||
if api.keystone.keystone_can_edit_user() is False:
|
if api.keystone.keystone_can_edit_user() is False:
|
||||||
for field in ('name', 'email'):
|
for field in ('name', 'email'):
|
||||||
self.fields.pop(field)
|
self.fields.pop(field)
|
||||||
# For keystone V3, display the two fields in read-only
|
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.fields["domain_id"].widget = readonlyInput
|
||||||
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
|
self.fields["domain_name"].widget = readonlyInput
|
||||||
self.fields["domain_id"].widget = readonlyInput
|
|
||||||
self.fields["domain_name"].widget = readonlyInput
|
|
||||||
# For keystone V2.0, hide description field
|
|
||||||
else:
|
|
||||||
self.fields["description"].widget = forms.HiddenInput()
|
|
||||||
|
|
||||||
def handle(self, request, data):
|
def handle(self, request, data):
|
||||||
user = data.pop('id')
|
user = data.pop('id')
|
||||||
@ -267,7 +249,7 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
|
|||||||
data.pop('domain_id')
|
data.pop('domain_id')
|
||||||
data.pop('domain_name')
|
data.pop('domain_name')
|
||||||
|
|
||||||
if not PROJECT_REQUIRED and 'project' not in self.changed_data:
|
if 'project' not in self.changed_data:
|
||||||
data.pop('project')
|
data.pop('project')
|
||||||
|
|
||||||
if 'description' not in self.changed_data:
|
if 'description' not in self.changed_data:
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
import horizon
|
import horizon
|
||||||
@ -30,7 +31,7 @@ class Users(horizon.Panel):
|
|||||||
("identity", "identity:list_users"))
|
("identity", "identity:list_users"))
|
||||||
|
|
||||||
def can_access(self, context):
|
def can_access(self, context):
|
||||||
if keystone.is_multi_domain_enabled() \
|
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
|
||||||
and not keystone.is_domain_admin(context['request']):
|
not keystone.is_domain_admin(context['request'])):
|
||||||
return False
|
return False
|
||||||
return super(Users, self).can_access(context)
|
return super(Users, self).can_access(context)
|
||||||
|
@ -159,13 +159,10 @@ class DeleteUsersAction(policy.PolicyTargetMixin, tables.DeleteAction):
|
|||||||
|
|
||||||
|
|
||||||
class UserFilterAction(tables.FilterAction):
|
class UserFilterAction(tables.FilterAction):
|
||||||
if api.keystone.VERSIONS.active < 3:
|
filter_type = "server"
|
||||||
filter_type = "query"
|
filter_choices = (("name", _("User Name ="), True),
|
||||||
else:
|
("id", _("User ID ="), True),
|
||||||
filter_type = "server"
|
("enabled", _("Enabled ="), True, _('e.g. Yes/No')))
|
||||||
filter_choices = (("name", _("User Name ="), True),
|
|
||||||
("id", _("User ID ="), True),
|
|
||||||
("enabled", _("Enabled ="), True, _('e.g. Yes/No')))
|
|
||||||
|
|
||||||
|
|
||||||
class UpdateRow(tables.Row):
|
class UpdateRow(tables.Row):
|
||||||
@ -209,11 +206,9 @@ class UsersTable(tables.DataTable):
|
|||||||
filters=(defaultfilters.yesno,
|
filters=(defaultfilters.yesno,
|
||||||
defaultfilters.capfirst),
|
defaultfilters.capfirst),
|
||||||
empty_value="False")
|
empty_value="False")
|
||||||
|
domain_name = tables.Column('domain_name',
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
verbose_name=_('Domain Name'),
|
||||||
domain_name = tables.Column('domain_name',
|
attrs={'data-type': 'uuid'})
|
||||||
verbose_name=_('Domain Name'),
|
|
||||||
attrs={'data-type': 'uuid'})
|
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
name = "users"
|
name = "users"
|
||||||
|
@ -40,19 +40,18 @@ class OverviewTab(tabs.Tab):
|
|||||||
|
|
||||||
def _get_domain_name(self, user):
|
def _get_domain_name(self, user):
|
||||||
domain_name = ''
|
domain_name = ''
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
try:
|
||||||
try:
|
if policy.check((("identity", "identity:get_domain"),),
|
||||||
if policy.check((("identity", "identity:get_domain"),),
|
self.request):
|
||||||
self.request):
|
domain = api.keystone.domain_get(
|
||||||
domain = api.keystone.domain_get(
|
self.request, user.domain_id)
|
||||||
self.request, user.domain_id)
|
domain_name = domain.name
|
||||||
domain_name = domain.name
|
else:
|
||||||
else:
|
domain = api.keystone.get_default_domain(self.request)
|
||||||
domain = api.keystone.get_default_domain(self.request)
|
domain_name = domain.get('name')
|
||||||
domain_name = domain.get('name')
|
except Exception:
|
||||||
except Exception:
|
exceptions.handle(self.request,
|
||||||
exceptions.handle(self.request,
|
_('Unable to retrieve user domain.'))
|
||||||
_('Unable to retrieve user domain.'))
|
|
||||||
return domain_name
|
return domain_name
|
||||||
|
|
||||||
def _get_project_name(self, user):
|
def _get_project_name(self, user):
|
||||||
@ -67,12 +66,9 @@ class OverviewTab(tabs.Tab):
|
|||||||
{'project_id': project_id, 'reason': e})
|
{'project_id': project_id, 'reason': e})
|
||||||
|
|
||||||
def _get_extras(self, user):
|
def _get_extras(self, user):
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
extra_info = settings.USER_TABLE_EXTRA_INFO
|
||||||
extra_info = settings.USER_TABLE_EXTRA_INFO
|
return dict((display_key, getattr(user, key, ''))
|
||||||
return dict((display_key, getattr(user, key, ''))
|
for key, display_key in extra_info.items())
|
||||||
for key, display_key in extra_info.items())
|
|
||||||
else:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def get_context_data(self, request):
|
def get_context_data(self, request):
|
||||||
user = self.tab_group.kwargs['user']
|
user = self.tab_group.kwargs['user']
|
||||||
|
@ -143,12 +143,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
])
|
])
|
||||||
self.assertEqual(2, self.mock_get_default_domain.call_count)
|
self.assertEqual(2, self.mock_get_default_domain.call_count)
|
||||||
|
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=None)
|
|
||||||
|
|
||||||
kwargs = {'phone_num': phone_number}
|
kwargs = {'phone_num': phone_number}
|
||||||
self.mock_user_create.assert_called_once_with(
|
self.mock_user_create.assert_called_once_with(
|
||||||
@ -217,12 +213,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
mock.call(test.IsHttpRequest()),
|
mock.call(test.IsHttpRequest()),
|
||||||
mock.call(test.IsHttpRequest(), False),
|
mock.call(test.IsHttpRequest(), False),
|
||||||
])
|
])
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=user.id)
|
|
||||||
self.mock_user_create.assert_called_once_with(
|
self.mock_user_create.assert_called_once_with(
|
||||||
test.IsHttpRequest(),
|
test.IsHttpRequest(),
|
||||||
name=user.name,
|
name=user.name,
|
||||||
@ -276,14 +268,9 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_get_default_domain, 2,
|
self.mock_get_default_domain, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_tenant_list, 2,
|
||||||
self.mock_tenant_list, 2,
|
mock.call(test.IsHttpRequest(), domain=domain_id))
|
||||||
mock.call(test.IsHttpRequest(), domain=domain_id))
|
|
||||||
else:
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
|
||||||
self.mock_tenant_list, 2,
|
|
||||||
mock.call(test.IsHttpRequest(), user=None))
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_role_list, 2,
|
self.mock_role_list, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
@ -329,14 +316,9 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_get_default_domain, 2,
|
self.mock_get_default_domain, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_tenant_list, 2,
|
||||||
self.mock_tenant_list, 2,
|
mock.call(test.IsHttpRequest(), domain=domain_id))
|
||||||
mock.call(test.IsHttpRequest(), domain=domain_id))
|
|
||||||
else:
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
|
||||||
self.mock_tenant_list, 2,
|
|
||||||
mock.call(test.IsHttpRequest(), user=None))
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_role_list, 2,
|
self.mock_role_list, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
@ -382,14 +364,9 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_get_default_domain, 2,
|
self.mock_get_default_domain, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.mock_tenant_list, 2,
|
||||||
self.mock_tenant_list, 2,
|
mock.call(test.IsHttpRequest(), domain=domain_id))
|
||||||
mock.call(test.IsHttpRequest(), domain=domain_id))
|
|
||||||
else:
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
|
||||||
self.mock_tenant_list, 2,
|
|
||||||
mock.call(test.IsHttpRequest(), user=None))
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_role_list, 2,
|
self.mock_role_list, 2,
|
||||||
mock.call(test.IsHttpRequest()))
|
mock.call(test.IsHttpRequest()))
|
||||||
@ -493,12 +470,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
admin=True)
|
admin=True)
|
||||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
domain_id)
|
domain_id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=user.id)
|
|
||||||
kwargs = {'phone_num': phone_number}
|
kwargs = {'phone_num': phone_number}
|
||||||
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
||||||
user.id,
|
user.id,
|
||||||
@ -538,12 +511,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
admin=True)
|
admin=True)
|
||||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
domain_id)
|
domain_id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=user.id)
|
|
||||||
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
||||||
user.id,
|
user.id,
|
||||||
email=user.email,
|
email=user.email,
|
||||||
@ -581,12 +550,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
admin=True)
|
admin=True)
|
||||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
domain_id)
|
domain_id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=user.id)
|
|
||||||
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
||||||
user.id,
|
user.id,
|
||||||
email=user.email or "",
|
email=user.email or "",
|
||||||
@ -657,12 +622,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
admin=True)
|
admin=True)
|
||||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
domain_id)
|
domain_id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
test.IsHttpRequest(), domain=domain.id)
|
||||||
test.IsHttpRequest(), domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(
|
|
||||||
test.IsHttpRequest(), user=user.id)
|
|
||||||
self.assert_mock_multiple_calls_with_same_arguments(
|
self.assert_mock_multiple_calls_with_same_arguments(
|
||||||
self.mock_keystone_can_edit_user, 2,
|
self.mock_keystone_can_edit_user, 2,
|
||||||
mock.call())
|
mock.call())
|
||||||
@ -1339,12 +1300,8 @@ class UsersViewTests(test.BaseAdminViewTests):
|
|||||||
admin=True)
|
admin=True)
|
||||||
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
|
||||||
domain_id)
|
domain_id)
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
|
||||||
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
|
domain=domain.id)
|
||||||
domain=domain.id)
|
|
||||||
else:
|
|
||||||
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
|
|
||||||
user=user.id)
|
|
||||||
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
|
||||||
user.id,
|
user.id,
|
||||||
email=user.email,
|
email=user.email,
|
||||||
|
@ -95,10 +95,9 @@ class IndexView(tables.DataTableView):
|
|||||||
msg = _("Insufficient privilege level to view user information.")
|
msg = _("Insufficient privilege level to view user information.")
|
||||||
messages.info(self.request, msg)
|
messages.info(self.request, msg)
|
||||||
|
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
domain_lookup = api.keystone.domain_lookup(self.request)
|
||||||
domain_lookup = api.keystone.domain_lookup(self.request)
|
for u in users:
|
||||||
for u in users:
|
u.domain_name = domain_lookup.get(u.domain_id)
|
||||||
u.domain_name = domain_lookup.get(u.domain_id)
|
|
||||||
return users
|
return users
|
||||||
|
|
||||||
|
|
||||||
@ -134,20 +133,19 @@ class UpdateView(forms.ModalFormView):
|
|||||||
domain_id = getattr(user, "domain_id", None)
|
domain_id = getattr(user, "domain_id", None)
|
||||||
domain_name = ''
|
domain_name = ''
|
||||||
# Retrieve the domain name where the project belongs
|
# Retrieve the domain name where the project belongs
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
try:
|
||||||
try:
|
if policy.check((("identity", "identity:get_domain"),),
|
||||||
if policy.check((("identity", "identity:get_domain"),),
|
self.request):
|
||||||
self.request):
|
domain = api.keystone.domain_get(self.request, domain_id)
|
||||||
domain = api.keystone.domain_get(self.request, domain_id)
|
domain_name = domain.name
|
||||||
domain_name = domain.name
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
domain = api.keystone.get_default_domain(self.request)
|
domain = api.keystone.get_default_domain(self.request)
|
||||||
domain_name = domain.get('name')
|
domain_name = domain.get('name')
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
exceptions.handle(self.request,
|
exceptions.handle(self.request,
|
||||||
_('Unable to retrieve project domain.'))
|
_('Unable to retrieve project domain.'))
|
||||||
|
|
||||||
data = {'domain_id': domain_id,
|
data = {'domain_id': domain_id,
|
||||||
'domain_name': domain_name,
|
'domain_name': domain_name,
|
||||||
@ -157,9 +155,8 @@ class UpdateView(forms.ModalFormView):
|
|||||||
'email': getattr(user, 'email', None),
|
'email': getattr(user, 'email', None),
|
||||||
'description': getattr(user, 'description', None),
|
'description': getattr(user, 'description', None),
|
||||||
'lock_password': options.get("lock_password", False)}
|
'lock_password': options.get("lock_password", False)}
|
||||||
if api.keystone.VERSIONS.active >= 3:
|
for key in settings.USER_TABLE_EXTRA_INFO:
|
||||||
for key in settings.USER_TABLE_EXTRA_INFO:
|
data[key] = getattr(user, key, None)
|
||||||
data[key] = getattr(user, key, None)
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,8 +17,6 @@ from __future__ import absolute_import
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django import template
|
from django import template
|
||||||
|
|
||||||
from openstack_dashboard.api import keystone
|
|
||||||
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
@ -27,9 +25,10 @@ def is_multi_region_configured(request):
|
|||||||
return len(request.user.available_services_regions) > 1
|
return len(request.user.available_services_regions) > 1
|
||||||
|
|
||||||
|
|
||||||
|
# TODO(e0ne): pass OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT to the template
|
||||||
|
# context and remove `is_multidomain` template tag
|
||||||
def is_multidomain_supported():
|
def is_multidomain_supported():
|
||||||
return (keystone.VERSIONS.active >= 3 and
|
return settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT
|
||||||
settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT)
|
|
||||||
|
|
||||||
|
|
||||||
@register.simple_tag(takes_context=True)
|
@register.simple_tag(takes_context=True)
|
||||||
|
@ -36,86 +36,152 @@ from openstack_auth import user as auth_user
|
|||||||
from openstack_dashboard.test.test_data import utils
|
from openstack_dashboard.test.test_data import utils
|
||||||
|
|
||||||
|
|
||||||
# Dummy service catalog with all service.
|
# Dummy service catalog with all service. All data should match
|
||||||
|
# scoped_auth_ref.service_catalog.catalog from keystoneauth1.
|
||||||
# All endpoint URLs should point to example.com.
|
# All endpoint URLs should point to example.com.
|
||||||
# Try to keep them as accurate to real data as possible (ports, URIs, etc.)
|
# Try to keep them as accurate to real data as possible (ports, URIs, etc.)
|
||||||
|
# TODO(e0ne): make RegionOne and RegionTwo links unique.
|
||||||
SERVICE_CATALOG = [
|
SERVICE_CATALOG = [
|
||||||
{"type": "compute",
|
{"type": "compute",
|
||||||
"name": "nova",
|
"name": "nova",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.nova.example.com:8774/v2",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.nova.example.com:8774/v2",
|
"url": "http://admin.nova.example.com:8774/v2"},
|
||||||
"publicURL": "http://public.nova.example.com:8774/v2"},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.nova.example.com:8774/v2"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.nova.example.com:8774/v2"},
|
||||||
{"region": "RegionTwo",
|
{"region": "RegionTwo",
|
||||||
"adminURL": "http://admin.nova2.example.com:8774/v2",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.nova2.example.com:8774/v2",
|
"url": "http://admin.nova2.example.com:8774/v2"},
|
||||||
"publicURL": "http://public.nova2.example.com:8774/v2"}]},
|
{"region": "RegionTwo",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.nova2.example.com:8774/v2"},
|
||||||
|
{"region": "RegionTwo",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.nova2.example.com:8774/v2"}
|
||||||
|
]},
|
||||||
{"type": "volumev2",
|
{"type": "volumev2",
|
||||||
"name": "cinderv2",
|
"name": "cinderv2",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.cinder.example.com:8776/v2",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.cinder.example.com:8776/v2",
|
"url": "http://admin.cinder.example.com:8776/v2"},
|
||||||
"publicURL": "http://public.cinder.example.com:8776/v2"},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.cinder.example.com:8776/v2"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.cinder.example.com:8776/v2"},
|
||||||
{"region": "RegionTwo",
|
{"region": "RegionTwo",
|
||||||
"adminURL": "http://admin.cinder.example.com:8776/v2",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.cinder.example.com:8776/v2",
|
"url": "http://admin.cinder2.example.com:8776/v2"},
|
||||||
"publicURL": "http://public.cinder.example.com:8776/v2"}]},
|
{"region": "RegionTwo",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.cinder2.example.com:8776/v2"},
|
||||||
|
{"region": "RegionTwo",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.cinder.example.com:8776/v2"}
|
||||||
|
]},
|
||||||
{"type": "volumev3",
|
{"type": "volumev3",
|
||||||
"name": "cinderv3",
|
"name": "cinderv3",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.cinder.example.com:8776/v3",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.cinder.example.com:8776/v3",
|
"url": "http://admin.cinder.example.com:8776/v3"},
|
||||||
"publicURL": "http://public.cinder.example.com:8776/v3"},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.cinder.example.com:8776/v3"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.cinder.example.com:8776/v3"},
|
||||||
{"region": "RegionTwo",
|
{"region": "RegionTwo",
|
||||||
"adminURL": "http://admin.cinder.example.com:8776/v3",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.cinder.example.com:8776/v3",
|
"url": "http://admin.cinder2.example.com:8776/v3"},
|
||||||
"publicURL": "http://public.cinder.example.com:8776/v3"}]},
|
{"region": "RegionTwo",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.cinder2.example.com:8776/v3"},
|
||||||
|
{"region": "RegionTwo",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.cinder2.example.com:8776/v3"}
|
||||||
|
]},
|
||||||
{"type": "image",
|
{"type": "image",
|
||||||
"name": "glance",
|
"name": "glance",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.glance.example.com:9292",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.glance.example.com:9292",
|
"url": "http://admin.glance.example.com:9292",
|
||||||
"publicURL": "http://public.glance.example.com:9292"}]},
|
},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.glance.example.com:9292"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.glance.example.com:9292"}
|
||||||
|
]},
|
||||||
{"type": "identity",
|
{"type": "identity",
|
||||||
"name": "keystone",
|
"name": "keystone",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.keystone.example.com/identity/v3",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.keystone.example.com/identity/v3",
|
"url": "http://admin.keystone.example.com/identity/v3"},
|
||||||
"publicURL": "http://public.keystone.example.com/identity/v3"}]},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.keystone.example.com/identity/v3"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.keystone.example.com/identity/v3"}
|
||||||
|
]},
|
||||||
{"type": "object-store",
|
{"type": "object-store",
|
||||||
"name": "swift",
|
"name": "swift",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.swift.example.com:8080/",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.swift.example.com:8080/",
|
"url": "http://admin.swift.example.com:8080/"},
|
||||||
"publicURL": "http://public.swift.example.com:8080/"}]},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.swift.example.com:8080/"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.swift.example.com:8080/"}
|
||||||
|
]},
|
||||||
{"type": "network",
|
{"type": "network",
|
||||||
"name": "neutron",
|
"name": "neutron",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.neutron.example.com:9696/",
|
"interface": "admin",
|
||||||
"internalURL": "http://int.neutron.example.com:9696/",
|
"url": "http://admin.neutron.example.com:9696/"},
|
||||||
"publicURL": "http://public.neutron.example.com:9696/"}]},
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.neutron.example.com:9696/"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.neutron.example.com:9696/"}
|
||||||
|
]},
|
||||||
{"type": "ec2",
|
{"type": "ec2",
|
||||||
"name": "EC2 Service",
|
"name": "EC2 Service",
|
||||||
"endpoints_links": [],
|
"endpoints_links": [],
|
||||||
"endpoints": [
|
"endpoints": [
|
||||||
{"region": "RegionOne",
|
{"region": "RegionOne",
|
||||||
"adminURL": "http://admin.nova.example.com:8773/services/Admin",
|
"interface": "admin",
|
||||||
"publicURL": "http://public.nova.example.com:8773/services/Cloud",
|
"url": "http://admin.nova.example.com:8773/services/Admin"},
|
||||||
"internalURL": "http://int.nova.example.com:8773/services/Cloud"}]},
|
{"region": "RegionOne",
|
||||||
|
"interface": "public",
|
||||||
|
"url": "http://public.nova.example.com:8773/services/Cloud"},
|
||||||
|
{"region": "RegionOne",
|
||||||
|
"interface": "internal",
|
||||||
|
"url": "http://int.nova.example.com:8773/services/Cloud"}
|
||||||
|
]},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,12 +74,11 @@ class ServiceAPITests(test.APIMockTestCase):
|
|||||||
def test_service_wrapper(self):
|
def test_service_wrapper(self):
|
||||||
catalog = self.service_catalog
|
catalog = self.service_catalog
|
||||||
identity_data = api.base.get_service_from_catalog(catalog, "identity")
|
identity_data = api.base.get_service_from_catalog(catalog, "identity")
|
||||||
|
# 'Service' class below requires 'id', so populate it here.
|
||||||
identity_data['id'] = 1
|
identity_data['id'] = 1
|
||||||
region = identity_data["endpoints"][0]["region"]
|
service = api.keystone.Service(identity_data, "RegionOne")
|
||||||
service = api.keystone.Service(identity_data, region)
|
|
||||||
self.assertEqual(u"identity (native backend)", str(service))
|
self.assertEqual(u"identity (native backend)", str(service))
|
||||||
self.assertEqual(identity_data["endpoints"][0]["region"],
|
self.assertEqual("RegionOne", service.region)
|
||||||
service.region)
|
|
||||||
self.assertEqual("http://int.keystone.example.com/identity/v3",
|
self.assertEqual("http://int.keystone.example.com/identity/v3",
|
||||||
service.url)
|
service.url)
|
||||||
self.assertEqual("http://public.keystone.example.com/identity/v3",
|
self.assertEqual("http://public.keystone.example.com/identity/v3",
|
||||||
@ -89,12 +88,11 @@ class ServiceAPITests(test.APIMockTestCase):
|
|||||||
def test_service_wrapper_service_in_region(self):
|
def test_service_wrapper_service_in_region(self):
|
||||||
catalog = self.service_catalog
|
catalog = self.service_catalog
|
||||||
compute_data = api.base.get_service_from_catalog(catalog, "compute")
|
compute_data = api.base.get_service_from_catalog(catalog, "compute")
|
||||||
|
# 'Service' class below requires 'id', so populate it here.
|
||||||
compute_data['id'] = 1
|
compute_data['id'] = 1
|
||||||
region = compute_data["endpoints"][1]["region"]
|
service = api.keystone.Service(compute_data, 'RegionTwo')
|
||||||
service = api.keystone.Service(compute_data, region)
|
|
||||||
self.assertEqual(u"compute", str(service))
|
self.assertEqual(u"compute", str(service))
|
||||||
self.assertEqual(compute_data["endpoints"][1]["region"],
|
self.assertEqual("RegionTwo", service.region)
|
||||||
service.region)
|
|
||||||
self.assertEqual("http://int.nova2.example.com:8774/v2",
|
self.assertEqual("http://int.nova2.example.com:8774/v2",
|
||||||
service.url)
|
service.url)
|
||||||
self.assertEqual("http://public.nova2.example.com:8774/v2",
|
self.assertEqual("http://public.nova2.example.com:8774/v2",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user