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,
self.slug,
self.index_url_name))
except:
except Exception as exc:
# Logging here since this will often be called in a template
# 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
@property

View File

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

View File

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

View File

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

View File

@ -21,7 +21,6 @@
from django import http
from django.core.urlresolvers import reverse
from mox import IsA
from novaclient import exceptions as novaclient_exceptions
from horizon import api
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_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)) \
.AndReturn(self.keypairs.list())
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name)
@ -49,11 +58,20 @@ class KeyPairViewTests(test.TestCase):
keypair = self.keypairs.first()
self.mox.StubOutWithMock(api.nova, 'keypair_list')
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)) \
.AndReturn(self.keypairs.list())
exc = novaclient_exceptions.ClientException('clientException')
api.nova.keypair_delete(IsA(http.HttpRequest), keypair.name) \
.AndRaise(exc)
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
formData = {'action': 'keypairs__delete__%s' % keypair.name}
@ -93,10 +111,10 @@ class KeyPairViewTests(test.TestCase):
def test_generate_keypair_exception(self):
keypair = self.keypairs.first()
exc = novaclient_exceptions.ClientException('clientException')
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()
context = {'keypair_name': keypair.name}

View File

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

View File

@ -21,7 +21,7 @@
from django import http
from django.conf import settings
from django.core.urlresolvers import reverse
from novaclient import exceptions as novaclient_exceptions
from mox import IsA
from horizon import api
@ -67,10 +67,10 @@ class SecurityGroupsViewTests(test.TestCase):
def test_create_security_groups_post_exception(self):
sec_group = self.security_groups.first()
self.mox.StubOutWithMock(api, 'security_group_create')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_create(IsA(http.HttpRequest),
sec_group.name,
sec_group.description).AndRaise(exc)
sec_group.description) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
formData = {'method': 'CreateGroup',
@ -103,10 +103,19 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group_list = self.security_groups.list()
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, '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(
IsA(http.HttpRequest)).AndReturn(sec_group_list)
api.security_group_list(
@ -122,6 +131,7 @@ class SecurityGroupsViewTests(test.TestCase):
rule = self.security_group_rules.first()
self.mox.StubOutWithMock(api, 'security_group_rule_create')
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_rule_create(IsA(http.HttpRequest),
sec_group.id,
rule.ip_protocol,
@ -129,7 +139,6 @@ class SecurityGroupsViewTests(test.TestCase):
int(rule.to_port),
rule.ip_range['cidr'],
None).AndReturn(rule)
self.mox.StubOutWithMock(api, 'security_group_list')
api.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list)
self.mox.ReplayAll()
@ -198,17 +207,16 @@ class SecurityGroupsViewTests(test.TestCase):
sec_group = self.security_groups.first()
sec_group_list = self.security_groups.list()
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_list')
api.security_group_rule_create(IsA(http.HttpRequest),
sec_group.id,
rule.ip_protocol,
int(rule.from_port),
int(rule.to_port),
rule.ip_range['cidr'],
None).AndRaise(exc)
self.mox.StubOutWithMock(api, 'security_group_list')
None).AndRaise(self.exceptions.nova)
api.security_group_list(
IsA(http.HttpRequest)).AndReturn(sec_group_list)
self.mox.ReplayAll()
@ -241,9 +249,8 @@ class SecurityGroupsViewTests(test.TestCase):
rule = self.security_group_rules.first()
self.mox.StubOutWithMock(api, 'security_group_rule_delete')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_rule_delete(IsA(http.HttpRequest),
rule.id).AndRaise(exc)
rule.id).AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
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")
self.mox.StubOutWithMock(api, 'security_group_delete')
exc = novaclient_exceptions.ClientException('ClientException')
api.security_group_delete(IsA(http.HttpRequest),
sec_group.id).AndRaise(exc)
sec_group.id).AndRaise(self.exceptions.nova)
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, 'security_group_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.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(floating_ips)
@ -66,10 +69,10 @@ class AccessAndSecurityTests(test.TestCase):
self.servers.add(server3)
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),
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()
res = self.client.get(

View File

@ -36,26 +36,12 @@ class DeleteContainer(tables.DeleteAction):
data_type_plural = _("Containers")
def delete(self, request, obj_id):
api.swift_delete_container(request, obj_id)
def handle(self, table, request, object_ids):
# Overriden to show clearer error messages instead of generic message
deleted = []
for obj_id in object_ids:
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')
try:
api.swift_delete_container(request, obj_id)
except ContainerNotEmpty:
messages.error(request,
_('Containers must be empty before deletion.'))
raise
class CreateContainer(tables.LinkAction):

View File

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

View File

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

View File

@ -20,7 +20,6 @@
from django import http
from django.core.urlresolvers import reverse
from novaclient import exceptions as novaclient_exceptions
from mox import IsA
from horizon import api
@ -58,8 +57,8 @@ class SnapshotsViewTests(test.TestCase):
def test_create_get_server_exception(self):
server = self.servers.first()
self.mox.StubOutWithMock(api, 'server_get')
exc = novaclient_exceptions.ClientException('apiException')
api.server_get(IsA(http.HttpRequest), server.id).AndRaise(exc)
api.server_get(IsA(http.HttpRequest), server.id) \
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
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, 'snapshot_create')
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) \
.AndRaise(exc)
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
formData = {'method': 'CreateSnapshot',

View File

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

View File

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

View File

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

View File

@ -22,7 +22,6 @@ from copy import deepcopy
from django import http
from django.core.urlresolvers import reverse
from mox import IsA
from novaclient import exceptions as novaclient_exceptions
from horizon import api
from horizon import test
@ -30,8 +29,10 @@ from horizon import test
class InstancesAndVolumesViewTest(test.TestCase):
def test_index(self):
self.mox.StubOutWithMock(api, 'flavor_list')
self.mox.StubOutWithMock(api, 'server_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.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, '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.volume_list(IsA(http.HttpRequest)).AndReturn(volumes)
@ -91,8 +94,7 @@ class InstancesAndVolumesViewTest(test.TestCase):
def test_index_server_list_exception(self):
self.mox.StubOutWithMock(api, 'server_list')
self.mox.StubOutWithMock(api, 'volume_list')
exception = novaclient_exceptions.ClientException('apiException')
api.server_list(IsA(http.HttpRequest)).AndRaise(exception)
api.server_list(IsA(http.HttpRequest)).AndRaise(self.exceptions.nova)
api.volume_list(IsA(http.HttpRequest)).AndReturn(self.volumes.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')
timestamp = datetime.datetime(now.year, now.month, 1, now.hour,
now.minute, now.second)
exception = nova_exceptions.ClientException(500)
api.usage_get(IsA(http.HttpRequest),
self.tenant.id,
timestamp,
datetime.datetime(now.year, now.month, now.day, now.hour,
now.minute, now.second)) \
.AndRaise(exception)
.AndRaise(self.exceptions.nova)
self.mox.ReplayAll()
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):
self.mox.StubOutWithMock(api.nova, 'server_list')
self.mox.StubOutWithMock(api.nova, 'flavor_list')
exception = novaclient_exceptions.ClientException('apiException')
api.nova.server_list(IsA(http.HttpRequest),
all_tenants=True).AndRaise(exception)
all_tenants=True).AndRaise(self.exceptions.nova)
self.mox.ReplayAll()

View File

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

View File

@ -20,7 +20,6 @@
from django import http
from django.core.urlresolvers import reverse
from keystoneclient import exceptions as keystone_exceptions
from mox import IgnoreArg, IsA
from horizon import api
@ -255,7 +254,7 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_user(self):
user = self.users.get(id="2")
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
@ -271,6 +270,7 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_disable_user(self):
user = self.users.get(id="2")
self.assertTrue(user.enabled)
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api.keystone.user_update_enabled(IgnoreArg(),
@ -279,7 +279,7 @@ class UsersViewTests(test.BaseAdminViewTests):
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)
self.assertRedirectsNoFollow(res, USERS_INDEX_URL)
@ -287,14 +287,10 @@ class UsersViewTests(test.BaseAdminViewTests):
@test.create_stubs({api.keystone: ('user_update_enabled', 'user_list')})
def test_enable_disable_user_exception(self):
user = self.users.get(id="2")
user.enabled = False
api.keystone.user_list(IgnoreArg()).AndReturn(self.users.list())
api_exception = keystone_exceptions.ClientException('apiException',
message='apiException')
api.keystone.user_update_enabled(IgnoreArg(),
user.id,
True).AndRaise(api_exception)
api.keystone.user_update_enabled(IgnoreArg(), user.id, True) \
.AndRaise(self.exceptions.keystone)
self.mox.ReplayAll()
formData = {'action': 'users__enable__%s' % user.id}
@ -309,7 +305,7 @@ class UsersViewTests(test.BaseAdminViewTests):
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)
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 os
import sys
from django.conf import settings
from django.contrib import messages
from django.utils import termcolors
from django.utils.translation import ugettext as _
from cloudfiles import errors as swiftclient
from glanceclient.common import exceptions as glanceclient
@ -31,6 +33,7 @@ from novaclient import exceptions as novaclient
LOG = logging.getLogger(__name__)
PALETTE = termcolors.PALETTES[termcolors.DEFAULT_PALETTE]
class HorizonException(Exception):
@ -106,6 +109,9 @@ class AlreadyExists(HorizonException):
def __repr__(self):
return self.msg % self.attrs
def __str__(self):
return self.msg % self.attrs
def __unicode__(self):
return _(self.msg) % self.attrs
@ -152,7 +158,12 @@ RECOVERABLE = (keystoneclient.ClientException,
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.
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.
"""
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
# 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:
return NotAuthorized
request.user_logout()
if not force_silence and not handled:
log_method(_error_color("Unauthorized: %s" % exc_value))
if not handled:
LOG.debug("Unauthorized: %s" % exc_value)
# We get some pretty useless error messages back from
# some clients, so let's define our own fallback.
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):
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:
LOG.debug("Not Found: %s" % exc_value)
messages.error(request, message or exc_value)
if redirect:
raise Http302(redirect)
@ -224,8 +240,9 @@ def handle(request, message=None, redirect=None, ignore=False, escalate=False):
if issubclass(exc_type, RECOVERABLE):
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:
LOG.debug("Recoverable error: %s" % exc_value)
messages.error(request, message or exc_value)
if redirect:
raise Http302(redirect)

View File

@ -19,6 +19,7 @@
# under the License.
import datetime
import os
import cloudfiles as swift_client
from django import http
@ -131,6 +132,7 @@ class TestCase(django_test.TestCase):
self.request.session = self.client._session()
self.request.session['token'] = self.token.id
middleware.HorizonMiddleware().process_request(self.request)
os.environ["HORIZON_TEST_RUN"] = "True"
def tearDown(self):
self.mox.UnsetStubs()
@ -138,6 +140,7 @@ class TestCase(django_test.TestCase):
context_processors.horizon = self._real_horizon_context_processor
users.get_user_from_request = self._real_get_user_from_request
self.mox.VerifyAll()
del os.environ["HORIZON_TEST_RUN"]
def setActiveUser(self, id=None, token=None, username=None, tenant_id=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),
aToken.id).AndReturn(tenants)
exc = keystone_exceptions.Unauthorized("Not authorized.")
exc.silence_logging = True
api.token_create_scoped(IsA(http.HttpRequest),
disabled_tenant.id,
aToken.id).AndRaise(exc)
@ -135,6 +136,7 @@ class AuthViewTests(test.TestCase):
def test_login_invalid_credentials(self):
self.mox.StubOutWithMock(api, 'token_create')
unauthorized = keystone_exceptions.Unauthorized("Invalid")
unauthorized.silence_logging = True
api.token_create(IsA(http.HttpRequest), "", self.user.name,
self.user.password).AndRaise(unauthorized)
@ -152,11 +154,10 @@ class AuthViewTests(test.TestCase):
def test_login_exception(self):
self.mox.StubOutWithMock(api, 'token_create')
ex = keystone_exceptions.BadRequest('Cannot talk to keystone')
api.token_create(IsA(http.HttpRequest),
"",
self.user.name,
self.user.password).AndRaise(ex)
self.user.password).AndRaise(self.exceptions.keystone)
self.mox.ReplayAll()

View File

@ -88,7 +88,9 @@ class RecoverableErrorTab(horizon_tabs.Tab):
def get_context_data(self, request):
# 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):

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

View File

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

View File

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

View File

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