From 1e29f2b16ac56191a145c4cd96d2f55875c485e6 Mon Sep 17 00:00:00 2001 From: John Tran Date: Fri, 25 Mar 2011 13:17:51 -0700 Subject: [PATCH 01/13] added a simple test for describe_images with mock for detail funciton --- Authors | 1 + nova/tests/test_cloud.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/Authors b/Authors index 1679d2de..39a85195 100644 --- a/Authors +++ b/Authors @@ -29,6 +29,7 @@ Jesse Andrews Joe Heck Joel Moore John Dewey +John Tran Jonathan Bryce Jordan Rinke Josh Durgin diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index cf8ee7ef..2f0571ca 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -81,7 +81,12 @@ class CloudTestCase(test.TestCase): def fake_show(meh, context, id): return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} + def fake_detail(meh, context): + return [{'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, + 'type':'machine'}}] + self.stubs.Set(local.LocalImageService, 'show', fake_show) + self.stubs.Set(local.LocalImageService, 'detail', fake_detail) self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show) def tearDown(self): @@ -224,6 +229,11 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, comp1['id']) db.service_destroy(self.context, comp2['id']) + def test_describe_images(self): + result = self.cloud.describe_images(self.context) + result = result['imagesSet'][0] + self.assertEqual(result['imageId'], 'ami-00000001') + def test_console_output(self): instance_type = FLAGS.default_instance_type max_count = 1 From 1222d65bf64531ee4dcbd25963f981395e70718f Mon Sep 17 00:00:00 2001 From: John Tran Date: Mon, 28 Mar 2011 11:29:23 -0700 Subject: [PATCH 02/13] when image_id provided cannot be found, returns more informative error message. --- nova/tests/test_cloud.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 2f0571ca..8043d467 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -41,6 +41,7 @@ from nova.api.ec2 import cloud from nova.api.ec2 import ec2utils from nova.image import local from nova.objectstore import image +from nova.exception import NotEmpty, NotFound FLAGS = flags.FLAGS @@ -85,8 +86,12 @@ class CloudTestCase(test.TestCase): return [{'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, 'type':'machine'}}] + def fake_delete(meh, context, id): + return None + self.stubs.Set(local.LocalImageService, 'show', fake_show) self.stubs.Set(local.LocalImageService, 'detail', fake_detail) + self.stubs.Set(local.LocalImageService, 'delete', fake_delete) self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show) def tearDown(self): @@ -234,6 +239,16 @@ class CloudTestCase(test.TestCase): result = result['imagesSet'][0] self.assertEqual(result['imageId'], 'ami-00000001') + def test_deregister_image(self): + deregister_image = self.cloud.deregister_image + """When provided a valid image, should be successful""" + result1 = deregister_image(self.context, 'ami-00000001') + self.assertEqual(result1['imageId'], 'ami-00000001') + """Invalid image should throw an NotFound exception""" + self.stubs.UnsetAll() + self.assertRaises(NotFound, deregister_image, + self.context, 'ami-bad001') + def test_console_output(self): instance_type = FLAGS.default_instance_type max_count = 1 From f2c3e5b66c272f526929f207ab4589599722ceaa Mon Sep 17 00:00:00 2001 From: John Tran Date: Mon, 28 Mar 2011 18:16:55 -0700 Subject: [PATCH 03/13] made changes per code review: 1) removed import of image from objectstore 2) changed to comments instaed of triple quotes. --- nova/tests/test_cloud.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 20c85d79..b8a95e45 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -41,8 +41,7 @@ from nova.compute import power_state from nova.api.ec2 import cloud from nova.api.ec2 import ec2utils from nova.image import local -from nova.objectstore import image -from nova.exception import NotEmpty, NotFound +from nova.exception import NotFound FLAGS = flags.FLAGS @@ -75,16 +74,7 @@ class CloudTestCase(test.TestCase): def fake_show(meh, context, id): return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} - def fake_detail(meh, context): - return [{'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, - 'type':'machine'}}] - - def fake_delete(meh, context, id): - return None - self.stubs.Set(local.LocalImageService, 'show', fake_show) - self.stubs.Set(local.LocalImageService, 'detail', fake_detail) - self.stubs.Set(local.LocalImageService, 'delete', fake_delete) self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show) def tearDown(self): @@ -228,17 +218,27 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, comp2['id']) def test_describe_images(self): + def fake_detail(meh, context): + return [{'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, + 'type':'machine'}}] + self.stubs.Set(local.LocalImageService, 'detail', fake_detail) result = self.cloud.describe_images(self.context) result = result['imagesSet'][0] self.assertEqual(result['imageId'], 'ami-00000001') def test_deregister_image(self): deregister_image = self.cloud.deregister_image - """When provided a valid image, should be successful""" + def fake_delete(meh, context, id): + return None + self.stubs.Set(local.LocalImageService, 'delete', fake_delete) + # valid image result1 = deregister_image(self.context, 'ami-00000001') self.assertEqual(result1['imageId'], 'ami-00000001') - """Invalid image should throw an NotFound exception""" + # invalid image self.stubs.UnsetAll() + def fake_detail_empty(meh, context): + return [] + self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty) self.assertRaises(NotFound, deregister_image, self.context, 'ami-bad001') From 5b4be8d7e563914cabff3e137c50113190d16b83 Mon Sep 17 00:00:00 2001 From: John Tran Date: Mon, 28 Mar 2011 18:19:56 -0700 Subject: [PATCH 04/13] cleaned up var name --- nova/tests/test_cloud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index b8a95e45..07e52a6b 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -232,8 +232,8 @@ class CloudTestCase(test.TestCase): return None self.stubs.Set(local.LocalImageService, 'delete', fake_delete) # valid image - result1 = deregister_image(self.context, 'ami-00000001') - self.assertEqual(result1['imageId'], 'ami-00000001') + result = deregister_image(self.context, 'ami-00000001') + self.assertEqual(result['imageId'], 'ami-00000001') # invalid image self.stubs.UnsetAll() def fake_detail_empty(meh, context): From 71aaab3876511858e05e64c4757b9d6397a13ff0 Mon Sep 17 00:00:00 2001 From: John Tran Date: Tue, 29 Mar 2011 13:43:00 -0700 Subject: [PATCH 05/13] added blank lines in between functions & removed the test_describe_images (was meant for a diff bug lp682888) --- nova/tests/test_cloud.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 07e52a6b..582e40e0 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -217,27 +217,22 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, comp1['id']) db.service_destroy(self.context, comp2['id']) - def test_describe_images(self): - def fake_detail(meh, context): - return [{'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1, - 'type':'machine'}}] - self.stubs.Set(local.LocalImageService, 'detail', fake_detail) - result = self.cloud.describe_images(self.context) - result = result['imagesSet'][0] - self.assertEqual(result['imageId'], 'ami-00000001') - def test_deregister_image(self): deregister_image = self.cloud.deregister_image + def fake_delete(meh, context, id): return None + self.stubs.Set(local.LocalImageService, 'delete', fake_delete) # valid image result = deregister_image(self.context, 'ami-00000001') self.assertEqual(result['imageId'], 'ami-00000001') # invalid image self.stubs.UnsetAll() + def fake_detail_empty(meh, context): return [] + self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty) self.assertRaises(NotFound, deregister_image, self.context, 'ami-bad001') From 56f28d01c6a578a2e58a96e616363235556140a0 Mon Sep 17 00:00:00 2001 From: John Tran Date: Wed, 30 Mar 2011 12:37:56 -0700 Subject: [PATCH 06/13] updated per code review, replaced NotFound with exception.NotFound --- nova/tests/test_cloud.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 582e40e0..145da8ad 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -36,12 +36,12 @@ from nova import rpc from nova import service from nova import test from nova import utils +from nova import exception from nova.auth import manager from nova.compute import power_state from nova.api.ec2 import cloud from nova.api.ec2 import ec2utils from nova.image import local -from nova.exception import NotFound FLAGS = flags.FLAGS @@ -234,7 +234,7 @@ class CloudTestCase(test.TestCase): return [] self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty) - self.assertRaises(NotFound, deregister_image, + self.assertRaises(exception.NotFound, deregister_image, self.context, 'ami-bad001') def test_console_output(self): From 0c0d6b8a496e5b2dcb37c380460cb039dcf71f68 Mon Sep 17 00:00:00 2001 From: John Tran Date: Wed, 30 Mar 2011 12:44:22 -0700 Subject: [PATCH 07/13] removed trailing whitespace --- nova/tests/test_cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 145da8ad..cde8041f 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -36,7 +36,7 @@ from nova import rpc from nova import service from nova import test from nova import utils -from nova import exception +from nova import exception from nova.auth import manager from nova.compute import power_state from nova.api.ec2 import cloud From 84598a77da26ec2e7694281925301ba94c3135aa Mon Sep 17 00:00:00 2001 From: William Wolf Date: Wed, 4 May 2011 21:50:54 -0400 Subject: [PATCH 08/13] added myself to Authors --- Authors | 1 + 1 file changed, 1 insertion(+) diff --git a/Authors b/Authors index 1cdeeff9..99c07f7c 100644 --- a/Authors +++ b/Authors @@ -78,6 +78,7 @@ Trey Morris Tushar Patil Vasiliy Shlykov Vishvananda Ishaya +William Wolf Yoshiaki Tamura Youcef Laribi Zhixue Wu From c5d77455e93bf5e8d51e023d342a654ea0d13882 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Tue, 10 May 2011 18:55:07 +0000 Subject: [PATCH 09/13] remove stubbing of XenAPISession.wait_for_task for xenapi tests as it doesn't need to be faked. Also removed duplicate code that stubbed xenapi_conn._parse_xmlrpc_value. --- nova/tests/xenapi/stubs.py | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 205f6c90..6db06144 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -28,29 +28,6 @@ def stubout_instance_snapshot(stubs): @classmethod def fake_fetch_image(cls, session, instance_id, image, user, project, type): - # Stubout wait_for_task - def fake_wait_for_task(self, task, id): - class FakeEvent: - - def send(self, value): - self.rv = value - - def wait(self): - return self.rv - - done = FakeEvent() - self._poll_task(id, task, done) - rv = done.wait() - return rv - - def fake_loop(self): - pass - - stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', - fake_wait_for_task) - - stubs.Set(xenapi_conn.XenAPISession, '_stop_loop', fake_loop) - from nova.virt.xenapi.fake import create_vdi name_label = "instance-%s" % instance_id #TODO: create fake SR record @@ -63,11 +40,6 @@ def stubout_instance_snapshot(stubs): stubs.Set(vm_utils.VMHelper, 'fetch_image', fake_fetch_image) - def fake_parse_xmlrpc_value(val): - return val - - stubs.Set(xenapi_conn, '_parse_xmlrpc_value', fake_parse_xmlrpc_value) - def fake_wait_for_vhd_coalesce(session, instance_id, sr_ref, vdi_ref, original_parent_uuid): from nova.virt.xenapi.fake import create_vdi From 0f0caa88adfe375d7416f04ccd1b3fa315292cae Mon Sep 17 00:00:00 2001 From: John Tran Date: Thu, 12 May 2011 12:51:03 -0700 Subject: [PATCH 10/13] incorporated ImageNotFound instead of NotFound --- nova/tests/test_cloud.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 82dd14cb..af1dbfd4 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -282,7 +282,7 @@ class CloudTestCase(test.TestCase): def test_deregister_image(self): deregister_image = self.cloud.deregister_image - def fake_delete(meh, context, id): + def fake_delete(self, context, id): return None self.stubs.Set(local.LocalImageService, 'delete', fake_delete) @@ -292,11 +292,11 @@ class CloudTestCase(test.TestCase): # invalid image self.stubs.UnsetAll() - def fake_detail_empty(meh, context): + def fake_detail_empty(self, context): return [] self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty) - self.assertRaises(exception.NotFound, deregister_image, + self.assertRaises(exception.ImageNotFound, deregister_image, self.context, 'ami-bad001') def test_console_output(self): From af416b1db46e6359ee1b3b10b18ae2b2dade571c Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Thu, 12 May 2011 20:01:32 +0000 Subject: [PATCH 11/13] Add a test for parallel builds. verified this test fails before this fix and succeeds after this fix --- nova/tests/test_xenapi.py | 23 +++++++++++++++++++++++ nova/tests/xenapi/stubs.py | 9 +++++++++ 2 files changed, 32 insertions(+) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 375480a2..a4e67981 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -16,6 +16,7 @@ """Test suite for XenAPI.""" +import eventlet import functools import os import re @@ -197,6 +198,28 @@ class XenAPIVMTestCase(test.TestCase): self.context = context.RequestContext('fake', 'fake', False) self.conn = xenapi_conn.get_connection(False) + def test_parallel_builds(self): + stubs.stubout_loopingcall_delay(self.stubs) + + def _do_build(id, proj, user, *args): + values = { + 'id': id, + 'project_id': proj, + 'user_id': user, + 'image_id': 1, + 'kernel_id': 2, + 'ramdisk_id': 3, + 'instance_type_id': '3', # m1.large + 'mac_address': 'aa:bb:cc:dd:ee:ff', + 'os_type': 'linux'} + instance = db.instance_create(self.context, values) + self.conn.spawn(instance) + + gt1 = eventlet.spawn(_do_build, 1, self.project.id, self.user.id) + gt2 = eventlet.spawn(_do_build, 2, self.project.id, self.user.id) + gt1.wait() + gt2.wait() + def test_list_instances_0(self): instances = self.conn.list_instances() self.assertEquals(instances, []) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 6db06144..f3d3d0ce 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -16,6 +16,7 @@ """Stubouts, mocks and fixtures for the test suite""" +import eventlet from nova.virt import xenapi_conn from nova.virt.xenapi import fake from nova.virt.xenapi import volume_utils @@ -115,6 +116,14 @@ def stubout_loopingcall_start(stubs): self.f(*self.args, **self.kw) stubs.Set(utils.LoopingCall, 'start', fake_start) +def stubout_loopingcall_delay(stubs): + def fake_start(self, interval, now=True): + self._running = True + eventlet.sleep(1) + self.f(*self.args, **self.kw) + # This would fail before parallel xenapi calls were fixed + assert self._running == False + stubs.Set(utils.LoopingCall, 'start', fake_start) class FakeSessionForVMTests(fake.SessionBase): """ Stubs out a XenAPISession for VM tests """ From fe84780dd7276a09e720d723809bd5f3cc1f7c45 Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Fri, 13 May 2011 16:47:18 +0000 Subject: [PATCH 13/13] pep8 fixes --- nova/tests/xenapi/stubs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index f3d3d0ce..4833ccb0 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -116,6 +116,7 @@ def stubout_loopingcall_start(stubs): self.f(*self.args, **self.kw) stubs.Set(utils.LoopingCall, 'start', fake_start) + def stubout_loopingcall_delay(stubs): def fake_start(self, interval, now=True): self._running = True @@ -125,6 +126,7 @@ def stubout_loopingcall_delay(stubs): assert self._running == False stubs.Set(utils.LoopingCall, 'start', fake_start) + class FakeSessionForVMTests(fake.SessionBase): """ Stubs out a XenAPISession for VM tests """ def __init__(self, uri):