Adding the ability to set/use domain context

Setting the domain context allows admins to view the identity
resources (projects, users, groups) for a particular domain.
The context can be set or cleared.  The default is no domain
context set.  If no context set, the current behavior of listing
all resources across domains is maintained.

Additionally, the identity panels have been grouped in a new
PanelGroup called Identity Panel to logically separate this
functionality from other service related panels.

Implements: blueprint domain-context

Change-Id: I5dd6279129824971968c20fd30919b109bf6b00a
This commit is contained in:
David Lyle 2013-06-05 08:24:03 -06:00
parent f827bf9b79
commit 87084f7af8
21 changed files with 471 additions and 92 deletions

View File

@ -0,0 +1,11 @@
{% load i18n %}
{% block page_header %}
<div class='page-header'>
<h2>
{% if request.session.domain_context_name %}
<em>{{ request.session.domain_context_name }}:</em>
{% endif %}
{{ title }}
</h2>
</div>
{% endblock %}

View File

@ -23,14 +23,19 @@ class SystemPanels(horizon.PanelGroup):
slug = "admin"
name = _("System Panel")
panels = ('overview', 'hypervisors', 'instances', 'volumes', 'flavors',
'images', 'domains', 'projects', 'users', 'groups',
'roles', 'networks', 'routers', 'info')
'images', 'networks', 'routers', 'info')
class IdentityPanels(horizon.PanelGroup):
slug = "identity"
name = _("Identity Panel")
panels = ('domains', 'projects', 'users', 'groups', 'roles')
class Admin(horizon.Dashboard):
name = _("Admin")
slug = "admin"
panels = (SystemPanels,)
panels = (SystemPanels, IdentityPanels)
default_panel = 'overview'
permissions = ('openstack.roles.admin',)

View File

@ -26,6 +26,7 @@ from horizon import tables
from openstack_dashboard import api
from .constants import DOMAINS_CREATE_URL
from .constants import DOMAINS_INDEX_URL
from .constants import DOMAINS_UPDATE_URL
@ -85,6 +86,51 @@ class DomainFilterAction(tables.FilterAction):
return filter(comp, domains)
class SetDomainContext(tables.Action):
name = "set_domain_context"
verbose_name = _("Set Domain Context")
url = DOMAINS_INDEX_URL
preempt = True
def allowed(self, request, datum):
ctx = request.session.get("domain_context", None)
if ctx and datum.id == ctx:
return False
return True
def single(self, table, request, obj_id):
if ('domain_context' not in request.session or
request.session['domain_context'] != obj_id):
try:
domain = api.keystone.domain_get(request, obj_id)
request.session['domain_context'] = obj_id
request.session['domain_context_name'] = domain.name
messages.success(request,
_('Domain Context updated to Domain %s.') %
domain.name)
except:
messages.error(request,
_('Unable to set Domain Context.'))
class UnsetDomainContext(tables.Action):
name = "clear_domain_context"
verbose_name = _("Clear Domain Context")
url = DOMAINS_INDEX_URL
preempt = True
requires_input = False
def allowed(self, request, datum):
ctx = request.session.get("domain_context", None)
return ctx is not None
def single(self, table, request, obj_id):
if 'domain_context' in request.session:
request.session.pop("domain_context")
request.session.pop("domain_context_name")
messages.success(request, _('Domain Context cleared.'))
class DomainsTable(tables.DataTable):
name = tables.Column('name', verbose_name=_('Name'))
description = tables.Column(lambda obj: getattr(obj, 'description', None),
@ -95,6 +141,6 @@ class DomainsTable(tables.DataTable):
class Meta:
name = "domains"
verbose_name = _("Domains")
row_actions = (EditDomainLink, DeleteDomainsAction)
row_actions = (SetDomainContext, EditDomainLink, DeleteDomainsAction)
table_actions = (DomainFilterAction, CreateDomainLink,
DeleteDomainsAction)
DeleteDomainsAction, UnsetDomainContext)

View File

