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:
Ivan Kolodyazhny 2020-04-10 17:15:39 +03:00 committed by Akihiro Motoki
parent 50837618bd
commit ee6fa9a245
29 changed files with 377 additions and 570 deletions

View File

@ -100,7 +100,7 @@ class Login(django_auth_forms.AuthenticationForm):
# if websso is enabled and keystone version supported
# prepend the websso_choices select input to the form
if utils.is_websso_enabled():
if settings.WEBSSO_ENABLED:
initial = settings.WEBSSO_INITIAL_CHOICE
self.fields['auth_type'] = forms.ChoiceField(
label=_("Authenticate using"),

View File

@ -967,7 +967,6 @@ class OpenStackAuthTestsWebSSO(OpenStackAuthTestsMixin, test.TestCase):
(settings.OPENSTACK_KEYSTONE_URL, protocol, origin))
url = reverse('login')
# POST to the page and redirect to keystone.
response = self.client.get(url)
self.assertRedirects(response, redirect_url, status_code=302,

View File

@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from django.conf import settings
from django.conf.urls import url
from django.views import generic
@ -37,7 +38,7 @@ if utils.allow_expired_passowrd_change():
name='password')
)
if utils.is_websso_enabled():
if settings.WEBSSO_ENABLED:
urlpatterns += [
url(r"^websso/$", views.websso, name='websso'),
url(r"^error/$",

View File

@ -187,8 +187,7 @@ class User(models.AbstractBaseUser, models.AnonymousUser):
.. attribute:: password_expires_at
Password expiration date. This attribute could be None when using
keystone version < 3.0 or if the feature is not enabled in keystone.
Password expiration date.
"""

View File

@ -136,33 +136,6 @@ def allow_expired_passowrd_change():
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):
"""Ensure absolute_uri are relative to WEBROOT."""
webroot = settings.WEBROOT

View File

@ -56,10 +56,10 @@ def login(request):
# If the user enabled websso and the default redirect
# redirect to the default websso url
if (request.method == 'GET' and utils.is_websso_enabled and
utils.is_websso_default_redirect()):
protocol = utils.get_websso_default_redirect_protocol()
region = utils.get_websso_default_redirect_region()
if (request.method == 'GET' and settings.WEBSSO_ENABLED and
settings.WEBSSO_DEFAULT_REDIRECT):
protocol = settings.WEBSSO_DEFAULT_REDIRECT_PROTOCOL
region = settings.WEBSSO_DEFAULT_REDIRECT_REGION
origin = utils.build_absolute_uri(request, '/auth/websso/')
url = ('%s/auth/OS-FEDERATION/websso/%s?origin=%s' %
(region, protocol, origin))
@ -70,7 +70,7 @@ def login(request):
if request.method == 'POST':
auth_type = request.POST.get('auth_type', 'credentials')
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')
auth_url = getattr(settings, 'WEBSSO_KEYSTONE_URL', None)
if auth_url is None:
@ -105,7 +105,7 @@ def login(request):
extra_context = {
'redirect_field_name': auth.REDIRECT_FIELD_NAME,
'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():
@ -171,7 +171,7 @@ def websso(request):
request.user = auth.authenticate(request, auth_url=auth_url,
token=token)
except exceptions.KeystoneAuthException as exc:
if utils.is_websso_default_redirect():
if settings.WEBSSO_DEFAULT_REDIRECT:
res = django_http.HttpResponseRedirect(settings.LOGIN_ERROR)
else:
msg = 'Login failed: %s' % exc
@ -202,11 +202,11 @@ def logout(request, login_url=None, **kwargs):
LOG.info(msg)
""" Securely logs a user out. """
if (utils.is_websso_enabled and utils.is_websso_default_redirect() and
utils.get_websso_default_redirect_logout()):
if (settings.WEBSSO_ENABLED and settings.WEBSSO_DEFAULT_REDIRECT and
settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT):
auth_user.unset_session_user_variables(request)
return django_http.HttpResponseRedirect(
utils.get_websso_default_redirect_logout())
settings.WEBSSO_DEFAULT_REDIRECT_LOGOUT)
else:
return django_auth_views.logout_then_login(request,
login_url=login_url,

View File

@ -293,17 +293,9 @@ def get_service_from_catalog(catalog, service_type):
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
# TODO(e0ne): remove this mapping once OPENSTACK_ENDPOINT_TYPE config option
# will be removed.
ENDPOINT_TYPE_TO_INTERFACE = {
'publicURL': 'public',
'internalURL': 'internal',
@ -315,31 +307,25 @@ def get_url_for_service(service, region, endpoint_type):
if 'type' not in service:
return None
identity_version = get_version_from_service(service)
service_endpoints = service.get('endpoints', [])
available_endpoints = [endpoint for endpoint in service_endpoints
if region == _get_endpoint_region(endpoint)]
"""if we are dealing with the identity service and there is no endpoint
in the current region, it is okay to use the first endpoint for any
identity service endpoints and we can assume that it is global
"""
# if we are dealing with the identity service and there is no endpoint
# in the current region, it is okay to use the first endpoint for any
# identity service endpoints and we can assume that it is global
if service['type'] == 'identity' and not available_endpoints:
available_endpoints = [endpoint for endpoint in service_endpoints]
for endpoint in available_endpoints:
try:
if identity_version < 3:
return endpoint.get(endpoint_type)
else:
interface = \
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
if endpoint.get('interface') == interface:
return endpoint.get('url')
except (IndexError, KeyError):
interface = \
ENDPOINT_TYPE_TO_INTERFACE.get(endpoint_type, '')
if endpoint['interface'] == interface:
return endpoint['url']
except KeyError:
# it could be that the current endpoint just doesn't match the
# type, continue trying the next one
pass
return None
def url_for(request, service_type, endpoint_type=None, region=None):

View File

@ -146,7 +146,7 @@ def keystoneclient(request, admin=False):
user = request.user
token_id = user.token.id
if is_multi_domain_enabled():
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
is_domain_context_specified = bool(
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_name = request.session.get("domain_context_name", None)
# if running in Keystone V3 or later
if VERSIONS.active >= 3 and domain_id is None:
if domain_id is None:
# if no domain context set, default to user's domain
domain_id = request.user.user_domain_id
domain_name = request.user.user_domain_name
@ -861,15 +860,6 @@ def get_version():
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,
enabled=False, remote_ids=None):
manager = keystoneclient(request, admin=True).federation.identity_providers

View File

@ -24,10 +24,6 @@ class ApplicationCredentialsPanel(horizon.Panel):
slug = 'application_credentials'
policy_rules = (('identity', 'identity:list_application_credentials'),)
@staticmethod
def can_register():
return keystone.VERSIONS.active >= 3
def can_access(self, context):
request = context['request']
keystone_version = keystone.get_identity_api_version(request)

View File

@ -16,8 +16,6 @@ from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import keystone
class Domains(horizon.Panel):
name = _("Domains")
@ -25,10 +23,6 @@ class Domains(horizon.Panel):
policy_rules = (("identity", "identity:get_domain"),
("identity", "identity:list_domains"))
@staticmethod
def can_register():
return keystone.VERSIONS.active >= 3
def can_access(self, context):
request = context['request']
domain_token = request.session.get('domain_token')

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import horizon
@ -24,12 +25,8 @@ class Groups(horizon.Panel):
slug = 'groups'
policy_rules = (("identity", "identity:list_groups"),)
@staticmethod
def can_register():
return keystone.VERSIONS.active >= 3
def can_access(self, context):
if keystone.is_multi_domain_enabled() \
and not keystone.is_domain_admin(context['request']):
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
not keystone.is_domain_admin(context['request'])):
return False
return super(Groups, self).can_access(context)

View File

@ -243,15 +243,10 @@ class GroupsViewTests(test.BaseAdminViewTests):
self.mock_group_get.assert_called_once_with(test.IsHttpRequest(),
group.id)
if api.keystone.VERSIONS.active >= 3:
self.mock_get_effective_domain_id.assert_called_once_with(
test.IsHttpRequest())
self.mock_user_list.assert_called_once_with(
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_get_effective_domain_id.assert_called_once_with(
test.IsHttpRequest())
self.mock_user_list.assert_called_once_with(
test.IsHttpRequest(), group=group.id, domain=domain_id)
@test.create_mocks({api.keystone: ('get_effective_domain_id',
'user_list',
@ -271,15 +266,10 @@ class GroupsViewTests(test.BaseAdminViewTests):
self.assertRedirectsNoFollow(res, GROUP_MANAGE_URL)
self.assertMessageCount(success=1)
if api.keystone.VERSIONS.active >= 3:
self.mock_get_effective_domain_id.assert_called_once_with(
test.IsHttpRequest())
self.mock_user_list.assert_called_once_with(
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_get_effective_domain_id.assert_called_once_with(
test.IsHttpRequest())
self.mock_user_list.assert_called_once_with(
test.IsHttpRequest(), group=group.id, domain=domain_id)
self.mock_remove_group_user.assert_called_once_with(
test.IsHttpRequest(),

View File

@ -12,12 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import keystone
class IdentityProviders(horizon.Panel):
name = _("Identity Providers")
@ -26,5 +25,4 @@ class IdentityProviders(horizon.Panel):
@staticmethod
def can_register():
return (keystone.VERSIONS.active >= 3 and
keystone.is_federation_management_enabled())
return settings.OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT

View File

@ -12,12 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import keystone
class Mappings(horizon.Panel):
name = _("Mappings")
@ -26,5 +25,4 @@ class Mappings(horizon.Panel):
@staticmethod
def can_register():
return (keystone.VERSIONS.active >= 3 and
keystone.is_federation_management_enabled())
return settings.OPENSTACK_KEYSTONE_FEDERATION_MANAGEMENT

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.template import defaultfilters as filters
from django.urls import reverse
from django.utils.http import urlencode
@ -62,7 +63,7 @@ class UpdateMembersLink(tables.LinkAction):
return "?".join([base_url, param])
def allowed(self, request, project):
if api.keystone.is_multi_domain_enabled():
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
# domain admin or cloud admin = True
# project admin or member = False
return api.keystone.is_domain_admin(request)
@ -79,7 +80,7 @@ class UpdateGroupsLink(tables.LinkAction):
policy_rules = (("identity", "identity:list_groups"),)
def allowed(self, request, project):
if api.keystone.is_multi_domain_enabled():
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
# domain admin or cloud admin = True
# project admin or member = False
return api.keystone.is_domain_admin(request)
@ -114,7 +115,7 @@ class CreateProject(tables.LinkAction):
policy_rules = (('identity', 'identity:create_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
# project admin or member = False
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"),)
def allowed(self, request, project):
if api.keystone.is_multi_domain_enabled():
if settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT:
# domain admin or cloud admin = True
# project admin or member = False
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"),)
def allowed(self, request, project):
if api.keystone.is_multi_domain_enabled() \
and not api.keystone.is_domain_admin(request):
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
not api.keystone.is_domain_admin(request)):
return False
return api.keystone.keystone_can_edit_project()
@ -220,11 +221,8 @@ class TenantsTable(tables.DataTable):
widget=forms.Textarea(attrs={'rows': 4}),
required=False))
id = tables.Column('id', verbose_name=_('Project ID'))
if api.keystone.VERSIONS.active >= 3:
domain_name = tables.Column(
'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,
filters=(filters.yesno, filters.capfirst),
form_field=forms.BooleanField(

View File

@ -41,28 +41,24 @@ class OverviewTab(tabs.Tab):
def _get_domain_name(self, project):
domain_name = ''
if api.keystone.VERSIONS.active >= 3:
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(
self.request, project.domain_id)
domain_name = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'))
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(
self.request, project.domain_id)
domain_name = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'))
return domain_name
def _get_extras(self, project):
if api.keystone.VERSIONS.active >= 3:
extra_info = settings.PROJECT_TABLE_EXTRA_INFO
return dict((display_key, getattr(project, key, ''))
for key, display_key in extra_info.items())
else:
return {}
extra_info = settings.PROJECT_TABLE_EXTRA_INFO
return dict((display_key, getattr(project, key, ''))
for key, display_key in extra_info.items())
class UsersTab(tabs.TableTab):

View File

@ -541,15 +541,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
'role_list',
'role_assignments_list')})
def test_update_project_get(self):
keystone_api_version = api.keystone.VERSIONS.active
project = self.tenants.first()
default_role = self.roles.first()
domain_id = project.domain_id
users = self._get_all_users(domain_id)
groups = self._get_all_groups(domain_id)
roles = self.roles.list()
proj_users = self._get_proj_users(project.id)
role_assignments = self._get_proj_role_assignment(project.id)
self.mock_tenant_get.return_value = project
@ -564,13 +561,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.mock_role_list.return_value = roles
self.mock_group_list.return_value = groups
if keystone_api_version >= 3:
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
self.mock_role_assignments_list.return_value = role_assignments
url = reverse('horizon:identity:projects:update',
args=[self.tenant.id])
@ -609,16 +600,10 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.mock_group_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain_id)
if keystone_api_version >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 2,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
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()
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 2,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
self.mock_roles_for_user.assert_not_called()
@test.create_mocks({api.keystone: ('tenant_get',
'domain_get',
@ -636,13 +621,10 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
'role_list',
'role_assignments_list')})
def test_update_project_save(self):
keystone_api_version = api.keystone.VERSIONS.active
project = self.tenants.first()
default_role = self.roles.first()
domain_id = project.domain_id
users = self._get_all_users(domain_id)
proj_users = self._get_proj_users(project.id)
groups = self._get_all_groups(domain_id)
roles = self.roles.list()
role_assignments = self._get_proj_role_assignment(project.id)
@ -670,16 +652,6 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
expected_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 + "2"] = ['2'] # member role
# Group assignment form data
@ -716,95 +688,67 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
expected_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
# warning message
workflow_data[USER_ROLE_PREFIX + "1"] = ['3']
# admin role with attempt to remove current admin, results in
# warning message
workflow_data[USER_ROLE_PREFIX + "1"] = ['3']
# member role
workflow_data[USER_ROLE_PREFIX + "2"] = ['1', '3']
# member role
workflow_data[USER_ROLE_PREFIX + "2"] = ['1', '3']
# admin role
workflow_data[GROUP_ROLE_PREFIX + "1"] = ['2', '3']
# admin role
workflow_data[GROUP_ROLE_PREFIX + "1"] = ['2', '3']
# member role
workflow_data[GROUP_ROLE_PREFIX + "2"] = ['1', '2', '3']
self.mock_role_assignments_list.return_value = role_assignments
# Give user 1 role 2
retvals_add_tenant_user_role.append(None)
expected_add_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='1',
role='2',))
# remove role 2 from user 2
retvals_remove_tenant_user_role.append(None)
expected_remove_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='2',
role='2'))
# member role
workflow_data[GROUP_ROLE_PREFIX + "2"] = ['1', '2', '3']
self.mock_role_assignments_list.return_value = role_assignments
# Give user 1 role 2
retvals_add_tenant_user_role.append(None)
expected_add_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='1',
role='2',))
# remove role 2 from user 2
retvals_remove_tenant_user_role.append(None)
expected_remove_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='2',
role='2'))
# Give user 3 role 1
retvals_add_tenant_user_role.append(None)
expected_add_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='3',
role='1'))
retvals_group_list.append(groups)
expected_group_list.append(
mock.call(test.IsHttpRequest(),
domain=self.domain.id,
project=self.tenant.id))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='1',
project=self.tenant.id))
retvals_remove_group_role.append(None)
expected_remove_group_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
group='1',
role='1'))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='2',
project=self.tenant.id))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='3',
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'))
# Give user 3 role 1
retvals_add_tenant_user_role.append(None)
expected_add_tenant_user_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
user='3',
role='1'))
retvals_group_list.append(groups)
expected_group_list.append(
mock.call(test.IsHttpRequest(),
domain=self.domain.id,
project=self.tenant.id))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='1',
project=self.tenant.id))
retvals_remove_group_role.append(None)
expected_remove_group_role.append(
mock.call(test.IsHttpRequest(),
project=self.tenant.id,
group='1',
role='1'))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='2',
project=self.tenant.id))
retvals_roles_for_group.append(roles)
expected_roles_for_group.append(
mock.call(test.IsHttpRequest(),
group='3',
project=self.tenant.id))
# submit form data
project_data = {"domain_id": project._info["domain_id"],
@ -859,12 +803,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
_check_mock_calls(self.mock_remove_group_role,
expected_remove_group_role)
if keystone_api_version >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 3,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
else:
self.mock_role_assignments_list.assert_not_called()
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 3,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
@test.create_mocks({api.keystone: ('tenant_get',)})
def test_update_project_get_error(self):
@ -895,8 +836,6 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
'role_list',
'role_assignments_list')})
def test_update_project_tenant_update_error(self):
keystone_api_version = api.keystone.VERSIONS.active
project = self.tenants.first()
default_role = self.roles.first()
domain_id = project.domain_id
@ -925,16 +864,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
expected_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
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))
self.mock_role_assignments_list.return_value = role_assignments
role_ids = [role.id for role in roles]
for user in proj_users:
@ -992,12 +922,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertEqual(len(expected_roles_for_user),
self.mock_roles_for_user.call_count)
if keystone_api_version >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 2,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
else:
self.mock_role_assignments_list.assert_not_called()
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_assignments_list, 2,
mock.call(test.IsHttpRequest(), project=self.tenant.id))
self.mock_get_effective_domain_id.assert_called_once_with(
test.IsHttpRequest())

View File

@ -131,10 +131,9 @@ class IndexView(tables.DataTableView):
_("Insufficient privilege level to view project information.")
messages.info(self.request, msg)
if api.keystone.VERSIONS.active >= 3:
domain_lookup = api.keystone.domain_lookup(self.request)
for t in tenants:
t.domain_name = domain_lookup.get(t.domain_id)
domain_lookup = api.keystone.domain_lookup(self.request)
for t in tenants:
t.domain_name = domain_lookup.get(t.domain_id)
return tenants
@ -182,28 +181,27 @@ class UpdateProjectView(workflows.WorkflowView):
for field in PROJECT_INFO_FIELDS:
initial[field] = getattr(project_info, field, None)
if keystone.VERSIONS.active >= 3:
# get extra columns info
ex_info = settings.PROJECT_TABLE_EXTRA_INFO
for ex_field in ex_info:
initial[ex_field] = getattr(project_info, ex_field, None)
# get extra columns info
ex_info = settings.PROJECT_TABLE_EXTRA_INFO
for ex_field in ex_info:
initial[ex_field] = getattr(project_info, ex_field, None)
# Retrieve the domain name where the project belong
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(self.request,
initial["domain_id"])
initial["domain_name"] = domain.name
# Retrieve the domain name where the project belong
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(self.request,
initial["domain_id"])
initial["domain_name"] = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
initial["domain_name"] = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
initial["domain_name"] = domain.name
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'),
redirect=reverse(INDEX_URL))
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'),
redirect=reverse(INDEX_URL))
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project details.'),

View File

@ -43,7 +43,6 @@ LOG = logging.getLogger(__name__)
INDEX_URL = "horizon:identity:projects:index"
ADD_USER_URL = "horizon:identity:projects:create_user"
PROJECT_GROUP_ENABLED = keystone.VERSIONS.active >= 3
PROJECT_USER_MEMBER_SLUG = "update_members"
PROJECT_GROUP_MEMBER_SLUG = "update_group_members"
COMMON_HORIZONTAL_TEMPLATE = "identity/projects/_common_horizontal_form.html"
@ -232,12 +231,10 @@ class CreateProjectInfoAction(workflows.Action):
super(CreateProjectInfoAction, self).__init__(request,
*args,
**kwargs)
# For keystone V3, display the two fields in read-only
if keystone.VERSIONS.active >= 3:
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
self.fields["domain_id"].widget = readonlyInput
self.fields["domain_name"].widget = readonlyInput
self.add_extra_fields()
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
self.fields["domain_id"].widget = readonlyInput
self.fields["domain_name"].widget = readonlyInput
self.add_extra_fields()
def add_extra_fields(self):
# add extra column defined by setting
@ -263,9 +260,8 @@ class CreateProjectInfo(workflows.Step):
def __init__(self, workflow):
super(CreateProjectInfo, self).__init__(workflow)
if keystone.VERSIONS.active >= 3:
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
self.contributes += tuple(EXTRA_INFO.keys())
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
self.contributes += tuple(EXTRA_INFO.keys())
class UpdateProjectMembersAction(workflows.MembershipAction):
@ -478,10 +474,9 @@ class CreateProject(workflows.Workflow):
def __init__(self, request=None, context_seed=None, entry_point=None,
*args, **kwargs):
if PROJECT_GROUP_ENABLED:
self.default_steps = (CreateProjectInfo,
UpdateProjectMembers,
UpdateProjectGroups)
self.default_steps = (CreateProjectInfo,
UpdateProjectMembers,
UpdateProjectGroups)
super(CreateProject, self).__init__(request=request,
context_seed=context_seed,
entry_point=entry_point,
@ -499,11 +494,8 @@ class CreateProject(workflows.Workflow):
domain_id = data['domain_id']
try:
# add extra information
if keystone.VERSIONS.active >= 3:
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
else:
kwargs = {}
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
desc = data['description']
self.object = api.keystone.tenant_create(request,
@ -545,10 +537,7 @@ class CreateProject(workflows.Workflow):
users_added += 1
users_to_add -= users_added
except Exception:
if PROJECT_GROUP_ENABLED:
group_msg = _(", add project groups")
else:
group_msg = ""
group_msg = _(", add project groups")
exceptions.handle(request,
_('Failed to add %(users_to_add)s project '
'members%(group_msg)s and set project quotas.')
@ -591,8 +580,7 @@ class CreateProject(workflows.Workflow):
return False
project_id = 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
@ -640,9 +628,8 @@ class UpdateProjectInfo(workflows.Step):
def __init__(self, workflow):
super(UpdateProjectInfo, self).__init__(workflow)
if keystone.VERSIONS.active >= 3:
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
self.contributes += tuple(EXTRA_INFO.keys())
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
self.contributes += tuple(EXTRA_INFO.keys())
class UpdateProject(workflows.Workflow):
@ -657,10 +644,9 @@ class UpdateProject(workflows.Workflow):
def __init__(self, request=None, context_seed=None, entry_point=None,
*args, **kwargs):
if PROJECT_GROUP_ENABLED:
self.default_steps = (UpdateProjectInfo,
UpdateProjectMembers,
UpdateProjectGroups)
self.default_steps = (UpdateProjectInfo,
UpdateProjectMembers,
UpdateProjectGroups)
super(UpdateProject, self).__init__(request=request,
context_seed=context_seed,
@ -685,11 +671,8 @@ class UpdateProject(workflows.Workflow):
project_id = data['project_id']
# add extra information
if keystone.VERSIONS.active >= 3:
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
else:
kwargs = {}
EXTRA_INFO = settings.PROJECT_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
return api.keystone.tenant_update(
request,
@ -832,10 +815,7 @@ class UpdateProject(workflows.Workflow):
users_to_modify -= users_added
return True
except Exception:
if PROJECT_GROUP_ENABLED:
group_msg = _(", update project groups")
else:
group_msg = ""
group_msg = _(", update project groups")
exceptions.handle(request,
_('Failed to modify %(users_to_modify)s'
' project members%(group_msg)s and '
@ -935,10 +915,9 @@ class UpdateProject(workflows.Workflow):
if not ret:
return False
if PROJECT_GROUP_ENABLED:
ret = self._update_project_groups(request, data,
project_id, domain_id)
if not ret:
return False
ret = self._update_project_groups(request, data,
project_id, domain_id)
if not ret:
return False
return True

View File

@ -12,6 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import horizon
@ -25,11 +26,7 @@ class Roles(horizon.Panel):
policy_rules = (("identity", "identity:list_roles"),)
def can_access(self, context):
if keystone.is_multi_domain_enabled() \
and not keystone.is_domain_admin(context['request']):
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
not keystone.is_domain_admin(context['request'])):
return False
return super(Roles, self).can_access(context)
@staticmethod
def can_register():
return keystone.VERSIONS.active >= 3

View File

@ -35,7 +35,6 @@ from horizon.utils import validators
from openstack_dashboard import api
LOG = logging.getLogger(__name__)
PROJECT_REQUIRED = api.keystone.VERSIONS.active < 3
class PasswordMixin(forms.SelfHandlingForm):
@ -72,12 +71,8 @@ class BaseUserForm(forms.SelfHandlingForm):
default_project_id = kwargs['initial'].get('project', None)
try:
if api.keystone.VERSIONS.active >= 3:
projects, has_more = api.keystone.tenant_list(
request, domain=domain_id)
else:
projects, has_more = api.keystone.tenant_list(
request, user=user_id)
projects, has_more = api.keystone.tenant_list(
request, domain=domain_id)
for project in sorted(projects, key=lambda p: p.name.lower()):
if project.enabled:
@ -96,14 +91,13 @@ class BaseUserForm(forms.SelfHandlingForm):
class AddExtraColumnMixIn(object):
def add_extra_fields(self, ordering=None):
if api.keystone.VERSIONS.active >= 3:
# add extra column defined by setting
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
for key, value in EXTRA_INFO.items():
self.fields[key] = forms.CharField(label=value,
required=False)
if ordering:
ordering.append(key)
# add extra column defined by setting
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
for key, value in EXTRA_INFO.items():
self.fields[key] = forms.CharField(label=value,
required=False)
if ordering:
ordering.append(key)
ADD_PROJECT_URL = "horizon:identity:projects:create"
@ -126,10 +120,10 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
label=_("Email"),
required=False)
project = forms.ThemableDynamicChoiceField(label=_("Primary Project"),
required=PROJECT_REQUIRED,
required=False,
add_item_link=ADD_PROJECT_URL)
role_id = forms.ThemableChoiceField(label=_("Role"),
required=PROJECT_REQUIRED)
required=False)
enabled = forms.BooleanField(label=_("Enabled"),
required=False,
initial=True)
@ -155,13 +149,9 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
self.fields['role_id'].choices = role_choices
# For keystone V3, display the two fields in read-only
if api.keystone.VERSIONS.active >= 3:
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
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()
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
self.fields["domain_id"].widget = readonlyInput
self.fields["domain_name"].widget = readonlyInput
# We have to protect the entire "data" dict because it contains the
# password and confirm_password strings.
@ -175,11 +165,8 @@ class CreateUserForm(PasswordMixin, BaseUserForm, AddExtraColumnMixIn):
data['email'] = data['email'] or None
# add extra information
if api.keystone.VERSIONS.active >= 3:
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
else:
kwargs = {}
EXTRA_INFO = settings.USER_TABLE_EXTRA_INFO
kwargs = dict((key, data.get(key)) for key in EXTRA_INFO)
if "lock_password" in data:
kwargs.update({'options':
@ -240,7 +227,7 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
label=_("Email"),
required=False)
project = forms.ThemableChoiceField(label=_("Primary Project"),
required=PROJECT_REQUIRED)
required=False)
lock_password = forms.BooleanField(label=_("Lock password"),
required=False,
@ -252,14 +239,9 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
if api.keystone.keystone_can_edit_user() is False:
for field in ('name', 'email'):
self.fields.pop(field)
# For keystone V3, display the two fields in read-only
if api.keystone.VERSIONS.active >= 3:
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
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()
readonlyInput = forms.TextInput(attrs={'readonly': 'readonly'})
self.fields["domain_id"].widget = readonlyInput
self.fields["domain_name"].widget = readonlyInput
def handle(self, request, data):
user = data.pop('id')
@ -267,7 +249,7 @@ class UpdateUserForm(BaseUserForm, AddExtraColumnMixIn):
data.pop('domain_id')
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')
if 'description' not in self.changed_data:

View File

@ -16,6 +16,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
import horizon
@ -30,7 +31,7 @@ class Users(horizon.Panel):
("identity", "identity:list_users"))
def can_access(self, context):
if keystone.is_multi_domain_enabled() \
and not keystone.is_domain_admin(context['request']):
if (settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT and
not keystone.is_domain_admin(context['request'])):
return False
return super(Users, self).can_access(context)

View File

@ -159,13 +159,10 @@ class DeleteUsersAction(policy.PolicyTargetMixin, tables.DeleteAction):
class UserFilterAction(tables.FilterAction):
if api.keystone.VERSIONS.active < 3:
filter_type = "query"
else:
filter_type = "server"
filter_choices = (("name", _("User Name ="), True),
("id", _("User ID ="), True),
("enabled", _("Enabled ="), True, _('e.g. Yes/No')))
filter_type = "server"
filter_choices = (("name", _("User Name ="), True),
("id", _("User ID ="), True),
("enabled", _("Enabled ="), True, _('e.g. Yes/No')))
class UpdateRow(tables.Row):
@ -209,11 +206,9 @@ class UsersTable(tables.DataTable):
filters=(defaultfilters.yesno,
defaultfilters.capfirst),
empty_value="False")
if api.keystone.VERSIONS.active >= 3:
domain_name = tables.Column('domain_name',
verbose_name=_('Domain Name'),
attrs={'data-type': 'uuid'})
domain_name = tables.Column('domain_name',
verbose_name=_('Domain Name'),
attrs={'data-type': 'uuid'})
class Meta(object):
name = "users"

View File

@ -40,19 +40,18 @@ class OverviewTab(tabs.Tab):
def _get_domain_name(self, user):
domain_name = ''
if api.keystone.VERSIONS.active >= 3:
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(
self.request, user.domain_id)
domain_name = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user domain.'))
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(
self.request, user.domain_id)
domain_name = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve user domain.'))
return domain_name
def _get_project_name(self, user):
@ -67,12 +66,9 @@ class OverviewTab(tabs.Tab):
{'project_id': project_id, 'reason': e})
def _get_extras(self, user):
if api.keystone.VERSIONS.active >= 3:
extra_info = settings.USER_TABLE_EXTRA_INFO
return dict((display_key, getattr(user, key, ''))
for key, display_key in extra_info.items())
else:
return {}
extra_info = settings.USER_TABLE_EXTRA_INFO
return dict((display_key, getattr(user, key, ''))
for key, display_key in extra_info.items())
def get_context_data(self, request):
user = self.tab_group.kwargs['user']

View File

@ -143,12 +143,8 @@ class UsersViewTests(test.BaseAdminViewTests):
])
self.assertEqual(2, self.mock_get_default_domain.call_count)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=None)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
kwargs = {'phone_num': phone_number}
self.mock_user_create.assert_called_once_with(
@ -217,12 +213,8 @@ class UsersViewTests(test.BaseAdminViewTests):
mock.call(test.IsHttpRequest()),
mock.call(test.IsHttpRequest(), False),
])
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=user.id)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
self.mock_user_create.assert_called_once_with(
test.IsHttpRequest(),
name=user.name,
@ -276,14 +268,9 @@ class UsersViewTests(test.BaseAdminViewTests):
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_get_default_domain, 2,
mock.call(test.IsHttpRequest()))
if api.keystone.VERSIONS.active >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_tenant_list, 2,
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.mock_tenant_list, 2,
mock.call(test.IsHttpRequest(), domain=domain_id))
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_list, 2,
mock.call(test.IsHttpRequest()))
@ -329,14 +316,9 @@ class UsersViewTests(test.BaseAdminViewTests):
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_get_default_domain, 2,
mock.call(test.IsHttpRequest()))
if api.keystone.VERSIONS.active >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_tenant_list, 2,
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.mock_tenant_list, 2,
mock.call(test.IsHttpRequest(), domain=domain_id))
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_list, 2,
mock.call(test.IsHttpRequest()))
@ -382,14 +364,9 @@ class UsersViewTests(test.BaseAdminViewTests):
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_get_default_domain, 2,
mock.call(test.IsHttpRequest()))
if api.keystone.VERSIONS.active >= 3:
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_tenant_list, 2,
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.mock_tenant_list, 2,
mock.call(test.IsHttpRequest(), domain=domain_id))
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_role_list, 2,
mock.call(test.IsHttpRequest()))
@ -493,12 +470,8 @@ class UsersViewTests(test.BaseAdminViewTests):
admin=True)
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
domain_id)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=user.id)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
kwargs = {'phone_num': phone_number}
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
user.id,
@ -538,12 +511,8 @@ class UsersViewTests(test.BaseAdminViewTests):
admin=True)
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
domain_id)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=user.id)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
user.id,
email=user.email,
@ -581,12 +550,8 @@ class UsersViewTests(test.BaseAdminViewTests):
admin=True)
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
domain_id)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=user.id)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
user.id,
email=user.email or "",
@ -657,12 +622,8 @@ class UsersViewTests(test.BaseAdminViewTests):
admin=True)
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
domain_id)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), user=user.id)
self.mock_tenant_list.assert_called_once_with(
test.IsHttpRequest(), domain=domain.id)
self.assert_mock_multiple_calls_with_same_arguments(
self.mock_keystone_can_edit_user, 2,
mock.call())
@ -1339,12 +1300,8 @@ class UsersViewTests(test.BaseAdminViewTests):
admin=True)
self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(),
domain_id)
if api.keystone.VERSIONS.active >= 3:
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
domain=domain.id)
else:
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
user=user.id)
self.mock_tenant_list.assert_called_once_with(test.IsHttpRequest(),
domain=domain.id)
self.mock_user_update.assert_called_once_with(test.IsHttpRequest(),
user.id,
email=user.email,

View File

@ -95,10 +95,9 @@ class IndexView(tables.DataTableView):
msg = _("Insufficient privilege level to view user information.")
messages.info(self.request, msg)
if api.keystone.VERSIONS.active >= 3:
domain_lookup = api.keystone.domain_lookup(self.request)
for u in users:
u.domain_name = domain_lookup.get(u.domain_id)
domain_lookup = api.keystone.domain_lookup(self.request)
for u in users:
u.domain_name = domain_lookup.get(u.domain_id)
return users
@ -134,20 +133,19 @@ class UpdateView(forms.ModalFormView):
domain_id = getattr(user, "domain_id", None)
domain_name = ''
# Retrieve the domain name where the project belongs
if api.keystone.VERSIONS.active >= 3:
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(self.request, domain_id)
domain_name = domain.name
try:
if policy.check((("identity", "identity:get_domain"),),
self.request):
domain = api.keystone.domain_get(self.request, domain_id)
domain_name = domain.name
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
else:
domain = api.keystone.get_default_domain(self.request)
domain_name = domain.get('name')
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'))
except Exception:
exceptions.handle(self.request,
_('Unable to retrieve project domain.'))
data = {'domain_id': domain_id,
'domain_name': domain_name,
@ -157,9 +155,8 @@ class UpdateView(forms.ModalFormView):
'email': getattr(user, 'email', None),
'description': getattr(user, 'description', None),
'lock_password': options.get("lock_password", False)}
if api.keystone.VERSIONS.active >= 3:
for key in settings.USER_TABLE_EXTRA_INFO:
data[key] = getattr(user, key, None)
for key in settings.USER_TABLE_EXTRA_INFO:
data[key] = getattr(user, key, None)
return data

View File

@ -17,8 +17,6 @@ from __future__ import absolute_import
from django.conf import settings
from django import template
from openstack_dashboard.api import keystone
register = template.Library()
@ -27,9 +25,10 @@ def is_multi_region_configured(request):
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():
return (keystone.VERSIONS.active >= 3 and
settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT)
return settings.OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT
@register.simple_tag(takes_context=True)

View File

@ -36,86 +36,152 @@ from openstack_auth import user as auth_user
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.
# Try to keep them as accurate to real data as possible (ports, URIs, etc.)
# TODO(e0ne): make RegionOne and RegionTwo links unique.
SERVICE_CATALOG = [
{"type": "compute",
"name": "nova",
"endpoints_links": [],
"endpoints": [
{"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"},
"interface": "admin",
"url": "http://admin.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",
"adminURL": "http://admin.nova2.example.com:8774/v2",
"internalURL": "http://int.nova2.example.com:8774/v2",
"publicURL": "http://public.nova2.example.com:8774/v2"}]},
"interface": "admin",
"url": "http://admin.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",
"name": "cinderv2",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.cinder.example.com:8776/v2",
"internalURL": "http://int.cinder.example.com:8776/v2",
"publicURL": "http://public.cinder.example.com:8776/v2"},
"interface": "admin",
"url": "http://admin.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",
"adminURL": "http://admin.cinder.example.com:8776/v2",
"internalURL": "http://int.cinder.example.com:8776/v2",
"publicURL": "http://public.cinder.example.com:8776/v2"}]},
"interface": "admin",
"url": "http://admin.cinder2.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",
"name": "cinderv3",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.cinder.example.com:8776/v3",
"internalURL": "http://int.cinder.example.com:8776/v3",
"publicURL": "http://public.cinder.example.com:8776/v3"},
"interface": "admin",
"url": "http://admin.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",
"adminURL": "http://admin.cinder.example.com:8776/v3",
"internalURL": "http://int.cinder.example.com:8776/v3",
"publicURL": "http://public.cinder.example.com:8776/v3"}]},
"interface": "admin",
"url": "http://admin.cinder2.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",
"name": "glance",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.glance.example.com:9292",
"internalURL": "http://int.glance.example.com:9292",
"publicURL": "http://public.glance.example.com:9292"}]},
"interface": "admin",
"url": "http://admin.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",
"name": "keystone",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.keystone.example.com/identity/v3",
"internalURL": "http://int.keystone.example.com/identity/v3",
"publicURL": "http://public.keystone.example.com/identity/v3"}]},
"interface": "admin",
"url": "http://admin.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",
"name": "swift",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.swift.example.com:8080/",
"internalURL": "http://int.swift.example.com:8080/",
"publicURL": "http://public.swift.example.com:8080/"}]},
"interface": "admin",
"url": "http://admin.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",
"name": "neutron",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.neutron.example.com:9696/",
"internalURL": "http://int.neutron.example.com:9696/",
"publicURL": "http://public.neutron.example.com:9696/"}]},
"interface": "admin",
"url": "http://admin.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",
"name": "EC2 Service",
"endpoints_links": [],
"endpoints": [
{"region": "RegionOne",
"adminURL": "http://admin.nova.example.com:8773/services/Admin",
"publicURL": "http://public.nova.example.com:8773/services/Cloud",
"internalURL": "http://int.nova.example.com:8773/services/Cloud"}]},
"interface": "admin",
"url": "http://admin.nova.example.com:8773/services/Admin"},
{"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"}
]},
]

View File

@ -74,12 +74,11 @@ class ServiceAPITests(test.APIMockTestCase):
def test_service_wrapper(self):
catalog = self.service_catalog
identity_data = api.base.get_service_from_catalog(catalog, "identity")
# 'Service' class below requires 'id', so populate it here.
identity_data['id'] = 1
region = identity_data["endpoints"][0]["region"]
service = api.keystone.Service(identity_data, region)
service = api.keystone.Service(identity_data, "RegionOne")
self.assertEqual(u"identity (native backend)", str(service))
self.assertEqual(identity_data["endpoints"][0]["region"],
service.region)
self.assertEqual("RegionOne", service.region)
self.assertEqual("http://int.keystone.example.com/identity/v3",
service.url)
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):
catalog = self.service_catalog
compute_data = api.base.get_service_from_catalog(catalog, "compute")
# 'Service' class below requires 'id', so populate it here.
compute_data['id'] = 1
region = compute_data["endpoints"][1]["region"]
service = api.keystone.Service(compute_data, region)
service = api.keystone.Service(compute_data, 'RegionTwo')
self.assertEqual(u"compute", str(service))
self.assertEqual(compute_data["endpoints"][1]["region"],
service.region)
self.assertEqual("RegionTwo", service.region)
self.assertEqual("http://int.nova2.example.com:8774/v2",
service.url)
self.assertEqual("http://public.nova2.example.com:8774/v2",