Allow proper log output during test runs.

This involved a huge amount of cleanup to existing code
in order to make sure that existing failures were properly
fixed or silenced when intentional.

Additionally, this introduces a set of pre-built exception
instances for test purposes which are marked with the
"silence_logging" attribute to denote expected failures which
should not be logged in test output.

Change-Id: I6b420382dcdc5792c7be4d727853f438154c641e
This commit is contained in:
Gabriel Hurley 2012-05-09 17:37:18 -07:00
parent 65824cb8c8
commit 856983fbcd
29 changed files with 349 additions and 198 deletions

View File

@ -237,10 +237,10 @@ class Panel(HorizonComponent):
return reverse('horizon:%s:%s:%s' % (self._registered_with.slug, return reverse('horizon:%s:%s:%s' % (self._registered_with.slug,
self.slug, self.slug,
self.index_url_name)) self.index_url_name))
except: except Exception as exc:
# Logging here since this will often be called in a template # Logging here since this will often be called in a template
# where the exception would be hidden. # where the exception would be hidden.
LOG.exception("Error reversing absolute URL for %s." % self) LOG.info("Error reversing absolute URL for %s: %s" % (self, exc))
raise raise
@property @property

View File

@ -24,7 +24,6 @@ import logging
from django.contrib import messages from django.contrib import messages
from django import shortcuts from django import shortcuts
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from novaclient import exceptions as novaclient_exceptions
from horizon import api from horizon import api
from horizon import exceptions from horizon import exceptions
@ -65,9 +64,9 @@ class FloatingIpAssociate(forms.SelfHandlingForm):
'with Instance: %(inst)s') 'with Instance: %(inst)s')
% {"ip": data['floating_ip'], % {"ip": data['floating_ip'],
"inst": data['instance_id']}) "inst": data['instance_id']})
except novaclient_exceptions.ClientException, e: except:
LOG.exception("ClientException in FloatingIpAssociate") exceptions.handle(request,
messages.error(request, _('Error associating Floating IP: %s') % e) _('Unable to associate floating IP.'))
return shortcuts.redirect('horizon:nova:access_and_security:index') return shortcuts.redirect('horizon:nova:access_and_security:index')

View File

@ -22,7 +22,6 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from mox import IsA from mox import IsA
from novaclient import exceptions as novaclient_exceptions
from horizon import api from horizon import api
from horizon import test from horizon import test
@ -35,9 +34,10 @@ NAMESPACE = "horizon:nova:access_and_security:floating_ips"
class FloatingIpViewTests(test.TestCase): class FloatingIpViewTests(test.TestCase):
def test_associate(self): def test_associate(self):
floating_ip = self.floating_ips.first() floating_ip = self.floating_ips.first()
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api.nova, 'server_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.nova.server_list(IsA(http.HttpRequest)) \
.AndReturn(self.servers.list())
api.tenant_floating_ip_get(IsA(http.HttpRequest), api.tenant_floating_ip_get(IsA(http.HttpRequest),
floating_ip.id).AndReturn(floating_ip) floating_ip.id).AndReturn(floating_ip)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -50,11 +50,19 @@ class FloatingIpViewTests(test.TestCase):
def test_associate_post(self): def test_associate_post(self):
floating_ip = self.floating_ips.first() floating_ip = self.floating_ips.first()
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list') self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api, 'server_add_floating_ip') self.mox.StubOutWithMock(api, 'server_add_floating_ip')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) self.mox.StubOutWithMock(api.nova, 'server_list')
self.mox.StubOutWithMock(api.nova, 'keypair_list')
api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list())
api.nova.server_list(IsA(http.HttpRequest)) \
.AndReturn(self.servers.list())
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list()) .AndReturn(self.floating_ips.list())
api.server_add_floating_ip(IsA(http.HttpRequest), api.server_add_floating_ip(IsA(http.HttpRequest),
@ -62,6 +70,8 @@ class FloatingIpViewTests(test.TestCase):
floating_ip.id) floating_ip.id)
api.tenant_floating_ip_get(IsA(http.HttpRequest), api.tenant_floating_ip_get(IsA(http.HttpRequest),
floating_ip.id).AndReturn(floating_ip) floating_ip.id).AndReturn(floating_ip)
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
self.mox.ReplayAll() self.mox.ReplayAll()
form_data = {'instance_id': server.id, form_data = {'instance_id': server.id,
@ -75,25 +85,29 @@ class FloatingIpViewTests(test.TestCase):
def test_associate_post_with_exception(self): def test_associate_post_with_exception(self):
floating_ip = self.floating_ips.first() floating_ip = self.floating_ips.first()
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list') self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api.nova, 'keypair_list') self.mox.StubOutWithMock(api.nova, 'keypair_list')
self.mox.StubOutWithMock(api, 'server_add_floating_ip') self.mox.StubOutWithMock(api, 'server_add_floating_ip')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest)) \
.AndReturn(self.servers.list())
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list()) .AndReturn(self.floating_ips.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list()) .AndReturn(self.security_groups.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \ api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list()) .AndReturn(self.keypairs.list())
exc = novaclient_exceptions.ClientException('ClientException')
api.server_add_floating_ip(IsA(http.HttpRequest), api.server_add_floating_ip(IsA(http.HttpRequest),
server.id, server.id,
floating_ip.id).AndRaise(exc) floating_ip.id) \
.AndRaise(self.exceptions.nova)
api.tenant_floating_ip_get(IsA(http.HttpRequest), api.tenant_floating_ip_get(IsA(http.HttpRequest),
floating_ip.id).AndReturn(floating_ip) floating_ip.id).AndReturn(floating_ip)
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('%s:associate' % NAMESPACE, args=[floating_ip.id]) url = reverse('%s:associate' % NAMESPACE, args=[floating_ip.id])
@ -102,7 +116,6 @@ class FloatingIpViewTests(test.TestCase):
'floating_ip_id': floating_ip.id, 'floating_ip_id': floating_ip.id,
'floating_ip': floating_ip.ip, 'floating_ip': floating_ip.ip,
'method': 'FloatingIpAssociate'}) 'method': 'FloatingIpAssociate'})
self.assertRaises(novaclient_exceptions.ClientException)
self.assertRedirects(res, INDEX_URL) self.assertRedirects(res, INDEX_URL)
def test_disassociate_post(self): def test_disassociate_post(self):
@ -113,7 +126,10 @@ class FloatingIpViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list') self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
self.mox.StubOutWithMock(api, 'server_remove_floating_ip') self.mox.StubOutWithMock(api, 'server_remove_floating_ip')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \ api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list()) .AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
@ -138,6 +154,10 @@ class FloatingIpViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list') self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
self.mox.StubOutWithMock(api, 'server_remove_floating_ip') self.mox.StubOutWithMock(api, 'server_remove_floating_ip')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \ api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list()) .AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
@ -145,13 +165,12 @@ class FloatingIpViewTests(test.TestCase):
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list()) .AndReturn(self.floating_ips.list())
exc = novaclient_exceptions.ClientException('ClientException')
api.server_remove_floating_ip(IsA(http.HttpRequest), api.server_remove_floating_ip(IsA(http.HttpRequest),
server.id, server.id,
floating_ip.id).AndRaise(exc) floating_ip.id) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
action = "floating_ips__disassociate__%s" % floating_ip.id action = "floating_ips__disassociate__%s" % floating_ip.id
res = self.client.post(INDEX_URL, {"action": action}) res = self.client.post(INDEX_URL, {"action": action})
self.assertRaises(novaclient_exceptions.ClientException)
self.assertRedirectsNoFollow(res, INDEX_URL) self.assertRedirectsNoFollow(res, INDEX_URL)