@ -3,7 +3,7 @@
{% block title %}{% trans "Domains" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Domains") %}
{% include "horizon/common/_domain_page_header.html" with title=_("Domains") %}
{% endblock page_header %}
{% block main %}

View File

@ -100,6 +100,32 @@ class DomainsViewTests(test.BaseAdminViewTests):
self.assertRedirectsNoFollow(res, DOMAINS_INDEX_URL)
self.assertMessageCount(error=2)
@test.create_stubs({api.keystone: ('domain_get',
'domain_list', )})
def test_set_clear_domain_context(self):
domain = self.domains.get(id="1")
api.keystone.domain_get(IgnoreArg(), domain.id).AndReturn(domain)
api.keystone.domain_get(IgnoreArg(), domain.id).AndReturn(domain)
api.keystone.domain_list(IgnoreArg()).AndReturn(self.domains.list())
self.mox.ReplayAll()
formData = {'action': 'domains__set_domain_context__%s' % domain.id}
res = self.client.post(DOMAINS_INDEX_URL, formData)
self.assertTemplateUsed(res, DOMAINS_INDEX_VIEW_TEMPLATE)
self.assertItemsEqual(res.context['table'].data, [domain, ])
self.assertContains(res, "<em>test_domain:</em>")
formData = {'action': 'domains__clear_domain_context__%s' % domain.id}
res = self.client.post(DOMAINS_INDEX_URL, formData)
self.assertTemplateUsed(res, DOMAINS_INDEX_VIEW_TEMPLATE)
self.assertItemsEqual(res.context['table'].data, self.domains.list())
self.assertNotContains(res, "<em>test_domain:</em>")
class CreateDomainWorkflowTests(test.BaseAdminViewTests):
def _get_domain_info(self, domain):

View File

@ -37,8 +37,14 @@ class IndexView(tables.DataTableView):
def get_data(self):
domains = []
domain_context = self.request.session.get('domain_context', None)
try:
domains = api.keystone.domain_list(self.request)
if domain_context:
domain = api.keystone.domain_get(self.request,
domain_context)
domains.append(domain)
else:
domains = api.keystone.domain_list(self.request)
except:
exceptions.handle(self.request,
_('Unable to retrieve domain list.'))

View File

@ -38,11 +38,10 @@ class CreateGroupForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
LOG.info('Creating group with name "%s"' % data['name'])
# TODO(lin-hua-cheng): Set the domain_id with the value from the
# Domain scope.
domain_context = request.session.get('domain_context', None)
new_group = api.keystone.group_create(
request,
domain_id=None,
domain_id=domain_context,
name=data['name'],
description=data['description'])
messages.success(request,

View File

@ -3,7 +3,7 @@
{% block title %}{% trans "Groups" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Groups") %}
{% include "horizon/common/_domain_page_header.html" with title=_("Groups") %}
{% endblock page_header %}
{% block main %}

View File

@ -40,25 +40,51 @@ GROUP_ADD_MEMBER_URL = reverse(add_member_url, args=[1])
class GroupsViewTests(test.BaseAdminViewTests):
def _get_domain_id(self):
return self.request.session.get('domain_context', None)
def _get_groups(self, domain_id):
if not domain_id:
groups = self.groups.list()
else:
groups = [group for group in self.groups.list()
if group.domain_id == domain_id]
return groups
@test.create_stubs({api.keystone: ('group_list',)})
def test_index(self):
api.keystone.group_list(IgnoreArg()).AndReturn(self.groups.list())
domain_id = self._get_domain_id()
groups = self._get_groups(domain_id)
api.keystone.group_list(IgnoreArg()).AndReturn(groups)
self.mox.ReplayAll()
res = self.client.get(GROUPS_INDEX_URL)
self.assertTemplateUsed(res, GROUPS_INDEX_VIEW_TEMPLATE)
self.assertItemsEqual(res.context['table'].data, self.groups.list())
self.assertItemsEqual(res.context['table'].data, groups)
if domain_id:
for group in res.context['table'].data:
self.assertItemsEqual(group.domain_id, domain_id)
self.assertContains(res, 'Create Group')
self.assertContains(res, 'Edit')
self.assertContains(res, 'Delete Group')
def test_index_with_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_index()
@test.create_stubs({api.keystone: ('group_list',
'keystone_can_edit_group')})
def test_index_with_keystone_can_edit_group_false(self):
api.keystone.group_list(IgnoreArg()).AndReturn(self.groups.list())
domain_id = self._get_domain_id()
groups = self._get_groups(domain_id)
api.keystone.group_list(IgnoreArg()).AndReturn(groups)
api.keystone.keystone_can_edit_group() \
.MultipleTimes().AndReturn(False)
@ -67,7 +93,7 @@ class GroupsViewTests(test.BaseAdminViewTests):
res = self.client.get(GROUPS_INDEX_URL)
self.assertTemplateUsed(res, GROUPS_INDEX_VIEW_TEMPLATE)
self.assertItemsEqual(res.context['table'].data, self.groups.list())
self.assertItemsEqual(res.context['table'].data, groups)
self.assertNotContains(res, 'Create Group')
self.assertNotContains(res, 'Edit')
@ -75,11 +101,12 @@ class GroupsViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('group_create', )})
def test_create(self):
domain_id = self._get_domain_id()
group = self.groups.get(id="1")
api.keystone.group_create(IsA(http.HttpRequest),
description=group.description,
domain_id=None,
domain_id=domain_id,
name=group.name).AndReturn(group)
self.mox.ReplayAll()
@ -92,6 +119,12 @@ class GroupsViewTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertMessageCount(success=1)
def test_create_with_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_create()
@test.create_stubs({api.keystone: ('group_get',
'group_update')})
def test_update(self):

View File

@ -44,8 +44,17 @@ class IndexView(tables.DataTableView):
def get_data(self):
groups = []
domain_context = self.request.session.get('domain_context', None)
try:
# TODO(dklyle): once keystoneclient supports filtering by
# domain change this to use that cleaner method
groups = api.keystone.group_list(self.request)
if domain_context:
domain_groups = []
for group in groups:
if group.domain_id == domain_context:
domain_groups.append(group)
groups = domain_groups
except:
exceptions.handle(self.request,
_('Unable to retrieve group list.'))

View File

@ -3,7 +3,7 @@
{% block title %}{% trans "Projects" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Projects") %}
{% include "horizon/common/_domain_page_header.html" with title=_("Projects") %}
{% endblock page_header %}
{% block main %}

View File

@ -3,9 +3,7 @@
{% block title %}{% trans "Project Usage Overview" %}{% endblock %}
{% block page_header %}
<div class='page-header'>
<h2>{% trans "Project Usage" %}</h2>
</div>
{% include "horizon/common/_domain_page_header.html" with title=_("Project Usage") %}
{% endblock %}
{% block main %}

View File

@ -31,27 +31,47 @@ from openstack_dashboard.usage import quotas
from .workflows import CreateProject
from .workflows import UpdateProject
INDEX_URL = reverse('horizon:admin:projects:index')
@test.create_stubs({api.keystone: ('tenant_list',)})
class TenantsViewTests(test.BaseAdminViewTests):
def test_index(self):
api.keystone.tenant_list(IsA(http.HttpRequest), paginate=True) \
.AndReturn([self.tenants.list(), False])
api.keystone.tenant_list(IsA(http.HttpRequest),
domain=None,
paginate=True) \
.AndReturn([self.tenants.list(), False])
self.mox.ReplayAll()
res = self.client.get(INDEX_URL)
self.assertTemplateUsed(res, 'admin/projects/index.html')
self.assertItemsEqual(res.context['table'].data, self.tenants.list())
@test.create_stubs({api.keystone: ('tenant_list', )})
def test_index_with_domain_context(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
domain_tenants = [tenant for tenant in self.tenants.list()
if tenant.domain_id == domain.id]
api.keystone.tenant_list(IsA(http.HttpRequest),
domain=domain.id) \
.AndReturn(domain_tenants)
self.mox.ReplayAll()
res = self.client.get(INDEX_URL)
self.assertTemplateUsed(res, 'admin/projects/index.html')
self.assertItemsEqual(res.context['table'].data, domain_tenants)
self.assertContains(res, "<em>test_domain:</em>")
class CreateProjectWorkflowTests(test.BaseAdminViewTests):
def _get_project_info(self, project):
domain_id = self.request.session.get('domain_context', None)
project_info = {"name": project.name,
"description": project.description,
"enabled": project.enabled}
"enabled": project.enabled,
"domain": domain_id}
return project_info
def _get_workflow_fields(self, project):
@ -75,6 +95,17 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project_info.update(quota_data)
return project_info
def _get_domain_id(self):
return self.request.session.get('domain_context', None)
def _get_all_users(self, domain_id):
if not domain_id:
users = self.users.list()
else:
users = [user for user in self.users.list()
if user.domain_id == domain_id]
return users
@test.create_stubs({api.keystone: ('get_default_role',
'user_list',
'role_list'),
@ -82,7 +113,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
def test_add_project_get(self):
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
quotas.get_default_quota_data(IsA(http.HttpRequest)).AndReturn(quota)
@ -90,7 +122,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
# init
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
self.mox.ReplayAll()
@ -112,6 +145,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
'<UpdateProjectMembers: update_members>',
'<UpdateProjectQuota: update_quotas>'])
def test_add_project_get_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_get()
@test.create_stubs({api.keystone: ('get_default_role',
'add_tenant_user_role',
'tenant_create',
@ -124,7 +163,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -132,7 +172,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
# contribute
@ -178,13 +219,20 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_add_project_post_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_post()
@test.create_stubs({api.keystone: ('user_list',
'role_list',
'get_default_role'),
quotas: ('get_default_quota_data',)})
def test_add_project_quota_defaults_error(self):
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -193,7 +241,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
self.mox.ReplayAll()
@ -204,6 +253,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertTemplateUsed(res, WorkflowView.template_name)
self.assertContains(res, "Unable to retrieve default quota values")
def test_add_project_quota_defaults_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_quota_defaults_error()
@test.create_stubs({api.keystone: ('tenant_create',
'user_list',
'role_list',
@ -213,7 +268,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -221,7 +277,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
# contribute
@ -243,6 +300,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_add_project_tenant_create_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_tenant_create_error()
@test.create_stubs({api.keystone: ('tenant_create',
'user_list',
'role_list',
@ -254,7 +317,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -262,7 +326,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
# contribute
@ -304,6 +369,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_add_project_quota_update_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_quota_update_error()
@test.create_stubs({api.keystone: ('tenant_create',
'user_list',
'role_list',
@ -316,7 +387,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -324,7 +396,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
# contribute
@ -335,7 +408,7 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
quota_data = self._get_quota_info(quota)
api.keystone.tenant_create(IsA(http.HttpRequest), **project_details) \
.AndReturn(project)
.AndReturn(project)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
@ -374,6 +447,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_add_project_user_update_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_user_update_error()
@test.create_stubs({api.keystone: ('user_list',
'role_list',
'get_default_role'),
@ -382,7 +461,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# init
@ -390,7 +470,8 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
# contribute
@ -406,6 +487,12 @@ class CreateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertContains(res, "field is required")
def test_add_project_missing_field_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_add_project_missing_field_error()
class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
def _get_quota_info(self, quota):
@ -417,6 +504,21 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
quota_data[field] = int(cinder_quota.get(field).limit)
return quota_data
def _get_domain_id(self):
return self.request.session.get('domain_context', None)
def _get_all_users(self, domain_id):
if not domain_id:
users = self.users.list()
else:
users = [user for user in self.users.list()
if user.domain_id == domain_id]
return users
def _get_proj_users(self, project_id):
return [user for user in self.users.list()
if user.project_id == project_id]
@test.create_stubs({api.keystone: ('get_default_role',
'roles_for_user',
'tenant_get',
@ -427,7 +529,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
api.keystone.tenant_get(IsA(http.HttpRequest),
@ -439,7 +542,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
for user in users:
@ -470,6 +574,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
'<UpdateProjectMembers: update_members>',
'<UpdateProjectQuota: update_quotas>'])
def test_update_project_get_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_update_project_get()
@test.create_stubs({api.keystone: ('tenant_get',
'tenant_update',
'get_default_role',
@ -485,7 +595,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
proj_users = self._get_proj_users(project.id)
roles = self.roles.list()
# get/init
@ -498,7 +610,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
workflow_data = {}
@ -532,7 +645,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
api.keystone.user_list(IsA(http.HttpRequest),
project=self.tenant.id).AndReturn(users)
project=self.tenant.id).AndReturn(proj_users)
# admin user - try to remove all roles on current project, warning
api.keystone.roles_for_user(IsA(http.HttpRequest), '1',
@ -584,9 +697,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
# submit form data
project_data = {"name": project._info["name"],
"id": project.id,
"description": project._info["description"],
"enabled": project.enabled}
"id": project.id,
"description": project._info["description"],
"enabled": project.enabled}
workflow_data.update(project_data)
workflow_data.update(updated_quota)
url = reverse('horizon:admin:projects:update',
@ -597,6 +710,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertMessageCount(error=0, warning=1)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_update_project_save_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_update_project_save()
@test.create_stubs({api.keystone: ('tenant_get',)})
def test_update_project_get_error(self):
@ -626,7 +745,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
roles = self.roles.list()
# get/init
@ -639,7 +759,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
workflow_data = {}
@ -676,9 +797,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
# submit form data
project_data = {"name": project._info["name"],
"id": project.id,
"description": project._info["description"],
"enabled": project.enabled}
"id": project.id,
"description": project._info["description"],
"enabled": project.enabled}
workflow_data.update(project_data)
workflow_data.update(updated_quota)
url = reverse('horizon:admin:projects:update',
@ -688,6 +809,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_update_project_tenant_update_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_update_project_tenant_update_error()
@test.create_stubs({api.keystone: ('tenant_get',
'tenant_update',
'get_default_role',
@ -702,7 +829,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
proj_users = self._get_proj_users(project.id)
roles = self.roles.list()
# get/init
@ -715,7 +844,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
workflow_data = {}
@ -751,7 +881,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
api.keystone.user_list(IsA(http.HttpRequest),
project=self.tenant.id).AndReturn(users)
project=self.tenant.id).AndReturn(proj_users)
# admin user - try to remove all roles on current project, warning
api.keystone.roles_for_user(IsA(http.HttpRequest), '1',
@ -797,6 +927,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertMessageCount(error=1, warning=0)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_update_project_quota_update_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_update_project_quota_update_error()
@test.create_stubs({api.keystone: ('tenant_get',
'tenant_update',
'get_default_role',
@ -810,7 +946,9 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
project = self.tenants.first()
quota = self.quotas.first()
default_role = self.roles.first()
users = self.users.list()
domain_id = self._get_domain_id()
users = self._get_all_users(domain_id)
proj_users = self._get_proj_users(project.id)
roles = self.roles.list()
# get/init
@ -823,7 +961,8 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.get_default_role(IsA(http.HttpRequest)) \
.AndReturn(default_role)
api.keystone.user_list(IsA(http.HttpRequest)).AndReturn(users)
api.keystone.user_list(IsA(http.HttpRequest), domain=domain_id) \
.AndReturn(users)
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
workflow_data = {}
@ -856,7 +995,7 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
api.keystone.role_list(IsA(http.HttpRequest)).AndReturn(roles)
api.keystone.user_list(IsA(http.HttpRequest),
project=self.tenant.id).AndReturn(users)
project=self.tenant.id).AndReturn(proj_users)
# admin user - try to remove all roles on current project, warning
api.keystone.roles_for_user(IsA(http.HttpRequest), '1',
@ -893,6 +1032,12 @@ class UpdateProjectWorkflowTests(test.BaseAdminViewTests):
self.assertMessageCount(error=1, warning=0)
self.assertRedirectsNoFollow(res, INDEX_URL)
def test_update_project_member_update_error_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_update_project_member_update_error()
@test.create_stubs({api.keystone: ('get_default_role', 'tenant_get'),
quotas: ('get_tenant_quota_data',)})
def test_update_project_when_default_role_does_not_exist(self):

View File

@ -80,11 +80,13 @@ class IndexView(tables.DataTableView):
tenants = []
marker = self.request.GET.get(
TenantsTable._meta.pagination_param, None)
domain_context = self.request.session.get('domain_context', None)
try:
tenants, self._more = api.keystone.tenant_list(
self.request,
paginate=True,
marker=marker)
self.request,
domain=domain_context,
paginate=True,
marker=marker)
except:
self._more = False
exceptions.handle(self.request,
@ -99,11 +101,13 @@ class UsersView(tables.MultiTableView):
def _get_shared_data(self, *args, **kwargs):
tenant_id = self.kwargs["tenant_id"]
if not hasattr(self, "_shared_data"):
domain_context = self.request.session.get('domain_context', None)
try:
tenant = api.keystone.tenant_get(self.request,
tenant_id,
admin=True)
all_users = api.keystone.user_list(self.request)
all_users = api.keystone.user_list(self.request,
domain=domain_context)
tenant_users = api.keystone.user_list(self.request, tenant_id)
self._shared_data = {'tenant': tenant,
'all_users': all_users,

View File

@ -138,8 +138,10 @@ class UpdateProjectMembersAction(workflows.Action):
# Get list of available users
all_users = []
domain_context = request.session.get('domain_context', None)
try:
all_users = api.keystone.user_list(request)
all_users = api.keystone.user_list(request,
domain=domain_context)
except:
exceptions.handle(request, err_msg)
users_list = [(user.id, user.name) for user in all_users]
@ -217,12 +219,14 @@ class CreateProject(workflows.Workflow):
def handle(self, request, data):
# create the project
domain_context = self.request.session.get('domain_context', None)
try:
desc = data['description']
self.object = api.keystone.tenant_create(request,
name=data['name'],
description=desc,
enabled=data['enabled'])
enabled=data['enabled'],
domain=domain_context)
except:
exceptions.handle(request, ignore=True)
return False

View File

@ -38,6 +38,8 @@ LOG = logging.getLogger(__name__)
class BaseUserForm(forms.SelfHandlingForm):
def __init__(self, request, *args, **kwargs):
super(BaseUserForm, self).__init__(request, *args, **kwargs)
domain_context = request.session.get('domain_context', None)
# Populate project choices
project_choices = [('', _("Select a project"))]
@ -45,6 +47,10 @@ class BaseUserForm(forms.SelfHandlingForm):
# the user has access to.
user_id = kwargs['initial'].get('id', None)
projects, has_more = api.keystone.tenant_list(request, user=user_id)
if domain_context:
domain_projects = [project for project in projects
if project.domain_id == domain_context]
projects = domain_projects
for project in projects:
if project.enabled:
project_choices.append((project.id, project.name))
@ -88,14 +94,16 @@ class CreateUserForm(BaseUserForm):
# password and confirm_password strings.
@sensitive_variables('data')
def handle(self, request, data):
domain_context = request.session.get('domain_context', None)
try:
LOG.info('Creating user with name "%s"' % data['name'])
new_user = api.keystone.user_create(request,
data['name'],
data['email'],
data['password'],
data['project'],
True)
name=data['name'],
email=data['email'],
password=data['password'],
project=data['project'],
enabled=True,
domain=domain_context)
messages.success(request,
_('User "%s" was successfully created.')
% data['name'])

View File

@ -3,7 +3,7 @@
{% block title %}{% trans "Users" %}{% endblock %}
{% block page_header %}
{% include "horizon/common/_page_header.html" with title=_("Users") %}
{% include "horizon/common/_domain_page_header.html" with title=_("Users") %}
{% endblock page_header %}
{% block main %}

View File

@ -36,16 +36,40 @@ USER_UPDATE_URL = reverse('horizon:admin:users:update', args=[1])
class UsersViewTests(test.BaseAdminViewTests):
def _get_domain_id(self):
return self.request.session.get('domain_context', None)
def _get_users(self, domain_id):
if not domain_id:
users = self.users.list()
else:
users = [user for user in self.users.list()
if user.domain_id == domain_id]
return users
@test.create_stubs({api.keystone: ('user_list',)})
def test_index(self):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
api.keystone.user_list(IgnoreArg(), domain=domain_id) \
.AndReturn(users)
self.mox.ReplayAll()
res = self.client.get(USERS_INDEX_URL)
self.assertTemplateUsed(res, 'admin/users/index.html')
self.assertItemsEqual(res.context['table'].data, self.users.list())
self.assertItemsEqual(res.context['table'].data, users)
if domain_id:
for user in res.context['table'].data:
self.assertItemsEqual(user.domain_id, domain_id)
def test_index_with_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_index()
@test.create_stubs({api.keystone: ('user_create',
'tenant_list',
@ -54,16 +78,19 @@ class UsersViewTests(test.BaseAdminViewTests):
'role_list')})
def test_create(self):
user = self.users.get(id="1")
domain_id = self._get_domain_id()
role = self.roles.first()
api.keystone.tenant_list(IgnoreArg(), user=None) \
.AndReturn([self.tenants.list(), False])
api.keystone.user_create(IgnoreArg(),
user.name,
user.email,
user.password,
self.tenant.id,
True).AndReturn(user)
name=user.name,
email=user.email,
password=user.password,
project=self.tenant.id,
enabled=True,
domain=domain_id).AndReturn(user)
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
api.keystone.get_default_role(IgnoreArg()).AndReturn(role)
api.keystone.add_tenant_user_role(IgnoreArg(), self.tenant.id,
@ -83,6 +110,12 @@ class UsersViewTests(test.BaseAdminViewTests):
self.assertNoFormErrors(res)
self.assertMessageCount(success=1)
def test_create_with_domain(self):
domain = self.domains.get(id="1")
self.setSessionValues(domain_context=domain.id,
domain_context_name=domain.name)
self.test_create()
@test.create_stubs({api.keystone: ('tenant_list',
'role_list',
'get_default_role')})
@ -283,8 +316,11 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_user(self):
user = self.users.get(id="2")
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=domain_id).AndReturn(users)
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
True).AndReturn(user)
@ -299,9 +335,13 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_disable_user(self):
user = self.users.get(id="2")
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
self.assertTrue(user.enabled)
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=domain_id) \
.AndReturn(users)
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
False).AndReturn(user)
@ -316,8 +356,12 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_disable_user_exception(self):
user = self.users.get(id="2")
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=domain_id) \
.AndReturn(users)
api.keystone.user_update_enabled(IgnoreArg(), user.id, True) \
.AndRaise(self.exceptions.keystone)
self.mox.ReplayAll()
@ -329,8 +373,11 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_list',)})
def test_disabling_current_user(self):
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
for i in range(0, 2):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=domain_id) \
.AndReturn(users)
self.mox.ReplayAll()
@ -343,8 +390,11 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_list',)})
def test_delete_user_with_improper_permissions(self):
domain_id = self._get_domain_id()
users = self._get_users(domain_id)
for i in range(0, 2):
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=domain_id) \
.AndReturn(users)
self.mox.ReplayAll()
@ -365,7 +415,8 @@ class SeleniumTests(test.SeleniumAdminTestCase):
api.keystone.tenant_list(IgnoreArg(), user=None) \
.AndReturn([self.tenants.list(), False])
api.keystone.role_list(IgnoreArg()).AndReturn(self.roles.list())
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_list(IgnoreArg(), domain=None) \
.AndReturn(self.users.list())
api.keystone.get_default_role(IgnoreArg()) \
.AndReturn(self.roles.first())
self.mox.ReplayAll()

View File

@ -43,8 +43,10 @@ class IndexView(tables.DataTableView):
def get_data(self):
users = []
domain_context = self.request.session.get('domain_context', None)
try:
users = api.keystone.user_list(self.request)
users = api.keystone.user_list(self.request,
domain=domain_context)
except:
exceptions.handle(self.request,
_('Unable to retrieve user list.'))

View File

@ -27,6 +27,7 @@ from django.contrib.messages.storage import default_storage
from django.core.handlers import wsgi
from django import http
from django.test.client import RequestFactory
from django.utils.importlib import import_module
from django.utils import unittest
from cinderclient import client as cinder_client
@ -224,6 +225,17 @@ class BaseAdminViewTests(TestCase):
kwargs['roles'] = [self.roles.admin._info]
super(BaseAdminViewTests, self).setActiveUser(*args, **kwargs)
def setSessionValues(self, **kwargs):
settings.SESSION_ENGINE = 'django.contrib.sessions.backends.file'
engine = import_module(settings.SESSION_ENGINE)
store = engine.SessionStore()
for key in kwargs:
store[key] = kwargs[key]
self.request.session[key] = kwargs[key]
store.save()
self.session = store
self.client.cookies[settings.SESSION_COOKIE_NAME] = store.session_key
class APITestCase(TestCase):
"""

View File

@ -147,7 +147,8 @@ def data(TEST):
'password': 'password',
'token': 'test_token',
'project_id': '1',
'enabled': True}
'enabled': True,
'domain_id': "1"}
user = users.User(users.UserManager(None), user_dict)
user_dict = {'id': "2",
'name': 'user_two',
@ -155,7 +156,8 @@ def data(TEST):
'password': 'password',
'token': 'test_token',
'project_id': '1',
'enabled': True}
'enabled': True,
'domain_id': "1"}
user2 = users.User(users.UserManager(None), user_dict)
user_dict = {'id': "3",
'name': 'user_three',
@ -163,9 +165,19 @@ def data(TEST):
'password': 'password',
'token': 'test_token',
'project_id': '1',
'enabled': True}
'enabled': True,
'domain_id': "1"}
user3 = users.User(users.UserManager(None), user_dict)
TEST.users.add(user, user2, user3)
user_dict = {'id': "4",
'name': 'user_four',
'email': 'four@example.com',
'password': 'password',
'token': 'test_token',
'project_id': '2',
'enabled': True,
'domain_id': "2"}
user4 = users.User(users.UserManager(None), user_dict)
TEST.users.add(user, user2, user3, user4)
TEST.user = user # Your "current" user
TEST.user.service_catalog = SERVICE_CATALOG
@ -179,20 +191,28 @@ def data(TEST):
'description': 'group two description',
'domain_id': '1'}
group2 = groups.Group(groups.GroupManager(None), group_dict)
TEST.groups.add(group, group2)
group_dict = {'id': "3",
'name': 'group_three',
'description': 'group three description',
'domain_id': '2'}
group3 = groups.Group(groups.GroupManager(None), group_dict)
TEST.groups.add(group, group2, group3)
tenant_dict = {'id': "1",
'name': 'test_tenant',
'description': "a test tenant.",
'enabled': True}
'enabled': True,
'domain_id': '1'}
tenant_dict_2 = {'id': "2",
'name': 'disabled_tenant',
'description': "a disabled test tenant.",
'enabled': False}
'enabled': False,
'domain_id': '2'}
tenant_dict_3 = {'id': "3",
'name': u'\u4e91\u89c4\u5219',
'description': "an unicode-named tenant.",
'enabled': True}
'enabled': True,
'domain_id': '2'}
tenant = tenants.Tenant(tenants.TenantManager, tenant_dict)
disabled_tenant = tenants.Tenant(tenants.TenantManager, tenant_dict_2)
tenant_unicode = tenants.Tenant(tenants.TenantManager, tenant_dict_3)