diff --git a/horizon/horizon/api/keystone.py b/horizon/horizon/api/keystone.py
index 44772ae29d6..f420442729b 100644
--- a/horizon/horizon/api/keystone.py
+++ b/horizon/horizon/api/keystone.py
@@ -26,10 +26,12 @@
from keystoneclient.v2_0 import client as keystone_client
from keystoneclient.v2_0 import tokens
-from horizon.api.base import *
+from horizon import exceptions
+from horizon.api import APIResourceWrapper
LOG = logging.getLogger(__name__)
+DEFAULT_ROLE = None
def _get_endpoint_url(request):
@@ -47,11 +49,6 @@ class User(APIResourceWrapper):
_attrs = ['email', 'enabled', 'id', 'tenantId', 'name']
-class Role(APIResourceWrapper):
- """Wrapper around keystoneclient.roles.role"""
- _attrs = ['id', 'name', 'description', 'service_id']
-
-
class Services(APIResourceWrapper):
_attrs = ['disabled', 'host', 'id', 'last_update', 'stats', 'type', 'up',
'zone']
@@ -226,34 +223,41 @@ def user_update_tenant(request, user_id, tenant_id):
.update_tenant(user_id, tenant_id))
-def _get_role(request, name):
- roles = keystoneclient(request).roles.list()
- for role in roles:
- if role.name.lower() == name.lower():
- return role
-
- raise Exception(_('Role does not exist: %s') % name)
+def role_list(request):
+ """ Returns a global list of available roles. """
+ return keystoneclient(request).roles.list()
-def _get_roleref(request, user_id, tenant_id, role):
- rolerefs = keystoneclient(request).roles.get_user_role_refs(user_id)
- for roleref in rolerefs:
- if roleref.roleId == role.id and roleref.tenantId == tenant_id:
- return roleref
- raise Exception(_('Role "%s" does not exist for that user on this tenant.')
- % role.name)
+def add_tenant_user_role(request, tenant_id, user_id, role_id):
+ """ Adds a role for a user on a tenant. """
+ return keystoneclient(request).roles.add_user_role(user_id,
+ role_id,
+ tenant_id)
-def role_add_for_tenant_user(request, tenant_id, user_id, role):
- role = _get_role(request, role)
- return keystoneclient(request).roles.add_user_to_tenant(tenant_id,
- user_id,
- role.id)
+def remove_tenant_user(request, tenant_id, user_id):
+ """ Removes all roles from a user on a tenant, removing them from it. """
+ client = keystoneclient(request)
+ roles = client.roles.roles_for_user(user_id, tenant_id)
+ for role in roles:
+ client.roles.remove_user_role(user_id, role.id, tenant_id)
-def role_delete_for_tenant_user(request, tenant_id, user_id, role):
- role = _get_role(request, role)
- roleref = _get_roleref(request, user_id, tenant_id, role)
- return keystoneclient(request).roles.remove_user_from_tenant(tenant_id,
- user_id,
- roleref.id)
+def get_default_role(request):
+ """
+ Gets the default role object from Keystone and saves it as a global
+ since this is configured in settings and should not change from request
+ to request. Supports lookup by name or id.
+ """
+ global DEFAULT_ROLE
+ default = getattr(settings, "OPENSTACK_KEYSTONE_DEFAULT_ROLE", None)
+ if default and DEFAULT_ROLE is None:
+ try:
+ roles = keystoneclient(request).roles.list()
+ except:
+ exceptions.handle(request)
+ for role in roles:
+ if role.id == default or role.name == default:
+ DEFAULT_ROLE = role
+ break
+ return DEFAULT_ROLE
diff --git a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_add_user.html b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_add_user.html
index 020d70335e2..3ccae3aa066 100644
--- a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_add_user.html
+++ b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_add_user.html
@@ -1,10 +1,25 @@
+{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
-
+
+{% block form_id %}add_user_form{% endblock %}
+{% block form_action %}{% url horizon:syspanel:tenants:add_user tenant_id user_id %}{% endblock %}
+
+{% block modal_id %}add_user_modal{% endblock %}
+{% block modal-header %}{% trans "Add User To Tenant" %}{% endblock %}
+
+{% block modal-body %}
+
+
+ {% include "horizon/common/_form_fields.html" %}
+
+
+
+
{% trans "Description" %}:
+
{% trans "Select the user role for the tenant." %}
+
+{% endblock %}
+
+{% block modal-footer %}
+
+ {% trans "Cancel" %}
+{% endblock %}
diff --git a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_remove_user.html b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_remove_user.html
deleted file mode 100644
index 130f0a13b77..00000000000
--- a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/_remove_user.html
+++ /dev/null
@@ -1,10 +0,0 @@
-{% load i18n %}
-
diff --git a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/add_user.html b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/add_user.html
new file mode 100644
index 00000000000..781698d24c2
--- /dev/null
+++ b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/add_user.html
@@ -0,0 +1,11 @@
+{% extends 'syspanel/base.html' %}
+{% load i18n %}
+{% block title %}{% trans "Add User To Tenant" %}{% endblock %}
+
+{% block page_header %}
+ {% include "horizon/common/_page_header.html" with title=_("Add User To Tenant") %}
+{% endblock page_header %}
+
+{% block syspanel_main %}
+ {% include 'syspanel/tenants/_add_user.html' %}
+{% endblock %}
diff --git a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/users.html b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/users.html
index 5e9efa14873..86014f195e5 100644
--- a/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/users.html
+++ b/horizon/horizon/dashboards/syspanel/templates/syspanel/tenants/users.html
@@ -4,64 +4,15 @@
{% block page_header %}
{% endblock %}
{% block syspanel_main %}
-
-
- {% if users %}
-
-
- {% trans "ID" %}
- {% trans "Name" %}
- {% trans "Email" %}
- {% trans "Actions" %}
-
-
- {% for user in users %}
-
- {{ user.id }}
- {{ user.name }}
- {{ user.email }}
-
-
- {% include "syspanel/tenants/_remove_user.html" with form=remove_user_form %}
-
-
-
- {% endfor %}
-
-
- {% else %}
-
-
{% trans "Info" %}
-
T{% trans "here are currently no users for this tenant" %}
-
- {% endif %}
- {% if new_users %}
-
{% trans "Add new users" %}
-
-
- {% trans "ID" %}
- {% trans "Name" %}
- {% trans "Actions" %}
-
-
- {% for user in new_users %}
-
- {{ user.id }}
- {{ user.name }}
-
-
- {% include "syspanel/tenants/_add_user.html" with form=add_user_form %}
-
-
-
- {% endfor %}
-
-
- {% endif %}
-
+
+ {{ tenant_users_table.render }}
+
+
+ {{ add_users_table.render }}
+
{% endblock %}
diff --git a/horizon/horizon/dashboards/syspanel/tenants/forms.py b/horizon/horizon/dashboards/syspanel/tenants/forms.py
index 0a40fd87ca9..640105c2942 100644
--- a/horizon/horizon/dashboards/syspanel/tenants/forms.py
+++ b/horizon/horizon/dashboards/syspanel/tenants/forms.py
@@ -21,7 +21,6 @@
import logging
from django import shortcuts
-from django.conf import settings
from django.contrib import messages
from django.utils.translation import ugettext as _
@@ -34,43 +33,27 @@
class AddUser(forms.SelfHandlingForm):
- user = forms.CharField()
- tenant = forms.CharField()
+ tenant_id = forms.CharField(widget=forms.widgets.HiddenInput())
+ user_id = forms.CharField(widget=forms.widgets.HiddenInput())
+ role_id = forms.ChoiceField(label=_("Role"))
- def handle(self, request, data):
- try:
- api.role_add_for_tenant_user(
- request,
- data['tenant'],
- data['user'],
- settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE)
- messages.success(request,
- _('%(user)s was successfully added to %(tenant)s.')
- % {"user": data['user'], "tenant": data['tenant']})
- except:
- exceptions.handle(request, _('Unable to add user to tenant.'))
- return shortcuts.redirect('horizon:syspanel:tenants:users',
- tenant_id=data['tenant'])
-
-
-class RemoveUser(forms.SelfHandlingForm):
- user = forms.CharField()
- tenant = forms.CharField()
+ def __init__(self, *args, **kwargs):
+ roles = kwargs.pop('roles')
+ super(AddUser, self).__init__(*args, **kwargs)
+ role_choices = [(role.id, role.name) for role in roles]
+ self.fields['role_id'].choices = role_choices
def handle(self, request, data):
try:
- api.role_delete_for_tenant_user(
- request,
- data['tenant'],
- data['user'],
- settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE)
- messages.success(request,
- _('%(user)s was successfully removed from %(tenant)s.')
- % {"user": data['user'], "tenant": data['tenant']})
+ api.add_tenant_user_role(request,
+ data['tenant_id'],
+ data['user_id'],
+ data['role_id'])
+ messages.success(request, _('Successfully added user to tenant.'))
except:
- exceptions.handle(request, _('Unable to remove user from tenant.'))
+ exceptions.handle(request, _('Unable to add user to tenant.'))
return shortcuts.redirect('horizon:syspanel:tenants:users',
- tenant_id=data['tenant'])
+ tenant_id=data['tenant_id'])
class CreateTenant(forms.SelfHandlingForm):
diff --git a/horizon/horizon/dashboards/syspanel/tenants/tables.py b/horizon/horizon/dashboards/syspanel/tenants/tables.py
index ea354c0cfbd..8fdd84b9d97 100644
--- a/horizon/horizon/dashboards/syspanel/tenants/tables.py
+++ b/horizon/horizon/dashboards/syspanel/tenants/tables.py
@@ -1,10 +1,13 @@
import logging
+from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import api
from horizon import tables
+from ..users.tables import UsersTable
+
LOG = logging.getLogger(__name__)
@@ -18,7 +21,7 @@ class ModifyQuotasLink(tables.LinkAction):
class ViewMembersLink(tables.LinkAction):
name = "users"
- verbose_name = _("View Members")
+ verbose_name = _("Modify Users")
url = "horizon:syspanel:tenants:users"
@@ -30,7 +33,7 @@ class UsageLink(tables.LinkAction):
class EditLink(tables.LinkAction):
name = "update"
- verbose_name = _("Edit")
+ verbose_name = _("Edit Tenant")
url = "horizon:syspanel:tenants:update"
attrs = {"class": "ajax-modal"}
@@ -77,3 +80,43 @@ class Meta:
row_actions = (EditLink, UsageLink, ViewMembersLink, ModifyQuotasLink,
DeleteTenantsAction)
table_actions = (TenantFilterAction, CreateLink, DeleteTenantsAction)
+
+
+class RemoveUserAction(tables.BatchAction):
+ name = "remove_user"
+ action_present = _("Remove")
+ action_past = _("Removed")
+ data_type_singular = _("User")
+ data_type_plural = _("Users")
+ classes = ('danger',)
+
+ def action(self, request, user_id):
+ tenant_id = self.table.kwargs['tenant_id']
+ api.keystone.remove_tenant_user(request, tenant_id, user_id)
+
+
+class TenantUsersTable(UsersTable):
+ class Meta:
+ name = "tenant_users"
+ verbose_name = _("Users For Tenant")
+ table_actions = (RemoveUserAction,)
+ row_actions = (RemoveUserAction,)
+
+
+class AddUserAction(tables.LinkAction):
+ name = "add_user"
+ verbose_name = _("Add To Tenant")
+ url = "horizon:syspanel:tenants:add_user"
+ classes = ('ajax-modal',)
+
+ def get_link_url(self, user):
+ tenant_id = self.table.kwargs['tenant_id']
+ return reverse(self.url, args=(tenant_id, user.id))
+
+
+class AddUsersTable(UsersTable):
+ class Meta:
+ name = "add_users"
+ verbose_name = _("Add New Users")
+ table_actions = ()
+ row_actions = (AddUserAction,)
diff --git a/horizon/horizon/dashboards/syspanel/tenants/urls.py b/horizon/horizon/dashboards/syspanel/tenants/urls.py
index ef68c1388b9..18bf748079a 100644
--- a/horizon/horizon/dashboards/syspanel/tenants/urls.py
+++ b/horizon/horizon/dashboards/syspanel/tenants/urls.py
@@ -20,7 +20,8 @@
from django.conf.urls.defaults import patterns, url
-from .views import IndexView, CreateView, UpdateView, QuotasView
+from .views import (IndexView, CreateView, UpdateView, QuotasView, UsersView,
+ AddUserView)
urlpatterns = patterns('horizon.dashboards.syspanel.tenants.views',
@@ -28,8 +29,10 @@
url(r'^create$', CreateView.as_view(), name='create'),
url(r'^(?P
[^/]+)/update/$',
UpdateView.as_view(), name='update'),
- url(r'^(?P[^/]+)/users/$', 'users', name='users'),
url(r'^(?P[^/]+)/quotas/$',
QuotasView.as_view(), name='quotas'),
- url(r'^(?P[^/]+)/usage/$', 'usage', name='usage')
+ url(r'^(?P[^/]+)/usage/$', 'usage', name='usage'),
+ url(r'^(?P[^/]+)/users/$', UsersView.as_view(), name='users'),
+ url(r'^(?P[^/]+)/users/(?P[^/]+)/add/$',
+ AddUserView.as_view(), name='add_user')
)
diff --git a/horizon/horizon/dashboards/syspanel/tenants/views.py b/horizon/horizon/dashboards/syspanel/tenants/views.py
index f56599ed8e1..5fc4ce27e6f 100644
--- a/horizon/horizon/dashboards/syspanel/tenants/views.py
+++ b/horizon/horizon/dashboards/syspanel/tenants/views.py
@@ -20,20 +20,21 @@
import datetime
import logging
+import operator
from django import shortcuts
from django import http
-from django.conf import settings
from django.contrib import messages
+from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from keystoneclient import exceptions as api_exceptions
from horizon import api
+from horizon import exceptions
from horizon import forms
from horizon import tables
-from .forms import (AddUser, RemoveUser, CreateTenant, UpdateTenant,
- UpdateQuotas)
-from .tables import TenantsTable
+from .forms import AddUser, CreateTenant, UpdateTenant, UpdateQuotas
+from .tables import TenantsTable, TenantUsersTable, AddUsersTable
from horizon.dashboards.syspanel.overview.views import GlobalSummary
@@ -90,26 +91,70 @@ def get_initial(self):
'enabled': self.object.enabled}
-def users(request, tenant_id):
- for f in (AddUser, RemoveUser,):
- form, handled = f.maybe_handle(request)
- if handled:
- return handled
+class UsersView(tables.MultiTableView):
+ table_classes = (TenantUsersTable, AddUsersTable)
+ template_name = 'syspanel/tenants/users.html'
- add_user_form = AddUser()
- remove_user_form = RemoveUser()
+ def get_data(self, *args, **kwargs):
+ tenant_id = self.kwargs["tenant_id"]
+ try:
+ self.tenant = api.keystone.tenant_get(self.request, tenant_id)
+ self.all_users = api.keystone.user_list(self.request)
+ self.tenant_users = api.keystone.user_list(self.request, tenant_id)
+ except:
+ redirect = reverse("horizon:syspanel:tenants:index")
+ exceptions.handle(self.request,
+ _("Unable to retrieve users."),
+ redirect=redirect)
+ return super(UsersView, self).get_data(*args, **kwargs)
+
+ def get_tenant_users_data(self):
+ return self.tenant_users
+
+ def get_add_users_data(self):
+ tenant_user_ids = [user.id for user in self.tenant_users]
+ return [user for user in self.all_users if
+ user.id not in tenant_user_ids]
+
+ def get_context_data(self, **kwargs):
+ context = super(UsersView, self).get_context_data(**kwargs)
+ context['tenant'] = self.tenant
+ return context
+
+
+class AddUserView(forms.ModalFormView):
+ form_class = AddUser
+ template_name = 'syspanel/tenants/add_user.html'
+ context_object_name = 'tenant'
+
+ def get_object(self, *args, **kwargs):
+ return api.keystone.tenant_get(self.request, kwargs["tenant_id"])
- users = api.user_list(request, tenant_id)
- all_users = api.user_list(request)
- user_ids = [u.id for u in users]
- new_users = [u for u in all_users if not u.id in user_ids]
- return shortcuts.render(request,
- 'syspanel/tenants/users.html', {
- 'add_user_form': add_user_form,
- 'remove_user_form': remove_user_form,
- 'tenant_id': tenant_id,
- 'users': users,
- 'new_users': new_users})
+ def get_context_data(self, **kwargs):
+ context = super(AddUserView, self).get_context_data(**kwargs)
+ context['tenant_id'] = self.kwargs["tenant_id"]
+ context['user_id'] = self.kwargs["user_id"]
+ return context
+
+ def get_form_kwargs(self):
+ kwargs = super(AddUserView, self).get_form_kwargs()
+ try:
+ roles = api.keystone.role_list(self.request)
+ except:
+ redirect = reverse("horizon:syspanel:tenants:users",
+ args=(self.kwargs["tenant_id"],))
+ exceptions.handle(self.request,
+ _("Unable to retrieve roles."),
+ redirect=redirect)
+ roles.sort(key=operator.attrgetter("id"))
+ kwargs['roles'] = roles
+ return kwargs
+
+ def get_initial(self):
+ default_role = api.keystone.get_default_role(self.request)
+ return {'tenant_id': self.kwargs['tenant_id'],
+ 'user_id': self.kwargs['user_id'],
+ 'role_id': getattr(default_role, "id", None)}
class QuotasView(forms.ModalFormView):
@@ -151,7 +196,6 @@ def usage(request, tenant_id):
if date_start > GlobalSummary.current_month():
messages.error(request, _('No data for the selected period'))
- date_end = date_start
datetime_end = datetime_start
usage = {}
diff --git a/horizon/horizon/dashboards/syspanel/users/forms.py b/horizon/horizon/dashboards/syspanel/users/forms.py
index ce424290a5d..08f9aa1b030 100644
--- a/horizon/horizon/dashboards/syspanel/users/forms.py
+++ b/horizon/horizon/dashboards/syspanel/users/forms.py
@@ -21,11 +21,11 @@
import logging
from django import shortcuts
-from django.conf import settings
from django.contrib import messages
from django.utils.translation import ugettext as _
from horizon import api
+from horizon import exceptions
from horizon import forms
@@ -68,29 +68,18 @@ def handle(self, request, data):
_('User "%s" was successfully created.')
% data['name'])
try:
- api.role_add_for_tenant_user(
- request, data['tenant_id'], new_user.id,
- settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE)
- except Exception, e:
- LOG.exception('Exception while assigning \
- role to new user: %s' % new_user.id)
- if not hasattr(e, 'message'):
- e.message = str(e)
- messages.error(request,
- _('Error assigning role to user: %s')
- % e.message)
-
+ default_role = api.keystone.get_default_role(request)
+ if default_role:
+ api.add_tenant_user_role(request,
+ data['tenant_id'],
+ new_user.id,
+ default_role.id)
+ except:
+ exceptions.handle(request,
+ _('Unable to add user to primary tenant.'))
return shortcuts.redirect('horizon:syspanel:users:index')
-
- except Exception, e:
- LOG.exception('Exception while creating user\n'
- 'name: "%s", email: "%s", tenant_id: "%s"' %
- (data['name'], data['email'], data['tenant_id']))
- if not hasattr(e, 'message'):
- e.message = str(e)
- messages.error(request,
- _('Error creating user: %s')
- % e.message)
+ except:
+ exceptions.handle(request, _('Unable to create user.'))
return shortcuts.redirect('horizon:syspanel:users:index')
diff --git a/horizon/horizon/tables/views.py b/horizon/horizon/tables/views.py
index 0a3e19a647d..7d403f7884a 100644
--- a/horizon/horizon/tables/views.py
+++ b/horizon/horizon/tables/views.py
@@ -58,9 +58,9 @@ def get_tables(self):
table_func = getattr(self, func_name, None)
data = self.get_data()[table._meta.name]
if table_func is None:
- tbl = table(self.request, data)
+ tbl = table(self.request, data, **self.kwargs)
else:
- tbl = table_func(self, self.request, data)
+ tbl = table_func(self, self.request, data, **self.kwargs)
self._tables[table._meta.name] = tbl
return self._tables
diff --git a/horizon/horizon/tests/api_tests/keystone.py b/horizon/horizon/tests/api_tests/keystone.py
index a9759ce7272..285b78d9e3f 100644
--- a/horizon/horizon/tests/api_tests/keystone.py
+++ b/horizon/horizon/tests/api_tests/keystone.py
@@ -20,13 +20,11 @@
from __future__ import absolute_import
-from django import http
from django.conf import settings
-from keystoneclient.v2_0 import tenants as keystoneclient_tenants
-from mox import IsA
+from keystoneclient.v2_0.roles import Role, RoleManager
from horizon import api
-from horizon.tests.api_tests.utils import (APITestCase, APIResource,
+from horizon.tests.api_tests.utils import (APITestCase,
TEST_RETURN, TEST_URL, TEST_USERNAME, TEST_TENANT_ID, TEST_TOKEN_ID,
TEST_TENANT_NAME, TEST_PASSWORD, TEST_EMAIL)
@@ -83,26 +81,47 @@ def test_token_create(self):
class RoleAPITests(APITestCase):
- def test_role_add_for_tenant_user(self):
+ def setUp(self):
+ super(RoleAPITests, self).setUp()
+ self.role = Role(RoleManager,
+ {'id': '2',
+ 'name': settings.OPENSTACK_KEYSTONE_DEFAULT_ROLE})
+ self.roles = (self.role,)
+
+ def test_remove_tenant_user(self):
+ """
+ Tests api.keystone.remove_tenant_user.
+
+ Verifies that remove_tenant_user is called with the right arguments
+ after iterating the user's roles.
+
+ There are no assertions in this test because the checking is handled
+ by mox in the VerifyAll() call in tearDown().
+ """
keystoneclient = self.stub_keystoneclient()
- role = api.Role(APIResource.get_instance())
- role.id = TEST_RETURN
- role.name = TEST_RETURN
-
keystoneclient.roles = self.mox.CreateMockAnything()
- keystoneclient.roles.add_user_to_tenant(TEST_TENANT_ID,
- TEST_USERNAME,
- TEST_RETURN).AndReturn(role)
- api.keystone._get_role = self.mox.CreateMockAnything()
- api.keystone._get_role(IsA(http.HttpRequest), IsA(str)).AndReturn(role)
+ keystoneclient.roles.roles_for_user(TEST_USERNAME, TEST_TENANT_ID) \
+ .AndReturn(self.roles)
+ keystoneclient.roles.remove_user_role(TEST_USERNAME,
+ self.role.id,
+ TEST_TENANT_ID) \
+ .AndReturn(self.role)
+ self.mox.ReplayAll()
+ api.keystone.remove_tenant_user(self.request,
+ TEST_TENANT_ID,
+ TEST_USERNAME)
+ def test_get_default_role(self):
+ keystoneclient = self.stub_keystoneclient()
+ keystoneclient.roles = self.mox.CreateMockAnything()
+ keystoneclient.roles.list().AndReturn(self.roles)
self.mox.ReplayAll()
- ret_val = api.role_add_for_tenant_user(self.request,
- TEST_TENANT_ID,
- TEST_USERNAME,
- TEST_RETURN)
- self.assertEqual(ret_val, role)
+ role = api.keystone.get_default_role(self.request)
+ self.assertEqual(role, self.role)
+ # Verify that a second call doesn't hit the API again,
+ # (it would show up in mox as an unexpected method call)
+ role = api.keystone.get_default_role(self.request)
class UserAPITests(APITestCase):
diff --git a/horizon/horizon/tests/testsettings.py b/horizon/horizon/tests/testsettings.py
index 6c03c4d7fef..1e3f9f91594 100644
--- a/horizon/horizon/tests/testsettings.py
+++ b/horizon/horizon/tests/testsettings.py
@@ -109,7 +109,7 @@
OPENSTACK_ADMIN_TOKEN = "openstack"
OPENSTACK_KEYSTONE_URL = "http://%s:5000/v2.0" % OPENSTACK_ADDRESS
OPENSTACK_KEYSTONE_ADMIN_URL = "http://%s:35357/v2.0" % OPENSTACK_ADDRESS
-OPENSTACK_KEYSTONE_DEFAULT_ROLE_ID = "2"
+OPENSTACK_KEYSTONE_DEFAULT_ROLE = "Member"
# Silence logging output during tests.
LOGGING = {
diff --git a/run_tests.sh b/run_tests.sh
index 4a3c33d7658..5884b720dba 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -6,7 +6,7 @@ set -o errexit
# Increment me any time the environment should be rebuilt.
# This includes dependncy changes, directory renames, etc.
# Simple integer secuence: 1, 2, 3...
-environment_version=7
+environment_version=8
#--------------------------------------------------------#
function usage {