View File

@ -53,7 +53,7 @@ class AssociateView(forms.ModalFormView):
def get_initial(self): def get_initial(self):
try: try:
servers = api.server_list(self.request) servers = api.nova.server_list(self.request)
except: except:
redirect = reverse('horizon:nova:access_and_security:index') redirect = reverse('horizon:nova:access_and_security:index')
exceptions.handle(self.request, exceptions.handle(self.request,

View File

@ -21,7 +21,6 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from mox import IsA from mox import IsA
from novaclient import exceptions as novaclient_exceptions
from horizon import api from horizon import api
from horizon import test from horizon import test
@ -36,6 +35,16 @@ class KeyPairViewTests(test.TestCase):
self.mox.StubOutWithMock(api.nova, 'keypair_list') self.mox.StubOutWithMock(api.nova, 'keypair_list')
self.mox.StubOutWithMock(api.nova, 'keypair_delete') self.mox.StubOutWithMock(api.nova, 'keypair_delete')
self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list())
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \ api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list()) .AndReturn(self.keypairs.list())
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name)
@ -49,11 +58,20 @@ class KeyPairViewTests(test.TestCase):
keypair = self.keypairs.first() keypair = self.keypairs.first()
self.mox.StubOutWithMock(api.nova, 'keypair_list') self.mox.StubOutWithMock(api.nova, 'keypair_list')
self.mox.StubOutWithMock(api.nova, 'keypair_delete') self.mox.StubOutWithMock(api.nova, 'keypair_delete')
self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list())
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \ api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list()) .AndReturn(self.keypairs.list())
exc = novaclient_exceptions.ClientException('clientException')
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \ api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \
.AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'keypairs__delete__%s' % keypair.name} formData = {'action': 'keypairs__delete__%s' % keypair.name}
@ -93,10 +111,10 @@ class KeyPairViewTests(test.TestCase):
def test_generate_keypair_exception(self): def test_generate_keypair_exception(self):
keypair = self.keypairs.first() keypair = self.keypairs.first()
exc = novaclient_exceptions.ClientException('clientException')
self.mox.StubOutWithMock(api, 'keypair_create') self.mox.StubOutWithMock(api, 'keypair_create')
api.keypair_create(IsA(http.HttpRequest), keypair.name).AndRaise(exc) api.keypair_create(IsA(http.HttpRequest), keypair.name) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
context = {'keypair_name': keypair.name} context = {'keypair_name': keypair.name}

View File

@ -146,8 +146,7 @@ class AddRule(forms.SelfHandlingForm):
data['source_group']) data['source_group'])
messages.success(request, _('Successfully added rule: %s') \ messages.success(request, _('Successfully added rule: %s') \
% unicode(rule)) % unicode(rule))
except novaclient_exceptions.ClientException, e: except:
LOG.exception("ClientException in AddRule") exceptions.handle(request,
messages.error(request, _('Error adding rule security group: %s') _('Unable to add rule to security group.'))
% e.message)
return shortcuts.redirect("horizon:nova:access_and_security:index") return shortcuts.redirect("horizon:nova:access_and_security:index")

View File

@ -21,7 +21,7 @@
from django import http from django import http
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from novaclient import exceptions as novaclient_exceptions
from mox import IsA from mox import IsA
from horizon import api from horizon import api
@ -67,10 +67,10 @@ class SecurityGroupsViewTests(test.TestCase):
def test_create_security_groups_post_exception(self): def test_create_security_groups_post_exception(self):
sec_group = self.security_groups.first() sec_group = self.security_groups.first()
self.mox.StubOutWithMock(api, 'security_group_create') self.mox.StubOutWithMock(api, 'security_group_create')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_create(IsA(http.HttpRequest), api.security_group_create(IsA(http.HttpRequest),
sec_group.name, sec_group.name,
sec_group.description).AndRaise(exc) sec_group.description) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'method': 'CreateGroup', formData = {'method': 'CreateGroup',
@ -103,10 +103,19 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group_list = self.security_groups.list() sec_group_list = self.security_groups.list()
self.mox.StubOutWithMock(api, 'security_group_get') self.mox.StubOutWithMock(api, 'security_group_get')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_get(IsA(http.HttpRequest),
sec_group.id).AndRaise(exc)
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api.nova, 'keypair_list')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.nova.keypair_list(IsA(http.HttpRequest)) \
.AndReturn(self.keypairs.list())
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list())
api.security_group_get(IsA(http.HttpRequest),
sec_group.id).AndRaise(self.exceptions.nova)
api.security_group_list( api.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
api.security_group_list( api.security_group_list(
@ -122,6 +131,7 @@ class SecurityGroupsViewTests(test.TestCase):
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
self.mox.StubOutWithMock(api, 'security_group_rule_create') self.mox.StubOutWithMock(api, 'security_group_rule_create')
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_rule_create(IsA(http.HttpRequest), api.security_group_rule_create(IsA(http.HttpRequest),
sec_group.id, sec_group.id,
rule.ip_protocol, rule.ip_protocol,
@ -129,7 +139,6 @@ class SecurityGroupsViewTests(test.TestCase):
int(rule.to_port), int(rule.to_port),
rule.ip_range['cidr'], rule.ip_range['cidr'],
None).AndReturn(rule) None).AndReturn(rule)
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_list( api.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -198,17 +207,16 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group = self.security_groups.first() sec_group = self.security_groups.first()
sec_group_list = self.security_groups.list() sec_group_list = self.security_groups.list()
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
exc = novaclient_exceptions.ClientException('ClientException')
self.mox.StubOutWithMock(api, 'security_group_rule_create') self.mox.StubOutWithMock(api, 'security_group_rule_create')
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_rule_create(IsA(http.HttpRequest), api.security_group_rule_create(IsA(http.HttpRequest),
sec_group.id, sec_group.id,
rule.ip_protocol, rule.ip_protocol,
int(rule.from_port), int(rule.from_port),
int(rule.to_port), int(rule.to_port),
rule.ip_range['cidr'], rule.ip_range['cidr'],
None).AndRaise(exc) None).AndRaise(self.exceptions.nova)
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_list( api.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list) IsA(http.HttpRequest)).AndReturn(sec_group_list)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -241,9 +249,8 @@ class SecurityGroupsViewTests(test.TestCase):
rule = self.security_group_rules.first() rule = self.security_group_rules.first()
self.mox.StubOutWithMock(api, 'security_group_rule_delete') self.mox.StubOutWithMock(api, 'security_group_rule_delete')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_rule_delete(IsA(http.HttpRequest), api.security_group_rule_delete(IsA(http.HttpRequest),
rule.id).AndRaise(exc) rule.id).AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
form_data = {"action": "rules__delete__%s" % rule.id} form_data = {"action": "rules__delete__%s" % rule.id}
@ -271,9 +278,8 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group = self.security_groups.get(name="other_group") sec_group = self.security_groups.get(name="other_group")
self.mox.StubOutWithMock(api, 'security_group_delete') self.mox.StubOutWithMock(api, 'security_group_delete')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_delete(IsA(http.HttpRequest), api.security_group_delete(IsA(http.HttpRequest),
sec_group.id).AndRaise(exc) sec_group.id).AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -35,7 +35,10 @@ class AccessAndSecurityTests(test.TestCase):
self.mox.StubOutWithMock(api, 'tenant_floating_ip_list') self.mox.StubOutWithMock(api, 'tenant_floating_ip_list')
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api.nova, 'keypair_list') self.mox.StubOutWithMock(api.nova, 'keypair_list')
self.mox.StubOutWithMock(api.nova, 'server_list')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndReturn(self.servers.list())
api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs) api.nova.keypair_list(IsA(http.HttpRequest)).AndReturn(keypairs)
api.tenant_floating_ip_list(IsA(http.HttpRequest)) \ api.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(floating_ips) .AndReturn(floating_ips)
@ -66,10 +69,10 @@ class AccessAndSecurityTests(test.TestCase):
self.servers.add(server3) self.servers.add(server3)
self.mox.StubOutWithMock(api, 'tenant_floating_ip_get') self.mox.StubOutWithMock(api, 'tenant_floating_ip_get')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api.nova, 'server_list')
api.tenant_floating_ip_get(IsA(http.HttpRequest), api.tenant_floating_ip_get(IsA(http.HttpRequest),
floating_ip.id).AndReturn(floating_ip) floating_ip.id).AndReturn(floating_ip)
api.server_list(IsA(http.HttpRequest)).AndReturn(servers) api.nova.server_list(IsA(http.HttpRequest)).AndReturn(servers)
self.mox.ReplayAll() self.mox.ReplayAll()
res = self.client.get( res = self.client.get(

View File

@ -36,26 +36,12 @@ class DeleteContainer(tables.DeleteAction):
data_type_plural = _("Containers") data_type_plural = _("Containers")
def delete(self, request, obj_id): def delete(self, request, obj_id):
api.swift_delete_container(request, obj_id) try:
api.swift_delete_container(request, obj_id)
def handle(self, table, request, object_ids): except ContainerNotEmpty:
# Overriden to show clearer error messages instead of generic message messages.error(request,
deleted = [] _('Containers must be empty before deletion.'))
for obj_id in object_ids: raise
obj = table.get_object_by_id(obj_id)
try:
self.delete(request, obj_id)
deleted.append(obj)
except ContainerNotEmpty:
LOG.exception('Unable to delete container "%s".' % obj.name)
messages.error(request,
_('Unable to delete non-empty container: %s') %
obj.name)
if deleted:
messages.success(request,
_('Successfully deleted containers: %s')
% ", ".join([obj.name for obj in deleted]))
return shortcuts.redirect('horizon:nova:containers:index')
class CreateContainer(tables.LinkAction): class CreateContainer(tables.LinkAction):

View File

@ -67,6 +67,7 @@ class ContainerViewTests(test.TestCase):
container = self.containers.first() container = self.containers.first()
self.mox.StubOutWithMock(api, 'swift_delete_container') self.mox.StubOutWithMock(api, 'swift_delete_container')
exc = ContainerNotEmpty('containerNotEmpty') exc = ContainerNotEmpty('containerNotEmpty')
exc.silence_logging = True
api.swift_delete_container(IsA(http.HttpRequest), api.swift_delete_container(IsA(http.HttpRequest),
container.name).AndRaise(exc) container.name).AndRaise(exc)
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -21,13 +21,9 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from glanceclient.common import exceptions as glance_exception
from horizon import api from horizon import api
from horizon import test from horizon import test
from keystoneclient import exceptions as keystone_exceptions
from mox import IgnoreArg, IsA from mox import IgnoreArg, IsA
@ -45,6 +41,12 @@ class ImageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'flavor_list') self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'keypair_list') self.mox.StubOutWithMock(api, 'keypair_list')
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
self.mox.StubOutWithMock(api, 'volume_list')
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_get(IsA(http.HttpRequest), image.id).AndReturn(image) api.image_get(IsA(http.HttpRequest), image.id).AndReturn(image)
api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quota_usages) api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(quota_usages)
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list()) api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
@ -84,7 +86,10 @@ class ImageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'server_create') self.mox.StubOutWithMock(api, 'server_create')
self.mox.StubOutWithMock(api, 'volume_list') self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list()) api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list()) api.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
@ -128,13 +133,18 @@ class ImageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'flavor_list') self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'keypair_list') self.mox.StubOutWithMock(api, 'keypair_list')
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
self.mox.StubOutWithMock(api, 'volume_list')
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_get(IsA(http.HttpRequest), api.image_get(IsA(http.HttpRequest),
image.id).AndReturn(image) image.id).AndReturn(image)
api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn( api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(
self.quota_usages.first()) self.quota_usages.first())
exc = keystone_exceptions.ClientException('Failed.') api.flavor_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
api.flavor_list(IsA(http.HttpRequest)).AndRaise(exc) api.flavor_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
api.flavor_list(IsA(http.HttpRequest)).AndRaise(exc)
api.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list()) api.keypair_list(IsA(http.HttpRequest)).AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list()) .AndReturn(self.security_groups.list())
@ -154,13 +164,18 @@ class ImageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'flavor_list') self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'keypair_list') self.mox.StubOutWithMock(api, 'keypair_list')
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
self.mox.StubOutWithMock(api, 'volume_list')
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_get(IsA(http.HttpRequest), image.id).AndReturn(image) api.image_get(IsA(http.HttpRequest), image.id).AndReturn(image)
api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn( api.tenant_quota_usages(IsA(http.HttpRequest)).AndReturn(
self.quota_usages.first()) self.quota_usages.first())
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list()) api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list()) api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
exception = keystone_exceptions.ClientException('Failed.') api.keypair_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
api.keypair_list(IsA(http.HttpRequest)).AndRaise(exception)
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list()) .AndReturn(self.security_groups.list())
self.mox.ReplayAll() self.mox.ReplayAll()
@ -186,14 +201,16 @@ class ImageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'security_group_list') self.mox.StubOutWithMock(api, 'security_group_list')
self.mox.StubOutWithMock(api, 'server_create') self.mox.StubOutWithMock(api, 'server_create')
self.mox.StubOutWithMock(api, 'volume_list') self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list()) api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
api.keypair_list(IgnoreArg()).AndReturn(self.keypairs.list()) api.keypair_list(IgnoreArg()).AndReturn(self.keypairs.list())
api.security_group_list(IsA(http.HttpRequest)) \ api.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list()) .AndReturn(self.security_groups.list())
api.image_get(IgnoreArg(), image.id).AndReturn(image) api.image_get(IgnoreArg(), image.id).AndReturn(image)
api.volume_list(IgnoreArg()).AndReturn(self.volumes.list()) api.volume_list(IgnoreArg()).AndReturn(self.volumes.list())
exc = keystone_exceptions.ClientException('Failed')
api.server_create(IsA(http.HttpRequest), api.server_create(IsA(http.HttpRequest),
server.name, server.name,
image.id, image.id,
@ -202,7 +219,8 @@ class ImageViewTests(test.TestCase):
USER_DATA, USER_DATA,
[sec_group.name], [sec_group.name],
None, None,
instance_count=IsA(int)).AndRaise(exc) instance_count=IsA(int)) \
.AndRaise(self.exceptions.keystone)
self.mox.ReplayAll() self.mox.ReplayAll()
form_data = {'method': 'LaunchForm', form_data = {'method': 'LaunchForm',
@ -284,7 +302,7 @@ class ImageViewTests(test.TestCase):
image = self.images.first() image = self.images.first()
self.mox.StubOutWithMock(api.glance, 'image_get') self.mox.StubOutWithMock(api.glance, 'image_get')
api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \ api.glance.image_get(IsA(http.HttpRequest), str(image.id)) \
.AndRaise(glance_exception.ClientException('Error')) .AndRaise(self.exceptions.glance)
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('horizon:nova:images_and_snapshots:images:detail', url = reverse('horizon:nova:images_and_snapshots:images:detail',

View File

@ -20,7 +20,6 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from novaclient import exceptions as novaclient_exceptions
from mox import IsA from mox import IsA
from horizon import api from horizon import api
@ -58,8 +57,8 @@ class SnapshotsViewTests(test.TestCase):
def test_create_get_server_exception(self): def test_create_get_server_exception(self):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_get') self.mox.StubOutWithMock(api, 'server_get')
exc = novaclient_exceptions.ClientException('apiException') api.server_get(IsA(http.HttpRequest), server.id) \
api.server_get(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('horizon:nova:images_and_snapshots:snapshots:create', url = reverse('horizon:nova:images_and_snapshots:snapshots:create',
@ -97,9 +96,8 @@ class SnapshotsViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'server_get') self.mox.StubOutWithMock(api, 'server_get')
self.mox.StubOutWithMock(api, 'snapshot_create') self.mox.StubOutWithMock(api, 'snapshot_create')
api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server) api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
exc = novaclient_exceptions.ClientException('apiException')
api.snapshot_create(IsA(http.HttpRequest), server.id, snapshot.name) \ api.snapshot_create(IsA(http.HttpRequest), server.id, snapshot.name) \
.AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'method': 'CreateSnapshot', formData = {'method': 'CreateSnapshot',

View File

@ -22,7 +22,6 @@
from copy import deepcopy from copy import deepcopy
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from glanceclient.common import exceptions as glance_exception
from mox import IsA from mox import IsA
from horizon import api from horizon import api
@ -38,6 +37,9 @@ class ImagesAndSnapshotsTests(test.TestCase):
snapshots = self.snapshots.list() snapshots = self.snapshots.list()
self.mox.StubOutWithMock(api, 'image_list_detailed') self.mox.StubOutWithMock(api, 'image_list_detailed')
self.mox.StubOutWithMock(api, 'snapshot_list_detailed') self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_list_detailed(IsA(http.HttpRequest)).AndReturn(images) api.image_list_detailed(IsA(http.HttpRequest)).AndReturn(images)
api.snapshot_list_detailed(IsA(http.HttpRequest)).AndReturn(snapshots) api.snapshot_list_detailed(IsA(http.HttpRequest)).AndReturn(snapshots)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -53,6 +55,9 @@ class ImagesAndSnapshotsTests(test.TestCase):
def test_index_no_images(self): def test_index_no_images(self):
self.mox.StubOutWithMock(api, 'snapshot_list_detailed') self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
self.mox.StubOutWithMock(api, 'image_list_detailed') self.mox.StubOutWithMock(api, 'image_list_detailed')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_list_detailed(IsA(http.HttpRequest)).AndReturn([]) api.image_list_detailed(IsA(http.HttpRequest)).AndReturn([])
api.snapshot_list_detailed(IsA(http.HttpRequest)) \ api.snapshot_list_detailed(IsA(http.HttpRequest)) \
.AndReturn(self.snapshots.list()) .AndReturn(self.snapshots.list())
@ -64,8 +69,11 @@ class ImagesAndSnapshotsTests(test.TestCase):
def test_index_error(self): def test_index_error(self):
self.mox.StubOutWithMock(api, 'image_list_detailed') self.mox.StubOutWithMock(api, 'image_list_detailed')
self.mox.StubOutWithMock(api, 'snapshot_list_detailed') self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
exc = glance_exception.ClientException('error') self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.image_list_detailed(IsA(http.HttpRequest)).AndRaise(exc) api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_list_detailed(IsA(http.HttpRequest)) \
.AndRaise(self.exceptions.glance)
api.snapshot_list_detailed(IsA(http.HttpRequest)) \ api.snapshot_list_detailed(IsA(http.HttpRequest)) \
.AndReturn(self.snapshots.list()) .AndReturn(self.snapshots.list())
self.mox.ReplayAll() self.mox.ReplayAll()
@ -75,17 +83,25 @@ class ImagesAndSnapshotsTests(test.TestCase):
def test_queued_snapshot_actions(self): def test_queued_snapshot_actions(self):
images = self.images.list() images = self.images.list()
snapshots = self.snapshots.list() snapshots = self.snapshots.list()
snapshot1 = deepcopy(snapshots[0]) snapshot1 = deepcopy(snapshots[0])
snapshot1.status = 'active' snapshot1.status = 'active'
snapshot1.owner = None
snapshot2 = deepcopy(snapshots[0]) snapshot2 = deepcopy(snapshots[0])
snapshot2.id = 4 snapshot2.id = 4
snapshot2.name = "snap2" snapshot2.name = "snap2"
snapshot2.status = "queued" snapshot2.status = "queued"
snapshot2.owner = '1' snapshot2.owner = '1'
new_snapshots = [snapshot1, snapshot2] new_snapshots = [snapshot1, snapshot2]
self.mox.StubOutWithMock(api, 'image_list_detailed') self.mox.StubOutWithMock(api, 'image_list_detailed')
self.mox.StubOutWithMock(api, 'snapshot_list_detailed') self.mox.StubOutWithMock(api, 'snapshot_list_detailed')
self.mox.StubOutWithMock(api, 'volume_snapshot_list')
api.volume_snapshot_list(IsA(http.HttpRequest)) \
.AndReturn(self.volumes.list())
api.image_list_detailed(IsA(http.HttpRequest)).AndReturn(images) api.image_list_detailed(IsA(http.HttpRequest)).AndReturn(images)
api.snapshot_list_detailed(IsA(http.HttpRequest)).\ api.snapshot_list_detailed(IsA(http.HttpRequest)).\
AndReturn(new_snapshots) AndReturn(new_snapshots)

View File

@ -83,7 +83,7 @@ class TogglePause(tables.BatchAction):
action_past = (_("Paused"), _("Unpaused")) action_past = (_("Paused"), _("Unpaused"))
data_type_singular = _("Instance") data_type_singular = _("Instance")
data_type_plural = _("Instances") data_type_plural = _("Instances")
classes = ("btn-pause") classes = ("btn-pause",)
def allowed(self, request, instance=None): def allowed(self, request, instance=None):
self.paused = False self.paused = False
@ -111,7 +111,7 @@ class ToggleSuspend(tables.BatchAction):
action_past = (_("Suspended"), _("Resumed")) action_past = (_("Suspended"), _("Resumed"))
data_type_singular = _("Instance") data_type_singular = _("Instance")
data_type_plural = _("Instances") data_type_plural = _("Instances")
classes = ("btn-suspend") classes = ("btn-suspend",)
def allowed(self, request, instance=None): def allowed(self, request, instance=None):
self.suspended = False self.suspended = False

View File

@ -21,7 +21,6 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from mox import IsA, IgnoreArg from mox import IsA, IgnoreArg
from novaclient import exceptions as nova_exceptions
from horizon import api from horizon import api
from horizon import test from horizon import test
@ -45,6 +44,8 @@ class InstanceViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'flavor_list') self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'server_delete') self.mox.StubOutWithMock(api, 'server_delete')
self.mox.StubOutWithMock(api, 'volume_list')
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list()) api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
api.server_delete(IsA(http.HttpRequest), server.id) api.server_delete(IsA(http.HttpRequest), server.id)
@ -59,10 +60,12 @@ class InstanceViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'flavor_list') self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'server_delete') self.mox.StubOutWithMock(api, 'server_delete')
self.mox.StubOutWithMock(api, 'volume_list')
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list()) api.flavor_list(IgnoreArg()).AndReturn(self.flavors.list())
exc = nova_exceptions.ClientException(500) api.server_delete(IsA(http.HttpRequest), server.id) \
api.server_delete(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__terminate__%s' % server.id} formData = {'action': 'instances__terminate__%s' % server.id}
@ -73,6 +76,10 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_pause') self.mox.StubOutWithMock(api, 'server_pause')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.server_pause(IsA(http.HttpRequest), server.id) api.server_pause(IsA(http.HttpRequest), server.id)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -83,11 +90,15 @@ class InstanceViewTests(test.TestCase):
def test_pause_instance_exception(self): def test_pause_instance_exception(self):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'server_pause') self.mox.StubOutWithMock(api, 'server_pause')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
exc = nova_exceptions.ClientException(500) api.server_pause(IsA(http.HttpRequest), server.id) \
api.server_pause(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__pause__%s' % server.id} formData = {'action': 'instances__pause__%s' % server.id}
@ -97,8 +108,12 @@ class InstanceViewTests(test.TestCase):
def test_unpause_instance(self): def test_unpause_instance(self):
server = self.servers.first() server = self.servers.first()
server.status = "PAUSED" server.status = "PAUSED"
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'server_unpause') self.mox.StubOutWithMock(api, 'server_unpause')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.server_unpause(IsA(http.HttpRequest), server.id) api.server_unpause(IsA(http.HttpRequest), server.id)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -110,11 +125,15 @@ class InstanceViewTests(test.TestCase):
def test_unpause_instance_exception(self): def test_unpause_instance_exception(self):
server = self.servers.first() server = self.servers.first()
server.status = "PAUSED" server.status = "PAUSED"
self.mox.StubOutWithMock(api, 'server_unpause') self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'server_unpause')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
exc = nova_exceptions.ClientException(500) api.server_unpause(IsA(http.HttpRequest), server.id) \
api.server_unpause(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__pause__%s' % server.id} formData = {'action': 'instances__pause__%s' % server.id}
@ -125,6 +144,10 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_reboot') self.mox.StubOutWithMock(api, 'server_reboot')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.server_reboot(IsA(http.HttpRequest), server.id) api.server_reboot(IsA(http.HttpRequest), server.id)
self.mox.ReplayAll() self.mox.ReplayAll()
@ -137,9 +160,13 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_reboot') self.mox.StubOutWithMock(api, 'server_reboot')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
exc = nova_exceptions.ClientException(500) api.server_reboot(IsA(http.HttpRequest), server.id) \
api.server_reboot(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__reboot__%s' % server.id} formData = {'action': 'instances__reboot__%s' % server.id}
@ -150,6 +177,10 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_suspend') self.mox.StubOutWithMock(api, 'server_suspend')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.server_suspend(IsA(http.HttpRequest), unicode(server.id)) api.server_suspend(IsA(http.HttpRequest), unicode(server.id))
self.mox.ReplayAll() self.mox.ReplayAll()
@ -162,10 +193,13 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_suspend') self.mox.StubOutWithMock(api, 'server_suspend')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
exception = nova_exceptions.ClientException(500)
api.server_suspend(IsA(http.HttpRequest), api.server_suspend(IsA(http.HttpRequest),
unicode(server.id)).AndRaise(exception) unicode(server.id)).AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__suspend__%s' % server.id} formData = {'action': 'instances__suspend__%s' % server.id}
@ -177,6 +211,10 @@ class InstanceViewTests(test.TestCase):
server.status = "SUSPENDED" server.status = "SUSPENDED"
self.mox.StubOutWithMock(api, 'server_resume') self.mox.StubOutWithMock(api, 'server_resume')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.server_resume(IsA(http.HttpRequest), unicode(server.id)) api.server_resume(IsA(http.HttpRequest), unicode(server.id))
self.mox.ReplayAll() self.mox.ReplayAll()
@ -190,10 +228,13 @@ class InstanceViewTests(test.TestCase):
server.status = "SUSPENDED" server.status = "SUSPENDED"
self.mox.StubOutWithMock(api, 'server_resume') self.mox.StubOutWithMock(api, 'server_resume')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
exception = nova_exceptions.ClientException(500)
api.server_resume(IsA(http.HttpRequest), api.server_resume(IsA(http.HttpRequest),
unicode(server.id)).AndRaise(exception) unicode(server.id)).AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'instances__suspend__%s' % server.id} formData = {'action': 'instances__suspend__%s' % server.id}
@ -223,9 +264,9 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_console_output') self.mox.StubOutWithMock(api, 'server_console_output')
exc = nova_exceptions.ClientException(500)
api.server_console_output(IsA(http.HttpRequest), api.server_console_output(IsA(http.HttpRequest),
server.id, tail_length=None).AndRaise(exc) server.id, tail_length=None) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('horizon:nova:instances_and_volumes:instances:console', url = reverse('horizon:nova:instances_and_volumes:instances:console',
@ -258,8 +299,8 @@ class InstanceViewTests(test.TestCase):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_vnc_console') self.mox.StubOutWithMock(api, 'server_vnc_console')
exc = nova_exceptions.ClientException(500) api.server_vnc_console(IsA(http.HttpRequest), server.id) \
api.server_vnc_console(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('horizon:nova:instances_and_volumes:instances:vnc', url = reverse('horizon:nova:instances_and_volumes:instances:vnc',
@ -283,8 +324,8 @@ class InstanceViewTests(test.TestCase):
def test_instance_update_get_server_get_exception(self): def test_instance_update_get_server_get_exception(self):
server = self.servers.first() server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_get') self.mox.StubOutWithMock(api, 'server_get')
exc = nova_exceptions.ClientException(500) api.server_get(IsA(http.HttpRequest), server.id) \
api.server_get(IsA(http.HttpRequest), server.id).AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
url = reverse('horizon:nova:instances_and_volumes:instances:update', url = reverse('horizon:nova:instances_and_volumes:instances:update',
@ -316,9 +357,8 @@ class InstanceViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'server_get') self.mox.StubOutWithMock(api, 'server_get')
self.mox.StubOutWithMock(api, 'server_update') self.mox.StubOutWithMock(api, 'server_update')
api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server) api.server_get(IsA(http.HttpRequest), server.id).AndReturn(server)
exc = nova_exceptions.ClientException(500)
api.server_update(IsA(http.HttpRequest), server.id, server.name) \ api.server_update(IsA(http.HttpRequest), server.id, server.name) \
.AndRaise(exc) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'method': 'UpdateInstance', formData = {'method': 'UpdateInstance',

View File

@ -22,7 +22,6 @@ from copy import deepcopy
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from mox import IsA from mox import IsA
from novaclient import exceptions as novaclient_exceptions
from horizon import api from horizon import api
from horizon import test from horizon import test
@ -30,8 +29,10 @@ from horizon import test
class InstancesAndVolumesViewTest(test.TestCase): class InstancesAndVolumesViewTest(test.TestCase):
def test_index(self): def test_index(self):
self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list') self.mox.StubOutWithMock(api, 'volume_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list()) api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
@ -61,6 +62,8 @@ class InstancesAndVolumesViewTest(test.TestCase):
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list') self.mox.StubOutWithMock(api, 'volume_list')
self.mox.StubOutWithMock(api, 'flavor_list')
api.flavor_list(IsA(http.HttpRequest)).AndReturn(self.flavors.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())
api.volume_list(IsA(http.HttpRequest)).AndReturn(volumes) api.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
@ -91,8 +94,7 @@ class InstancesAndVolumesViewTest(test.TestCase):
def test_index_server_list_exception(self): def test_index_server_list_exception(self):
self.mox.StubOutWithMock(api, 'server_list') self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list') self.mox.StubOutWithMock(api, 'volume_list')
exception = novaclient_exceptions.ClientException('apiException') api.server_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
api.server_list(IsA(http.HttpRequest)).AndRaise(exception)
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list()) api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.list())
api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list()) api.server_list(IsA(http.HttpRequest)).AndReturn(self.servers.list())

View File

@ -80,13 +80,12 @@ class UsageViewTests(test.TestCase):
self.mox.StubOutWithMock(api, 'usage_get') self.mox.StubOutWithMock(api, 'usage_get')
timestamp = datetime.datetime(now.year, now.month, 1, now.hour, timestamp = datetime.datetime(now.year, now.month, 1, now.hour,
now.minute, now.second) now.minute, now.second)
exception = nova_exceptions.ClientException(500)
api.usage_get(IsA(http.HttpRequest), api.usage_get(IsA(http.HttpRequest),
self.tenant.id, self.tenant.id,
timestamp, timestamp,
datetime.datetime(now.year, now.month, now.day, now.hour, datetime.datetime(now.year, now.month, now.day, now.hour,
now.minute, now.second)) \ now.minute, now.second)) \
.AndRaise(exception) .AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()
res = self.client.get(reverse('horizon:nova:overview:index')) res = self.client.get(reverse('horizon:nova:overview:index'))

View File

@ -46,9 +46,8 @@ class InstanceViewTest(test.BaseAdminViewTests):
def test_index_server_list_exception(self): def test_index_server_list_exception(self):
self.mox.StubOutWithMock(api.nova, 'server_list') self.mox.StubOutWithMock(api.nova, 'server_list')
self.mox.StubOutWithMock(api.nova, 'flavor_list') self.mox.StubOutWithMock(api.nova, 'flavor_list')
exception = novaclient_exceptions.ClientException('apiException')
api.nova.server_list(IsA(http.HttpRequest), api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndRaise(exception) all_tenants=True).AndRaise(self.exceptions.nova)
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -1,6 +1,5 @@
import logging import logging
from django import shortcuts
from django.contrib import messages from django.contrib import messages
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -10,6 +9,9 @@ from horizon import tables
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
ENABLE = 0
DISABLE = 1
class CreateUserLink(tables.LinkAction): class CreateUserLink(tables.LinkAction):
name = "create" name = "create"
@ -30,67 +32,41 @@ class EditUserLink(tables.LinkAction):
classes = ("ajax-modal", "btn-edit") classes = ("ajax-modal", "btn-edit")
class EnableUsersAction(tables.Action): class ToggleEnabled(tables.BatchAction):
name = "enable" name = "enable"
verbose_name = _("Enable") action_present = (_("Enable"), _("Disable"))
verbose_name_plural = _("Enable Users") action_past = (_("Enabled"), _("Disabled"))
data_type_singular = _("User")
data_type_plural = _("Users")
classes = ("btn-enable",) classes = ("btn-enable",)
def allowed(self, request, user): def allowed(self, request, user=None):
return not user.enabled self.enabled = True
if not user:
def handle(self, data_table, request, object_ids): return self.enabled
failures = 0 self.enabled = user.enabled
enabled = [] if self.enabled:
for obj_id in object_ids: self.current_present_action = DISABLE
try:
api.keystone.user_update_enabled(request, obj_id, True)
enabled.append(obj_id)
except Exception, e:
failures += 1
messages.error(request, _("Error enabling user: %s") % e)
LOG.exception("Error enabling user.")
if failures:
messages.info(request, _("Enabled the following users: %s")
% ", ".join(enabled))
else: else:
messages.success(request, _("Successfully enabled users: %s") self.current_present_action = ENABLE
% ", ".join(enabled)) return True
return shortcuts.redirect('horizon:syspanel:users:index')
def update(self, request, user=None):
super(ToggleEnabled, self).update(request, user)
if user and user.id == request.user.id:
self.attrs["disabled"] = "disabled"
class DisableUsersAction(tables.Action): def action(self, request, obj_id):
name = "disable" if obj_id == request.user.id:
verbose_name = _("Disable") messages.info(request, _('You cannot disable the user you are '
verbose_name_plural = _("Disable Users") 'currently logged in as.'))
classes = ("btn-disable",) return
if self.enabled:
def allowed(self, request, user): api.keystone.user_update_enabled(request, obj_id, False)
return user.enabled self.current_past_action = DISABLE
def handle(self, data_table, request, object_ids):
failures = 0
disabled = []
for obj_id in object_ids:
if obj_id == request.user.id:
messages.info(request, _('You cannot disable the user you are '
'currently logged in as.'))
continue
try:
api.keystone.user_update_enabled(request, obj_id, False)
disabled.append(obj_id)
except Exception, e:
failures += 1
messages.error(request, _("Error disabling user: %s") % e)
LOG.exception("Error disabling user.")
if failures:
messages.info(request, _("Disabled the following users: %s")
% ", ".join(disabled))
else: else:
if disabled: api.keystone.user_update_enabled(request, obj_id, True)
messages.success(request, _("Successfully disabled users: %s") self.current_past_action = ENABLE
% ", ".join(disabled))
return shortcuts.redirect('horizon:syspanel:users:index')
class DeleteUsersAction(tables.DeleteAction): class DeleteUsersAction(tables.DeleteAction):
@ -135,11 +111,11 @@ class UsersTable(tables.DataTable):
# verbose_name=_('Default Project')) # verbose_name=_('Default Project'))
enabled = tables.Column('enabled', verbose_name=_('Enabled'), enabled = tables.Column('enabled', verbose_name=_('Enabled'),
status=True, status=True,
status_choices=STATUS_CHOICES) status_choices=STATUS_CHOICES,
empty_value="False")
class Meta: class Meta:
name = "users" name = "users"
verbose_name = _("Users") verbose_name = _("Users")
row_actions = (EditUserLink, EnableUsersAction, DisableUsersAction, row_actions = (EditUserLink, ToggleEnabled, DeleteUsersAction)
DeleteUsersAction)
table_actions = (UserFilterAction, CreateUserLink, DeleteUsersAction) table_actions = (UserFilterAction, CreateUserLink, DeleteUsersAction)

View File

@ -20,7 +20,6 @@
from django import http from django import http
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from keystoneclient import exceptions as keystone_exceptions
from mox import IgnoreArg, IsA from mox import IgnoreArg, IsA
from horizon import api from horizon import api
@ -255,7 +254,7 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')}) @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_user(self): def test_enable_user(self):
user = self.users.get(id="2") user = self.users.get(id="2")
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list()) api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(), api.keystone.user_update_enabled(IgnoreArg(),
user.id, user.id,
@ -271,6 +270,7 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')}) @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_disable_user(self): def test_disable_user(self):
user = self.users.get(id="2") user = self.users.get(id="2")
self.assertTrue(user.enabled)
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list()) api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(), api.keystone.user_update_enabled(IgnoreArg(),
@ -279,7 +279,7 @@ class UsersViewTests(test.BaseAdminViewTests):
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'users__disable__%s' % user.id} formData = {'action': 'users__enable__%s' % user.id}
res = self.client.post(USERS_INDEX_URL, formData) res = self.client.post(USERS_INDEX_URL, formData)
self.assertRedirectsNoFollow(res, USERS_INDEX_URL) self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
@ -287,14 +287,10 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')}) @test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_disable_user_exception(self): def test_enable_disable_user_exception(self):
user = self.users.get(id="2") user = self.users.get(id="2")
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list()) api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api_exception = keystone_exceptions.ClientException('apiException', api.keystone.user_update_enabled(IgnoreArg(), user.id, True) \
message='apiException') .AndRaise(self.exceptions.keystone)
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
True).AndRaise(api_exception)
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'users__enable__%s' % user.id} formData = {'action': 'users__enable__%s' % user.id}
@ -309,7 +305,7 @@ class UsersViewTests(test.BaseAdminViewTests):
self.mox.ReplayAll() self.mox.ReplayAll()
formData = {'action': 'users__disable__%s' % self.request.user.id} formData = {'action': 'users__enable__%s' % self.request.user.id}
res = self.client.post(USERS_INDEX_URL, formData, follow=True) res = self.client.post(USERS_INDEX_URL, formData, follow=True)
self.assertEqual(list(res.context['messages'])[0].message, self.assertEqual(list(res.context['messages'])[0].message,

View File

@ -19,10 +19,12 @@ Exceptions raised by the Horizon code and the machinery for handling them.
""" """
import logging import logging
import os
import sys import sys
from django.conf import settings from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.utils import termcolors
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from cloudfiles import errors as swiftclient from cloudfiles import errors as swiftclient
from glanceclient.common import exceptions as glanceclient from glanceclient.common import exceptions as glanceclient
@ -31,6 +33,7 @@ from novaclient import exceptions as novaclient
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
PALETTE = termcolors.PALETTES[termcolors.DEFAULT_PALETTE]
class HorizonException(Exception): class HorizonException(Exception):
@ -106,6 +109,9 @@ class AlreadyExists(HorizonException):
def __repr__(self): def __repr__(self):
return self.msg % self.attrs return self.msg % self.attrs
def __str__(self):
return self.msg % self.attrs
def __unicode__(self): def __unicode__(self):
return _(self.msg) % self.attrs return _(self.msg) % self.attrs
@ -152,7 +158,12 @@ RECOVERABLE = (keystoneclient.ClientException,
RECOVERABLE += tuple(EXCEPTION_CONFIG.get('recoverable', [])) RECOVERABLE += tuple(EXCEPTION_CONFIG.get('recoverable', []))
def handle(request, message=None, redirect=None, ignore=False, escalate=False): def _error_color(msg):
return termcolors.colorize(msg, **PALETTE['ERROR'])
def handle(request, message=None, redirect=None, ignore=False,
escalate=False, log_level=None, force_log=None):
""" Centralized error handling for Horizon. """ Centralized error handling for Horizon.
Because Horizon consumes so many different APIs with completely Because Horizon consumes so many different APIs with completely
@ -181,6 +192,9 @@ def handle(request, message=None, redirect=None, ignore=False, escalate=False):
returned. returned.
""" """
exc_type, exc_value, exc_traceback = sys.exc_info() exc_type, exc_value, exc_traceback = sys.exc_info()
log_method = getattr(LOG, log_level or "exception")
force_log = force_log or os.environ.get("HORIZON_TEST_RUN", False)
force_silence = getattr(exc_value, "silence_logging", False)
# Because the same exception may travel through this method more than # Because the same exception may travel through this method more than
# once (if it's re-raised) we may want to treat it differently # once (if it's re-raised) we may want to treat it differently
@ -204,8 +218,9 @@ def handle(request, message=None, redirect=None, ignore=False, escalate=False):
if ignore: if ignore:
return NotAuthorized return NotAuthorized
request.user_logout() request.user_logout()
if not force_silence and not handled:
log_method(_error_color("Unauthorized: %s" % exc_value))
if not handled: if not handled:
LOG.debug("Unauthorized: %s" % exc_value)
# We get some pretty useless error messages back from # We get some pretty useless error messages back from
# some clients, so let's define our own fallback. # some clients, so let's define our own fallback.
fallback = _("Unauthorized. Please try logging in again.") fallback = _("Unauthorized. Please try logging in again.")
@ -214,8 +229,9 @@ def handle(request, message=None, redirect=None, ignore=False, escalate=False):
if issubclass(exc_type, NOT_FOUND): if issubclass(exc_type, NOT_FOUND):
wrap = True wrap = True
if not force_silence and not handled and (not ignore or force_log):
log_method(_error_color("Not Found: %s" % exc_value))
if not ignore and not handled: if not ignore and not handled:
LOG.debug("Not Found: %s" % exc_value)
messages.error(request, message or exc_value) messages.error(request, message or exc_value)
if redirect: if redirect:
raise Http302(redirect) raise Http302(redirect)
@ -224,8 +240,9 @@ def handle(request, message=None, redirect=None, ignore=False, escalate=False):
if issubclass(exc_type, RECOVERABLE): if issubclass(exc_type, RECOVERABLE):
wrap = True wrap = True
if not force_silence and not handled and (not ignore or force_log):
log_method(_error_color("Recoverable error: %s" % exc_value))
if not ignore and not handled: if not ignore and not handled:
LOG.debug("Recoverable error: %s" % exc_value)
messages.error(request, message or exc_value) messages.error(request, message or exc_value)
if redirect: if redirect:
raise Http302(redirect) raise Http302(redirect)

View File

@ -19,6 +19,7 @@
# under the License. # under the License.
import datetime import datetime
import os
import cloudfiles as swift_client import cloudfiles as swift_client
from django import http from django import http
@ -131,6 +132,7 @@ class TestCase(django_test.TestCase):
self.request.session = self.client._session() self.request.session = self.client._session()
self.request.session['token'] = self.token.id self.request.session['token'] = self.token.id
middleware.HorizonMiddleware().process_request(self.request) middleware.HorizonMiddleware().process_request(self.request)
os.environ["HORIZON_TEST_RUN"] = "True"
def tearDown(self): def tearDown(self):
self.mox.UnsetStubs() self.mox.UnsetStubs()
@ -138,6 +140,7 @@ class TestCase(django_test.TestCase):
context_processors.horizon = self._real_horizon_context_processor context_processors.horizon = self._real_horizon_context_processor
users.get_user_from_request = self._real_get_user_from_request users.get_user_from_request = self._real_get_user_from_request
self.mox.VerifyAll() self.mox.VerifyAll()
del os.environ["HORIZON_TEST_RUN"]
def setActiveUser(self, id=None, token=None, username=None, tenant_id=None, def setActiveUser(self, id=None, token=None, username=None, tenant_id=None,
service_catalog=None, tenant_name=None, roles=None, service_catalog=None, tenant_name=None, roles=None,

View File

@ -118,6 +118,7 @@ class AuthViewTests(test.TestCase):
api.tenant_list_for_token(IsA(http.HttpRequest), api.tenant_list_for_token(IsA(http.HttpRequest),
aToken.id).AndReturn(tenants) aToken.id).AndReturn(tenants)
exc = keystone_exceptions.Unauthorized("Not authorized.") exc = keystone_exceptions.Unauthorized("Not authorized.")
exc.silence_logging = True
api.token_create_scoped(IsA(http.HttpRequest), api.token_create_scoped(IsA(http.HttpRequest),
disabled_tenant.id, disabled_tenant.id,
aToken.id).AndRaise(exc) aToken.id).AndRaise(exc)
@ -135,6 +136,7 @@ class AuthViewTests(test.TestCase):
def test_login_invalid_credentials(self): def test_login_invalid_credentials(self):
self.mox.StubOutWithMock(api, 'token_create') self.mox.StubOutWithMock(api, 'token_create')
unauthorized = keystone_exceptions.Unauthorized("Invalid") unauthorized = keystone_exceptions.Unauthorized("Invalid")
unauthorized.silence_logging = True
api.token_create(IsA(http.HttpRequest), "", self.user.name, api.token_create(IsA(http.HttpRequest), "", self.user.name,
self.user.password).AndRaise(unauthorized) self.user.password).AndRaise(unauthorized)
@ -152,11 +154,10 @@ class AuthViewTests(test.TestCase):
def test_login_exception(self): def test_login_exception(self):
self.mox.StubOutWithMock(api, 'token_create') self.mox.StubOutWithMock(api, 'token_create')
ex = keystone_exceptions.BadRequest('Cannot talk to keystone')
api.token_create(IsA(http.HttpRequest), api.token_create(IsA(http.HttpRequest),
"", "",
self.user.name, self.user.name,
self.user.password).AndRaise(ex) self.user.password).AndRaise(self.exceptions.keystone)
self.mox.ReplayAll() self.mox.ReplayAll()

View File

@ -88,7 +88,9 @@ class RecoverableErrorTab(horizon_tabs.Tab):
def get_context_data(self, request): def get_context_data(self, request):
# Raise a known recoverable error. # Raise a known recoverable error.
raise exceptions.AlreadyExists("Recoverable!", None) exc = exceptions.AlreadyExists("Recoverable!", horizon_tabs.Tab)
exc.silence_logging = True
raise exc
class TableTabGroup(horizon_tabs.TabGroup): class TableTabGroup(horizon_tabs.TabGroup):

View File

@ -0,0 +1,36 @@
# Copyright 2012 Nebula, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from glanceclient.common import exceptions as glance_exceptions
from keystoneclient import exceptions as keystone_exceptions
from novaclient import exceptions as nova_exceptions
from .utils import TestDataContainer
def data(TEST):
TEST.exceptions = TestDataContainer()
msg = "Expected failure."
keystone_exception = keystone_exceptions.ClientException(500, message=msg)
keystone_exception.silence_logging = True
TEST.exceptions.keystone = keystone_exception
nova_exception = nova_exceptions.ClientException(500, message=msg)
nova_exception.silence_logging = True
TEST.exceptions.nova = nova_exception
glance_exception = glance_exceptions.ClientException(500, message=msg)
glance_exception.silence_logging = True
TEST.exceptions.glance = glance_exception

View File

@ -25,6 +25,8 @@ def data(TEST):
snapshot_dict = {'name': u'snapshot', snapshot_dict = {'name': u'snapshot',
'container_format': u'ami', 'container_format': u'ami',
'id': 3, 'id': 3,
'status': "active",
'owner': TEST.tenant.id,
'properties': {'image_type': u'snapshot'}} 'properties': {'image_type': u'snapshot'}}
snapshot = Image(ImageManager(None), snapshot_dict) snapshot = Image(ImageManager(None), snapshot_dict)
TEST.snapshots.add(snapshot) TEST.snapshots.add(snapshot)
@ -32,12 +34,16 @@ def data(TEST):
# Images # Images
image_dict = {'id': '1', image_dict = {'id': '1',
'name': 'public_image', 'name': 'public_image',
'status': "active",
'owner': TEST.tenant.id,
'container_format': 'novaImage', 'container_format': 'novaImage',
'properties': {'image_type': u'image'}} 'properties': {'image_type': u'image'}}
public_image = Image(ImageManager(None), image_dict) public_image = Image(ImageManager(None), image_dict)
image_dict = {'id': '2', image_dict = {'id': '2',
'name': 'private_image', 'name': 'private_image',
'status': "active",
'owner': TEST.tenant.id,
'container_format': 'aki'} 'container_format': 'aki'}
private_image = Image(ImageManager(None), image_dict) private_image = Image(ImageManager(None), image_dict)

View File

@ -103,7 +103,8 @@ def data(TEST):
'name': 'test_user', 'name': 'test_user',
'email': 'test@example.com', 'email': 'test@example.com',
'password': 'password', 'password': 'password',
'token': 'test_token'} 'token': 'test_token',
'enabled': True}
user = users.User(users.UserManager(None), user_dict) user = users.User(users.UserManager(None), user_dict)
user_dict.update({'id': "2", user_dict.update({'id': "2",
'name': 'user_two', 'name': 'user_two',

View File

@ -14,13 +14,15 @@
def load_test_data(load_onto=None): def load_test_data(load_onto=None):
from . import exceptions
from . import glance_data from . import glance_data
from . import keystone_data from . import keystone_data
from . import nova_data from . import nova_data
from . import swift_data from . import swift_data
# The order of these loaders matters, some depend on others. # The order of these loaders matters, some depend on others.
loaders = (keystone_data.data, loaders = (exceptions.data,
keystone_data.data,
glance_data.data, glance_data.data,
nova_data.data, nova_data.data,
swift_data.data) swift_data.data)

View File

@ -115,6 +115,10 @@ LOGGING = {
'level': 'DEBUG', 'level': 'DEBUG',
'class': 'django.utils.log.NullHandler', 'class': 'django.utils.log.NullHandler',
}, },
'test': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
}
}, },
'loggers': { 'loggers': {
'django.db.backends': { 'django.db.backends': {
@ -122,19 +126,23 @@ LOGGING = {
'propagate': False, 'propagate': False,
}, },
'horizon': { 'horizon': {
'handlers': ['null'], 'handlers': ['test'],
'propagate': False, 'propagate': False,
}, },
'novaclient': { 'novaclient': {
'handlers': ['null'], 'handlers': ['test'],
'propagate': False, 'propagate': False,
}, },
'keystoneclient': { 'keystoneclient': {
'handlers': ['null'], 'handlers': ['test'],
'propagate': False,
},
'glanceclient': {
'handlers': ['test'],
'propagate': False, 'propagate': False,
}, },
'quantum': { 'quantum': {
'handlers': ['null'], 'handlers': ['test'],
'propagate': False, 'propagate': False,
}, },
'nose.plugins.manager': { 'nose.plugins.manager': {