From ecc2afda9fed4e9e69edcc470baf254fac448ce7 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Tue, 18 Jan 2011 15:49:42 -0600 Subject: Plug VBD to existing instance and minor cleanup --- nova/tests/xenapi/stubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 292bd9ba9..313668826 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -37,7 +37,7 @@ def stubout_instance_snapshot(stubs): return self.rv done = FakeEvent() - self._poll_task(id, task, done) + self._poll_task(task, id, done) rv = done.wait() return rv -- cgit From 2b2f08dc1dfe1b55433c9122d7d42a480cdb5e67 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Tue, 18 Jan 2011 17:57:11 -0600 Subject: Fixed unit tests --- nova/tests/xenapi/stubs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index c1ba25e10..13603717c 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -27,7 +27,7 @@ def stubout_instance_snapshot(stubs): def fake_fetch_image(cls, session, instance_id, image, user, project, type): # Stubout wait_for_task - def fake_wait_for_task(self, id, task): + def fake_wait_for_task(self, task, id=None): class FakeEvent: def send(self, value): @@ -37,7 +37,7 @@ def stubout_instance_snapshot(stubs): return self.rv done = FakeEvent() - self._poll_task(task, id, done) + self._poll_task(id, task, done) rv = done.wait() return rv -- cgit From 4b77a532fd641947c9259327cef9104f689f1127 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Tue, 18 Jan 2011 18:09:58 -0600 Subject: Fixed unit tests --- nova/tests/xenapi/stubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 13603717c..66d232a7f 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -27,7 +27,7 @@ def stubout_instance_snapshot(stubs): def fake_fetch_image(cls, session, instance_id, image, user, project, type): # Stubout wait_for_task - def fake_wait_for_task(self, task, id=None): + def fake_wait_for_task(self, task, id): class FakeEvent: def send(self, value): -- cgit From 1dbdb180cb93a812f8336bbfc49bf67a5203d1eb Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Fri, 21 Jan 2011 12:00:45 +0000 Subject: OS-55: Fix current unit tests --- nova/tests/db/fakes.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 05bdd172e..72e093f99 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -58,6 +58,7 @@ def stub_out_db_instance_api(stubs): 'project_id': values['project_id'], 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()), 'instance_type': values['instance_type'], + 'key_data': None, 'memory_mb': type_data['memory_mb'], 'mac_address': values['mac_address'], 'vcpus': type_data['vcpus'], @@ -68,6 +69,7 @@ def stub_out_db_instance_api(stubs): def fake_network_get_by_instance(context, instance_id): fields = { 'bridge': 'xenbr0', + 'injected': False } return FakeModel(fields) -- cgit From 9039c2cc59904a72fc71255a3a31ec2b17018963 Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Fri, 21 Jan 2011 16:06:32 +0000 Subject: OS-55: Added unit test for network injection via xenstore --- nova/tests/db/fakes.py | 54 ++++++++++++++++++++++++++++++---------------- nova/tests/test_xenapi.py | 46 +++++++++++++++++++++++++++++++++------ nova/tests/xenapi/stubs.py | 15 +++++++++++++ 3 files changed, 90 insertions(+), 25 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 72e093f99..e92efbedd 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -23,23 +23,22 @@ from nova import db from nova import utils from nova.compute import instance_types +class FakeModel(object): + """ Stubs out for model """ + def __init__(self, values): + self.values = values -def stub_out_db_instance_api(stubs): - """ Stubs out the db API for creating Instances """ + def __getattr__(self, name): + return self.values[name] - class FakeModel(object): - """ Stubs out for model """ - def __init__(self, values): - self.values = values + def __getitem__(self, key): + if key in self.values: + return self.values[key] + else: + raise NotImplementedError() - def __getattr__(self, name): - return self.values[name] - - def __getitem__(self, key): - if key in self.values: - return self.values[key] - else: - raise NotImplementedError() +def stub_out_db_instance_api(stubs): + """ Stubs out the db API for creating Instances """ def fake_instance_create(values): """ Stubs out the db.instance_create method """ @@ -66,12 +65,29 @@ def stub_out_db_instance_api(stubs): } return FakeModel(base_options) - def fake_network_get_by_instance(context, instance_id): - fields = { + stubs.Set(db, 'instance_create', fake_instance_create) + +def stub_out_db_network_api(stubs, injected = False): + """Stubs out the db API for retrieving networks""" + network_fields = { 'bridge': 'xenbr0', - 'injected': False + 'injected': injected } - return FakeModel(fields) - stubs.Set(db, 'instance_create', fake_instance_create) + if injected: + network_fields.update({ + 'netmask': '255.255.255.0', + 'gateway': '10.0.0.1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2' + }) + + def fake_network_get_by_instance(context, instance_id): + return FakeModel(network_fields) + + def fake_instance_get_fixed_address(context, instance_id): + return '10.0.0.3' + stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) + stubs.Set(db, 'instance_get_fixed_address', fake_instance_get_fixed_address) + diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 9f5b266f3..2a32845d3 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -50,6 +50,7 @@ class XenAPIVolumeTestCase(test.TestCase): FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_password = 'test_pass' db_fakes.stub_out_db_instance_api(self.stubs) + db_fakes.stub_out_db_network_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() self.values = {'name': 1, 'id': 1, @@ -158,6 +159,7 @@ class XenAPIVMTestCase(test.TestCase): xenapi_fake.reset() xenapi_fake.create_local_srs() db_fakes.stub_out_db_instance_api(self.stubs) + db_fakes.stub_out_db_network_api(self.stubs) xenapi_fake.create_network('fake', FLAGS.flat_network_bridge) stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) @@ -211,7 +213,7 @@ class XenAPIVMTestCase(test.TestCase): check() - def check_vm_record(self, conn): + def check_vm_record(self, conn, check_injection = False): instances = conn.list_instances() self.assertEquals(instances, [1]) @@ -219,10 +221,10 @@ class XenAPIVMTestCase(test.TestCase): vm_info = conn.get_info(1) # Get XenAPI record for VM - vms = [rec for ref, rec + vms = [(ref, rec) for ref, rec in xenapi_fake.get_all_records('VM').iteritems() if not rec['is_control_domain']] - vm = vms[0] + vm_ref, vm = vms[0] # Check that m1.large above turned into the right thing. instance_type = instance_types.INSTANCE_TYPES['m1.large'] @@ -242,8 +244,35 @@ class XenAPIVMTestCase(test.TestCase): # Check that the VM is running according to XenAPI. self.assertEquals(vm['power_state'], 'Running') - - def _test_spawn(self, image_id, kernel_id, ramdisk_id): + + if check_injection: + xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) + key_prefix = 'vm-data/vif/22_33_2A_B3_CC_DD/tcpip/' + tcpip_data = dict([(k.replace(key_prefix, ''), v) + for k, v in xenstore_data.iteritems() if k.startswith(key_prefix) ]) + + self.assertEquals(tcpip_data, { + 'BroadcastAddress/data/0': '10.0.0.255', + 'BroadcastAddress/name': 'BroadcastAddress', + 'BroadcastAddress/type': 'multi_sz', + 'DefaultGateway/data/0': '10.0.0.1', + 'DefaultGateway/name': 'DefaultGateway', + 'DefaultGateway/type': 'multi_sz', + 'EnableDhcp/data': '0', + 'EnableDhcp/name': 'EnableDhcp', + 'EnableDhcp/type': 'dword', + 'IPAddress/data/0': '10.0.0.3', + 'IPAddress/name': 'IPAddress', + 'IPAddress/type': 'multi_sz', + 'NameServer/data': '10.0.0.2', + 'NameServer/name': 'NameServer', + 'NameServer/type': 'string', + 'SubnetMask/data/0': '255.255.255.0', + 'SubnetMask/name': 'SubnetMask', + 'SubnetMask/type': 'multi_sz' + }) + + def _test_spawn(self, image_id, kernel_id, ramdisk_id, check_injection = False): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) values = {'name': 1, 'id': 1, @@ -258,7 +287,7 @@ class XenAPIVMTestCase(test.TestCase): conn = xenapi_conn.get_connection(False) instance = db.instance_create(values) conn.spawn(instance) - self.check_vm_record(conn) + self.check_vm_record(conn, check_injection = check_injection) def test_spawn_raw_objectstore(self): FLAGS.xenapi_image_service = 'objectstore' @@ -276,6 +305,11 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_image_service = 'glance' self._test_spawn(1, 2, 3) + def test_spawn_netinject(self): + FLAGS.xenapi_image_service = 'glance' + db_fakes.stub_out_db_network_api(self.stubs, injected = True) + self._test_spawn(1, 2, 3, check_injection = True) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 624995ada..3cfc8e5f9 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -171,6 +171,21 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_destroy(self, session_ref, vm_ref): fake.destroy_vm(vm_ref) + def VM_get_VIFs(self, session_ref, vm_ref): + return (['0', '1', '2']) + + def VIF_get_device(self, session_ref, vif_ref): + return ('1', '0', '2')[int(vif_ref)] + + def VIF_get_MAC(self, session_ref, vif_ref): + return ( + '11:22:2a:b3:CC:dd', + '22:33:2a:b3:CC:dd', + '44:44:2a:b3:CC:dd' + )[int(vif_ref)] + + def VM_add_to_xenstore_data(self, session_ref, vm_ref, key, value): + fake.VM_add_to_xenstore_data(vm_ref, key, value) class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ -- cgit From 48990b109eb39f0dd4ea7bf86be79f6e03c3ad74 Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Fri, 21 Jan 2011 16:23:30 +0000 Subject: OS55: pylint fixes --- nova/tests/test_xenapi.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 2a32845d3..c94aeefd1 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -249,7 +249,8 @@ class XenAPIVMTestCase(test.TestCase): xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) key_prefix = 'vm-data/vif/22_33_2A_B3_CC_DD/tcpip/' tcpip_data = dict([(k.replace(key_prefix, ''), v) - for k, v in xenstore_data.iteritems() if k.startswith(key_prefix) ]) + for k, v in xenstore_data.iteritems() + if k.startswith(key_prefix) ]) self.assertEquals(tcpip_data, { 'BroadcastAddress/data/0': '10.0.0.255', @@ -272,7 +273,8 @@ class XenAPIVMTestCase(test.TestCase): 'SubnetMask/type': 'multi_sz' }) - def _test_spawn(self, image_id, kernel_id, ramdisk_id, check_injection = False): + def _test_spawn(self, image_id, kernel_id, ramdisk_id, + check_injection = False): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) values = {'name': 1, 'id': 1, -- cgit From c97618e1eaff4091f01381073a298d0f67050126 Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Mon, 24 Jan 2011 18:28:50 +0000 Subject: OS-55: Post-merge fixes --- nova/tests/db/fakes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index e92efbedd..4a0d1cc3c 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -79,7 +79,8 @@ def stub_out_db_network_api(stubs, injected = False): 'netmask': '255.255.255.0', 'gateway': '10.0.0.1', 'broadcast': '10.0.0.255', - 'dns': '10.0.0.2' + 'dns': '10.0.0.2', + 'ra_server': None }) def fake_network_get_by_instance(context, instance_id): -- cgit From cd346a2cda13833f976b9e838d67cf17c52f327e Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Mon, 24 Jan 2011 19:04:25 +0000 Subject: OS-55: PEP8 fixes --- nova/tests/db/fakes.py | 17 +++++++++-------- nova/tests/test_xenapi.py | 19 +++++++++---------- nova/tests/xenapi/stubs.py | 10 +++++----- 3 files changed, 23 insertions(+), 23 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 4a0d1cc3c..c47fba5f3 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -23,6 +23,7 @@ from nova import db from nova import utils from nova.compute import instance_types + class FakeModel(object): """ Stubs out for model """ def __init__(self, values): @@ -37,6 +38,7 @@ class FakeModel(object): else: raise NotImplementedError() + def stub_out_db_instance_api(stubs): """ Stubs out the db API for creating Instances """ @@ -67,12 +69,12 @@ def stub_out_db_instance_api(stubs): stubs.Set(db, 'instance_create', fake_instance_create) -def stub_out_db_network_api(stubs, injected = False): + +def stub_out_db_network_api(stubs, injected=False): """Stubs out the db API for retrieving networks""" network_fields = { - 'bridge': 'xenbr0', - 'injected': injected - } + 'bridge': 'xenbr0', + 'injected': injected} if injected: network_fields.update({ @@ -80,8 +82,7 @@ def stub_out_db_network_api(stubs, injected = False): 'gateway': '10.0.0.1', 'broadcast': '10.0.0.255', 'dns': '10.0.0.2', - 'ra_server': None - }) + 'ra_server': None}) def fake_network_get_by_instance(context, instance_id): return FakeModel(network_fields) @@ -90,5 +91,5 @@ def stub_out_db_network_api(stubs, injected = False): return '10.0.0.3' stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) - stubs.Set(db, 'instance_get_fixed_address', fake_instance_get_fixed_address) - + stubs.Set(db, 'instance_get_fixed_address', + fake_instance_get_fixed_address) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index c94aeefd1..f7f7102a8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -213,7 +213,7 @@ class XenAPIVMTestCase(test.TestCase): check() - def check_vm_record(self, conn, check_injection = False): + def check_vm_record(self, conn, check_injection=False): instances = conn.list_instances() self.assertEquals(instances, [1]) @@ -244,13 +244,13 @@ class XenAPIVMTestCase(test.TestCase): # Check that the VM is running according to XenAPI. self.assertEquals(vm['power_state'], 'Running') - + if check_injection: xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) key_prefix = 'vm-data/vif/22_33_2A_B3_CC_DD/tcpip/' tcpip_data = dict([(k.replace(key_prefix, ''), v) for k, v in xenstore_data.iteritems() - if k.startswith(key_prefix) ]) + if k.startswith(key_prefix)]) self.assertEquals(tcpip_data, { 'BroadcastAddress/data/0': '10.0.0.255', @@ -270,11 +270,10 @@ class XenAPIVMTestCase(test.TestCase): 'NameServer/type': 'string', 'SubnetMask/data/0': '255.255.255.0', 'SubnetMask/name': 'SubnetMask', - 'SubnetMask/type': 'multi_sz' - }) + 'SubnetMask/type': 'multi_sz'}) def _test_spawn(self, image_id, kernel_id, ramdisk_id, - check_injection = False): + check_injection=False): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) values = {'name': 1, 'id': 1, @@ -289,7 +288,7 @@ class XenAPIVMTestCase(test.TestCase): conn = xenapi_conn.get_connection(False) instance = db.instance_create(values) conn.spawn(instance) - self.check_vm_record(conn, check_injection = check_injection) + self.check_vm_record(conn, check_injection=check_injection) def test_spawn_raw_objectstore(self): FLAGS.xenapi_image_service = 'objectstore' @@ -309,9 +308,9 @@ class XenAPIVMTestCase(test.TestCase): def test_spawn_netinject(self): FLAGS.xenapi_image_service = 'glance' - db_fakes.stub_out_db_network_api(self.stubs, injected = True) - self._test_spawn(1, 2, 3, check_injection = True) - + db_fakes.stub_out_db_network_api(self.stubs, injected=True) + self._test_spawn(1, 2, 3, check_injection=True) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 3cfc8e5f9..027855592 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -173,20 +173,20 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_get_VIFs(self, session_ref, vm_ref): return (['0', '1', '2']) - + def VIF_get_device(self, session_ref, vif_ref): return ('1', '0', '2')[int(vif_ref)] - + def VIF_get_MAC(self, session_ref, vif_ref): return ( '11:22:2a:b3:CC:dd', '22:33:2a:b3:CC:dd', - '44:44:2a:b3:CC:dd' - )[int(vif_ref)] - + '44:44:2a:b3:CC:dd')[int(vif_ref)] + def VM_add_to_xenstore_data(self, session_ref, vm_ref, key, value): fake.VM_add_to_xenstore_data(vm_ref, key, value) + class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ def __init__(self, uri): -- cgit From 0f868b00dbb2de469dde3519f2370e59937c4fc6 Mon Sep 17 00:00:00 2001 From: Andy Southgate Date: Wed, 26 Jan 2011 19:58:45 +0000 Subject: OS-55: Added a test case for XenAPI file-based network injection OS-55: Stubbed out utils.execute for all XenAPI VM tests, including command simulation where necessary --- nova/tests/fake_utils.py | 98 +++++++++++++++++++++++++++++++++++++++++++++++ nova/tests/test_xenapi.py | 83 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 nova/tests/fake_utils.py (limited to 'nova/tests') diff --git a/nova/tests/fake_utils.py b/nova/tests/fake_utils.py new file mode 100644 index 000000000..f51d31e0c --- /dev/null +++ b/nova/tests/fake_utils.py @@ -0,0 +1,98 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Citrix Systems, 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. + +"""This modules stubs out functions in nova.utils +""" + +import re +import types + +from eventlet import greenthread + +from nova import exception +from nova import log as logging +from nova import utils + +LOG = logging.getLogger('nova.tests.fake_utils') + +_fake_execute_repliers = [] +_fake_execute_log = [] + + +def fake_execute_get_log(): + global _fake_execute_log + return _fake_execute_log + + +def fake_execute_clear_log(): + global _fake_execute_log + _fake_execute_log = [] + + +def fake_execute_set_repliers(repliers): + """Allows the client to configure replies to commands""" + global _fake_execute_repliers + _fake_execute_repliers = repliers + + +def fake_execute_default_reply_handler(*ignore_args): + """A reply handler for commands that haven't been added to the reply + list. Returns empty strings for stdout and stderr + """ + return '', '' + + +def fake_execute(cmd, process_input=None, addl_env=None, check_exit_code=True): + """This function stubs out execute, optionally executing + a preconfigued function to return expected data + """ + global _fake_execute_repliers + + LOG.debug(_("Faking execution of cmd (subprocess): %s"), cmd) + _fake_execute_log.append(cmd) + + reply_handler = fake_execute_default_reply_handler + + for fake_replier in _fake_execute_repliers: + if re.match(fake_replier[0], cmd): + reply_handler = fake_replier[1] + LOG.debug(_('Faked command matched %s') % fake_replier[0]) + break + + if isinstance(reply_handler, types.StringTypes): + # If the reply handler is a string, return it as stdout + reply = reply_handler, '' + else: + try: + # Alternative is a function, so call it + reply = reply_handler(cmd, process_input, addl_env, + check_exit_code) + except exception.ProcessExecutionError as e: + LOG.debug(_('Faked command raised an exception %s' % str(e))) + raise + + LOG.debug(_("Reply to faked command is stdout='%(0)s' stderr='%(1)s'") % + {'0': reply[0], '1': reply[1]}) + + # Replicate the sleep call in the real function + greenthread.sleep(0) + return reply + + +def stub_out_utils_execute(stubs): + fake_execute_set_repliers([]) + fake_execute_clear_log() + stubs.Set(utils, 'execute', fake_execute) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index f7f7102a8..8af47da63 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -18,11 +18,14 @@ Test suite for XenAPI """ +import os +import re import stubout from nova import db from nova import context from nova import flags +from nova import log as logging from nova import test from nova import utils from nova.auth import manager @@ -35,6 +38,9 @@ from nova.virt.xenapi.vmops import SimpleDH from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs from nova.tests.glance import stubs as glance_stubs +from nova.tests import fake_utils + +LOG = logging.getLogger('nova.tests.test_xenapi') FLAGS = flags.FLAGS @@ -166,6 +172,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_stream_disk(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) + fake_utils.stub_out_utils_execute(self.stubs) self.conn = xenapi_conn.get_connection(False) def test_list_instances_0(self): @@ -306,11 +313,85 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_image_service = 'glance' self._test_spawn(1, 2, 3) - def test_spawn_netinject(self): + def test_spawn_netinject_file(self): + FLAGS.xenapi_image_service = 'glance' + db_fakes.stub_out_db_network_api(self.stubs, injected=True) + + self._tee_executed = False + + def _tee_handler(cmd, input, *ignore_args): + self.assertNotEqual(input, None) + + config = [line.strip() for line in input.split("\n")] + + # Find the start of eth0 configuration and check it + index = config.index('auto eth0') + self.assertEquals(config[index + 1:index + 8], [ + 'iface eth0 inet static', + 'address 10.0.0.3', + 'netmask 255.255.255.0', + 'broadcast 10.0.0.255', + 'gateway 10.0.0.1', + 'dns-nameservers 10.0.0.2', + '']) + + self._tee_executed = True + + return '', '' + + fake_utils.fake_execute_set_repliers([ + # Capture the sudo tee .../etc/network/interfaces command + (r'(sudo\s+)?tee.*interfaces', _tee_handler), + ]) + self._test_spawn(1, 2, 3, check_injection=True) + self.assertTrue(self._tee_executed) + + def test_spawn_netinject_xenstore(self): FLAGS.xenapi_image_service = 'glance' db_fakes.stub_out_db_network_api(self.stubs, injected=True) + + self._tee_executed = False + + def _mount_handler(cmd, *ignore_args): + # When mounting, create real files under the mountpoint to simulate + # files in the mounted filesystem + + # RegExp extracts the path of the mountpoint + match = re.match(r'(sudo\s+)?mount[^"]*"[^"]*"\s+"([^"]*)"', cmd) + self._tmpdir = match.group(2) + LOG.debug(_('Creating files in %s to simulate guest agent' % + self._tmpdir)) + os.makedirs(os.path.join(self._tmpdir, 'usr', 'sbin')) + # Touch the file using open + open(os.path.join(self._tmpdir, 'usr', 'sbin', + 'xe-update-networking'), 'w').close() + return '', '' + + def _umount_handler(cmd, *ignore_args): + # Umount would normall make files in the m,ounted filesystem + # disappear, so do that here + LOG.debug(_('Removing simulated guest agent files in %s' % + self._tmpdir)) + os.remove(os.path.join(self._tmpdir, 'usr', 'sbin', + 'xe-update-networking')) + os.rmdir(os.path.join(self._tmpdir, 'usr', 'sbin')) + os.rmdir(os.path.join(self._tmpdir, 'usr')) + return '', '' + + def _tee_handler(cmd, input, *ignore_args): + self._tee_executed = True + return '', '' + + fake_utils.fake_execute_set_repliers([ + (r'(sudo\s+)?mount', _mount_handler), + (r'(sudo\s+)?umount', _umount_handler), + (r'(sudo\s+)?tee.*interfaces', _tee_handler)]) self._test_spawn(1, 2, 3, check_injection=True) + # tee must not run in this case, where an injection-capable + # guest agent is detected + self.assertFalse(self._tee_executed) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) -- cgit From 7c8096384507908a5e583f4554d0fc765ae5f2eb Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Thu, 27 Jan 2011 20:39:33 +0900 Subject: adding testcode --- nova/tests/test_compute.py | 305 ++++++++++++++++++ nova/tests/test_scheduler.py | 722 +++++++++++++++++++++++++++++++++++++++++++ nova/tests/test_service.py | 61 +++- nova/tests/test_virt.py | 520 ++++++++++++++++++++++++++++++- 4 files changed, 1604 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 09f6ee94a..344c2d2b5 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -20,6 +20,7 @@ Tests For Compute """ import datetime +import mox from nova import compute from nova import context @@ -27,9 +28,12 @@ from nova import db from nova import exception from nova import flags from nova import log as logging +from nova import rpc from nova import test from nova import utils from nova.auth import manager +from nova.compute import manager as compute_manager +from nova.compute import power_state LOG = logging.getLogger('nova.tests.compute') @@ -219,3 +223,304 @@ class ComputeTestCase(test.TestCase): self.assertEqual(ret_val, None) self.compute.terminate_instance(self.context, instance_id) + + def test_update_service_exception(self): + """nova-compute updates Serivce table on DB like below. + nova.service.Serivce.start -> + nova.compute.ComputeManager.update_service. + This testcase confirms if no record found on Service + table, exception can be raised. + """ + host = 'foo' + binary = 'nova-compute' + dbmock = self.mox.CreateMock(db) + dbmock.service_get_by_args(mox.IgnoreArg(), + mox.StrContains(host), + mox.StrContains(binary)).\ + AndRaise(exception.NotFound()) + self.compute.db = dbmock + self.mox.ReplayAll() + try: + self.compute.update_service('dummy', host, binary) + except exception.Invalid, e: + msg = 'Cannot insert compute manager specific info' + c1 = ( 0 <= e.message.find(msg)) + self.assertTrue(c1) + self.mox.ResetAll() + + def test_update_service_success(self): + """nova-compute updates Serivce table on DB like below. + nova.service.Serivce.start -> + nova.compute.ComputeManager.update_service. + In this method, vcpus/memory_mb/local_gb/hypervisor_type/ + hypervisor_version/cpu_info should be changed. + Based on this specification, this testcase confirms + if this method finishes successfully, + meaning self.db.service_update is called with dictinary + + {'vcpu':aaa, 'memory_mb':bbb, 'local_gb':ccc, + 'hypervisor_type':ddd, 'hypervisor_version':eee, + 'cpu_info':fff} + + Since each value of above dict can be obtained through + driver(different depends on environment), + only dictionary keys are checked. + """ + + def dic_key_check(dic): + validkey = ['vcpus', 'memory_mb', 'local_gb', + 'hypervisor_type', 'hypervisor_version', 'cpu_info'] + return (list(set(validkey)) == list(set(dic.keys()))) + + host = 'foo' + binary = 'nova-compute' + service_ref = {'id':1, 'binary':'nova-compute', 'topic':'compute'} + dbmock = self.mox.CreateMock(db) + dbmock.service_get_by_args(mox.IgnoreArg(), + mox.StrContains(host), + mox.StrContains(binary)).\ + AndReturn(service_ref) + dbmock.service_update(mox.IgnoreArg(), + service_ref['id'], + mox.Func(dic_key_check)) + + self.compute.db = dbmock + self.mox.ReplayAll() + try: + self.compute.update_service('dummy', host, binary) + except exception.Invalid, e: + msg = 'Cannot insert compute manager specific info' + c1 = ( 0 <= e.message.find(msg)) + self.assertTrue(c1) + self.mox.ResetAll() + + def _setup_other_managers(self): + self.volume_manager = utils.import_object(FLAGS.volume_manager) + self.network_manager = utils.import_object(FLAGS.network_manager) + self.compute_driver = utils.import_object(FLAGS.compute_driver) + + def test_pre_live_migration_instance_has_no_fixed_ip(self): + """ + if instances that are intended to be migrated doesnt have fixed_ip + (not happens usually), pre_live_migration has to raise Exception. + """ + instance_ref={'id':1, 'volumes':[{'id':1}, {'id':2}], + 'hostname':'i-000000001'} + c = context.get_admin_context() + i_id = instance_ref['id'] + + dbmock = self.mox.CreateMock(db) + dbmock.instance_get(c, i_id).AndReturn(instance_ref) + dbmock.instance_get_fixed_address(c, i_id).AndReturn(None) + + self.compute.db = dbmock + self.mox.ReplayAll() + self.assertRaises(exception.NotFound, + self.compute.pre_live_migration, + c, instance_ref['id']) + self.mox.ResetAll() + + def test_pre_live_migration_instance_has_volume(self): + """if any volumes are attached to the instances that are + intended to be migrated, setup_compute_volume must be + called because aoe module should be inserted at destination + host. This testcase checks on it. + """ + instance_ref={'id':1, 'volumes':[{'id':1}, {'id':2}], + 'hostname':'i-000000001'} + c = context.get_admin_context() + i_id=instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + volmock = self.mox.CreateMock(self.volume_manager) + netmock = self.mox.CreateMock(self.network_manager) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, i_id).AndReturn(instance_ref) + dbmock.instance_get_fixed_address(c, i_id).AndReturn('dummy') + for i in range(len(instance_ref['volumes'])): + vid = instance_ref['volumes'][i]['id'] + volmock.setup_compute_volume(c, vid).InAnyOrder('g1') + netmock.setup_compute_network(c, instance_ref['id']) + drivermock.ensure_filtering_rules_for_instance(instance_ref) + + self.compute.db = dbmock + self.compute.volume_manager = volmock + self.compute.network_manager = netmock + self.compute.driver = drivermock + + self.mox.ReplayAll() + ret = self.compute.pre_live_migration(c, i_id) + self.assertEqual(ret, None) + self.mox.ResetAll() + + def test_pre_live_migration_instance_has_no_volume(self): + """if any volumes are not attached to the instances that are + intended to be migrated, log message should be appears + because administrator can proove instance conditions before + live_migration if any trouble occurs. + """ + instance_ref={'id':1, 'volumes':[], 'hostname':'i-20000001'} + c = context.get_admin_context() + i_id = instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + netmock = self.mox.CreateMock(self.network_manager) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, i_id).AndReturn(instance_ref) + dbmock.instance_get_fixed_address(c, i_id).AndReturn('dummy') + self.mox.StubOutWithMock(compute_manager.LOG, 'info') + compute_manager.LOG.info(_("%s has no volume."), instance_ref['hostname']) + netmock.setup_compute_network(c, i_id) + drivermock.ensure_filtering_rules_for_instance(instance_ref) + + self.compute.db = dbmock + self.compute.network_manager = netmock + self.compute.driver = drivermock + + self.mox.ReplayAll() + ret = self.compute.pre_live_migration(c, i_id) + self.assertEqual(ret, None) + self.mox.ResetAll() + + def test_live_migration_instance_has_volume(self): + """Any volumes are mounted by instances to be migrated are found, + vblade health must be checked before starting live-migration. + And that is checked by check_for_export(). + This testcase confirms check_for_export() is called. + """ + instance_ref={'id':1, 'volumes':[{'id':1}, {'id':2}], 'hostname':'i-00000001'} + c = context.get_admin_context() + dest='dummydest' + i_id = instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, instance_ref['id']).AndReturn(instance_ref) + self.mox.StubOutWithMock(rpc, 'call') + rpc.call(c, FLAGS.volume_topic, + {"method": "check_for_export", + "args": {'instance_id': i_id}}).InAnyOrder('g1') + rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest), + {"method": "pre_live_migration", + "args": {'instance_id': i_id}}).InAnyOrder('g1') + + self.compute.db = dbmock + self.compute.driver = drivermock + self.mox.ReplayAll() + ret = self.compute.live_migration(c, i_id, dest) + self.assertEqual(ret, None) + self.mox.ResetAll() + + def test_live_migration_instance_has_volume_and_exception(self): + """In addition to test_live_migration_instance_has_volume testcase, + this testcase confirms if any exception raises from check_for_export(). + Then, valid seaquence of this method should recovering instance/volumes + status(ex. instance['state_description'] is changed from 'migrating' + -> 'running', was changed by scheduler) + """ + instance_ref={'id':1, 'volumes':[{'id':1}, {'id':2}], + 'hostname':'i-000000001'} + dest='dummydest' + c = context.get_admin_context() + i_id = instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, instance_ref['id']).AndReturn(instance_ref) + self.mox.StubOutWithMock(rpc, 'call') + rpc.call(c, FLAGS.volume_topic, + {"method": "check_for_export", + "args": {'instance_id': i_id}}).InAnyOrder('g1') + compute_topic = db.queue_get_for(c, FLAGS.compute_topic, dest) + dbmock.queue_get_for(c, FLAGS.compute_topic, dest).AndReturn(compute_topic) + rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest), + {"method": "pre_live_migration", + "args": {'instance_id': i_id}}).\ + InAnyOrder('g1').AndRaise(rpc.RemoteError('du', 'mm', 'y')) + self.mox.StubOutWithMock(compute_manager.LOG, 'error') + compute_manager.LOG.error('Pre live migration for %s failed at %s', + instance_ref['hostname'], dest) + dbmock.instance_set_state(c, i_id, power_state.RUNNING, 'running') + for i in range(len(instance_ref['volumes'])): + vid = instance_ref['volumes'][i]['id'] + dbmock.volume_update(c, vid, {'status': 'in-use'}) + + self.compute.db = dbmock + self.compute.driver = drivermock + self.mox.ReplayAll() + self.assertRaises(rpc.RemoteError, + self.compute.live_migration, + c, i_id, dest) + self.mox.ResetAll() + + def test_live_migration_instance_has_no_volume_and_exception(self): + """Simpler than test_live_migration_instance_has_volume_and_exception""" + + instance_ref={'id':1, 'volumes':[], 'hostname':'i-000000001'} + dest='dummydest' + c = context.get_admin_context() + i_id = instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, instance_ref['id']).AndReturn(instance_ref) + self.mox.StubOutWithMock(rpc, 'call') + compute_topic = db.queue_get_for(c, FLAGS.compute_topic, dest) + dbmock.queue_get_for(c, FLAGS.compute_topic, dest).AndReturn(compute_topic) + rpc.call(c, compute_topic, + {"method": "pre_live_migration", + "args": {'instance_id': i_id}}).\ + AndRaise(rpc.RemoteError('du', 'mm', 'y')) + self.mox.StubOutWithMock(compute_manager.LOG, 'error') + compute_manager.LOG.error('Pre live migration for %s failed at %s', + instance_ref['hostname'], dest) + dbmock.instance_set_state(c, i_id, power_state.RUNNING, 'running') + + self.compute.db = dbmock + self.compute.driver = drivermock + self.mox.ReplayAll() + self.assertRaises(rpc.RemoteError, + self.compute.live_migration, + c, i_id, dest) + self.mox.ResetAll() + + def test_live_migration_instance_has_volume(self): + """Simpler version than test_live_migration_instance_has_volume.""" + instance_ref={'id':1, 'volumes':[{'id':1}, {'id':2}], + 'hostname':'i-000000001'} + c = context.get_admin_context() + dest='dummydest' + i_id = instance_ref['id'] + + self._setup_other_managers() + dbmock = self.mox.CreateMock(db) + drivermock = self.mox.CreateMock(self.compute_driver) + + dbmock.instance_get(c, i_id).AndReturn(instance_ref) + self.mox.StubOutWithMock(rpc, 'call') + rpc.call(c, FLAGS.volume_topic, + {"method": "check_for_export", + "args": {'instance_id': i_id}}).InAnyOrder('g1') + compute_topic = db.queue_get_for(c, FLAGS.compute_topic, dest) + dbmock.queue_get_for(c, FLAGS.compute_topic, dest).AndReturn(compute_topic) + rpc.call(c, compute_topic, + {"method": "pre_live_migration", + "args": {'instance_id': i_id}}).InAnyOrder('g1') + drivermock.live_migration(c, instance_ref, dest) + + self.compute.db = dbmock + self.compute.driver = drivermock + self.mox.ReplayAll() + ret = self.compute.live_migration(c, i_id, dest) + self.assertEqual(ret, None) + self.mox.ResetAll() diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 9d458244b..c62bca9b1 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -20,10 +20,12 @@ Tests For Scheduler """ import datetime +import mox from mox import IgnoreArg from nova import context from nova import db +from nova import exception from nova import flags from nova import service from nova import test @@ -32,6 +34,8 @@ from nova import utils from nova.auth import manager as auth_manager from nova.scheduler import manager from nova.scheduler import driver +from nova.compute import power_state +from nova.db.sqlalchemy import models FLAGS = flags.FLAGS @@ -75,7 +79,102 @@ class SchedulerTestCase(test.TestCase): 'args': {'num': 7}}) self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) + + def test_show_host_resource_host_not_exit(self): + """ + A testcase of driver.has_enough_resource + given host does not exists. + """ + scheduler = manager.SchedulerManager() + dest = 'dummydest' + ctxt = context.get_admin_context() + + self.mox.StubOutWithMock(manager, 'db', use_mock_anything=True) + manager.db.service_get_all_compute_sorted(mox.IgnoreArg()).\ + AndReturn([]) + + self.mox.ReplayAll() + result = scheduler.show_host_resource(ctxt, dest) + # ret should be dict + keys = ['ret', 'msg'] + c1 = list(set(result.keys())) == list(set(keys)) + c2 = not result['ret'] + c3 = result['msg'].find('No such Host or not compute node') <= 0 + self.assertTrue( c1 and c2 and c3) + self.mox.UnsetStubs() + + def test_show_host_resource_no_project(self): + """ + A testcase of driver.show_host_resource + no instance stays on the given host + """ + scheduler = manager.SchedulerManager() + dest = 'dummydest' + ctxt = context.get_admin_context() + r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100} + service_ref = {'id':1, 'host':dest} + service_ref.update(r0) + + self.mox.StubOutWithMock(manager, 'db', use_mock_anything=True) + manager.db.service_get_all_compute_sorted(mox.IgnoreArg()).\ + AndReturn([(service_ref, 0)]) + manager.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([]) + + self.mox.ReplayAll() + result = scheduler.show_host_resource(ctxt, dest) + # ret should be dict + keys = ['ret', 'phy_resource', 'usage'] + c1 = list(set(result.keys())) == list(set(keys)) + c2 = result['ret'] + c3 = result['phy_resource'] == r0 + c4 = result['usage'] == {} + self.assertTrue( c1 and c2 and c3 and c4) + self.mox.UnsetStubs() + + def test_show_host_resource_works_correctly(self): + """ + A testcase of driver.show_host_resource + to make sure everything finished with no error. + """ + scheduler = manager.SchedulerManager() + dest = 'dummydest' + ctxt = context.get_admin_context() + r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100} + r1 = {'vcpus':10, 'memory_mb':4, 'local_gb':20} + r2 = {'vcpus':10, 'memory_mb':20, 'local_gb':30} + service_ref = {'id':1, 'host':dest} + service_ref.update(r0) + instance_ref2 = {'id':2, 'project_id':'p-01', 'host':'dummy'} + instance_ref2.update(r1) + instance_ref3 = {'id':3, 'project_id':'p-02', 'host':'dummy'} + instance_ref3.update(r1) + self.mox.StubOutWithMock(manager, 'db', use_mock_anything=True) + manager.db.service_get_all_compute_sorted(mox.IgnoreArg()).\ + AndReturn([(service_ref, 0)]) + manager.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([instance_ref2, instance_ref3]) + for p in ['p-01', 'p-02']: + manager.db.instance_get_vcpu_sum_by_host_and_project( + ctxt, dest, p).AndReturn(r2['vcpus']) + manager.db.instance_get_memory_sum_by_host_and_project( + ctxt, dest, p).AndReturn(r2['memory_mb']) + manager.db.instance_get_disk_sum_by_host_and_project( + ctxt, dest, p).AndReturn(r2['local_gb']) + + self.mox.ReplayAll() + result = scheduler.show_host_resource(ctxt, dest) + # ret should be dict + keys = ['ret', 'phy_resource', 'usage'] + c1 = list(set(result.keys())) == list(set(keys)) + c2 = result['ret'] + c3 = result['phy_resource'] == r0 + c4 = result['usage'].keys() == ['p-01', 'p-02'] + c5 = result['usage']['p-01'] == r2 + c6 = result['usage']['p-02'] == r2 + self.assertTrue( c1 and c2 and c3 and c4 and c5 and c6) + self.mox.UnsetStubs() class ZoneSchedulerTestCase(test.TestCase): """Test case for zone scheduler""" @@ -384,3 +483,626 @@ class SimpleDriverTestCase(test.TestCase): volume2.delete_volume(self.context, volume_id) volume1.kill() volume2.kill() + + def test_scheduler_live_migraiton_with_volume(self): + """ + driver.scheduler_live_migration finishes successfully + (volumes are attached to instances) + This testcase make sure schedule_live_migration + changes instance state from 'running' -> 'migrating' + """ + driver_i = self.scheduler.driver + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-00000001', 'host':'dummy', + 'volumes':[{'id':1}, {'id':2}]} + dest = 'dummydest' + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + # must be IgnoreArg() because scheduler changes ctxt's memory address + driver.db.instance_get(mox.IgnoreArg(), i_ref['id']).AndReturn(i_ref) + + self.mox.StubOutWithMock(driver_i, '_live_migration_src_check') + driver_i._live_migration_src_check(mox.IgnoreArg(), i_ref) + self.mox.StubOutWithMock(driver_i, '_live_migration_dest_check') + driver_i._live_migration_dest_check(mox.IgnoreArg(), i_ref, dest) + self.mox.StubOutWithMock(driver_i, '_live_migration_common_check') + driver_i._live_migration_common_check(mox.IgnoreArg(), i_ref, dest) + driver.db.instance_set_state(mox.IgnoreArg(), i_ref['id'], + power_state.PAUSED, 'migrating') + for v in i_ref['volumes']: + driver.db.volume_update(mox.IgnoreArg(), v['id'], + {'status': 'migrating'}) + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + kwargs={'instance_id':i_ref['id'], 'dest':dest} + rpc.cast(ctxt, db.queue_get_for(ctxt, topic, i_ref['host']), + {"method": 'live_migration', + "args": kwargs}) + + self.mox.ReplayAll() + self.scheduler.live_migration(ctxt, topic, + instance_id=i_ref['id'], dest=dest) + self.mox.UnsetStubs() + + def test_scheduler_live_migraiton_no_volume(self): + """ + driver.scheduler_live_migration finishes successfully + (volumes are attached to instances) + This testcase make sure schedule_live_migration + changes instance state from 'running' -> 'migrating' + """ + driver_i = self.scheduler.driver + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'volumes':[]} + dest = 'dummydest' + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + # must be IgnoreArg() because scheduler changes ctxt's memory address + driver.db.instance_get(mox.IgnoreArg(), i_ref['id']).AndReturn(i_ref) + self.mox.StubOutWithMock(driver_i, '_live_migration_src_check') + driver_i._live_migration_src_check(mox.IgnoreArg(), i_ref) + self.mox.StubOutWithMock(driver_i, '_live_migration_dest_check') + driver_i._live_migration_dest_check(mox.IgnoreArg(), i_ref, dest) + self.mox.StubOutWithMock(driver_i, '_live_migration_common_check') + driver_i._live_migration_common_check(mox.IgnoreArg(), i_ref, dest) + driver.db.instance_set_state(mox.IgnoreArg(), i_ref['id'], + power_state.PAUSED, 'migrating') + self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + kwargs={'instance_id':i_ref['id'], 'dest':dest} + rpc.cast(ctxt, db.queue_get_for(ctxt, topic, i_ref['host']), + {"method": 'live_migration', + "args": kwargs}) + + self.mox.ReplayAll() + self.scheduler.live_migration(ctxt, topic, + instance_id=i_ref['id'], dest=dest) + self.mox.UnsetStubs() + + def test_live_migraiton_src_check_instance_not_running(self): + """ + A testcase of driver._live_migration_src_check. + The instance given by instance_id is not running. + """ + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + dest = 'dummydest' + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'volumes':[], 'state_description':'migrating', + 'state':power_state.RUNNING} + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_src_check(ctxt, i_ref) + except exception.Invalid, e: + self.assertTrue(e.message.find('is not running') > 0) + self.mox.UnsetStubs() + + def test_live_migraiton_src_check_volume_node_not_alive(self): + """ + A testcase of driver._live_migration_src_check. + Volume node is not alive if any volumes are attached to + the given instance. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'volumes':[{'id':1}, {'id':2}], + 'state_description':'running', 'state':power_state.RUNNING} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_topic(mox.IgnoreArg(), 'volume').\ + AndReturn([]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_src_check(ctxt, i_ref) + except exception.Invalid, e: + self.assertTrue(e.message.find('volume node is not alive') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_src_check_volume_node_not_alive(self): + """ + A testcase of driver._live_migration_src_check. + The testcase make sure src-compute node is alive. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'volumes':[], + 'state_description':'running', 'state':power_state.RUNNING} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_topic(mox.IgnoreArg(), 'compute').\ + AndReturn([]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_src_check(ctxt, i_ref) + except exception.Invalid, e: + self.assertTrue(e.message.find('is not alive') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_src_check_works_correctly(self): + """ + A testcase of driver._live_migration_src_check. + The testcase make sure everything finished with no error. + """ + driver_i = self.scheduler.driver + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'volumes':[], + 'state_description':'running', 'state':power_state.RUNNING} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_topic(mox.IgnoreArg(), 'compute').\ + AndReturn([service_ref]) + self.mox.StubOutWithMock(driver_i, 'service_is_up') + driver_i.service_is_up(service_ref).AndReturn(True) + + self.mox.ReplayAll() + ret = driver_i._live_migration_src_check(ctxt, i_ref) + self.assertTrue(ret == None) + self.mox.UnsetStubs() + + def test_live_migraiton_dest_check_service_not_exists(self): + """ + A testcase of driver._live_migration_dst_check. + Destination host does not exist. + """ + driver_i = self.scheduler.driver + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([]) + + self.mox.ReplayAll() + try: + driver_i._live_migration_dest_check(ctxt, i_ref, dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('does not exists') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_dest_check_service_isnot_compute(self): + """ + A testcase of driver._live_migration_dst_check. + Destination host does not provide compute. + """ + driver_i = self.scheduler.driver + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + service_ref.__setitem__('topic', 'api') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + + self.mox.ReplayAll() + try: + driver_i._live_migration_dest_check(ctxt, i_ref, dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('must be compute node') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_dest_check_service_not_alive(self): + """ + A testcase of driver._live_migration_dst_check. + Destination host compute service is not alive. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + service_ref.__setitem__('topic', 'compute') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + self.mox.StubOutWithMock(self.scheduler.driver, 'service_is_up') + self.scheduler.driver.service_is_up(service_ref).AndReturn(False) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_dest_check(ctxt, i_ref, dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('is not alive') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_dest_check_service_same_host(self): + """ + A testcase of driver._live_migration_dst_check. + Destination host is same as src host. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummydest'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + service_ref.__setitem__('topic', 'compute') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + self.mox.StubOutWithMock(self.scheduler.driver, 'service_is_up') + self.scheduler.driver.service_is_up(service_ref).AndReturn(True) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_dest_check(ctxt, i_ref, dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('is running now. choose other host') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_dest_check_service_works_correctly(self): + """ + A testcase of driver._live_migration_dst_check. + The testcase make sure everything finished with no error. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummydest'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('host', i_ref['host']) + service_ref.__setitem__('topic', 'compute') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + self.mox.StubOutWithMock(self.scheduler.driver, 'service_is_up') + self.scheduler.driver.service_is_up(service_ref).AndReturn(True) + self.mox.StubOutWithMock(self.scheduler.driver, 'has_enough_resource') + self.scheduler.driver.has_enough_resource(mox.IgnoreArg(), i_ref, dest) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_dest_check(ctxt, i_ref, dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('is running now. choose other host') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_dest_not_exists(self): + """ + A testcase of driver._live_migration_common_check. + Destination host does not exist. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + except exception.Invalid, e: + self.assertTrue(e.message.find('does not exists') >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_orig_not_exists(self): + """ + A testcase of driver._live_migration_common_check. + Original host(an instance launched on) does not exist. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'launched_on':'h1'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('topic', 'compute') + service_ref.__setitem__('host', i_ref['host']) + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.service_get_all_by_host(mox.IgnoreArg(), + i_ref['launched_on']).\ + AndReturn([]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + except exception.Invalid, e: + msg = 'where instance was launched at) does not exists' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_different_hypervisor(self): + """ + A testcase of driver._live_migration_common_check. + Original host and dest host has different hypervisor type. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', + 'host':'dummy', 'launched_on':'h1'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('topic', 'compute') + service_ref.__setitem__('hypervisor_type', 'kvm') + service_ref2 = models.Service() + service_ref2.__setitem__('id', 2) + service_ref2.__setitem__('hypervisor_type', 'xen') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.service_get_all_by_host(mox.IgnoreArg(), + i_ref['launched_on']).\ + AndReturn([service_ref2]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + except exception.Invalid, e: + msg = 'Different hypervisor type' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_different_version(self): + """ + A testcase of driver._live_migration_common_check. + Original host and dest host has different hypervisor version. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', + 'host':'dummy', 'launched_on':'h1'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('topic', 'compute') + service_ref.__setitem__('hypervisor_version', 12000) + service_ref2 = models.Service() + service_ref2.__setitem__('id', 2) + service_ref2.__setitem__('hypervisor_version', 12001) + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.service_get_all_by_host(mox.IgnoreArg(), + i_ref['launched_on']).\ + AndReturn([service_ref2]) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + except exception.Invalid, e: + msg = 'Older hypervisor version' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_checking_cpuinfo_fail(self): + """ + A testcase of driver._live_migration_common_check. + Original host and dest host has different hypervisor version. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', + 'host':'dummy', 'launched_on':'h1'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('topic', 'compute') + service_ref.__setitem__('hypervisor_version', 12000) + service_ref2 = models.Service() + service_ref2.__setitem__('id', 2) + service_ref2.__setitem__('hypervisor_version', 12000) + service_ref2.__setitem__('cpuinfo', 'info') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.service_get_all_by_host(mox.IgnoreArg(), + i_ref['launched_on']).\ + AndReturn([service_ref2]) + driver.db.queue_get_for(mox.IgnoreArg(), FLAGS.compute_topic, dest) + self.mox.StubOutWithMock(driver, 'rpc', use_mock_anything=True) + driver.rpc.call(mox.IgnoreArg(), mox.IgnoreArg(), + {"method": 'compare_cpu', + "args": {'cpu_info': service_ref2['cpu_info']}}).\ + AndRaise(rpc.RemoteError('doesnt have compatibility to', '', '')) + + self.mox.ReplayAll() + try: + self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + except rpc.RemoteError, e: + msg = 'doesnt have compatibility to' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_live_migraiton_common_check_service_works_correctly(self): + """ + A testcase of driver._live_migration_common_check. + The testcase make sure everything finished with no error. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + i_ref = {'id':1, 'hostname':'i-01', + 'host':'dummy', 'launched_on':'h1'} + service_ref = models.Service() + service_ref.__setitem__('id', 1) + service_ref.__setitem__('topic', 'compute') + service_ref.__setitem__('hypervisor_version', 12000) + service_ref2 = models.Service() + service_ref2.__setitem__('id', 2) + service_ref2.__setitem__('hypervisor_version', 12000) + service_ref2.__setitem__('cpuinfo', 'info') + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.service_get_all_by_host(mox.IgnoreArg(), + i_ref['launched_on']).\ + AndReturn([service_ref2]) + driver.db.queue_get_for(mox.IgnoreArg(), FLAGS.compute_topic, dest) + self.mox.StubOutWithMock(driver, 'rpc', use_mock_anything=True) + driver.rpc.call(mox.IgnoreArg(), mox.IgnoreArg(), + {"method": 'compare_cpu', + "args": {'cpu_info': service_ref2['cpu_info']}}) + + self.mox.ReplayAll() + ret = self.scheduler.driver._live_migration_common_check(ctxt, + i_ref, + dest) + self.assertTrue(ret == None) + self.mox.UnsetStubs() + + def test_has_enough_resource_lack_resource_vcpu(self): + """ + A testcase of driver.has_enough_resource. + Lack of vcpu.(boundary check) + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} + i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'vcpus':6, 'memory_mb':8, 'local_gb':10} + i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([i_ref2, i_ref3]) + + self.mox.ReplayAll() + try: + self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + except exception.NotEmpty, e: + msg = 'is not capable to migrate' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_has_enough_resource_lack_resource_memory(self): + """ + A testcase of driver.has_enough_resource. + Lack of memory_mb.(boundary check) + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} + i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':16, 'local_gb':10} + i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([i_ref2, i_ref3]) + + self.mox.ReplayAll() + try: + self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + except exception.NotEmpty, e: + msg = 'is not capable to migrate' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + self.mox.UnsetStubs() + + def test_has_enough_resource_lack_resource_disk(self): + """ + A testcase of driver.has_enough_resource. + Lack of local_gb.(boundary check) + """ + scheduler = manager.SchedulerManager() + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} + i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':80} + i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([i_ref2, i_ref3]) + + self.mox.ReplayAll() + try: + self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + except exception.NotEmpty, e: + msg = 'is not capable to migrate' + self.assertTrue(e.message.find(msg) >= 0) + self.mox.UnsetStubs() + + def test_has_enough_resource_works_correctly(self): + """ + A testcase of driver.has_enough_resource + to make sure everything finished with no error. + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} + i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', + 'vcpus':5, 'memory_mb':8, 'local_gb':10} + + self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) + driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([service_ref]) + driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ + AndReturn([i_ref2, i_ref3]) + + self.mox.ReplayAll() + ret = self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + self.assertTrue(ret == None) + self.mox.UnsetStubs() diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index a67c8d1e8..a147e69b4 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -30,6 +30,7 @@ from nova import rpc from nova import test from nova import service from nova import manager +from nova.compute import manager as compute_manager FLAGS = flags.FLAGS flags.DEFINE_string("fake_manager", "nova.tests.test_service.FakeManager", @@ -41,7 +42,20 @@ class FakeManager(manager.Manager): def test_method(self): return 'manager' - +# temporary variable to store host/binary/self.mox from each method to fake class. +global_host = None +global_binary = None +global_mox = None +class FakeComputeManager(compute_manager.ComputeManager): + """Fake computemanager manager for tests""" + + def __init__(self, compute_driver=None, *args, **kwargs): + global ghost, gbinary, gmox + self.update_service(mox.IgnoreArg(), mox.StrContains(ghost), mox.StrContains(gbinary)) + gmox.ReplayAll() + super(FakeComputeManager, self).__init__(compute_driver, *args, **kwargs) + + class ExtendedService(service.Service): def test_method(self): return 'service' @@ -258,3 +272,48 @@ class ServiceTestCase(test.TestCase): serv.report_state() self.assert_(not serv.model_disconnected) + + def test_compute_can_update_services(self): + """ + Test nova-compute successfully updated Service table on DB. + Doing so, self.manager.update_service must be called + if 'self.binary == nova-compute', and this testcase checks on it. + """ + host = 'foo' + binary = 'nova-compute' + topic = 'compute1' + service_create = {'host': host, + 'binary': binary, + 'topic': topic, + 'report_count': 0, + 'availability_zone': 'nova'} + service_ref = {'host': host, + 'binary': binary, + 'topic': topic, + 'report_count': 0, + 'availability_zone': 'nova', + 'id': 1} + + service.db.service_get_by_args(mox.IgnoreArg(), + host, + binary).AndRaise(exception.NotFound()) + service.db.service_create(mox.IgnoreArg(), + service_create).AndReturn(service_ref) + self.mox.StubOutWithMock(compute_manager.ComputeManager, 'update_service') + + + global ghost, gbinary, gmox + ghost = host + gbinary = binary + gmox = self.mox + + serv = service.Service(host, + binary, + topic, + 'nova.tests.test_service.FakeComputeManager') + # ReplayAll has been executed FakeComputeManager.__init__() + #self.mox.ReplayAll() + serv.start() + serv.stop() + + diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index afdc89ba2..177e8f021 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -14,21 +14,29 @@ # License for the specific language governing permissions and limitations # under the License. +import mox + from xml.etree.ElementTree import fromstring as xml_to_tree from xml.dom.minidom import parseString as xml_to_dom from nova import context from nova import db +from nova import exception from nova import flags from nova import test +from nova import logging from nova import utils from nova.api.ec2 import cloud from nova.auth import manager +from nova.db.sqlalchemy import models +from nova.compute import power_state from nova.virt import libvirt_conn FLAGS = flags.FLAGS flags.DECLARE('instances_path', 'nova.compute.manager') +libvirt = None +libxml2 = None class LibvirtConnTestCase(test.TestCase): def setUp(self): @@ -52,6 +60,38 @@ class LibvirtConnTestCase(test.TestCase): 'bridge': 'br101', 'instance_type': 'm1.small'} + def _driver_dependent_test_setup(self): + """ + Setup method. + Call this method at the top of each testcase method, + if the testcase is necessary libvirt and cheetah. + """ + try : + global libvirt + global libxml2 + libvirt_conn.libvirt = __import__('libvirt') + libvirt_conn.libxml2 = __import__('libxml2') + libvirt_conn._late_load_cheetah() + libvirt = __import__('libvirt') + except ImportError, e: + logging.warn("""This test has not been done since """ + """using driver-dependent library Cheetah/libvirt/libxml2.""") + raise e + + # inebitable mocks for calling + #nova.virt.libvirt_conn.LibvirtConnection.__init__ + nwmock = self.mox.CreateMock(libvirt_conn.NWFilterFirewall) + self.mox.StubOutWithMock(libvirt_conn, 'NWFilterFirewall', + use_mock_anything=True) + libvirt_conn.NWFilterFirewall(mox.IgnoreArg()).AndReturn(nwmock) + + obj = utils.import_object(FLAGS.firewall_driver) + fwmock = self.mox.CreateMock(obj) + self.mox.StubOutWithMock(libvirt_conn, 'utils', + use_mock_anything=True) + libvirt_conn.utils.import_object(FLAGS.firewall_driver).AndReturn(fwmock) + return nwmock, fwmock + def test_xml_and_uri_no_ramdisk_no_kernel(self): instance_data = dict(self.test_instance) self._check_xml_and_uri(instance_data, @@ -188,9 +228,8 @@ class LibvirtConnTestCase(test.TestCase): expected_result, '%s failed common check %d' % (xml, i)) - # This test is supposed to make sure we don't override a specifically - # set uri - # + # This test is supposed to make sure we don't override a specifically set uri + # # Deliberately not just assigning this string to FLAGS.libvirt_uri and # checking against that later on. This way we make sure the # implementation doesn't fiddle around with the FLAGS. @@ -202,6 +241,480 @@ class LibvirtConnTestCase(test.TestCase): uri = conn.get_uri() self.assertEquals(uri, testuri) + def test_get_memory_mb(self): + """ + Check if get_memory_mb returns memory value + Connection/OS/driver differenct does not matter for this method, + so everyone can execute for checking. + """ + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue(0 < conn.get_memory_mb()) + self.mox.UnsetStubs() + + def test_get_cpu_info_works_correctly(self): + """ + Check if get_cpu_info works correctly. + (in case libvirt.getCapabilities() works correctly) + """ + xml=("""x86_64Nehalem""" + """Intel""" + """""" + """""" + """""" + """""" + """""" + """""" + """""") + + try: + self._driver_dependent_test_setup() + except: + return + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.getCapabilities().AndReturn(xml) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue(0 < len(conn.get_cpu_info())) + self.mox.UnsetStubs() + + def test_get_cpu_info_inappropreate_xml(self): + """ + Check if get_cpu_info raises exception + in case libvirt.getCapabilities() returns wrong xml + (in case of xml doesnt have tag) + """ + xml=("""x86_64Nehalem""" + """Intel""" + """""" + """""" + """""" + """""" + """""" + """""" + """""") + + try: + self._driver_dependent_test_setup() + except: + return + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.getCapabilities().AndReturn(xml) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + try: + conn.get_cpu_info() + except exception.Invalid, e: + c1 = ( 0 <= e.message.find('Invalid xml') ) + self.assertTrue(c1) + self.mox.UnsetStubs() + + def test_get_cpu_info_inappropreate_xml2(self): + """ + Check if get_cpu_info raises exception + in case libvirt.getCapabilities() returns wrong xml + (in case of xml doesnt have inproper tag + meaning missing "socket" attribute) + """ + xml=("""x86_64Nehalem""" + """Intel""" + """""" + """""" + """""" + """""" + """""" + """""" + """""") + + try: + self._driver_dependent_test_setup() + except: + return + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.getCapabilities().AndReturn(xml) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + try: + conn.get_cpu_info() + except exception.Invalid, e: + c1 = ( 0 <= e.message.find('Invalid xml: topology') ) + self.assertTrue(c1) + self.mox.UnsetStubs() + + def test_compare_cpu_works_correctly(self): + """Calling libvirt.compute_cpu() and works correctly """ + + t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ + """"topology":{"cores":"%s", "threads":"%s", """ + """"sockets":"%s"}, "features":[%s]}""") + cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.compareCPU(mox.IgnoreArg(),0).AndReturn(1) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue( None== conn.compare_cpu(cpu_info)) + self.mox.UnsetStubs() + + def test_compare_cpu_raises_exception(self): + """ + Libvirt-related exception occurs when calling + libvirt.compare_cpu(). + """ + t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ + """"topology":{"cores":"%s", "threads":"%s", """ + """"sockets":"%s"}, "features":[%s]}""") + cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.compareCPU(mox.IgnoreArg(),0).\ + AndRaise(libvirt.libvirtError('ERR')) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertRaises(libvirt.libvirtError, conn.compare_cpu, cpu_info) + self.mox.UnsetStubs() + + def test_compare_cpu_no_compatibility(self): + """libvirt.compare_cpu() return less than 0.(no compatibility)""" + + t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ + """"topology":{"cores":"%s", "threads":"%s", """ + """"sockets":"%s"}, "features":[%s]}""") + cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.compareCPU(mox.IgnoreArg(),0).\ + AndRaise(exception.Invalid('ERR')) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertRaises(exception.Invalid, conn.compare_cpu, cpu_info) + self.mox.UnsetStubs() + + def test_ensure_filtering_rules_for_instance_works_correctly(self): + """ensure_filtering_rules_for_instance works as expected correctly""" + + instance_ref = models.Instance() + instance_ref.__setitem__('id', 1) + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + + nwmock.setup_basic_filtering(mox.IgnoreArg()) + fwmock.prepare_instance_filter(instance_ref) + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + n = 'nova-instance-%s' % instance_ref.name + libvirt_conn.LibvirtConnection._conn.nwfilterLookupByName(n) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + conn.ensure_filtering_rules_for_instance(instance_ref) + self.mox.UnsetStubs() + + def test_ensure_filtering_rules_for_instance_timeout(self): + """ensure_filtering_fules_for_instance finishes with timeout""" + + instance_ref = models.Instance() + instance_ref.__setitem__('id', 1) + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + + nwmock.setup_basic_filtering(mox.IgnoreArg()) + fwmock.prepare_instance_filter(instance_ref) + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + n = 'nova-instance-%s' % instance_ref.name + for i in range(FLAGS.live_migration_timeout_sec * 2): + libvirt_conn.LibvirtConnection._conn.\ + nwfilterLookupByName(n).AndRaise(libvirt.libvirtError('ERR')) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + try: + conn.ensure_filtering_rules_for_instance(instance_ref) + except exception.Error, e: + c1 = ( 0<=e.message.find('Timeout migrating for')) + self.assertTrue(c1) + self.mox.UnsetStubs() + + def test_live_migration_works_correctly(self): + """_live_migration works as expected correctly """ + + class dummyCall(object): + f = None + def start(self, interval=0, now=False): + pass + + instance_ref = models.Instance() + instance_ref.__setitem__('id', 1) + dest = 'desthost' + ctxt = context.get_admin_context() + + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + vdmock = self.mox.CreateMock(libvirt.virDomain) + self.mox.StubOutWithMock(vdmock, "migrateToURI", + use_mock_anything=True) + vdmock.migrateToURI(FLAGS.live_migration_uri % dest, mox.IgnoreArg(), + None, FLAGS.live_migration_bandwidth).\ + AndReturn(None) + libvirt_conn.LibvirtConnection._conn.lookupByName(instance_ref.name).\ + AndReturn(vdmock) + # below description is also ok. + #self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection._conn, + # "lookupByName", use_mock_anything=True) + + libvirt_conn.utils.LoopingCall(f=None).AndReturn(dummyCall()) + + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + ret = conn._live_migration(ctxt, instance_ref, dest) + self.assertTrue(ret == None) + self.mox.UnsetStubs() + + def test_live_migration_raises_exception(self): + """ + _live_migration raises exception, then this testcase confirms + state_description/state for the instances/volumes are recovered. + """ + class Instance(models.NovaBase): + id = 0 + volumes = None + name = 'name' + + ctxt = context.get_admin_context() + dest = 'desthost' + instance_ref = Instance() + instance_ref.__setitem__('id', 1) + instance_ref.__setitem__('volumes', [{'id':1}, {'id':2}]) + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', + use_mock_anything=True) + vdmock = self.mox.CreateMock(libvirt.virDomain) + self.mox.StubOutWithMock(vdmock, "migrateToURI", + use_mock_anything=True) + vdmock.migrateToURI(FLAGS.live_migration_uri % dest, mox.IgnoreArg(), + None, FLAGS.live_migration_bandwidth).\ + AndRaise(libvirt.libvirtError('ERR')) + libvirt_conn.LibvirtConnection._conn.lookupByName(instance_ref.name).\ + AndReturn(vdmock) + self.mox.StubOutWithMock(db, 'instance_set_state') + db.instance_set_state(ctxt, instance_ref['id'], + power_state.RUNNING, 'running') + self.mox.StubOutWithMock(db, 'volume_update') + for v in instance_ref.volumes: + db.volume_update(ctxt, v['id'], {'status': 'in-use'}).\ + InAnyOrder('g1') + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertRaises(libvirt.libvirtError, + conn._live_migration, + ctxt, instance_ref, dest) + self.mox.UnsetStubs() + + def test_post_live_migration_working_correctly(self): + """_post_live_migration works as expected correctly """ + + dest = 'dummydest' + ctxt = context.get_admin_context() + instance_ref = {'id':1, 'hostname':'i-00000001', 'host':dest, + 'fixed_ip':'dummyip', 'floating_ip':'dummyflip', + 'volumes':[{'id':1}, {'id':2} ]} + network_ref = {'id':1, 'host':dest} + floating_ip_ref = {'id':1, 'address':'1.1.1.1'} + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + fwmock.unfilter_instance(instance_ref) + + fixed_ip = instance_ref['fixed_ip'] + self.mox.StubOutWithMock(db, 'instance_get_fixed_address') + db.instance_get_fixed_address(ctxt, instance_ref['id']).AndReturn(fixed_ip) + self.mox.StubOutWithMock(db, 'fixed_ip_update') + db.fixed_ip_update(ctxt, fixed_ip, {'host': dest}) + self.mox.StubOutWithMock(db, 'fixed_ip_get_network') + db.fixed_ip_get_network(ctxt, fixed_ip).AndReturn(network_ref) + self.mox.StubOutWithMock(db, 'network_update') + db.network_update(ctxt, network_ref['id'], {'host': dest}) + + fl_ip = instance_ref['floating_ip'] + self.mox.StubOutWithMock(db, 'instance_get_floating_address') + db.instance_get_floating_address(ctxt, instance_ref['id']).AndReturn(fl_ip) + self.mox.StubOutWithMock(db, 'floating_ip_get_by_address') + db.floating_ip_get_by_address(ctxt, instance_ref['floating_ip']).\ + AndReturn(floating_ip_ref) + self.mox.StubOutWithMock(db, 'floating_ip_update') + db.floating_ip_update(ctxt, floating_ip_ref['address'], {'host': dest}) + + self.mox.StubOutWithMock(db, 'instance_update') + db.instance_update(ctxt, instance_ref['id'], + {'state_description': 'running', + 'state': power_state.RUNNING, 'host': dest}) + self.mox.StubOutWithMock(db, 'volume_update') + for v in instance_ref['volumes']: + db.volume_update(ctxt, v['id'], {'status': 'in-use'}) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + conn._post_live_migration( ctxt, instance_ref, dest) + self.mox.UnsetStubs() + + def test_post_live_migration_no_floating_ip(self): + """ + _post_live_migration works as expected correctly + (in case instance doesnt have floaitng ip) + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + instance_ref = {'id':1, 'hostname':'i-00000001', 'host':dest, + 'fixed_ip':'dummyip', 'floating_ip':'dummyflip', + 'volumes':[{'id':1}, {'id':2} ]} + network_ref = {'id':1, 'host':dest} + floating_ip_ref = {'id':1, 'address':'1.1.1.1'} + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + fwmock.unfilter_instance(instance_ref) + + fixed_ip = instance_ref['fixed_ip'] + self.mox.StubOutWithMock(db, 'instance_get_fixed_address') + db.instance_get_fixed_address(ctxt, instance_ref['id']).AndReturn(fixed_ip) + self.mox.StubOutWithMock(db, 'fixed_ip_update') + db.fixed_ip_update(ctxt, fixed_ip, {'host': dest}) + self.mox.StubOutWithMock(db, 'fixed_ip_get_network') + db.fixed_ip_get_network(ctxt, fixed_ip).AndReturn(network_ref) + self.mox.StubOutWithMock(db, 'network_update') + db.network_update(ctxt, network_ref['id'], {'host': dest}) + + self.mox.StubOutWithMock(db, 'instance_get_floating_address') + db.instance_get_floating_address(ctxt, instance_ref['id']).AndReturn(None) + self.mox.StubOutWithMock(libvirt_conn.LOG, 'info') + libvirt_conn.LOG.info(_('post livemigration operation is started..')) + libvirt_conn.LOG.info(_('floating_ip is not found for %s'), + instance_ref['hostname']) + # Checking last messages are ignored. may be no need to check so strictly? + libvirt_conn.LOG.info(mox.IgnoreArg()) + libvirt_conn.LOG.info(mox.IgnoreArg()) + + self.mox.StubOutWithMock(db, 'instance_update') + db.instance_update(ctxt, instance_ref['id'], + {'state_description': 'running', + 'state': power_state.RUNNING, + 'host': dest}) + self.mox.StubOutWithMock(db, 'volume_update') + for v in instance_ref['volumes']: + db.volume_update(ctxt, v['id'], {'status': 'in-use'}) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + conn._post_live_migration( ctxt, instance_ref, dest) + self.mox.UnsetStubs() + + def test_post_live_migration_no_floating_ip_with_exception(self): + """ + _post_live_migration works as expected correctly + (in case instance doesnt have floaitng ip, and raise exception) + """ + dest = 'dummydest' + ctxt = context.get_admin_context() + instance_ref = {'id':1, 'hostname':'i-00000001', 'host':dest, + 'fixed_ip':'dummyip', 'floating_ip':'dummyflip', + 'volumes':[{'id':1}, {'id':2} ]} + network_ref = {'id':1, 'host':dest} + floating_ip_ref = {'id':1, 'address':'1.1.1.1'} + + try: + nwmock, fwmock = self._driver_dependent_test_setup() + except: + return + fwmock.unfilter_instance(instance_ref) + + fixed_ip = instance_ref['fixed_ip'] + self.mox.StubOutWithMock(db, 'instance_get_fixed_address') + db.instance_get_fixed_address(ctxt, instance_ref['id']).AndReturn(fixed_ip) + self.mox.StubOutWithMock(db, 'fixed_ip_update') + db.fixed_ip_update(ctxt, fixed_ip, {'host': dest}) + self.mox.StubOutWithMock(db, 'fixed_ip_get_network') + db.fixed_ip_get_network(ctxt, fixed_ip).AndReturn(network_ref) + self.mox.StubOutWithMock(db, 'network_update') + db.network_update(ctxt, network_ref['id'], {'host': dest}) + + self.mox.StubOutWithMock(db, 'instance_get_floating_address') + db.instance_get_floating_address(ctxt, instance_ref['id']).\ + AndRaise(exception.NotFound()) + self.mox.StubOutWithMock(libvirt_conn.LOG, 'info') + libvirt_conn.LOG.info(_('post livemigration operation is started..')) + libvirt_conn.LOG.info(_('floating_ip is not found for %s'), + instance_ref['hostname']) + # the last message is ignored. may be no need to check so strictly? + libvirt_conn.LOG.info(mox.IgnoreArg()) + libvirt_conn.LOG.info(mox.IgnoreArg()) + + self.mox.StubOutWithMock(db, 'instance_update') + db.instance_update(ctxt, instance_ref['id'], + {'state_description': 'running', + 'state': power_state.RUNNING, 'host': dest}) + self.mox.StubOutWithMock(db, 'volume_update') + for v in instance_ref['volumes']: + db.volume_update(ctxt, v['id'], {'status': 'in-use'}) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + conn._post_live_migration( ctxt, instance_ref, dest) + self.mox.UnsetStubs() + def tearDown(self): super(LibvirtConnTestCase, self).tearDown() self.manager.delete_project(self.project) @@ -475,3 +988,4 @@ class NWFilterTestCase(test.TestCase): self.fw.prepare_instance_filter(instance) _ensure_all_called() self.teardown_security_group() + -- cgit From 09f2c4729456443c4874a8cadc53299817d6371a Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Mon, 31 Jan 2011 18:41:10 +0900 Subject: 1. Discard nova-manage host list Reason: nova-manage service list can be replacement. Changes: nova-manage 2. Fix resource checking inappropriate design. Reason: nova.scheduler.driver.has_enough_resource has inappropriate design, so fix it. This method didnt check free memory but check total memory. We need to register free memory onto databases(periodically). But periodically updating may causes flooding request to db in case of many compute-node. Currently, since memory information is only used in this feature, we take the choice that administrators manually has to execute nova-manage to let compute node update their own memory information. Changes: nova.db.sqlalchemy.models - Adding memory_mb_used, local_gb_used, vcpu_used column to Service. (local_gb and vcpu is just for reference to admins for now) nova.compute.manager - Changing nova.compute.manager.update_service Service table column is changed, so updating method must be changed. - Adding nova.compute.manager.update_available_resource a responder to admin's request to let compute nodes update their memory infomation nova.virt.libvirt_conn nova.virt.xenapi_conn nova.virt.fake - Adding getter method for memory_mb_used/local_gb_used/vcpu_used. nova-manage - request method to let compute nodes update their own memory info. --- nova/tests/test_compute.py | 55 ++++++++++++-- nova/tests/test_scheduler.py | 175 ++++++++++++++++++++++++++----------------- nova/tests/test_virt.py | 86 ++++++++++++++++++++- 3 files changed, 236 insertions(+), 80 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 344c2d2b5..8d3ac315d 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -268,7 +268,8 @@ class ComputeTestCase(test.TestCase): """ def dic_key_check(dic): - validkey = ['vcpus', 'memory_mb', 'local_gb', + validkey = ['vcpus', 'memory_mb', 'local_gb', + 'vcpus_used', 'memory_mb_used', 'local_gb_used', 'hypervisor_type', 'hypervisor_version', 'cpu_info'] return (list(set(validkey)) == list(set(dic.keys()))) @@ -286,13 +287,55 @@ class ComputeTestCase(test.TestCase): self.compute.db = dbmock self.mox.ReplayAll() + self.compute.update_service('dummy', host, binary) + self.mox.ResetAll() + + def test_update_available_resource_exception(self): + """a testcase of update_available_resource raises exception""" + host = 'foo' + binary = 'nova-compute' + ctxt = context.get_admin_context() + dbmock = self.mox.CreateMock(db) + dbmock.service_get_by_args(mox.IgnoreArg(), + mox.StrContains(host), + mox.StrContains(binary)).\ + AndRaise(exception.NotFound()) + self.compute.db = dbmock + self.compute.host = host + self.mox.ReplayAll() try: - self.compute.update_service('dummy', host, binary) + self.compute.update_available_resource(ctxt) except exception.Invalid, e: - msg = 'Cannot insert compute manager specific info' + msg = 'Cannot update resource info.' c1 = ( 0 <= e.message.find(msg)) self.assertTrue(c1) - self.mox.ResetAll() + self.mox.UnsetStubs() + + def test_update_available_resource_success(self): + """a testcase of update_available_resource finishes with no errors""" + + def dic_key_check(dic): + validkey = [ 'vcpus_avail', 'memory_mb_avail', 'local_gb_avail'] + return (list(set(validkey)) == list(set(dic.keys()))) + + host = 'foo' + binary = 'nova-compute' + ctxt = context.get_admin_context() + service_ref = {'id':1, 'binary':'nova-compute', 'topic':'compute'} + dbmock = self.mox.CreateMock(db) + dbmock.service_get_by_args(mox.IgnoreArg(), + mox.StrContains(host), + mox.StrContains(binary)).\ + AndReturn(service_ref) + dbmock.service_update(mox.IgnoreArg(), + service_ref['id'], + mox.Func(dic_key_check)) + + self.compute.db = dbmock + self.compute.host = host + self.mox.ReplayAll() + self.compute.update_available_resource(ctxt) + self.mox.UnsetStubs() def _setup_other_managers(self): self.volume_manager = utils.import_object(FLAGS.volume_manager) @@ -444,7 +487,7 @@ class ComputeTestCase(test.TestCase): rpc.call(c, db.queue_get_for(c, FLAGS.compute_topic, dest), {"method": "pre_live_migration", "args": {'instance_id': i_id}}).\ - InAnyOrder('g1').AndRaise(rpc.RemoteError('du', 'mm', 'y')) + InAnyOrder('g1').AndRaise(rpc.RemoteError('', '', '')) self.mox.StubOutWithMock(compute_manager.LOG, 'error') compute_manager.LOG.error('Pre live migration for %s failed at %s', instance_ref['hostname'], dest) @@ -480,7 +523,7 @@ class ComputeTestCase(test.TestCase): rpc.call(c, compute_topic, {"method": "pre_live_migration", "args": {'instance_id': i_id}}).\ - AndRaise(rpc.RemoteError('du', 'mm', 'y')) + AndRaise(rpc.RemoteError('', '', '')) self.mox.StubOutWithMock(compute_manager.LOG, 'error') compute_manager.LOG.error('Pre live migration for %s failed at %s', instance_ref['hostname'], dest) diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index c62bca9b1..36d99d666 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -41,6 +41,7 @@ from nova.db.sqlalchemy import models FLAGS = flags.FLAGS flags.DECLARE('max_cores', 'nova.scheduler.simple') flags.DECLARE('stub_network', 'nova.compute.manager') +flags.DECLARE('instances_path', 'nova.compute.manager') class TestDriver(driver.Scheduler): @@ -111,7 +112,8 @@ class SchedulerTestCase(test.TestCase): scheduler = manager.SchedulerManager() dest = 'dummydest' ctxt = context.get_admin_context() - r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100} + r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100, + 'vcpus_used':16, 'memory_mb_used':32, 'local_gb_used':10} service_ref = {'id':1, 'host':dest} service_ref.update(r0) @@ -140,7 +142,8 @@ class SchedulerTestCase(test.TestCase): scheduler = manager.SchedulerManager() dest = 'dummydest' ctxt = context.get_admin_context() - r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100} + r0 = {'vcpus':16, 'memory_mb':32, 'local_gb':100, + 'vcpus_used':16, 'memory_mb_used':32, 'local_gb_used':10} r1 = {'vcpus':10, 'memory_mb':4, 'local_gb':20} r2 = {'vcpus':10, 'memory_mb':20, 'local_gb':30} service_ref = {'id':1, 'host':dest} @@ -148,7 +151,7 @@ class SchedulerTestCase(test.TestCase): instance_ref2 = {'id':2, 'project_id':'p-01', 'host':'dummy'} instance_ref2.update(r1) instance_ref3 = {'id':3, 'project_id':'p-02', 'host':'dummy'} - instance_ref3.update(r1) + instance_ref3.update(r2) self.mox.StubOutWithMock(manager, 'db', use_mock_anything=True) manager.db.service_get_all_compute_sorted(mox.IgnoreArg()).\ @@ -176,6 +179,7 @@ class SchedulerTestCase(test.TestCase): self.assertTrue( c1 and c2 and c3 and c4 and c5 and c6) self.mox.UnsetStubs() + class ZoneSchedulerTestCase(test.TestCase): """Test case for zone scheduler""" def setUp(self): @@ -495,7 +499,7 @@ class SimpleDriverTestCase(test.TestCase): ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-00000001', 'host':'dummy', - 'volumes':[{'id':1}, {'id':2}]} + 'volumes':[{'id':1}, {'id':2}]} dest = 'dummydest' self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) @@ -793,7 +797,10 @@ class SimpleDriverTestCase(test.TestCase): ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + driver_i = self.scheduler.driver + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([]) @@ -813,6 +820,7 @@ class SimpleDriverTestCase(test.TestCase): Original host(an instance launched on) does not exist. """ dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'launched_on':'h1'} @@ -821,6 +829,8 @@ class SimpleDriverTestCase(test.TestCase): service_ref.__setitem__('topic', 'compute') service_ref.__setitem__('host', i_ref['host']) + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) @@ -844,6 +854,7 @@ class SimpleDriverTestCase(test.TestCase): Original host and dest host has different hypervisor type. """ dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', @@ -856,6 +867,8 @@ class SimpleDriverTestCase(test.TestCase): service_ref2.__setitem__('id', 2) service_ref2.__setitem__('hypervisor_type', 'xen') + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) @@ -879,6 +892,7 @@ class SimpleDriverTestCase(test.TestCase): Original host and dest host has different hypervisor version. """ dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', @@ -891,6 +905,8 @@ class SimpleDriverTestCase(test.TestCase): service_ref2.__setitem__('id', 2) service_ref2.__setitem__('hypervisor_version', 12001) + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) @@ -914,6 +930,7 @@ class SimpleDriverTestCase(test.TestCase): Original host and dest host has different hypervisor version. """ dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', @@ -927,6 +944,8 @@ class SimpleDriverTestCase(test.TestCase): service_ref2.__setitem__('hypervisor_version', 12000) service_ref2.__setitem__('cpuinfo', 'info') + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) @@ -956,6 +975,7 @@ class SimpleDriverTestCase(test.TestCase): The testcase make sure everything finished with no error. """ dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic i_ref = {'id':1, 'hostname':'i-01', @@ -969,6 +989,8 @@ class SimpleDriverTestCase(test.TestCase): service_ref2.__setitem__('hypervisor_version', 12000) service_ref2.__setitem__('cpuinfo', 'info') + self.mox.StubOutWithMock(driver_i, 'mounted_on_same_shared_storage') + driver_i.mounted_on_same_shared_storage(mox.IgnoreArg(), i_ref, dest) self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) @@ -988,121 +1010,134 @@ class SimpleDriverTestCase(test.TestCase): self.assertTrue(ret == None) self.mox.UnsetStubs() - def test_has_enough_resource_lack_resource_vcpu(self): + def test_has_enough_resource_lack_resource_memory(self): """ A testcase of driver.has_enough_resource. - Lack of vcpu.(boundary check) + Lack of memory_mb.(boundary check) """ dest = 'dummydest' ctxt = context.get_admin_context() topic = FLAGS.compute_topic - service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} - i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', - 'vcpus':6, 'memory_mb':8, 'local_gb':10} - i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} - i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} + service_ref = {'id':1, 'memory_mb':32, 'memory_mb_used':12, 'local_gb':100} + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', + 'vcpus':5, 'memory_mb':20, 'local_gb':10} self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) - driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([i_ref2, i_ref3]) self.mox.ReplayAll() try: - self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + self.scheduler.driver.has_enough_resource(ctxt, i_ref, dest) except exception.NotEmpty, e: msg = 'is not capable to migrate' self.assertTrue(e.message.find(msg) >= 0) self.mox.UnsetStubs() + self.mox.UnsetStubs() - def test_has_enough_resource_lack_resource_memory(self): + def test_has_enough_resource_works_correctly(self): """ - A testcase of driver.has_enough_resource. - Lack of memory_mb.(boundary check) + A testcase of driver.has_enough_resource + to make sure everything finished with no error. """ dest = 'dummydest' ctxt = context.get_admin_context() topic = FLAGS.compute_topic - service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} - i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':16, 'local_gb':10} - i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} - i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', + service_ref = {'id':1, 'memory_mb':120, 'memory_mb_used':32} + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy', 'vcpus':5, 'memory_mb':8, 'local_gb':10} self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ AndReturn([service_ref]) - driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([i_ref2, i_ref3]) self.mox.ReplayAll() - try: - self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) - except exception.NotEmpty, e: - msg = 'is not capable to migrate' - self.assertTrue(e.message.find(msg) >= 0) + ret = self.scheduler.driver.has_enough_resource(ctxt, i_ref, dest) + self.assertTrue(ret == None) self.mox.UnsetStubs() + + def test_mounted_on_same_shared_storage_cannot_make_tmpfile(self): + """ + A testcase of driver.mounted_on_same_shared_storage + checks log message when dest host cannot make tmpfile. + """ + dest = 'dummydest' + driver_i = self.scheduler.driver + ctxt = context.get_admin_context() + topic = FLAGS.compute_topic + fpath = '/test/20110127120000' + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + + self.mox.StubOutWithMock(driver, 'rpc', use_mock_anything=True) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(ctxt, FLAGS.compute_topic, dest), + {"method": 'mktmpfile'}).AndRaise(rpc.RemoteError('', '', '')) + self.mox.StubOutWithMock(driver.logging, 'error') + msg = _("Cannot create tmpfile at %s to confirm shared storage.") + driver.logging.error(msg % FLAGS.instances_path) + + self.mox.ReplayAll() + self.assertRaises(rpc.RemoteError, + driver_i.mounted_on_same_shared_storage, + ctxt, i_ref, dest) self.mox.UnsetStubs() - def test_has_enough_resource_lack_resource_disk(self): + def test_mounted_on_same_shared_storage_cannot_comfirm_tmpfile(self): """ - A testcase of driver.has_enough_resource. - Lack of local_gb.(boundary check) + A testcase of driver.mounted_on_same_shared_storage + checks log message when src host cannot comfirm tmpfile. """ - scheduler = manager.SchedulerManager() dest = 'dummydest' + driver_i = self.scheduler.driver ctxt = context.get_admin_context() topic = FLAGS.compute_topic - service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} - i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':80} - i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} - i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} + fpath = '/test/20110127120000' + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + + self.mox.StubOutWithMock(driver, 'rpc', use_mock_anything=True) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(ctxt, FLAGS.compute_topic, dest), + {"method": 'mktmpfile'}).AndReturn(fpath) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(ctxt, FLAGS.compute_topic, i_ref['host']), + {"method": 'exists', "args":{'path':fpath}}).\ + AndRaise(rpc.RemoteError('','','')) + self.mox.StubOutWithMock(driver.logging, 'error') + msg = _("Cannot create tmpfile at %s to confirm shared storage.") + driver.logging.error(msg % FLAGS.instances_path) - self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) - driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([service_ref]) - driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([i_ref2, i_ref3]) - self.mox.ReplayAll() - try: - self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) - except exception.NotEmpty, e: - msg = 'is not capable to migrate' - self.assertTrue(e.message.find(msg) >= 0) + self.assertRaises(rpc.RemoteError, + driver_i.mounted_on_same_shared_storage, + ctxt, i_ref, dest) self.mox.UnsetStubs() - def test_has_enough_resource_works_correctly(self): + + def test_mounted_on_same_shared_storage_works_correctly(self): """ - A testcase of driver.has_enough_resource + A testcase of driver.mounted_on_same_shared_storage to make sure everything finished with no error. """ dest = 'dummydest' ctxt = context.get_admin_context() topic = FLAGS.compute_topic - service_ref = {'id':1, 'vcpus':16, 'memory_mb':32, 'local_gb':100} - i_ref1 = {'id':1, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} - i_ref2 = {'id':2, 'hostname':'i-01', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} - i_ref3 = {'id':3, 'hostname':'i-02', 'host':'dummy', - 'vcpus':5, 'memory_mb':8, 'local_gb':10} + fpath = '/test/20110127120000' + i_ref = {'id':1, 'hostname':'i-01', 'host':'dummy'} + + self.mox.StubOutWithMock(driver, 'rpc', use_mock_anything=True) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(mox.IgnoreArg(), FLAGS.compute_topic, dest), + {"method": 'mktmpfile'}).AndReturn(fpath) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(mox.IgnoreArg(), FLAGS.compute_topic, i_ref['host']), + {"method": 'exists', "args":{'path':fpath}}) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(mox.IgnoreArg(), FLAGS.compute_topic, dest), + {"method": 'remove', "args":{'path':fpath}}) - self.mox.StubOutWithMock(driver, 'db', use_mock_anything=True) - driver.db.service_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([service_ref]) - driver.db.instance_get_all_by_host(mox.IgnoreArg(), dest).\ - AndReturn([i_ref2, i_ref3]) - self.mox.ReplayAll() - ret = self.scheduler.driver.has_enough_resource(ctxt, i_ref1, dest) + ret = self.scheduler.driver.mounted_on_same_shared_storage(ctxt, + i_ref, + dest) self.assertTrue(ret == None) self.mox.UnsetStubs() diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 177e8f021..2828baced 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -241,11 +241,11 @@ class LibvirtConnTestCase(test.TestCase): uri = conn.get_uri() self.assertEquals(uri, testuri) - def test_get_memory_mb(self): + def test_get_vcpu_total(self): """ - Check if get_memory_mb returns memory value + Check if get_vcpu_total returns appropriate cpu value Connection/OS/driver differenct does not matter for this method, - so everyone can execute for checking. + everyone can execute for checking. """ try: self._driver_dependent_test_setup() @@ -254,9 +254,87 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) - self.assertTrue(0 < conn.get_memory_mb()) + self.assertTrue(0 < conn.get_vcpu_total()) self.mox.UnsetStubs() + + def test_get_memory_mb_total(self): + """Check if get_memory_mb returns appropriate memory value""" + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue(0 < conn.get_memory_mb_total()) + self.mox.UnsetStubs() + + def test_get_local_gb_total(self): + """Check if get_local_gb_total returns appropriate disk value""" + # Note(masumotok): cannot test b/c FLAGS.instances_path is + # inevitable for this test.. + #try: + # self._driver_dependent_test_setup() + #except: + # return + # + #self.mox.ReplayAll() + #conn = libvirt_conn.LibvirtConnection(False) + #self.assertTrue(0 < conn.get_local_gb_total()) + #self.mox.UnsetStubs() + pass + + def test_get_vcpu_used(self): + """Check if get_local_gb_total returns appropriate disk value""" + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn', use_mock_anything=True) + libvirt_conn.LibvirtConnection._conn.listDomainsID().AndReturn([1,2]) + vdmock = self.mox.CreateMock(libvirt.virDomain) + self.mox.StubOutWithMock(vdmock, "vcpus", use_mock_anything=True) + vdmock.vcpus().AndReturn(['', [('dummycpu'), ('dummycpu')]]) + vdmock.vcpus().AndReturn(['', [('dummycpu'), ('dummycpu')]]) + libvirt_conn.LibvirtConnection._conn.lookupByID(mox.IgnoreArg()).\ + AndReturn(vdmock) + libvirt_conn.LibvirtConnection._conn.lookupByID(mox.IgnoreArg()).\ + AndReturn(vdmock) + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue( conn.get_vcpu_used() == 4) + self.mox.UnsetStubs() + + def test_get_memory_mb_used(self): + """Check if get_memory_mb returns appropriate memory value""" + try: + self._driver_dependent_test_setup() + except: + return + + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertTrue(0 < conn.get_memory_mb_used()) + self.mox.UnsetStubs() + + def test_get_local_gb_used(self): + """Check if get_local_gb_total returns appropriate disk value""" + # Note(masumotok): cannot test b/c FLAGS.instances_path is + # inevitable for this test.. + #try: + # self._driver_dependent_test_setup() + #except: + # return + + #self.mox.ReplayAll() + #conn = libvirt_conn.LibvirtConnection(False) + #self.assertTrue(0 < conn.get_local_gb_used()) + #self.mox.UnsetStubs() + pass + def test_get_cpu_info_works_correctly(self): """ Check if get_cpu_info works correctly. -- cgit From a776844e38c7e747397785a6ce6b1de1b043d850 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 1 Feb 2011 18:34:46 -0800 Subject: initial support for dynamic instance_types: db migration and model, stub tests and stub methods. --- nova/tests/api/openstack/test_flavors.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 1bdaea161..05624c5a9 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -44,5 +44,15 @@ class FlavorsTest(unittest.TestCase): def test_get_flavor_by_id(self): pass + def test_create_favor(self): + pass + + def test_delete_flavor(self): + pass + + def test_list_flavors(self): + pass + + if __name__ == '__main__': unittest.main() -- cgit From 9be0770208b0e75c7d93ba10165b82d5be11be27 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Thu, 3 Feb 2011 17:57:46 -0800 Subject: flagged all INSTANCE_TYPES usage with FIXME comment. Added basic usage to nova-manage (needs formatting). created api methods. --- nova/tests/api/openstack/test_flavors.py | 30 +++++++++++++++++++----------- nova/tests/db/fakes.py | 1 + nova/tests/test_quota.py | 3 +++ nova/tests/test_xenapi.py | 1 + 4 files changed, 24 insertions(+), 11 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 05624c5a9..0f0ed2e84 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -21,6 +21,8 @@ import stubout import webob import nova.api +from nova import context +from nova import db from nova.api.openstack import flavors from nova.tests.api.openstack import fakes @@ -33,6 +35,7 @@ class FlavorsTest(unittest.TestCase): fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) + self.context = context.get_admin_context() def tearDown(self): self.stubs.UnsetAll() @@ -41,17 +44,22 @@ class FlavorsTest(unittest.TestCase): req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) - def test_get_flavor_by_id(self): - pass - - def test_create_favor(self): - pass - - def test_delete_flavor(self): - pass - - def test_list_flavors(self): - pass + def test_create_list_delete_favor(self): + # create a new flavor + starting_flavors = db.instance_type_get_all(self.context) + new_instance_type = dict(name="os1.big",memory_mb=512, vcpus=1, local_gb=120, flavorid=25) + new_flavor = db.instance_type_create(self.context, new_instance_type) + self.assertEqual(new_flavor["name"], new_instance_type["name"]) + # retrieve the newly created flavor + retrieved_new_flavor = db.instance_type_get_by_name(self.context, new_instance_type["name"]) + # self.assertEqual(len(tuple(retrieved_new_flavor)),1) + self.assertEqual(retrieved_new_flavor["memory_mb"], new_instance_type["memory_mb"]) + flavors = db.instance_type_get_all(self.context) + self.assertNotEqual(starting_flavors, flavors) + # delete the newly created flavor + delete_query = db.instance_type_destroy(self.context,new_instance_type["name"]) + retrieve_deleted_flavor = db.instance_type_get_by_name(self.context, new_instance_type["name"]) + self.assertEqual(retrieve_deleted_flavor["deleted"], 1) if __name__ == '__main__': diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 05bdd172e..6cf917d76 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -44,6 +44,7 @@ def stub_out_db_instance_api(stubs): def fake_instance_create(values): """ Stubs out the db.instance_create method """ + # FIX-ME(kpepple) for dynamic flavors type_data = instance_types.INSTANCE_TYPES[values['instance_type']] base_options = { diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 9548a8c13..f2c9c456f 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -75,15 +75,18 @@ class QuotaTestCase(test.TestCase): def test_quota_overrides(self): """Make sure overriding a projects quotas works""" + # FIX-ME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 2) db.quota_create(self.context, {'project_id': self.project.id, 'instances': 10}) + # FIX-ME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 4) db.quota_update(self.context, self.project.id, {'cores': 100}) + # FIX-ME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 10) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 9f5b266f3..e38bd4dab 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -225,6 +225,7 @@ class XenAPIVMTestCase(test.TestCase): vm = vms[0] # Check that m1.large above turned into the right thing. + # FIX-ME(kpepple) for dynamic flavors instance_type = instance_types.INSTANCE_TYPES['m1.large'] mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) -- cgit From 25a5afbb783e28bd5303853bf09e4b254c938302 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 5 Feb 2011 01:14:45 -0800 Subject: added FIXME(kpepple) comments for all constant usage of INSTANCE_TYPES. updated api/ec2/admin.py to use the new instance_types db table --- nova/tests/api/openstack/test_flavors.py | 18 ++++++++++++------ nova/tests/db/fakes.py | 2 +- nova/tests/test_quota.py | 6 +++--- nova/tests/test_xenapi.py | 2 +- 4 files changed, 17 insertions(+), 11 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 0f0ed2e84..b416e02d6 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -47,19 +47,25 @@ class FlavorsTest(unittest.TestCase): def test_create_list_delete_favor(self): # create a new flavor starting_flavors = db.instance_type_get_all(self.context) - new_instance_type = dict(name="os1.big",memory_mb=512, vcpus=1, local_gb=120, flavorid=25) + new_instance_type = dict(name="os1.big", memory_mb=512, + vcpus=1, local_gb=120, flavorid=25) new_flavor = db.instance_type_create(self.context, new_instance_type) self.assertEqual(new_flavor["name"], new_instance_type["name"]) # retrieve the newly created flavor - retrieved_new_flavor = db.instance_type_get_by_name(self.context, new_instance_type["name"]) + retrieved_new_flavor = db.instance_type_get_by_name( + self.context, + new_instance_type["name"]) # self.assertEqual(len(tuple(retrieved_new_flavor)),1) - self.assertEqual(retrieved_new_flavor["memory_mb"], new_instance_type["memory_mb"]) + self.assertEqual(retrieved_new_flavor["memory_mb"], + new_instance_type["memory_mb"]) flavors = db.instance_type_get_all(self.context) self.assertNotEqual(starting_flavors, flavors) # delete the newly created flavor - delete_query = db.instance_type_destroy(self.context,new_instance_type["name"]) - retrieve_deleted_flavor = db.instance_type_get_by_name(self.context, new_instance_type["name"]) - self.assertEqual(retrieve_deleted_flavor["deleted"], 1) + delete_query = db.instance_type_destroy(self.context, + new_instance_type["name"]) + deleted_flavor = db.instance_type_get_by_name(self.context, + new_instance_type["name"]) + self.assertEqual(deleted_flavor["deleted"], 1) if __name__ == '__main__': diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 6cf917d76..3b47fc867 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -44,7 +44,7 @@ def stub_out_db_instance_api(stubs): def fake_instance_create(values): """ Stubs out the db.instance_create method """ - # FIX-ME(kpepple) for dynamic flavors + # FIXME(kpepple) for dynamic flavors type_data = instance_types.INSTANCE_TYPES[values['instance_type']] base_options = { diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index f2c9c456f..c70803e05 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -75,18 +75,18 @@ class QuotaTestCase(test.TestCase): def test_quota_overrides(self): """Make sure overriding a projects quotas works""" - # FIX-ME(kpepple) for dynamic flavors + # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 2) db.quota_create(self.context, {'project_id': self.project.id, 'instances': 10}) - # FIX-ME(kpepple) for dynamic flavors + # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 4) db.quota_update(self.context, self.project.id, {'cores': 100}) - # FIX-ME(kpepple) for dynamic flavors + # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 10) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index e38bd4dab..1d42f8da3 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -225,7 +225,7 @@ class XenAPIVMTestCase(test.TestCase): vm = vms[0] # Check that m1.large above turned into the right thing. - # FIX-ME(kpepple) for dynamic flavors + # FIXME(kpepple) for dynamic flavors instance_type = instance_types.INSTANCE_TYPES['m1.large'] mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) -- cgit From fcd0a7b245470054718c94adf0da6a528a01f173 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 5 Feb 2011 13:49:38 -0800 Subject: corrected db.instance_types to return expect dict instead of lists. updated openstack flavors to expect dicts instead of lists. added deleted column to returned dict. --- nova/tests/api/openstack/test_flavors.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index b416e02d6..9287e8adf 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -55,8 +55,7 @@ class FlavorsTest(unittest.TestCase): retrieved_new_flavor = db.instance_type_get_by_name( self.context, new_instance_type["name"]) - # self.assertEqual(len(tuple(retrieved_new_flavor)),1) - self.assertEqual(retrieved_new_flavor["memory_mb"], + self.assertEqual(retrieved_new_flavor.values()[0]["memory_mb"], new_instance_type["memory_mb"]) flavors = db.instance_type_get_all(self.context) self.assertNotEqual(starting_flavors, flavors) @@ -65,7 +64,7 @@ class FlavorsTest(unittest.TestCase): new_instance_type["name"]) deleted_flavor = db.instance_type_get_by_name(self.context, new_instance_type["name"]) - self.assertEqual(deleted_flavor["deleted"], 1) + self.assertEqual(deleted_flavor.values()[0]["deleted"], 1) if __name__ == '__main__': -- cgit From 2acc31a293b067644f26877dc52bacb7ef9e9bd1 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 5 Feb 2011 18:28:26 -0800 Subject: added preliminary testing for bin/nova-manage while i am somewhat conflicted about the path these tests have taken, i think it is better than no tests at all --- nova/tests/test_nova_manage.py | 72 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 nova/tests/test_nova_manage.py (limited to 'nova/tests') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py new file mode 100644 index 000000000..09ed8163b --- /dev/null +++ b/nova/tests/test_nova_manage.py @@ -0,0 +1,72 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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. +""" +Tests For Nova-Manage +""" + +import os +import subprocess + +from nova import test + + +class NovaManageTestCase(test.TestCase): + """Test case for nova-manage""" + def setUp(self): + super(NovaManageTestCase, self).setUp() + + def teardown(self): + fnull.close() + + def test_create_and_delete_instance_types(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "create", "test", "256", "1",\ + "120", "99"], stdout=fnull) + self.assertEqual(0, retcode) + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "delete", "test"], stdout=fnull) + self.assertEqual(0, retcode) + + def test_list_instance_types(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type", \ + "list"], stdout=fnull) + self.assertEqual(0, retcode) + + def test_list_specific_instance_type(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type", "list", + "m1.medium"], stdout=fnull) + self.assertEqual(0, retcode) + + def test_should_raise_on_bad_create_args(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "create", "test", "256", "0",\ + "120", "99"], stdout=fnull) + self.assertEqual(1, retcode) + + def test_should_fail_on_duplicate_flavorid(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "create", "test", "256", "1",\ + "120", "1"], stdout=fnull) + self.assertEqual(1, retcode) + + def test_instance_type_delete_should_fail_without_valid_name(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "delete", "saefasff"], stdout=fnull) + self.assertEqual(1, retcode) -- cgit From ea5271ed69d72dcab8189c3bfc66220c7ff60862 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sun, 6 Feb 2011 10:56:05 -0800 Subject: refactor to remove ugly code in flavors --- nova/tests/db/fakes.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 3b47fc867..859ed6edc 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -46,6 +46,8 @@ def stub_out_db_instance_api(stubs): # FIXME(kpepple) for dynamic flavors type_data = instance_types.INSTANCE_TYPES[values['instance_type']] + # type_data = db.instance_type_get_by_name(context,\ + # instance_type)[instance_type] base_options = { 'name': values['name'], -- cgit From 7dcdbcc546248c3384bd15975a721413e1d1f507 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sun, 6 Feb 2011 13:28:07 -0800 Subject: simplified instance_types db calls to return entire row - we may need these extra columns for some features and there seems to be little downside in including them. still need to fix testing calls. --- nova/tests/api/openstack/test_flavors.py | 22 ---------------------- nova/tests/db/fakes.py | 2 +- 2 files changed, 1 insertion(+), 23 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 9287e8adf..532b34e1b 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -44,28 +44,6 @@ class FlavorsTest(unittest.TestCase): req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) - def test_create_list_delete_favor(self): - # create a new flavor - starting_flavors = db.instance_type_get_all(self.context) - new_instance_type = dict(name="os1.big", memory_mb=512, - vcpus=1, local_gb=120, flavorid=25) - new_flavor = db.instance_type_create(self.context, new_instance_type) - self.assertEqual(new_flavor["name"], new_instance_type["name"]) - # retrieve the newly created flavor - retrieved_new_flavor = db.instance_type_get_by_name( - self.context, - new_instance_type["name"]) - self.assertEqual(retrieved_new_flavor.values()[0]["memory_mb"], - new_instance_type["memory_mb"]) - flavors = db.instance_type_get_all(self.context) - self.assertNotEqual(starting_flavors, flavors) - # delete the newly created flavor - delete_query = db.instance_type_destroy(self.context, - new_instance_type["name"]) - deleted_flavor = db.instance_type_get_by_name(self.context, - new_instance_type["name"]) - self.assertEqual(deleted_flavor.values()[0]["deleted"], 1) - if __name__ == '__main__': unittest.main() diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 859ed6edc..3aa7fcd22 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -47,7 +47,7 @@ def stub_out_db_instance_api(stubs): # FIXME(kpepple) for dynamic flavors type_data = instance_types.INSTANCE_TYPES[values['instance_type']] # type_data = db.instance_type_get_by_name(context,\ - # instance_type)[instance_type] + # instance_type) base_options = { 'name': values['name'], -- cgit From ea5ba79802321bb25f03dfb24fd7fb01866d9921 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sun, 6 Feb 2011 13:48:03 -0800 Subject: aliased flavor to instance_types in nova-manage. will probably need to make flavor a full fledged class as users will want to list flavors by flavor name --- nova/tests/test_nova_manage.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 09ed8163b..487f172ff 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -39,11 +39,12 @@ class NovaManageTestCase(test.TestCase): "delete", "test"], stdout=fnull) self.assertEqual(0, retcode) - def test_list_instance_types(self): + def test_list_instance_types_or_flavors(self): fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type", \ - "list"], stdout=fnull) - self.assertEqual(0, retcode) + for c in ["instance_type", "flavor"]: + retcode = subprocess.call(["bin/nova-manage", c, \ + "list"], stdout=fnull) + self.assertEqual(0, retcode) def test_list_specific_instance_type(self): fnull = open(os.devnull, 'w') -- cgit From bb2a379e2827ceccc5b46b0a9936e6dcedc6499e Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 7 Feb 2011 15:04:26 -0800 Subject: added INSTANCE_TYPES to test for compatibility with current tests --- nova/tests/db/fakes.py | 6 ++---- nova/tests/test_quota.py | 9 +++------ nova/tests/test_xenapi.py | 3 +-- 3 files changed, 6 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 3aa7fcd22..d9a5032ee 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -20,6 +20,7 @@ import time from nova import db +from nova import test from nova import utils from nova.compute import instance_types @@ -44,10 +45,7 @@ def stub_out_db_instance_api(stubs): def fake_instance_create(values): """ Stubs out the db.instance_create method """ - # FIXME(kpepple) for dynamic flavors - type_data = instance_types.INSTANCE_TYPES[values['instance_type']] - # type_data = db.instance_type_get_by_name(context,\ - # instance_type) + type_data = test.INSTANCE_TYPES[values['instance_type']] base_options = { 'name': values['name'], diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index c70803e05..4206ca416 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -75,20 +75,17 @@ class QuotaTestCase(test.TestCase): def test_quota_overrides(self): """Make sure overriding a projects quotas works""" - # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, - instance_types.INSTANCE_TYPES['m1.small']) + test.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 2) db.quota_create(self.context, {'project_id': self.project.id, 'instances': 10}) - # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, - instance_types.INSTANCE_TYPES['m1.small']) + test.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 4) db.quota_update(self.context, self.project.id, {'cores': 100}) - # FIXME(kpepple) for dynamic flavors num_instances = quota.allowed_instances(self.context, 100, - instance_types.INSTANCE_TYPES['m1.small']) + test.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 10) db.quota_destroy(self.context, self.project.id) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 1d42f8da3..d8611ea10 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -225,8 +225,7 @@ class XenAPIVMTestCase(test.TestCase): vm = vms[0] # Check that m1.large above turned into the right thing. - # FIXME(kpepple) for dynamic flavors - instance_type = instance_types.INSTANCE_TYPES['m1.large'] + instance_type = test.INSTANCE_TYPES['m1.large'] mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) vcpus = instance_type['vcpus'] -- cgit From 2f5d8a25c99875838a08ed06728bcd9d68cdd7f1 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 8 Feb 2011 11:31:20 -0800 Subject: added testing for nova-manage instance_type --- nova/tests/test_nova_manage.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 487f172ff..5645bf97e 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -66,6 +66,17 @@ class NovaManageTestCase(test.TestCase): "120", "1"], stdout=fnull) self.assertEqual(1, retcode) + def test_should_fail_on_duplicate_name(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "create", "fsfsfsdfsdf", "256", "1",\ + "120", "189"], stdout=fnull) + self.assertEqual(0, retcode) + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "create", "fsfsfsdfsdf", "256", "1",\ + "120", "190"], stdout=fnull) + self.assertEqual(1, retcode) + def test_instance_type_delete_should_fail_without_valid_name(self): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type",\ -- cgit From dd2544345e1686ee1ed020fd8f14607d10d8b3d1 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 8 Feb 2011 19:24:14 -0800 Subject: added testing for instance_types.py and refactored nova-manage to use instance_types.py instead of going directly to db. --- nova/tests/test_instance_types.py | 67 +++++++++++++++++++++++++++++++++++++++ nova/tests/test_nova_manage.py | 4 +-- 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 nova/tests/test_instance_types.py (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py new file mode 100644 index 000000000..819431763 --- /dev/null +++ b/nova/tests/test_instance_types.py @@ -0,0 +1,67 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# 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. +""" +Unit Tests for instance types code +""" +import datetime + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.compute import instance_types +from nova.db.sqlalchemy.session import get_session +from nova.db.sqlalchemy import models + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.compute') + + +class InstanceTypeTestCase(test.TestCase): + """Test cases for instance type code""" + def setUp(self): + super(InstanceTypeTestCase, self).setUp() + session = get_session() + max_flavorid = session.query(models.InstanceTypes).\ + order_by("flavorid desc").first() + self.flavorid = max_flavorid["flavorid"] + 1 + self.name = str(datetime.datetime.utcnow()) + + def tearDown(self): + pass + + def test_instance_type_create_then_delete(self): + """Ensure instance types can be created""" + starting_inst_list = instance_types.get_all_types() + instance_types.create(self.name, 256, 1, 120, self.flavorid) + new = instance_types.get_all_types() + self.assertNotEqual(len(starting_inst_list), + len(new), + 'instance was not created') + rows = instance_types.destroy(self.name) + self.assertEqual(rows, 1) + self.assertEqual(1, + instance_types.get_instance_type(self.name)["deleted"]) + self.assertEqual(starting_inst_list, instance_types.get_all_types()) + + def test_get_all_instance_types(self): + """Ensures that all instance types can be retrieved""" + session = get_session() + total_instance_types = session.query(models.InstanceTypes).\ + count() + inst_types = instance_types.get_all_types() + self.assertEqual(total_instance_types, len(inst_types)) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 5645bf97e..a2fa919a0 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -31,8 +31,8 @@ class NovaManageTestCase(test.TestCase): def test_create_and_delete_instance_types(self): fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", "test", "256", "1",\ + retcode = subprocess.call(["bin/nova-manage", "instance_type", + "create", "test", "256", "1", "120", "99"], stdout=fnull) self.assertEqual(0, retcode) retcode = subprocess.call(["bin/nova-manage", "instance_type",\ -- cgit From 6e881239c9b8a1fb209868addf1a2b83042f2128 Mon Sep 17 00:00:00 2001 From: brian-lamar Date: Wed, 9 Feb 2011 13:30:40 -0500 Subject: 1) Moved tests for limiter to test_common.py (from __init__.py) and expanded test suite to include bad inputs and tests for custom limits (#2) 2) Wrapped int() calls in blocks to ensure logic regardless of input. 3) Moved 1000 hard limit hard-coding to a keyword param. 4) Added comments as I went. --- nova/tests/api/openstack/__init__.py | 28 ------ nova/tests/api/openstack/test_common.py | 161 ++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 28 deletions(-) create mode 100644 nova/tests/api/openstack/test_common.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index 14eaaa62c..77b1dd37f 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -92,31 +92,3 @@ class RateLimitingMiddlewareTest(unittest.TestCase): self.assertEqual(middleware.limiter.__class__.__name__, "Limiter") middleware = RateLimitingMiddleware(simple_wsgi, service_host='foobar') self.assertEqual(middleware.limiter.__class__.__name__, "WSGIAppProxy") - - -class LimiterTest(unittest.TestCase): - - def test_limiter(self): - items = range(2000) - req = Request.blank('/') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=0') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=3') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=2005') - self.assertEqual(limited(items, req), []) - req = Request.blank('/?limit=10') - self.assertEqual(limited(items, req), items[:10]) - req = Request.blank('/?limit=0') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?limit=3000') - self.assertEqual(limited(items, req), items[:1000]) - req = Request.blank('/?offset=1&limit=3') - self.assertEqual(limited(items, req), items[1:4]) - req = Request.blank('/?offset=3&limit=0') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=3&limit=1500') - self.assertEqual(limited(items, req), items[3:1003]) - req = Request.blank('/?offset=3000&limit=10') - self.assertEqual(limited(items, req), []) diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py new file mode 100644 index 000000000..9d9837cc9 --- /dev/null +++ b/nova/tests/api/openstack/test_common.py @@ -0,0 +1,161 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +""" +Test suites for 'common' code used throughout the OpenStack HTTP API. +""" + +import unittest + +from webob import Request + +from nova.api.openstack.common import limited + + +class LimiterTest(unittest.TestCase): + """ + Unit tests for the `nova.api.openstack.common.limited` method which takes + in a list of items and, depending on the 'offset' and 'limit' GET params, + returns a subset or complete set of the given items. + """ + + def setUp(self): + """ + Run before each test. + """ + self.tiny = range(1) + self.small = range(10) + self.medium = range(1000) + self.large = range(10000) + + def test_limiter_offset_zero(self): + """ + Test offset key works with 0. + """ + req = Request.blank('/?offset=0') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_offset_medium(self): + """ + Test offset key works with a medium sized number. + """ + req = Request.blank('/?offset=10') + self.assertEqual(limited(self.tiny, req), []) + self.assertEqual(limited(self.small, req), self.small[10:]) + self.assertEqual(limited(self.medium, req), self.medium[10:]) + self.assertEqual(limited(self.large, req), self.large[10:1010]) + + def test_limiter_offset_over_max(self): + """ + Test offset key works with a number over 1000 (max_limit). + """ + req = Request.blank('/?offset=1001') + self.assertEqual(limited(self.tiny, req), []) + self.assertEqual(limited(self.small, req), []) + self.assertEqual(limited(self.medium, req), []) + self.assertEqual(limited(self.large, req), self.large[1001:2001]) + + def test_limiter_offset_blank(self): + """ + Test offset key works with a blank offset. + """ + req = Request.blank('/?offset=') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_offset_bad(self): + """ + Test offset key works with a BAD offset. + """ + req = Request.blank(u'/?offset=\u0020aa') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_nothing(self): + """ + Test request with no offset or limit + """ + req = Request.blank('/') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_zero(self): + """ + Test limit of zero. + """ + req = Request.blank('/?limit=0') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_medium(self): + """ + Test limit of 10. + """ + req = Request.blank('/?limit=10') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium[:10]) + self.assertEqual(limited(self.large, req), self.large[:10]) + + def test_limiter_limit_over_max(self): + """ + Test limit of 3000. + """ + req = Request.blank('/?limit=3000') + self.assertEqual(limited(self.tiny, req), self.tiny) + self.assertEqual(limited(self.small, req), self.small) + self.assertEqual(limited(self.medium, req), self.medium) + self.assertEqual(limited(self.large, req), self.large[:1000]) + + def test_limiter_limit_and_offset(self): + """ + Test request with both limit and offset. + """ + items = range(2000) + req = Request.blank('/?offset=1&limit=3') + self.assertEqual(limited(items, req), items[1:4]) + req = Request.blank('/?offset=3&limit=0') + self.assertEqual(limited(items, req), items[3:1003]) + req = Request.blank('/?offset=3&limit=1500') + self.assertEqual(limited(items, req), items[3:1003]) + req = Request.blank('/?offset=3000&limit=10') + self.assertEqual(limited(items, req), []) + + def test_limiter_custom_max_limit(self): + """ + Test a max_limit other than 1000. + """ + items = range(2000) + req = Request.blank('/?offset=1&limit=3') + self.assertEqual(limited(items, req, max_limit=2000), items[1:4]) + req = Request.blank('/?offset=3&limit=0') + self.assertEqual(limited(items, req, max_limit=2000), items[3:]) + req = Request.blank('/?offset=3&limit=2500') + self.assertEqual(limited(items, req, max_limit=2000), items[3:]) + req = Request.blank('/?offset=3000&limit=10') + self.assertEqual(limited(items, req, max_limit=2000), []) -- cgit From 52e1ad5321590b7b4671349373217bc8fce275fc Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 9 Feb 2011 15:55:29 -0500 Subject: - population of public and private addresses containers in openstack api - replacement of sqlalchemy model in instance stub with dict --- nova/tests/api/openstack/test_servers.py | 66 ++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 724f14f19..816a0ab8c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -17,6 +17,7 @@ import json import unittest +import datetime import stubout import webob @@ -39,6 +40,13 @@ def return_server(context, id): return stub_instance(id) +def return_server_with_addresses(private, public): + def _return_server(context, id): + return stub_instance(id, private_address=private, + public_addresses=public) + return _return_server + + def return_servers(context, user_id=1): return [stub_instance(i, user_id) for i in xrange(5)] @@ -55,9 +63,45 @@ def instance_address(context, instance_id): return None -def stub_instance(id, user_id=1): - return Instance(id=id, state=0, image_id=10, user_id=user_id, - display_name='server%s' % id) +def stub_instance(id, user_id=1, private_address=None, public_addresses=None): + if public_addresses == None: + public_addresses = list() + + instance = { + "id": id, + "admin_pass": "", + "user_id": user_id, + "project_id": "", + "image_id": 10, + "kernel_id": "", + "ramdisk_id": "", + "launch_index": 0, + "key_name": "", + "key_data": "", + "state": 0, + "state_description": "", + "memory_mb": 0, + "vcpus": 0, + "local_gb": 0, + "hostname": "", + "host": "", + "instance_type": "", + "user_data": "", + "reservation_id": "", + "mac_address": "", + "scheduled_at": datetime.datetime.now(), + "launched_at": datetime.datetime.now(), + "terminated_at": datetime.datetime.now(), + "availability_zone": "", + "display_name": "server%s" % id, + "display_description": "", + "locked": False} + + instance["fixed_ip"] = { + "address": private_address, + "floating_ips": [{"address":ip} for ip in public_addresses]} + + return instance def fake_compute_api(cls, req, id): @@ -105,6 +149,22 @@ class ServersTest(unittest.TestCase): self.assertEqual(res_dict['server']['id'], '1') self.assertEqual(res_dict['server']['name'], 'server1') + def test_get_server_by_id_with_addresses(self): + private = "192.168.0.3" + public = ["1.2.3.4"] + new_return_server = return_server_with_addresses(private, public) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + req = webob.Request.blank('/v1.0/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['name'], 'server1') + addresses = res_dict['server']['addresses'] + self.assertEqual(len(addresses["public"]), len(public)) + self.assertEqual(addresses["public"][0], public[0]) + self.assertEqual(len(addresses["private"]), 1) + self.assertEqual(addresses["private"][0], private) + def test_get_server_list(self): req = webob.Request.blank('/v1.0/servers') res = req.get_response(fakes.wsgi_app()) -- cgit From fd915e3db7f1006e67342b034eb8db0384c87d34 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Thu, 10 Feb 2011 11:21:53 -0800 Subject: testing refactor --- nova/tests/test_instance_types.py | 10 ++++------ nova/tests/test_nova_manage.py | 32 ++++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 819431763..283f0bce8 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -14,7 +14,7 @@ """ Unit Tests for instance types code """ -import datetime +import time from nova import context from nova import db @@ -37,12 +37,10 @@ class InstanceTypeTestCase(test.TestCase): super(InstanceTypeTestCase, self).setUp() session = get_session() max_flavorid = session.query(models.InstanceTypes).\ - order_by("flavorid desc").first() + order_by("flavorid desc").\ + first() self.flavorid = max_flavorid["flavorid"] + 1 - self.name = str(datetime.datetime.utcnow()) - - def tearDown(self): - pass + self.name = str(int(time.time())) def test_instance_type_create_then_delete(self): """Ensure instance types can be created""" diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index a2fa919a0..d2c24e8b0 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -15,16 +15,25 @@ Tests For Nova-Manage """ +import time import os import subprocess from nova import test +from nova.db.sqlalchemy.session import get_session +from nova.db.sqlalchemy import models class NovaManageTestCase(test.TestCase): """Test case for nova-manage""" def setUp(self): super(NovaManageTestCase, self).setUp() + session = get_session() + max_flavorid = session.query(models.InstanceTypes).\ + order_by("flavorid desc").first() + self.flavorid = str(max_flavorid["flavorid"] + 1) + # self.flavorid = str(self.flavorid) + self.name = str(int(time.time())) def teardown(self): fnull.close() @@ -32,11 +41,11 @@ class NovaManageTestCase(test.TestCase): def test_create_and_delete_instance_types(self): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type", - "create", "test", "256", "1", - "120", "99"], stdout=fnull) + "create", self.name, "256", "1", + "120", self.flavorid], stdout=fnull) self.assertEqual(0, retcode) retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "delete", "test"], stdout=fnull) + "delete", self.name], stdout=fnull) self.assertEqual(0, retcode) def test_list_instance_types_or_flavors(self): @@ -52,17 +61,20 @@ class NovaManageTestCase(test.TestCase): "m1.medium"], stdout=fnull) self.assertEqual(0, retcode) - def test_should_raise_on_bad_create_args(self): + def test_should_error_on_bad_create_args(self): fnull = open(os.devnull, 'w') + # shouldn't be able to create instance type with 0 vcpus retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", "test", "256", "0",\ - "120", "99"], stdout=fnull) - self.assertEqual(1, retcode) + "create", self.name, "256", "0",\ + "120", self.flavorid], stdout=fnull) + # self.assertEqual(1, retcode, + # ("bin/nova-manage instance_type create %s 256 0 120 %s"\ + # % (self.name, self.flavorid))) def test_should_fail_on_duplicate_flavorid(self): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", "test", "256", "1",\ + "create", self.name, "256", "1",\ "120", "1"], stdout=fnull) self.assertEqual(1, retcode) @@ -70,11 +82,11 @@ class NovaManageTestCase(test.TestCase): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "create", "fsfsfsdfsdf", "256", "1",\ - "120", "189"], stdout=fnull) + "120", self.flavorid], stdout=fnull) self.assertEqual(0, retcode) retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "create", "fsfsfsdfsdf", "256", "1",\ - "120", "190"], stdout=fnull) + "120", self.flavorid], stdout=fnull) self.assertEqual(1, retcode) def test_instance_type_delete_should_fail_without_valid_name(self): -- cgit From 8ac02818a514716fa4899d633831877a388239c0 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Thu, 10 Feb 2011 16:29:25 -0800 Subject: fixed destroy calls --- nova/tests/test_instance_types.py | 3 +-- nova/tests/test_nova_manage.py | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 283f0bce8..36c29d336 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -50,8 +50,7 @@ class InstanceTypeTestCase(test.TestCase): self.assertNotEqual(len(starting_inst_list), len(new), 'instance was not created') - rows = instance_types.destroy(self.name) - self.assertEqual(rows, 1) + instance_types.destroy(self.name) self.assertEqual(1, instance_types.get_instance_type(self.name)["deleted"]) self.assertEqual(starting_inst_list, instance_types.get_all_types()) diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index d2c24e8b0..c1ef8cae9 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -89,8 +89,8 @@ class NovaManageTestCase(test.TestCase): "120", self.flavorid], stdout=fnull) self.assertEqual(1, retcode) - def test_instance_type_delete_should_fail_without_valid_name(self): - fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "delete", "saefasff"], stdout=fnull) - self.assertEqual(1, retcode) + # def test_instance_type_delete_should_fail_without_valid_name(self): + # fnull = open(os.devnull, 'w') + # retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + # "delete", "saefasff"], stdout=fnull) + # self.assertEqual(1, retcode) -- cgit From c230dba962a3db2a3a8bb502dfb33313f0ef274b Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 11 Feb 2011 11:25:55 -0400 Subject: rough cut at zone api tests --- nova/tests/api/openstack/test_zones.py | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 nova/tests/api/openstack/test_zones.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py new file mode 100644 index 000000000..8a817bebe --- /dev/null +++ b/nova/tests/api/openstack/test_zones.py @@ -0,0 +1,74 @@ +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import unittest + +import stubout +import webob + +import nova.api +from nova.api.openstack import zones +from nova.tests.api.openstack import fakes + + +class ZonesTest(unittest.TestCase): + def setUp(self): + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + + def tearDown(self): + self.stubs.UnsetAll() + + def test_get_zone_list(self): + req = webob.Request.blank('/v1.0/zones') + res = req.get_response(fakes.wsgi_app()) + + def test_get_zone_by_id(self): + req = webob.Request.blank('/v1.0/zones/1') + res = req.get_response(fakes.wsgi_app()) + + def test_zone_delete(self): + req = webob.Request.blank('/v1.0/zones/1') + res = req.get_response(fakes.wsgi_app()) + + def test_zone_create(self): + body = dict(server=dict(api_url='http://blah.zoo', username='bob', + password='qwerty')) + req = webob.Request.blank('/v1.0/zones') + req.method = 'POST' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + + self.assertEqual(res.status_int, 200) + + def test_zone_update(self): + body = dict(server=dict(api_url='http://blah.zoo', username='zeb', + password='sneaky')) + req = webob.Request.blank('/v1.0/zones/1') + req.method = 'PUT' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + + self.assertEqual(res.status_int, 200) + + +if __name__ == '__main__': + unittest.main() -- cgit From df9bf23ecda1f32fd31ebffc6013e2f60f7fd3fa Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 11 Feb 2011 15:13:05 -0400 Subject: zone api tests passing --- nova/tests/api/openstack/test_zones.py | 81 +++++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 8a817bebe..8dbdffa41 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -17,12 +17,50 @@ import unittest import stubout import webob +import json -import nova.api +import nova.db +from nova import context +from nova import flags from nova.api.openstack import zones from nova.tests.api.openstack import fakes +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +def zone_get(context, zone_id): + return dict(id=1, api_url='http://foo.com', username='bob', + password='xxx') + + +def zone_create(context, values): + zone = dict(id=1) + zone.update(values) + return zone + + +def zone_update(context, zone_id, values): + zone = dict(id=zone_id, api_url='http://foo.com', username='bob', + password='xxx') + zone.update(values) + return zone + + +def zone_delete(context, zone_id): + pass + + +def zone_get_all(context): + return [ + dict(id=1, api_url='http://foo.com', username='bob', + password='xxx'), + dict(id=2, api_url='http://blah.com', username='alice', + password='qwerty') + ] + + class ZonesTest(unittest.TestCase): def setUp(self): self.stubs = stubout.StubOutForTesting() @@ -32,42 +70,75 @@ class ZonesTest(unittest.TestCase): fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) + self.allow_admin = FLAGS.allow_admin_api + FLAGS.allow_admin_api = True + + self.stubs.Set(nova.db, 'zone_get', zone_get) + self.stubs.Set(nova.db, 'zone_get_all', zone_get_all) + self.stubs.Set(nova.db, 'zone_update', zone_update) + self.stubs.Set(nova.db, 'zone_create', zone_create) + self.stubs.Set(nova.db, 'zone_delete', zone_delete) + def tearDown(self): self.stubs.UnsetAll() + FLAGS.allow_admin_api = self.allow_admin def test_get_zone_list(self): req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_by_id(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['username'], 'bob') + self.assertEqual(res_dict['zone']['password'], 'xxx') + + self.assertEqual(res.status_int, 200) def test_zone_delete(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + def test_zone_create(self): - body = dict(server=dict(api_url='http://blah.zoo', username='bob', - password='qwerty')) + body = dict(zone=dict(api_url='http://blah.zoo', username='fred', + password='fubar')) req = webob.Request.blank('/v1.0/zones') req.method = 'POST' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') + self.assertEqual(res_dict['zone']['username'], 'fred') + self.assertEqual(res_dict['zone']['password'], 'fubar') def test_zone_update(self): - body = dict(server=dict(api_url='http://blah.zoo', username='zeb', - password='sneaky')) + body = dict(zone=dict(username='zeb', password='sneaky')) req = webob.Request.blank('/v1.0/zones/1') req.method = 'PUT' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['zone']['id'], 1) + self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['username'], 'zeb') + self.assertEqual(res_dict['zone']['password'], 'sneaky') if __name__ == '__main__': -- cgit From 4a058908db774bfebce4ece814534225e123345c Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Fri, 11 Feb 2011 15:04:49 -0600 Subject: Added more columns to instance_types tables --- nova/tests/test_nova_manage.py | 48 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index c1ef8cae9..5a6e1287f 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -40,9 +40,19 @@ class NovaManageTestCase(test.TestCase): def test_create_and_delete_instance_types(self): fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type", - "create", self.name, "256", "1", - "120", self.flavorid], stdout=fnull) + retcode = subprocess.call([ + "bin/nova-manage", + "instance_type", + "create", + self.name, + "256", + "1", + "120", + self.flavorid, + "2", + "10", + "10"], + stdout=fnull) self.assertEqual(0, retcode) retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "delete", self.name], stdout=fnull) @@ -80,13 +90,33 @@ class NovaManageTestCase(test.TestCase): def test_should_fail_on_duplicate_name(self): fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", "fsfsfsdfsdf", "256", "1",\ - "120", self.flavorid], stdout=fnull) + retcode = subprocess.call([ + "bin/nova-manage", + "instance_type", + "create", + "fsfsfsdfsdf", + "256", + "1", + "120", + self.flavorid, + "2", + "10", + "10"], + stdout=fnull) self.assertEqual(0, retcode) - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", "fsfsfsdfsdf", "256", "1",\ - "120", self.flavorid], stdout=fnull) + retcode = subprocess.call([ + "bin/nova-manage", + "instance_type", + "create", + "fsfsfsdfsdf", + "256", + "1", + "120", + self.flavorid, + "2", + "10", + "10"], + stdout=fnull) self.assertEqual(1, retcode) # def test_instance_type_delete_should_fail_without_valid_name(self): -- cgit From 40ec6d45a25bf997ae62dbbf08494aa39f047e33 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Fri, 11 Feb 2011 13:53:54 -0800 Subject: updated tests and added more error checking --- nova/tests/test_instance_types.py | 17 +++++++++++++++++ nova/tests/test_nova_manage.py | 21 +++++++++------------ 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 36c29d336..68ca3b842 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -62,3 +62,20 @@ class InstanceTypeTestCase(test.TestCase): count() inst_types = instance_types.get_all_types() self.assertEqual(total_instance_types, len(inst_types)) + + def test_invalid_create_args_should_fail(self): + """Ensures that instance type creation fails with invalid args""" + self.assertRaises( + exception.InvalidInputException, + instance_types.create, self.name, 0, 1, 120, self.flavorid) + self.assertRaises( + exception.InvalidInputException, + instance_types.create, self.name, 256, -1, 120, self.flavorid) + self.assertRaises( + exception.InvalidInputException, + instance_types.create, self.name, 256, 1, "aa", self.flavorid) + + def test_non_existant_inst_type_shouldnt_delete(self): + """Ensures that instance type creation fails with invalid args""" + self.assertRaises(exception.ApiError, + instance_types.destroy, "sfsfsdfdfs") diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index c1ef8cae9..8ab23ba2b 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -32,7 +32,6 @@ class NovaManageTestCase(test.TestCase): max_flavorid = session.query(models.InstanceTypes).\ order_by("flavorid desc").first() self.flavorid = str(max_flavorid["flavorid"] + 1) - # self.flavorid = str(self.flavorid) self.name = str(int(time.time())) def teardown(self): @@ -42,7 +41,7 @@ class NovaManageTestCase(test.TestCase): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type", "create", self.name, "256", "1", - "120", self.flavorid], stdout=fnull) + "10", self.flavorid], stdout=fnull) self.assertEqual(0, retcode) retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "delete", self.name], stdout=fnull) @@ -67,16 +66,14 @@ class NovaManageTestCase(test.TestCase): retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "create", self.name, "256", "0",\ "120", self.flavorid], stdout=fnull) - # self.assertEqual(1, retcode, - # ("bin/nova-manage instance_type create %s 256 0 120 %s"\ - # % (self.name, self.flavorid))) + self.assertEqual(1, retcode) def test_should_fail_on_duplicate_flavorid(self): fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "create", self.name, "256", "1",\ "120", "1"], stdout=fnull) - self.assertEqual(1, retcode) + self.assertEqual(3, retcode) def test_should_fail_on_duplicate_name(self): fnull = open(os.devnull, 'w') @@ -87,10 +84,10 @@ class NovaManageTestCase(test.TestCase): retcode = subprocess.call(["bin/nova-manage", "instance_type",\ "create", "fsfsfsdfsdf", "256", "1",\ "120", self.flavorid], stdout=fnull) - self.assertEqual(1, retcode) + self.assertEqual(3, retcode) - # def test_instance_type_delete_should_fail_without_valid_name(self): - # fnull = open(os.devnull, 'w') - # retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - # "delete", "saefasff"], stdout=fnull) - # self.assertEqual(1, retcode) + def test_instance_type_delete_should_fail_without_valid_name(self): + fnull = open(os.devnull, 'w') + retcode = subprocess.call(["bin/nova-manage", "instance_type",\ + "delete", "doesntexist"], stdout=fnull) + self.assertEqual(1, retcode) -- cgit From b03d6f523a0dda7c942c298ac75bc46331085056 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Fri, 11 Feb 2011 14:06:33 -0800 Subject: added instance_type_purge() to actually remove records from db --- nova/tests/test_instance_types.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 68ca3b842..0d54cc283 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -54,6 +54,7 @@ class InstanceTypeTestCase(test.TestCase): self.assertEqual(1, instance_types.get_instance_type(self.name)["deleted"]) self.assertEqual(starting_inst_list, instance_types.get_all_types()) + db.instance_type_purge(context.get_admin_context(), self.name) def test_get_all_instance_types(self): """Ensures that all instance types can be retrieved""" -- cgit From c15289a63c90218a573d5e75833985ec2ad8691e Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 14 Feb 2011 23:02:26 -0400 Subject: better filtering --- nova/tests/api/openstack/test_zones.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 8dbdffa41..5542a1cf3 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -98,9 +98,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') - self.assertEqual(res_dict['zone']['username'], 'bob') - self.assertEqual(res_dict['zone']['password'], 'xxx') - + self.assertFalse('password' in res_dict['zone']) self.assertEqual(res.status_int, 200) def test_zone_delete(self): @@ -122,8 +120,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') - self.assertEqual(res_dict['zone']['username'], 'fred') - self.assertEqual(res_dict['zone']['password'], 'fubar') + self.assertFalse('username' in res_dict['zone']) def test_zone_update(self): body = dict(zone=dict(username='zeb', password='sneaky')) @@ -137,8 +134,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') - self.assertEqual(res_dict['zone']['username'], 'zeb') - self.assertEqual(res_dict['zone']['password'], 'sneaky') + self.assertFalse('username' in res_dict['zone']) if __name__ == '__main__': -- cgit From 21a3d77fee681d05c465c74e40177ae022bc24af Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 22:41:27 +0000 Subject: Fixing test by adding stub for get_image_meta --- nova/tests/glance/stubs.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index f182b857a..4cd5c357f 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -29,9 +29,10 @@ class FakeGlance(object): def __init__(self, host, port=None, use_ssl=False): pass - def get_image(self, image): - meta = { - 'size': 0, - } + def get_image_meta(self, image_id): + return {'size': 0, 'properties': {}} + + def get_image(self, image_id): + meta = self.get_image_meta(image_id) image_file = StringIO.StringIO('') return meta, image_file -- cgit From 1b9413e11ba1b4b49b50965e3f812e636f2319d5 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Tue, 15 Feb 2011 18:20:44 -0600 Subject: stubbed out reset networkin xenapi VM tests to solve domid problem --- nova/tests/test_xenapi.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index d5660c5d1..6b8efc9d8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -32,6 +32,7 @@ from nova.virt import xenapi_conn from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import volume_utils from nova.virt.xenapi.vmops import SimpleDH +from nova.virt.xenapi.vmops import VMOps from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs from nova.tests.glance import stubs as glance_stubs @@ -141,6 +142,10 @@ class XenAPIVolumeTestCase(test.TestCase): self.stubs.UnsetAll() +def reset_network(*args): + pass + + class XenAPIVMTestCase(test.TestCase): """ Unit tests for VM operations @@ -162,6 +167,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_stream_disk(self.stubs) + self.stubs.Set(VMOps, 'reset_network', reset_network) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) self.conn = xenapi_conn.get_connection(False) -- cgit From 163e81ac2bc2f9945273b0659ceb473767e5b19f Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 16 Feb 2011 11:53:50 -0500 Subject: This implements the blueprint 'Openstack API support for hostId': https://blueprints.launchpad.net/nova/+spec/openstack-api-hostid Now instances will have a unique hostId which for now is just a hash of the host. If the instance does not have a host yet, the hostId will be ''. --- nova/tests/api/openstack/test_servers.py | 41 +++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 724f14f19..e615141ff 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -43,6 +43,10 @@ def return_servers(context, user_id=1): return [stub_instance(i, user_id) for i in xrange(5)] +def return_servers_with_host(context, user_id=1): + return [stub_instance(i, user_id, 1) for i in xrange(5)] + + def return_security_group(context, instance_id, security_group_id): pass @@ -55,9 +59,13 @@ def instance_address(context, instance_id): return None -def stub_instance(id, user_id=1): - return Instance(id=id, state=0, image_id=10, user_id=user_id, - display_name='server%s' % id) +def stub_instance(id, user_id=1, with_hosts=False): + if with_hosts: + return Instance(id=id, state=0, image_id=10, user_id=user_id, + display_name='server%s' % id, host='host%s' % (id % 2)) + else: + return Instance(id=id, state=0, image_id=10, user_id=user_id, + display_name='server%s' % id) def fake_compute_api(cls, req, id): @@ -229,6 +237,33 @@ class ServersTest(unittest.TestCase): i = 0 for s in res_dict['servers']: self.assertEqual(s['id'], i) + self.assertEqual(s['hostId'], '') + self.assertEqual(s['name'], 'server%d' % i) + self.assertEqual(s['imageId'], 10) + i += 1 + + def test_get_all_server_details_with_host(self): + ''' + We want to make sure that if two instances are on the same host, then + they return the same hostId. If two instances are on different hosts, + they should return different hostId's. In this test, we get 5 instances + back where 2 are on one host and 3 are on another. + ''' + self.stubs.Set(nova.db.api, 'instance_get_all_by_user', + return_servers_with_host) + req = webob.Request.blank('/v1.0/servers/detail') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + server_list = res_dict['servers'] + host_ids = [server_list[0]['hostId'], server_list[1]['hostId']] + self.assertTrue(host_ids[0]) + self.assertTrue(host_ids[1]) + self.assertTrue(host_ids[0] != host_ids[1]) + i = 0 + for s in res_dict['servers']: + self.assertEqual(s['id'], i) + self.assertEqual(s['hostId'], host_ids[i % 2]) self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageId'], 10) i += 1 -- cgit From 4375069b6635d6ccd87231cb7d9f5b17708ffb1a Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Wed, 16 Feb 2011 11:11:49 -0600 Subject: Stubbed out flavor create/delete API calls --- nova/tests/api/openstack/test_flavors.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 532b34e1b..7bfc46e0b 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -43,7 +43,17 @@ class FlavorsTest(unittest.TestCase): def test_get_flavor_list(self): req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + def test_create_flavor(self): + req = webob.Request.blank("/v1.0/flavors/create/test") + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + + def test_delete_flavor(self): + req = webob.Request.blank("/v1.0/flavors/delete/test") + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) if __name__ == '__main__': unittest.main() -- cgit From c6b8f129ae57da2ea0cd844150e58d4fac7eb71d Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Wed, 16 Feb 2011 14:12:54 -0600 Subject: added test for reset_network to openstack api tests, tabstop 5 to 4, renamed migration --- nova/tests/api/openstack/test_servers.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 724f14f19..89e192eed 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -281,6 +281,18 @@ class ServersTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) + def test_server_reset_network(self): + FLAGS.allow_admin_api = True + body = dict(server=dict( + name='server_test', imageId=2, flavorId=2, metadata={}, + personality={})) + req = webob.Request.blank('/v1.0/servers/1/reset_network') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + def test_server_diagnostics(self): req = webob.Request.blank("/v1.0/servers/1/diagnostics") req.method = "GET" -- cgit From 49a7e430ca30768a68a111223068652c781206fe Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 16 Feb 2011 13:17:42 -0800 Subject: zone manager tests --- nova/tests/test_zones.py | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 nova/tests/test_zones.py (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py new file mode 100644 index 000000000..b4c8815d5 --- /dev/null +++ b/nova/tests/test_zones.py @@ -0,0 +1,132 @@ +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Tests For ZoneManager +""" + +import datetime +import mox + +from nova import context +from nova import db +from nova import flags +from nova import service +from nova import test +from nova import rpc +from nova import utils +from nova.auth import manager as auth_manager +from nova.scheduler import zone_manager + + +class FakeZone: + """Represents a fake zone from the db""" + def __init__(self, *args, **kwargs): + for k, v in kwargs.iteritems(): + setattr(self, k, v) + + +class ZoneManagerTestCase(test.TestCase): + """Test case for zone manager""" + def test_ping(self): + zm = zone_manager.ZoneManager() + self.mox.StubOutWithMock(zm, '_refresh_from_db') + self.mox.StubOutWithMock(zm, '_poll_zones') + zm._refresh_from_db(mox.IgnoreArg()) + zm._poll_zones(mox.IgnoreArg()) + + self.mox.ReplayAll() + zm.ping(None) + self.mox.VerifyAll() + + def test_refresh_from_db_new(self): + zm = zone_manager.ZoneManager() + + self.mox.StubOutWithMock(db, 'zone_get_all') + db.zone_get_all(mox.IgnoreArg()).AndReturn([ + FakeZone(id=1, api_url='http://foo.com', username='user1', + password='pass1'), + ]) + + self.assertEquals(len(zm.zone_states), 0) + + self.mox.ReplayAll() + zm._refresh_from_db(None) + self.mox.VerifyAll() + + self.assertEquals(len(zm.zone_states), 1) + self.assertEquals(zm.zone_states[1].username, 'user1') + + def test_refresh_from_db_replace_existing(self): + zm = zone_manager.ZoneManager() + zone_state = zone_manager.ZoneState() + zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com', + username='user1', password='pass1')) + zm.zone_states[1] = zone_state + + self.mox.StubOutWithMock(db, 'zone_get_all') + db.zone_get_all(mox.IgnoreArg()).AndReturn([ + FakeZone(id=1, api_url='http://foo.com', username='user2', + password='pass2'), + ]) + + self.assertEquals(len(zm.zone_states), 1) + + self.mox.ReplayAll() + zm._refresh_from_db(None) + self.mox.VerifyAll() + + self.assertEquals(len(zm.zone_states), 1) + self.assertEquals(zm.zone_states[1].username, 'user2') + + def test_refresh_from_db_missing(self): + zm = zone_manager.ZoneManager() + zone_state = zone_manager.ZoneState() + zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com', + username='user1', password='pass1')) + zm.zone_states[1] = zone_state + + self.mox.StubOutWithMock(db, 'zone_get_all') + db.zone_get_all(mox.IgnoreArg()).AndReturn([ ]) + + self.assertEquals(len(zm.zone_states), 1) + + self.mox.ReplayAll() + zm._refresh_from_db(None) + self.mox.VerifyAll() + + self.assertEquals(len(zm.zone_states), 0) + + def test_refresh_from_db_add_and_delete(self): + zm = zone_manager.ZoneManager() + zone_state = zone_manager.ZoneState() + zone_state.update_credentials(FakeZone(id=1, api_url='http://foo.com', + username='user1', password='pass1')) + zm.zone_states[1] = zone_state + + self.mox.StubOutWithMock(db, 'zone_get_all') + + db.zone_get_all(mox.IgnoreArg()).AndReturn([ + FakeZone(id=2, api_url='http://foo.com', username='user2', + password='pass2'), + ]) + self.assertEquals(len(zm.zone_states), 1) + + self.mox.ReplayAll() + zm._refresh_from_db(None) + self.mox.VerifyAll() + + self.assertEquals(len(zm.zone_states), 1) + self.assertEquals(zm.zone_states[2].username, 'user2') -- cgit From a5ec2be709d28267075ddc9616c5c29b62622af5 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 16 Feb 2011 23:07:43 +0000 Subject: Adding basic test --- nova/tests/glance/stubs.py | 22 ++++++++++++++++++---- nova/tests/test_xenapi.py | 4 ++++ nova/tests/xenapi/stubs.py | 6 ++++++ 3 files changed, 28 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index 4cd5c357f..fc120e523 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -26,13 +26,27 @@ def stubout_glance_client(stubs, cls): class FakeGlance(object): + IMAGE_FIXTURES = { + 1: {'image_meta': {'name': 'fakemachine', 'size': 0, + 'properties': {}}, + 'image_data': StringIO.StringIO('') }, + 2: {'image_meta': {'name': 'fakekernel', 'size': 0, + 'properties': {}}, + 'image_data': StringIO.StringIO('') }, + 3: {'image_meta': {'name': 'fakekernel', 'size': 0, + 'properties': {}}, + 'image_data': StringIO.StringIO('') }, + 4: {'image_meta': {'name': 'fakekernel', 'size': 0, + 'properties': {'disk_format': 'vhd'}}, + 'image_data': StringIO.StringIO('') }, + } + def __init__(self, host, port=None, use_ssl=False): pass def get_image_meta(self, image_id): - return {'size': 0, 'properties': {}} + return self.IMAGE_FIXTURES[image_id]['image_meta'] def get_image(self, image_id): - meta = self.get_image_meta(image_id) - image_file = StringIO.StringIO('') - return meta, image_file + image = self.IMAGE_FIXTURES[image_id] + return image['image_meta'], image['image_data'] diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index d5660c5d1..75387e7f5 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -279,6 +279,10 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_image_service = 'glance' self._test_spawn(1, None, None) + def test_spawn_vhd_glance(self): + FLAGS.xenapi_image_service = 'glance' + self._test_spawn(4, None, None) + def test_spawn_glance(self): FLAGS.xenapi_image_service = 'glance' self._test_spawn(1, 2, 3) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 624995ada..2e3b62a77 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -171,6 +171,12 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_destroy(self, session_ref, vm_ref): fake.destroy_vm(vm_ref) + def SR_scan(self, session_ref, sr_ref): + pass + + def VDI_set_name_label(self, session_ref, vdi_ref, name_label): + pass + class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ -- cgit From c56b1814cfae7a9c814b2d37388aff5e772771b6 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 16 Feb 2011 23:39:12 +0000 Subject: Pep8 fixes --- nova/tests/glance/stubs.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index fc120e523..c58357962 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -29,16 +29,16 @@ class FakeGlance(object): IMAGE_FIXTURES = { 1: {'image_meta': {'name': 'fakemachine', 'size': 0, 'properties': {}}, - 'image_data': StringIO.StringIO('') }, + 'image_data': StringIO.StringIO('')}, 2: {'image_meta': {'name': 'fakekernel', 'size': 0, 'properties': {}}, - 'image_data': StringIO.StringIO('') }, + 'image_data': StringIO.StringIO('')}, 3: {'image_meta': {'name': 'fakekernel', 'size': 0, 'properties': {}}, - 'image_data': StringIO.StringIO('') }, + 'image_data': StringIO.StringIO('')}, 4: {'image_meta': {'name': 'fakekernel', 'size': 0, 'properties': {'disk_format': 'vhd'}}, - 'image_data': StringIO.StringIO('') }, + 'image_data': StringIO.StringIO('')}, } def __init__(self, host, port=None, use_ssl=False): -- cgit From ce847afcc1e24463d7aa522f227a08193c72fcc0 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 16 Feb 2011 19:12:44 -0500 Subject: Moved definition of return_servers_with_host stub to inside the test_get_all_server_details_with_host test. --- nova/tests/api/openstack/test_servers.py | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index e615141ff..6c91b3f5b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -43,10 +43,6 @@ def return_servers(context, user_id=1): return [stub_instance(i, user_id) for i in xrange(5)] -def return_servers_with_host(context, user_id=1): - return [stub_instance(i, user_id, 1) for i in xrange(5)] - - def return_security_group(context, instance_id, security_group_id): pass @@ -60,12 +56,8 @@ def instance_address(context, instance_id): def stub_instance(id, user_id=1, with_hosts=False): - if with_hosts: - return Instance(id=id, state=0, image_id=10, user_id=user_id, - display_name='server%s' % id, host='host%s' % (id % 2)) - else: - return Instance(id=id, state=0, image_id=10, user_id=user_id, - display_name='server%s' % id) + return Instance(id=id, state=0, image_id=10, user_id=user_id, + display_name='server%s' % id) def fake_compute_api(cls, req, id): @@ -246,20 +238,27 @@ class ServersTest(unittest.TestCase): ''' We want to make sure that if two instances are on the same host, then they return the same hostId. If two instances are on different hosts, - they should return different hostId's. In this test, we get 5 instances - back where 2 are on one host and 3 are on another. + they should return different hostId's. In this test, there are 5 + instances - 2 on one host and 3 on another. ''' + + def return_servers_with_host(context, user_id=1): + return [ + Instance(id=i, state=0, image_id=10, user_id=user_id, + display_name='server%s' % i, host='host%s' % (i % 2)) + for i in xrange(5)] self.stubs.Set(nova.db.api, 'instance_get_all_by_user', - return_servers_with_host) + return_servers_with_host) + req = webob.Request.blank('/v1.0/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) server_list = res_dict['servers'] host_ids = [server_list[0]['hostId'], server_list[1]['hostId']] - self.assertTrue(host_ids[0]) - self.assertTrue(host_ids[1]) + self.assertTrue(host_ids[0] and host_ids[1]) self.assertTrue(host_ids[0] != host_ids[1]) + i = 0 for s in res_dict['servers']: self.assertEqual(s['id'], i) -- cgit From 56ad2a63f1dcf4a900fa4464671015dbaac05fdc Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Wed, 16 Feb 2011 19:37:28 -0500 Subject: Minor change. Adding a helper function stub_instance() inside the test test_get_all_server_details_with_host for readability. --- nova/tests/api/openstack/test_servers.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6c91b3f5b..630e1e5eb 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -55,7 +55,7 @@ def instance_address(context, instance_id): return None -def stub_instance(id, user_id=1, with_hosts=False): +def stub_instance(id, user_id=1): return Instance(id=id, state=0, image_id=10, user_id=user_id, display_name='server%s' % id) @@ -242,11 +242,13 @@ class ServersTest(unittest.TestCase): instances - 2 on one host and 3 on another. ''' + def stub_instance(id, user_id=1): + return Instance(id=id, state=0, image_id=10, user_id=user_id, + display_name='server%s' % id, host='host%s' % (id % 2)) + def return_servers_with_host(context, user_id=1): - return [ - Instance(id=i, state=0, image_id=10, user_id=user_id, - display_name='server%s' % i, host='host%s' % (i % 2)) - for i in xrange(5)] + return [stub_instance(i) for i in xrange(5)] + self.stubs.Set(nova.db.api, 'instance_get_all_by_user', return_servers_with_host) -- cgit From 04e29f6dc4b13b6fd0cbe5013cf241a727eb56ac Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 17 Feb 2011 01:24:31 +0000 Subject: Use glance image type to determine disk type --- nova/tests/glance/stubs.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index c58357962..1a5fb7ffb 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -28,16 +28,16 @@ def stubout_glance_client(stubs, cls): class FakeGlance(object): IMAGE_FIXTURES = { 1: {'image_meta': {'name': 'fakemachine', 'size': 0, - 'properties': {}}, + 'type': 'machine'}, 'image_data': StringIO.StringIO('')}, 2: {'image_meta': {'name': 'fakekernel', 'size': 0, - 'properties': {}}, + 'type': 'kernel'}, 'image_data': StringIO.StringIO('')}, - 3: {'image_meta': {'name': 'fakekernel', 'size': 0, - 'properties': {}}, + 3: {'image_meta': {'name': 'fakeramdisk', 'size': 0, + 'type': 'ramdisk'}, 'image_data': StringIO.StringIO('')}, - 4: {'image_meta': {'name': 'fakekernel', 'size': 0, - 'properties': {'disk_format': 'vhd'}}, + 4: {'image_meta': {'name': 'fakevhd', 'size': 0, + 'type': 'vhd'}, 'image_data': StringIO.StringIO('')}, } -- cgit From 719dbda7f8b856af334744de4807036e6ee704c1 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 16 Feb 2011 18:30:56 -0800 Subject: polling tests --- nova/tests/test_zones.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index b4c8815d5..2cb070aca 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -19,6 +19,7 @@ Tests For ZoneManager import datetime import mox +import novatools from nova import context from nova import db @@ -30,6 +31,8 @@ from nova import utils from nova.auth import manager as auth_manager from nova.scheduler import zone_manager +FLAGS = flags.FLAGS + class FakeZone: """Represents a fake zone from the db""" @@ -38,6 +41,11 @@ class FakeZone: setattr(self, k, v) +def exploding_novatools(zone): + """Used when we want to simulate a novatools call failing.""" + raise Exception("kaboom") + + class ZoneManagerTestCase(test.TestCase): """Test case for zone manager""" def test_ping(self): @@ -130,3 +138,36 @@ class ZoneManagerTestCase(test.TestCase): self.assertEquals(len(zm.zone_states), 1) self.assertEquals(zm.zone_states[2].username, 'user2') + + def test_poll_zone(self): + self.mox.StubOutWithMock(zone_manager, '_call_novatools') + zone_manager._call_novatools(mox.IgnoreArg()).AndReturn( + dict(name='zohan', capabilities='hairdresser')) + + zone_state = zone_manager.ZoneState() + zone_state.update_credentials(FakeZone(id=2, + api_url='http://foo.com', username='user2', + password='pass2')) + zone_state.attempt = 1 + + self.mox.ReplayAll() + zone_manager._poll_zone(zone_state) + self.mox.VerifyAll() + self.assertEquals(zone_state.attempt, 0) + self.assertEquals(zone_state.name, 'zohan') + + def test_poll_zone_fails(self): + self.stubs.Set(zone_manager, "_call_novatools", exploding_novatools) + + zone_state = zone_manager.ZoneState() + zone_state.update_credentials(FakeZone(id=2, + api_url='http://foo.com', username='user2', + password='pass2')) + zone_state.attempt = FLAGS.zone_failures_to_offline - 1 + + self.mox.ReplayAll() + zone_manager._poll_zone(zone_state) + self.mox.VerifyAll() + self.assertEquals(zone_state.attempt, 3) + self.assertFalse(zone_state.is_active) + self.assertEquals(zone_state.name, None) -- cgit From 923a4938b73b84aa8a31f08a7c7b983cc82959fe Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 17 Feb 2011 07:29:50 +0000 Subject: Adding tests --- nova/tests/glance/stubs.py | 25 +++++++++++++---- nova/tests/test_xenapi.py | 70 ++++++++++++++++++++++++++++++++++++++++++++-- nova/tests/xenapi/stubs.py | 10 +++++++ 3 files changed, 96 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index 1a5fb7ffb..3ff8d7ce5 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -26,20 +26,33 @@ def stubout_glance_client(stubs, cls): class FakeGlance(object): + IMAGE_MACHINE = 1 + IMAGE_KERNEL = 2 + IMAGE_RAMDISK = 3 + IMAGE_RAW = 4 + IMAGE_VHD = 5 + IMAGE_FIXTURES = { - 1: {'image_meta': {'name': 'fakemachine', 'size': 0, + IMAGE_MACHINE: { + 'image_meta': {'name': 'fakemachine', 'size': 0, 'type': 'machine'}, 'image_data': StringIO.StringIO('')}, - 2: {'image_meta': {'name': 'fakekernel', 'size': 0, + IMAGE_KERNEL: { + 'image_meta': {'name': 'fakekernel', 'size': 0, 'type': 'kernel'}, 'image_data': StringIO.StringIO('')}, - 3: {'image_meta': {'name': 'fakeramdisk', 'size': 0, + IMAGE_RAMDISK: { + 'image_meta': {'name': 'fakeramdisk', 'size': 0, 'type': 'ramdisk'}, 'image_data': StringIO.StringIO('')}, - 4: {'image_meta': {'name': 'fakevhd', 'size': 0, - 'type': 'vhd'}, + IMAGE_RAW: { + 'image_meta': {'name': 'fakeraw', 'size': 0, + 'type': 'raw'}, 'image_data': StringIO.StringIO('')}, - } + IMAGE_VHD: { + 'image_meta': {'name': 'fakevhd', 'size': 0, + 'type': 'vhd'}, + 'image_data': StringIO.StringIO('')}} def __init__(self, host, port=None, use_ssl=False): pass diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 75387e7f5..f8a3d72c4 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -31,6 +31,7 @@ from nova.compute import power_state from nova.virt import xenapi_conn from nova.virt.xenapi import fake as xenapi_fake from nova.virt.xenapi import volume_utils +from nova.virt.xenapi import vm_utils from nova.virt.xenapi.vmops import SimpleDH from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs @@ -162,6 +163,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_stream_disk(self.stubs) + stubs.stubout_lookup_image(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) self.conn = xenapi_conn.get_connection(False) @@ -277,15 +279,17 @@ class XenAPIVMTestCase(test.TestCase): def test_spawn_raw_glance(self): FLAGS.xenapi_image_service = 'glance' - self._test_spawn(1, None, None) + self._test_spawn(glance_stubs.FakeGlance.IMAGE_RAW, None, None) def test_spawn_vhd_glance(self): FLAGS.xenapi_image_service = 'glance' - self._test_spawn(4, None, None) + self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None) def test_spawn_glance(self): FLAGS.xenapi_image_service = 'glance' - self._test_spawn(1, 2, 3) + self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, + glance_stubs.FakeGlance.IMAGE_KERNEL, + glance_stubs.FakeGlance.IMAGE_RAMDISK) def tearDown(self): super(XenAPIVMTestCase, self).tearDown() @@ -334,3 +338,63 @@ class XenAPIDiffieHellmanTestCase(test.TestCase): def tearDown(self): super(XenAPIDiffieHellmanTestCase, self).tearDown() + + +class XenAPIDetermineDiskImageTestCase(test.TestCase): + """ + Unit tests for code that detects the ImageType + """ + def setUp(self): + super(XenAPIDetermineDiskImageTestCase, self).setUp() + glance_stubs.stubout_glance_client(self.stubs, + glance_stubs.FakeGlance) + + class FakeInstance(object): + pass + + self.fake_instance = FakeInstance() + self.fake_instance.id = 42 + + def assert_disk_type(self, disk_type): + dt = vm_utils.VMHelper.determine_disk_image_type( + self.fake_instance) + self.assertEqual(disk_type, dt) + + def test_instance_disk(self): + """ + If a kernel is specified then the image type is DISK (aka machine) + """ + FLAGS.xenapi_image_service = 'objectstore' + self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_MACHINE + self.fake_instance.kernel_id = glance_stubs.FakeGlance.IMAGE_KERNEL + self.assert_disk_type(vm_utils.ImageType.DISK) + + def test_instance_disk_raw(self): + """ + If the kernel isn't specified, and we're not using Glance, then + DISK_RAW is assumed. + """ + FLAGS.xenapi_image_service = 'objectstore' + self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_RAW + self.fake_instance.kernel_id = None + self.assert_disk_type(vm_utils.ImageType.DISK_RAW) + + def test_glance_disk_raw(self): + """ + If we're using Glance, then defer to the image_type field, which in + this case will be 'raw'. + """ + FLAGS.xenapi_image_service = 'glance' + self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_RAW + self.fake_instance.kernel_id = None + self.assert_disk_type(vm_utils.ImageType.DISK_RAW) + + def test_glance_disk_vhd(self): + """ + If we're using Glance, then defer to the image_type field, which in + this case will be 'vhd'. + """ + FLAGS.xenapi_image_service = 'glance' + self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_VHD + self.fake_instance.kernel_id = None + self.assert_disk_type(vm_utils.ImageType.DISK_VHD) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 2e3b62a77..1e6758a33 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -130,6 +130,16 @@ def stubout_stream_disk(stubs): stubs.Set(vm_utils, '_stream_disk', f) +def stubout_lookup_image(stubs): + @classmethod + def fake_lookup_image(cls, session, instance_id, vdi_ref): + # NOTE(sirp): pretending each image is paravirtualized for now + is_pv = True + return is_pv + + stubs.Set(vm_utils.VMHelper, 'lookup_image', fake_lookup_image) + + class FakeSessionForVMTests(fake.SessionBase): """ Stubs out a XenAPISession for VM tests """ def __init__(self, uri): -- cgit From e28ce7f82d1c89ab0c4e5ebfa98c12f502a33138 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 17 Feb 2011 09:48:16 -0500 Subject: removing superfluous pass statements; replacing list comprehension with for loop; alphabetizing imports --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 816a0ab8c..ace3b6850 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -15,9 +15,9 @@ # License for the specific language governing permissions and limitations # under the License. +import datetime import json import unittest -import datetime import stubout import webob -- cgit From 9d056b6fadcefed9ef9573bd89125b00af5e2726 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 17 Feb 2011 10:50:49 -0600 Subject: More testing --- nova/tests/api/openstack/test_flavors.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 7bfc46e0b..209ace0f8 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -46,12 +46,14 @@ class FlavorsTest(unittest.TestCase): self.assertEqual(res.status_int, 200) def test_create_flavor(self): - req = webob.Request.blank("/v1.0/flavors/create/test") + req = webob.Request.blank("/v1.0/flavors") + req.method = "POST" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) def test_delete_flavor(self): - req = webob.Request.blank("/v1.0/flavors/delete/test") + req = webob.Request.blank("/v1.0/flavors/1") + req.method = "DELETE" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) -- cgit From e77f8751dd59e5d650d047a6711c3d137947dda7 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Feb 2011 16:18:03 -0400 Subject: fixup --- nova/tests/test_zones.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 2cb070aca..7036ebe58 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -67,7 +67,7 @@ class ZoneManagerTestCase(test.TestCase): FakeZone(id=1, api_url='http://foo.com', username='user1', password='pass1'), ]) - + self.assertEquals(len(zm.zone_states), 0) self.mox.ReplayAll() @@ -89,7 +89,7 @@ class ZoneManagerTestCase(test.TestCase): FakeZone(id=1, api_url='http://foo.com', username='user2', password='pass2'), ]) - + self.assertEquals(len(zm.zone_states), 1) self.mox.ReplayAll() @@ -107,8 +107,8 @@ class ZoneManagerTestCase(test.TestCase): zm.zone_states[1] = zone_state self.mox.StubOutWithMock(db, 'zone_get_all') - db.zone_get_all(mox.IgnoreArg()).AndReturn([ ]) - + db.zone_get_all(mox.IgnoreArg()).AndReturn([]) + self.assertEquals(len(zm.zone_states), 1) self.mox.ReplayAll() @@ -125,7 +125,7 @@ class ZoneManagerTestCase(test.TestCase): zm.zone_states[1] = zone_state self.mox.StubOutWithMock(db, 'zone_get_all') - + db.zone_get_all(mox.IgnoreArg()).AndReturn([ FakeZone(id=2, api_url='http://foo.com', username='user2', password='pass2'), -- cgit From b48201be9a5fa08ce21ef241052071800e5777ca Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Feb 2011 12:43:22 -0800 Subject: fixed zone list tests --- nova/tests/api/openstack/test_zones.py | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 5542a1cf3..6c06fa8b8 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -52,7 +52,20 @@ def zone_delete(context, zone_id): pass -def zone_get_all(context): +def zone_get_all_scheduler(x, y, z): + return [ + dict(id=1, api_url='http://foo.com', username='bob', + password='xxx'), + dict(id=2, api_url='http://blah.com', username='alice', + password='qwerty') + ] + + +def zone_get_all_scheduler_empty(x, y, z): + return [] + + +def zone_get_all_db(context): return [ dict(id=1, api_url='http://foo.com', username='bob', password='xxx'), @@ -74,7 +87,6 @@ class ZonesTest(unittest.TestCase): FLAGS.allow_admin_api = True self.stubs.Set(nova.db, 'zone_get', zone_get) - self.stubs.Set(nova.db, 'zone_get_all', zone_get_all) self.stubs.Set(nova.db, 'zone_update', zone_update) self.stubs.Set(nova.db, 'zone_create', zone_create) self.stubs.Set(nova.db, 'zone_delete', zone_delete) @@ -83,7 +95,9 @@ class ZonesTest(unittest.TestCase): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin - def test_get_zone_list(self): + def test_get_zone_list_scheduler(self): + self.stubs.Set(zones.Controller, '_call_scheduler', + zone_get_all_scheduler) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -91,6 +105,18 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(len(res_dict['zones']), 2) + def test_get_zone_list_db(self): + self.stubs.Set(zones.Controller, '_call_scheduler', + zone_get_all_scheduler_empty) + self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db) + req = webob.Request.blank('/v1.0/zones') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res_dict['zones']), 2) + + def test_get_zone_by_id(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) -- cgit From 46269872192b843c80d72206a05c8b759c9f66a8 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Feb 2011 17:32:25 -0400 Subject: merge from dev --- nova/tests/api/openstack/test_zones.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 6c06fa8b8..65cc1c023 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -62,7 +62,7 @@ def zone_get_all_scheduler(x, y, z): def zone_get_all_scheduler_empty(x, y, z): - return [] + return [] def zone_get_all_db(context): @@ -106,7 +106,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_list_db(self): - self.stubs.Set(zones.Controller, '_call_scheduler', + self.stubs.Set(zones.Controller, '_call_scheduler', zone_get_all_scheduler_empty) self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db) req = webob.Request.blank('/v1.0/zones') @@ -116,7 +116,6 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(len(res_dict['zones']), 2) - def test_get_zone_by_id(self): req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) -- cgit From e5d979596ff8c588c7bbe82b7f1cb90de8af041a Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Feb 2011 18:49:30 -0400 Subject: missing docstring and fixed copyrights --- nova/tests/test_zones.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 7036ebe58..c273230a9 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -1,5 +1,4 @@ # Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may -- cgit From 3f3dddee0245cb143004dfb8c20204c511bec658 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Feb 2011 16:52:31 -0600 Subject: a few changes and a bunch of unit tests --- nova/tests/api/openstack/common.py | 30 ++++++++++ nova/tests/api/openstack/test_servers.py | 98 +++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 nova/tests/api/openstack/common.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/common.py b/nova/tests/api/openstack/common.py new file mode 100644 index 000000000..b55d3087b --- /dev/null +++ b/nova/tests/api/openstack/common.py @@ -0,0 +1,30 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json + +import webob + +def webob_factory(url): + base_url = url + def web_request(url, method, body=None): + req = webob.Request.blank("%s%s" % (base_url, url)) + req.method = method + req.body = json.dumps(body) + return req + return web_request + diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a7be0796e..878b62f85 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010-2011 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -29,6 +29,7 @@ from nova.api.openstack import servers import nova.db.api from nova.db.sqlalchemy.models import Instance import nova.rpc +from nova.tests.api.openstack import common from nova.tests.api.openstack import fakes @@ -138,6 +139,8 @@ class ServersTest(unittest.TestCase): self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) self.allow_admin = FLAGS.allow_admin_api + self.webreq = common.webob_factor('/v1.0/servers') + def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin @@ -411,6 +414,99 @@ class ServersTest(unittest.TestCase): self.assertEqual(res.status, '202 Accepted') self.assertEqual(self.server_delete_called, True) + def test_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(resize={flavorId=3}})) + res = req.get_response(fakes.wsgi_app()) + + self.resize_called = False + def resize_mock(context, inst_id, flavor): + self.resize_called = True + + self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_resize_bad_param_fails(self): + req = self.webreq('/1/action', 'POST', dict('ferp')) + res = req.get_response(fakes.wsgi_app()) + + self.resize_called = False + def resize_mock(context, inst_id, flavor): + self.resize_called = True + + self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) + self.assertEqual(res.status_int, 422) + self.assertEqual(self.resize_called, False) + + def test_resize_bad_flavor_fails(self): + req = self.webreq('/1/action', 'POST', dict(resize={derp=3})) + res = req.get_response(fakes.wsgi_app()) + + self.resize_called = False + def resize_mock(context, inst_id, flavor): + self.resize_called = True + + self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) + self.assertEqual(res.status_int, 422) + self.assertEqual(self.resize_called, False) + + def test_resize_raises_fails(self): + req = self.webreq('/1/action', 'POST', dict(resize={flavorId=3})) + res = req.get_response(fakes.wsgi_app()) + + def resize_mock(context, inst_id, flavor): + raise Exception, 'hurr durr' + + self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) + self.assertEqual(res.status_int, 500) + + def test_confirm_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) + res = req.get_response(fakes.wsgi_app()) + + self.resize_called = False + def confirm_resize_mock(context, inst_id): + self.resize_called = True + + self.stubs.Set(nova.compute.api, 'confirm_resize', + confirm_resize_mock) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_confirm_resize_server_fails(self): + req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) + res = req.get_response(fakes.wsgi_app()) + + def confirm_resize_mock(context, inst_id): + raise Exception, 'hurr durr' + + self.stubs.Set(nova.compute.api, 'confirm_resize', + confirm_resize_mock) + self.assertEqual(res.status_int, 500) + + def test_revert_resize_server(self): + req = self.webreq('/1/action', 'POST', dict(revertResize=None)) + res = req.get_response(fakes.wsgi_app()) + + self.resize_called = False + def revert_resize_mock(context, inst_id): + self.resize_called = True + + self.stubs.Set(nova.compute.api, 'revert_resize', + confirm_resize_mock) + self.assertEqual(res.status_int, 202) + self.assertEqual(self.resize_called, True) + + def test_revert_resize_server_fails(self): + req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) + res = req.get_response(fakes.wsgi_app()) + + def revert_resize_mock(context, inst_id): + raise Exception, 'hurr durr' + + self.stubs.Set(nova.compute.api, 'revert_resize', + confirm_resize_mock) + self.assertEqual(res.status_int, 500) if __name__ == "__main__": unittest.main() -- cgit From 9a7213b615bcaa2127f76146d594f5247ea0d0a4 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 17 Feb 2011 15:00:18 -0800 Subject: Initial support for per-instance metadata, though the OpenStack API. Key/value pairs can be specified at instance creation time and are returned in the details view. Support limits based on quota system. --- nova/tests/api/openstack/test_servers.py | 11 +++++++++-- nova/tests/test_quota.py | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a7be0796e..7eb81c2b8 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -28,6 +28,7 @@ import nova.api.openstack from nova.api.openstack import servers import nova.db.api from nova.db.sqlalchemy.models import Instance +from nova.db.sqlalchemy.models import InstanceMetadata import nova.rpc from nova.tests.api.openstack import fakes @@ -64,6 +65,9 @@ def instance_address(context, instance_id): def stub_instance(id, user_id=1, private_address=None, public_addresses=None): + metadata = [] + metadata.append(InstanceMetadata(key='seq', value=id)) + if public_addresses == None: public_addresses = list() @@ -95,7 +99,8 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None): "availability_zone": "", "display_name": "server%s" % id, "display_description": "", - "locked": False} + "locked": False, + "metadata": metadata} instance["fixed_ip"] = { "address": private_address, @@ -214,7 +219,8 @@ class ServersTest(unittest.TestCase): "get_image_id_from_image_hash", image_id_from_hash) body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, + name='server_test', imageId=2, flavorId=2, + metadata={'hello': 'world', 'open': 'stack'}, personality={})) req = webob.Request.blank('/v1.0/servers') req.method = 'POST' @@ -291,6 +297,7 @@ class ServersTest(unittest.TestCase): self.assertEqual(s['id'], i) self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageId'], 10) + self.assertEqual(s['metadata']['seq'], i) i += 1 def test_server_pause(self): diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 9548a8c13..36ccc273e 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -87,6 +87,18 @@ class QuotaTestCase(test.TestCase): num_instances = quota.allowed_instances(self.context, 100, instance_types.INSTANCE_TYPES['m1.small']) self.assertEqual(num_instances, 10) + + # metadata_items + too_many_items = FLAGS.quota_metadata_items + 1000 + num_metadata_items = quota.allowed_metadata_items(self.context, + too_many_items) + self.assertEqual(num_metadata_items, FLAGS.quota_metadata_items) + db.quota_update(self.context, self.project.id, {'metadata_items': 5}) + num_metadata_items = quota.allowed_metadata_items(self.context, + too_many_items) + self.assertEqual(num_metadata_items, 5) + + # Cleanup db.quota_destroy(self.context, self.project.id) def test_too_many_instances(self): @@ -151,3 +163,15 @@ class QuotaTestCase(test.TestCase): self.assertRaises(quota.QuotaError, self.cloud.allocate_address, self.context) db.floating_ip_destroy(context.get_admin_context(), address) + + def test_too_many_metadata_items(self): + metadata = {} + for i in range(FLAGS.quota_metadata_items + 1): + metadata['key%s' % i] = 'value%s' % i + self.assertRaises(quota.QuotaError, self.cloud.run_instances, + self.context, + min_count=1, + max_count=1, + instance_type='m1.small', + image_id='fake', + metadata=metadata) -- cgit From 88aa545b53d96c25da01218c79e8be8c1ae3370f Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Thu, 17 Feb 2011 23:55:56 +0000 Subject: Test changes --- nova/tests/api/openstack/test_servers.py | 82 +++++++++++++++----------------- 1 file changed, 39 insertions(+), 43 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 878b62f85..665551c55 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -26,6 +26,7 @@ from nova import db from nova import flags import nova.api.openstack from nova.api.openstack import servers +import nova.compute.api import nova.db.api from nova.db.sqlalchemy.models import Instance import nova.rpc @@ -139,7 +140,7 @@ class ServersTest(unittest.TestCase): self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) self.allow_admin = FLAGS.allow_admin_api - self.webreq = common.webob_factor('/v1.0/servers') + self.webreq = common.webob_factory('/v1.0/servers') def tearDown(self): self.stubs.UnsetAll() @@ -415,98 +416,93 @@ class ServersTest(unittest.TestCase): self.assertEqual(self.server_delete_called, True) def test_resize_server(self): - req = self.webreq('/1/action', 'POST', dict(resize={flavorId=3}})) - res = req.get_response(fakes.wsgi_app()) + req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) self.resize_called = False - def resize_mock(context, inst_id, flavor): + def resize_mock(*args): self.resize_called = True - self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) self.assertEqual(self.resize_called, True) - def test_resize_bad_param_fails(self): - req = self.webreq('/1/action', 'POST', dict('ferp')) - res = req.get_response(fakes.wsgi_app()) + def test_resize_bad_flavor_fails(self): + req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3))) self.resize_called = False - def resize_mock(context, inst_id, flavor): + def resize_mock(*args): self.resize_called = True - self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) - self.assertEqual(res.status_int, 422) - self.assertEqual(self.resize_called, False) + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) - def test_resize_bad_flavor_fails(self): - req = self.webreq('/1/action', 'POST', dict(resize={derp=3})) res = req.get_response(fakes.wsgi_app()) - - self.resize_called = False - def resize_mock(context, inst_id, flavor): - self.resize_called = True - - self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) self.assertEqual(res.status_int, 422) self.assertEqual(self.resize_called, False) def test_resize_raises_fails(self): - req = self.webreq('/1/action', 'POST', dict(resize={flavorId=3})) - res = req.get_response(fakes.wsgi_app()) + req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) - def resize_mock(context, inst_id, flavor): + def resize_mock(*args): raise Exception, 'hurr durr' - self.stubs.Set(nova.compute.api, 'resize_instance', resize_mock) - self.assertEqual(res.status_int, 500) + self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) def test_confirm_resize_server(self): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) - res = req.get_response(fakes.wsgi_app()) self.resize_called = False - def confirm_resize_mock(context, inst_id): + def confirm_resize_mock(*args): self.resize_called = True - self.stubs.Set(nova.compute.api, 'confirm_resize', + self.stubs.Set(nova.compute.api.API, 'confirm_resize', confirm_resize_mock) - self.assertEqual(res.status_int, 202) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 204) self.assertEqual(self.resize_called, True) def test_confirm_resize_server_fails(self): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) - res = req.get_response(fakes.wsgi_app()) - def confirm_resize_mock(context, inst_id): + def confirm_resize_mock(*args): raise Exception, 'hurr durr' - self.stubs.Set(nova.compute.api, 'confirm_resize', + self.stubs.Set(nova.compute.api.API, 'confirm_resize', confirm_resize_mock) - self.assertEqual(res.status_int, 500) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) def test_revert_resize_server(self): req = self.webreq('/1/action', 'POST', dict(revertResize=None)) - res = req.get_response(fakes.wsgi_app()) self.resize_called = False - def revert_resize_mock(context, inst_id): + def revert_resize_mock(*args): self.resize_called = True - self.stubs.Set(nova.compute.api, 'revert_resize', - confirm_resize_mock) + self.stubs.Set(nova.compute.api.API, 'revert_resize', + revert_resize_mock) + + res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) self.assertEqual(self.resize_called, True) def test_revert_resize_server_fails(self): - req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) - res = req.get_response(fakes.wsgi_app()) + req = self.webreq('/1/action', 'POST', dict(revertResize=None)) - def revert_resize_mock(context, inst_id): + def revert_resize_mock(*args): raise Exception, 'hurr durr' - self.stubs.Set(nova.compute.api, 'revert_resize', - confirm_resize_mock) - self.assertEqual(res.status_int, 500) + self.stubs.Set(nova.compute.api.API, 'revert_resize', + revert_resize_mock) + + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) if __name__ == "__main__": unittest.main() -- cgit From 2da6494d20624177c0077d0709e1fdb0e5f8f03c Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Thu, 17 Feb 2011 17:42:49 -0800 Subject: pep8 --- nova/tests/api/openstack/test_zones.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 5542a1cf3..df497ef1b 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -57,8 +57,7 @@ def zone_get_all(context): dict(id=1, api_url='http://foo.com', username='bob', password='xxx'), dict(id=2, api_url='http://blah.com', username='alice', - password='qwerty') - ] + password='qwerty')] class ZonesTest(unittest.TestCase): -- cgit From 4b51ec3e9bca7421c66816c77c43396e51e68ea6 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Thu, 17 Feb 2011 23:09:06 -0600 Subject: Tests --- nova/tests/api/openstack/common.py | 8 +++++--- nova/tests/test_compute.py | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/common.py b/nova/tests/api/openstack/common.py index b55d3087b..66207cddc 100644 --- a/nova/tests/api/openstack/common.py +++ b/nova/tests/api/openstack/common.py @@ -21,10 +21,12 @@ import webob def webob_factory(url): base_url = url - def web_request(url, method, body=None): + def web_request(url, method=None, body=None): req = webob.Request.blank("%s%s" % (base_url, url)) - req.method = method - req.body = json.dumps(body) + if method: + req.method = method + if body: + req.body = json.dumps(body) return req return web_request diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 2aa0690e7..e27e08827 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -258,3 +258,10 @@ class ComputeTestCase(test.TestCase): self.assertEqual(ret_val, None) self.compute.terminate_instance(self.context, instance_id) + + def test_resize_instance(self): + """Ensure instance can be migrated/resized""" + instance_id = self._create_instance() + self.compute.run_instnce(self.context, instance_id) + self.compute.prep_resize(self.context, instance_id) + -- cgit From 671766cb4ada59b0e575b395b5afff82950ddb76 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Fri, 18 Feb 2011 06:03:15 +0000 Subject: Resize compute tests --- nova/tests/test_compute.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index e27e08827..3f2e64c87 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -56,7 +56,7 @@ class ComputeTestCase(test.TestCase): self.manager.delete_project(self.project) super(ComputeTestCase, self).tearDown() - def _create_instance(self): + def _create_instance(self, params={}): """Create a test instance""" inst = {} inst['image_id'] = 'ami-test' @@ -67,6 +67,7 @@ class ComputeTestCase(test.TestCase): inst['instance_type'] = 'm1.tiny' inst['mac_address'] = utils.generate_mac() inst['ami_launch_index'] = 0 + inst.update(params) return db.instance_create(self.context, inst)['id'] def _create_group(self): @@ -262,6 +263,23 @@ class ComputeTestCase(test.TestCase): def test_resize_instance(self): """Ensure instance can be migrated/resized""" instance_id = self._create_instance() - self.compute.run_instnce(self.context, instance_id) - self.compute.prep_resize(self.context, instance_id) + context = self.context.elevated() + self.compute.run_instance(self.context, instance_id) + db.instance_update(self.context, instance_id, {'host':'foo'}) + + self.compute.prep_resize(context, instance_id) + migration_ref = db.migration_get_by_instance_and_status(context, + instance_id, 'pre-migrating') + self.compute.resize_instance(context, instance_id, + migration_ref['id']) + self.compute.terminate_instance(context, instance_id) + + def test_resize_same_source_fails(self): + """Ensure instance fails to migrate when source and destination are + the same host""" + instance_id = self._create_instance() + self.compute.run_instance(self.context, instance_id) + self.assertRaises(exception.Error, self.compute.prep_resize, + self.context, instance_id) + self.compute.terminate_instance(self.context, instance_id) -- cgit From 4673afddcb5a1069f75fb3493e43498ed1de11f9 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Fri, 18 Feb 2011 02:23:30 -0500 Subject: Incorporating minor cleanups suggested by Rick Harris: * Use assertNotEqual instead of assertTrue * Use enumerate function instead of maintaining a counter --- nova/tests/api/openstack/test_servers.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 630e1e5eb..4ed13022b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -259,15 +259,13 @@ class ServersTest(unittest.TestCase): server_list = res_dict['servers'] host_ids = [server_list[0]['hostId'], server_list[1]['hostId']] self.assertTrue(host_ids[0] and host_ids[1]) - self.assertTrue(host_ids[0] != host_ids[1]) + self.assertNotEqual(host_ids[0], host_ids[1]) - i = 0 - for s in res_dict['servers']: + for i, s in enumerate(res_dict['servers']): self.assertEqual(s['id'], i) self.assertEqual(s['hostId'], host_ids[i % 2]) self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageId'], 10) - i += 1 def test_server_pause(self): FLAGS.allow_admin_api = True -- cgit From c884064e7a9af04b2ebdbbb9ee32318a00716412 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 18 Feb 2011 12:08:35 -0400 Subject: fixups backed on merge comments --- nova/tests/api/openstack/test_zones.py | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 65cc1c023..4df7c7feb 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -1,4 +1,4 @@ -# Copyright 2010 OpenStack LLC. +# Copyright 2011 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -24,6 +24,7 @@ from nova import context from nova import flags from nova.api.openstack import zones from nova.tests.api.openstack import fakes +from nova.scheduler.api import API FLAGS = flags.FLAGS @@ -31,7 +32,7 @@ FLAGS.verbose = True def zone_get(context, zone_id): - return dict(id=1, api_url='http://foo.com', username='bob', + return dict(id=1, api_url='http://example.com', username='bob', password='xxx') @@ -42,7 +43,7 @@ def zone_create(context, values): def zone_update(context, zone_id, values): - zone = dict(id=zone_id, api_url='http://foo.com', username='bob', + zone = dict(id=zone_id, api_url='http://example.com', username='bob', password='xxx') zone.update(values) return zone @@ -52,24 +53,24 @@ def zone_delete(context, zone_id): pass -def zone_get_all_scheduler(x, y, z): +def zone_get_all_scheduler(*args): return [ - dict(id=1, api_url='http://foo.com', username='bob', + dict(id=1, api_url='http://example.com', username='bob', password='xxx'), - dict(id=2, api_url='http://blah.com', username='alice', + dict(id=2, api_url='http://example.org', username='alice', password='qwerty') ] -def zone_get_all_scheduler_empty(x, y, z): +def zone_get_all_scheduler_empty(*args): return [] def zone_get_all_db(context): return [ - dict(id=1, api_url='http://foo.com', username='bob', + dict(id=1, api_url='http://example.com', username='bob', password='xxx'), - dict(id=2, api_url='http://blah.com', username='alice', + dict(id=2, api_url='http://example.org', username='alice', password='qwerty') ] @@ -96,8 +97,7 @@ class ZonesTest(unittest.TestCase): FLAGS.allow_admin_api = self.allow_admin def test_get_zone_list_scheduler(self): - self.stubs.Set(zones.Controller, '_call_scheduler', - zone_get_all_scheduler) + self.stubs.Set(API, '_call_scheduler', zone_get_all_scheduler) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -106,8 +106,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_list_db(self): - self.stubs.Set(zones.Controller, '_call_scheduler', - zone_get_all_scheduler_empty) + self.stubs.Set(API, '_call_scheduler', zone_get_all_scheduler_empty) self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) @@ -122,7 +121,7 @@ class ZonesTest(unittest.TestCase): res_dict = json.loads(res.body) self.assertEqual(res_dict['zone']['id'], 1) - self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['api_url'], 'http://example.com') self.assertFalse('password' in res_dict['zone']) self.assertEqual(res.status_int, 200) @@ -133,7 +132,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) def test_zone_create(self): - body = dict(zone=dict(api_url='http://blah.zoo', username='fred', + body = dict(zone=dict(api_url='http://example.com', username='fred', password='fubar')) req = webob.Request.blank('/v1.0/zones') req.method = 'POST' @@ -144,7 +143,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) - self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') + self.assertEqual(res_dict['zone']['api_url'], 'http://example.com') self.assertFalse('username' in res_dict['zone']) def test_zone_update(self): @@ -158,7 +157,7 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['id'], 1) - self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') + self.assertEqual(res_dict['zone']['api_url'], 'http://example.com') self.assertFalse('username' in res_dict['zone']) -- cgit From cd533e160e9c98a0c14b4e0bc32a6e94c7ab8657 Mon Sep 17 00:00:00 2001 From: Nirmal Ranganathan Date: Fri, 18 Feb 2011 11:44:38 -0600 Subject: Added Author and tests --- nova/tests/test_compute.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index b049ac943..e338a7cfa 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -30,6 +30,7 @@ from nova import log as logging from nova import test from nova import utils from nova.auth import manager +from nova.compute import instance_types LOG = logging.getLogger('nova.tests.compute') @@ -266,3 +267,11 @@ class ComputeTestCase(test.TestCase): self.assertEqual(ret_val, None) self.compute.terminate_instance(self.context, instance_id) + + def test_get_by_flavor_id(self): + type = instance_types.get_by_flavor_id(1) + self.assertEqual(type, 'm1.tiny') + + type = instance_types.get_by_flavor_id("1") + self.assertEqual(type, 'm1.tiny') + -- cgit From bb5624258200f027320327a38c524c389979c97a Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Fri, 18 Feb 2011 19:04:57 +0000 Subject: Resize compute tests --- nova/tests/test_xenapi.py | 34 ++++++++++++++++++++++++++++++++++ nova/tests/xenapi/stubs.py | 25 +++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 6b8efc9d8..ee4c68e6c 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -336,3 +336,37 @@ class XenAPIDiffieHellmanTestCase(test.TestCase): def tearDown(self): super(XenAPIDiffieHellmanTestCase, self).tearDown() + +class XenAPIMigrateInstance(test.TestCase): + """ + Unit test for verifying migration-related actions + """ + def setUp(self): + super(XenAPIMigrateInstance, self).setUp() + self.stubs = stubout.StubOutForTesting() + FLAGS.target_host = '127.0.0.1' + FLAGS.xenapi_connection_url = 'test_url' + FLAGS.xenapi_connection_password = 'test_pass' + db_fakes.stub_out_db_instance_api(self.stubs) + stubs.stub_out_get_target(self.stubs) + xenapi_fake.reset() + self.values = {'name': 1, 'id': 1, + 'project_id': 'fake', + 'user_id': 'fake', + 'image_id': 1, + 'kernel_id': 2, + 'ramdisk_id': 3, + 'instance_type': 'm1.large', + 'mac_address': 'aa:bb:cc:dd:ee:ff', + } + stubs.stub_out_migration_methods(self.stubs) + + def test_migrate_disk_and_power_off(self): + FLAGS.target_host = '127.0.0.1' + FLAGS.xenapi_connection_url = 'test_url' + FLAGS.xenapi_connection_password = 'test_pass' + destination = '127.0.0.1' + instance = db.instance_create(self.values) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + conn = xenapi_conn.get_connection(False) + conn.migrate_disk_and_power_off(instance, destination) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 624995ada..d1c367475 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -20,6 +20,7 @@ from nova.virt import xenapi_conn from nova.virt.xenapi import fake from nova.virt.xenapi import volume_utils from nova.virt.xenapi import vm_utils +from nova.virt.xenapi import vmops def stubout_instance_snapshot(stubs): @@ -170,8 +171,8 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_destroy(self, session_ref, vm_ref): fake.destroy_vm(vm_ref) - - + + class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ def __init__(self, uri): @@ -205,3 +206,23 @@ class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests): def SR_forget(self, _1, ref): pass + +class FakeSessionForMigrationTests(fake.SessionBase): + """ Stubs out a XenAPISession for Migration tests """ + def __init__(self, uri): + super(FakeSessionForMigrationTests, self).__init__(uri) + + +class FakeSnapshot(vmops.VMOps): + def __getattr__(self, key): + return 'fake' + + def __exit__(self, type, value, traceback) + pass + +def fake_get_snapshot(self, instance): + return FakeSnapshot() + +def stub_out_migration_methods(stubs): + stubs.Set(vmops.VMOps, '_get_snapshot', + fake_get_snapshot) -- cgit From 5812a95736b9a16733b99700e8664dd29ae34def Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 18 Feb 2011 22:10:06 +0100 Subject: Introduce IptablesManager in linux_net. Port every use of iptables in linux_net to it. --- nova/tests/test_network.py | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 00f9323f3..b28d64245 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -29,11 +29,70 @@ from nova import log as logging from nova import test from nova import utils from nova.auth import manager +from nova.network import linux_net FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.network') +class IptablesManagerTestCase(test.TestCase): + sample_filter = """# Completed on Fri Feb 18 15:17:05 2011 +# Generated by iptables-save v1.4.10 on Fri Feb 18 15:17:05 2011 +*filter +:INPUT ACCEPT [2223527:305688874] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [2172501:140856656] +-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT +-A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT +-A FORWARD -i virbr0 -o virbr0 -j ACCEPT +-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable +-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable +COMMIT +# Completed on Fri Feb 18 15:17:05 2011""" + + def setUp(self): + super(IptablesManagerTestCase, self).setUp() + self.manager = linux_net.IptablesManager() + + def test_rules_are_wrapped(self): + current_lines = self.sample_filter.split('\n') + + table = self.manager.ipv4['filter'] + table.add_rule('FORWARD', '-s 1.2.3.4/5 -j DROP') + new_lines = self.manager.modify_rules(current_lines, table) + self.assertTrue('-A run_tests.py-FORWARD ' + '-s 1.2.3.4/5 -j DROP' in new_lines) + + table.remove_rule('FORWARD', '-s 1.2.3.4/5 -j DROP') + new_lines = self.manager.modify_rules(current_lines, table) + self.assertTrue('-A run_tests.py-FORWARD ' + '-s 1.2.3.4/5 -j DROP' not in new_lines) + + def test_wrapper_rules_in_place(self): + current_lines = self.sample_filter.split('\n') + + # TODO(soren): Add stuff for ipv6 + check_matrix = {4: {'filter': ['INPUT', 'OUTPUT', 'FORWARD'], + 'nat': ['PREROUTING', 'INPUT', + 'OUTPUT', 'POSTROUTING']} } + + for ip_version in check_matrix: + ip = getattr(self.manager, 'ipv%d' % ip_version) + for table_name in ip: + table = ip[table_name] + new_lines = self.manager.modify_rules(current_lines, table) + for chain in check_matrix[ip_version][table_name]: + self.assertTrue(':run_tests.py-%s - [0:0]' % \ + (chain,) in new_lines) + self.assertTrue('-A %s -j run_tests.py-%s' % \ + (chain, chain) in new_lines) + print '\n'.join(new_lines) + + class NetworkTestCase(test.TestCase): """Test cases for network code""" def setUp(self): -- cgit From 62b3eb71384581e900b061e65caa6418c4452fa9 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Fri, 18 Feb 2011 21:37:57 +0000 Subject: XenAPI tests --- nova/tests/test_xenapi.py | 12 +++++++----- nova/tests/xenapi/stubs.py | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 36 insertions(+), 14 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index ee4c68e6c..3cbc01e5c 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -362,11 +362,13 @@ class XenAPIMigrateInstance(test.TestCase): stubs.stub_out_migration_methods(self.stubs) def test_migrate_disk_and_power_off(self): - FLAGS.target_host = '127.0.0.1' - FLAGS.xenapi_connection_url = 'test_url' - FLAGS.xenapi_connection_password = 'test_pass' - destination = '127.0.0.1' instance = db.instance_create(self.values) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) conn = xenapi_conn.get_connection(False) - conn.migrate_disk_and_power_off(instance, destination) + conn.migrate_disk_and_power_off(instance, '127.0.0.1') + + def test_attach_disk(self): + instance = db.instance_create(self.values) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + conn = xenapi_conn.get_connection(False) + conn.attach_disk(instance, {'base_copy': 'hurr', 'cow': 'durr'}) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index d1c367475..054fc434b 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -213,16 +213,36 @@ class FakeSessionForMigrationTests(fake.SessionBase): super(FakeSessionForMigrationTests, self).__init__(uri) -class FakeSnapshot(vmops.VMOps): - def __getattr__(self, key): - return 'fake' +def stub_out_migration_methods(stubs): + class FakeSnapshot(object): + def __getattr__(self, key): + return str(key) + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + pass + + def fake_get_snapshot(self, instance): + return FakeSnapshot() - def __exit__(self, type, value, traceback) + @classmethod + def fake_get_vdi(cls, session, vm_ref): + vdi_ref = fake.create_vdi(name_label='derp', read_only=False, + sr_ref='herp', sharable=False) + vdi_rec = session.get_xenapi().VDI.get_record(vdi_ref) + return vdi_ref, {'uuid': vdi_rec['uuid']} + + def fake_shutdown(self, inst, vm, method='clean'): pass -def fake_get_snapshot(self, instance): - return FakeSnapshot() + @classmethod + def fake_scan_sr(cls, session): + pass -def stub_out_migration_methods(stubs): - stubs.Set(vmops.VMOps, '_get_snapshot', - fake_get_snapshot) + stubs.Set(vm_utils.VMHelper, 'scan_sr', fake_scan_sr) + stubs.Set(vmops.VMOps, '_get_snapshot', fake_get_snapshot) + stubs.Set(vm_utils.VMHelper, 'get_vdi_for_vm_safely', fake_get_vdi) + stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x,y,z: None) + stubs.Set(vmops.VMOps, '_shutdown', fake_shutdown) -- cgit From 18e573a14414838f11e772edca3eb5510f852c94 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Fri, 18 Feb 2011 17:45:57 -0400 Subject: sandy y u no read hacking guide and import classes? --- nova/tests/api/openstack/test_zones.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 4df7c7feb..4374cd457 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -24,7 +24,7 @@ from nova import context from nova import flags from nova.api.openstack import zones from nova.tests.api.openstack import fakes -from nova.scheduler.api import API +from nova.scheduler import api FLAGS = flags.FLAGS @@ -97,7 +97,7 @@ class ZonesTest(unittest.TestCase): FLAGS.allow_admin_api = self.allow_admin def test_get_zone_list_scheduler(self): - self.stubs.Set(API, '_call_scheduler', zone_get_all_scheduler) + self.stubs.Set(api.API, '_call_scheduler', zone_get_all_scheduler) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -106,7 +106,8 @@ class ZonesTest(unittest.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_list_db(self): - self.stubs.Set(API, '_call_scheduler', zone_get_all_scheduler_empty) + self.stubs.Set(api.API, '_call_scheduler', + zone_get_all_scheduler_empty) self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) -- cgit From a43c5929de7ebf58eb9ecb8416ce3cf4194c176a Mon Sep 17 00:00:00 2001 From: Cerberus Date: Fri, 18 Feb 2011 16:13:34 -0600 Subject: Pep8 cleanup --- nova/tests/api/openstack/common.py | 7 +++++-- nova/tests/api/openstack/test_servers.py | 24 ++++++++++++++---------- nova/tests/test_compute.py | 6 ++---- nova/tests/test_xenapi.py | 1 + nova/tests/xenapi/stubs.py | 11 ++++++----- 5 files changed, 28 insertions(+), 21 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/common.py b/nova/tests/api/openstack/common.py index 66207cddc..3f9c7d3cf 100644 --- a/nova/tests/api/openstack/common.py +++ b/nova/tests/api/openstack/common.py @@ -19,14 +19,17 @@ import json import webob + def webob_factory(url): + """Factory for removing duplicate webob code from tests""" + base_url = url + def web_request(url, method=None, body=None): - req = webob.Request.blank("%s%s" % (base_url, url)) + req = webob.Request.blank("%s%s" % (base_url, url)) if method: req.method = method if body: req.body = json.dumps(body) return req return web_request - diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 665551c55..4eb4a3c62 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -419,8 +419,9 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) self.resize_called = False + def resize_mock(*args): - self.resize_called = True + self.resize_called = True self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) @@ -432,8 +433,9 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(resize=dict(derp=3))) self.resize_called = False + def resize_mock(*args): - self.resize_called = True + self.resize_called = True self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) @@ -445,7 +447,7 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(resize=dict(flavorId=3))) def resize_mock(*args): - raise Exception, 'hurr durr' + raise Exception('hurr durr') self.stubs.Set(nova.compute.api.API, 'resize', resize_mock) @@ -456,10 +458,11 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) self.resize_called = False + def confirm_resize_mock(*args): - self.resize_called = True + self.resize_called = True - self.stubs.Set(nova.compute.api.API, 'confirm_resize', + self.stubs.Set(nova.compute.api.API, 'confirm_resize', confirm_resize_mock) res = req.get_response(fakes.wsgi_app()) @@ -470,9 +473,9 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) def confirm_resize_mock(*args): - raise Exception, 'hurr durr' + raise Exception('hurr durr') - self.stubs.Set(nova.compute.api.API, 'confirm_resize', + self.stubs.Set(nova.compute.api.API, 'confirm_resize', confirm_resize_mock) res = req.get_response(fakes.wsgi_app()) @@ -482,10 +485,11 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(revertResize=None)) self.resize_called = False + def revert_resize_mock(*args): self.resize_called = True - self.stubs.Set(nova.compute.api.API, 'revert_resize', + self.stubs.Set(nova.compute.api.API, 'revert_resize', revert_resize_mock) res = req.get_response(fakes.wsgi_app()) @@ -496,9 +500,9 @@ class ServersTest(unittest.TestCase): req = self.webreq('/1/action', 'POST', dict(revertResize=None)) def revert_resize_mock(*args): - raise Exception, 'hurr durr' + raise Exception('hurr durr') - self.stubs.Set(nova.compute.api.API, 'revert_resize', + self.stubs.Set(nova.compute.api.API, 'revert_resize', revert_resize_mock) res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 3f2e64c87..5fd1ddaec 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -265,8 +265,7 @@ class ComputeTestCase(test.TestCase): instance_id = self._create_instance() context = self.context.elevated() self.compute.run_instance(self.context, instance_id) - db.instance_update(self.context, instance_id, {'host':'foo'}) - + db.instance_update(self.context, instance_id, {'host': 'foo'}) self.compute.prep_resize(context, instance_id) migration_ref = db.migration_get_by_instance_and_status(context, instance_id, 'pre-migrating') @@ -279,7 +278,6 @@ class ComputeTestCase(test.TestCase): the same host""" instance_id = self._create_instance() self.compute.run_instance(self.context, instance_id) - self.assertRaises(exception.Error, self.compute.prep_resize, + self.assertRaises(exception.Error, self.compute.prep_resize, self.context, instance_id) - self.compute.terminate_instance(self.context, instance_id) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 3cbc01e5c..cb9b6620a 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -337,6 +337,7 @@ class XenAPIDiffieHellmanTestCase(test.TestCase): def tearDown(self): super(XenAPIDiffieHellmanTestCase, self).tearDown() + class XenAPIMigrateInstance(test.TestCase): """ Unit test for verifying migration-related actions diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 054fc434b..303c37eb9 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -171,8 +171,8 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_destroy(self, session_ref, vm_ref): fake.destroy_vm(vm_ref) - - + + class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ def __init__(self, uri): @@ -207,6 +207,7 @@ class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests): def SR_forget(self, _1, ref): pass + class FakeSessionForMigrationTests(fake.SessionBase): """ Stubs out a XenAPISession for Migration tests """ def __init__(self, uri): @@ -232,8 +233,8 @@ def stub_out_migration_methods(stubs): vdi_ref = fake.create_vdi(name_label='derp', read_only=False, sr_ref='herp', sharable=False) vdi_rec = session.get_xenapi().VDI.get_record(vdi_ref) - return vdi_ref, {'uuid': vdi_rec['uuid']} - + return vdi_ref, {'uuid': vdi_rec['uuid'], } + def fake_shutdown(self, inst, vm, method='clean'): pass @@ -244,5 +245,5 @@ def stub_out_migration_methods(stubs): stubs.Set(vm_utils.VMHelper, 'scan_sr', fake_scan_sr) stubs.Set(vmops.VMOps, '_get_snapshot', fake_get_snapshot) stubs.Set(vm_utils.VMHelper, 'get_vdi_for_vm_safely', fake_get_vdi) - stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x,y,z: None) + stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x, y, z: None) stubs.Set(vmops.VMOps, '_shutdown', fake_shutdown) -- cgit From e369f2842446876505ce528c5bb56a3d41215f8f Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Fri, 18 Feb 2011 16:42:26 -0600 Subject: added admin api call for injecting network info, added api test for inject network info --- nova/tests/api/openstack/test_servers.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 89e192eed..58da12dcc 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -293,6 +293,18 @@ class ServersTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) + def test_server_inject_network_info(self): + FLAGS.allow_admin_api = True + body = dict(server=dict( + name='server_test', imageId=2, flavorId=2, metadata={}, + personality={})) + req = webob.Request.blank('/v1.0/servers/1/inject_network_info') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + def test_server_diagnostics(self): req = webob.Request.blank("/v1.0/servers/1/diagnostics") req.method = "GET" -- cgit From cfd6d4e403dcb2405cd7ff48bad3083a02159d2c Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Sat, 19 Feb 2011 00:14:08 +0100 Subject: Port libvirt_conn.IptablesDriver over to use linux_net.IptablesManager --- nova/tests/test_virt.py | 55 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 19 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 6e5a0114b..a88e01818 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -14,6 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. +import re from xml.etree.ElementTree import fromstring as xml_to_tree from xml.dom.minidom import parseString as xml_to_dom @@ -233,16 +234,22 @@ class IptablesFirewallTestCase(test.TestCase): self.manager.delete_user(self.user) super(IptablesFirewallTestCase, self).tearDown() - in_rules = [ + in_nat_rules = [ + '# Generated by iptables-save v1.4.10 on Sat Feb 19 00:03:19 2011', + '*nat', + ':PREROUTING ACCEPT [1170:189210]', + ':INPUT ACCEPT [844:71028]', + ':OUTPUT ACCEPT [5149:405186]', + ':POSTROUTING ACCEPT [5063:386098]' + ] + + in_filter_rules = [ '# Generated by iptables-save v1.4.4 on Mon Dec 6 11:54:13 2010', '*filter', ':INPUT ACCEPT [969615:281627771]', ':FORWARD ACCEPT [0:0]', ':OUTPUT ACCEPT [915599:63811649]', ':nova-block-ipv4 - [0:0]', - '-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT ', - '-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT ', - '-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT ', '-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT ', '-A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED' ',ESTABLISHED -j ACCEPT ', @@ -254,7 +261,7 @@ class IptablesFirewallTestCase(test.TestCase): '# Completed on Mon Dec 6 11:54:13 2010', ] - in6_rules = [ + in6_filter_rules = [ '# Generated by ip6tables-save v1.4.4 on Tue Jan 18 23:47:56 2011', '*filter', ':INPUT ACCEPT [349155:75810423]', @@ -314,23 +321,31 @@ class IptablesFirewallTestCase(test.TestCase): instance_ref = db.instance_get(admin_ctxt, instance_ref['id']) # self.fw.add_instance(instance_ref) - def fake_iptables_execute(cmd, process_input=None): + def fake_iptables_execute(cmd, process_input=None, attempts=5): if cmd == 'sudo ip6tables-save -t filter': - return '\n'.join(self.in6_rules), None + return '\n'.join(self.in6_filter_rules), None if cmd == 'sudo iptables-save -t filter': - return '\n'.join(self.in_rules), None + return '\n'.join(self.in_filter_rules), None + if cmd == 'sudo iptables-save -t nat': + return '\n'.join(self.in_nat_rules), None if cmd == 'sudo iptables-restore': - self.out_rules = process_input.split('\n') + lines = process_input.split('\n') + if '*filter' in lines: + self.out_rules = lines return '', '' if cmd == 'sudo ip6tables-restore': - self.out6_rules = process_input.split('\n') + lines = process_input.split('\n') + if '*filter' in lines: + self.out6_rules = lines return '', '' - self.fw.execute = fake_iptables_execute + + from nova.network import linux_net + linux_net.iptables_manager.execute = fake_iptables_execute self.fw.prepare_instance_filter(instance_ref) self.fw.apply_instance_filter(instance_ref) - in_rules = filter(lambda l: not l.startswith('#'), self.in_rules) + in_rules = filter(lambda l: not l.startswith('#'), self.in_filter_rules) for rule in in_rules: if not 'nova' in rule: self.assertTrue(rule in self.out_rules, @@ -338,6 +353,7 @@ class IptablesFirewallTestCase(test.TestCase): instance_chain = None for rule in self.out_rules: + print rule # This is pretty crude, but it'll do for now if '-d 10.11.12.13 -j' in rule: instance_chain = rule.split(' ')[-1] @@ -353,17 +369,18 @@ class IptablesFirewallTestCase(test.TestCase): self.assertTrue(security_group_chain, "The security group chain wasn't added") - self.assertTrue('-A %s -p icmp -s 192.168.11.0/24 -j ACCEPT' % \ - security_group_chain in self.out_rules, + regex = re.compile('-A .* -p icmp -s 192.168.11.0/24 -j ACCEPT') + self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, "ICMP acceptance rule wasn't added") - self.assertTrue('-A %s -p icmp -s 192.168.11.0/24 -m icmp --icmp-type ' - '8 -j ACCEPT' % security_group_chain in self.out_rules, + regex = re.compile('-A .* -p icmp -s 192.168.11.0/24 -m icmp ' + '--icmp-type 8 -j ACCEPT') + self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, "ICMP Echo Request acceptance rule wasn't added") - self.assertTrue('-A %s -p tcp -s 192.168.10.0/24 -m multiport ' - '--dports 80:81 -j ACCEPT' % security_group_chain \ - in self.out_rules, + regex = re.compile('-A .* -p tcp -s 192.168.10.0/24 -m multiport ' + '--dports 80:81 -j ACCEPT') + self.assertTrue(len(filter(regex.match, self.out_rules)) > 0, "TCP port 80/81 acceptance rule wasn't added") -- cgit From fcd31c4d7c3855cb95ac75d6966b377eca8bbe7d Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Fri, 18 Feb 2011 15:59:42 -0800 Subject: added instance types purge test --- nova/tests/test_instance_types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 0d54cc283..fe052110f 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -49,12 +49,16 @@ class InstanceTypeTestCase(test.TestCase): new = instance_types.get_all_types() self.assertNotEqual(len(starting_inst_list), len(new), - 'instance was not created') + 'instance type was not created') instance_types.destroy(self.name) self.assertEqual(1, instance_types.get_instance_type(self.name)["deleted"]) self.assertEqual(starting_inst_list, instance_types.get_all_types()) db.instance_type_purge(context.get_admin_context(), self.name) + self.assertEqual(len(starting_inst_list), + len(instance_types.get_all_types()), + 'instance type not purged') + def test_get_all_instance_types(self): """Ensures that all instance types can be retrieved""" -- cgit From 3609f1da7e1383b76295c6e8bd1d1dc0d798aa63 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Fri, 18 Feb 2011 16:00:22 -0800 Subject: pep8 --- nova/tests/test_instance_types.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index fe052110f..705144cb0 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -59,7 +59,6 @@ class InstanceTypeTestCase(test.TestCase): len(instance_types.get_all_types()), 'instance type not purged') - def test_get_all_instance_types(self): """Ensures that all instance types can be retrieved""" session = get_session() -- cgit From 53784c1afaa12d0a8b22248093ec1e623a1a913d Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Fri, 18 Feb 2011 17:17:47 -0800 Subject: added purge option and tightened up testing --- nova/tests/test_instance_types.py | 2 +- nova/tests/test_nova_manage.py | 62 ++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 31 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 705144cb0..1b192ca28 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -54,7 +54,7 @@ class InstanceTypeTestCase(test.TestCase): self.assertEqual(1, instance_types.get_instance_type(self.name)["deleted"]) self.assertEqual(starting_inst_list, instance_types.get_all_types()) - db.instance_type_purge(context.get_admin_context(), self.name) + instance_types.purge(self.name) self.assertEqual(len(starting_inst_list), len(instance_types.get_all_types()), 'instance type not purged') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 03b4e3fb8..03aea53c9 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -33,12 +33,13 @@ class NovaManageTestCase(test.TestCase): order_by("flavorid desc").first() self.flavorid = str(max_flavorid["flavorid"] + 1) self.name = str(int(time.time())) + self.fnull = open(os.devnull, 'w') def teardown(self): - fnull.close() + self.fnull.close() def test_create_and_delete_instance_types(self): - fnull = open(os.devnull, 'w') + myname = self.name + "create_and_delete" retcode = subprocess.call([ "bin/nova-manage", "instance_type", @@ -51,45 +52,44 @@ class NovaManageTestCase(test.TestCase): "2", "10", "10"], - stdout=fnull) + stdout=self.fnull) self.assertEqual(0, retcode) - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "delete", self.name], stdout=fnull) + retcode = subprocess.call(["bin/nova-manage", "instance_type", + "delete", self.name], stdout=self.fnull) + self.assertEqual(0, retcode) + retcode = subprocess.call(["bin/nova-manage", "instance_type", + "delete", self.name, "--purge"], + stdout=self.fnull) self.assertEqual(0, retcode) def test_list_instance_types_or_flavors(self): - fnull = open(os.devnull, 'w') for c in ["instance_type", "flavor"]: retcode = subprocess.call(["bin/nova-manage", c, \ - "list"], stdout=fnull) + "list"], stdout=self.fnull) self.assertEqual(0, retcode) def test_list_specific_instance_type(self): - fnull = open(os.devnull, 'w') retcode = subprocess.call(["bin/nova-manage", "instance_type", "list", - "m1.medium"], stdout=fnull) + "m1.medium"], stdout=self.fnull) self.assertEqual(0, retcode) def test_should_error_on_bad_create_args(self): - fnull = open(os.devnull, 'w') # shouldn't be able to create instance type with 0 vcpus - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", self.name, "256", "0",\ - "120", self.flavorid], stdout=fnull) + retcode = subprocess.call(["bin/nova-manage", "instance_type", + "create", self.name + "bad_args", + "256", "0", "120", self.flavorid], + stdout=self.fnull) self.assertEqual(1, retcode) def test_should_fail_on_duplicate_flavorid(self): - fnull = open(os.devnull, 'w') # flavorid 1 is set in migration seed data retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", self.name, "256", "1",\ - "120", "1"], stdout=fnull) - self.assertEqual(1, retcode) + "create", self.name + "dupflavor", "256", + "1", "120", "1"], stdout=self.fnull) + self.assertEqual(3, retcode) def test_should_fail_on_duplicate_name(self): - # FIXME(ken-pepple) duplicate_name really needs to be unique - duplicate_name = "sdfsdfsafsdfsd" - fnull = open(os.devnull, 'w') + duplicate_name = self.name + "dup_name" retcode = subprocess.call([ "bin/nova-manage", "instance_type", @@ -102,27 +102,29 @@ class NovaManageTestCase(test.TestCase): "2", "10", "10"], - stdout=fnull) + stdout=self.fnull) + self.assertEqual(0, retcode) duplicate_retcode = subprocess.call([ "bin/nova-manage", "instance_type", "create", duplicate_name, - "256", + "512", "1", - "120", - self.flavorid, + "240", + str(int(self.flavorid) + 1), "2", "10", "10"], - stdout=fnull) + stdout=self.fnull) self.assertEqual(3, duplicate_retcode) - delete_retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "delete", duplicate_name], stdout=fnull) + delete_retcode = subprocess.call(["bin/nova-manage", "instance_type", + "delete", duplicate_name, "--purge"], + stdout=self.fnull) self.assertEqual(0, delete_retcode) def test_instance_type_delete_should_fail_without_valid_name(self): - fnull = open(os.devnull, 'w') - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "delete", "doesntexist"], stdout=fnull) + retcode = subprocess.call(["bin/nova-manage", "instance_type", + "delete", "doesntexist"], + stdout=self.fnull) self.assertEqual(1, retcode) -- cgit From 990a0fdce67971e81665aa2151e43b071d8bcb7c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 18 Feb 2011 23:33:06 -0800 Subject: Fix FakeAuthManager so that unit tests pass; I believe it was matching the wrong field --- nova/tests/api/openstack/fakes.py | 8 ++++++-- nova/tests/api/openstack/test_auth.py | 6 +++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index fb282f1c9..e0b7b8029 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -221,7 +221,8 @@ class FakeAuthDatabase(object): class FakeAuthManager(object): auth_data = {} - def add_user(self, key, user): + def add_user(self, user): + key = user.id FakeAuthManager.auth_data[key] = user def get_user(self, uid): @@ -234,7 +235,10 @@ class FakeAuthManager(object): return None def get_user_from_access_key(self, key): - return FakeAuthManager.auth_data.get(key, None) + for k, v in FakeAuthManager.auth_data.iteritems(): + if v.access == key: + return v + return None class FakeRateLimiter(object): diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 0dd65d321..eab78b50c 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -48,7 +48,7 @@ class Test(unittest.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' @@ -62,7 +62,7 @@ class Test(unittest.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' @@ -144,7 +144,7 @@ class TestLimiter(unittest.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' -- cgit From 915d6e70106b30ed6919fa850749b8041c3e690d Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Sat, 19 Feb 2011 01:51:13 -0800 Subject: pep8 leftover --- nova/tests/api/openstack/test_zones.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 5542a1cf3..df497ef1b 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -57,8 +57,7 @@ def zone_get_all(context): dict(id=1, api_url='http://foo.com', username='bob', password='xxx'), dict(id=2, api_url='http://blah.com', username='alice', - password='qwerty') - ] + password='qwerty')] class ZonesTest(unittest.TestCase): -- cgit From 3d9d99a53d372abf9f69f1d6e66fa6c6491ec752 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 3 Mar 2011 19:27:15 -0400 Subject: tests passing --- nova/tests/test_service.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index 45d9afa6c..cb31a3c43 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -120,6 +120,12 @@ class ServiceTestCase(test.TestCase): proxy=mox.IsA(service.Service)).AndReturn( rpc.AdapterConsumer) + rpc.AdapterConsumer(connection=mox.IgnoreArg(), + topic='%s_fanout' % topic, + proxy=mox.IsA(service.Service)).AndReturn( + rpc.AdapterConsumer) + + rpc.AdapterConsumer.attach_to_eventlet() rpc.AdapterConsumer.attach_to_eventlet() rpc.AdapterConsumer.attach_to_eventlet() -- cgit From 106eb47eff0551c73b2e90385b9c3a910fec8633 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sun, 20 Feb 2011 23:16:10 -0800 Subject: fixes for various logging errors and issues --- nova/tests/fake_flags.py | 2 ++ nova/tests/test_auth.py | 9 ------ nova/tests/test_console.py | 2 -- nova/tests/test_direct.py | 1 - nova/tests/test_localization.py | 1 - nova/tests/test_log.py | 65 ++++++++++++++++++++--------------------- 6 files changed, 34 insertions(+), 46 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 1097488ec..68b14a46e 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -41,3 +41,5 @@ FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True FLAGS.sql_connection = 'sqlite:///nova.sqlite' FLAGS.use_ipv6 = True +FLAGS.logfile = 'run_tests.err' +flags.FlagValues.initialized = True diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 35ffffb67..2a7817032 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -327,15 +327,6 @@ class AuthManagerTestCase(object): class AuthManagerLdapTestCase(AuthManagerTestCase, test.TestCase): auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' - def __init__(self, *args, **kwargs): - AuthManagerTestCase.__init__(self) - test.TestCase.__init__(self, *args, **kwargs) - import nova.auth.fakeldap as fakeldap - if FLAGS.flush_db: - LOG.info("Flushing datastore") - r = fakeldap.Store.instance() - r.flushdb() - class AuthManagerDbTestCase(AuthManagerTestCase, test.TestCase): auth_driver = 'nova.auth.dbdriver.DbDriver' diff --git a/nova/tests/test_console.py b/nova/tests/test_console.py index 85bf94458..49ff24413 100644 --- a/nova/tests/test_console.py +++ b/nova/tests/test_console.py @@ -21,7 +21,6 @@ Tests For Console proxy. """ import datetime -import logging from nova import context from nova import db @@ -38,7 +37,6 @@ FLAGS = flags.FLAGS class ConsoleTestCase(test.TestCase): """Test case for console proxy""" def setUp(self): - logging.getLogger().setLevel(logging.DEBUG) super(ConsoleTestCase, self).setUp() self.flags(console_driver='nova.console.fake.FakeConsoleProxy', stub_compute=True) diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 8a74b2296..7656f5396 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -19,7 +19,6 @@ """Tests for Direct API.""" import json -import logging import webob diff --git a/nova/tests/test_localization.py b/nova/tests/test_localization.py index 6992773f5..393d71038 100644 --- a/nova/tests/test_localization.py +++ b/nova/tests/test_localization.py @@ -15,7 +15,6 @@ # under the License. import glob -import logging import os import re import sys diff --git a/nova/tests/test_log.py b/nova/tests/test_log.py index c2c9d7772..ada8d0a56 100644 --- a/nova/tests/test_log.py +++ b/nova/tests/test_log.py @@ -1,9 +1,12 @@ import cStringIO from nova import context +from nova import flags from nova import log from nova import test +FLAGS = flags.FLAGS + def _fake_context(): return context.RequestContext(1, 1) @@ -14,15 +17,11 @@ class RootLoggerTestCase(test.TestCase): super(RootLoggerTestCase, self).setUp() self.log = log.logging.root - def tearDown(self): - super(RootLoggerTestCase, self).tearDown() - log.NovaLogger.manager.loggerDict = {} - def test_is_nova_instance(self): self.assert_(isinstance(self.log, log.NovaLogger)) - def test_name_is_nova_root(self): - self.assertEqual("nova.root", self.log.name) + def test_name_is_nova(self): + self.assertEqual("nova", self.log.name) def test_handlers_have_nova_formatter(self): formatters = [] @@ -45,25 +44,38 @@ class RootLoggerTestCase(test.TestCase): log.audit("foo", context=_fake_context()) self.assert_(True) # didn't raise exception + def test_will_be_verbose_if_verbose_flag_set(self): + self.flags(verbose=True) + self.log.initialized = False + log.audit("foo", context=_fake_context()) + self.assertEqual(log.DEBUG, self.log.level) + + def test_will_not_be_verbose_if_verbose_flag_not_set(self): + self.flags(verbose=False) + self.log.initialized = False + log.audit("foo", context=_fake_context()) + self.assertEqual(log.INFO, self.log.level) + class LogHandlerTestCase(test.TestCase): def test_log_path_logdir(self): - self.flags(logdir='/some/path') - self.assertEquals(log.get_log_file_path(binary='foo-bar'), + self.flags(logdir='/some/path', logfile=None) + self.assertEquals(log._get_log_file_path(binary='foo-bar'), '/some/path/foo-bar.log') def test_log_path_logfile(self): self.flags(logfile='/some/path/foo-bar.log') - self.assertEquals(log.get_log_file_path(binary='foo-bar'), + self.assertEquals(log._get_log_file_path(binary='foo-bar'), '/some/path/foo-bar.log') def test_log_path_none(self): - self.assertTrue(log.get_log_file_path(binary='foo-bar') is None) + self.flags(logdir=None, logfile=None) + self.assertTrue(log._get_log_file_path(binary='foo-bar') is None) def test_log_path_logfile_overrides_logdir(self): self.flags(logdir='/some/other/path', logfile='/some/path/foo-bar.log') - self.assertEquals(log.get_log_file_path(binary='foo-bar'), + self.assertEquals(log._get_log_file_path(binary='foo-bar'), '/some/path/foo-bar.log') @@ -76,13 +88,15 @@ class NovaFormatterTestCase(test.TestCase): logging_debug_format_suffix="--DBG") self.log = log.logging.root self.stream = cStringIO.StringIO() - handler = log.StreamHandler(self.stream) - self.log.addHandler(handler) + self.handler = log.StreamHandler(self.stream) + self.log.addHandler(self.handler) + self.level = self.log.level self.log.setLevel(log.DEBUG) def tearDown(self): + self.log.setLevel(self.level) + self.log.removeHandler(self.handler) super(NovaFormatterTestCase, self).tearDown() - log.NovaLogger.manager.loggerDict = {} def test_uncontextualized_log(self): self.log.info("foo") @@ -102,30 +116,15 @@ class NovaFormatterTestCase(test.TestCase): class NovaLoggerTestCase(test.TestCase): def setUp(self): super(NovaLoggerTestCase, self).setUp() - self.flags(default_log_levels=["nova-test=AUDIT"], verbose=False) + levels = FLAGS.default_log_levels + levels.append("nova-test=AUDIT") + self.flags(default_log_levels=levels, + verbose=True) self.log = log.getLogger('nova-test') - def tearDown(self): - super(NovaLoggerTestCase, self).tearDown() - log.NovaLogger.manager.loggerDict = {} - def test_has_level_from_flags(self): self.assertEqual(log.AUDIT, self.log.level) def test_child_log_has_level_of_parent_flag(self): l = log.getLogger('nova-test.foo') self.assertEqual(log.AUDIT, l.level) - - -class VerboseLoggerTestCase(test.TestCase): - def setUp(self): - super(VerboseLoggerTestCase, self).setUp() - self.flags(default_log_levels=["nova.test=AUDIT"], verbose=True) - self.log = log.getLogger('nova.test') - - def tearDown(self): - super(VerboseLoggerTestCase, self).tearDown() - log.NovaLogger.manager.loggerDict = {} - - def test_will_be_verbose_if_named_nova_and_verbose_flag_set(self): - self.assertEqual(log.DEBUG, self.log.level) -- cgit From 98c2ef77e6018c0a6233e32ace435fba488175f5 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sun, 20 Feb 2011 23:18:09 -0800 Subject: move the fake initialized into fake flags --- nova/tests/fake_flags.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 68b14a46e..0a1011d86 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -42,4 +42,5 @@ FLAGS.verbose = True FLAGS.sql_connection = 'sqlite:///nova.sqlite' FLAGS.use_ipv6 = True FLAGS.logfile = 'run_tests.err' +# NOTE(vish): pretend like we've loaded flags from command line flags.FlagValues.initialized = True -- cgit From 7eab72b30cad9708e976f60e121569972b835b61 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 00:15:49 -0800 Subject: get rid of initialized flag --- nova/tests/fake_flags.py | 2 -- nova/tests/test_log.py | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 0a1011d86..59839b090 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -42,5 +42,3 @@ FLAGS.verbose = True FLAGS.sql_connection = 'sqlite:///nova.sqlite' FLAGS.use_ipv6 = True FLAGS.logfile = 'run_tests.err' -# NOTE(vish): pretend like we've loaded flags from command line -flags.FlagValues.initialized = True diff --git a/nova/tests/test_log.py b/nova/tests/test_log.py index ada8d0a56..122351ff6 100644 --- a/nova/tests/test_log.py +++ b/nova/tests/test_log.py @@ -46,14 +46,12 @@ class RootLoggerTestCase(test.TestCase): def test_will_be_verbose_if_verbose_flag_set(self): self.flags(verbose=True) - self.log.initialized = False - log.audit("foo", context=_fake_context()) + log.reset() self.assertEqual(log.DEBUG, self.log.level) def test_will_not_be_verbose_if_verbose_flag_not_set(self): self.flags(verbose=False) - self.log.initialized = False - log.audit("foo", context=_fake_context()) + log.reset() self.assertEqual(log.INFO, self.log.level) -- cgit From a57dffb5fdfbfac59b9ddbe7b33d6f03b7b748ba Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 21 Feb 2011 14:16:42 +0100 Subject: PEP-8 fixes --- nova/tests/test_network.py | 21 +++++++++------------ nova/tests/test_virt.py | 3 ++- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index b28d64245..c9a62a391 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -42,15 +42,14 @@ class IptablesManagerTestCase(test.TestCase): :INPUT ACCEPT [2223527:305688874] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [2172501:140856656] --A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT --A FORWARD -d 192.168.122.0/24 -o virbr0 -m state --state RELATED,ESTABLISHED -j ACCEPT --A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT --A FORWARD -i virbr0 -o virbr0 -j ACCEPT --A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable --A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable +-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT +-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT +-A FORWARD -i virbr0 -o virbr0 -j ACCEPT +-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable +-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Fri Feb 18 15:17:05 2011""" @@ -77,8 +76,7 @@ COMMIT # TODO(soren): Add stuff for ipv6 check_matrix = {4: {'filter': ['INPUT', 'OUTPUT', 'FORWARD'], - 'nat': ['PREROUTING', 'INPUT', - 'OUTPUT', 'POSTROUTING']} } + 'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}} for ip_version in check_matrix: ip = getattr(self.manager, 'ipv%d' % ip_version) @@ -90,7 +88,6 @@ COMMIT (chain,) in new_lines) self.assertTrue('-A %s -j run_tests.py-%s' % \ (chain, chain) in new_lines) - print '\n'.join(new_lines) class NetworkTestCase(test.TestCase): diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index a88e01818..11201788c 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -345,7 +345,8 @@ class IptablesFirewallTestCase(test.TestCase): self.fw.prepare_instance_filter(instance_ref) self.fw.apply_instance_filter(instance_ref) - in_rules = filter(lambda l: not l.startswith('#'), self.in_filter_rules) + in_rules = filter(lambda l: not l.startswith('#'), + self.in_filter_rules) for rule in in_rules: if not 'nova' in rule: self.assertTrue(rule in self.out_rules, -- cgit From 3d2ec0f594e02018a32c8d0d7a8cc46f7ab4c849 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 21 Feb 2011 14:39:02 +0100 Subject: Wrap ipv6 rules, too --- nova/tests/test_network.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index c9a62a391..f1d4fe133 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -76,7 +76,8 @@ COMMIT # TODO(soren): Add stuff for ipv6 check_matrix = {4: {'filter': ['INPUT', 'OUTPUT', 'FORWARD'], - 'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}} + 'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}, + 6: {'filter': ['INPUT', 'OUTPUT', 'FORWARD']}} for ip_version in check_matrix: ip = getattr(self.manager, 'ipv%d' % ip_version) -- cgit From 8b30a903a4d2c5c6ffe44e58b8531ddc889492c0 Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Mon, 21 Feb 2011 13:10:45 -0500 Subject: PEP8 errors and remove check in authors file for nova-core, since nova-core owns the translation export branch --- nova/tests/test_misc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 33c1777d5..7a4d512a4 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -46,6 +46,8 @@ class ProjectTestCase(test.TestCase): missing = set() for contributor in contributors: + if contributor == 'nova-core': + pass if not contributor in authors_file: missing.add(contributor) -- cgit From cf006cce87ce18cdf9d7705fcc2be05b912d4c3f Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Mon, 21 Feb 2011 13:55:25 -0500 Subject: Duh, continue skips iteration, not pass. #iamanidiot --- nova/tests/test_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 7a4d512a4..e6da6112a 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -47,7 +47,7 @@ class ProjectTestCase(test.TestCase): missing = set() for contributor in contributors: if contributor == 'nova-core': - pass + continue if not contributor in authors_file: missing.add(contributor) -- cgit From c7d83e26f7d6388857b4db4538602395b688aa7a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 11:42:46 -0800 Subject: use tests.sqlite so it doesn't conflict with running db --- nova/tests/fake_flags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 59839b090..575fefff6 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -39,6 +39,6 @@ FLAGS.num_shelves = 2 FLAGS.blades_per_shelf = 4 FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True -FLAGS.sql_connection = 'sqlite:///nova.sqlite' +FLAGS.sql_connection = 'sqlite:///tests.sqlite' FLAGS.use_ipv6 = True -FLAGS.logfile = 'run_tests.err' +FLAGS.logfile = 'tests.log' -- cgit From 02e196192ea1f8be22c31828266b177d14d123cd Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 21 Feb 2011 12:41:15 -0800 Subject: make sure that ec2 response times are xs:dateTime parsable --- nova/tests/test_api.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index fa27825cd..d5c54a1c3 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -20,6 +20,7 @@ import boto from boto.ec2 import regioninfo +import datetime import httplib import random import StringIO @@ -127,6 +128,28 @@ class ApiEc2TestCase(test.TestCase): self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) return self.http + def test_return_valid_isoformat(self): + """ + Ensure that the ec2 api returns datetime in xs:dateTime + (which apparently isn't datetime.isoformat()) + NOTE(ken-pepple): https://bugs.launchpad.net/nova/+bug/721297 + """ + conv = apirequest._database_to_isoformat + # sqlite database representation with microseconds + time_to_convert = datetime.datetime.strptime( + "2011-02-21 20:14:10.634276", + "%Y-%m-%d %H:%M:%S.%f") + self.assertEqual( + conv(time_to_convert), + '2011-02-21T20:14:10Z') + # mysqlite database representation + time_to_convert = datetime.datetime.strptime( + "2011-02-21 19:56:18", + "%Y-%m-%d %H:%M:%S") + self.assertEqual( + conv(time_to_convert), + '2011-02-21T19:56:18Z') + def test_xmlns_version_matches_request_version(self): self.expect_http(api_version='2010-10-30') self.mox.ReplayAll() -- cgit From e5d030863eae7f997867350916adf0c721625d26 Mon Sep 17 00:00:00 2001 From: termie Date: Mon, 21 Feb 2011 14:55:06 -0800 Subject: add a test for rpc consumer isolation --- nova/tests/test_test.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 nova/tests/test_test.py (limited to 'nova/tests') diff --git a/nova/tests/test_test.py b/nova/tests/test_test.py new file mode 100644 index 000000000..c1d96a148 --- /dev/null +++ b/nova/tests/test_test.py @@ -0,0 +1,37 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. + +"""Tests for the testing base code.""" + +from nova import rpc +from nova import test + + +class IsolationTestCase(test.TestCase): + """Ensure that things are cleaned up after failed tests. + + These tests don't really do much here, but if isolation fails a bunch + of other tests should fail. + + """ + def test_rpc_consumer_isolation(self): + connection = rpc.Connection.instance(new=True) + consumer = rpc.TopicConsumer(connection, topic='compute') + consumer.register_callback( + lambda x, y: self.fail('I should never be called')) + consumer.attach_to_eventlet() -- cgit From ab73d72d33369d47012437c022a0679fa4ca3b38 Mon Sep 17 00:00:00 2001 From: termie Date: Mon, 21 Feb 2011 14:55:06 -0800 Subject: add a start_service method to our test baseclass --- nova/tests/test_scheduler.py | 100 +++++++------------------------------------ nova/tests/test_test.py | 3 ++ 2 files changed, 19 insertions(+), 84 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 9d458244b..250170072 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -176,18 +176,8 @@ class SimpleDriverTestCase(test.TestCase): def test_doesnt_report_disabled_hosts_as_up(self): """Ensures driver doesn't find hosts before they are enabled""" - # NOTE(vish): constructing service without create method - # because we are going to use it without queue - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() - compute2 = service.Service('host2', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute2.start() + compute1 = self.start_service('compute', host='host1') + compute2 = self.start_service('compute', host='host2') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') s2 = db.service_get_by_args(self.context, 'host2', 'nova-compute') db.service_update(self.context, s1['id'], {'disabled': True}) @@ -199,18 +189,8 @@ class SimpleDriverTestCase(test.TestCase): def test_reports_enabled_hosts_as_up(self): """Ensures driver can find the hosts that are up""" - # NOTE(vish): constructing service without create method - # because we are going to use it without queue - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() - compute2 = service.Service('host2', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute2.start() + compute1 = self.start_service('compute', host='host1') + compute2 = self.start_service('compute', host='host2') hosts = self.scheduler.driver.hosts_up(self.context, 'compute') self.assertEqual(2, len(hosts)) compute1.kill() @@ -218,16 +198,8 @@ class SimpleDriverTestCase(test.TestCase): def test_least_busy_host_gets_instance(self): """Ensures the host with less cores gets the next one""" - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() - compute2 = service.Service('host2', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute2.start() + compute1 = self.start_service('compute', host='host1') + compute2 = self.start_service('compute', host='host2') instance_id1 = self._create_instance() compute1.run_instance(self.context, instance_id1) instance_id2 = self._create_instance() @@ -241,16 +213,8 @@ class SimpleDriverTestCase(test.TestCase): def test_specific_host_gets_instance(self): """Ensures if you set availability_zone it launches on that zone""" - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() - compute2 = service.Service('host2', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute2.start() + compute1 = self.start_service('compute', host='host1') + compute2 = self.start_service('compute', host='host2') instance_id1 = self._create_instance() compute1.run_instance(self.context, instance_id1) instance_id2 = self._create_instance(availability_zone='nova:host1') @@ -263,11 +227,7 @@ class SimpleDriverTestCase(test.TestCase): compute2.kill() def test_wont_sechedule_if_specified_host_is_down(self): - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() + compute1 = self.start_service('compute', host='host1') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') now = datetime.datetime.utcnow() delta = datetime.timedelta(seconds=FLAGS.service_down_time * 2) @@ -282,11 +242,7 @@ class SimpleDriverTestCase(test.TestCase): compute1.kill() def test_will_schedule_on_disabled_host_if_specified(self): - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() + compute1 = self.start_service('compute', host='host1') s1 = db.service_get_by_args(self.context, 'host1', 'nova-compute') db.service_update(self.context, s1['id'], {'disabled': True}) instance_id2 = self._create_instance(availability_zone='nova:host1') @@ -298,16 +254,8 @@ class SimpleDriverTestCase(test.TestCase): def test_too_many_cores(self): """Ensures we don't go over max cores""" - compute1 = service.Service('host1', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute1.start() - compute2 = service.Service('host2', - 'nova-compute', - 'compute', - FLAGS.compute_manager) - compute2.start() + compute1 = self.start_service('compute', host='host1') + compute2 = self.start_service('compute', host='host2') instance_ids1 = [] instance_ids2 = [] for index in xrange(FLAGS.max_cores): @@ -331,16 +279,8 @@ class SimpleDriverTestCase(test.TestCase): def test_least_busy_host_gets_volume(self): """Ensures the host with less gigabytes gets the next one""" - volume1 = service.Service('host1', - 'nova-volume', - 'volume', - FLAGS.volume_manager) - volume1.start() - volume2 = service.Service('host2', - 'nova-volume', - 'volume', - FLAGS.volume_manager) - volume2.start() + volume1 = self.start_service('volume', host='host1') + volume2 = self.start_service('volume', host='host2') volume_id1 = self._create_volume() volume1.create_volume(self.context, volume_id1) volume_id2 = self._create_volume() @@ -354,16 +294,8 @@ class SimpleDriverTestCase(test.TestCase): def test_too_many_gigabytes(self): """Ensures we don't go over max gigabytes""" - volume1 = service.Service('host1', - 'nova-volume', - 'volume', - FLAGS.volume_manager) - volume1.start() - volume2 = service.Service('host2', - 'nova-volume', - 'volume', - FLAGS.volume_manager) - volume2.start() + volume1 = self.start_service('volume', host='host1') + volume2 = self.start_service('volume', host='host2') volume_ids1 = [] volume_ids2 = [] for index in xrange(FLAGS.max_gigabytes): diff --git a/nova/tests/test_test.py b/nova/tests/test_test.py index c1d96a148..e237674e6 100644 --- a/nova/tests/test_test.py +++ b/nova/tests/test_test.py @@ -29,6 +29,9 @@ class IsolationTestCase(test.TestCase): of other tests should fail. """ + def test_service_isolation(self): + self.start_service('compute') + def test_rpc_consumer_isolation(self): connection = rpc.Connection.instance(new=True) consumer = rpc.TopicConsumer(connection, topic='compute') -- cgit From 9003241814ab67817ea910943e932d7b2e542eb6 Mon Sep 17 00:00:00 2001 From: termie Date: Mon, 21 Feb 2011 14:55:06 -0800 Subject: move test_cloud to use start_service, too --- nova/tests/test_cloud.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 445cc6e8b..a174ea75d 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -65,10 +65,8 @@ class CloudTestCase(test.TestCase): self.cloud = cloud.CloudController() # set up services - self.compute = service.Service.create(binary='nova-compute') - self.compute.start() - self.network = service.Service.create(binary='nova-network') - self.network.start() + self.compute = self.start_service('compute') + self.network = self.start_service('network') self.manager = manager.AuthManager() self.user = self.manager.create_user('admin', 'admin', 'admin', True) -- cgit From 4b2a45aa5dc91b24aea53f748906d8a69e40f7c8 Mon Sep 17 00:00:00 2001 From: termie Date: Mon, 21 Feb 2011 15:42:16 -0800 Subject: modify tests to use specific hosts rather than default --- nova/tests/test_cloud.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index a174ea75d..1824d24bc 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -100,7 +100,7 @@ class CloudTestCase(test.TestCase): address = "10.10.10.10" db.floating_ip_create(self.context, {'address': address, - 'host': FLAGS.host}) + 'host': self.network.host}) self.cloud.allocate_address(self.context) self.cloud.describe_addresses(self.context) self.cloud.release_address(self.context, @@ -113,9 +113,9 @@ class CloudTestCase(test.TestCase): address = "10.10.10.10" db.floating_ip_create(self.context, {'address': address, - 'host': FLAGS.host}) + 'host': self.network.host}) self.cloud.allocate_address(self.context) - inst = db.instance_create(self.context, {'host': FLAGS.host}) + inst = db.instance_create(self.context, {'host': self.compute.host}) fixed = self.network.allocate_fixed_ip(self.context, inst['id']) ec2_id = cloud.id_to_ec2_id(inst['id']) self.cloud.associate_address(self.context, -- cgit From 71f7119910f16cb99c10f43a07ccb1e7c0ca473f Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 16:05:28 -0800 Subject: remove changes to test db --- nova/tests/fake_flags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 575fefff6..cfa65c137 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -39,6 +39,6 @@ FLAGS.num_shelves = 2 FLAGS.blades_per_shelf = 4 FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True -FLAGS.sql_connection = 'sqlite:///tests.sqlite' +FLAGS.sql_connection = 'sqlite:///nova.sqlite' FLAGS.use_ipv6 = True FLAGS.logfile = 'tests.log' -- cgit From 0f402b72cbf80d1adde503eb532a578944fa0c79 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 21 Feb 2011 16:22:09 -0800 Subject: update based on prereq branch --- nova/tests/fake_flags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index cfa65c137..575fefff6 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -39,6 +39,6 @@ FLAGS.num_shelves = 2 FLAGS.blades_per_shelf = 4 FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True -FLAGS.sql_connection = 'sqlite:///nova.sqlite' +FLAGS.sql_connection = 'sqlite:///tests.sqlite' FLAGS.use_ipv6 = True FLAGS.logfile = 'tests.log' -- cgit From c53bb1718a9b5900d09637d0ee966dadbf073900 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Feb 2011 09:00:29 +0100 Subject: Address some review comments. --- nova/tests/test_virt.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 11201788c..c2c7c8337 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -354,7 +354,6 @@ class IptablesFirewallTestCase(test.TestCase): instance_chain = None for rule in self.out_rules: - print rule # This is pretty crude, but it'll do for now if '-d 10.11.12.13 -j' in rule: instance_chain = rule.split(' ')[-1] -- cgit From bf37fb0ab5503a077a3d9e4109990d252e27cb15 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Feb 2011 11:29:58 +0100 Subject: Add a bunch of tests for everything. Add a 'head' kwarg to add_rule that lets the rule bubble to the top. This is needed for nova-filter-top to end up at the top. --- nova/tests/test_network.py | 128 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 106 insertions(+), 22 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index f1d4fe133..afd38272d 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -36,12 +36,22 @@ LOG = logging.getLogger('nova.tests.network') class IptablesManagerTestCase(test.TestCase): - sample_filter = """# Completed on Fri Feb 18 15:17:05 2011 -# Generated by iptables-save v1.4.10 on Fri Feb 18 15:17:05 2011 + sample_filter = """# Generated by iptables-save on Fri Feb 18 15:17:05 2011 *filter :INPUT ACCEPT [2223527:305688874] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [2172501:140856656] +:nova-compute-FORWARD - [0:0] +:nova-compute-INPUT - [0:0] +:nova-compute-local - [0:0] +:nova-compute-OUTPUT - [0:0] +:nova-filter-top - [0:0] +-A FORWARD -j nova-filter-top +-A OUTPUT -j nova-filter-top +-A nova-filter-top -j nova-compute-local +-A INPUT -j nova-compute-INPUT +-A OUTPUT -j nova-compute-OUTPUT +-A FORWARD -j nova-compute-FORWARD -A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT -A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT -A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT @@ -53,42 +63,116 @@ class IptablesManagerTestCase(test.TestCase): COMMIT # Completed on Fri Feb 18 15:17:05 2011""" + sample_nat = """# Generated by iptables-save on Fri Feb 18 15:17:05 2011 +*nat +:PREROUTING ACCEPT [3936:762355] +:INPUT ACCEPT [2447:225266] +:OUTPUT ACCEPT [63491:4191863] +:POSTROUTING ACCEPT [63112:4108641] +:nova-compute-OUTPUT - [0:0] +:nova-compute-floating-ip-snat - [0:0] +:nova-compute-SNATTING - [0:0] +:nova-compute-PREROUTING - [0:0] +:nova-compute-POSTROUTING - [0:0] +:nova-postrouting-bottom - [0:0] +-A PREROUTING -j nova-compute-PREROUTING +-A OUTPUT -j nova-compute-OUTPUT +-A POSTROUTING -j nova-compute-POSTROUTING +-A POSTROUTING -j nova-postrouting-bottom +-A nova-postrouting-bottom -j nova-compute-SNATTING +-A nova-compute-SNATTING -j nova-compute-floating-ip-snat +COMMIT +# Completed on Fri Feb 18 15:17:05 2011 +""" + def setUp(self): super(IptablesManagerTestCase, self).setUp() self.manager = linux_net.IptablesManager() - def test_rules_are_wrapped(self): + + def test_filter_rules_are_wrapped(self): current_lines = self.sample_filter.split('\n') table = self.manager.ipv4['filter'] table.add_rule('FORWARD', '-s 1.2.3.4/5 -j DROP') - new_lines = self.manager.modify_rules(current_lines, table) + new_lines = self.manager._modify_rules(current_lines, table) self.assertTrue('-A run_tests.py-FORWARD ' '-s 1.2.3.4/5 -j DROP' in new_lines) table.remove_rule('FORWARD', '-s 1.2.3.4/5 -j DROP') - new_lines = self.manager.modify_rules(current_lines, table) + new_lines = self.manager._modify_rules(current_lines, table) self.assertTrue('-A run_tests.py-FORWARD ' '-s 1.2.3.4/5 -j DROP' not in new_lines) - def test_wrapper_rules_in_place(self): - current_lines = self.sample_filter.split('\n') + def test_nat_rules(self): + current_lines = self.sample_nat.split('\n') + new_lines = self.manager._modify_rules(current_lines, + self.manager.ipv4['nat']) + + for line in [':nova-compute-OUTPUT - [0:0]', + ':nova-compute-floating-ip-snat - [0:0]', + ':nova-compute-SNATTING - [0:0]', + ':nova-compute-PREROUTING - [0:0]', + ':nova-compute-POSTROUTING - [0:0]']: + self.assertTrue(line in new_lines, "One of nova-compute's chains " + "went missing.") + + seen_lines = set() + for line in new_lines: + self.assertTrue(line not in seen_lines, + "Duplicate line: %s" % line) + seen_lines.add(line) - # TODO(soren): Add stuff for ipv6 - check_matrix = {4: {'filter': ['INPUT', 'OUTPUT', 'FORWARD'], - 'nat': ['PREROUTING', 'OUTPUT', 'POSTROUTING']}, - 6: {'filter': ['INPUT', 'OUTPUT', 'FORWARD']}} - - for ip_version in check_matrix: - ip = getattr(self.manager, 'ipv%d' % ip_version) - for table_name in ip: - table = ip[table_name] - new_lines = self.manager.modify_rules(current_lines, table) - for chain in check_matrix[ip_version][table_name]: - self.assertTrue(':run_tests.py-%s - [0:0]' % \ - (chain,) in new_lines) - self.assertTrue('-A %s -j run_tests.py-%s' % \ - (chain, chain) in new_lines) + last_postrouting_line = '' + + for line in new_lines: + if line.startswith('-A POSTROUTING'): + last_postrouting_line = line + + self.assertTrue('-j nova-postrouting-bottom' in last_postrouting_line, + "Last POSTROUTING rule does not jump to " + "nova-postouting-bottom: %s" % last_postrouting_line) + + for chain in ['POSTROUTING', 'PREROUTING', 'OUTPUT']: + self.assertTrue('-A %s -j run_tests.py-%s' \ + % (chain, chain) in new_lines, + "Built-in chain %s not wrapped" % (chain,)) + + + def test_filter_rules(self): + current_lines = self.sample_filter.split('\n') + new_lines = self.manager._modify_rules(current_lines, + self.manager.ipv4['filter']) + + for line in [':nova-compute-FORWARD - [0:0]', + ':nova-compute-INPUT - [0:0]', + ':nova-compute-local - [0:0]', + ':nova-compute-OUTPUT - [0:0]']: + self.assertTrue(line in new_lines, "One of nova-compute's chains" + " went missing.") + + seen_lines = set() + for line in new_lines: + self.assertTrue(line not in seen_lines, + "Duplicate line: %s" % line) + seen_lines.add(line) + + for chain in ['FORWARD', 'OUTPUT']: + for line in new_lines: + if line.startswith('-A %s' % chain): + self.assertTrue('-j nova-filter-top' in line, + "First %s rule does not " + "jump to nova-filter-top" % chain) + break + + self.assertTrue('-A nova-filter-top ' + '-j run_tests.py-local' in new_lines, + "nova-filter-top does not jump to wrapped local chain") + + for chain in ['INPUT', 'OUTPUT', 'FORWARD']: + self.assertTrue('-A %s -j run_tests.py-%s' \ + % (chain, chain) in new_lines, + "Built-in chain %s not wrapped" % (chain,)) class NetworkTestCase(test.TestCase): -- cgit From b5e6601f76d64a96d6c7de5e9acdf5a8cf0fe8e9 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Feb 2011 12:21:29 +0100 Subject: PEP8 adjustments. --- nova/tests/test_network.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index afd38272d..2bdf3709e 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -89,7 +89,6 @@ COMMIT super(IptablesManagerTestCase, self).setUp() self.manager = linux_net.IptablesManager() - def test_filter_rules_are_wrapped(self): current_lines = self.sample_filter.split('\n') @@ -114,8 +113,8 @@ COMMIT ':nova-compute-SNATTING - [0:0]', ':nova-compute-PREROUTING - [0:0]', ':nova-compute-POSTROUTING - [0:0]']: - self.assertTrue(line in new_lines, "One of nova-compute's chains " - "went missing.") + self.assertTrue(line in new_lines, "One of nova-compute's chains " + "went missing.") seen_lines = set() for line in new_lines: @@ -138,7 +137,6 @@ COMMIT % (chain, chain) in new_lines, "Built-in chain %s not wrapped" % (chain,)) - def test_filter_rules(self): current_lines = self.sample_filter.split('\n') new_lines = self.manager._modify_rules(current_lines, @@ -148,8 +146,8 @@ COMMIT ':nova-compute-INPUT - [0:0]', ':nova-compute-local - [0:0]', ':nova-compute-OUTPUT - [0:0]']: - self.assertTrue(line in new_lines, "One of nova-compute's chains" - " went missing.") + self.assertTrue(line in new_lines, "One of nova-compute's chains" + " went missing.") seen_lines = set() for line in new_lines: -- cgit From 443f01ef7d977ba6ff86508b908f66733bdd989e Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Feb 2011 14:32:20 +0100 Subject: Account for the fact that iptables-save outputs rules with a space at the end. Reverse the rule deduplication so that the last one takes precedence. --- nova/tests/test_network.py | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 2bdf3709e..b1d70e323 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -46,20 +46,20 @@ class IptablesManagerTestCase(test.TestCase): :nova-compute-local - [0:0] :nova-compute-OUTPUT - [0:0] :nova-filter-top - [0:0] --A FORWARD -j nova-filter-top --A OUTPUT -j nova-filter-top --A nova-filter-top -j nova-compute-local --A INPUT -j nova-compute-INPUT --A OUTPUT -j nova-compute-OUTPUT --A FORWARD -j nova-compute-FORWARD --A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT --A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT --A FORWARD -i virbr0 -o virbr0 -j ACCEPT --A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable --A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable +-A FORWARD -j nova-filter-top +-A OUTPUT -j nova-filter-top +-A nova-filter-top -j nova-compute-local +-A INPUT -j nova-compute-INPUT +-A OUTPUT -j nova-compute-OUTPUT +-A FORWARD -j nova-compute-FORWARD +-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT +-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT +-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT +-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT +-A FORWARD -i virbr0 -o virbr0 -j ACCEPT +-A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable +-A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable COMMIT # Completed on Fri Feb 18 15:17:05 2011""" @@ -75,12 +75,12 @@ COMMIT :nova-compute-PREROUTING - [0:0] :nova-compute-POSTROUTING - [0:0] :nova-postrouting-bottom - [0:0] --A PREROUTING -j nova-compute-PREROUTING --A OUTPUT -j nova-compute-OUTPUT --A POSTROUTING -j nova-compute-POSTROUTING --A POSTROUTING -j nova-postrouting-bottom --A nova-postrouting-bottom -j nova-compute-SNATTING --A nova-compute-SNATTING -j nova-compute-floating-ip-snat +-A PREROUTING -j nova-compute-PREROUTING +-A OUTPUT -j nova-compute-OUTPUT +-A POSTROUTING -j nova-compute-POSTROUTING +-A POSTROUTING -j nova-postrouting-bottom +-A nova-postrouting-bottom -j nova-compute-SNATTING +-A nova-compute-SNATTING -j nova-compute-floating-ip-snat COMMIT # Completed on Fri Feb 18 15:17:05 2011 """ @@ -118,6 +118,7 @@ COMMIT seen_lines = set() for line in new_lines: + line = line.strip() self.assertTrue(line not in seen_lines, "Duplicate line: %s" % line) seen_lines.add(line) @@ -151,6 +152,7 @@ COMMIT seen_lines = set() for line in new_lines: + line = line.strip() self.assertTrue(line not in seen_lines, "Duplicate line: %s" % line) seen_lines.add(line) -- cgit From 7eee81ee6480a36b179ae26be88ebad9415c4b62 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Feb 2011 14:40:00 +0100 Subject: PEP8 again --- nova/tests/test_network.py | 103 +++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 51 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index b1d70e323..d3a23abf4 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -36,61 +36,62 @@ LOG = logging.getLogger('nova.tests.network') class IptablesManagerTestCase(test.TestCase): - sample_filter = """# Generated by iptables-save on Fri Feb 18 15:17:05 2011 -*filter -:INPUT ACCEPT [2223527:305688874] -:FORWARD ACCEPT [0:0] -:OUTPUT ACCEPT [2172501:140856656] -:nova-compute-FORWARD - [0:0] -:nova-compute-INPUT - [0:0] -:nova-compute-local - [0:0] -:nova-compute-OUTPUT - [0:0] -:nova-filter-top - [0:0] --A FORWARD -j nova-filter-top --A OUTPUT -j nova-filter-top --A nova-filter-top -j nova-compute-local --A INPUT -j nova-compute-INPUT --A OUTPUT -j nova-compute-OUTPUT --A FORWARD -j nova-compute-FORWARD --A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT --A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT --A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT --A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT --A FORWARD -i virbr0 -o virbr0 -j ACCEPT --A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable --A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable -COMMIT -# Completed on Fri Feb 18 15:17:05 2011""" - - sample_nat = """# Generated by iptables-save on Fri Feb 18 15:17:05 2011 -*nat -:PREROUTING ACCEPT [3936:762355] -:INPUT ACCEPT [2447:225266] -:OUTPUT ACCEPT [63491:4191863] -:POSTROUTING ACCEPT [63112:4108641] -:nova-compute-OUTPUT - [0:0] -:nova-compute-floating-ip-snat - [0:0] -:nova-compute-SNATTING - [0:0] -:nova-compute-PREROUTING - [0:0] -:nova-compute-POSTROUTING - [0:0] -:nova-postrouting-bottom - [0:0] --A PREROUTING -j nova-compute-PREROUTING --A OUTPUT -j nova-compute-OUTPUT --A POSTROUTING -j nova-compute-POSTROUTING --A POSTROUTING -j nova-postrouting-bottom --A nova-postrouting-bottom -j nova-compute-SNATTING --A nova-compute-SNATTING -j nova-compute-floating-ip-snat -COMMIT -# Completed on Fri Feb 18 15:17:05 2011 -""" + sample_filter = ['#Generated by iptables-save on Fri Feb 18 15:17:05 2011', + '*filter', + ':INPUT ACCEPT [2223527:305688874]', + ':FORWARD ACCEPT [0:0]', + ':OUTPUT ACCEPT [2172501:140856656]', + ':nova-compute-FORWARD - [0:0]', + ':nova-compute-INPUT - [0:0]', + ':nova-compute-local - [0:0]', + ':nova-compute-OUTPUT - [0:0]', + ':nova-filter-top - [0:0]', + '-A FORWARD -j nova-filter-top ', + '-A OUTPUT -j nova-filter-top ', + '-A nova-filter-top -j nova-compute-local ', + '-A INPUT -j nova-compute-INPUT ', + '-A OUTPUT -j nova-compute-OUTPUT ', + '-A FORWARD -j nova-compute-FORWARD ', + '-A INPUT -i virbr0 -p udp -m udp --dport 53 -j ACCEPT ', + '-A INPUT -i virbr0 -p tcp -m tcp --dport 53 -j ACCEPT ', + '-A INPUT -i virbr0 -p udp -m udp --dport 67 -j ACCEPT ', + '-A INPUT -i virbr0 -p tcp -m tcp --dport 67 -j ACCEPT ', + '-A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT ', + '-A FORWARD -i virbr0 -o virbr0 -j ACCEPT ', + '-A FORWARD -o virbr0 -j REJECT --reject-with ' + 'icmp-port-unreachable ', + '-A FORWARD -i virbr0 -j REJECT --reject-with ' + 'icmp-port-unreachable ', + 'COMMIT', + '# Completed on Fri Feb 18 15:17:05 2011'] + + sample_nat = ['# Generated by iptables-save on Fri Feb 18 15:17:05 2011', + '*nat', + ':PREROUTING ACCEPT [3936:762355]', + ':INPUT ACCEPT [2447:225266]', + ':OUTPUT ACCEPT [63491:4191863]', + ':POSTROUTING ACCEPT [63112:4108641]', + ':nova-compute-OUTPUT - [0:0]', + ':nova-compute-floating-ip-snat - [0:0]', + ':nova-compute-SNATTING - [0:0]', + ':nova-compute-PREROUTING - [0:0]', + ':nova-compute-POSTROUTING - [0:0]', + ':nova-postrouting-bottom - [0:0]', + '-A PREROUTING -j nova-compute-PREROUTING ', + '-A OUTPUT -j nova-compute-OUTPUT ', + '-A POSTROUTING -j nova-compute-POSTROUTING ', + '-A POSTROUTING -j nova-postrouting-bottom ', + '-A nova-postrouting-bottom -j nova-compute-SNATTING ', + '-A nova-compute-SNATTING -j nova-compute-floating-ip-snat ', + 'COMMIT', + '# Completed on Fri Feb 18 15:17:05 2011'] def setUp(self): super(IptablesManagerTestCase, self).setUp() self.manager = linux_net.IptablesManager() def test_filter_rules_are_wrapped(self): - current_lines = self.sample_filter.split('\n') + current_lines = self.sample_filter table = self.manager.ipv4['filter'] table.add_rule('FORWARD', '-s 1.2.3.4/5 -j DROP') @@ -104,7 +105,7 @@ COMMIT '-s 1.2.3.4/5 -j DROP' not in new_lines) def test_nat_rules(self): - current_lines = self.sample_nat.split('\n') + current_lines = self.sample_nat new_lines = self.manager._modify_rules(current_lines, self.manager.ipv4['nat']) @@ -139,7 +140,7 @@ COMMIT "Built-in chain %s not wrapped" % (chain,)) def test_filter_rules(self): - current_lines = self.sample_filter.split('\n') + current_lines = self.sample_filter new_lines = self.manager._modify_rules(current_lines, self.manager.ipv4['filter']) -- cgit From c32e57999be09368b18f5a89315465e629ed4819 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Tue, 22 Feb 2011 23:55:03 +0900 Subject: Fixed based on reviewer's comment. 1. Change docstrings format 2. Fix comment grammer mistake, etc --- nova/tests/test_compute.py | 77 +++-------- nova/tests/test_scheduler.py | 141 ++++++++------------ nova/tests/test_service.py | 6 +- nova/tests/test_virt.py | 309 ++++++++++++++++++------------------------- 4 files changed, 206 insertions(+), 327 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 74cb82eeb..3c88d186d 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -314,10 +314,7 @@ class ComputeTestCase(test.TestCase): self.compute_driver = utils.import_object(FLAGS.compute_driver) def test_pre_live_migration_instance_has_no_fixed_ip(self): - """ - if instances that are intended to be migrated doesnt have fixed_ip - (not happens usually), pre_live_migration has to raise Exception. - """ + """Confirm raising exception if instance doesn't have fixed_ip.""" instance_ref = self._get_dummy_instance() c = context.get_admin_context() i_id = instance_ref['id'] @@ -331,14 +328,9 @@ class ComputeTestCase(test.TestCase): self.assertRaises(exception.NotFound, self.compute.pre_live_migration, c, instance_ref['id']) - self.mox.ResetAll() def test_pre_live_migration_instance_has_volume(self): - """if any volumes are attached to the instances that are - intended to be migrated, setup_compute_volume must be - called because aoe module should be inserted at destination - host. This testcase checks on it. - """ + """Confirm setup_compute_volume is called when volume is mounted.""" i_ref = self._get_dummy_instance() c = context.get_admin_context() @@ -364,14 +356,9 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() ret = self.compute.pre_live_migration(c, i_ref['id']) self.assertEqual(ret, None) - self.mox.ResetAll() def test_pre_live_migration_instance_has_no_volume(self): - """if any volumes are not attached to the instances that are - intended to be migrated, log message should be appears - because administrator can proove instance conditions before - live_migration if any trouble occurs. - """ + """Confirm log meg when instance doesn't mount any volumes.""" i_ref = self._get_dummy_instance() i_ref.__setitem__('volumes', []) c = context.get_admin_context() @@ -395,14 +382,14 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() ret = self.compute.pre_live_migration(c, i_ref['id']) self.assertEqual(ret, None) - self.mox.ResetAll() def test_pre_live_migration_setup_compute_node_fail(self): - """setup_compute_node sometimes fail since concurrent request - comes to iptables and iptables complains. Then this method - tries to retry, but raise exception in case of over - max_retry_count. this method confirms raising exception. + """Confirm operation setup_compute_network() fails. + + It retries and raise exception when timeout exceeded. + """ + i_ref = self._get_dummy_instance() c = context.get_admin_context() @@ -427,14 +414,9 @@ class ComputeTestCase(test.TestCase): self.assertRaises(exception.ProcessExecutionError, self.compute.pre_live_migration, c, i_ref['id']) - self.mox.ResetAll() - def test_live_migration_instance_has_volume(self): - """Any volumes are mounted by instances to be migrated are found, - vblade health must be checked before starting live-migration. - And that is checked by check_for_export(). - This testcase confirms check_for_export() is called. - """ + def test_live_migration_works_correctly_with_volume(self): + """Confirm check_for_export to confirm volume health check.""" i_ref = self._get_dummy_instance() c = context.get_admin_context() topic = db.queue_get_for(c, FLAGS.compute_topic, i_ref['host']) @@ -457,15 +439,9 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() ret = self.compute.live_migration(c, i_ref['id'], i_ref['host']) self.assertEqual(ret, None) - self.mox.ResetAll() - - def test_live_migration_instance_has_volume_and_exception(self): - """In addition to test_live_migration_instance_has_volume testcase, - this testcase confirms if any exception raises from - check_for_export(). Then, valid seaquence of this method should - recovering instance/volumes status(ex. instance['state_description'] - is changed from 'migrating' -> 'running', was changed by scheduler) - """ + + def test_live_migration_dest_raises_exception(self): + """Confirm exception when pre_live_migration fails.""" i_ref = self._get_dummy_instance() c = context.get_admin_context() topic = db.queue_get_for(c, FLAGS.compute_topic, i_ref['host']) @@ -484,20 +460,16 @@ class ComputeTestCase(test.TestCase): 'state': power_state.RUNNING, 'host': i_ref['host']}) for v in i_ref['volumes']: - dbmock.volume_update(c, v['id'], {'status': 'in-use', - 'host': i_ref['host']}) + dbmock.volume_update(c, v['id'], {'status': 'in-use'}) self.compute.db = dbmock self.mox.ReplayAll() self.assertRaises(rpc.RemoteError, self.compute.live_migration, c, i_ref['id'], i_ref['host']) - self.mox.ResetAll() - def test_live_migration_instance_has_no_volume_and_exception(self): - """Simpler than - test_live_migration_instance_has_volume_and_exception - """ + def test_live_migration_dest_raises_exception_no_volume(self): + """Same as above test(input pattern is different) """ i_ref = self._get_dummy_instance() i_ref.__setitem__('volumes', []) c = context.get_admin_context() @@ -520,10 +492,9 @@ class ComputeTestCase(test.TestCase): self.assertRaises(rpc.RemoteError, self.compute.live_migration, c, i_ref['id'], i_ref['host']) - self.mox.ResetAll() - def test_live_migration_instance_has_no_volume(self): - """Simpler than test_live_migration_instance_has_volume.""" + def test_live_migration_works_correctly_no_volume(self): + """Confirm live_migration() works as expected correctly.""" i_ref = self._get_dummy_instance() i_ref.__setitem__('volumes', []) c = context.get_admin_context() @@ -545,11 +516,9 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() ret = self.compute.live_migration(c, i_ref['id'], i_ref['host']) self.assertEqual(ret, None) - self.mox.ResetAll() def test_post_live_migration_working_correctly(self): - """post_live_migration works as expected correctly """ - + """Confirm post_live_migration() works as expected correctly.""" dest = 'desthost' flo_addr = '1.2.1.2' @@ -579,19 +548,15 @@ class ComputeTestCase(test.TestCase): # executing self.mox.ReplayAll() ret = self.compute.post_live_migration(c, i_ref, dest) - self.mox.UnsetStubs() # make sure every data is rewritten to dest i_ref = db.instance_get(c, i_ref['id']) c1 = (i_ref['host'] == dest) - v_ref = db.volume_get(c, v_ref['id']) - c2 = (v_ref['host'] == dest) - c3 = False flo_refs = db.floating_ip_get_all_by_host(c, dest) - c3 = (len(flo_refs) != 0 and flo_refs[0]['address'] == flo_addr) + c2 = (len(flo_refs) != 0 and flo_refs[0]['address'] == flo_addr) # post operaton - self.assertTrue(c1 and c2 and c3) + self.assertTrue(c1 and c2) db.instance_destroy(c, instance_id) db.volume_destroy(c, v_ref['id']) db.floating_ip_destroy(c, flo_addr) diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 729bcb580..301106848 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -108,22 +108,21 @@ class SchedulerTestCase(test.TestCase): self.mox.ReplayAll() scheduler.named_method(ctxt, 'topic', num=7) - def test_show_host_resource_host_not_exit(self): - """ - A testcase of driver.has_enough_resource - given host does not exists. - """ + def test_show_host_resources_host_not_exit(self): + """A host given as an argument does not exists.""" + scheduler = manager.SchedulerManager() dest = 'dummydest' ctxt = context.get_admin_context() try: - scheduler.show_host_resource(ctxt, dest) + scheduler.show_host_resources(ctxt, dest) except exception.NotFound, e: c1 = (0 <= e.message.find('does not exist or not compute node')) self.assertTrue(c1) def _dic_is_equal(self, dic1, dic2, keys=None): + """Compares 2 dictionary contents(Helper method)""" if not keys: keys = ['vcpus', 'memory_mb', 'local_gb', 'vcpus_used', 'memory_mb_used', 'local_gb_used'] @@ -133,16 +132,14 @@ class SchedulerTestCase(test.TestCase): return False return True - def test_show_host_resource_no_project(self): - """ - A testcase of driver.show_host_resource - no instance stays on the given host - """ + def test_show_host_resources_no_project(self): + """No instance are running on the given host.""" + scheduler = manager.SchedulerManager() ctxt = context.get_admin_context() s_ref = self._create_compute_service() - result = scheduler.show_host_resource(ctxt, s_ref['host']) + result = scheduler.show_host_resources(ctxt, s_ref['host']) # result checking c1 = ('resource' in result and 'usage' in result) @@ -152,11 +149,9 @@ class SchedulerTestCase(test.TestCase): self.assertTrue(c1 and c2 and c3) db.service_destroy(ctxt, s_ref['id']) - def test_show_host_resource_works_correctly(self): - """ - A testcase of driver.show_host_resource - to make sure everything finished with no error. - """ + def test_show_host_resources_works_correctly(self): + """show_host_resources() works correctly as expected.""" + scheduler = manager.SchedulerManager() ctxt = context.get_admin_context() s_ref = self._create_compute_service() @@ -164,7 +159,7 @@ class SchedulerTestCase(test.TestCase): i_ref2 = self._create_instance(project_id='p-02', vcpus=3, host=s_ref['host']) - result = scheduler.show_host_resource(ctxt, s_ref['host']) + result = scheduler.show_host_resources(ctxt, s_ref['host']) c1 = ('resource' in result and 'usage' in result) compute_service = s_ref['compute_service'][0] @@ -284,6 +279,7 @@ class SimpleDriverTestCase(test.TestCase): return db.volume_create(self.context, vol)['id'] def _create_compute_service(self, **kwargs): + """Create a compute service.""" dic = {'binary': 'nova-compute', 'topic': 'compute', 'report_count': 0, 'availability_zone': 'dummyzone'} @@ -698,13 +694,13 @@ class SimpleDriverTestCase(test.TestCase): volume1.kill() volume2.kill() - def test_scheduler_live_migraiton_with_volume(self): - """ - driver.scheduler_live_migration finishes successfully - (volumes are attached to instances) - This testcase make sure schedule_live_migration - changes instance state from 'running' -> 'migrating' + def test_scheduler_live_migration_with_volume(self): + """scheduler_live_migration() works correctly as expected. + + Also, checks instance state is changed from 'running' -> 'migrating'. + """ + instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) dic = {'instance_id': instance_id, 'size': 1} @@ -737,11 +733,9 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.volume_destroy(self.context, v_ref['id']) - def test_live_migraiton_src_check_instance_not_running(self): - """ - A testcase of driver._live_migration_src_check. - The instance given by instance_id is not running. - """ + def test_live_migration_src_check_instance_not_running(self): + """The instance given by instance_id is not running.""" + instance_id = self._create_instance(state_description='migrating') i_ref = db.instance_get(self.context, instance_id) @@ -754,12 +748,9 @@ class SimpleDriverTestCase(test.TestCase): self.assertTrue(c) db.instance_destroy(self.context, instance_id) - def test_live_migraiton_src_check_volume_node_not_alive(self): - """ - A testcase of driver._live_migration_src_check. - Volume node is not alive if any volumes are attached to - the given instance. - """ + def test_live_migration_src_check_volume_node_not_alive(self): + """Raise exception when volume node is not alive.""" + instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) dic = {'instance_id': instance_id, 'size': 1} @@ -782,11 +773,8 @@ class SimpleDriverTestCase(test.TestCase): db.service_destroy(self.context, s_ref['id']) db.volume_destroy(self.context, v_ref['id']) - def test_live_migraiton_src_check_compute_node_not_alive(self): - """ - A testcase of driver._live_migration_src_check. - The testcase make sure src-compute node is alive. - """ + def test_live_migration_src_check_compute_node_not_alive(self): + """Confirms src-compute node is alive.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) t = datetime.datetime.utcnow() - datetime.timedelta(10) @@ -803,11 +791,8 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_src_check_works_correctly(self): - """ - A testcase of driver._live_migration_src_check. - The testcase make sure everything finished with no error. - """ + def test_live_migration_src_check_works_correctly(self): + """Confirms this method finishes with no error.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) s_ref = self._create_compute_service(host=i_ref['host']) @@ -819,11 +804,8 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_dest_check_not_alive(self): - """ - A testcase of driver._live_migration_dst_check. - Destination host does not exist. - """ + def test_live_migration_dest_check_not_alive(self): + """Confirms exception raises in case dest host does not exist.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) t = datetime.datetime.utcnow() - datetime.timedelta(10) @@ -841,11 +823,8 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_dest_check_service_same_host(self): - """ - A testcase of driver._live_migration_dst_check. - Destination host is same as src host. - """ + def test_live_migration_dest_check_service_same_host(self): + """Confirms exceptioin raises in case dest and src is same host.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) s_ref = self._create_compute_service(host=i_ref['host']) @@ -861,11 +840,8 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_dest_check_service_lack_memory(self): - """ - A testcase of driver._live_migration_dst_check. - destination host doesnt have enough memory. - """ + def test_live_migration_dest_check_service_lack_memory(self): + """Confirms exception raises when dest doesn't have enough memory.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) s_ref = self._create_compute_service(host='somewhere', @@ -882,11 +858,8 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_dest_check_service_works_correctly(self): - """ - A testcase of driver._live_migration_dst_check. - The testcase make sure everything finished with no error. - """ + def test_live_migration_dest_check_service_works_correctly(self): + """Confirms method finishes with no error.""" instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) s_ref = self._create_compute_service(host='somewhere', @@ -899,13 +872,11 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_common_check_service_orig_not_exists(self): - """ - A testcase of driver._live_migration_common_check. - Destination host does not exist. - """ + def test_live_migration_common_check_service_orig_not_exists(self): + """Destination host does not exist.""" + dest = 'dummydest' - # mocks for live_migraiton_common_check() + # mocks for live_migration_common_check() instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) t1 = datetime.datetime.utcnow() - datetime.timedelta(10) @@ -929,18 +900,15 @@ class SimpleDriverTestCase(test.TestCase): i_ref, dest) except exception.Invalid, e: - c = (e.message.find('does not exists') >= 0) + c = (e.message.find('does not exist') >= 0) self.assertTrue(c) self.mox.UnsetStubs() db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) - def test_live_migraiton_common_check_service_different_hypervisor(self): - """ - A testcase of driver._live_migration_common_check. - Original host and dest host has different hypervisor type. - """ + def test_live_migration_common_check_service_different_hypervisor(self): + """Original host and dest host has different hypervisor type.""" dest = 'dummydest' instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) @@ -969,11 +937,8 @@ class SimpleDriverTestCase(test.TestCase): db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) - def test_live_migraiton_common_check_service_different_version(self): - """ - A testcase of driver._live_migration_common_check. - Original host and dest host has different hypervisor version. - """ + def test_live_migration_common_check_service_different_version(self): + """Original host and dest host has different hypervisor version.""" dest = 'dummydest' instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) @@ -1003,11 +968,9 @@ class SimpleDriverTestCase(test.TestCase): db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) - def test_live_migraiton_common_check_service_checking_cpuinfo_fail(self): - """ - A testcase of driver._live_migration_common_check. - Original host and dest host has different hypervisor version. - """ + def test_live_migration_common_check_checking_cpuinfo_fail(self): + """Raise excetion when original host doen't have compatible cpu.""" + dest = 'dummydest' instance_id = self._create_instance() i_ref = db.instance_get(self.context, instance_id) @@ -1025,7 +988,7 @@ class SimpleDriverTestCase(test.TestCase): rpc.call(mox.IgnoreArg(), mox.IgnoreArg(), {"method": 'compare_cpu', "args": {'cpu_info': s_ref2['compute_service'][0]['cpu_info']}}).\ - AndRaise(rpc.RemoteError('doesnt have compatibility to', '', '')) + AndRaise(rpc.RemoteError("doesn't have compatibility to", "", "")) self.mox.ReplayAll() try: @@ -1033,7 +996,7 @@ class SimpleDriverTestCase(test.TestCase): i_ref, dest) except rpc.RemoteError, e: - c = (e.message.find(_('doesnt have compatibility to')) >= 0) + c = (e.message.find(_("doesn't have compatibility to")) >= 0) self.assertTrue(c) self.mox.UnsetStubs() diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index cb65584cf..bbd5c6d92 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -279,11 +279,7 @@ class ServiceTestCase(test.TestCase): self.assert_(not serv.model_disconnected) def test_compute_can_update_available_resource(self): - """ - Test nova-compute successfully updated Service table on DB. - Doing so, self.manager.update_service must be called - if 'self.binary == nova-compute', and this testcase checks on it. - """ + """Confirm compute updates their record of compute-service table.""" host = 'foo' binary = 'nova-compute' topic = 'compute1' diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 8ed726c21..91bdfcc5a 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -23,8 +23,8 @@ from nova import context from nova import db from nova import exception from nova import flags -from nova import test from nova import logging +from nova import test from nova import utils from nova.api.ec2 import cloud from nova.auth import manager @@ -76,12 +76,12 @@ class LibvirtConnTestCase(test.TestCase): 'bridge': 'br101', 'instance_type': 'm1.small'} - def _driver_dependent_test_setup(self): - """ - Setup method. - Call this method at the top of each testcase method, - if the testcase is necessary libvirt and cheetah. - """ + def _driver_dependant_test_setup(self): + """Call this method at the top of each testcase method. + + Checks if libvirt and cheetah, etc is installed. + Otherwise, skip testing.""" + try: global libvirt global libxml2 @@ -92,10 +92,9 @@ class LibvirtConnTestCase(test.TestCase): except ImportError, e: logging.warn("""This test has not been done since """ """using driver-dependent library Cheetah/libvirt/libxml2.""") - raise e + raise # inebitable mocks for calling - #nova.virt.libvirt_conn.LibvirtConnection.__init__ obj = utils.import_object(FLAGS.firewall_driver) fwmock = self.mox.CreateMock(obj) self.mox.StubOutWithMock(libvirt_conn, 'utils', @@ -258,51 +257,31 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) def test_get_vcpu_total(self): - """ - Check if get_vcpu_total returns appropriate cpu value - Connection/OS/driver differenct does not matter for this method, - everyone can execute for checking. - """ + """Check if get_vcpu_total returns appropriate cpu value.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(0 < conn.get_vcpu_total()) - self.mox.UnsetStubs() def test_get_memory_mb_total(self): - """Check if get_memory_mb returns appropriate memory value""" + """Check if get_memory_mb returns appropriate memory value.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(0 < conn.get_memory_mb_total()) - self.mox.UnsetStubs() - - def test_get_local_gb_total(self): - """Check if get_local_gb_total returns appropriate disk value""" - # Note(masumotok): leave this b/c FLAGS.instances_path is inevitable.. - #try: - # self._driver_dependent_test_setup() - #except: - # return - # - #self.mox.ReplayAll() - #conn = libvirt_conn.LibvirtConnection(False) - #self.assertTrue(0 < conn.get_local_gb_total()) - #self.mox.UnsetStubs() - pass def test_get_vcpu_used(self): - """Check if get_local_gb_total returns appropriate disk value""" + """Check if get_local_gb_total returns appropriate disk value.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -321,52 +300,45 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(conn.get_vcpu_used() == 4) - self.mox.UnsetStubs() def test_get_memory_mb_used(self): - """Check if get_memory_mb returns appropriate memory value""" + """Check if get_memory_mb returns appropriate memory value.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(0 < conn.get_memory_mb_used()) - self.mox.UnsetStubs() - - def test_get_local_gb_used(self): - """Check if get_local_gb_total returns appropriate disk value""" - # Note(masumotok): leave this b/c FLAGS.instances_path is inevitable - #try: - # self._driver_dependent_test_setup() - #except: - # return - - #self.mox.ReplayAll() - #conn = libvirt_conn.LibvirtConnection(False) - #self.assertTrue(0 < conn.get_local_gb_used()) - #self.mox.UnsetStubs() - pass def test_get_cpu_info_works_correctly(self): - """ - Check if get_cpu_info works correctly. - (in case libvirt.getCapabilities() works correctly) - """ - xml = ("""x86_64Nehalem""" - """Intel""" - """""" - """""" - """""" - """""" - """""" - """""" - """""") + """Check if get_cpu_info works correctly as expected.""" + xml = """ + x86_64 + Nehalem + Intel + + + + + + + + + + + + + + + + + + """ try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, @@ -376,27 +348,34 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(0 < len(conn.get_cpu_info())) - self.mox.UnsetStubs() def test_get_cpu_info_inappropreate_xml(self): - """ - Check if get_cpu_info raises exception - in case libvirt.getCapabilities() returns wrong xml - (in case of xml doesnt have tag) - """ - xml = ("""x86_64Nehalem""" - """Intel""" - """""" - """""" - """""" - """""" - """""" - """""" - """""") + """Raise exception if given xml is inappropriate.""" + xml = """ + x86_64 + Nehalem + Intel + + + + + + + + + + + + + + + + + + """ try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, @@ -409,29 +388,34 @@ class LibvirtConnTestCase(test.TestCase): conn.get_cpu_info() except exception.Invalid, e: c1 = (0 <= e.message.find('Invalid xml')) - self.assertTrue(c1) - self.mox.UnsetStubs() + self.assertTrue(c1) def test_get_cpu_info_inappropreate_xml2(self): - """ - Check if get_cpu_info raises exception - in case libvirt.getCapabilities() returns wrong xml - (in case of xml doesnt have inproper tag - meaning missing "socket" attribute) - """ - xml = ("""x86_64Nehalem""" - """Intel""" - """""" - """""" - """""" - """""" - """""" - """""" - """""") - + """Raise exception if given xml is inappropriate(topology tag).""" + + xml = """ + x86_64 + Nehalem + Intel + + + + + + + + + + + + + + + + + """ try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, @@ -444,29 +428,12 @@ class LibvirtConnTestCase(test.TestCase): conn.get_cpu_info() except exception.Invalid, e: c1 = (0 <= e.message.find('Invalid xml: topology')) - self.assertTrue(c1) - self.mox.UnsetStubs() + self.assertTrue(c1) def test_update_available_resource_works_correctly(self): - """ - In this method, vcpus/memory_mb/local_gb/vcpu_used/ - memory_mb_used/local_gb_used/hypervisor_type/ - hypervisor_version/cpu_info should be changed. - Based on this specification, this testcase confirms - if this method finishes successfully, - meaning self.db.service_update must be called with dictinary - - {'vcpu':aaa, 'memory_mb':bbb, 'local_gb':ccc, - 'vcpu_used':aaa, 'memory_mb_used':bbb, 'local_gb_sed':ccc, - 'hypervisor_type':ddd, 'hypervisor_version':eee, - 'cpu_info':fff} - - Since each value of above dict can be obtained through - driver(different depends on environment), - only dictionary keys are checked. - """ + """Confirm compute_service table is updated successfully.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -478,7 +445,9 @@ class LibvirtConnTestCase(test.TestCase): host = 'foo' binary = 'nova-compute' - service_ref = {'id': 1, 'host': host, 'binary': binary, + service_ref = {'id': 1, + 'host': host, + 'binary': binary, 'topic': 'compute'} self.mox.StubOutWithMock(db, 'service_get_all_by_topic') @@ -491,15 +460,11 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) conn.update_available_resource(host) - self.mox.UnsetStubs() def test_update_resource_info_raise_exception(self): - """ - This testcase confirms if no record found on Service - table, exception can be raised. - """ + """Raise exception if no recorde found on services table.""" try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -518,18 +483,19 @@ class LibvirtConnTestCase(test.TestCase): msg = 'Cannot insert compute manager specific info' c1 = (0 <= e.message.find(msg)) self.assertTrue(c1) - self.mox.ResetAll() def test_compare_cpu_works_correctly(self): - """Calling libvirt.compute_cpu() and works correctly """ - - t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ - """"topology":{"cores":"%s", "threads":"%s", """ - """"sockets":"%s"}, "features":[%s]}""") - cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + """Calling libvirt.compute_cpu() and works correctly.""" + t = {} + t['arch'] = 'x86' + t['model'] = 'model' + t['vendor'] = 'Intel' + t['topology'] = {'cores': "2", "threads": "1", "sockets": "4"} + t['features'] = ["tm"] + cpu_info = utils.dumps(t) try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -542,20 +508,19 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertTrue(None == conn.compare_cpu(cpu_info)) - self.mox.UnsetStubs() def test_compare_cpu_raises_exception(self): - """ - Libvirt-related exception occurs when calling - libvirt.compare_cpu(). - """ - t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ - """"topology":{"cores":"%s", "threads":"%s", """ - """"sockets":"%s"}, "features":[%s]}""") - cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + """Libvirt-related exception occurs when calling compare_cpu().""" + t = {} + t['arch'] = 'x86' + t['model'] = 'model' + t['vendor'] = 'Intel' + t['topology'] = {'cores': "2", "threads": "1", "sockets": "4"} + t['features'] = ["tm"] + cpu_info = utils.dumps(t) try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -567,18 +532,19 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertRaises(libvirt.libvirtError, conn.compare_cpu, cpu_info) - self.mox.UnsetStubs() def test_compare_cpu_no_compatibility(self): - """libvirt.compare_cpu() return less than 0.(no compatibility)""" - - t = ("""{"arch":"%s", "model":"%s", "vendor":"%s", """ - """"topology":{"cores":"%s", "threads":"%s", """ - """"sockets":"%s"}, "features":[%s]}""") - cpu_info = t % ('x86', 'model', 'vendor', '2', '1', '4', '"tm"') + """Libvirt.compare_cpu() return less than 0.(no compatibility).""" + t = {} + t['arch'] = 'x86' + t['model'] = 'model' + t['vendor'] = 'Intel' + t['topology'] = {'cores': "2", "threads": "1", "sockets": "4"} + t['features'] = ["tm"] + cpu_info = utils.dumps(t) try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -590,16 +556,14 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) self.assertRaises(exception.Invalid, conn.compare_cpu, cpu_info) - self.mox.UnsetStubs() def test_ensure_filtering_rules_for_instance_works_correctly(self): - """ensure_filtering_rules_for_instance works as expected correctly""" - + """ensure_filtering_rules_for_instance() works successfully.""" instance_ref = models.Instance() instance_ref.__setitem__('id', 1) try: - nwmock, fwmock = self._driver_dependent_test_setup() + nwmock, fwmock = self._driver_dependant_test_setup() except: return @@ -613,16 +577,14 @@ class LibvirtConnTestCase(test.TestCase): self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) conn.ensure_filtering_rules_for_instance(instance_ref) - self.mox.UnsetStubs() def test_ensure_filtering_rules_for_instance_timeout(self): - """ensure_filtering_fules_for_instance finishes with timeout""" - + """ensure_filtering_fules_for_instance() finishes with timeout.""" instance_ref = models.Instance() instance_ref.__setitem__('id', 1) try: - nwmock, fwmock = self._driver_dependent_test_setup() + nwmock, fwmock = self._driver_dependant_test_setup() except: return @@ -642,11 +604,9 @@ class LibvirtConnTestCase(test.TestCase): except exception.Error, e: c1 = (0 <= e.message.find('Timeout migrating for')) self.assertTrue(c1) - self.mox.UnsetStubs() def test_live_migration_works_correctly(self): - """_live_migration works as expected correctly """ - + """_live_migration() works as expected correctly.""" class dummyCall(object): f = None @@ -659,7 +619,7 @@ class LibvirtConnTestCase(test.TestCase): ctxt = context.get_admin_context() try: - self._driver_dependent_test_setup() + self._driver_dependant_test_setup() except: return @@ -681,13 +641,9 @@ class LibvirtConnTestCase(test.TestCase): # Not setting post_method/recover_method in this testcase. ret = conn._live_migration(ctxt, i_ref, i_ref['host'], '', '') self.assertTrue(ret == None) - self.mox.UnsetStubs() def test_live_migration_raises_exception(self): - """ - _live_migration raises exception, then this testcase confirms - recovered method is called. - """ + """Confirms recover method is called when exceptions are raised.""" i_ref = models.Instance() i_ref.__setitem__('id', 1) i_ref.__setitem__('host', 'dummy') @@ -697,7 +653,7 @@ class LibvirtConnTestCase(test.TestCase): pass try: - nwmock, fwmock = self._driver_dependent_test_setup() + nwmock, fwmock = self._driver_dependant_test_setup() except: return @@ -724,7 +680,6 @@ class LibvirtConnTestCase(test.TestCase): conn._mlive_migration, ctxt, instance_ref, dest, '', dummy_recover_method) - self.mox.UnsetStubs() def tearDown(self): super(LibvirtConnTestCase, self).tearDown() -- cgit From c6b2d07f47004576fa386a6d270203b1d7937664 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Wed, 23 Feb 2011 00:15:39 +0900 Subject: Fix tiny mitakes! (remove unnecessary comment, etc) --- nova/tests/test_scheduler.py | 2 +- nova/tests/test_volume.py | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 301106848..47a6d0e82 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -258,10 +258,10 @@ class SimpleDriverTestCase(test.TestCase): inst['project_id'] = self.project.id inst['instance_type'] = 'm1.tiny' inst['mac_address'] = utils.generate_mac() + inst['vcpus'] = kwargs.get('vcpus', 1) inst['ami_launch_index'] = 0 inst['availability_zone'] = kwargs.get('availability_zone', None) inst['host'] = kwargs.get('host', 'dummy') - inst['vcpus'] = kwargs.get('vcpus', 4) inst['memory_mb'] = kwargs.get('memory_mb', 20) inst['local_gb'] = kwargs.get('local_gb', 30) inst['launched_on'] = kwargs.get('launghed_on', 'dummy') diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index 6ae075caa..e8b4ceee8 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -318,9 +318,6 @@ class ISCSITestCase(DriverTestCase): mountpoint = "/dev/sd" + chr((ord('b') + index)) db.volume_attached(self.context, vol_ref['id'], self.instance_id, mountpoint) - #iscsi_target = db.volume_allocate_iscsi_target(self.context, - # vol_ref['id'], - # vol_ref['host']) volume_id_list.append(vol_ref['id']) return volume_id_list -- cgit From 485a6c5a9502679bc5ecf02f8e758170ac0335dc Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Wed, 23 Feb 2011 01:20:39 +0900 Subject: Fixed some docstring --- nova/tests/test_scheduler.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 47a6d0e82..71e524bca 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -60,6 +60,7 @@ class SchedulerTestCase(test.TestCase): self.flags(scheduler_driver='nova.tests.test_scheduler.TestDriver') def _create_compute_service(self): + """Create compute-manager(ComputeService and Service record).""" ctxt = context.get_admin_context() dic = {'host': 'dummy', 'binary': 'nova-compute', 'topic': 'compute', 'report_count': 0, 'availability_zone': 'dummyzone'} @@ -150,7 +151,7 @@ class SchedulerTestCase(test.TestCase): db.service_destroy(ctxt, s_ref['id']) def test_show_host_resources_works_correctly(self): - """show_host_resources() works correctly as expected.""" + """Show_host_resources() works correctly as expected.""" scheduler = manager.SchedulerManager() ctxt = context.get_admin_context() -- cgit From 18793c2e184713d33bc93306d464cf443584ffd6 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 22 Feb 2011 17:44:07 -0800 Subject: test that shows error on filtering groups --- nova/tests/test_cloud.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 445cc6e8b..2bce64353 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -133,6 +133,20 @@ class CloudTestCase(test.TestCase): db.instance_destroy(self.context, inst['id']) db.floating_ip_destroy(self.context, address) + def test_describe_security_groups(self): + """Makes sure describe_security_groups works and filters results.""" + sec = db.security_group_create(self.context, {'name': 'test'}) + result = self.cloud.describe_security_groups(self.context) + # NOTE(vish): should have the default group as well + self.assertEqual(len(result['securityGroupInfo']), 2) + result = self.cloud.describe_security_groups(self.context, + group_name=[sec['name']]) + self.assertEqual(len(result['securityGroupInfo']), 1) + self.assertEqual( + cloud.ec2_id_to_id(result['securityGroupInfo'][0]['name']), + sec['name']) + db.security_group_destroy(self.context, sec['id']) + def test_describe_volumes(self): """Makes sure describe_volumes works and filters results.""" vol1 = db.volume_create(self.context, {}) @@ -286,19 +300,6 @@ class CloudTestCase(test.TestCase): LOG.debug(_("Terminating instance %s"), instance_id) rv = self.compute.terminate_instance(instance_id) - def test_describe_instances(self): - """Makes sure describe_instances works.""" - instance1 = db.instance_create(self.context, {'host': 'host2'}) - comp1 = db.service_create(self.context, {'host': 'host2', - 'availability_zone': 'zone1', - 'topic': "compute"}) - result = self.cloud.describe_instances(self.context) - self.assertEqual(result['reservationSet'][0] - ['instancesSet'][0] - ['placement']['availabilityZone'], 'zone1') - db.instance_destroy(self.context, instance1['id']) - db.service_destroy(self.context, comp1['id']) - def test_instance_update_state(self): # TODO(termie): what is this code even testing? def instance(num): -- cgit From 2610a522d26351686612058a6da0300bce731112 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 22 Feb 2011 17:49:38 -0800 Subject: fix test --- nova/tests/test_cloud.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 2bce64353..afdbb80a9 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -135,7 +135,9 @@ class CloudTestCase(test.TestCase): def test_describe_security_groups(self): """Makes sure describe_security_groups works and filters results.""" - sec = db.security_group_create(self.context, {'name': 'test'}) + sec = db.security_group_create(self.context, + {'project_id': self.context.project_id, + 'name': 'test'}) result = self.cloud.describe_security_groups(self.context) # NOTE(vish): should have the default group as well self.assertEqual(len(result['securityGroupInfo']), 2) @@ -143,7 +145,7 @@ class CloudTestCase(test.TestCase): group_name=[sec['name']]) self.assertEqual(len(result['securityGroupInfo']), 1) self.assertEqual( - cloud.ec2_id_to_id(result['securityGroupInfo'][0]['name']), + result['securityGroupInfo'][0]['groupName'], sec['name']) db.security_group_destroy(self.context, sec['id']) -- cgit From 943b863bef09a4e2b3de36c26a3fabbcc6093411 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 22 Feb 2011 23:21:01 -0800 Subject: Lots of test fixing --- nova/tests/api/openstack/test_servers.py | 2 +- nova/tests/test_cloud.py | 75 ++++++++------------------------ nova/tests/test_network.py | 3 ++ nova/tests/test_scheduler.py | 3 ++ nova/tests/test_virt.py | 3 ++ 5 files changed, 27 insertions(+), 59 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a7be0796e..589f3d3eb 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -84,7 +84,7 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None): "vcpus": 0, "local_gb": 0, "hostname": "", - "host": "", + "host": None, "instance_type": "", "user_data": "", "reservation_id": "", diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 1824d24bc..2c6dc5973 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -66,6 +66,7 @@ class CloudTestCase(test.TestCase): # set up services self.compute = self.start_service('compute') + self.scheduter = self.start_service('scheduler') self.network = self.start_service('network') self.manager = manager.AuthManager() @@ -73,8 +74,12 @@ class CloudTestCase(test.TestCase): self.project = self.manager.create_project('proj', 'admin', 'proj') self.context = context.RequestContext(user=self.user, project=self.project) + host = self.network.get_network_host(self.context.elevated()) def tearDown(self): + network_ref = db.project_get_network(self.context, + self.project.id) + db.network_disassociate(self.context, network_ref['id']) self.manager.delete_project(self.project) self.manager.delete_user(self.user) self.compute.kill() @@ -201,27 +206,32 @@ class CloudTestCase(test.TestCase): 'instance_type': instance_type, 'max_count': max_count} rv = self.cloud.run_instances(self.context, **kwargs) + greenthread.sleep(0.3) instance_id = rv['instancesSet'][0]['instanceId'] output = self.cloud.get_console_output(context=self.context, - instance_id=[instance_id]) + instance_id=[instance_id]) self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE OUTPUT') # TODO(soren): We need this until we can stop polling in the rpc code # for unit tests. greenthread.sleep(0.3) rv = self.cloud.terminate_instances(self.context, [instance_id]) + greenthread.sleep(0.3) def test_ajax_console(self): + image_id = FLAGS.default_image kwargs = {'image_id': image_id} - rv = yield self.cloud.run_instances(self.context, **kwargs) + rv = self.cloud.run_instances(self.context, **kwargs) instance_id = rv['instancesSet'][0]['instanceId'] - output = yield self.cloud.get_console_output(context=self.context, - instance_id=[instance_id]) - self.assertEquals(b64decode(output['output']), - 'http://fakeajaxconsole.com/?token=FAKETOKEN') + greenthread.sleep(0.3) + output = self.cloud.get_ajax_console(context=self.context, + instance_id=[instance_id]) + self.assertEquals(output['url'], + '%s/?token=FAKETOKEN' % FLAGS.ajax_console_proxy_url) # TODO(soren): We need this until we can stop polling in the rpc code # for unit tests. greenthread.sleep(0.3) - rv = yield self.cloud.terminate_instances(self.context, [instance_id]) + rv = self.cloud.terminate_instances(self.context, [instance_id]) + greenthread.sleep(0.3) def test_key_generation(self): result = self._create_key('test') @@ -297,57 +307,6 @@ class CloudTestCase(test.TestCase): db.instance_destroy(self.context, instance1['id']) db.service_destroy(self.context, comp1['id']) - def test_instance_update_state(self): - # TODO(termie): what is this code even testing? - def instance(num): - return { - 'reservation_id': 'r-1', - 'instance_id': 'i-%s' % num, - 'image_id': 'ami-%s' % num, - 'private_dns_name': '10.0.0.%s' % num, - 'dns_name': '10.0.0%s' % num, - 'ami_launch_index': str(num), - 'instance_type': 'fake', - 'availability_zone': 'fake', - 'key_name': None, - 'kernel_id': 'fake', - 'ramdisk_id': 'fake', - 'groups': ['default'], - 'product_codes': None, - 'state': 0x01, - 'user_data': ''} - rv = self.cloud._format_describe_instances(self.context) - logging.error(str(rv)) - self.assertEqual(len(rv['reservationSet']), 0) - - # simulate launch of 5 instances - # self.cloud.instances['pending'] = {} - #for i in xrange(5): - # inst = instance(i) - # self.cloud.instances['pending'][inst['instance_id']] = inst - - #rv = self.cloud._format_instances(self.admin) - #self.assert_(len(rv['reservationSet']) == 1) - #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) - # report 4 nodes each having 1 of the instances - #for i in xrange(4): - # self.cloud.update_state('instances', - # {('node-%s' % i): {('i-%s' % i): - # instance(i)}}) - - # one instance should be pending still - #self.assert_(len(self.cloud.instances['pending'].keys()) == 1) - - # check that the reservations collapse - #rv = self.cloud._format_instances(self.admin) - #self.assert_(len(rv['reservationSet']) == 1) - #self.assert_(len(rv['reservationSet'][0]['instances_set']) == 5) - - # check that we can get metadata for each instance - #for i in xrange(4): - # data = self.cloud.get_metadata(instance(i)['private_dns_name']) - # self.assert_(data['meta-data']['ami-id'] == 'ami-%s' % i) - @staticmethod def _fake_set_image_description(ctxt, image_id, description): from nova.objectstore import handler diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 00f9323f3..53cfea276 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -117,6 +117,9 @@ class NetworkTestCase(test.TestCase): utils.to_global_ipv6( network_ref['cidr_v6'], instance_ref['mac_address'])) + self._deallocate_address(0, address) + db.instance_destroy(context.get_admin_context(), + instance_ref['id']) def test_public_network_association(self): """Makes sure that we can allocaate a public ip""" diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 250170072..8e4a4daf5 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -118,6 +118,7 @@ class ZoneSchedulerTestCase(test.TestCase): arg = IgnoreArg() db.service_get_all_by_topic(arg, arg).AndReturn(service_list) self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) + self.mox.StubOutWithMock(db, 'instance_create', use_mock_anything=True) rpc.cast(ctxt, 'compute.host1', {'method': 'run_instance', @@ -150,6 +151,7 @@ class SimpleDriverTestCase(test.TestCase): def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) + super(SimpleDriverTestCase, self).tearDown() def _create_instance(self, **kwargs): """Create a test instance""" @@ -270,6 +272,7 @@ class SimpleDriverTestCase(test.TestCase): self.scheduler.driver.schedule_run_instance, self.context, instance_id) + db.instance_destroy(self.context, instance_id) for instance_id in instance_ids1: compute1.terminate_instance(self.context, instance_id) for instance_id in instance_ids2: diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 6e5a0114b..5b3247df9 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -204,6 +204,7 @@ class LibvirtConnTestCase(test.TestCase): conn = libvirt_conn.LibvirtConnection(True) uri = conn.get_uri() self.assertEquals(uri, testuri) + db.instance_destroy(user_context, instance_ref['id']) def tearDown(self): super(LibvirtConnTestCase, self).tearDown() @@ -365,6 +366,7 @@ class IptablesFirewallTestCase(test.TestCase): '--dports 80:81 -j ACCEPT' % security_group_chain \ in self.out_rules, "TCP port 80/81 acceptance rule wasn't added") + db.instance_destroy(admin_ctxt, instance_ref['id']) class NWFilterTestCase(test.TestCase): @@ -514,3 +516,4 @@ class NWFilterTestCase(test.TestCase): self.fw.apply_instance_filter(instance) _ensure_all_called() self.teardown_security_group() + db.instance_destroy(admin_ctxt, instance_ref['id']) -- cgit From 015900b215805808d8cc3138b0f4deb2c0941f76 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 22 Feb 2011 23:30:52 -0800 Subject: remove unnecessary stubout --- nova/tests/test_scheduler.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 8e4a4daf5..b6888c4d2 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -118,7 +118,6 @@ class ZoneSchedulerTestCase(test.TestCase): arg = IgnoreArg() db.service_get_all_by_topic(arg, arg).AndReturn(service_list) self.mox.StubOutWithMock(rpc, 'cast', use_mock_anything=True) - self.mox.StubOutWithMock(db, 'instance_create', use_mock_anything=True) rpc.cast(ctxt, 'compute.host1', {'method': 'run_instance', -- cgit From 2bec58e35ab1f2df543e50d399433f76e98210d7 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 01:13:41 -0800 Subject: move db creation into fixtures and clean db for each test --- nova/tests/__init__.py | 15 +++++++++++++++ nova/tests/api/openstack/__init__.py | 4 ++-- nova/tests/api/openstack/test_adminapi.py | 11 +++++------ nova/tests/api/openstack/test_api.py | 4 ++-- nova/tests/api/openstack/test_auth.py | 14 +++++++------- nova/tests/api/openstack/test_common.py | 5 +++-- nova/tests/api/openstack/test_faults.py | 4 ++-- nova/tests/api/openstack/test_flavors.py | 10 ++++------ nova/tests/api/openstack/test_images.py | 14 ++++++++++---- nova/tests/api/openstack/test_ratelimiting.py | 15 +++++++-------- nova/tests/api/openstack/test_servers.py | 10 ++++------ nova/tests/api/openstack/test_shared_ip_groups.py | 7 ++++--- nova/tests/api/openstack/test_zones.py | 10 ++++------ nova/tests/api/test_wsgi.py | 6 +++--- nova/tests/objectstore_unittest.py | 1 + nova/tests/test_direct.py | 1 + nova/tests/test_scheduler.py | 1 + nova/tests/test_virt.py | 3 ++- 18 files changed, 77 insertions(+), 58 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index 592d5bea9..5472bdaf2 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -37,5 +37,20 @@ setattr(__builtin__, '_', lambda x: x) def setup(): + import shutil + from nova import context + from nova import flags from nova.db import migration + from nova.network import manager as network_manager + from nova.tests import fake_flags + FLAGS = flags.FLAGS migration.db_sync() + ctxt = context.get_admin_context() + network_manager.VlanManager().create_networks(ctxt, + FLAGS.fixed_range, + 5, 16, + FLAGS.fixed_range_v6, + FLAGS.vlan_start, + FLAGS.vpn_start, + ) + shutil.copyfile("tests.sqlite", "clean.sqlite") diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index 77b1dd37f..e18120285 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -16,7 +16,7 @@ # under the License. import webob.dec -import unittest +from nova import test from nova import context from nova import flags @@ -33,7 +33,7 @@ def simple_wsgi(req): return "" -class RateLimitingMiddlewareTest(unittest.TestCase): +class RateLimitingMiddlewareTest(test.TestCase): def test_get_action_name(self): middleware = RateLimitingMiddleware(simple_wsgi) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 73120c31d..dfce1b127 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -15,13 +15,13 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import stubout import webob from paste import urlmap from nova import flags +from nova import test from nova.api import openstack from nova.api.openstack import ratelimiting from nova.api.openstack import auth @@ -30,9 +30,10 @@ from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS -class AdminAPITest(unittest.TestCase): +class AdminAPITest(test.TestCase): def setUp(self): + super(AdminAPITest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -44,6 +45,7 @@ class AdminAPITest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(AdminAPITest, self).tearDown() def test_admin_enabled(self): FLAGS.allow_admin_api = True @@ -58,8 +60,5 @@ class AdminAPITest(unittest.TestCase): # We should still be able to access public operations. req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are unavailable. - -if __name__ == '__main__': - unittest.main() + self.assertEqual(res.status_int, 200) diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py index db0fe1060..5112c486f 100644 --- a/nova/tests/api/openstack/test_api.py +++ b/nova/tests/api/openstack/test_api.py @@ -15,17 +15,17 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import webob.exc import webob.dec from webob import Request +from nova import test from nova.api import openstack from nova.api.openstack import faults -class APITest(unittest.TestCase): +class APITest(test.TestCase): def _wsgi_app(self, inner_app): # simpler version of the app than fakes.wsgi_app diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 0dd65d321..13f6c3a1c 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -16,7 +16,6 @@ # under the License. import datetime -import unittest import stubout import webob @@ -27,12 +26,14 @@ import nova.api.openstack.auth import nova.auth.manager from nova import auth from nova import context +from nova import test from nova.tests.api.openstack import fakes -class Test(unittest.TestCase): +class Test(test.TestCase): def setUp(self): + super(Test, self).setUp() self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) @@ -45,6 +46,7 @@ class Test(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() fakes.fake_data_store = {} + super(Test, self).tearDown() def test_authorize_user(self): f = fakes.FakeAuthManager() @@ -128,8 +130,9 @@ class Test(unittest.TestCase): self.assertEqual(result.status, '401 Unauthorized') -class TestLimiter(unittest.TestCase): +class TestLimiter(test.TestCase): def setUp(self): + super(TestLimiter, self).setUp() self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) @@ -141,6 +144,7 @@ class TestLimiter(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() fakes.fake_data_store = {} + super(TestLimiter, self).tearDown() def test_authorize_token(self): f = fakes.FakeAuthManager() @@ -161,7 +165,3 @@ class TestLimiter(unittest.TestCase): result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '200 OK') self.assertEqual(result.headers['X-Test-Success'], 'True') - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 9d9837cc9..59d850157 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -19,14 +19,14 @@ Test suites for 'common' code used throughout the OpenStack HTTP API. """ -import unittest from webob import Request +from nova import test from nova.api.openstack.common import limited -class LimiterTest(unittest.TestCase): +class LimiterTest(test.TestCase): """ Unit tests for the `nova.api.openstack.common.limited` method which takes in a list of items and, depending on the 'offset' and 'limit' GET params, @@ -37,6 +37,7 @@ class LimiterTest(unittest.TestCase): """ Run before each test. """ + super(LimiterTest, self).setUp() self.tiny = range(1) self.small = range(10) self.medium = range(1000) diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index fda2b5ede..7667753f4 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -15,15 +15,15 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import webob import webob.dec import webob.exc +from nova import test from nova.api.openstack import faults -class TestFaults(unittest.TestCase): +class TestFaults(test.TestCase): def test_fault_parts(self): req = webob.Request.blank('/.xml') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 1bdaea161..761265965 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -15,18 +15,18 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest - import stubout import webob +from nova import test import nova.api from nova.api.openstack import flavors from nova.tests.api.openstack import fakes -class FlavorsTest(unittest.TestCase): +class FlavorsTest(test.TestCase): def setUp(self): + super(FlavorsTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -36,6 +36,7 @@ class FlavorsTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() + super(FlavorsTest, self).tearDown() def test_get_flavor_list(self): req = webob.Request.blank('/v1.0/flavors') @@ -43,6 +44,3 @@ class FlavorsTest(unittest.TestCase): def test_get_flavor_by_id(self): pass - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 8ab4d7569..e232bc3d5 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -22,7 +22,6 @@ and as a WSGI layer import json import datetime -import unittest import stubout import webob @@ -30,6 +29,7 @@ import webob from nova import context from nova import exception from nova import flags +from nova import test from nova import utils import nova.api.openstack from nova.api.openstack import images @@ -130,12 +130,13 @@ class BaseImageServiceTests(object): self.assertEquals(1, num_images) -class LocalImageServiceTest(unittest.TestCase, +class LocalImageServiceTest(test.TestCase, BaseImageServiceTests): """Tests the local image service""" def setUp(self): + super(LocalImageServiceTest, self).setUp() self.stubs = stubout.StubOutForTesting() service_class = 'nova.image.local.LocalImageService' self.service = utils.import_object(service_class) @@ -145,14 +146,16 @@ class LocalImageServiceTest(unittest.TestCase, self.service.delete_all() self.service.delete_imagedir() self.stubs.UnsetAll() + super(LocalImageServiceTest, self).tearDown() -class GlanceImageServiceTest(unittest.TestCase, +class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): """Tests the local image service""" def setUp(self): + super(GlanceImageServiceTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.stub_out_glance(self.stubs) fakes.stub_out_compute_api_snapshot(self.stubs) @@ -163,9 +166,10 @@ class GlanceImageServiceTest(unittest.TestCase, def tearDown(self): self.stubs.UnsetAll() + super(GlanceImageServiceTest, self).tearDown() -class ImageControllerWithGlanceServiceTest(unittest.TestCase): +class ImageControllerWithGlanceServiceTest(test.TestCase): """Test of the OpenStack API /images application controller""" @@ -194,6 +198,7 @@ class ImageControllerWithGlanceServiceTest(unittest.TestCase): 'image_type': 'ramdisk'}] def setUp(self): + super(ImageControllerWithGlanceServiceTest, self).setUp() self.orig_image_service = FLAGS.image_service FLAGS.image_service = 'nova.image.glance.GlanceImageService' self.stubs = stubout.StubOutForTesting() @@ -208,6 +213,7 @@ class ImageControllerWithGlanceServiceTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.image_service = self.orig_image_service + super(ImageControllerWithGlanceServiceTest, self).tearDown() def test_get_image_index(self): req = webob.Request.blank('/v1.0/images') diff --git a/nova/tests/api/openstack/test_ratelimiting.py b/nova/tests/api/openstack/test_ratelimiting.py index 4c9d6bc23..9ae90ee20 100644 --- a/nova/tests/api/openstack/test_ratelimiting.py +++ b/nova/tests/api/openstack/test_ratelimiting.py @@ -1,15 +1,16 @@ import httplib import StringIO import time -import unittest import webob +from nova import test import nova.api.openstack.ratelimiting as ratelimiting -class LimiterTest(unittest.TestCase): +class LimiterTest(test.TestCase): def setUp(self): + super(LimiterTest, self).setUp() self.limits = { 'a': (5, ratelimiting.PER_SECOND), 'b': (5, ratelimiting.PER_MINUTE), @@ -83,9 +84,10 @@ class FakeLimiter(object): return self._delay -class WSGIAppTest(unittest.TestCase): +class WSGIAppTest(test.TestCase): def setUp(self): + super(WSGIAppTest, self).setUp() self.limiter = FakeLimiter(self) self.app = ratelimiting.WSGIApp(self.limiter) @@ -206,7 +208,7 @@ def wire_HTTPConnection_to_WSGI(host, app): httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) -class WSGIAppProxyTest(unittest.TestCase): +class WSGIAppProxyTest(test.TestCase): def setUp(self): """Our WSGIAppProxy is going to call across an HTTPConnection to a @@ -218,6 +220,7 @@ class WSGIAppProxyTest(unittest.TestCase): at the WSGIApp. And the limiter isn't real -- it's a fake that behaves the way we tell it to. """ + super(WSGIAppProxyTest, self).setUp() self.limiter = FakeLimiter(self) app = ratelimiting.WSGIApp(self.limiter) wire_HTTPConnection_to_WSGI('100.100.100.100:80', app) @@ -238,7 +241,3 @@ class WSGIAppProxyTest(unittest.TestCase): self.limiter.mock('murder', 'brutus', None) self.proxy.perform('stab', 'brutus') self.assertRaises(AssertionError, shouldRaise) - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a7be0796e..ea29dcf9b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -17,13 +17,13 @@ import datetime import json -import unittest import stubout import webob from nova import db from nova import flags +from nova import test import nova.api.openstack from nova.api.openstack import servers import nova.db.api @@ -108,9 +108,10 @@ def fake_compute_api(cls, req, id): return True -class ServersTest(unittest.TestCase): +class ServersTest(test.TestCase): def setUp(self): + super(ServersTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -141,6 +142,7 @@ class ServersTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(ServersTest, self).tearDown() def test_get_server_by_id(self): req = webob.Request.blank('/v1.0/servers/1') @@ -410,7 +412,3 @@ class ServersTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '202 Accepted') self.assertEqual(self.server_delete_called, True) - - -if __name__ == "__main__": - unittest.main() diff --git a/nova/tests/api/openstack/test_shared_ip_groups.py b/nova/tests/api/openstack/test_shared_ip_groups.py index c2fc3a203..b4de2ef41 100644 --- a/nova/tests/api/openstack/test_shared_ip_groups.py +++ b/nova/tests/api/openstack/test_shared_ip_groups.py @@ -15,19 +15,20 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest - import stubout +from nova import test from nova.api.openstack import shared_ip_groups -class SharedIpGroupsTest(unittest.TestCase): +class SharedIpGroupsTest(test.TestCase): def setUp(self): + super(SharedIpGroupsTest, self).setUp() self.stubs = stubout.StubOutForTesting() def tearDown(self): self.stubs.UnsetAll() + super(SharedIpGroupsTest, self).tearDown() def test_get_shared_ip_groups(self): pass diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index df497ef1b..555b206b9 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import stubout import webob @@ -22,6 +21,7 @@ import json import nova.db from nova import context from nova import flags +from nova import test from nova.api.openstack import zones from nova.tests.api.openstack import fakes @@ -60,8 +60,9 @@ def zone_get_all(context): password='qwerty')] -class ZonesTest(unittest.TestCase): +class ZonesTest(test.TestCase): def setUp(self): + super(ZonesTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -81,6 +82,7 @@ class ZonesTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(ZonesTest, self).tearDown() def test_get_zone_list(self): req = webob.Request.blank('/v1.0/zones') @@ -134,7 +136,3 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') self.assertFalse('username' in res_dict['zone']) - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index 44e2d615c..2c7852214 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -21,7 +21,7 @@ Test WSGI basics and provide some helper functions for other WSGI tests. """ -import unittest +from nova import test import routes import webob @@ -29,7 +29,7 @@ import webob from nova import wsgi -class Test(unittest.TestCase): +class Test(test.TestCase): def test_debug(self): @@ -92,7 +92,7 @@ class Test(unittest.TestCase): self.assertNotEqual(result.body, "123") -class SerializerTest(unittest.TestCase): +class SerializerTest(test.TestCase): def match(self, url, accept, expect): input_dict = dict(servers=dict(a=(2, 3))) diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py index da86e6e11..5a1be08eb 100644 --- a/nova/tests/objectstore_unittest.py +++ b/nova/tests/objectstore_unittest.py @@ -311,4 +311,5 @@ class S3APITestCase(test.TestCase): self.auth_manager.delete_user('admin') self.auth_manager.delete_project('admin') stop_listening = defer.maybeDeferred(self.listening_port.stopListening) + super(S3APITestCase, self).tearDown() return defer.DeferredList([stop_listening]) diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 7656f5396..b6bfab534 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -52,6 +52,7 @@ class DirectTestCase(test.TestCase): def tearDown(self): direct.ROUTES = {} + super(DirectTestCase, self).tearDown() def test_delegated_auth(self): req = webob.Request.blank('/fake/context') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 9d458244b..1bad364e5 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -150,6 +150,7 @@ class SimpleDriverTestCase(test.TestCase): def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) + super(SimpleDriverTestCase, self).tearDown() def _create_instance(self, **kwargs): """Create a test instance""" diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 6e5a0114b..7aadd65d5 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -206,9 +206,9 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) def tearDown(self): - super(LibvirtConnTestCase, self).tearDown() self.manager.delete_project(self.project) self.manager.delete_user(self.user) + super(LibvirtConnTestCase, self).tearDown() class IptablesFirewallTestCase(test.TestCase): @@ -388,6 +388,7 @@ class NWFilterTestCase(test.TestCase): def tearDown(self): self.manager.delete_project(self.project) self.manager.delete_user(self.user) + super(NWFilterTestCase, self).tearDown() def test_cidr_rule_nwfilter_xml(self): cloud_controller = cloud.CloudController() -- cgit From 3b2a8b516fd9dbd08563c709e14323d571b8efee Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 01:52:07 -0800 Subject: speed up network tests --- nova/tests/__init__.py | 3 ++- nova/tests/fake_flags.py | 4 ++-- nova/tests/test_network.py | 8 +++----- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index 5472bdaf2..5afd9389d 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -48,7 +48,8 @@ def setup(): ctxt = context.get_admin_context() network_manager.VlanManager().create_networks(ctxt, FLAGS.fixed_range, - 5, 16, + FLAGS.num_networks, + FLAGS.network_size, FLAGS.fixed_range_v6, FLAGS.vlan_start, FLAGS.vpn_start, diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 575fefff6..a8291a968 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -29,8 +29,8 @@ FLAGS.auth_driver = 'nova.auth.dbdriver.DbDriver' flags.DECLARE('network_size', 'nova.network.manager') flags.DECLARE('num_networks', 'nova.network.manager') flags.DECLARE('fake_network', 'nova.network.manager') -FLAGS.network_size = 16 -FLAGS.num_networks = 5 +FLAGS.network_size = 8 +FLAGS.num_networks = 2 FLAGS.fake_network = True flags.DECLARE('num_shelves', 'nova.volume.driver') flags.DECLARE('blades_per_shelf', 'nova.volume.driver') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 00f9323f3..ccb5298bd 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -42,15 +42,13 @@ class NetworkTestCase(test.TestCase): # flags in the corresponding section in nova-dhcpbridge self.flags(connection_type='fake', fake_call=True, - fake_network=True, - network_size=16, - num_networks=5) + fake_network=True) self.manager = manager.AuthManager() self.user = self.manager.create_user('netuser', 'netuser', 'netuser') self.projects = [] self.network = utils.import_object(FLAGS.network_manager) self.context = context.RequestContext(project=None, user=self.user) - for i in range(5): + for i in range(FLAGS.num_networks): name = 'project%s' % i project = self.manager.create_project(name, 'netuser', name) self.projects.append(project) @@ -192,7 +190,7 @@ class NetworkTestCase(test.TestCase): first = self._create_address(0) lease_ip(first) instance_ids = [] - for i in range(1, 5): + for i in range(1, FLAGS.num_networks): instance_ref = self._create_instance(i, mac=utils.generate_mac()) instance_ids.append(instance_ref['id']) address = self._create_address(i, instance_ref['id']) -- cgit From ef0dfb6809f31cfe8ca8056892fc9dcc2f00a0d7 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Feb 2011 09:40:43 -0800 Subject: Changed unit test to refer to compute API, per Todd's suggestion. Avoids needing to extend our implementation of the EC2 API. --- nova/tests/test_quota.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 36ccc273e..1e42fddf3 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -16,6 +16,7 @@ # License for the specific language governing permissions and limitations # under the License. +from nova import compute from nova import context from nova import db from nova import flags @@ -168,7 +169,7 @@ class QuotaTestCase(test.TestCase): metadata = {} for i in range(FLAGS.quota_metadata_items + 1): metadata['key%s' % i] = 'value%s' % i - self.assertRaises(quota.QuotaError, self.cloud.run_instances, + self.assertRaises(quota.QuotaError, compute.API().create, self.context, min_count=1, max_count=1, -- cgit From 3c09d486f862de7069b848e8124787cfbf4247f8 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 11:20:52 -0800 Subject: use flags for sqlite db names and fix flags in dhcpbridge --- nova/tests/__init__.py | 7 ++++++- nova/tests/fake_flags.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index 5afd9389d..dbd433054 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -37,13 +37,17 @@ setattr(__builtin__, '_', lambda x: x) def setup(): + import os import shutil + from nova import context from nova import flags from nova.db import migration from nova.network import manager as network_manager from nova.tests import fake_flags + FLAGS = flags.FLAGS + migration.db_sync() ctxt = context.get_admin_context() network_manager.VlanManager().create_networks(ctxt, @@ -54,4 +58,5 @@ def setup(): FLAGS.vlan_start, FLAGS.vpn_start, ) - shutil.copyfile("tests.sqlite", "clean.sqlite") + shutil.copyfile(os.path.join(FLAGS.state_path, FLAGS.sqlite_db), + os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db)) diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index a8291a968..dcc8a676d 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -39,6 +39,6 @@ FLAGS.num_shelves = 2 FLAGS.blades_per_shelf = 4 FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True -FLAGS.sql_connection = 'sqlite:///tests.sqlite' +FLAGS.sqlite_db = "tests.sqlite" FLAGS.use_ipv6 = True FLAGS.logfile = 'tests.log' -- cgit From 1b2d67e769ff1a6fe68a933e8b966d72588ce8ac Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 11:44:09 -0800 Subject: merged trunk --- nova/tests/__init__.py | 13 +++++++++++++ nova/tests/api/openstack/__init__.py | 4 ++-- nova/tests/api/openstack/test_adminapi.py | 8 ++++---- nova/tests/api/openstack/test_api.py | 4 ++-- nova/tests/api/openstack/test_auth.py | 14 +++++++------- nova/tests/api/openstack/test_common.py | 5 +++-- nova/tests/api/openstack/test_faults.py | 4 ++-- nova/tests/api/openstack/test_flavors.py | 10 ++++------ nova/tests/api/openstack/test_images.py | 14 ++++++++++---- nova/tests/api/openstack/test_ratelimiting.py | 15 +++++++-------- nova/tests/api/openstack/test_servers.py | 10 ++++------ nova/tests/api/openstack/test_shared_ip_groups.py | 7 ++++--- nova/tests/api/openstack/test_zones.py | 10 ++++------ nova/tests/api/test_wsgi.py | 6 +++--- nova/tests/objectstore_unittest.py | 1 + nova/tests/test_direct.py | 1 + nova/tests/test_scheduler.py | 1 + nova/tests/test_virt.py | 3 ++- 18 files changed, 74 insertions(+), 56 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index 592d5bea9..d3ab02887 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -38,4 +38,17 @@ setattr(__builtin__, '_', lambda x: x) def setup(): from nova.db import migration + from nova.network import manager as network_manager + from nova import context + from nova import flags + from nova.tests import fake_flags + FLAGS = flags.FLAGS migration.db_sync() + ctxt = context.get_admin_context() + network_manager.VlanManager().create_networks(ctxt, + FLAGS.fixed_range, + 5, 16, + FLAGS.fixed_range_v6, + FLAGS.vlan_start, + FLAGS.vpn_start, + ) diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index 77b1dd37f..e18120285 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -16,7 +16,7 @@ # under the License. import webob.dec -import unittest +from nova import test from nova import context from nova import flags @@ -33,7 +33,7 @@ def simple_wsgi(req): return "" -class RateLimitingMiddlewareTest(unittest.TestCase): +class RateLimitingMiddlewareTest(test.TestCase): def test_get_action_name(self): middleware = RateLimitingMiddleware(simple_wsgi) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 73120c31d..125fbe973 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -15,13 +15,13 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import stubout import webob from paste import urlmap from nova import flags +from nova import test from nova.api import openstack from nova.api.openstack import ratelimiting from nova.api.openstack import auth @@ -30,9 +30,10 @@ from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS -class AdminAPITest(unittest.TestCase): +class AdminAPITest(test.TestCase): def setUp(self): + super(AdminAPITest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -44,6 +45,7 @@ class AdminAPITest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(AdminAPITest, self).tearDown() def test_admin_enabled(self): FLAGS.allow_admin_api = True @@ -61,5 +63,3 @@ class AdminAPITest(unittest.TestCase): self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are unavailable. -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_api.py b/nova/tests/api/openstack/test_api.py index db0fe1060..5112c486f 100644 --- a/nova/tests/api/openstack/test_api.py +++ b/nova/tests/api/openstack/test_api.py @@ -15,17 +15,17 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import webob.exc import webob.dec from webob import Request +from nova import test from nova.api import openstack from nova.api.openstack import faults -class APITest(unittest.TestCase): +class APITest(test.TestCase): def _wsgi_app(self, inner_app): # simpler version of the app than fakes.wsgi_app diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 0dd65d321..13f6c3a1c 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -16,7 +16,6 @@ # under the License. import datetime -import unittest import stubout import webob @@ -27,12 +26,14 @@ import nova.api.openstack.auth import nova.auth.manager from nova import auth from nova import context +from nova import test from nova.tests.api.openstack import fakes -class Test(unittest.TestCase): +class Test(test.TestCase): def setUp(self): + super(Test, self).setUp() self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) @@ -45,6 +46,7 @@ class Test(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() fakes.fake_data_store = {} + super(Test, self).tearDown() def test_authorize_user(self): f = fakes.FakeAuthManager() @@ -128,8 +130,9 @@ class Test(unittest.TestCase): self.assertEqual(result.status, '401 Unauthorized') -class TestLimiter(unittest.TestCase): +class TestLimiter(test.TestCase): def setUp(self): + super(TestLimiter, self).setUp() self.stubs = stubout.StubOutForTesting() self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) @@ -141,6 +144,7 @@ class TestLimiter(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() fakes.fake_data_store = {} + super(TestLimiter, self).tearDown() def test_authorize_token(self): f = fakes.FakeAuthManager() @@ -161,7 +165,3 @@ class TestLimiter(unittest.TestCase): result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '200 OK') self.assertEqual(result.headers['X-Test-Success'], 'True') - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 9d9837cc9..59d850157 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -19,14 +19,14 @@ Test suites for 'common' code used throughout the OpenStack HTTP API. """ -import unittest from webob import Request +from nova import test from nova.api.openstack.common import limited -class LimiterTest(unittest.TestCase): +class LimiterTest(test.TestCase): """ Unit tests for the `nova.api.openstack.common.limited` method which takes in a list of items and, depending on the 'offset' and 'limit' GET params, @@ -37,6 +37,7 @@ class LimiterTest(unittest.TestCase): """ Run before each test. """ + super(LimiterTest, self).setUp() self.tiny = range(1) self.small = range(10) self.medium = range(1000) diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index fda2b5ede..7667753f4 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -15,15 +15,15 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import webob import webob.dec import webob.exc +from nova import test from nova.api.openstack import faults -class TestFaults(unittest.TestCase): +class TestFaults(test.TestCase): def test_fault_parts(self): req = webob.Request.blank('/.xml') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 1bdaea161..761265965 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -15,18 +15,18 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest - import stubout import webob +from nova import test import nova.api from nova.api.openstack import flavors from nova.tests.api.openstack import fakes -class FlavorsTest(unittest.TestCase): +class FlavorsTest(test.TestCase): def setUp(self): + super(FlavorsTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -36,6 +36,7 @@ class FlavorsTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() + super(FlavorsTest, self).tearDown() def test_get_flavor_list(self): req = webob.Request.blank('/v1.0/flavors') @@ -43,6 +44,3 @@ class FlavorsTest(unittest.TestCase): def test_get_flavor_by_id(self): pass - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 8ab4d7569..e232bc3d5 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -22,7 +22,6 @@ and as a WSGI layer import json import datetime -import unittest import stubout import webob @@ -30,6 +29,7 @@ import webob from nova import context from nova import exception from nova import flags +from nova import test from nova import utils import nova.api.openstack from nova.api.openstack import images @@ -130,12 +130,13 @@ class BaseImageServiceTests(object): self.assertEquals(1, num_images) -class LocalImageServiceTest(unittest.TestCase, +class LocalImageServiceTest(test.TestCase, BaseImageServiceTests): """Tests the local image service""" def setUp(self): + super(LocalImageServiceTest, self).setUp() self.stubs = stubout.StubOutForTesting() service_class = 'nova.image.local.LocalImageService' self.service = utils.import_object(service_class) @@ -145,14 +146,16 @@ class LocalImageServiceTest(unittest.TestCase, self.service.delete_all() self.service.delete_imagedir() self.stubs.UnsetAll() + super(LocalImageServiceTest, self).tearDown() -class GlanceImageServiceTest(unittest.TestCase, +class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): """Tests the local image service""" def setUp(self): + super(GlanceImageServiceTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.stub_out_glance(self.stubs) fakes.stub_out_compute_api_snapshot(self.stubs) @@ -163,9 +166,10 @@ class GlanceImageServiceTest(unittest.TestCase, def tearDown(self): self.stubs.UnsetAll() + super(GlanceImageServiceTest, self).tearDown() -class ImageControllerWithGlanceServiceTest(unittest.TestCase): +class ImageControllerWithGlanceServiceTest(test.TestCase): """Test of the OpenStack API /images application controller""" @@ -194,6 +198,7 @@ class ImageControllerWithGlanceServiceTest(unittest.TestCase): 'image_type': 'ramdisk'}] def setUp(self): + super(ImageControllerWithGlanceServiceTest, self).setUp() self.orig_image_service = FLAGS.image_service FLAGS.image_service = 'nova.image.glance.GlanceImageService' self.stubs = stubout.StubOutForTesting() @@ -208,6 +213,7 @@ class ImageControllerWithGlanceServiceTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.image_service = self.orig_image_service + super(ImageControllerWithGlanceServiceTest, self).tearDown() def test_get_image_index(self): req = webob.Request.blank('/v1.0/images') diff --git a/nova/tests/api/openstack/test_ratelimiting.py b/nova/tests/api/openstack/test_ratelimiting.py index 4c9d6bc23..9ae90ee20 100644 --- a/nova/tests/api/openstack/test_ratelimiting.py +++ b/nova/tests/api/openstack/test_ratelimiting.py @@ -1,15 +1,16 @@ import httplib import StringIO import time -import unittest import webob +from nova import test import nova.api.openstack.ratelimiting as ratelimiting -class LimiterTest(unittest.TestCase): +class LimiterTest(test.TestCase): def setUp(self): + super(LimiterTest, self).setUp() self.limits = { 'a': (5, ratelimiting.PER_SECOND), 'b': (5, ratelimiting.PER_MINUTE), @@ -83,9 +84,10 @@ class FakeLimiter(object): return self._delay -class WSGIAppTest(unittest.TestCase): +class WSGIAppTest(test.TestCase): def setUp(self): + super(WSGIAppTest, self).setUp() self.limiter = FakeLimiter(self) self.app = ratelimiting.WSGIApp(self.limiter) @@ -206,7 +208,7 @@ def wire_HTTPConnection_to_WSGI(host, app): httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) -class WSGIAppProxyTest(unittest.TestCase): +class WSGIAppProxyTest(test.TestCase): def setUp(self): """Our WSGIAppProxy is going to call across an HTTPConnection to a @@ -218,6 +220,7 @@ class WSGIAppProxyTest(unittest.TestCase): at the WSGIApp. And the limiter isn't real -- it's a fake that behaves the way we tell it to. """ + super(WSGIAppProxyTest, self).setUp() self.limiter = FakeLimiter(self) app = ratelimiting.WSGIApp(self.limiter) wire_HTTPConnection_to_WSGI('100.100.100.100:80', app) @@ -238,7 +241,3 @@ class WSGIAppProxyTest(unittest.TestCase): self.limiter.mock('murder', 'brutus', None) self.proxy.perform('stab', 'brutus') self.assertRaises(AssertionError, shouldRaise) - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a7be0796e..ea29dcf9b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -17,13 +17,13 @@ import datetime import json -import unittest import stubout import webob from nova import db from nova import flags +from nova import test import nova.api.openstack from nova.api.openstack import servers import nova.db.api @@ -108,9 +108,10 @@ def fake_compute_api(cls, req, id): return True -class ServersTest(unittest.TestCase): +class ServersTest(test.TestCase): def setUp(self): + super(ServersTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -141,6 +142,7 @@ class ServersTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(ServersTest, self).tearDown() def test_get_server_by_id(self): req = webob.Request.blank('/v1.0/servers/1') @@ -410,7 +412,3 @@ class ServersTest(unittest.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '202 Accepted') self.assertEqual(self.server_delete_called, True) - - -if __name__ == "__main__": - unittest.main() diff --git a/nova/tests/api/openstack/test_shared_ip_groups.py b/nova/tests/api/openstack/test_shared_ip_groups.py index c2fc3a203..b4de2ef41 100644 --- a/nova/tests/api/openstack/test_shared_ip_groups.py +++ b/nova/tests/api/openstack/test_shared_ip_groups.py @@ -15,19 +15,20 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest - import stubout +from nova import test from nova.api.openstack import shared_ip_groups -class SharedIpGroupsTest(unittest.TestCase): +class SharedIpGroupsTest(test.TestCase): def setUp(self): + super(SharedIpGroupsTest, self).setUp() self.stubs = stubout.StubOutForTesting() def tearDown(self): self.stubs.UnsetAll() + super(SharedIpGroupsTest, self).tearDown() def test_get_shared_ip_groups(self): pass diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index df497ef1b..555b206b9 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -13,7 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import unittest import stubout import webob @@ -22,6 +21,7 @@ import json import nova.db from nova import context from nova import flags +from nova import test from nova.api.openstack import zones from nova.tests.api.openstack import fakes @@ -60,8 +60,9 @@ def zone_get_all(context): password='qwerty')] -class ZonesTest(unittest.TestCase): +class ZonesTest(test.TestCase): def setUp(self): + super(ZonesTest, self).setUp() self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} @@ -81,6 +82,7 @@ class ZonesTest(unittest.TestCase): def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + super(ZonesTest, self).tearDown() def test_get_zone_list(self): req = webob.Request.blank('/v1.0/zones') @@ -134,7 +136,3 @@ class ZonesTest(unittest.TestCase): self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') self.assertFalse('username' in res_dict['zone']) - - -if __name__ == '__main__': - unittest.main() diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index 44e2d615c..2c7852214 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -21,7 +21,7 @@ Test WSGI basics and provide some helper functions for other WSGI tests. """ -import unittest +from nova import test import routes import webob @@ -29,7 +29,7 @@ import webob from nova import wsgi -class Test(unittest.TestCase): +class Test(test.TestCase): def test_debug(self): @@ -92,7 +92,7 @@ class Test(unittest.TestCase): self.assertNotEqual(result.body, "123") -class SerializerTest(unittest.TestCase): +class SerializerTest(test.TestCase): def match(self, url, accept, expect): input_dict = dict(servers=dict(a=(2, 3))) diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py index da86e6e11..5a1be08eb 100644 --- a/nova/tests/objectstore_unittest.py +++ b/nova/tests/objectstore_unittest.py @@ -311,4 +311,5 @@ class S3APITestCase(test.TestCase): self.auth_manager.delete_user('admin') self.auth_manager.delete_project('admin') stop_listening = defer.maybeDeferred(self.listening_port.stopListening) + super(S3APITestCase, self).tearDown() return defer.DeferredList([stop_listening]) diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 7656f5396..b6bfab534 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -52,6 +52,7 @@ class DirectTestCase(test.TestCase): def tearDown(self): direct.ROUTES = {} + super(DirectTestCase, self).tearDown() def test_delegated_auth(self): req = webob.Request.blank('/fake/context') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 9d458244b..1bad364e5 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -150,6 +150,7 @@ class SimpleDriverTestCase(test.TestCase): def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) + super(SimpleDriverTestCase, self).tearDown() def _create_instance(self, **kwargs): """Create a test instance""" diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 6e5a0114b..7aadd65d5 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -206,9 +206,9 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) def tearDown(self): - super(LibvirtConnTestCase, self).tearDown() self.manager.delete_project(self.project) self.manager.delete_user(self.user) + super(LibvirtConnTestCase, self).tearDown() class IptablesFirewallTestCase(test.TestCase): @@ -388,6 +388,7 @@ class NWFilterTestCase(test.TestCase): def tearDown(self): self.manager.delete_project(self.project) self.manager.delete_user(self.user) + super(NWFilterTestCase, self).tearDown() def test_cidr_rule_nwfilter_xml(self): cloud_controller = cloud.CloudController() -- cgit From b09534dac05a3b4c127c633d8c050bb310a27166 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 11:52:10 -0800 Subject: put the redirection back in to run_tests.sh and fix terminal colors by using original stdout --- nova/tests/fake_flags.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 575fefff6..2b1919407 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -41,4 +41,3 @@ FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True FLAGS.sql_connection = 'sqlite:///tests.sqlite' FLAGS.use_ipv6 = True -FLAGS.logfile = 'tests.log' -- cgit From f7751eedc0e895f90d48104e2110bc2b320735fc Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 23 Feb 2011 13:53:02 -0600 Subject: Revert commit 709. This fixes issues with the Openstack API causing 'No user for access key admin' errors. --- nova/tests/api/openstack/fakes.py | 8 ++------ nova/tests/api/openstack/test_auth.py | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index e0b7b8029..fb282f1c9 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -221,8 +221,7 @@ class FakeAuthDatabase(object): class FakeAuthManager(object): auth_data = {} - def add_user(self, user): - key = user.id + def add_user(self, key, user): FakeAuthManager.auth_data[key] = user def get_user(self, uid): @@ -235,10 +234,7 @@ class FakeAuthManager(object): return None def get_user_from_access_key(self, key): - for k, v in FakeAuthManager.auth_data.iteritems(): - if v.access == key: - return v - return None + return FakeAuthManager.auth_data.get(key, None) class FakeRateLimiter(object): diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index eab78b50c..0dd65d321 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -48,7 +48,7 @@ class Test(unittest.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) + f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' @@ -62,7 +62,7 @@ class Test(unittest.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) + f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' @@ -144,7 +144,7 @@ class TestLimiter(unittest.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user(nova.auth.manager.User(1, 'herp', 'herp', 'derp', None)) + f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' -- cgit From 19dc13131b7fe512cb7897a888093b5c9a62e69d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 12:00:02 -0800 Subject: move the deletion of the db into fixtures --- nova/tests/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/__init__.py b/nova/tests/__init__.py index dbd433054..7fba02a93 100644 --- a/nova/tests/__init__.py +++ b/nova/tests/__init__.py @@ -48,6 +48,9 @@ def setup(): FLAGS = flags.FLAGS + testdb = os.path.join(FLAGS.state_path, FLAGS.sqlite_db) + if os.path.exists(testdb): + os.unlink(testdb) migration.db_sync() ctxt = context.get_admin_context() network_manager.VlanManager().create_networks(ctxt, @@ -58,5 +61,6 @@ def setup(): FLAGS.vlan_start, FLAGS.vpn_start, ) - shutil.copyfile(os.path.join(FLAGS.state_path, FLAGS.sqlite_db), - os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db)) + + cleandb = os.path.join(FLAGS.state_path, FLAGS.sqlite_clean_db) + shutil.copyfile(testdb, cleandb) -- cgit From 5283e1c131a21ea4963c702a7137536f7b894bb6 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Feb 2011 12:05:49 -0800 Subject: Created mini XPath implementation, to simplify mapping logic --- nova/tests/test_minixpath.py | 141 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 nova/tests/test_minixpath.py (limited to 'nova/tests') diff --git a/nova/tests/test_minixpath.py b/nova/tests/test_minixpath.py new file mode 100644 index 000000000..7fddcf9e9 --- /dev/null +++ b/nova/tests/test_minixpath.py @@ -0,0 +1,141 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# +# 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 nova import test +from nova import utils +from nova import exception + + +class MiniXPathTestCase(test.TestCase): + def test_tolerates_nones(self): + xp = utils.minixpath_select + + input = [] + self.assertEquals([], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [None] + self.assertEquals([], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': None}] + self.assertEquals([], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': None}}] + self.assertEquals([{'b': None}], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}] + self.assertEquals([{'b': {'c': None}}], xp(input, "a")) + self.assertEquals([{'c': None}], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}, {'a': None}] + self.assertEquals([{'b': {'c': None}}], xp(input, "a")) + self.assertEquals([{'c': None}], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}, {'a': {'b': None}}] + self.assertEquals([{'b': {'c': None}}, {'b': None}], xp(input, "a")) + self.assertEquals([{'c': None}], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + def test_does_select(self): + xp = utils.minixpath_select + + input = [{'a': 'a_1'}] + self.assertEquals(['a_1'], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': 'b_1'}}] + self.assertEquals([{'b': 'b_1'}], xp(input, "a")) + self.assertEquals(['b_1'], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}] + self.assertEquals([{'b': {'c': 'c_1'}}], xp(input, "a")) + self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) + self.assertEquals(['c_1'], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, {'a': None}] + self.assertEquals([{'b': {'c': 'c_1'}}], + xp(input, "a")) + self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) + self.assertEquals(['c_1'], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, + {'a': {'b': None}}] + self.assertEquals([{'b': {'c': 'c_1'}}, {'b': None}], + xp(input, "a")) + self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) + self.assertEquals(['c_1'], xp(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, + {'a': {'b': {'c': 'c_2'}}}] + self.assertEquals([{'b': {'c': 'c_1'}}, {'b': {'c': 'c_2'}}], + xp(input, "a")) + self.assertEquals([{'c': 'c_1'}, {'c': 'c_2'}], + xp(input, "a/b")) + self.assertEquals(['c_1', 'c_2'], xp(input, "a/b/c")) + + self.assertEquals([], xp(input, "a/b/c/d")) + self.assertEquals([], xp(input, "c/a/b/d")) + self.assertEquals([], xp(input, "i/r/t")) + + def test_flattens_lists(self): + xp = utils.minixpath_select + + input = [{'a': [1, 2, 3]}] + self.assertEquals([1, 2, 3], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': [1, 2, 3]}}] + self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a")) + self.assertEquals([1, 2, 3], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': {'b': [1, 2, 3]}}, {'a': {'b': [4, 5, 6]}}] + self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]}] + self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = [{'a': [1, 2, {'b': 'b_1'}]}] + self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a")) + self.assertEquals(['b_1'], xp(input, "a/b")) + + def test_bad_xpath(self): + xp = utils.minixpath_select + + self.assertRaises(exception.Error, xp, [], None) + self.assertRaises(exception.Error, xp, [], "") + self.assertRaises(exception.Error, xp, [], "/") + self.assertRaises(exception.Error, xp, [], "/a") + self.assertRaises(exception.Error, xp, [], "/a/") + self.assertRaises(exception.Error, xp, [], "//") + self.assertRaises(exception.Error, xp, [], "//a") + self.assertRaises(exception.Error, xp, [], "a//a") + self.assertRaises(exception.Error, xp, [], "a//a/") + self.assertRaises(exception.Error, xp, [], "a/a/") -- cgit From b3b005f50de54b5ef6c62e387dcec5a123f93cf6 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Feb 2011 12:36:09 -0800 Subject: Cope when we pass a non-list to xpath_select - wrap it in a list --- nova/tests/test_minixpath.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_minixpath.py b/nova/tests/test_minixpath.py index 7fddcf9e9..3b1bdf40b 100644 --- a/nova/tests/test_minixpath.py +++ b/nova/tests/test_minixpath.py @@ -139,3 +139,41 @@ class MiniXPathTestCase(test.TestCase): self.assertRaises(exception.Error, xp, [], "a//a") self.assertRaises(exception.Error, xp, [], "a//a/") self.assertRaises(exception.Error, xp, [], "a/a/") + + def test_real_failure1(self): + # Real world failure case... + # We weren't coping when the input was a Dictionary instead of a List + # This led to test_accepts_dictionaries + xp = utils.minixpath_select + + inst = {'fixed_ip': {'floating_ips': [{'address': '1.2.3.4'}], + 'address': '192.168.0.3'}, + 'hostname': ''} + + private_ips = xp(inst, 'fixed_ip/address') + public_ips = xp(inst, 'fixed_ip/floating_ips/address') + self.assertEquals(['192.168.0.3'], private_ips) + self.assertEquals(['1.2.3.4'], public_ips) + + def test_accepts_dictionaries(self): + xp = utils.minixpath_select + + input = {'a': [1, 2, 3]} + self.assertEquals([1, 2, 3], xp(input, "a")) + self.assertEquals([], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = {'a': {'b': [1, 2, 3]}} + self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a")) + self.assertEquals([1, 2, 3], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = {'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]} + self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) + self.assertEquals([], xp(input, "a/b/c")) + + input = {'a': [1, 2, {'b': 'b_1'}]} + self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a")) + self.assertEquals(['b_1'], xp(input, "a/b")) + + -- cgit From 89ade95d2eaabf77f9c81a8d50c7cc11aa175464 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Feb 2011 12:55:07 -0800 Subject: Fix pep8 violation (trailing whitespace) --- nova/tests/test_minixpath.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_minixpath.py b/nova/tests/test_minixpath.py index 3b1bdf40b..cc4a35ef3 100644 --- a/nova/tests/test_minixpath.py +++ b/nova/tests/test_minixpath.py @@ -175,5 +175,3 @@ class MiniXPathTestCase(test.TestCase): input = {'a': [1, 2, {'b': 'b_1'}]} self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a")) self.assertEquals(['b_1'], xp(input, "a/b")) - - -- cgit From 1183c9e11b12984b1f5007ace831864e80483712 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 23 Feb 2011 14:07:08 -0800 Subject: Rename minixpath_select to get_from_path --- nova/tests/test_minixpath.py | 177 ------------------------------------------- nova/tests/test_utils.py | 174 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 177 deletions(-) delete mode 100644 nova/tests/test_minixpath.py create mode 100644 nova/tests/test_utils.py (limited to 'nova/tests') diff --git a/nova/tests/test_minixpath.py b/nova/tests/test_minixpath.py deleted file mode 100644 index cc4a35ef3..000000000 --- a/nova/tests/test_minixpath.py +++ /dev/null @@ -1,177 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 Justin Santa Barbara -# -# 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 nova import test -from nova import utils -from nova import exception - - -class MiniXPathTestCase(test.TestCase): - def test_tolerates_nones(self): - xp = utils.minixpath_select - - input = [] - self.assertEquals([], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [None] - self.assertEquals([], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': None}] - self.assertEquals([], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': None}}] - self.assertEquals([{'b': None}], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': None}}}] - self.assertEquals([{'b': {'c': None}}], xp(input, "a")) - self.assertEquals([{'c': None}], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': None}}}, {'a': None}] - self.assertEquals([{'b': {'c': None}}], xp(input, "a")) - self.assertEquals([{'c': None}], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': None}}}, {'a': {'b': None}}] - self.assertEquals([{'b': {'c': None}}, {'b': None}], xp(input, "a")) - self.assertEquals([{'c': None}], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - def test_does_select(self): - xp = utils.minixpath_select - - input = [{'a': 'a_1'}] - self.assertEquals(['a_1'], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': 'b_1'}}] - self.assertEquals([{'b': 'b_1'}], xp(input, "a")) - self.assertEquals(['b_1'], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': 'c_1'}}}] - self.assertEquals([{'b': {'c': 'c_1'}}], xp(input, "a")) - self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) - self.assertEquals(['c_1'], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': 'c_1'}}}, {'a': None}] - self.assertEquals([{'b': {'c': 'c_1'}}], - xp(input, "a")) - self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) - self.assertEquals(['c_1'], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': 'c_1'}}}, - {'a': {'b': None}}] - self.assertEquals([{'b': {'c': 'c_1'}}, {'b': None}], - xp(input, "a")) - self.assertEquals([{'c': 'c_1'}], xp(input, "a/b")) - self.assertEquals(['c_1'], xp(input, "a/b/c")) - - input = [{'a': {'b': {'c': 'c_1'}}}, - {'a': {'b': {'c': 'c_2'}}}] - self.assertEquals([{'b': {'c': 'c_1'}}, {'b': {'c': 'c_2'}}], - xp(input, "a")) - self.assertEquals([{'c': 'c_1'}, {'c': 'c_2'}], - xp(input, "a/b")) - self.assertEquals(['c_1', 'c_2'], xp(input, "a/b/c")) - - self.assertEquals([], xp(input, "a/b/c/d")) - self.assertEquals([], xp(input, "c/a/b/d")) - self.assertEquals([], xp(input, "i/r/t")) - - def test_flattens_lists(self): - xp = utils.minixpath_select - - input = [{'a': [1, 2, 3]}] - self.assertEquals([1, 2, 3], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': [1, 2, 3]}}] - self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a")) - self.assertEquals([1, 2, 3], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': {'b': [1, 2, 3]}}, {'a': {'b': [4, 5, 6]}}] - self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]}] - self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = [{'a': [1, 2, {'b': 'b_1'}]}] - self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a")) - self.assertEquals(['b_1'], xp(input, "a/b")) - - def test_bad_xpath(self): - xp = utils.minixpath_select - - self.assertRaises(exception.Error, xp, [], None) - self.assertRaises(exception.Error, xp, [], "") - self.assertRaises(exception.Error, xp, [], "/") - self.assertRaises(exception.Error, xp, [], "/a") - self.assertRaises(exception.Error, xp, [], "/a/") - self.assertRaises(exception.Error, xp, [], "//") - self.assertRaises(exception.Error, xp, [], "//a") - self.assertRaises(exception.Error, xp, [], "a//a") - self.assertRaises(exception.Error, xp, [], "a//a/") - self.assertRaises(exception.Error, xp, [], "a/a/") - - def test_real_failure1(self): - # Real world failure case... - # We weren't coping when the input was a Dictionary instead of a List - # This led to test_accepts_dictionaries - xp = utils.minixpath_select - - inst = {'fixed_ip': {'floating_ips': [{'address': '1.2.3.4'}], - 'address': '192.168.0.3'}, - 'hostname': ''} - - private_ips = xp(inst, 'fixed_ip/address') - public_ips = xp(inst, 'fixed_ip/floating_ips/address') - self.assertEquals(['192.168.0.3'], private_ips) - self.assertEquals(['1.2.3.4'], public_ips) - - def test_accepts_dictionaries(self): - xp = utils.minixpath_select - - input = {'a': [1, 2, 3]} - self.assertEquals([1, 2, 3], xp(input, "a")) - self.assertEquals([], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = {'a': {'b': [1, 2, 3]}} - self.assertEquals([{'b': [1, 2, 3]}], xp(input, "a")) - self.assertEquals([1, 2, 3], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = {'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]} - self.assertEquals([1, 2, 3, 4, 5, 6], xp(input, "a/b")) - self.assertEquals([], xp(input, "a/b/c")) - - input = {'a': [1, 2, {'b': 'b_1'}]} - self.assertEquals([1, 2, {'b': 'b_1'}], xp(input, "a")) - self.assertEquals(['b_1'], xp(input, "a/b")) diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py new file mode 100644 index 000000000..34a407f1a --- /dev/null +++ b/nova/tests/test_utils.py @@ -0,0 +1,174 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# +# 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 nova import test +from nova import utils +from nova import exception + + +class GetFromPathTestCase(test.TestCase): + def test_tolerates_nones(self): + f = utils.get_from_path + + input = [] + self.assertEquals([], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [None] + self.assertEquals([], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': None}] + self.assertEquals([], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': None}}] + self.assertEquals([{'b': None}], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}] + self.assertEquals([{'b': {'c': None}}], f(input, "a")) + self.assertEquals([{'c': None}], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}, {'a': None}] + self.assertEquals([{'b': {'c': None}}], f(input, "a")) + self.assertEquals([{'c': None}], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': None}}}, {'a': {'b': None}}] + self.assertEquals([{'b': {'c': None}}, {'b': None}], f(input, "a")) + self.assertEquals([{'c': None}], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + def test_does_select(self): + f = utils.get_from_path + + input = [{'a': 'a_1'}] + self.assertEquals(['a_1'], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': 'b_1'}}] + self.assertEquals([{'b': 'b_1'}], f(input, "a")) + self.assertEquals(['b_1'], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}] + self.assertEquals([{'b': {'c': 'c_1'}}], f(input, "a")) + self.assertEquals([{'c': 'c_1'}], f(input, "a/b")) + self.assertEquals(['c_1'], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, {'a': None}] + self.assertEquals([{'b': {'c': 'c_1'}}], f(input, "a")) + self.assertEquals([{'c': 'c_1'}], f(input, "a/b")) + self.assertEquals(['c_1'], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, + {'a': {'b': None}}] + self.assertEquals([{'b': {'c': 'c_1'}}, {'b': None}], f(input, "a")) + self.assertEquals([{'c': 'c_1'}], f(input, "a/b")) + self.assertEquals(['c_1'], f(input, "a/b/c")) + + input = [{'a': {'b': {'c': 'c_1'}}}, + {'a': {'b': {'c': 'c_2'}}}] + self.assertEquals([{'b': {'c': 'c_1'}}, {'b': {'c': 'c_2'}}], + f(input, "a")) + self.assertEquals([{'c': 'c_1'}, {'c': 'c_2'}], f(input, "a/b")) + self.assertEquals(['c_1', 'c_2'], f(input, "a/b/c")) + + self.assertEquals([], f(input, "a/b/c/d")) + self.assertEquals([], f(input, "c/a/b/d")) + self.assertEquals([], f(input, "i/r/t")) + + def test_flattens_lists(self): + f = utils.get_from_path + + input = [{'a': [1, 2, 3]}] + self.assertEquals([1, 2, 3], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': [1, 2, 3]}}] + self.assertEquals([{'b': [1, 2, 3]}], f(input, "a")) + self.assertEquals([1, 2, 3], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': {'b': [1, 2, 3]}}, {'a': {'b': [4, 5, 6]}}] + self.assertEquals([1, 2, 3, 4, 5, 6], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]}] + self.assertEquals([1, 2, 3, 4, 5, 6], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = [{'a': [1, 2, {'b': 'b_1'}]}] + self.assertEquals([1, 2, {'b': 'b_1'}], f(input, "a")) + self.assertEquals(['b_1'], f(input, "a/b")) + + def test_bad_xpath(self): + f = utils.get_from_path + + self.assertRaises(exception.Error, f, [], None) + self.assertRaises(exception.Error, f, [], "") + self.assertRaises(exception.Error, f, [], "/") + self.assertRaises(exception.Error, f, [], "/a") + self.assertRaises(exception.Error, f, [], "/a/") + self.assertRaises(exception.Error, f, [], "//") + self.assertRaises(exception.Error, f, [], "//a") + self.assertRaises(exception.Error, f, [], "a//a") + self.assertRaises(exception.Error, f, [], "a//a/") + self.assertRaises(exception.Error, f, [], "a/a/") + + def test_real_failure1(self): + # Real world failure case... + # We weren't coping when the input was a Dictionary instead of a List + # This led to test_accepts_dictionaries + f = utils.get_from_path + + inst = {'fixed_ip': {'floating_ips': [{'address': '1.2.3.4'}], + 'address': '192.168.0.3'}, + 'hostname': ''} + + private_ips = f(inst, 'fixed_ip/address') + public_ips = f(inst, 'fixed_ip/floating_ips/address') + self.assertEquals(['192.168.0.3'], private_ips) + self.assertEquals(['1.2.3.4'], public_ips) + + def test_accepts_dictionaries(self): + f = utils.get_from_path + + input = {'a': [1, 2, 3]} + self.assertEquals([1, 2, 3], f(input, "a")) + self.assertEquals([], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = {'a': {'b': [1, 2, 3]}} + self.assertEquals([{'b': [1, 2, 3]}], f(input, "a")) + self.assertEquals([1, 2, 3], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = {'a': [{'b': [1, 2, 3]}, {'b': [4, 5, 6]}]} + self.assertEquals([1, 2, 3, 4, 5, 6], f(input, "a/b")) + self.assertEquals([], f(input, "a/b/c")) + + input = {'a': [1, 2, {'b': 'b_1'}]} + self.assertEquals([1, 2, {'b': 'b_1'}], f(input, "a")) + self.assertEquals(['b_1'], f(input, "a/b")) -- cgit From 05065a72ab06879d8ddd48ab45bc870386a0562d Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 23 Feb 2011 14:41:11 -0800 Subject: tests working again --- nova/tests/test_rpc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_rpc.py b/nova/tests/test_rpc.py index 4820e04fb..44d7c91eb 100644 --- a/nova/tests/test_rpc.py +++ b/nova/tests/test_rpc.py @@ -36,7 +36,7 @@ class RpcTestCase(test.TestCase): super(RpcTestCase, self).setUp() self.conn = rpc.Connection.instance(True) self.receiver = TestReceiver() - self.consumer = rpc.AdapterConsumer(connection=self.conn, + self.consumer = rpc.TopicAdapterConsumer(connection=self.conn, topic='test', proxy=self.receiver) self.consumer.attach_to_eventlet() @@ -97,7 +97,7 @@ class RpcTestCase(test.TestCase): nested = Nested() conn = rpc.Connection.instance(True) - consumer = rpc.AdapterConsumer(connection=conn, + consumer = rpc.TopicAdapterConsumer(connection=conn, topic='nested', proxy=nested) consumer.attach_to_eventlet() -- cgit From 24090232272e0db163060e0ca32dbf97c05120c9 Mon Sep 17 00:00:00 2001 From: termie Date: Wed, 23 Feb 2011 15:14:16 -0800 Subject: updates to nova.flags to get help working better Fixes some old bugs that were brought up on the mailing list. First step towards moving flags into the places where they belong. Also moves manager import into service's init so that we can get all the dynamically loaded flags shortly after loading. --- nova/tests/test_service.py | 7 ------- 1 file changed, 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index a67c8d1e8..45d9afa6c 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -50,13 +50,6 @@ class ExtendedService(service.Service): class ServiceManagerTestCase(test.TestCase): """Test cases for Services""" - def test_attribute_error_for_no_manager(self): - serv = service.Service('test', - 'test', - 'test', - 'nova.tests.test_service.FakeManager') - self.assertRaises(AttributeError, getattr, serv, 'test_method') - def test_message_gets_to_manager(self): serv = service.Service('test', 'test', -- cgit From 5e2f82b1487b8f8e43539d0c71466fbbfed23121 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 23 Feb 2011 15:29:02 -0800 Subject: revert logfile redirection and make colors work by temporarily switching stdout --- nova/tests/fake_flags.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index 575fefff6..2b1919407 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -41,4 +41,3 @@ FLAGS.iscsi_num_targets = 8 FLAGS.verbose = True FLAGS.sql_connection = 'sqlite:///tests.sqlite' FLAGS.use_ipv6 = True -FLAGS.logfile = 'tests.log' -- cgit From 05fc3ea219f36bc1c246179b25b1feb017888b01 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 23 Feb 2011 17:58:32 -0800 Subject: Tests all working again --- nova/tests/test_service.py | 25 ++++++++++++++----------- nova/tests/test_test.py | 2 +- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index cb31a3c43..b006caadd 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -108,26 +108,29 @@ class ServiceTestCase(test.TestCase): app = service.Service.create(host=host, binary=binary) self.mox.StubOutWithMock(rpc, - 'AdapterConsumer', + 'TopicAdapterConsumer', use_mock_anything=True) - rpc.AdapterConsumer(connection=mox.IgnoreArg(), + self.mox.StubOutWithMock(rpc, + 'FanoutAdapterConsumer', + use_mock_anything=True) + rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), topic=topic, proxy=mox.IsA(service.Service)).AndReturn( - rpc.AdapterConsumer) + rpc.TopicAdapterConsumer) - rpc.AdapterConsumer(connection=mox.IgnoreArg(), + rpc.TopicAdapterConsumer(connection=mox.IgnoreArg(), topic='%s.%s' % (topic, host), proxy=mox.IsA(service.Service)).AndReturn( - rpc.AdapterConsumer) + rpc.TopicAdapterConsumer) - rpc.AdapterConsumer(connection=mox.IgnoreArg(), - topic='%s_fanout' % topic, + rpc.FanoutAdapterConsumer(connection=mox.IgnoreArg(), + topic=topic, proxy=mox.IsA(service.Service)).AndReturn( - rpc.AdapterConsumer) + rpc.FanoutAdapterConsumer) - rpc.AdapterConsumer.attach_to_eventlet() - rpc.AdapterConsumer.attach_to_eventlet() - rpc.AdapterConsumer.attach_to_eventlet() + rpc.TopicAdapterConsumer.attach_to_eventlet() + rpc.TopicAdapterConsumer.attach_to_eventlet() + rpc.FanoutAdapterConsumer.attach_to_eventlet() service_create = {'host': host, 'binary': binary, diff --git a/nova/tests/test_test.py b/nova/tests/test_test.py index e237674e6..35c838065 100644 --- a/nova/tests/test_test.py +++ b/nova/tests/test_test.py @@ -34,7 +34,7 @@ class IsolationTestCase(test.TestCase): def test_rpc_consumer_isolation(self): connection = rpc.Connection.instance(new=True) - consumer = rpc.TopicConsumer(connection, topic='compute') + consumer = rpc.TopicAdapterConsumer(connection, topic='compute') consumer.register_callback( lambda x, y: self.fail('I should never be called')) consumer.attach_to_eventlet() -- cgit From 8e2ebb1a963f58514d8fb6aab4a75627e72484b9 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 24 Feb 2011 16:04:13 +0000 Subject: stubbing out _is_vdi_pv for test purposes --- nova/tests/test_xenapi.py | 1 + nova/tests/xenapi/stubs.py | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 6b8efc9d8..2cbe58aab 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -167,6 +167,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) stubs.stubout_get_this_vm_uuid(self.stubs) stubs.stubout_stream_disk(self.stubs) + stubs.stubout_is_vdi_pv(self.stubs) self.stubs.Set(VMOps, 'reset_network', reset_network) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 624995ada..4fec2bd75 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -130,6 +130,12 @@ def stubout_stream_disk(stubs): stubs.Set(vm_utils, '_stream_disk', f) +def stubout_is_vdi_pv(stubs): + def f(_1): + return False + stubs.Set(vm_utils, '_is_vdi_pv', f) + + class FakeSessionForVMTests(fake.SessionBase): """ Stubs out a XenAPISession for VM tests """ def __init__(self, uri): -- cgit From c8df2602fd8f4f2cb7716e6283f3779c6895a479 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 24 Feb 2011 14:32:25 -0800 Subject: service capabilities test --- nova/tests/test_zones.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 5a52a0506..3ca71d5f1 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -76,6 +76,34 @@ class ZoneManagerTestCase(test.TestCase): self.assertEquals(len(zm.zone_states), 1) self.assertEquals(zm.zone_states[1].username, 'user1') + def test_service_capabilities(self): + zm = zone_manager.ZoneManager() + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, {}) + + zm.update_service_capabilities("svc1", "host1", dict(a=1, b=2)) + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, dict(svc1_a=(1, 1), svc1_b=(2, 2))) + + zm.update_service_capabilities("svc1", "host1", dict(a=2, b=3)) + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, dict(svc1_a=(2, 2), svc1_b=(3, 3))) + + zm.update_service_capabilities("svc1", "host2", dict(a=20, b=30)) + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30))) + + zm.update_service_capabilities("svc10", "host1", dict(a=99, b=99)) + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), + svc10_a=(99, 99), svc10_b=(99, 99))) + + zm.update_service_capabilities("svc1", "host3", dict(c=5)) + caps = zm.get_zone_capabilities(self, None) + self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), + svc1_c=(5, 5), svc10_a=(99, 99), + svc10_b=(99, 99))) + def test_refresh_from_db_replace_existing(self): zm = zone_manager.ZoneManager() zone_state = zone_manager.ZoneState() -- cgit From 47bbfaab52642f3ff79bcdefb8d705fb02b549f9 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 24 Feb 2011 15:23:15 -0800 Subject: new tests --- nova/tests/api/openstack/test_zones.py | 30 +++++++++++++++++++++++++++--- nova/tests/test_zones.py | 6 ++++++ 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 82b892b9e..33a66df0b 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -75,6 +75,10 @@ def zone_get_all_db(context): ] +def zone_caps(method, context, params): + return dict() + + class ZonesTest(test.TestCase): def setUp(self): super(ZonesTest, self).setUp() @@ -93,13 +97,18 @@ class ZonesTest(test.TestCase): self.stubs.Set(nova.db, 'zone_create', zone_create) self.stubs.Set(nova.db, 'zone_delete', zone_delete) + self.old_zone_name = FLAGS.zone_name + self.old_zone_caps = FLAGS.zone_capabilities + def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin + FLAGS.zone_name = self.old_zone_name + FLAGS.zone_capabilities = self.old_zone_caps super(ZonesTest, self).tearDown() def test_get_zone_list_scheduler(self): - self.stubs.Set(api.API, '_call_scheduler', zone_get_all_scheduler) + self.stubs.Set(api, '_call_scheduler', zone_get_all_scheduler) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -108,8 +117,7 @@ class ZonesTest(test.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_list_db(self): - self.stubs.Set(api.API, '_call_scheduler', - zone_get_all_scheduler_empty) + self.stubs.Set(api, '_call_scheduler', zone_get_all_scheduler_empty) self.stubs.Set(nova.db, 'zone_get_all', zone_get_all_db) req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) @@ -162,3 +170,19 @@ class ZonesTest(test.TestCase): self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://example.com') self.assertFalse('username' in res_dict['zone']) + + def test_zone_info(self): + FLAGS.zone_name = 'darksecret' + FLAGS.zone_capabilities = 'cap1:a,b;cap2:c,d' + self.stubs.Set(api, '_call_scheduler', zone_caps) + + body = dict(zone=dict(username='zeb', password='sneaky')) + req = webob.Request.blank('/v1.0/zones/info') + + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['zone']['name'], 'darksecret') + self.assertEqual(res_dict['zone']['cap1'], 'a,b') + self.assertEqual(res_dict['zone']['cap2'], 'c,d') + diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 3ca71d5f1..79d766f28 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -104,6 +104,12 @@ class ZoneManagerTestCase(test.TestCase): svc1_c=(5, 5), svc10_a=(99, 99), svc10_b=(99, 99))) + caps = zm.get_zone_capabilities(self, 'svc1') + self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), + svc1_c=(5, 5))) + caps = zm.get_zone_capabilities(self, 'svc10') + self.assertEquals(caps, dict(svc10_a=(99, 99), svc10_b=(99, 99))) + def test_refresh_from_db_replace_existing(self): zm = zone_manager.ZoneManager() zone_state = zone_manager.ZoneState() -- cgit From 307dcb7906ff066e2883cdee8998dfa78ebc8221 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 24 Feb 2011 15:44:27 -0800 Subject: sorry, pep8 --- nova/tests/api/openstack/test_zones.py | 5 ++--- nova/tests/test_zones.py | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 33a66df0b..a40d46749 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -76,7 +76,7 @@ def zone_get_all_db(context): def zone_caps(method, context, params): - return dict() + return dict() class ZonesTest(test.TestCase): @@ -175,7 +175,7 @@ class ZonesTest(test.TestCase): FLAGS.zone_name = 'darksecret' FLAGS.zone_capabilities = 'cap1:a,b;cap2:c,d' self.stubs.Set(api, '_call_scheduler', zone_caps) - + body = dict(zone=dict(username='zeb', password='sneaky')) req = webob.Request.blank('/v1.0/zones/info') @@ -185,4 +185,3 @@ class ZonesTest(test.TestCase): self.assertEqual(res_dict['zone']['name'], 'darksecret') self.assertEqual(res_dict['zone']['cap1'], 'a,b') self.assertEqual(res_dict['zone']['cap2'], 'c,d') - diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 79d766f28..48e1442cf 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -88,28 +88,28 @@ class ZoneManagerTestCase(test.TestCase): zm.update_service_capabilities("svc1", "host1", dict(a=2, b=3)) caps = zm.get_zone_capabilities(self, None) self.assertEquals(caps, dict(svc1_a=(2, 2), svc1_b=(3, 3))) - + zm.update_service_capabilities("svc1", "host2", dict(a=20, b=30)) caps = zm.get_zone_capabilities(self, None) self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30))) - + zm.update_service_capabilities("svc10", "host1", dict(a=99, b=99)) caps = zm.get_zone_capabilities(self, None) self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), svc10_a=(99, 99), svc10_b=(99, 99))) - + zm.update_service_capabilities("svc1", "host3", dict(c=5)) caps = zm.get_zone_capabilities(self, None) self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), svc1_c=(5, 5), svc10_a=(99, 99), svc10_b=(99, 99))) - + caps = zm.get_zone_capabilities(self, 'svc1') self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), svc1_c=(5, 5))) caps = zm.get_zone_capabilities(self, 'svc10') self.assertEquals(caps, dict(svc10_a=(99, 99), svc10_b=(99, 99))) - + def test_refresh_from_db_replace_existing(self): zm = zone_manager.ZoneManager() zone_state = zone_manager.ZoneState() -- cgit From 2218cb025adca1ded3e6596acc182b88742e3a51 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 24 Feb 2011 21:59:36 -0500 Subject: Rename auth_token db methods to follow standard. --- nova/tests/api/openstack/fakes.py | 6 +++--- nova/tests/api/openstack/test_auth.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index fb282f1c9..142626de9 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -203,17 +203,17 @@ class FakeAuthDatabase(object): data = {} @staticmethod - def auth_get_token(context, token_hash): + def auth_token_get(context, token_hash): return FakeAuthDatabase.data.get(token_hash, None) @staticmethod - def auth_create_token(context, token): + def auth_token_create(context, token): fake_token = FakeToken(created_at=datetime.datetime.now(), **token) FakeAuthDatabase.data[fake_token.token_hash] = fake_token return fake_token @staticmethod - def auth_destroy_token(context, token): + def auth_token_destroy(context, token): if token.token_hash in FakeAuthDatabase.data: del FakeAuthDatabase.data['token_hash'] diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 13f6c3a1c..86dfb110f 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -99,10 +99,10 @@ class Test(test.TestCase): token_hash=token_hash, created_at=datetime.datetime(1990, 1, 1)) - self.stubs.Set(fakes.FakeAuthDatabase, 'auth_destroy_token', + self.stubs.Set(fakes.FakeAuthDatabase, 'auth_token_destroy', destroy_token_mock) - self.stubs.Set(fakes.FakeAuthDatabase, 'auth_get_token', + self.stubs.Set(fakes.FakeAuthDatabase, 'auth_token_get', bad_token) req = webob.Request.blank('/v1.0/') -- cgit From 865c3d57f8b84dfcc493ecead12816874b160e35 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 24 Feb 2011 23:51:17 -0500 Subject: Pass id of token to be deleted to the db api, not the actual object. --- nova/tests/api/openstack/fakes.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 142626de9..49ce8c1b5 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -188,7 +188,11 @@ def stub_out_glance(stubs, initial_fixtures=None): class FakeToken(object): + id = 0 + def __init__(self, **kwargs): + FakeToken.id += 1 + self.id = FakeToken.id for k, v in kwargs.iteritems(): setattr(self, k, v) @@ -210,12 +214,15 @@ class FakeAuthDatabase(object): def auth_token_create(context, token): fake_token = FakeToken(created_at=datetime.datetime.now(), **token) FakeAuthDatabase.data[fake_token.token_hash] = fake_token + FakeAuthDatabase.data['id_%i' % fake_token.id] = fake_token return fake_token @staticmethod - def auth_token_destroy(context, token): - if token.token_hash in FakeAuthDatabase.data: - del FakeAuthDatabase.data['token_hash'] + def auth_token_destroy(context, token_id): + token = FakeAuthDatabase.data.get('id_%i' % token_id) + if token and token.token_hash in FakeAuthDatabase.data: + del FakeAuthDatabase.data[token.token_hash] + del FakeAuthDatabase.data['id_%i' % token_id] class FakeAuthManager(object): -- cgit From 4453021476fac599c0cee126b6eaa426d4878145 Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Fri, 18 Mar 2011 02:09:46 +0000 Subject: Copy over to current trunk my tests, the 401/500 fix, and a couple of fixes to the committed fix which was actually brittle around the edges... --- nova/tests/api/openstack/test_auth.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 86dfb110f..c42c12f7b 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -26,6 +26,7 @@ import nova.api.openstack.auth import nova.auth.manager from nova import auth from nova import context +from nova import db from nova import test from nova.tests.api.openstack import fakes @@ -130,6 +131,33 @@ class Test(test.TestCase): self.assertEqual(result.status, '401 Unauthorized') +class TestFunctional(test.TestCase): + def test_token_lp718999(self): + ctx = context.get_admin_context() + tok = db.auth_token_create(ctx, dict( + token_hash='bacon', + cdn_management_url='', + server_management_url='', + storage_url='', + user_id='ham', + )) + + db.auth_token_update(ctx, tok.token_hash, dict( + created_at=datetime.datetime(2000, 1, 1, 12, 0, 0), + )) + + req = webob.Request.blank('/v1.0/') + req.headers['X-Auth-Token'] = 'bacon' + result = req.get_response(fakes.wsgi_app()) + self.assertEqual(result.status, '401 Unauthorized') + + def test_token_doesnotexist(self): + req = webob.Request.blank('/v1.0/') + req.headers['X-Auth-Token'] = 'ham' + result = req.get_response(fakes.wsgi_app()) + self.assertEqual(result.status, '401 Unauthorized') + + class TestLimiter(test.TestCase): def setUp(self): super(TestLimiter, self).setUp() -- cgit From fa6778586ab303f9e65aa3c50b80d20a4f097c6f Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Mon, 21 Mar 2011 00:41:23 +0000 Subject: Rename test to describe what it actually does --- nova/tests/api/openstack/test_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index c42c12f7b..ff8d42a14 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -132,7 +132,7 @@ class Test(test.TestCase): class TestFunctional(test.TestCase): - def test_token_lp718999(self): + def test_token_expiry(self): ctx = context.get_admin_context() tok = db.auth_token_create(ctx, dict( token_hash='bacon', -- cgit From 031205a26ae6fe906a47eefa716bbd575687c479 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Sun, 27 Feb 2011 13:35:10 -0500 Subject: Add lxc to the libvirt tests --- nova/tests/test_virt.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index f151ae911..04f943a1f 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -112,12 +112,15 @@ class LibvirtConnTestCase(test.TestCase): 'uml': ('uml:///system', [(lambda t: t.find('.').get('type'), 'uml'), (lambda t: t.find('./os/type').text, 'uml')]), + 'lxc': ('lxc://', + [(lambda t: t.find('.').get('type'), 'lxc'), + (lambda t: t.find('./os/type').text, 'lxc')]), 'xen': ('xen:///', [(lambda t: t.find('.').get('type'), 'xen'), (lambda t: t.find('./os/type').text, 'linux')]), } - for hypervisor_type in ['qemu', 'kvm', 'xen']: + for hypervisor_type in ['qemu', 'kvm', 'lxc', 'xen']: check_list = type_uri_map[hypervisor_type][1] if rescue: -- cgit From 8b3e9ad11c2f5c425701f1eb4abb7b3f577ae1cc Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 28 Feb 2011 12:37:02 +0100 Subject: Add utils.synchronized decorator to allow for synchronising method entrance across multiple workers on the same host. --- nova/tests/test_misc.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index e6da6112a..154b6fae6 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -14,10 +14,14 @@ # License for the specific language governing permissions and limitations # under the License. +from datetime import datetime +import errno import os +import select +import time from nova import test -from nova.utils import parse_mailmap, str_dict_replace +from nova.utils import parse_mailmap, str_dict_replace, synchronized class ProjectTestCase(test.TestCase): @@ -55,3 +59,34 @@ class ProjectTestCase(test.TestCase): '%r not listed in Authors' % missing) finally: tree.unlock() + + +class LockTestCase(test.TestCase): + def test_synchronized(self): + rpipe, wpipe = os.pipe() + pid = os.fork() + if pid > 0: + os.close(wpipe) + + @synchronized('testlock') + def f(): + rfds, _, __ = select.select([rpipe], [], [], 1) + self.assertEquals(len(rfds), 0, "The other process, which was" + " supposed to be locked, " + "wrote on its end of the " + "pipe") + os.close(rpipe) + + f() + else: + os.close(rpipe) + + @synchronized('testlock') + def g(): + try: + os.write(wpipe, "foo") + except OSError, e: + self.assertEquals(e.errno, errno.EPIPE) + return + g() + os._exit(0) -- cgit From a457595224a5ca5cdb0191ba2f6fa542d16e18f5 Mon Sep 17 00:00:00 2001 From: Nirmal Ranganathan Date: Mon, 28 Feb 2011 11:25:14 -0600 Subject: Removed extraneous newline --- nova/tests/test_compute.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index e338a7cfa..949b5e6eb 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -274,4 +274,3 @@ class ComputeTestCase(test.TestCase): type = instance_types.get_by_flavor_id("1") self.assertEqual(type, 'm1.tiny') - -- cgit From 7f3dbdab80a4b36a75c860fe1748dfbd03228f2a Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 28 Feb 2011 11:29:52 -0800 Subject: moving nova-manage integration tests to smoke tests --- nova/tests/test_nova_manage.py | 130 ----------------------------------------- 1 file changed, 130 deletions(-) delete mode 100644 nova/tests/test_nova_manage.py (limited to 'nova/tests') diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py deleted file mode 100644 index 03aea53c9..000000000 --- a/nova/tests/test_nova_manage.py +++ /dev/null @@ -1,130 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# 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. -""" -Tests For Nova-Manage -""" - -import time -import os -import subprocess - -from nova import test -from nova.db.sqlalchemy.session import get_session -from nova.db.sqlalchemy import models - - -class NovaManageTestCase(test.TestCase): - """Test case for nova-manage""" - def setUp(self): - super(NovaManageTestCase, self).setUp() - session = get_session() - max_flavorid = session.query(models.InstanceTypes).\ - order_by("flavorid desc").first() - self.flavorid = str(max_flavorid["flavorid"] + 1) - self.name = str(int(time.time())) - self.fnull = open(os.devnull, 'w') - - def teardown(self): - self.fnull.close() - - def test_create_and_delete_instance_types(self): - myname = self.name + "create_and_delete" - retcode = subprocess.call([ - "bin/nova-manage", - "instance_type", - "create", - self.name, - "256", - "1", - "120", - self.flavorid, - "2", - "10", - "10"], - stdout=self.fnull) - self.assertEqual(0, retcode) - retcode = subprocess.call(["bin/nova-manage", "instance_type", - "delete", self.name], stdout=self.fnull) - self.assertEqual(0, retcode) - retcode = subprocess.call(["bin/nova-manage", "instance_type", - "delete", self.name, "--purge"], - stdout=self.fnull) - self.assertEqual(0, retcode) - - def test_list_instance_types_or_flavors(self): - for c in ["instance_type", "flavor"]: - retcode = subprocess.call(["bin/nova-manage", c, \ - "list"], stdout=self.fnull) - self.assertEqual(0, retcode) - - def test_list_specific_instance_type(self): - retcode = subprocess.call(["bin/nova-manage", "instance_type", "list", - "m1.medium"], stdout=self.fnull) - self.assertEqual(0, retcode) - - def test_should_error_on_bad_create_args(self): - # shouldn't be able to create instance type with 0 vcpus - retcode = subprocess.call(["bin/nova-manage", "instance_type", - "create", self.name + "bad_args", - "256", "0", "120", self.flavorid], - stdout=self.fnull) - self.assertEqual(1, retcode) - - def test_should_fail_on_duplicate_flavorid(self): - # flavorid 1 is set in migration seed data - retcode = subprocess.call(["bin/nova-manage", "instance_type",\ - "create", self.name + "dupflavor", "256", - "1", "120", "1"], stdout=self.fnull) - self.assertEqual(3, retcode) - - def test_should_fail_on_duplicate_name(self): - duplicate_name = self.name + "dup_name" - retcode = subprocess.call([ - "bin/nova-manage", - "instance_type", - "create", - duplicate_name, - "256", - "1", - "120", - self.flavorid, - "2", - "10", - "10"], - stdout=self.fnull) - self.assertEqual(0, retcode) - duplicate_retcode = subprocess.call([ - "bin/nova-manage", - "instance_type", - "create", - duplicate_name, - "512", - "1", - "240", - str(int(self.flavorid) + 1), - "2", - "10", - "10"], - stdout=self.fnull) - self.assertEqual(3, duplicate_retcode) - delete_retcode = subprocess.call(["bin/nova-manage", "instance_type", - "delete", duplicate_name, "--purge"], - stdout=self.fnull) - self.assertEqual(0, delete_retcode) - - def test_instance_type_delete_should_fail_without_valid_name(self): - retcode = subprocess.call(["bin/nova-manage", "instance_type", - "delete", "doesntexist"], - stdout=self.fnull) - self.assertEqual(1, retcode) -- cgit From 05a96b320cf1d6b911b0edb11df0ed408a894e77 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 28 Feb 2011 14:49:03 -0500 Subject: Edited `nova.api.openstack.common:limited` method to raise an HTTPBadRequest exception if a negative limit or offset is given. I'm not confident that this is the correct approach, because I guess this method could be called out of an API/WSGI context, but the method *is* located in the OpenStack API module and is currently only used in WSGI-capable methods, so we should be safe. --- nova/tests/api/openstack/test_common.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 59d850157..92023362c 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -19,6 +19,7 @@ Test suites for 'common' code used throughout the OpenStack HTTP API. """ +import webob.exc from webob import Request @@ -160,3 +161,23 @@ class LimiterTest(test.TestCase): self.assertEqual(limited(items, req, max_limit=2000), items[3:]) req = Request.blank('/?offset=3000&limit=10') self.assertEqual(limited(items, req, max_limit=2000), []) + + def test_limiter_negative_limit(self): + """ + Test a negative limit. + """ + def _limit_large(): + limited(self.large, req, max_limit=2000) + + req = Request.blank('/?limit=-3000') + self.assertRaises(webob.exc.HTTPBadRequest, _limit_large) + + def test_limiter_negative_offset(self): + """ + Test a negative offset. + """ + def _limit_large(): + limited(self.large, req, max_limit=2000) + + req = Request.blank('/?offset=-30') + self.assertRaises(webob.exc.HTTPBadRequest, _limit_large) -- cgit From 0550124fcd863be60dd0e6fefb5f30641331b198 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 28 Feb 2011 18:06:11 -0500 Subject: add test for instance creation without personalities --- nova/tests/api/openstack/test_servers.py | 40 ++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 7a25abe9d..7e5bc0080 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -232,6 +232,46 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) + def _create_instance_with_personality(self, personality): + + class FakeComputeAPI(object): + + def __init__(self): + self.onset_files = None + + def create(*args, **kwargs): + if 'onset_files' in kwargs: + self.onset_files = kwargs['onset_files'] + else: + self.onset_files = None + return [{'id': '1234', 'display_name': 'fakeinstance'}] + + def make_stub_method(canned_return): + def stub_method(*args, **kwargs): + return canned_return + return stub_method + + compute_api = FakeComputeAPI() + self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api)) + self.stubs.Set(nova.api.openstack.servers.Controller, + '_get_kernel_ramdisk_from_image', make_stub_method((1, 1))) + self.stubs.Set(nova.api.openstack.common, + 'get_image_id_from_image_hash', make_stub_method(2)) + body = dict(server=dict( + name='server_test', imageId=2, flavorId=2, + metadata={}, + personality=personality)) + + req = webob.Request.blank('/v1.0/servers') + req.method = 'POST' + req.body = json.dumps(body) + return req.get_response(fakes.wsgi_app()), compute_api.onset_files + + def test_create_instance_with_no_personality(self): + res, onset_files = self._create_instance_with_personality(personality={}) + self.assertEquals(res.status_int, 200) + self.assertEquals(onset_files, None) + def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' -- cgit From aafd83233a675ccf5f3c4e737d966652e45a0ecb Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 28 Feb 2011 16:28:46 -0800 Subject: replaced ugly INSTANCE_TYPE constant with (slightly less ugly) stubs --- nova/tests/db/fakes.py | 20 ++++++++++++++++++-- nova/tests/test_quota.py | 17 ++++++++++++++--- nova/tests/test_xenapi.py | 2 +- 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index d9a5032ee..d760dc456 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -22,12 +22,20 @@ import time from nova import db from nova import test from nova import utils -from nova.compute import instance_types def stub_out_db_instance_api(stubs): """ Stubs out the db API for creating Instances """ + INSTANCE_TYPES = { + 'm1.tiny': dict(memory_mb=512, vcpus=1, local_gb=0, flavorid=1), + 'm1.small': dict(memory_mb=2048, vcpus=1, local_gb=20, flavorid=2), + 'm1.medium': + dict(memory_mb=4096, vcpus=2, local_gb=40, flavorid=3), + 'm1.large': dict(memory_mb=8192, vcpus=4, local_gb=80, flavorid=4), + 'm1.xlarge': + dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} + class FakeModel(object): """ Stubs out for model """ def __init__(self, values): @@ -42,10 +50,16 @@ def stub_out_db_instance_api(stubs): else: raise NotImplementedError() + def fake_instance_type_get_all(context, inactive=0): + return INSTANCE_TYPES + + def fake_instance_type_get_by_name(context, name): + return INSTANCE_TYPES[name] + def fake_instance_create(values): """ Stubs out the db.instance_create method """ - type_data = test.INSTANCE_TYPES[values['instance_type']] + type_data = INSTANCE_TYPES[values['instance_type']] base_options = { 'name': values['name'], @@ -74,3 +88,5 @@ def stub_out_db_instance_api(stubs): stubs.Set(db, 'instance_create', fake_instance_create) stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) + stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all) + stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name) diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index faafe2d31..4ecb36b54 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -74,19 +74,30 @@ class QuotaTestCase(test.TestCase): vol['size'] = size return db.volume_create(self.context, vol)['id'] + def _get_instance_type(self, name): + instance_types = { + 'm1.tiny': dict(memory_mb=512, vcpus=1, local_gb=0, flavorid=1), + 'm1.small': dict(memory_mb=2048, vcpus=1, local_gb=20, flavorid=2), + 'm1.medium': + dict(memory_mb=4096, vcpus=2, local_gb=40, flavorid=3), + 'm1.large': dict(memory_mb=8192, vcpus=4, local_gb=80, flavorid=4), + 'm1.xlarge': + dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} + return instance_types[name] + def test_quota_overrides(self): """Make sure overriding a projects quotas works""" num_instances = quota.allowed_instances(self.context, 100, - test.INSTANCE_TYPES['m1.small']) + self._get_instance_type('m1.small')) self.assertEqual(num_instances, 2) db.quota_create(self.context, {'project_id': self.project.id, 'instances': 10}) num_instances = quota.allowed_instances(self.context, 100, - test.INSTANCE_TYPES['m1.small']) + self._get_instance_type('m1.small')) self.assertEqual(num_instances, 4) db.quota_update(self.context, self.project.id, {'cores': 100}) num_instances = quota.allowed_instances(self.context, 100, - test.INSTANCE_TYPES['m1.small']) + self._get_instance_type('m1.small')) self.assertEqual(num_instances, 10) # metadata_items diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 27131c45e..106c0bd6f 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -233,7 +233,7 @@ class XenAPIVMTestCase(test.TestCase): vm = vms[0] # Check that m1.large above turned into the right thing. - instance_type = test.INSTANCE_TYPES['m1.large'] + instance_type = db.instance_type_get_by_name(conn, 'm1.large') mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) vcpus = instance_type['vcpus'] -- cgit From 4e4711ccfc7ce3c3df704a8635dccd506d6e7f01 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Tue, 1 Mar 2011 00:28:59 +0000 Subject: Units tests fixed partially. Still need to address checking data injected into xenstore need to convert string into dict or similar. Also todo PEP8 fixes --- nova/tests/db/fakes.py | 41 +++++++++++++++++++++++++++++++---------- nova/tests/test_xenapi.py | 42 ++++++++++++++++++------------------------ nova/tests/xenapi/stubs.py | 3 +++ 3 files changed, 52 insertions(+), 34 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index c47fba5f3..b939f99a0 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -36,6 +36,8 @@ class FakeModel(object): if key in self.values: return self.values[key] else: + print "Key:%s" %key + print "Values:%s" %self.values raise NotImplementedError() @@ -70,26 +72,45 @@ def stub_out_db_instance_api(stubs): stubs.Set(db, 'instance_create', fake_instance_create) -def stub_out_db_network_api(stubs, injected=False): +def stub_out_db_network_api(stubs, injected=True): """Stubs out the db API for retrieving networks""" + network_fields = { + 'id': 'test', 'bridge': 'xenbr0', + 'label': 'test_network', + 'netmask': '255.255.255.0', + 'gateway': '10.0.0.1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2', + 'ra_server': None, 'injected': injected} - - if injected: - network_fields.update({ - 'netmask': '255.255.255.0', - 'gateway': '10.0.0.1', - 'broadcast': '10.0.0.255', - 'dns': '10.0.0.2', - 'ra_server': None}) + + fixed_ip_fields = { + 'address':'10.0.0.3', + 'network_id':'test'} def fake_network_get_by_instance(context, instance_id): return FakeModel(network_fields) + def fake_network_get_all_by_instance(context, instance_id): + l = [] + l.append(FakeModel(network_fields)) + return l + def fake_instance_get_fixed_address(context, instance_id): - return '10.0.0.3' + return FakeModel(fixed_ip_fields).address + + def fake_fixed_ip_get_all_by_instance(context, instance_id): + l = [] + l.append(FakeModel(fixed_ip_fields)) + return l stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) stubs.Set(db, 'instance_get_fixed_address', fake_instance_get_fixed_address) + stubs.Set(db, 'network_get_all_by_instance', + fake_network_get_all_by_instance) + stubs.Set(db, 'fixed_ip_get_all_by_instance', + fake_fixed_ip_get_all_by_instance) + \ No newline at end of file diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index ce89a53c8..10a1b6c11 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -261,30 +261,21 @@ class XenAPIVMTestCase(test.TestCase): if check_injection: xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) - key_prefix = 'vm-data/vif/22_33_2A_B3_CC_DD/tcpip/' - tcpip_data = dict([(k.replace(key_prefix, ''), v) - for k, v in xenstore_data.iteritems() - if k.startswith(key_prefix)]) - - self.assertEquals(tcpip_data, { - 'BroadcastAddress/data/0': '10.0.0.255', - 'BroadcastAddress/name': 'BroadcastAddress', - 'BroadcastAddress/type': 'multi_sz', - 'DefaultGateway/data/0': '10.0.0.1', - 'DefaultGateway/name': 'DefaultGateway', - 'DefaultGateway/type': 'multi_sz', - 'EnableDhcp/data': '0', - 'EnableDhcp/name': 'EnableDhcp', - 'EnableDhcp/type': 'dword', - 'IPAddress/data/0': '10.0.0.3', - 'IPAddress/name': 'IPAddress', - 'IPAddress/type': 'multi_sz', - 'NameServer/data': '10.0.0.2', - 'NameServer/name': 'NameServer', - 'NameServer/type': 'string', - 'SubnetMask/data/0': '255.255.255.0', - 'SubnetMask/name': 'SubnetMask', - 'SubnetMask/type': 'multi_sz'}) + key = 'vm-data/networking/aabbccddeeff' + LOG.debug("Xenstore data: %s",xenstore_data) + xenstore_value=xenstore_data[key] + #tcpip_data = dict([(k, v) + # for k, v in xenstore_value.iteritems() + # if k.startswith(key_prefix)]) + #LOG.debug("tcpip data: %s",tcpip_data) + #self.assertEquals(tcpip_data['label'],'test_network') + #self.assertEquals(tcpip_data, { + # 'label': 'test_network', + # 'broadcast': '10.0.0.255', + # 'ips': [{'ip': '10.0.0.3', 'netmask':'255.255.255.0', 'enabled':'1'}], + # 'mac': 'aa:bb:cc:dd:ee:ff', + # 'dns': ['10.0.0.2'], + # 'gateway': '10.0.0.1'}) def _test_spawn(self, image_id, kernel_id, ramdisk_id, instance_type="m1.large", check_injection=False): @@ -340,6 +331,9 @@ class XenAPIVMTestCase(test.TestCase): # Find the start of eth0 configuration and check it index = config.index('auto eth0') + LOG.debug("CONFIG") + LOG.debug(config) + self.assertEquals(config[index + 1:index + 8], [ 'iface eth0 inet static', 'address 10.0.0.3', diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 6981b4f7a..551d326a4 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -191,6 +191,9 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_add_to_xenstore_data(self, session_ref, vm_ref, key, value): fake.VM_add_to_xenstore_data(vm_ref, key, value) + + def VM_remove_from_xenstore_data(self, session_ref, vm_ref, key): + fake.VM_remove_from_xenstore_data(vm_ref, key) class FakeSessionForVolumeTests(fake.SessionBase): -- cgit From 8806858918f396cfca41a28c191dc9e8d2809a0e Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Tue, 1 Mar 2011 01:10:38 +0000 Subject: Fixed xenapi tests Gave up on clever things with map stored as string in xenstore. Used ast.liteeral_eval instead. Changed instance ID and names in tests from in to string (1 => '1') This simplified VMOps._get_vm_opaqueref Changed VMOps._get_vm_opaqueref as references returned by fake xenapi do not start with "OpaqueRef:" prefix. Fixed PEP8 Errors --- nova/tests/db/fakes.py | 13 +++++-------- nova/tests/test_xenapi.py | 46 +++++++++++++++++++++------------------------- nova/tests/xenapi/stubs.py | 2 +- 3 files changed, 27 insertions(+), 34 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index b939f99a0..7aa72e4a3 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -36,8 +36,6 @@ class FakeModel(object): if key in self.values: return self.values[key] else: - print "Key:%s" %key - print "Values:%s" %self.values raise NotImplementedError() @@ -74,7 +72,7 @@ def stub_out_db_instance_api(stubs): def stub_out_db_network_api(stubs, injected=True): """Stubs out the db API for retrieving networks""" - + network_fields = { 'id': 'test', 'bridge': 'xenbr0', @@ -83,12 +81,12 @@ def stub_out_db_network_api(stubs, injected=True): 'gateway': '10.0.0.1', 'broadcast': '10.0.0.255', 'dns': '10.0.0.2', - 'ra_server': None, + 'ra_server': None, 'injected': injected} - + fixed_ip_fields = { - 'address':'10.0.0.3', - 'network_id':'test'} + 'address': '10.0.0.3', + 'network_id': 'test'} def fake_network_get_by_instance(context, instance_id): return FakeModel(network_fields) @@ -113,4 +111,3 @@ def stub_out_db_network_api(stubs, injected=True): fake_network_get_all_by_instance) stubs.Set(db, 'fixed_ip_get_all_by_instance', fake_fixed_ip_get_all_by_instance) - \ No newline at end of file diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 10a1b6c11..a3d3371a1 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -21,6 +21,7 @@ Test suite for XenAPI import os import re import stubout +import ast from nova import db from nova import context @@ -204,7 +205,7 @@ class XenAPIVMTestCase(test.TestCase): if not vm_rec["is_control_domain"]: vm_labels.append(vm_rec["name_label"]) - self.assertEquals(vm_labels, [1]) + self.assertEquals(vm_labels, ['1']) def ensure_vbd_was_torn_down(): vbd_labels = [] @@ -212,7 +213,7 @@ class XenAPIVMTestCase(test.TestCase): vbd_rec = xenapi_fake.get_record('VBD', vbd_ref) vbd_labels.append(vbd_rec["vm_name_label"]) - self.assertEquals(vbd_labels, [1]) + self.assertEquals(vbd_labels, ['1']) def ensure_vdi_was_torn_down(): for vdi_ref in xenapi_fake.get_all('VDI'): @@ -229,10 +230,10 @@ class XenAPIVMTestCase(test.TestCase): def check_vm_record(self, conn, check_injection=False): instances = conn.list_instances() - self.assertEquals(instances, [1]) + self.assertEquals(instances, ['1']) # Get Nova record for VM - vm_info = conn.get_info(1) + vm_info = conn.get_info('1') # Get XenAPI record for VM vms = [(ref, rec) for ref, rec @@ -262,27 +263,24 @@ class XenAPIVMTestCase(test.TestCase): if check_injection: xenstore_data = xenapi_fake.VM_get_xenstore_data(vm_ref) key = 'vm-data/networking/aabbccddeeff' - LOG.debug("Xenstore data: %s",xenstore_data) - xenstore_value=xenstore_data[key] - #tcpip_data = dict([(k, v) - # for k, v in xenstore_value.iteritems() - # if k.startswith(key_prefix)]) - #LOG.debug("tcpip data: %s",tcpip_data) - #self.assertEquals(tcpip_data['label'],'test_network') - #self.assertEquals(tcpip_data, { - # 'label': 'test_network', - # 'broadcast': '10.0.0.255', - # 'ips': [{'ip': '10.0.0.3', 'netmask':'255.255.255.0', 'enabled':'1'}], - # 'mac': 'aa:bb:cc:dd:ee:ff', - # 'dns': ['10.0.0.2'], - # 'gateway': '10.0.0.1'}) + xenstore_value = xenstore_data[key] + tcpip_data = ast.literal_eval(xenstore_value) + self.assertEquals(tcpip_data, { + 'label': 'test_network', + 'broadcast': '10.0.0.255', + 'ips': [{'ip': '10.0.0.3', + 'netmask':'255.255.255.0', + 'enabled':'1'}], + 'mac': 'aa:bb:cc:dd:ee:ff', + 'dns': ['10.0.0.2'], + 'gateway': '10.0.0.1'}) def _test_spawn(self, image_id, kernel_id, ramdisk_id, instance_type="m1.large", check_injection=False): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) - values = {'name': 1, - 'id': 1, + values = {'name': "1", + 'id': "1", 'project_id': self.project.id, 'user_id': self.user.id, 'image_id': image_id, @@ -331,9 +329,7 @@ class XenAPIVMTestCase(test.TestCase): # Find the start of eth0 configuration and check it index = config.index('auto eth0') - LOG.debug("CONFIG") - LOG.debug(config) - + self.assertEquals(config[index + 1:index + 8], [ 'iface eth0 inet static', 'address 10.0.0.3', @@ -409,8 +405,8 @@ class XenAPIVMTestCase(test.TestCase): def _create_instance(self): """Creates and spawns a test instance""" values = { - 'name': 1, - 'id': 1, + 'name': '1', + 'id': '1', 'project_id': self.project.id, 'user_id': self.user.id, 'image_id': 1, diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 551d326a4..2392a97b3 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -191,7 +191,7 @@ class FakeSessionForVMTests(fake.SessionBase): def VM_add_to_xenstore_data(self, session_ref, vm_ref, key, value): fake.VM_add_to_xenstore_data(vm_ref, key, value) - + def VM_remove_from_xenstore_data(self, session_ref, vm_ref, key): fake.VM_remove_from_xenstore_data(vm_ref, key) -- cgit From d13a623625a56a029f9dd5ccba3e70f492efdb2c Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Tue, 1 Mar 2011 18:32:57 +0900 Subject: test_compute is changed b/c lack of import instance_types --- nova/tests/test_compute.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 3c88d186d..2a18dd47b 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -32,6 +32,7 @@ from nova import rpc from nova import test from nova import utils from nova.auth import manager +from nova.compute import instance_types from nova.compute import manager as compute_manager from nova.compute import power_state from nova.db.sqlalchemy import models -- cgit From 688acacd85e07fc578c8731df6a4421e64499c8b Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Tue, 1 Mar 2011 18:53:02 +0900 Subject: At previous commit, I forget to erase conflict - fixed it. --- nova/tests/test_compute.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 75fbc9324..3438719f4 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -309,7 +309,13 @@ class ComputeTestCase(test.TestCase): self.compute.terminate_instance(self.context, instance_id) -<<<<<<< TREE + def test_get_by_flavor_id(self): + type = instance_types.get_by_flavor_id(1) + self.assertEqual(type, 'm1.tiny') + + type = instance_types.get_by_flavor_id("1") + self.assertEqual(type, 'm1.tiny') + def _setup_other_managers(self): self.volume_manager = utils.import_object(FLAGS.volume_manager) self.network_manager = utils.import_object(FLAGS.network_manager) @@ -562,11 +568,3 @@ class ComputeTestCase(test.TestCase): db.instance_destroy(c, instance_id) db.volume_destroy(c, v_ref['id']) db.floating_ip_destroy(c, flo_addr) -======= - def test_get_by_flavor_id(self): - type = instance_types.get_by_flavor_id(1) - self.assertEqual(type, 'm1.tiny') - - type = instance_types.get_by_flavor_id("1") - self.assertEqual(type, 'm1.tiny') ->>>>>>> MERGE-SOURCE -- cgit From 282a18a4c15f066e371596104f783f522309c5ee Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 1 Mar 2011 10:40:56 -0800 Subject: corrected copyrights for new files --- nova/tests/test_instance_types.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_instance_types.py b/nova/tests/test_instance_types.py index 1b192ca28..edc538879 100644 --- a/nova/tests/test_instance_types.py +++ b/nova/tests/test_instance_types.py @@ -1,5 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright 2011 Ken Pepple # 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 -- cgit From f9d08c16d5c620c711d962a78be3a94b99364f14 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 1 Mar 2011 13:56:33 -0500 Subject: support adding a single personality in the osapi --- nova/tests/api/openstack/test_servers.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 7e5bc0080..42665ba6d 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -232,6 +232,9 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) + def _personality_dict(self, path, contents): + return {'path': path, 'contents': contents} + def _create_instance_with_personality(self, personality): class FakeComputeAPI(object): @@ -239,7 +242,7 @@ class ServersTest(test.TestCase): def __init__(self): self.onset_files = None - def create(*args, **kwargs): + def create(self, *args, **kwargs): if 'onset_files' in kwargs: self.onset_files = kwargs['onset_files'] else: @@ -265,12 +268,20 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.0/servers') req.method = 'POST' req.body = json.dumps(body) - return req.get_response(fakes.wsgi_app()), compute_api.onset_files + return req, req.get_response(fakes.wsgi_app()), compute_api.onset_files def test_create_instance_with_no_personality(self): - res, onset_files = self._create_instance_with_personality(personality={}) - self.assertEquals(res.status_int, 200) - self.assertEquals(onset_files, None) + request, response, onset_files = \ + self._create_instance_with_personality(personality=[]) + self.assertEquals(response.status_int, 200) + self.assertEquals(onset_files, []) + + def test_create_instance_with_one_personality(self): + personality = [self._personality_dict('/my/path', 'myfilecontents')] + request, response, onset_files = \ + self._create_instance_with_personality(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(onset_files, [('/my/path', 'myfilecontents')]) def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') -- cgit From e21763b15948603e618d4435335ef3785dc5660a Mon Sep 17 00:00:00 2001 From: sateesh Date: Wed, 2 Mar 2011 01:00:31 +0530 Subject: Fake database module for vmware vi api. Includes false injection layer at the level of API calls. This module is base for unit tests for vmwareapi module. The unit tests runs regardless of presence of ESX/ESXi server as computer provider in OpenStack. --- nova/tests/test_vmwareapi.py | 207 +++++++++++++++++++++++++++++++++++++++ nova/tests/vmwareapi/__init__.py | 16 +++ nova/tests/vmwareapi/db_fakes.py | 93 ++++++++++++++++++ nova/tests/vmwareapi/stubs.py | 46 +++++++++ 4 files changed, 362 insertions(+) create mode 100644 nova/tests/test_vmwareapi.py create mode 100644 nova/tests/vmwareapi/__init__.py create mode 100644 nova/tests/vmwareapi/db_fakes.py create mode 100644 nova/tests/vmwareapi/stubs.py (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py new file mode 100644 index 000000000..ff2761e72 --- /dev/null +++ b/nova/tests/test_vmwareapi.py @@ -0,0 +1,207 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# +# 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. + +""" +Test suite for VMWareAPI +""" +import stubout + +from nova import context +from nova import db +from nova import flags +from nova import test +from nova import utils +from nova.auth import manager +from nova.compute import instance_types +from nova.compute import power_state +from nova.tests.glance import stubs as glance_stubs +from nova.tests.vmwareapi import db_fakes +from nova.tests.vmwareapi import stubs +from nova.virt import vmwareapi_conn +from nova.virt.vmwareapi import fake as vmwareapi_fake + + +FLAGS = flags.FLAGS + + +class VMWareAPIVMTestCase(test.TestCase): + """ + Unit tests for Vmware API connection calls + """ + + def setUp(self): + super(VMWareAPIVMTestCase, self).setUp() + self.manager = manager.AuthManager() + self.user = self.manager.create_user('fake', 'fake', 'fake', + admin=True) + self.project = self.manager.create_project('fake', 'fake', 'fake') + self.network = utils.import_object(FLAGS.network_manager) + self.stubs = stubout.StubOutForTesting() + FLAGS.vmwareapi_host_ip = 'test_url' + FLAGS.vmwareapi_host_username = 'test_username' + FLAGS.vmwareapi_host_password = 'test_pass' + vmwareapi_fake.reset() + db_fakes.stub_out_db_instance_api(self.stubs) + stubs.set_stubs(self.stubs) + glance_stubs.stubout_glance_client(self.stubs, + glance_stubs.FakeGlance) + self.conn = vmwareapi_conn.get_connection(False) + + def _create_vm(self): + """ Create and spawn the VM """ + values = {'name': 1, + 'id': 1, + 'project_id': self.project.id, + 'user_id': self.user.id, + 'image_id': "1", + 'kernel_id': "1", + 'ramdisk_id': "1", + 'instance_type': 'm1.large', + 'mac_address': 'aa:bb:cc:dd:ee:ff', + } + self.instance = db.instance_create(values) + self.type_data = instance_types.INSTANCE_TYPES[values['instance_type']] + self.conn.spawn(self.instance) + self._check_vm_record() + + def _check_vm_record(self): + """ Check if the spawned VM's properties corresponds to the instance in + the db """ + instances = self.conn.list_instances() + self.assertEquals(len(instances), 1) + + # Get Nova record for VM + vm_info = self.conn.get_info(1) + + # Get XenAPI record for VM + vms = vmwareapi_fake._get_objects("VirtualMachine") + vm = vms[0] + + # Check that m1.large above turned into the right thing. + mem_kib = long(self.type_data['memory_mb']) << 10 + vcpus = self.type_data['vcpus'] + self.assertEquals(vm_info['max_mem'], mem_kib) + self.assertEquals(vm_info['mem'], mem_kib) + self.assertEquals(vm.get("summary.config.numCpu"), vcpus) + self.assertEquals(vm.get("summary.config.memorySizeMB"), + self.type_data['memory_mb']) + + # Check that the VM is running according to Nova + self.assertEquals(vm_info['state'], power_state.RUNNING) + + # Check that the VM is running according to XenAPI. + self.assertEquals(vm.get("runtime.powerState"), 'poweredOn') + + def _check_vm_info(self, info, pwr_state=power_state.RUNNING): + """ Check if the get_info returned values correspond to the instance + object in the db """ + mem_kib = long(self.type_data['memory_mb']) << 10 + self.assertEquals(info["state"], pwr_state) + self.assertEquals(info["max_mem"], mem_kib) + self.assertEquals(info["mem"], mem_kib) + self.assertEquals(info["num_cpu"], self.type_data['vcpus']) + + def test_list_instances(self): + instances = self.conn.list_instances() + self.assertEquals(len(instances), 0) + + def test_list_instances_1(self): + self._create_vm() + instances = self.conn.list_instances() + self.assertEquals(len(instances), 1) + + def test_spawn(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + + def test_snapshot(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.conn.snapshot(self.instance, "Test-Snapshot") + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + + def test_reboot(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.conn.reboot(self.instance) + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + + def test_suspend(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.conn.suspend(self.instance, self.dummy_callback_handler) + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.PAUSED) + + def test_resume(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.conn.suspend(self.instance, self.dummy_callback_handler) + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.PAUSED) + self.conn.resume(self.instance, self.dummy_callback_handler) + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + + def test_get_info(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + + def test_destroy(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + instances = self.conn.list_instances() + self.assertTrue(len(instances) == 1) + self.conn.destroy(self.instance) + instances = self.conn.list_instances() + self.assertTrue(len(instances) == 0) + + def test_pause(self): + pass + + def test_unpause(self): + pass + + def test_diagnostics(self): + pass + + def test_get_console_output(self): + pass + + def test_get_ajax_console(self): + pass + + def dummy_callback_handler(self, ret): + """ Dummy callback function to be passed to suspend, resume, etc. + calls """ + pass + + def tearDown(self): + super(VMWareAPIVMTestCase, self).tearDown() + vmwareapi_fake.cleanup() + self.manager.delete_project(self.project) + self.manager.delete_user(self.user) + self.stubs.UnsetAll() diff --git a/nova/tests/vmwareapi/__init__.py b/nova/tests/vmwareapi/__init__.py new file mode 100644 index 000000000..f346c053b --- /dev/null +++ b/nova/tests/vmwareapi/__init__.py @@ -0,0 +1,16 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# +# 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. diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py new file mode 100644 index 000000000..555537304 --- /dev/null +++ b/nova/tests/vmwareapi/db_fakes.py @@ -0,0 +1,93 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# +# 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. + +""" +Stubouts, mocks and fixtures for the test suite +""" + +import time + +from nova import db +from nova import utils +from nova.compute import instance_types + + +def stub_out_db_instance_api(stubs): + """ Stubs out the db API for creating Instances """ + + class FakeModel(object): + """ Stubs out for model """ + + def __init__(self, values): + self.values = values + + def __getattr__(self, name): + return self.values[name] + + def __getitem__(self, key): + if key in self.values: + return self.values[key] + else: + raise NotImplementedError() + + def fake_instance_create(values): + """ Stubs out the db.instance_create method """ + + type_data = instance_types.INSTANCE_TYPES[values['instance_type']] + + base_options = { + 'name': values['name'], + 'id': values['id'], + 'reservation_id': utils.generate_uid('r'), + 'image_id': values['image_id'], + 'kernel_id': values['kernel_id'], + 'ramdisk_id': values['ramdisk_id'], + 'state_description': 'scheduling', + 'user_id': values['user_id'], + 'project_id': values['project_id'], + 'launch_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()), + 'instance_type': values['instance_type'], + 'memory_mb': type_data['memory_mb'], + 'mac_address': values['mac_address'], + 'vcpus': type_data['vcpus'], + 'local_gb': type_data['local_gb'], + } + return FakeModel(base_options) + + def fake_network_get_by_instance(context, instance_id): + """ Stubs out the db.network_get_by_instance method """ + + fields = { + 'bridge': 'vmnet0', + 'netmask': '255.255.255.0', + 'gateway': '10.10.10.1', + 'vlan': 100} + return FakeModel(fields) + + def fake_instance_action_create(context, action): + """ Stubs out the db.instance_action_create method """ + pass + + def fake_instance_get_fixed_address(context, instance_id): + """ Stubs out the db.instance_get_fixed_address method """ + return '10.10.10.10' + + stubs.Set(db, 'instance_create', fake_instance_create) + stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) + stubs.Set(db, 'instance_action_create', fake_instance_action_create) + stubs.Set(db, 'instance_get_fixed_address', + fake_instance_get_fixed_address) diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py new file mode 100644 index 000000000..da2d43c29 --- /dev/null +++ b/nova/tests/vmwareapi/stubs.py @@ -0,0 +1,46 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Citrix Systems, Inc. +# Copyright 2011 OpenStack LLC. +# +# 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. + +""" +Stubouts for the test suite +""" + +from nova.virt import vmwareapi_conn +from nova.virt.vmwareapi import fake +from nova.virt.vmwareapi import vmware_images + + +def fake_get_vim_object(arg): + """ Stubs out the VMWareAPISession's get_vim_object method """ + return fake.FakeVim() + + +def fake_is_vim_object(arg, module): + """ Stubs out the VMWareAPISession's is_vim_object method """ + return isinstance(module, fake.FakeVim) + + +def set_stubs(stubs): + """ Set the stubs """ + stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image) + stubs.Set(vmware_images, 'get_vmdk_size_and_properties', + fake.fake_get_vmdk_size_and_properties) + stubs.Set(vmware_images, 'upload_image', fake.fake_upload_image) + stubs.Set(vmwareapi_conn.VMWareAPISession, "_get_vim_object", + fake_get_vim_object) + stubs.Set(vmwareapi_conn.VMWareAPISession, "_is_vim_object", + fake_is_vim_object) -- cgit From be9004ffa4c70358c8edda1f33ffe7ba7e1ae1ee Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 1 Mar 2011 20:49:46 +0100 Subject: Use functools.wraps to make sure wrapped method's metadata (docstring and name) doesn't get mangled. --- nova/tests/test_misc.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 154b6fae6..9f572b58e 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -14,11 +14,9 @@ # License for the specific language governing permissions and limitations # under the License. -from datetime import datetime import errno import os import select -import time from nova import test from nova.utils import parse_mailmap, str_dict_replace, synchronized @@ -62,6 +60,16 @@ class ProjectTestCase(test.TestCase): class LockTestCase(test.TestCase): + def test_synchronized_wrapped_function_metadata(self): + @synchronized('whatever') + def foo(): + """Bar""" + pass + self.assertEquals(foo.__doc__, 'Bar', "Wrapped function's docstring " + "got lost") + self.assertEquals(foo.__name__, 'foo', "Wrapped function's name " + "got mangled") + def test_synchronized(self): rpipe, wpipe = os.pipe() pid = os.fork() -- cgit From 94e42c3002f9043fc3c5b90a1cb5ad0c50ba261b Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 1 Mar 2011 16:21:37 -0500 Subject: ensure personality contents are b64 encoded --- nova/tests/api/openstack/test_servers.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 144dbd4af..4b40793a7 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import base64 import datetime import json @@ -272,16 +273,28 @@ class ServersTest(test.TestCase): def test_create_instance_with_no_personality(self): request, response, onset_files = \ - self._create_instance_with_personality(personality=[]) + self._create_instance_with_personality(personality=[]) self.assertEquals(response.status_int, 200) self.assertEquals(onset_files, []) - def test_create_instance_with_one_personality(self): - personality = [self._personality_dict('/my/path', 'myfilecontents')] + def test_create_instance_with_personality(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Hello, World!"\n' + b64contents = base64.b64encode(contents) + personality = [self._personality_dict(path, b64contents)] request, response, onset_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [('/my/path', 'myfilecontents')]) + self.assertEquals(onset_files, [(path, contents)]) + + def test_create_instance_with_personality_with_non_b64_content(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Oh no!"\n' + personality = [self._personality_dict(path, contents)] + request, response, onset_files = \ + self._create_instance_with_personality(personality) + self.assertEquals(response.status_int, 400) + self.assertEquals(onset_files, None) def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') -- cgit From 7b3ccd5fd1636ebc437a89a3667e6e712004e87f Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 1 Mar 2011 16:48:01 -0500 Subject: test osapi server create with multiple personalities --- nova/tests/api/openstack/test_servers.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 4b40793a7..dd951e90c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -296,6 +296,20 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 400) self.assertEquals(onset_files, None) + def test_create_instance_with_two_personalities(self): + files = [ + ('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'), + ('/etc/motd', 'Enjoy your root access!\n'), + ] + personality = [] + for path, content in files: + personality.append(self._personality_dict( + path, base64.b64encode(content))) + request, response, onset_files = \ + self._create_instance_with_personality(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(onset_files, files) + def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' -- cgit From d33866923958b3529a812f4eef7dea4a6591a423 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 2 Mar 2011 17:36:21 -0500 Subject: add support for quotas on file injection --- nova/tests/test_quota.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 1e42fddf3..48e5a5538 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -176,3 +176,13 @@ class QuotaTestCase(test.TestCase): instance_type='m1.small', image_id='fake', metadata=metadata) + + def test_allowed_file_injection_files(self): + self.assertEqual( + quota.allowed_file_injection_files(self.context), + FLAGS.quota_file_injection_max_files) + + def test_allowed_file_injection_file_bytes(self): + self.assertEqual( + quota.allowed_file_injection_file_bytes(self.context), + FLAGS.quota_file_injection_max_file_bytes) -- cgit From 077a77a1ab6fbec468b36e2975c1e185235c17ff Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Wed, 2 Mar 2011 15:49:51 -0800 Subject: removed create and delete method (and corresponding tests) from flavors.py --- nova/tests/api/openstack/test_flavors.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 2626f92ba..319767bb5 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -46,17 +46,7 @@ class FlavorsTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) - def test_create_flavor(self): - req = webob.Request.blank("/v1.0/flavors") - req.method = "POST" - res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status_int, 200) - - def test_delete_flavor(self): - req = webob.Request.blank("/v1.0/flavors/1") - req.method = "DELETE" + def test_get_flavor_by_id(self): + req = webob.Request.blank('/v1.0/flavors/1') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) - - def test_get_flavor_by_id(self): - pass -- cgit From 668cdc96b3f6fb412b9d1d4a3780744d6b2340b1 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 3 Mar 2011 00:59:09 -0500 Subject: more rigorous testing and error handling for os api personality --- nova/tests/api/openstack/test_servers.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index dd951e90c..272d34e3a 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -265,6 +265,8 @@ class ServersTest(test.TestCase): name='server_test', imageId=2, flavorId=2, metadata={}, personality=personality)) + if personality is None: + del body['server']['personality'] req = webob.Request.blank('/v1.0/servers') req.method = 'POST' @@ -273,7 +275,7 @@ class ServersTest(test.TestCase): def test_create_instance_with_no_personality(self): request, response, onset_files = \ - self._create_instance_with_personality(personality=[]) + self._create_instance_with_personality(personality=None) self.assertEquals(response.status_int, 200) self.assertEquals(onset_files, []) @@ -296,10 +298,11 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 400) self.assertEquals(onset_files, None) - def test_create_instance_with_two_personalities(self): + def test_create_instance_with_three_personalities(self): files = [ ('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'), ('/etc/motd', 'Enjoy your root access!\n'), + ('/etc/dovecot.conf', 'dovecot\nconfig\nstuff\n'), ] personality = [] for path, content in files: @@ -310,6 +313,24 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 200) self.assertEquals(onset_files, files) + def test_create_instance_personality_empty_content(self): + path = '/my/file/path' + contents = '' + personality = [self._personality_dict(path, contents)] + request, response, onset_files = \ + self._create_instance_with_personality(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(onset_files, [(path, contents)]) + + def test_create_instance_personality_not_a_list(self): + path = '/my/file/path' + contents = 'myfilecontents' + personality = self._personality_dict(path, contents) + request, response, onset_files = \ + self._create_instance_with_personality(personality) + self.assertEquals(response.status_int, 400) + self.assertEquals(onset_files, None) + def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' -- cgit From 693e4335dbef72317147abd70bdaa10e0d174020 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Thu, 3 Mar 2011 22:54:11 +0900 Subject: Fixed based on reviewer's comments. Main changes are below. 1. Rename nova.compute.manager.ComputeManager.mktmpfile for better naming. 2. Several tests code in tests/test_virt.py are removed. Because it only works in libvirt environment. Only db-related testcode remains. --- nova/tests/test_scheduler.py | 14 +- nova/tests/test_virt.py | 363 +++++++++---------------------------------- 2 files changed, 78 insertions(+), 299 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index c4e4d148e..62db42b11 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -661,7 +661,6 @@ class SimpleDriverTestCase(test.TestCase): self.scheduler.live_migration(self.context, FLAGS.compute_topic, instance_id=instance_id, dest=i_ref['host']) - self.mox.UnsetStubs() i_ref = db.instance_get(self.context, instance_id) self.assertTrue(i_ref['state_description'] == 'migrating') @@ -824,10 +823,15 @@ class SimpleDriverTestCase(test.TestCase): topic = FLAGS.compute_topic driver.rpc.call(mox.IgnoreArg(), db.queue_get_for(self.context, topic, dest), - {"method": 'mktmpfile'}).AndReturn(fpath) + {"method": 'create_shared_storage_test_file'}).AndReturn(fpath) driver.rpc.call(mox.IgnoreArg(), db.queue_get_for(mox.IgnoreArg(), topic, i_ref['host']), - {"method": 'confirm_tmpfile', "args": {'filename': fpath}}) + {"method": 'check_shared_storage_test_file', + "args": {'filename': fpath}}) + driver.rpc.call(mox.IgnoreArg(), + db.queue_get_for(mox.IgnoreArg(), topic, dest), + {"method": 'cleanup_shared_storage_test_file', + "args": {'filename': fpath}}) self.mox.ReplayAll() try: @@ -838,7 +842,6 @@ class SimpleDriverTestCase(test.TestCase): c = (e.message.find('does not exist') >= 0) self.assertTrue(c) - self.mox.UnsetStubs() db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) @@ -867,7 +870,6 @@ class SimpleDriverTestCase(test.TestCase): c = (e.message.find(_('Different hypervisor type')) >= 0) self.assertTrue(c) - self.mox.UnsetStubs() db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) @@ -898,7 +900,6 @@ class SimpleDriverTestCase(test.TestCase): c = (e.message.find(_('Older hypervisor version')) >= 0) self.assertTrue(c) - self.mox.UnsetStubs() db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) @@ -934,7 +935,6 @@ class SimpleDriverTestCase(test.TestCase): c = (e.message.find(_("doesn't have compatibility to")) >= 0) self.assertTrue(c) - self.mox.UnsetStubs() db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index f46b5950e..17b80c294 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -14,7 +14,6 @@ # License for the specific language governing permissions and limitations # under the License. -import libvirt import mox from xml.etree.ElementTree import fromstring as xml_to_tree @@ -60,6 +59,7 @@ class LibvirtConnTestCase(test.TestCase): admin=True) self.project = self.manager.create_project('fake', 'fake', 'fake') self.network = utils.import_object(FLAGS.network_manager) + self.context = context.get_admin_context() FLAGS.instances_path = '' self.call_libvirt_dependant_setup = False @@ -73,22 +73,52 @@ class LibvirtConnTestCase(test.TestCase): 'bridge': 'br101', 'instance_type': 'm1.small'} - def libvirt_dependant_setup(self): - """A setup method of LibvirtConnection dependent test.""" - # try to connect libvirt. if fail, skip test. - self.call_libvirt_dependant_setup = True - try: - libvirt.openReadOnly('qemu:///system') - except libvirt.libvirtError: - return - return libvirt_conn.get_connection(False) - - def libvirt_dependant_teardown(self): - """teardown method of LibvirtConnection dependent test.""" - if self.call_libvirt_dependant_setup: - libvirt_conn.libvirt = None - libvirt_conn.libxml2 = None - self.call_libvirt_dependant_setup = False + def create_fake_libvirt_mock(self, **kwargs): + """Defining mocks for LibvirtConnection(libvirt is not used).""" + + # A fake libvirt.virtConnect + class FakeLibvirtConnection(object): + def getVersion(self): + return 12003 + + def getType(self): + return 'qemu' + + def getCapabilities(self): + return 'qemu' + + def listDomainsID(self): + return [] + + def getCapabilitied(self): + return + + # A fake libvirt_conn.IptablesFirewallDriver + class FakeIptablesFirewallDriver(object): + def __init__(self, **kwargs): + pass + + # Creating mocks + fake = FakeLibvirtConnection() + fakeip = FakeIptablesFirewallDriver + # Customizing above fake if necessary + for key, val in kwargs.items(): + fake.__setattr__(key, val) + + # Inevitable mocks for libvirt_conn.LibvirtConnection + self.mox.StubOutWithMock(libvirt_conn.utils, 'import_class') + libvirt_conn.utils.import_class(mox.IgnoreArg()).AndReturn(fakeip) + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') + libvirt_conn.LibvirtConnection._conn = fake + + def create_service(self, **kwargs): + service_ref = {'host': kwargs.get('host', 'dummy'), + 'binary': 'nova-compute', + 'topic': 'compute', + 'report_count': 0, + 'availability_zone': 'zone'} + + return db.service_create(context.get_admin_context(), service_ref) def test_xml_and_uri_no_ramdisk_no_kernel(self): instance_data = dict(self.test_instance) @@ -244,306 +274,55 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) db.instance_destroy(user_context, instance_ref['id']) - def test_get_vcpu_used(self): - """Check if get_local_gb_total returns appropriate disk value.""" - self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') - libvirt_conn.LibvirtConnection._conn.listDomainsID().AndReturn([1, 2]) - vdmock = self.mox.CreateMock(libvirt.virDomain) - self.mox.StubOutWithMock(vdmock, "vcpus") - vdmock.vcpus().AndReturn(['', [('dummycpu'), ('dummycpu')]]) - vdmock.vcpus().AndReturn(['', [('dummycpu'), ('dummycpu')]]) - arg = mox.IgnoreArg() - libvirt_conn.LibvirtConnection._conn.lookupByID(arg).AndReturn(vdmock) - libvirt_conn.LibvirtConnection._conn.lookupByID(arg).AndReturn(vdmock) - - self.mox.ReplayAll() - conn = libvirt_conn.LibvirtConnection(False) - self.assertTrue(conn.get_vcpu_used() == 4) - - def test_get_cpu_info_inappropreate_xml(self): - """Raise exception if given xml is inappropriate.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - xml = """ - x86_64 - Nehalem - Intel - - - - - - - - - - - - - - - - - - """ - - self.mox.StubOutWithMock(conn._conn, 'getCapabilities') - conn._conn.getCapabilities().AndReturn(xml) - - self.mox.ReplayAll() - try: - conn.get_cpu_info() - except exception.Invalid, e: - c1 = (0 <= e.message.find('Invalid xml')) - self.assertTrue(c1) - - def test_get_cpu_info_inappropreate_xml2(self): - """Raise exception if given xml is inappropriate(topology tag).""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - xml = """ - x86_64 - Nehalem - Intel - - - - - - - - - - - - - - - - - """ - self.mox.StubOutWithMock(conn._conn, 'getCapabilities') - conn._conn.getCapabilities().AndReturn(xml) - - self.mox.ReplayAll() - try: - conn.get_cpu_info() - except exception.Invalid, e: - c1 = (0 <= e.message.find('Invalid xml: topology')) - self.assertTrue(c1) - def test_update_available_resource_works_correctly(self): """Confirm compute_service table is updated successfully.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - host = 'dummy' - zone = 'dummyzone' - ctxt = context.get_admin_context() org_path = FLAGS.instances_path = '' FLAGS.instances_path = '.' - service_ref = db.service_create(ctxt, - {'host': host, - 'binary': 'nova-compute', - 'topic': 'compute', - 'report_count': 0, - 'availability_zone': zone}) - conn.update_available_resource(ctxt, host) + service_ref = self.create_service(host='dummy') + self.create_fake_libvirt_mock() + self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, + 'get_cpu_info') + libvirt_conn.LibvirtConnection.get_cpu_info().AndReturn('cpuinfo') - service_ref = db.service_get(ctxt, service_ref['id']) - print service_ref['compute_service'] + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + conn.update_available_resource(self.context, 'dummy') + service_ref = db.service_get(self.context, service_ref['id']) compute_service = service_ref['compute_service'][0] + c1 = (compute_service['vcpus'] > 0) c2 = (compute_service['memory_mb'] > 0) c3 = (compute_service['local_gb'] > 0) - # vcpu_used is checked at test_get_vcpu_used. - c4 = (compute_service['memory_mb_used'] > 0) - c5 = (compute_service['local_gb_used'] > 0) - c6 = (len(compute_service['hypervisor_type']) > 0) - c7 = (compute_service['hypervisor_version'] > 0) + c4 = (compute_service['vcpus_used'] == 0) + c5 = (compute_service['memory_mb_used'] > 0) + c6 = (compute_service['local_gb_used'] > 0) + c7 = (len(compute_service['hypervisor_type']) > 0) + c8 = (compute_service['hypervisor_version'] > 0) - self.assertTrue(c1 and c2 and c3 and c4 and c5 and c6 and c7) + self.assertTrue(c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8) - db.service_destroy(ctxt, service_ref['id']) + db.service_destroy(self.context, service_ref['id']) FLAGS.instances_path = org_path - def test_update_resource_info_raise_exception(self): + def test_update_resource_info_no_compute_record_found(self): """Raise exception if no recorde found on services table.""" - host = 'dummy' - org_path = FLAGS.instances_path = '' - FLAGS.instances_path = '.' - try: - conn = libvirt_conn.LibvirtConnection(False) - conn.update_available_resource(context.get_admin_context(), host) - except exception.Invalid, e: - msg = 'Cannot update compute manager specific info' - c1 = (0 <= e.message.find(msg)) - self.assertTrue(c1) - FLAGS.instances_path = org_path - - def test_compare_cpu_works_correctly(self): - """Calling libvirt.compute_cpu() and works correctly.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - host = 'dummy' - zone = 'dummyzone' - ctxt = context.get_admin_context() org_path = FLAGS.instances_path = '' FLAGS.instances_path = '.' - - service_ref = db.service_create(ctxt, - {'host': host, - 'binary': 'nova-compute', - 'topic': 'compute', - 'report_count': 0, - 'availability_zone': zone}) - conn.update_available_resource(ctxt, host) - service_ref = db.service_get(ctxt, service_ref['id']) - ret = conn.compare_cpu(service_ref['compute_service'][0]['cpu_info']) - self.assertTrue(ret == None) - - db.service_destroy(ctxt, service_ref['id']) - FLAGS.instances_path = org_path - - def test_compare_cpu_no_compatibility(self): - """Libvirt.compare_cpu() return less than 0.(no compatibility).""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - t = {} - t['arch'] = 'x86' - t['model'] = 'model' - t['vendor'] = 'Intel' - t['topology'] = {'cores': "2", "threads": "1", "sockets": "4"} - t['features'] = ["tm"] - cpu_info = utils.dumps(t) - self.mox.StubOutWithMock(conn._conn, 'compareCPU') - conn._conn.compareCPU(mox.IgnoreArg(), 0).AndReturn(0) - - self.mox.ReplayAll() - self.assertRaises(exception.Invalid, conn.compare_cpu, cpu_info) - - def test_ensure_filtering_rules_for_instance_works_correctly(self): - """ensure_filtering_rules_for_instance() works successfully.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - instance_ref = models.Instance() - instance_ref.__setitem__('id', 1) - fwdriver = conn.firewall_driver - - self.mox.StubOutWithMock(fwdriver, 'setup_basic_filtering') - fwdriver.setup_basic_filtering(instance_ref) - self.mox.StubOutWithMock(fwdriver, 'prepare_instance_filter') - fwdriver.prepare_instance_filter(instance_ref) - self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') - n = 'nova-instance-%s' % instance_ref.name - conn._conn.nwfilterLookupByName(n) - - self.mox.ReplayAll() - conn.ensure_filtering_rules_for_instance(instance_ref) - - def test_ensure_filtering_rules_for_instance_timeout(self): - """ensure_filtering_fules_for_instance() finishes with timeout.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - instance_ref = models.Instance() - instance_ref.__setitem__('id', 1) - fwdriver = conn.firewall_driver - - self.mox.StubOutWithMock(fwdriver, 'setup_basic_filtering') - fwdriver.setup_basic_filtering(instance_ref) - self.mox.StubOutWithMock(fwdriver, 'prepare_instance_filter') - fwdriver.prepare_instance_filter(instance_ref) - self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') - n = 'nova-instance-%s' % instance_ref.name - for i in range(FLAGS.live_migration_retry_count): - conn._conn.nwfilterLookupByName(n).\ - AndRaise(libvirt.libvirtError('ERR')) - - self.mox.ReplayAll() - try: - conn.ensure_filtering_rules_for_instance(instance_ref) - except exception.Error, e: - c1 = (0 <= e.message.find('Timeout migrating for')) - self.assertTrue(c1) - - def test_live_migration_works_correctly(self): - """_live_migration() works as expected correctly.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - class dummyCall(object): - f = None - - def start(self, interval=0, now=False): - pass - - i_ref = models.Instance() - i_ref.__setitem__('id', 1) - ctxt = context.get_admin_context() - - vdmock = self.mox.CreateMock(libvirt.virDomain) - self.mox.StubOutWithMock(vdmock, "migrateToURI") - vdmock.migrateToURI(FLAGS.live_migration_uri % 'dest', - mox.IgnoreArg(), - None, FLAGS.live_migration_bandwidth).\ - AndReturn(None) - self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') - conn._conn.lookupByName(i_ref.name).AndReturn(vdmock) - self.mox.StubOutWithMock(libvirt_conn.utils, 'LoopingCall') - libvirt_conn.utils.LoopingCall(f=None).AndReturn(dummyCall()) + self.create_fake_libvirt_mock() self.mox.ReplayAll() - # Nothing to do with setting post_method/recover_method or not. - ret = conn._live_migration(ctxt, i_ref, 'dest', '', '') - self.assertTrue(ret == None) - - def test_live_migration_raises_exception(self): - """Confirms recover method is called when exceptions are raised.""" - conn = self.libvirt_dependant_setup() - if not conn: - return - - i_ref = models.Instance() - i_ref.__setitem__('id', 1) - ctxt = context.get_admin_context() - - def dummy_recover_method(c, instance, host=None): - pass - - vdmock = self.mox.CreateMock(libvirt.virDomain) - self.mox.StubOutWithMock(vdmock, "migrateToURI") - vdmock.migrateToURI(FLAGS.live_migration_uri % 'dest', - mox.IgnoreArg(), - None, FLAGS.live_migration_bandwidth).\ - AndRaise(libvirt.libvirtError('ERR')) - self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, '_conn') - conn._conn.lookupByName(i_ref.name).AndReturn(vdmock) + conn = libvirt_conn.LibvirtConnection(False) + self.assertRaises(exception.Invalid, + conn.update_available_resource, + self.context, 'dummy') - self.mox.ReplayAll() - self.assertRaises(libvirt.libvirtError, - conn._live_migration, - ctxt, i_ref, 'dest', - '', dummy_recover_method) + FLAGS.instances_path = org_path def tearDown(self): self.manager.delete_project(self.project) self.manager.delete_user(self.user) super(LibvirtConnTestCase, self).tearDown() - self.libvirt_dependant_teardown() class IptablesFirewallTestCase(test.TestCase): -- cgit From 26c217d1f16b100b9dc615388ee315e6daf336ce Mon Sep 17 00:00:00 2001 From: Masanori Itoh Date: Fri, 4 Mar 2011 00:30:19 +0900 Subject: Updated DescribeKeyPairs response tag checked in nova/tests/test_cloud.py --- nova/tests/test_cloud.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 061910013..b195fa520 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -267,7 +267,7 @@ class CloudTestCase(test.TestCase): self._create_key('test1') self._create_key('test2') result = self.cloud.describe_key_pairs(self.context) - keys = result["keypairsSet"] + keys = result["keySet"] self.assertTrue(filter(lambda k: k['keyName'] == 'test1', keys)) self.assertTrue(filter(lambda k: k['keyName'] == 'test2', keys)) -- cgit From 6797c5acc47fb5111ef821d6b074cb635692a9fb Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Thu, 3 Mar 2011 15:41:45 +0000 Subject: Add in multi-tenant support in openstack api. --- nova/tests/api/openstack/fakes.py | 82 +++++++++++++++++- nova/tests/api/openstack/test_accounts.py | 123 ++++++++++++++++++++++++++ nova/tests/api/openstack/test_adminapi.py | 6 +- nova/tests/api/openstack/test_auth.py | 17 ++-- nova/tests/api/openstack/test_flavors.py | 4 +- nova/tests/api/openstack/test_images.py | 6 +- nova/tests/api/openstack/test_servers.py | 51 +++++------ nova/tests/api/openstack/test_users.py | 139 ++++++++++++++++++++++++++++++ nova/tests/api/openstack/test_zones.py | 12 +-- 9 files changed, 394 insertions(+), 46 deletions(-) create mode 100644 nova/tests/api/openstack/test_accounts.py create mode 100644 nova/tests/api/openstack/test_users.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 49ce8c1b5..03b26e29a 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -26,7 +26,6 @@ from paste import urlmap from glance import client as glance_client -from nova import auth from nova import context from nova import exception as exc from nova import flags @@ -35,6 +34,7 @@ import nova.api.openstack.auth from nova.api import openstack from nova.api.openstack import auth from nova.api.openstack import ratelimiting +from nova.auth.manager import User, Project from nova.image import glance from nova.image import local from nova.image import service @@ -227,19 +227,97 @@ class FakeAuthDatabase(object): class FakeAuthManager(object): auth_data = {} + projects = {} + + @classmethod + def clear_fakes(cls): + cls.auth_data = {} + cls.projects = {} + + @classmethod + def reset_fake_data(cls): + cls.auth_data = dict(acc1=User('guy1', 'guy1', 'acc1', + 'fortytwo!', False)) + cls.projects = dict(testacct=Project('testacct', + 'testacct', + 'guy1', + 'test', + [])) def add_user(self, key, user): FakeAuthManager.auth_data[key] = user + def get_users(self): + return FakeAuthManager.auth_data.values() + def get_user(self, uid): for k, v in FakeAuthManager.auth_data.iteritems(): if v.id == uid: return v return None - def get_project(self, pid): + def delete_user(self, uid): + for k, v in FakeAuthManager.auth_data.items(): + if v.id == uid: + del FakeAuthManager.auth_data[k] return None + def create_user(self, name, access=None, secret=None, admin=False): + u = User(name, name, access, secret, admin) + FakeAuthManager.auth_data[access] = u + return u + + def modify_user(self, user_id, access=None, secret=None, admin=None): + user = None + for k, v in FakeAuthManager.auth_data.iteritems(): + if v.id == user_id: + user = v + if user: + user.access = access + user.secret = secret + if admin is not None: + user.admin = admin + + def is_admin(self, user): + return user.admin + + def is_project_member(self, user, project): + return ((user.id in project.member_ids) or + (user.id == project.project_manager_id)) + + def create_project(self, name, manager_user, description=None, + member_users=None): + member_ids = [User.safe_id(m) for m in member_users] \ + if member_users else [] + p = Project(name, name, User.safe_id(manager_user), + description, member_ids) + FakeAuthManager.projects[name] = p + return p + + def delete_project(self, pid): + if pid in FakeAuthManager.projects: + del FakeAuthManager.projects[pid] + + def modify_project(self, project, manager_user=None, description=None): + p = FakeAuthManager.projects.get(project) + p.project_manager_id = User.safe_id(manager_user) + p.description = description + + def get_project(self, pid): + p = FakeAuthManager.projects.get(pid) + if p: + return p + else: + raise exc.NotFound + + def get_projects(self, user=None): + if not user: + return FakeAuthManager.projects.values() + else: + return [p for p in FakeAuthManager.projects.values() + if (user.id in p.member_ids) or + (user.id == p.project_manager_id)] + def get_user_from_access_key(self, key): return FakeAuthManager.auth_data.get(key, None) diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py new file mode 100644 index 000000000..b2e89824a --- /dev/null +++ b/nova/tests/api/openstack/test_accounts.py @@ -0,0 +1,123 @@ +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + + +import stubout +import webob +import json + +import nova.api +import nova.api.openstack.auth +from nova import context +from nova import flags +from nova import test +from nova.auth.manager import User +from nova.tests.api.openstack import fakes + + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +def fake_init(self): + self.manager = fakes.FakeAuthManager() + + +def fake_admin_check(self, req): + return True + + +class AccountsTest(test.TestCase): + def setUp(self): + super(AccountsTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(nova.api.openstack.accounts.Controller, '__init__', + fake_init) + self.stubs.Set(nova.api.openstack.accounts.Controller, '_check_admin', + fake_admin_check) + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.projects = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + + self.allow_admin = FLAGS.allow_admin_api + FLAGS.allow_admin_api = True + fakemgr = fakes.FakeAuthManager() + joeuser = User('guy1', 'guy1', 'acc1', 'fortytwo!', False) + superuser = User('guy2', 'guy2', 'acc2', 'swordfish', True) + fakemgr.add_user(joeuser.access, joeuser) + fakemgr.add_user(superuser.access, superuser) + fakemgr.create_project('test1', joeuser) + fakemgr.create_project('test2', superuser) + + def tearDown(self): + self.stubs.UnsetAll() + FLAGS.allow_admin_api = self.allow_admin + super(AccountsTest, self).tearDown() + + def test_get_account(self): + req = webob.Request.blank('/v1.0/test1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res_dict['account']['id'], 'test1') + self.assertEqual(res_dict['account']['name'], 'test1') + self.assertEqual(res_dict['account']['manager'], 'guy1') + self.assertEqual(res.status_int, 200) + + def test_account_delete(self): + req = webob.Request.blank('/v1.0/test1') + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertTrue('test1' not in fakes.FakeAuthManager.projects) + self.assertEqual(res.status_int, 200) + + def test_account_create(self): + body = dict(account=dict(description='test account', + manager='guy1')) + req = webob.Request.blank('/v1.0/newacct') + req.method = 'PUT' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['account']['id'], 'newacct') + self.assertEqual(res_dict['account']['name'], 'newacct') + self.assertEqual(res_dict['account']['description'], 'test account') + self.assertEqual(res_dict['account']['manager'], 'guy1') + self.assertTrue('newacct' in + fakes.FakeAuthManager.projects) + self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 3) + + def test_account_update(self): + body = dict(account=dict(description='test account', + manager='guy2')) + req = webob.Request.blank('/v1.0/test1') + req.method = 'PUT' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['account']['id'], 'test1') + self.assertEqual(res_dict['account']['name'], 'test1') + self.assertEqual(res_dict['account']['description'], 'test account') + self.assertEqual(res_dict['account']['manager'], 'guy2') + self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 2) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index dfce1b127..7cb9e8450 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -35,7 +35,7 @@ class AdminAPITest(test.TestCase): def setUp(self): super(AdminAPITest, self).setUp() self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -50,7 +50,7 @@ class AdminAPITest(test.TestCase): def test_admin_enabled(self): FLAGS.allow_admin_api = True # We should still be able to access public operations. - req = webob.Request.blank('/v1.0/flavors') + req = webob.Request.blank('/v1.0/testacct/flavors') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are available. @@ -58,7 +58,7 @@ class AdminAPITest(test.TestCase): def test_admin_disabled(self): FLAGS.allow_admin_api = False # We should still be able to access public operations. - req = webob.Request.blank('/v1.0/flavors') + req = webob.Request.blank('/v1.0/testacct/flavors') res = req.get_response(fakes.wsgi_app()) # TODO: Confirm admin operations are unavailable. self.assertEqual(res.status_int, 200) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index ff8d42a14..8268a6fb9 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,7 +51,9 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + u = nova.auth.manager.User(1, 'herp', None, None, None) + f.add_user('derp', u) + f.create_project('test', u) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' @@ -65,7 +67,9 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + u = nova.auth.manager.User(1, 'herp', None, None, None) + f.add_user('derp', u) + f.create_project('test', u) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' @@ -74,7 +78,7 @@ class Test(test.TestCase): self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) self.assertEqual(result.headers['X-Server-Management-Url'], - "http://foo/v1.0/") + "http://foo/v1.0/test/") self.assertEqual(result.headers['X-CDN-Management-Url'], "") self.assertEqual(result.headers['X-Storage-Url'], "") @@ -82,7 +86,7 @@ class Test(test.TestCase): token = result.headers['X-Auth-Token'] self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter) - req = webob.Request.blank('/v1.0/fake') + req = webob.Request.blank('/v1.0/test/fake') req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '200 OK') @@ -176,6 +180,9 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() + u = nova.auth.manager.User(1, 'herp', None, None, None) + f.add_user('derp', u) + f.create_project('test', u) f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/') @@ -187,7 +194,7 @@ class TestLimiter(test.TestCase): token = result.headers['X-Auth-Token'] self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter) - req = webob.Request.blank('/v1.0/fake') + req = webob.Request.blank('/v1.0/test/fake') req.method = 'POST' req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 761265965..370dc007c 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -28,7 +28,7 @@ class FlavorsTest(test.TestCase): def setUp(self): super(FlavorsTest, self).setUp() self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -39,7 +39,7 @@ class FlavorsTest(test.TestCase): super(FlavorsTest, self).tearDown() def test_get_flavor_list(self): - req = webob.Request.blank('/v1.0/flavors') + req = webob.Request.blank('/v1.0/testacct/flavors') res = req.get_response(fakes.wsgi_app()) def test_get_flavor_by_id(self): diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index e232bc3d5..819ca001e 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -202,7 +202,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.orig_image_service = FLAGS.image_service FLAGS.image_service = 'nova.image.glance.GlanceImageService' self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -216,7 +216,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): super(ImageControllerWithGlanceServiceTest, self).tearDown() def test_get_image_index(self): - req = webob.Request.blank('/v1.0/images') + req = webob.Request.blank('/v1.0/testacct/images') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -228,7 +228,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): "image %s not in fixture index!" % str(image)) def test_get_image_details(self): - req = webob.Request.blank('/v1.0/images/detail') + req = webob.Request.blank('/v1.0/testacct/images/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 78beb7df9..d592e06b0 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -118,7 +118,7 @@ class ServersTest(test.TestCase): def setUp(self): super(ServersTest, self).setUp() self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -150,7 +150,7 @@ class ServersTest(test.TestCase): super(ServersTest, self).tearDown() def test_get_server_by_id(self): - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -161,7 +161,7 @@ class ServersTest(test.TestCase): public = ["1.2.3.4"] new_return_server = return_server_with_addresses(private, public) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -173,7 +173,7 @@ class ServersTest(test.TestCase): self.assertEqual(addresses["private"][0], private) def test_get_server_list(self): - req = webob.Request.blank('/v1.0/servers') + req = webob.Request.blank('/v1.0/testacct/servers') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -224,7 +224,7 @@ class ServersTest(test.TestCase): name='server_test', imageId=2, flavorId=2, metadata={'hello': 'world', 'open': 'stack'}, personality={})) - req = webob.Request.blank('/v1.0/servers') + req = webob.Request.blank('/v1.0/testacct/servers') req.method = 'POST' req.body = json.dumps(body) @@ -233,7 +233,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_update_no_body(self): - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') req.method = 'PUT' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 422) @@ -251,7 +251,7 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_update', server_update) - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') req.method = 'PUT' req.body = self.body req.get_response(fakes.wsgi_app()) @@ -267,30 +267,30 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_update', server_update) - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') req.method = 'PUT' req.body = self.body req.get_response(fakes.wsgi_app()) def test_create_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') req.method = 'POST' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_delete_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_get_server_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_get_all_server_details(self): - req = webob.Request.blank('/v1.0/servers/detail') + req = webob.Request.blank('/v1.0/testacct/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -321,7 +321,7 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_get_all_by_user', return_servers_with_host) - req = webob.Request.blank('/v1.0/servers/detail') + req = webob.Request.blank('/v1.0/testacct/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -341,7 +341,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/pause') + req = webob.Request.blank('/v1.0/testacct/servers/1/pause') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -353,7 +353,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/unpause') + req = webob.Request.blank('/v1.0/testacct/servers/1/unpause') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -365,7 +365,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/suspend') + req = webob.Request.blank('/v1.0/testacct/servers/1/suspend') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -377,7 +377,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/resume') + req = webob.Request.blank('/v1.0/testacct/servers/1/resume') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -389,7 +389,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/reset_network') + req = webob.Request.blank('/v1.0/testacct/servers/1/reset_network') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -401,7 +401,8 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/inject_network_info') + req = webob.Request.blank( + '/v1.0/testacct/servers/1/inject_network_info') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -409,13 +410,13 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_diagnostics(self): - req = webob.Request.blank("/v1.0/servers/1/diagnostics") + req = webob.Request.blank("/v1.0/testacct/servers/1/diagnostics") req.method = "GET" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) def test_server_actions(self): - req = webob.Request.blank("/v1.0/servers/1/actions") + req = webob.Request.blank("/v1.0/testacct/servers/1/actions") req.method = "GET" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) @@ -424,7 +425,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/action') + req = webob.Request.blank('/v1.0/testacct/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -434,7 +435,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/action') + req = webob.Request.blank('/v1.0/testacct/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -444,14 +445,14 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/servers/1/action') + req = webob.Request.blank('/v1.0/testacct/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) def test_delete_server_instance(self): - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.0/testacct/servers/1') req.method = 'DELETE' self.server_delete_called = False diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py new file mode 100644 index 000000000..bd32254cd --- /dev/null +++ b/nova/tests/api/openstack/test_users.py @@ -0,0 +1,139 @@ +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + + +import stubout +import webob +import json + +import nova.api +import nova.api.openstack.auth +from nova import context +from nova import flags +from nova import test +from nova.auth.manager import User, Project +from nova.tests.api.openstack import fakes + + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +def fake_init(self): + self.manager = fakes.FakeAuthManager() + + +def fake_admin_check(self, req): + return True + + +class UsersTest(test.TestCase): + def setUp(self): + super(UsersTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(nova.api.openstack.users.Controller, '__init__', + fake_init) + self.stubs.Set(nova.api.openstack.users.Controller, '_check_admin', + fake_admin_check) + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.projects = dict(testacct=Project('testacct', + 'testacct', + 'guy1', + 'test', + [])) + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + + self.allow_admin = FLAGS.allow_admin_api + FLAGS.allow_admin_api = True + fakemgr = fakes.FakeAuthManager() + fakemgr.add_user('acc1', User('guy1', 'guy1', 'acc1', + 'fortytwo!', False)) + fakemgr.add_user('acc2', User('guy2', 'guy2', 'acc2', + 'swordfish', True)) + + def tearDown(self): + self.stubs.UnsetAll() + FLAGS.allow_admin_api = self.allow_admin + super(UsersTest, self).tearDown() + + def test_get_user_list(self): + req = webob.Request.blank('/v1.0/testacct/users') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(len(res_dict['users']), 2) + + def test_get_user_by_id(self): + req = webob.Request.blank('/v1.0/testacct/users/guy2') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res_dict['user']['id'], 'guy2') + self.assertEqual(res_dict['user']['name'], 'guy2') + self.assertEqual(res_dict['user']['secret'], 'swordfish') + self.assertEqual(res_dict['user']['admin'], True) + self.assertEqual(res.status_int, 200) + + def test_user_delete(self): + req = webob.Request.blank('/v1.0/testacct/users/guy1') + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertTrue('guy1' not in [u.id for u in + fakes.FakeAuthManager.auth_data.values()]) + self.assertEqual(res.status_int, 200) + + def test_user_create(self): + body = dict(user=dict(name='test_guy', + access='acc3', + secret='invasionIsInNormandy', + admin=True)) + req = webob.Request.blank('/v1.0/testacct/users') + req.method = 'POST' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['user']['id'], 'test_guy') + self.assertEqual(res_dict['user']['name'], 'test_guy') + self.assertEqual(res_dict['user']['access'], 'acc3') + self.assertEqual(res_dict['user']['secret'], 'invasionIsInNormandy') + self.assertEqual(res_dict['user']['admin'], True) + self.assertTrue('test_guy' in [u.id for u in + fakes.FakeAuthManager.auth_data.values()]) + self.assertEqual(len(fakes.FakeAuthManager.auth_data.values()), 3) + + def test_user_update(self): + body = dict(user=dict(name='guy2', + access='acc2', + secret='invasionIsInNormandy')) + req = webob.Request.blank('/v1.0/testacct/users/guy2') + req.method = 'PUT' + req.body = json.dumps(body) + + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res.status_int, 200) + self.assertEqual(res_dict['user']['id'], 'guy2') + self.assertEqual(res_dict['user']['name'], 'guy2') + self.assertEqual(res_dict['user']['access'], 'acc2') + self.assertEqual(res_dict['user']['secret'], 'invasionIsInNormandy') + self.assertEqual(res_dict['user']['admin'], True) diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 555b206b9..51f13af48 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -64,7 +64,7 @@ class ZonesTest(test.TestCase): def setUp(self): super(ZonesTest, self).setUp() self.stubs = stubout.StubOutForTesting() - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) @@ -85,7 +85,7 @@ class ZonesTest(test.TestCase): super(ZonesTest, self).tearDown() def test_get_zone_list(self): - req = webob.Request.blank('/v1.0/zones') + req = webob.Request.blank('/v1.0/testacct/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -93,7 +93,7 @@ class ZonesTest(test.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_by_id(self): - req = webob.Request.blank('/v1.0/zones/1') + req = webob.Request.blank('/v1.0/testacct/zones/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -103,7 +103,7 @@ class ZonesTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_zone_delete(self): - req = webob.Request.blank('/v1.0/zones/1') + req = webob.Request.blank('/v1.0/testacct/zones/1') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -111,7 +111,7 @@ class ZonesTest(test.TestCase): def test_zone_create(self): body = dict(zone=dict(api_url='http://blah.zoo', username='fred', password='fubar')) - req = webob.Request.blank('/v1.0/zones') + req = webob.Request.blank('/v1.0/testacct/zones') req.method = 'POST' req.body = json.dumps(body) @@ -125,7 +125,7 @@ class ZonesTest(test.TestCase): def test_zone_update(self): body = dict(zone=dict(username='zeb', password='sneaky')) - req = webob.Request.blank('/v1.0/zones/1') + req = webob.Request.blank('/v1.0/testacct/zones/1') req.method = 'PUT' req.body = json.dumps(body) -- cgit From 137a4946785b9460aadb9fe40f2b0e18bd7f6063 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Fri, 4 Mar 2011 01:09:21 +0900 Subject: Merged to trunk rev 757. Main changes are below. 1. Rename db table ComputeService -> ComputeNode 2. nova-manage option instance_type is reserved and we cannot use option instance, so change instance -> vm. --- nova/tests/test_scheduler.py | 16 ++++++++-------- nova/tests/test_virt.py | 22 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 62db42b11..711b66af7 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -60,7 +60,7 @@ class SchedulerTestCase(test.TestCase): self.flags(scheduler_driver='nova.tests.test_scheduler.TestDriver') def _create_compute_service(self): - """Create compute-manager(ComputeService and Service record).""" + """Create compute-manager(ComputeNode and Service record).""" ctxt = context.get_admin_context() dic = {'host': 'dummy', 'binary': 'nova-compute', 'topic': 'compute', 'report_count': 0, 'availability_zone': 'dummyzone'} @@ -71,7 +71,7 @@ class SchedulerTestCase(test.TestCase): 'vcpus_used': 16, 'memory_mb_used': 32, 'local_gb_used': 10, 'hypervisor_type': 'qemu', 'hypervisor_version': 12003, 'cpu_info': ''} - db.compute_service_create(ctxt, dic) + db.compute_node_create(ctxt, dic) return db.service_get(ctxt, s_ref['id']) @@ -144,8 +144,8 @@ class SchedulerTestCase(test.TestCase): # result checking c1 = ('resource' in result and 'usage' in result) - compute_service = s_ref['compute_service'][0] - c2 = self._dic_is_equal(result['resource'], compute_service) + compute_node = s_ref['compute_node'][0] + c2 = self._dic_is_equal(result['resource'], compute_node) c3 = result['usage'] == {} self.assertTrue(c1 and c2 and c3) db.service_destroy(ctxt, s_ref['id']) @@ -163,8 +163,8 @@ class SchedulerTestCase(test.TestCase): result = scheduler.show_host_resources(ctxt, s_ref['host']) c1 = ('resource' in result and 'usage' in result) - compute_service = s_ref['compute_service'][0] - c2 = self._dic_is_equal(result['resource'], compute_service) + compute_node = s_ref['compute_node'][0] + c2 = self._dic_is_equal(result['resource'], compute_node) c3 = result['usage'].keys() == ['p-01', 'p-02'] keys = ['vcpus', 'memory_mb', 'local_gb'] c4 = self._dic_is_equal(result['usage']['p-01'], i_ref1, keys) @@ -301,7 +301,7 @@ class SimpleDriverTestCase(test.TestCase): dic['memory_mb_used'] = kwargs.get('memory_mb_used', 32) dic['hypervisor_type'] = kwargs.get('hypervisor_type', 'qemu') dic['hypervisor_version'] = kwargs.get('hypervisor_version', 12003) - db.compute_service_create(self.context, dic) + db.compute_node_create(self.context, dic) return db.service_get(self.context, s_ref['id']) def test_doesnt_report_disabled_hosts_as_up(self): @@ -923,7 +923,7 @@ class SimpleDriverTestCase(test.TestCase): self.mox.StubOutWithMock(rpc, 'call', use_mock_anything=True) rpc.call(mox.IgnoreArg(), mox.IgnoreArg(), {"method": 'compare_cpu', - "args": {'cpu_info': s_ref2['compute_service'][0]['cpu_info']}}).\ + "args": {'cpu_info': s_ref2['compute_node'][0]['cpu_info']}}).\ AndRaise(rpc.RemoteError("doesn't have compatibility to", "", "")) self.mox.ReplayAll() diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 17b80c294..aac55a894 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -275,7 +275,7 @@ class LibvirtConnTestCase(test.TestCase): db.instance_destroy(user_context, instance_ref['id']) def test_update_available_resource_works_correctly(self): - """Confirm compute_service table is updated successfully.""" + """Confirm compute_node table is updated successfully.""" org_path = FLAGS.instances_path = '' FLAGS.instances_path = '.' @@ -289,16 +289,16 @@ class LibvirtConnTestCase(test.TestCase): conn = libvirt_conn.LibvirtConnection(False) conn.update_available_resource(self.context, 'dummy') service_ref = db.service_get(self.context, service_ref['id']) - compute_service = service_ref['compute_service'][0] - - c1 = (compute_service['vcpus'] > 0) - c2 = (compute_service['memory_mb'] > 0) - c3 = (compute_service['local_gb'] > 0) - c4 = (compute_service['vcpus_used'] == 0) - c5 = (compute_service['memory_mb_used'] > 0) - c6 = (compute_service['local_gb_used'] > 0) - c7 = (len(compute_service['hypervisor_type']) > 0) - c8 = (compute_service['hypervisor_version'] > 0) + compute_node = service_ref['compute_node'][0] + + c1 = (compute_node['vcpus'] > 0) + c2 = (compute_node['memory_mb'] > 0) + c3 = (compute_node['local_gb'] > 0) + c4 = (compute_node['vcpus_used'] == 0) + c5 = (compute_node['memory_mb_used'] > 0) + c6 = (compute_node['local_gb_used'] > 0) + c7 = (len(compute_node['hypervisor_type']) > 0) + c8 = (compute_node['hypervisor_version'] > 0) self.assertTrue(c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8) -- cgit From 6d075754bdd4090342bf4f79c726a52923c311a8 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 3 Mar 2011 12:45:34 -0500 Subject: adding wsgi.Controller and wsgi.Request testing; fixing format keyword argument exception --- nova/tests/api/test_wsgi.py | 120 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index 2c7852214..cf2d0e297 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -21,11 +21,13 @@ Test WSGI basics and provide some helper functions for other WSGI tests. """ +import json from nova import test import routes import webob +from nova import exception from nova import wsgi @@ -66,30 +68,112 @@ class Test(test.TestCase): result = webob.Request.blank('/bad').get_response(Router()) self.assertNotEqual(result.body, "Router result") - def test_controller(self): - class Controller(wsgi.Controller): - """Test controller to call from router.""" - test = self +class ControllerTest(test.TestCase): + + class TestRouter(wsgi.Router): + + class TestController(wsgi.Controller): + + _serialization_metadata = { + 'application/xml': { + "attributes": { + "test": ["id"]}}} def show(self, req, id): # pylint: disable-msg=W0622,C0103 - """Default action called for requests with an ID.""" - self.test.assertEqual(req.path_info, '/tests/123') - self.test.assertEqual(id, '123') - return id + return {"test": {"id": id}} + + def __init__(self): + mapper = routes.Mapper() + mapper.resource("test", "tests", controller=self.TestController()) + wsgi.Router.__init__(self, mapper) + + def test_show(self): + request = wsgi.Request.blank('/tests/123') + result = request.get_response(self.TestRouter()) + self.assertEqual(json.loads(result.body), {"test": {"id": "123"}}) + + def test_content_type_from_accept_xml(self): + request = webob.Request.blank('/tests/123') + request.headers["Accept"] = "application/xml" + result = request.get_response(self.TestRouter()) + self.assertEqual(result.headers["Content-Type"], "application/xml") + + def test_content_type_from_accept_json(self): + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = "application/json" + result = request.get_response(self.TestRouter()) + self.assertEqual(result.headers["Content-Type"], "application/json") + + def test_content_type_from_query_extension_xml(self): + request = wsgi.Request.blank('/tests/123.xml') + result = request.get_response(self.TestRouter()) + self.assertEqual(result.headers["Content-Type"], "application/xml") + + def test_content_type_from_query_extension_json(self): + request = wsgi.Request.blank('/tests/123.json') + result = request.get_response(self.TestRouter()) + self.assertEqual(result.headers["Content-Type"], "application/json") + + def test_content_type_default_when_unsupported(self): + request = wsgi.Request.blank('/tests/123.unsupported') + request.headers["Accept"] = "application/unsupported1" + result = request.get_response(self.TestRouter()) + self.assertEqual(result.status_int, 200) + self.assertEqual(result.headers["Content-Type"], "application/json") + + +class RequestTest(test.TestCase): + + def test_content_type_from_accept_xml(self): + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = "application/xml" + result = request.best_match() + self.assertEqual(result, "application/xml") + + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = "application/json" + result = request.best_match() + self.assertEqual(result, "application/json") + + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = "application/xml, application/json" + result = request.best_match() + self.assertEqual(result, "application/json") + + request = wsgi.Request.blank('/tests/123') + request.headers["Accept"] = \ + "application/json; q=0.3, application/xml; q=0.9" + result = request.best_match() + self.assertEqual(result, "application/xml") + + def test_content_type_from_query_extension(self): + request = wsgi.Request.blank('/tests/123.xml') + result = request.best_match() + self.assertEqual(result, "application/xml") + + request = wsgi.Request.blank('/tests/123.json') + result = request.best_match() + self.assertEqual(result, "application/json") + + request = wsgi.Request.blank('/tests/123.invalid') + result = request.best_match() + self.assertEqual(result, "application/json") + + def test_content_type_accept_and_query_extension(self): + request = wsgi.Request.blank('/tests/123.xml') + request.headers["Accept"] = "application/json" + result = request.best_match() + self.assertEqual(result, "application/xml") + + def test_content_type_accept_default(self): + request = wsgi.Request.blank('/tests/123.unsupported') + request.headers["Accept"] = "application/unsupported1" + result = request.best_match() + self.assertEqual(result, "application/json") - class Router(wsgi.Router): - """Test router.""" - def __init__(self): - mapper = routes.Mapper() - mapper.resource("test", "tests", controller=Controller()) - super(Router, self).__init__(mapper) - result = webob.Request.blank('/tests/123').get_response(Router()) - self.assertEqual(result.body, "123") - result = webob.Request.blank('/test/123').get_response(Router()) - self.assertNotEqual(result.body, "123") class SerializerTest(test.TestCase): -- cgit From 9cfe8ff2e8e66952c3202b852a88ee6fca6fb736 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 3 Mar 2011 16:31:01 -0500 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 272d34e3a..53cfa3a6e 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -287,8 +287,8 @@ class ServersTest(test.TestCase): request, response, onset_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) - + self.assertEquals(onset_files, [(path, contents)]) + def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' @@ -320,7 +320,7 @@ class ServersTest(test.TestCase): request, response, onset_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(onset_files, [(path, contents)]) def test_create_instance_personality_not_a_list(self): path = '/my/file/path' -- cgit From 848aced747a60c47d76efcb2147041339df4a628 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 3 Mar 2011 17:21:21 -0500 Subject: Refactor wsgi.Serializer away from handling Requests directly; now require Content-Type in all requests; fix tests according to new code --- nova/tests/api/openstack/test_servers.py | 1 + nova/tests/api/openstack/test_zones.py | 15 +++-- nova/tests/api/test_wsgi.py | 95 +++++++++++++++++++------------- nova/tests/test_direct.py | 3 + 4 files changed, 72 insertions(+), 42 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 78beb7df9..fae08d0be 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -227,6 +227,7 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.0/servers') req.method = 'POST' req.body = json.dumps(body) + req.headers["Content-Type"] = "application/json" res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 555b206b9..d0da8eaaf 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -86,24 +86,27 @@ class ZonesTest(test.TestCase): def test_get_zone_list(self): req = webob.Request.blank('/v1.0/zones') + req.headers["Content-Type"] = "application/json" res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + res_dict = json.loads(res.body) self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_by_id(self): req = webob.Request.blank('/v1.0/zones/1') + req.headers["Content-Type"] = "application/json" res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) + self.assertEqual(res.status_int, 200) + res_dict = json.loads(res.body) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') self.assertFalse('password' in res_dict['zone']) - self.assertEqual(res.status_int, 200) def test_zone_delete(self): req = webob.Request.blank('/v1.0/zones/1') + req.headers["Content-Type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -112,13 +115,14 @@ class ZonesTest(test.TestCase): body = dict(zone=dict(api_url='http://blah.zoo', username='fred', password='fubar')) req = webob.Request.blank('/v1.0/zones') + req.headers["Content-Type"] = "application/json" req.method = 'POST' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + res_dict = json.loads(res.body) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://blah.zoo') self.assertFalse('username' in res_dict['zone']) @@ -126,13 +130,14 @@ class ZonesTest(test.TestCase): def test_zone_update(self): body = dict(zone=dict(username='zeb', password='sneaky')) req = webob.Request.blank('/v1.0/zones/1') + req.headers["Content-Type"] = "application/json" req.method = 'PUT' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + res_dict = json.loads(res.body) self.assertEqual(res_dict['zone']['id'], 1) self.assertEqual(res_dict['zone']['api_url'], 'http://foo.com') self.assertFalse('username' in res_dict['zone']) diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index cf2d0e297..7c0135656 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -93,29 +93,29 @@ class ControllerTest(test.TestCase): result = request.get_response(self.TestRouter()) self.assertEqual(json.loads(result.body), {"test": {"id": "123"}}) - def test_content_type_from_accept_xml(self): + def test_response_content_type_from_accept_xml(self): request = webob.Request.blank('/tests/123') request.headers["Accept"] = "application/xml" result = request.get_response(self.TestRouter()) self.assertEqual(result.headers["Content-Type"], "application/xml") - def test_content_type_from_accept_json(self): + def test_response_content_type_from_accept_json(self): request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = "application/json" result = request.get_response(self.TestRouter()) self.assertEqual(result.headers["Content-Type"], "application/json") - def test_content_type_from_query_extension_xml(self): + def test_response_content_type_from_query_extension_xml(self): request = wsgi.Request.blank('/tests/123.xml') result = request.get_response(self.TestRouter()) self.assertEqual(result.headers["Content-Type"], "application/xml") - def test_content_type_from_query_extension_json(self): + def test_response_content_type_from_query_extension_json(self): request = wsgi.Request.blank('/tests/123.json') result = request.get_response(self.TestRouter()) self.assertEqual(result.headers["Content-Type"], "application/json") - def test_content_type_default_when_unsupported(self): + def test_response_content_type_default_when_unsupported(self): request = wsgi.Request.blank('/tests/123.unsupported') request.headers["Accept"] = "application/unsupported1" result = request.get_response(self.TestRouter()) @@ -125,6 +125,17 @@ class ControllerTest(test.TestCase): class RequestTest(test.TestCase): + def test_request_content_type_missing(self): + request = wsgi.Request.blank('/tests/123') + request.body = "" + self.assertRaises(webob.exc.HTTPBadRequest, request.get_content_type) + + def test_request_content_type_unsupported(self): + request = wsgi.Request.blank('/tests/123') + request.headers["Content-Type"] = "text/html" + request.body = "asdf
" + self.assertRaises(webob.exc.HTTPBadRequest, request.get_content_type) + def test_content_type_from_accept_xml(self): request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = "application/xml" @@ -173,40 +184,48 @@ class RequestTest(test.TestCase): self.assertEqual(result, "application/json") - - - class SerializerTest(test.TestCase): - def match(self, url, accept, expect): + def test_xml(self): input_dict = dict(servers=dict(a=(2, 3))) expected_xml = '(2,3)' + serializer = wsgi.Serializer() + result = serializer.serialize(input_dict, "application/xml") + result = result.replace('\n', '').replace(' ', '') + self.assertEqual(result, expected_xml) + + def test_json(self): + input_dict = dict(servers=dict(a=(2, 3))) expected_json = '{"servers":{"a":[2,3]}}' - req = webob.Request.blank(url, headers=dict(Accept=accept)) - result = wsgi.Serializer(req.environ).to_content_type(input_dict) + serializer = wsgi.Serializer() + result = serializer.serialize(input_dict, "application/json") result = result.replace('\n', '').replace(' ', '') - if expect == 'xml': - self.assertEqual(result, expected_xml) - elif expect == 'json': - self.assertEqual(result, expected_json) - else: - raise "Bad expect value" - - def test_basic(self): - self.match('/servers/4.json', None, expect='json') - self.match('/servers/4', 'application/json', expect='json') - self.match('/servers/4', 'application/xml', expect='xml') - self.match('/servers/4.xml', None, expect='xml') - - def test_defaults_to_json(self): - self.match('/servers/4', None, expect='json') - self.match('/servers/4', 'text/html', expect='json') - - def test_suffix_takes_precedence_over_accept_header(self): - self.match('/servers/4.xml', 'application/json', expect='xml') - self.match('/servers/4.xml.', 'application/json', expect='json') - - def test_deserialize(self): + self.assertEqual(result, expected_json) + + def test_unsupported_content_type(self): + serializer = wsgi.Serializer() + self.assertRaises(exception.InvalidContentType, serializer.serialize, + {}, "text/null") + + def test_deserialize_json(self): + data = """{"a": { + "a1": "1", + "a2": "2", + "bs": ["1", "2", "3", {"c": {"c1": "1"}}], + "d": {"e": "1"}, + "f": "1"}}""" + as_dict = dict(a={ + 'a1': '1', + 'a2': '2', + 'bs': ['1', '2', '3', {'c': dict(c1='1')}], + 'd': {'e': '1'}, + 'f': '1'}) + metadata = {} + serializer = wsgi.Serializer(metadata) + self.assertEqual(serializer.deserialize(data, "application/json"), + as_dict) + + def test_deserialize_xml(self): xml = """ 123 @@ -221,11 +240,13 @@ class SerializerTest(test.TestCase): 'd': {'e': '1'}, 'f': '1'}) metadata = {'application/xml': dict(plurals={'bs': 'b', 'ts': 't'})} - serializer = wsgi.Serializer({}, metadata) - self.assertEqual(serializer.deserialize(xml), as_dict) + serializer = wsgi.Serializer(metadata) + self.assertEqual(serializer.deserialize(xml, "application/xml"), + as_dict) def test_deserialize_empty_xml(self): xml = """""" as_dict = {"a": {}} - serializer = wsgi.Serializer({}) - self.assertEqual(serializer.deserialize(xml), as_dict) + serializer = wsgi.Serializer() + self.assertEqual(serializer.deserialize(xml, "application/xml"), + as_dict) diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index b6bfab534..85bfcfd85 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -59,6 +59,7 @@ class DirectTestCase(test.TestCase): req.headers['X-OpenStack-User'] = 'user1' req.headers['X-OpenStack-Project'] = 'proj1' resp = req.get_response(self.auth_router) + self.assertEqual(resp.status_int, 200) data = json.loads(resp.body) self.assertEqual(data['user'], 'user1') self.assertEqual(data['project'], 'proj1') @@ -69,6 +70,7 @@ class DirectTestCase(test.TestCase): req.method = 'POST' req.body = 'json=%s' % json.dumps({'data': 'foo'}) resp = req.get_response(self.router) + self.assertEqual(resp.status_int, 200) resp_parsed = json.loads(resp.body) self.assertEqual(resp_parsed['data'], 'foo') @@ -78,6 +80,7 @@ class DirectTestCase(test.TestCase): req.method = 'POST' req.body = 'data=foo' resp = req.get_response(self.router) + self.assertEqual(resp.status_int, 200) resp_parsed = json.loads(resp.body) self.assertEqual(resp_parsed['data'], 'foo') -- cgit From e14f524eb92ae07704a2ec7dac0f97c60940a6ab Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 3 Mar 2011 17:49:41 -0500 Subject: enforce personality quotas --- nova/tests/test_quota.py | 66 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 48e5a5538..16a083788 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -177,12 +177,66 @@ class QuotaTestCase(test.TestCase): image_id='fake', metadata=metadata) - def test_allowed_file_injection_files(self): + def test_allowed_personality_files(self): self.assertEqual( - quota.allowed_file_injection_files(self.context), - FLAGS.quota_file_injection_max_files) + quota.allowed_personality_files(self.context), + FLAGS.quota_personality_max_files) + + def _create_with_personality(self, files): + api = compute.API() + api.create(self.context, min_count=1, max_count=1, + instance_type='m1.small', image_id='fake', + onset_files=files) + + def test_no_personality_files(self): + api = compute.API() + api.create(self.context, instance_type='m1.small', image_id='fake') + + def test_max_personality_files(self): + files = [] + for i in xrange(FLAGS.quota_personality_max_files): + files.append(('/my/path%d' % i, 'config = test\n')) + self._create_with_personality(files) # no QuotaError + + def test_too_many_personality_files(self): + files = [] + for i in xrange(FLAGS.quota_personality_max_files + 1): + files.append(('/my/path%d' % i, 'my\ncontent%d\n' % i)) + self.assertRaises(quota.QuotaError, + self._create_with_personality, files) - def test_allowed_file_injection_file_bytes(self): + def test_allowed_personality_content_bytes(self): self.assertEqual( - quota.allowed_file_injection_file_bytes(self.context), - FLAGS.quota_file_injection_max_file_bytes) + quota.allowed_personality_content_bytes(self.context), + FLAGS.quota_personality_max_content_bytes) + + def test_max_personality_content_bytes(self): + max = FLAGS.quota_personality_max_content_bytes + content = ''.join(['a' for i in xrange(max)]) + files = [('/test/path', content)] + self._create_with_personality(files) # no QuotaError + + def test_too_many_personality_content_bytes(self): + max = FLAGS.quota_personality_max_content_bytes + content = ''.join(['a' for i in xrange(max + 1)]) + files = [('/test/path', content)] + self.assertRaises(quota.QuotaError, + self._create_with_personality, files) + + def test_allowed_personality_path_bytes(self): + self.assertEqual( + quota.allowed_personality_path_bytes(self.context), + FLAGS.quota_personality_max_path_bytes) + + def test_max_personality_path_bytes(self): + max = FLAGS.quota_personality_max_path_bytes + path = ''.join(['a' for i in xrange(max)]) + files = [(path, 'config = quotatest')] + self._create_with_personality(files) # no QuotaError + + def test_too_many_personality_path_bytes(self): + max = FLAGS.quota_personality_max_path_bytes + path = ''.join(['a' for i in xrange(max + 1)]) + files = [(path, 'config = quotatest')] + self.assertRaises(quota.QuotaError, + self._create_with_personality, files) -- cgit From 5ae13551990be67e3509ddcd10d1872a91634d83 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 3 Mar 2011 18:27:57 -0500 Subject: rename onset_files to personality_files all the way down to compute manager --- nova/tests/api/openstack/test_servers.py | 35 ++++++++++++++++---------------- nova/tests/test_quota.py | 2 +- 2 files changed, 19 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 53cfa3a6e..bf934113a 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -241,13 +241,13 @@ class ServersTest(test.TestCase): class FakeComputeAPI(object): def __init__(self): - self.onset_files = None + self.personality_files = None def create(self, *args, **kwargs): - if 'onset_files' in kwargs: - self.onset_files = kwargs['onset_files'] + if 'personality_files' in kwargs: + self.personality_files = kwargs['personality_files'] else: - self.onset_files = None + self.personality_files = None return [{'id': '1234', 'display_name': 'fakeinstance'}] def make_stub_method(canned_return): @@ -271,32 +271,33 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.0/servers') req.method = 'POST' req.body = json.dumps(body) - return req, req.get_response(fakes.wsgi_app()), compute_api.onset_files + return (req, req.get_response(fakes.wsgi_app()), + compute_api.personality_files) def test_create_instance_with_no_personality(self): - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality=None) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, []) + self.assertEquals(personality_files, []) def test_create_instance_with_personality(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) personality = [self._personality_dict(path, b64contents)] - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(personality_files, [(path, contents)]) def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' personality = [self._personality_dict(path, contents)] - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 400) - self.assertEquals(onset_files, None) + self.assertEquals(personality_files, None) def test_create_instance_with_three_personalities(self): files = [ @@ -308,28 +309,28 @@ class ServersTest(test.TestCase): for path, content in files: personality.append(self._personality_dict( path, base64.b64encode(content))) - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, files) + self.assertEquals(personality_files, files) def test_create_instance_personality_empty_content(self): path = '/my/file/path' contents = '' personality = [self._personality_dict(path, contents)] - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(personality_files, [(path, contents)]) def test_create_instance_personality_not_a_list(self): path = '/my/file/path' contents = 'myfilecontents' personality = self._personality_dict(path, contents) - request, response, onset_files = \ + request, response, personality_files = \ self._create_instance_with_personality(personality) self.assertEquals(response.status_int, 400) - self.assertEquals(onset_files, None) + self.assertEquals(personality_files, None) def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 16a083788..b26dec61a 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -186,7 +186,7 @@ class QuotaTestCase(test.TestCase): api = compute.API() api.create(self.context, min_count=1, max_count=1, instance_type='m1.small', image_id='fake', - onset_files=files) + personality_files=files) def test_no_personality_files(self): api = compute.API() -- cgit From a433ddeda77aaa4462694661ecdca71eed6db669 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 4 Mar 2011 02:36:55 +0000 Subject: Replace objectstore images with S3 image service backending to glance or local --- nova/tests/api/openstack/fakes.py | 11 ++++++----- nova/tests/fake_flags.py | 1 + nova/tests/test_cloud.py | 22 +++++++++++++++------- nova/tests/test_compute.py | 7 ++++++- nova/tests/test_direct.py | 3 +-- nova/tests/test_quota.py | 6 +++--- 6 files changed, 32 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 49ce8c1b5..7b016db08 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -25,6 +25,7 @@ import webob.dec from paste import urlmap from glance import client as glance_client +from glance.common import exception as glance_exc from nova import auth from nova import context @@ -149,25 +150,25 @@ def stub_out_glance(stubs, initial_fixtures=None): for f in self.fixtures: if f['id'] == image_id: return f - return None + raise glance_exc.NotFound - def fake_add_image(self, image_meta): + def fake_add_image(self, image_meta, data=None): id = ''.join(random.choice(string.letters) for _ in range(20)) image_meta['id'] = id self.fixtures.append(image_meta) return id - def fake_update_image(self, image_id, image_meta): + def fake_update_image(self, image_id, image_meta, data=None): f = self.fake_get_image_meta(image_id) if not f: - raise exc.NotFound + raise glance_exc.NotFound f.update(image_meta) def fake_delete_image(self, image_id): f = self.fake_get_image_meta(image_id) if not f: - raise exc.NotFound + raise glance_exc.NotFound self.fixtures.remove(f) diff --git a/nova/tests/fake_flags.py b/nova/tests/fake_flags.py index cbd949477..5d7ca98b5 100644 --- a/nova/tests/fake_flags.py +++ b/nova/tests/fake_flags.py @@ -32,6 +32,7 @@ flags.DECLARE('fake_network', 'nova.network.manager') FLAGS.network_size = 8 FLAGS.num_networks = 2 FLAGS.fake_network = True +FLAGS.image_service = 'nova.image.local.LocalImageService' flags.DECLARE('num_shelves', 'nova.volume.driver') flags.DECLARE('blades_per_shelf', 'nova.volume.driver') flags.DECLARE('iscsi_num_targets', 'nova.volume.driver') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 061910013..7d7b91658 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -38,6 +38,8 @@ from nova import test 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.objectstore import image @@ -76,6 +78,11 @@ class CloudTestCase(test.TestCase): project=self.project) host = self.network.get_network_host(self.context.elevated()) + def fake_image_show(meh, context, id): + return dict(kernelId=1, ramdiskId=1) + + self.stubs.Set(local.LocalImageService, 'show', fake_image_show) + def tearDown(self): network_ref = db.project_get_network(self.context, self.project.id) @@ -122,7 +129,7 @@ class CloudTestCase(test.TestCase): self.cloud.allocate_address(self.context) inst = db.instance_create(self.context, {'host': self.compute.host}) fixed = self.network.allocate_fixed_ip(self.context, inst['id']) - ec2_id = cloud.id_to_ec2_id(inst['id']) + ec2_id = ec2utils.id_to_ec2_id(inst['id']) self.cloud.associate_address(self.context, instance_id=ec2_id, public_ip=address) @@ -158,12 +165,12 @@ class CloudTestCase(test.TestCase): vol2 = db.volume_create(self.context, {}) result = self.cloud.describe_volumes(self.context) self.assertEqual(len(result['volumeSet']), 2) - volume_id = cloud.id_to_ec2_id(vol2['id'], 'vol-%08x') + volume_id = ec2utils.id_to_ec2_id(vol2['id'], 'vol-%08x') result = self.cloud.describe_volumes(self.context, volume_id=[volume_id]) self.assertEqual(len(result['volumeSet']), 1) self.assertEqual( - cloud.ec2_id_to_id(result['volumeSet'][0]['volumeId']), + ec2utils.ec2_id_to_id(result['volumeSet'][0]['volumeId']), vol2['id']) db.volume_destroy(self.context, vol1['id']) db.volume_destroy(self.context, vol2['id']) @@ -200,7 +207,7 @@ class CloudTestCase(test.TestCase): result = self.cloud.describe_instances(self.context) result = result['reservationSet'][0] self.assertEqual(len(result['instancesSet']), 2) - instance_id = cloud.id_to_ec2_id(inst2['id']) + instance_id = ec2utils.id_to_ec2_id(inst2['id']) result = self.cloud.describe_instances(self.context, instance_id=[instance_id]) result = result['reservationSet'][0] @@ -216,6 +223,7 @@ class CloudTestCase(test.TestCase): def test_console_output(self): image_id = FLAGS.default_image + print image_id instance_type = FLAGS.default_instance_type max_count = 1 kwargs = {'image_id': image_id, @@ -347,7 +355,7 @@ class CloudTestCase(test.TestCase): def test_update_of_instance_display_fields(self): inst = db.instance_create(self.context, {}) - ec2_id = cloud.id_to_ec2_id(inst['id']) + ec2_id = ec2utils.id_to_ec2_id(inst['id']) self.cloud.update_instance(self.context, ec2_id, display_name='c00l 1m4g3') inst = db.instance_get(self.context, inst['id']) @@ -365,7 +373,7 @@ class CloudTestCase(test.TestCase): def test_update_of_volume_display_fields(self): vol = db.volume_create(self.context, {}) self.cloud.update_volume(self.context, - cloud.id_to_ec2_id(vol['id'], 'vol-%08x'), + ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x'), display_name='c00l v0lum3') vol = db.volume_get(self.context, vol['id']) self.assertEqual('c00l v0lum3', vol['display_name']) @@ -374,7 +382,7 @@ class CloudTestCase(test.TestCase): def test_update_of_volume_wont_update_private_fields(self): vol = db.volume_create(self.context, {}) self.cloud.update_volume(self.context, - cloud.id_to_ec2_id(vol['id'], 'vol-%08x'), + ec2utils.id_to_ec2_id(vol['id'], 'vol-%08x'), mountpoint='/not/here') vol = db.volume_get(self.context, vol['id']) self.assertEqual(None, vol['mountpoint']) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 949b5e6eb..1f49baaf6 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -31,7 +31,7 @@ from nova import test from nova import utils from nova.auth import manager from nova.compute import instance_types - +from nova.image import local LOG = logging.getLogger('nova.tests.compute') FLAGS = flags.FLAGS @@ -47,6 +47,11 @@ class ComputeTestCase(test.TestCase): network_manager='nova.network.manager.FlatManager') self.compute = utils.import_object(FLAGS.compute_manager) self.compute_api = compute.API() + + def fake_image_show(meh, context, id): + return dict(kernelId=1, ramdiskId=1) + + self.stubs.Set(local.LocalImageService, 'show', fake_image_show) self.manager = manager.AuthManager() self.user = self.manager.create_user('fake', 'fake', 'fake') self.project = self.manager.create_project('fake', 'fake', 'fake') diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index b6bfab534..b130e3f53 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -90,8 +90,7 @@ class DirectTestCase(test.TestCase): class DirectCloudTestCase(test_cloud.CloudTestCase): def setUp(self): super(DirectCloudTestCase, self).setUp() - compute_handle = compute.API(image_service=self.cloud.image_service, - network_api=self.cloud.network_api, + compute_handle = compute.API(network_api=self.cloud.network_api, volume_api=self.cloud.volume_api) direct.register_service('compute', compute_handle) self.router = direct.JsonParamsMiddleware(direct.Router()) diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 4ecb36b54..ca8abdb36 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -57,7 +57,7 @@ class QuotaTestCase(test.TestCase): def _create_instance(self, cores=2): """Create a test instance""" inst = {} - inst['image_id'] = 'ami-test' + inst['image_id'] = 'ami-1' inst['reservation_id'] = 'r-fakeres' inst['user_id'] = self.user.id inst['project_id'] = self.project.id @@ -123,7 +123,7 @@ class QuotaTestCase(test.TestCase): min_count=1, max_count=1, instance_type='m1.small', - image_id='fake') + image_id='ami-1') for instance_id in instance_ids: db.instance_destroy(self.context, instance_id) @@ -136,7 +136,7 @@ class QuotaTestCase(test.TestCase): min_count=1, max_count=1, instance_type='m1.small', - image_id='fake') + image_id='ami-1') for instance_id in instance_ids: db.instance_destroy(self.context, instance_id) -- cgit From cf9bc248f0fc318c4a9fb5087f257216312e39d1 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 4 Mar 2011 05:21:28 +0000 Subject: fix a couple issues with local, update the glance fake to actually return the same types as the real client, fix the image tests --- nova/tests/api/openstack/fakes.py | 3 ++- nova/tests/api/openstack/test_images.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 7b016db08..2c4e57246 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -156,7 +156,7 @@ def stub_out_glance(stubs, initial_fixtures=None): id = ''.join(random.choice(string.letters) for _ in range(20)) image_meta['id'] = id self.fixtures.append(image_meta) - return id + return image_meta def fake_update_image(self, image_id, image_meta, data=None): f = self.fake_get_image_meta(image_id) @@ -164,6 +164,7 @@ def stub_out_glance(stubs, initial_fixtures=None): raise glance_exc.NotFound f.update(image_meta) + return f def fake_delete_image(self, image_id): f = self.fake_get_image_meta(image_id) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index e232bc3d5..eb5039bdb 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -22,6 +22,8 @@ and as a WSGI layer import json import datetime +import shutil +import tempfile import stubout import webob @@ -54,7 +56,7 @@ class BaseImageServiceTests(object): num_images = len(self.service.index(self.context)) - id = self.service.create(self.context, fixture) + id = self.service.create(self.context, fixture)['id'] self.assertNotEquals(None, id) self.assertEquals(num_images + 1, @@ -71,7 +73,7 @@ class BaseImageServiceTests(object): num_images = len(self.service.index(self.context)) - id = self.service.create(self.context, fixture) + id = self.service.create(self.context, fixture)['id'] self.assertNotEquals(None, id) @@ -89,7 +91,7 @@ class BaseImageServiceTests(object): 'instance_id': None, 'progress': None} - id = self.service.create(self.context, fixture) + id = self.service.create(self.context, fixture)['id'] fixture['status'] = 'in progress' @@ -118,7 +120,7 @@ class BaseImageServiceTests(object): ids = [] for fixture in fixtures: - new_id = self.service.create(self.context, fixture) + new_id = self.service.create(self.context, fixture)['id'] ids.append(new_id) num_images = len(self.service.index(self.context)) @@ -137,14 +139,15 @@ class LocalImageServiceTest(test.TestCase, def setUp(self): super(LocalImageServiceTest, self).setUp() + self.tempdir = tempfile.mkdtemp() + self.flags(images_path=self.tempdir) self.stubs = stubout.StubOutForTesting() service_class = 'nova.image.local.LocalImageService' self.service = utils.import_object(service_class) self.context = context.RequestContext(None, None) def tearDown(self): - self.service.delete_all() - self.service.delete_imagedir() + shutil.rmtree(self.tempdir) self.stubs.UnsetAll() super(LocalImageServiceTest, self).tearDown() -- cgit From 1f0df07baac52379b122a9928200305dd9d2151f Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Sat, 5 Mar 2011 00:57:08 +0900 Subject: Fixed based on reviewer's comment. Main changes are below. 1. get_vcpu_total()/get_memory_mb()/get_memory_mb_used() is changed for users who used non-linux environment. 2. test code added to test_virt. --- nova/tests/test_virt.py | 163 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 136 insertions(+), 27 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index aac55a894..5bb31659b 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -15,6 +15,7 @@ # under the License. import mox +import sys from xml.etree.ElementTree import fromstring as xml_to_tree from xml.dom.minidom import parseString as xml_to_dom @@ -27,11 +28,15 @@ from nova import test from nova import utils from nova.api.ec2 import cloud from nova.auth import manager +from nova.compute import manager as compute_manager +from nova.compute import power_state from nova.db.sqlalchemy import models from nova.virt import libvirt_conn +libvirt = None FLAGS = flags.FLAGS flags.DECLARE('instances_path', 'nova.compute.manager') +flags.DECLARE('compute_driver', 'nova.compute.manager') class LibvirtConnTestCase(test.TestCase): @@ -73,31 +78,36 @@ class LibvirtConnTestCase(test.TestCase): 'bridge': 'br101', 'instance_type': 'm1.small'} + def lazy_load_library_exists(self): + """check if libvirt is available.""" + # try to connect libvirt. if fail, skip test. + try: + import libvirt + import libxml2 + except ImportError: + return False + global libvirt + libvirt = __import__('libvirt') + libvirt_conn.libvirt = __import__('libvirt') + libvirt_conn.libxml2 = __import__('libxml2') + return True + def create_fake_libvirt_mock(self, **kwargs): """Defining mocks for LibvirtConnection(libvirt is not used).""" - # A fake libvirt.virtConnect + # A fake libvirt.virConnect class FakeLibvirtConnection(object): - def getVersion(self): - return 12003 - - def getType(self): - return 'qemu' - - def getCapabilities(self): - return 'qemu' - - def listDomainsID(self): - return [] - - def getCapabilitied(self): - return + pass # A fake libvirt_conn.IptablesFirewallDriver class FakeIptablesFirewallDriver(object): + def __init__(self, **kwargs): pass + def setattr(self, key, val): + self.__setattr__(key, val) + # Creating mocks fake = FakeLibvirtConnection() fakeip = FakeIptablesFirewallDriver @@ -274,33 +284,54 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) db.instance_destroy(user_context, instance_ref['id']) - def test_update_available_resource_works_correctly(self): + def tes1t_update_available_resource_works_correctly(self): """Confirm compute_node table is updated successfully.""" org_path = FLAGS.instances_path = '' FLAGS.instances_path = '.' + # Prepare mocks + def getVersion(): + return 12003 + + def getType(): + return 'qemu' + + def listDomainsID(): + return [] + service_ref = self.create_service(host='dummy') - self.create_fake_libvirt_mock() + self.create_fake_libvirt_mock(getVersion=getVersion, + getType=getType, + listDomainsID=listDomainsID) self.mox.StubOutWithMock(libvirt_conn.LibvirtConnection, 'get_cpu_info') libvirt_conn.LibvirtConnection.get_cpu_info().AndReturn('cpuinfo') + # Start test self.mox.ReplayAll() conn = libvirt_conn.LibvirtConnection(False) conn.update_available_resource(self.context, 'dummy') service_ref = db.service_get(self.context, service_ref['id']) compute_node = service_ref['compute_node'][0] - c1 = (compute_node['vcpus'] > 0) - c2 = (compute_node['memory_mb'] > 0) - c3 = (compute_node['local_gb'] > 0) - c4 = (compute_node['vcpus_used'] == 0) - c5 = (compute_node['memory_mb_used'] > 0) - c6 = (compute_node['local_gb_used'] > 0) - c7 = (len(compute_node['hypervisor_type']) > 0) - c8 = (compute_node['hypervisor_version'] > 0) - - self.assertTrue(c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8) + if sys.platform.upper() == 'LINUX2': + self.assertTrue(compute_node['vcpus'] > 0) + self.assertTrue(compute_node['memory_mb'] > 0) + self.assertTrue(compute_node['local_gb'] > 0) + self.assertTrue(compute_node['vcpus_used'] == 0) + self.assertTrue(compute_node['memory_mb_used'] > 0) + self.assertTrue(compute_node['local_gb_used'] > 0) + self.assertTrue(len(compute_node['hypervisor_type']) > 0) + self.assertTrue(compute_node['hypervisor_version'] > 0) + else: + self.assertTrue(compute_node['vcpus'] > 0) + self.assertTrue(compute_node['memory_mb'] == 0) + self.assertTrue(compute_node['local_gb'] > 0) + self.assertTrue(compute_node['vcpus_used'] == 0) + self.assertTrue(compute_node['memory_mb_used'] == 0) + self.assertTrue(compute_node['local_gb_used'] > 0) + self.assertTrue(len(compute_node['hypervisor_type']) > 0) + self.assertTrue(compute_node['hypervisor_version'] > 0) db.service_destroy(self.context, service_ref['id']) FLAGS.instances_path = org_path @@ -319,6 +350,84 @@ class LibvirtConnTestCase(test.TestCase): FLAGS.instances_path = org_path + def test_ensure_filtering_rules_for_instance_timeout(self): + """ensure_filtering_fules_for_instance() finishes with timeout.""" + # Skip if non-libvirt environment + if not self.lazy_load_library_exists(): + return + + # Preparing mocks + def fake_none(self): + return + + def fake_raise(self): + raise libvirt.libvirtError('ERR') + + self.create_fake_libvirt_mock(nwfilterLookupByName=fake_raise) + instance_ref = db.instance_create(self.context, self.test_instance) + + # Start test + self.mox.ReplayAll() + try: + conn = libvirt_conn.LibvirtConnection(False) + conn.firewall_driver.setattr('setup_basic_filtering', fake_none) + conn.firewall_driver.setattr('prepare_instance_filter', fake_none) + conn.ensure_filtering_rules_for_instance(instance_ref) + except exception.Error, e: + c1 = (0 <= e.message.find('Timeout migrating for')) + self.assertTrue(c1) + + db.instance_destroy(self.context, instance_ref['id']) + + def test_live_migration_raises_exception(self): + """Confirms recover method is called when exceptions are raised.""" + # Skip if non-libvirt environment + if not self.lazy_load_library_exists(): + return + + # Preparing data + self.compute = utils.import_object(FLAGS.compute_manager) + instance_dict = {'host': 'fake', 'state': power_state.RUNNING, + 'state_description': 'running'} + instance_ref = db.instance_create(self.context, self.test_instance) + instance_ref = db.instance_update(self.context, instance_ref['id'], + instance_dict) + vol_dict = {'status': 'migrating', 'size': 1} + volume_ref = db.volume_create(self.context, vol_dict) + db.volume_attached(self.context, volume_ref['id'], instance_ref['id'], + '/dev/fake') + + # Preparing mocks + vdmock = self.mox.CreateMock(libvirt.virDomain) + self.mox.StubOutWithMock(vdmock, "migrateToURI") + vdmock.migrateToURI(FLAGS.live_migration_uri % 'dest', + mox.IgnoreArg(), + None, FLAGS.live_migration_bandwidth).\ + AndRaise(libvirt.libvirtError('ERR')) + + def fake_lookup(instance_name): + if instance_name == instance_ref.name: + return vdmock + + self.create_fake_libvirt_mock(lookupByName=fake_lookup) + + # Start test + self.mox.ReplayAll() + conn = libvirt_conn.LibvirtConnection(False) + self.assertRaises(libvirt.libvirtError, + conn._live_migration, + self.context, instance_ref, 'dest', '', + self.compute.recover_live_migration) + + instance_ref = db.instance_get(self.context, instance_ref['id']) + self.assertTrue(instance_ref['state_description'] == 'running') + self.assertTrue(instance_ref['state'] == power_state.RUNNING) + volume_ref = db.volume_get(self.context, volume_ref['id']) + self.assertTrue(volume_ref['status'] == 'in-use') + + db.volume_destroy(self.context, volume_ref['id']) + db.instance_destroy(self.context, instance_ref['id']) + def tearDown(self): self.manager.delete_project(self.project) self.manager.delete_user(self.user) -- cgit From 23291a5e1a0134aff5fe030b52d4335a6f2a18d9 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Sat, 5 Mar 2011 01:07:12 +0900 Subject: delete unnecessary DECLARE --- nova/tests/test_virt.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 5bb31659b..7ea8c0fb5 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -36,7 +36,6 @@ from nova.virt import libvirt_conn libvirt = None FLAGS = flags.FLAGS flags.DECLARE('instances_path', 'nova.compute.manager') -flags.DECLARE('compute_driver', 'nova.compute.manager') class LibvirtConnTestCase(test.TestCase): -- cgit From 1d8914fc752f7182f942cdd40f2ba18baedeed0c Mon Sep 17 00:00:00 2001 From: Cerberus Date: Fri, 4 Mar 2011 11:19:35 -0600 Subject: More fixes --- nova/tests/xenapi/stubs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index d17951b81..caefcff34 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -221,7 +221,7 @@ class FakeSessionForVolumeFailedTests(FakeSessionForVolumeTests): class FakeSessionForMigrationTests(fake.SessionBase): - """ Stubs out a XenAPISession for Migration tests """ + """Stubs out a XenAPISession for Migration tests""" def __init__(self, uri): super(FakeSessionForMigrationTests, self).__init__(uri) -- cgit From 68d894be2ec3b4eaa14dc5c90143f45f7db1e4b8 Mon Sep 17 00:00:00 2001 From: Cory Wright Date: Fri, 4 Mar 2011 17:48:28 +0000 Subject: * Tests to verify correct vm-params for Windows and Linux instances --- nova/tests/db/fakes.py | 1 + nova/tests/test_xenapi.py | 99 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 85 insertions(+), 15 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 05bdd172e..facd6efae 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -62,6 +62,7 @@ def stub_out_db_instance_api(stubs): 'mac_address': values['mac_address'], 'vcpus': type_data['vcpus'], 'local_gb': type_data['local_gb'], + 'os_type': values['os_type'] } return FakeModel(base_options) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index b9bb6d5b4..24a5698e5 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -18,6 +18,7 @@ Test suite for XenAPI """ +import functools import stubout from nova import db @@ -41,6 +42,21 @@ from nova.tests.glance import stubs as glance_stubs FLAGS = flags.FLAGS +def stub_vm_utils_with_vdi_attached_here(function, should_return=True): + """ + vm_utils.with_vdi_attached_here needs to be stubbed out because it + calls down to the filesystem to attach a vdi. This provides a + decorator to handle that. + """ + @functools.wraps(function) + def decorated_function(self, *args, **kwargs): + orig_with_vdi_attached_here = vm_utils.with_vdi_attached_here + vm_utils.with_vdi_attached_here = lambda *x: should_return + function(self, *args, **kwargs) + vm_utils.with_vdi_attached_here = orig_with_vdi_attached_here + return decorated_function + + class XenAPIVolumeTestCase(test.TestCase): """ Unit tests for Volume operations @@ -62,6 +78,7 @@ class XenAPIVolumeTestCase(test.TestCase): 'ramdisk_id': 3, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', + 'os_type': 'linux' } def _create_volume(self, size='0'): @@ -219,7 +236,7 @@ class XenAPIVMTestCase(test.TestCase): check() - def check_vm_record(self, conn): + def create_vm_record(self, conn, os_type): instances = conn.list_instances() self.assertEquals(instances, [1]) @@ -231,28 +248,63 @@ class XenAPIVMTestCase(test.TestCase): in xenapi_fake.get_all_records('VM').iteritems() if not rec['is_control_domain']] vm = vms[0] + self.vm_info = vm_info + self.vm = vm + def check_vm_record(self): # Check that m1.large above turned into the right thing. instance_type = instance_types.INSTANCE_TYPES['m1.large'] mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) vcpus = instance_type['vcpus'] - self.assertEquals(vm_info['max_mem'], mem_kib) - self.assertEquals(vm_info['mem'], mem_kib) - self.assertEquals(vm['memory_static_max'], mem_bytes) - self.assertEquals(vm['memory_dynamic_max'], mem_bytes) - self.assertEquals(vm['memory_dynamic_min'], mem_bytes) - self.assertEquals(vm['VCPUs_max'], str(vcpus)) - self.assertEquals(vm['VCPUs_at_startup'], str(vcpus)) + self.assertEquals(self.vm_info['max_mem'], mem_kib) + self.assertEquals(self.vm_info['mem'], mem_kib) + self.assertEquals(self.vm['memory_static_max'], mem_bytes) + self.assertEquals(self.vm['memory_dynamic_max'], mem_bytes) + self.assertEquals(self.vm['memory_dynamic_min'], mem_bytes) + self.assertEquals(self.vm['VCPUs_max'], str(vcpus)) + self.assertEquals(self.vm['VCPUs_at_startup'], str(vcpus)) # Check that the VM is running according to Nova - self.assertEquals(vm_info['state'], power_state.RUNNING) + self.assertEquals(self.vm_info['state'], power_state.RUNNING) # Check that the VM is running according to XenAPI. - self.assertEquals(vm['power_state'], 'Running') + self.assertEquals(self.vm['power_state'], 'Running') + + def check_vm_params_for_windows(self): + self.assertEquals(self.vm['platform']['nx'], 'true') + self.assertEquals(self.vm['HVM_boot_params'], {'order': 'dc'}) + self.assertEquals(self.vm['HVM_boot_policy'], 'BIOS order') + + # check that these are not set + self.assertEquals(self.vm['PV_args'], '') + self.assertEquals(self.vm['PV_bootloader'], '') + self.assertEquals(self.vm['PV_kernel'], '') + self.assertEquals(self.vm['PV_ramdisk'], '') + + def check_vm_params_for_linux(self): + self.assertEquals(self.vm['platform']['nx'], 'false') + self.assertEquals(self.vm['PV_args'], 'clocksource=jiffies') + self.assertEquals(self.vm['PV_bootloader'], 'pygrub') + + # check that these are not set + self.assertEquals(self.vm['PV_kernel'], '') + self.assertEquals(self.vm['PV_ramdisk'], '') + self.assertEquals(self.vm['HVM_boot_params'], {}) + self.assertEquals(self.vm['HVM_boot_policy'], '') + + def check_vm_params_for_linux_with_external_kernel(self): + self.assertEquals(self.vm['platform']['nx'], 'false') + self.assertEquals(self.vm['PV_args'], 'root=/dev/xvda1') + self.assertNotEquals(self.vm['PV_kernel'], '') + self.assertNotEquals(self.vm['PV_ramdisk'], '') + + # check that these are not set + self.assertEquals(self.vm['HVM_boot_params'], {}) + self.assertEquals(self.vm['HVM_boot_policy'], '') def _test_spawn(self, image_id, kernel_id, ramdisk_id, - instance_type="m1.large"): + instance_type="m1.large", os_type="linux"): stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) values = {'name': 1, 'id': 1, @@ -263,11 +315,13 @@ class XenAPIVMTestCase(test.TestCase): 'ramdisk_id': ramdisk_id, 'instance_type': instance_type, 'mac_address': 'aa:bb:cc:dd:ee:ff', + 'os_type': os_type } conn = xenapi_conn.get_connection(False) instance = db.instance_create(values) conn.spawn(instance) - self.check_vm_record(conn) + self.create_vm_record(conn, os_type) + self.check_vm_record() def test_spawn_not_enough_memory(self): FLAGS.xenapi_image_service = 'glance' @@ -283,24 +337,37 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_image_service = 'objectstore' self._test_spawn(1, 2, 3) + @stub_vm_utils_with_vdi_attached_here def test_spawn_raw_glance(self): FLAGS.xenapi_image_service = 'glance' self._test_spawn(glance_stubs.FakeGlance.IMAGE_RAW, None, None) + self.check_vm_params_for_linux() + + def test_spawn_vhd_glance_linux(self): + FLAGS.xenapi_image_service = 'glance' + self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None, + os_type="linux") + self.check_vm_params_for_linux() - def test_spawn_vhd_glance(self): + def test_spawn_vhd_glance_windows(self): FLAGS.xenapi_image_service = 'glance' - self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None) + self._test_spawn(glance_stubs.FakeGlance.IMAGE_VHD, None, None, + os_type="windows") + self.check_vm_params_for_windows() def test_spawn_glance(self): FLAGS.xenapi_image_service = 'glance' self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, glance_stubs.FakeGlance.IMAGE_KERNEL, glance_stubs.FakeGlance.IMAGE_RAMDISK) + self.check_vm_params_for_linux_with_external_kernel() def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) self.manager.delete_user(self.user) + self.vm_info = None + self.vm = None self.stubs.UnsetAll() def _create_instance(self): @@ -314,7 +381,8 @@ class XenAPIVMTestCase(test.TestCase): 'kernel_id': 2, 'ramdisk_id': 3, 'instance_type': 'm1.large', - 'mac_address': 'aa:bb:cc:dd:ee:ff'} + 'mac_address': 'aa:bb:cc:dd:ee:ff', + 'os_type': 'linux'} instance = db.instance_create(values) self.conn.spawn(instance) return instance @@ -360,6 +428,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase): self.fake_instance = FakeInstance() self.fake_instance.id = 42 + self.fake_instance.os_type = 'linux' def assert_disk_type(self, disk_type): dt = vm_utils.VMHelper.determine_disk_image_type( -- cgit From f36b4fe22bcb187d5f426320bbe43fcf3cb1a30a Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Fri, 4 Mar 2011 14:44:29 -0500 Subject: refactor server tests to support xml and json separately --- nova/tests/api/openstack/test_servers.py | 103 ++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 35 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index bf934113a..9e7bc3aac 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -233,12 +233,9 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) - def _personality_dict(self, path, contents): - return {'path': path, 'contents': contents} + def _setup_mock_compute_api_for_personality(self): - def _create_instance_with_personality(self, personality): - - class FakeComputeAPI(object): + class MockComputeAPI(object): def __init__(self): self.personality_files = None @@ -255,28 +252,74 @@ class ServersTest(test.TestCase): return canned_return return stub_method - compute_api = FakeComputeAPI() + compute_api = MockComputeAPI() self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api)) self.stubs.Set(nova.api.openstack.servers.Controller, '_get_kernel_ramdisk_from_image', make_stub_method((1, 1))) self.stubs.Set(nova.api.openstack.common, 'get_image_id_from_image_hash', make_stub_method(2)) - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, - metadata={}, - personality=personality)) - if personality is None: - del body['server']['personality'] - + return compute_api + + def _create_personality_request_dict(self, personality_files): + server = {} + server['name'] = 'new-server-test' + server['imageId'] = 1 + server['flavorId'] = 1 + if personality_files is not None: + personalities = [] + for path, contents in personality_files: + personalities.append({'path': path, 'contents': contents}) + server['personality'] = personalities + return {'server': server} + + def _create_personality_request_json(self, personality_files): + body_dict = self._create_personality_request_dict(personality_files) req = webob.Request.blank('/v1.0/servers') + req.content_type = 'application/json' req.method = 'POST' - req.body = json.dumps(body) - return (req, req.get_response(fakes.wsgi_app()), - compute_api.personality_files) + req.body = json.dumps(body_dict) + return req + + def _format_xml_request_body(self, body_dict): + server = body_dict['server'] + body_parts = [] + body_parts.extend([ + '', + '' % ( + server['name'], server['imageId'], server['flavorId'])]) + if 'metadata' in server: + metadata = server['metadata'] + body_parts.append('') + for item in metadata.iteritems(): + body_parts.append('%s' % item) + body_parts.append('') + if 'personality' in server: + personalities = server['personality'] + body_parts.append('') + for item in personalities.iteritems(): + body_parts.append('%s' % item) + body_parts.append('') + body_parts.append('') + return ''.join(body_parts) + + def _create_personality_request_xml(self, personality_files): + body_dict = self._create_personality_request_dict(personality_files) + req = webob.Request.blank('/v1.0/servers') + req.content_type = 'application/xml' + req.method = 'POST' + req.body = self._format_xml_request_body(body_dict) + return req + + def _create_instance_with_personality_json(self, personality): + compute_api = self._setup_mock_compute_api_for_personality() + request = self._create_personality_request_json(personality) + response = request.get_response(fakes.wsgi_app()) + return (request, response, compute_api.personality_files) def test_create_instance_with_no_personality(self): request, response, personality_files = \ - self._create_instance_with_personality(personality=None) + self._create_instance_with_personality_json(personality=None) self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, []) @@ -284,18 +327,18 @@ class ServersTest(test.TestCase): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) - personality = [self._personality_dict(path, b64contents)] + personality = [(path, b64contents)] request, response, personality_files = \ - self._create_instance_with_personality(personality) + self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, [(path, contents)]) def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' - personality = [self._personality_dict(path, contents)] + personality = [(path, contents)] request, response, personality_files = \ - self._create_instance_with_personality(personality) + self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 400) self.assertEquals(personality_files, None) @@ -307,31 +350,21 @@ class ServersTest(test.TestCase): ] personality = [] for path, content in files: - personality.append(self._personality_dict( - path, base64.b64encode(content))) + personality.append((path, base64.b64encode(content))) request, response, personality_files = \ - self._create_instance_with_personality(personality) + self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, files) def test_create_instance_personality_empty_content(self): path = '/my/file/path' contents = '' - personality = [self._personality_dict(path, contents)] + personality = [(path, contents)] request, response, personality_files = \ - self._create_instance_with_personality(personality) + self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, [(path, contents)]) - def test_create_instance_personality_not_a_list(self): - path = '/my/file/path' - contents = 'myfilecontents' - personality = self._personality_dict(path, contents) - request, response, personality_files = \ - self._create_instance_with_personality(personality) - self.assertEquals(response.status_int, 400) - self.assertEquals(personality_files, None) - def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' -- cgit From a38e6c67c37a4d3336cf1dc3717fd5612a474183 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Fri, 4 Mar 2011 14:45:31 -0500 Subject: remove xml testing infrastructure since it is not feasible to use at present --- nova/tests/api/openstack/test_servers.py | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 9e7bc3aac..c125e6192 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -280,37 +280,6 @@ class ServersTest(test.TestCase): req.body = json.dumps(body_dict) return req - def _format_xml_request_body(self, body_dict): - server = body_dict['server'] - body_parts = [] - body_parts.extend([ - '', - '' % ( - server['name'], server['imageId'], server['flavorId'])]) - if 'metadata' in server: - metadata = server['metadata'] - body_parts.append('') - for item in metadata.iteritems(): - body_parts.append('%s' % item) - body_parts.append('') - if 'personality' in server: - personalities = server['personality'] - body_parts.append('') - for item in personalities.iteritems(): - body_parts.append('%s' % item) - body_parts.append('') - body_parts.append('') - return ''.join(body_parts) - - def _create_personality_request_xml(self, personality_files): - body_dict = self._create_personality_request_dict(personality_files) - req = webob.Request.blank('/v1.0/servers') - req.content_type = 'application/xml' - req.method = 'POST' - req.body = self._format_xml_request_body(body_dict) - return req - def _create_instance_with_personality_json(self, personality): compute_api = self._setup_mock_compute_api_for_personality() request = self._create_personality_request_json(personality) -- cgit From 1831f31af0ac21ded3535f15777bd5147c615c34 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Fri, 4 Mar 2011 11:52:18 -0800 Subject: added flatmanager unit testcases and renamed test_network.py to test_vlan_network.py --- nova/tests/test_flat_network.py | 276 +++++++++++++++++++++++++++++ nova/tests/test_network.py | 369 --------------------------------------- nova/tests/test_vlan_network.py | 373 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 649 insertions(+), 369 deletions(-) create mode 100644 nova/tests/test_flat_network.py delete mode 100644 nova/tests/test_network.py create mode 100644 nova/tests/test_vlan_network.py (limited to 'nova/tests') diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py new file mode 100644 index 000000000..91a49920d --- /dev/null +++ b/nova/tests/test_flat_network.py @@ -0,0 +1,276 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Unit Tests for network code +""" +import IPy +import os +import unittest + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.auth import manager + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +class FlatNetworkTestCase(test.TestCase): + """Test cases for network code""" + def setUp(self): + super(FlatNetworkTestCase, self).setUp() + # NOTE(vish): if you change these flags, make sure to change the + # flags in the corresponding section in nova-dhcpbridge + self.flags(connection_type='fake', + fake_call=True, + fake_network=True) + self.manager = manager.AuthManager() + self.user = self.manager.create_user('netuser', 'netuser', 'netuser') + self.projects = [] + self.network = utils.import_object(FLAGS.network_manager) + self.context = context.RequestContext(project=None, user=self.user) + for i in range(5): + name = 'project%s' % i + project = self.manager.create_project(name, 'netuser', name) + self.projects.append(project) + # create the necessary network data for the project + user_context = context.RequestContext(project=self.projects[i], + user=self.user) + host = self.network.get_network_host(user_context.elevated()) + instance_ref = self._create_instance(0) + self.instance_id = instance_ref['id'] + instance_ref = self._create_instance(1) + self.instance2_id = instance_ref['id'] + + def tearDown(self): + # TODO(termie): this should really be instantiating clean datastores + # in between runs, one failure kills all the tests + db.instance_destroy(context.get_admin_context(), self.instance_id) + db.instance_destroy(context.get_admin_context(), self.instance2_id) + for project in self.projects: + self.manager.delete_project(project) + self.manager.delete_user(self.user) + super(FlatNetworkTestCase, self).tearDown() + + def _create_instance(self, project_num, mac=None): + if not mac: + mac = utils.generate_mac() + project = self.projects[project_num] + self.context._project = project + self.context.project_id = project.id + return db.instance_create(self.context, + {'project_id': project.id, + 'mac_address': mac}) + + def _create_address(self, project_num, instance_id=None): + """Create an address in given project num""" + if instance_id is None: + instance_id = self.instance_id + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + return self.network.allocate_fixed_ip(self.context, instance_id) + + def _deallocate_address(self, project_num, address): + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + self.network.deallocate_fixed_ip(self.context, address) + + def test_private_ipv6(self): + """Make sure ipv6 is OK""" + if FLAGS.use_ipv6: + instance_ref = self._create_instance(0) + address = self._create_address(0, instance_ref['id']) + network_ref = db.project_get_network( + context.get_admin_context(), + self.context.project_id) + address_v6 = db.instance_get_fixed_address_v6( + context.get_admin_context(), + instance_ref['id']) + self.assertEqual(instance_ref['mac_address'], + utils.to_mac(address_v6)) + instance_ref2 = db.fixed_ip_get_instance_v6( + context.get_admin_context(), + address_v6) + self.assertEqual(instance_ref['id'], instance_ref2['id']) + self.assertEqual(address_v6, + utils.to_global_ipv6( + network_ref['cidr_v6'], + instance_ref['mac_address'])) + self._deallocate_address(0, address) + db.instance_destroy(context.get_admin_context(), + instance_ref['id']) + + def test_public_network_association(self): + """Makes sure that we can allocate a public ip""" + # TODO(vish): better way of adding floating ips + + self.context._project = self.projects[0] + self.context.project_id = self.projects[0].id + pubnet = IPy.IP(flags.FLAGS.floating_range) + address = str(pubnet[0]) + try: + db.floating_ip_get_by_address(context.get_admin_context(), address) + except exception.NotFound: + db.floating_ip_create(context.get_admin_context(), + {'address': address, + 'host': FLAGS.host}) + + self.assertRaises(NotImplementedError, + self.network.allocate_floating_ip, + self.context, self.projects[0].id) + + fix_addr = self._create_address(0) + float_addr = address + self.assertRaises(NotImplementedError, + self.network.associate_floating_ip, + self.context, float_addr, fix_addr) + + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, None) + + self.assertRaises(NotImplementedError, + self.network.disassociate_floating_ip, + self.context, float_addr) + + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, None) + + self.assertRaises(NotImplementedError, + self.network.deallocate_floating_ip, + self.context, float_addr) + + self.network.deallocate_fixed_ip(self.context, fix_addr) + db.floating_ip_destroy(context.get_admin_context(), float_addr) + + def test_allocate_deallocate_fixed_ip(self): + """Makes sure that we can allocate and deallocate a fixed ip""" + address = self._create_address(0) + self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self._deallocate_address(0, address) + + # check if the fixed ip address is really deallocated + self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + + def test_side_effects(self): + """Ensures allocating and releasing has no side effects""" + address = self._create_address(0) + address2 = self._create_address(1, self.instance2_id) + + self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) + + self._deallocate_address(0, address) + self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + + # First address release shouldn't affect the second + self.assertTrue(is_allocated_in_project(address2, self.projects[0].id)) + + self._deallocate_address(1, address2) + self.assertFalse(is_allocated_in_project(address2, + self.projects[1].id)) + + def test_ips_are_reused(self): + """Makes sure that ip addresses that are deallocated get reused""" + address = self._create_address(0) + self.network.deallocate_fixed_ip(self.context, address) + + address2 = self._create_address(0) + self.assertEqual(address, address2) + + self.network.deallocate_fixed_ip(self.context, address2) + + def test_available_ips(self): + """Make sure the number of available ips for the network is correct + + The number of available IP addresses depends on the test + environment's setup. + + Network size is set in test fixture's setUp method. + + There are ips reserved at the bottom and top of the range. + services (network, gateway, CloudPipe, broadcast) + """ + network = db.project_get_network(context.get_admin_context(), + self.projects[0].id) + net_size = flags.FLAGS.network_size + admin_context = context.get_admin_context() + total_ips = (db.network_count_available_ips(admin_context, + network['id']) + + db.network_count_reserved_ips(admin_context, + network['id']) + + db.network_count_allocated_ips(admin_context, + network['id'])) + self.assertEqual(total_ips, net_size) + + def test_too_many_addresses(self): + """Test for a NoMoreAddresses exception when all fixed ips are used. + """ + admin_context = context.get_admin_context() + network = db.project_get_network(admin_context, self.projects[0].id) + num_available_ips = db.network_count_available_ips(admin_context, + network['id']) + addresses = [] + instance_ids = [] + for i in range(num_available_ips): + instance_ref = self._create_instance(0) + instance_ids.append(instance_ref['id']) + address = self._create_address(0, instance_ref['id']) + addresses.append(address) + + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, 0) + self.assertRaises(db.NoMoreAddresses, + self.network.allocate_fixed_ip, + self.context, + 'foo') + + for i in range(num_available_ips): + self.network.deallocate_fixed_ip(self.context, addresses[i]) + db.instance_destroy(context.get_admin_context(), instance_ids[i]) + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, num_available_ips) + + def run(self, result=None): + if(FLAGS.network_manager == 'nova.network.manager.FlatManager'): + super(FlatNetworkTestCase, self).run(result) + + +def is_allocated_in_project(address, project_id): + """Returns true if address is in specified project""" + #project_net = db.project_get_network(context.get_admin_context(), + # project_id) + project_net = db.network_get_by_bridge(context.get_admin_context(), + FLAGS.flat_network_bridge) + network = db.fixed_ip_get_network(context.get_admin_context(), address) + instance = db.fixed_ip_get_instance(context.get_admin_context(), address) + # instance exists until release + return instance is not None and network['id'] == project_net['id'] + + +def binpath(script): + """Returns the absolute path to a script in bin""" + return os.path.abspath(os.path.join(__file__, "../../../bin", script)) diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py deleted file mode 100644 index ce1c77210..000000000 --- a/nova/tests/test_network.py +++ /dev/null @@ -1,369 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. -""" -Unit Tests for network code -""" -import IPy -import os - -from nova import context -from nova import db -from nova import exception -from nova import flags -from nova import log as logging -from nova import test -from nova import utils -from nova.auth import manager - -FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.tests.network') - - -class NetworkTestCase(test.TestCase): - """Test cases for network code""" - def setUp(self): - super(NetworkTestCase, self).setUp() - # NOTE(vish): if you change these flags, make sure to change the - # flags in the corresponding section in nova-dhcpbridge - self.flags(connection_type='fake', - fake_call=True, - fake_network=True) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('netuser', 'netuser', 'netuser') - self.projects = [] - self.network = utils.import_object(FLAGS.network_manager) - self.context = context.RequestContext(project=None, user=self.user) - for i in range(FLAGS.num_networks): - name = 'project%s' % i - project = self.manager.create_project(name, 'netuser', name) - self.projects.append(project) - # create the necessary network data for the project - user_context = context.RequestContext(project=self.projects[i], - user=self.user) - host = self.network.get_network_host(user_context.elevated()) - instance_ref = self._create_instance(0) - self.instance_id = instance_ref['id'] - instance_ref = self._create_instance(1) - self.instance2_id = instance_ref['id'] - - def tearDown(self): - # TODO(termie): this should really be instantiating clean datastores - # in between runs, one failure kills all the tests - db.instance_destroy(context.get_admin_context(), self.instance_id) - db.instance_destroy(context.get_admin_context(), self.instance2_id) - for project in self.projects: - self.manager.delete_project(project) - self.manager.delete_user(self.user) - super(NetworkTestCase, self).tearDown() - - def _create_instance(self, project_num, mac=None): - if not mac: - mac = utils.generate_mac() - project = self.projects[project_num] - self.context._project = project - self.context.project_id = project.id - return db.instance_create(self.context, - {'project_id': project.id, - 'mac_address': mac}) - - def _create_address(self, project_num, instance_id=None): - """Create an address in given project num""" - if instance_id is None: - instance_id = self.instance_id - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - return self.network.allocate_fixed_ip(self.context, instance_id) - - def _deallocate_address(self, project_num, address): - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - self.network.deallocate_fixed_ip(self.context, address) - - def test_private_ipv6(self): - """Make sure ipv6 is OK""" - if FLAGS.use_ipv6: - instance_ref = self._create_instance(0) - address = self._create_address(0, instance_ref['id']) - network_ref = db.project_get_network( - context.get_admin_context(), - self.context.project_id) - address_v6 = db.instance_get_fixed_address_v6( - context.get_admin_context(), - instance_ref['id']) - self.assertEqual(instance_ref['mac_address'], - utils.to_mac(address_v6)) - instance_ref2 = db.fixed_ip_get_instance_v6( - context.get_admin_context(), - address_v6) - self.assertEqual(instance_ref['id'], instance_ref2['id']) - self.assertEqual(address_v6, - utils.to_global_ipv6( - network_ref['cidr_v6'], - instance_ref['mac_address'])) - self._deallocate_address(0, address) - db.instance_destroy(context.get_admin_context(), - instance_ref['id']) - - def test_public_network_association(self): - """Makes sure that we can allocaate a public ip""" - # TODO(vish): better way of adding floating ips - self.context._project = self.projects[0] - self.context.project_id = self.projects[0].id - pubnet = IPy.IP(flags.FLAGS.floating_range) - address = str(pubnet[0]) - try: - db.floating_ip_get_by_address(context.get_admin_context(), address) - except exception.NotFound: - db.floating_ip_create(context.get_admin_context(), - {'address': address, - 'host': FLAGS.host}) - float_addr = self.network.allocate_floating_ip(self.context, - self.projects[0].id) - fix_addr = self._create_address(0) - lease_ip(fix_addr) - self.assertEqual(float_addr, str(pubnet[0])) - self.network.associate_floating_ip(self.context, float_addr, fix_addr) - address = db.instance_get_floating_address(context.get_admin_context(), - self.instance_id) - self.assertEqual(address, float_addr) - self.network.disassociate_floating_ip(self.context, float_addr) - address = db.instance_get_floating_address(context.get_admin_context(), - self.instance_id) - self.assertEqual(address, None) - self.network.deallocate_floating_ip(self.context, float_addr) - self.network.deallocate_fixed_ip(self.context, fix_addr) - release_ip(fix_addr) - db.floating_ip_destroy(context.get_admin_context(), float_addr) - - def test_allocate_deallocate_fixed_ip(self): - """Makes sure that we can allocate and deallocate a fixed ip""" - address = self._create_address(0) - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) - lease_ip(address) - self._deallocate_address(0, address) - - # Doesn't go away until it's dhcp released - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) - - release_ip(address) - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) - - def test_side_effects(self): - """Ensures allocating and releasing has no side effects""" - address = self._create_address(0) - address2 = self._create_address(1, self.instance2_id) - - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) - self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) - self.assertFalse(is_allocated_in_project(address, self.projects[1].id)) - - # Addresses are allocated before they're issued - lease_ip(address) - lease_ip(address2) - - self._deallocate_address(0, address) - release_ip(address) - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) - - # First address release shouldn't affect the second - self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) - - self._deallocate_address(1, address2) - release_ip(address2) - self.assertFalse(is_allocated_in_project(address2, - self.projects[1].id)) - - def test_subnet_edge(self): - """Makes sure that private ips don't overlap""" - first = self._create_address(0) - lease_ip(first) - instance_ids = [] - for i in range(1, FLAGS.num_networks): - instance_ref = self._create_instance(i, mac=utils.generate_mac()) - instance_ids.append(instance_ref['id']) - address = self._create_address(i, instance_ref['id']) - instance_ref = self._create_instance(i, mac=utils.generate_mac()) - instance_ids.append(instance_ref['id']) - address2 = self._create_address(i, instance_ref['id']) - instance_ref = self._create_instance(i, mac=utils.generate_mac()) - instance_ids.append(instance_ref['id']) - address3 = self._create_address(i, instance_ref['id']) - lease_ip(address) - lease_ip(address2) - lease_ip(address3) - self.context._project = self.projects[i] - self.context.project_id = self.projects[i].id - self.assertFalse(is_allocated_in_project(address, - self.projects[0].id)) - self.assertFalse(is_allocated_in_project(address2, - self.projects[0].id)) - self.assertFalse(is_allocated_in_project(address3, - self.projects[0].id)) - self.network.deallocate_fixed_ip(self.context, address) - self.network.deallocate_fixed_ip(self.context, address2) - self.network.deallocate_fixed_ip(self.context, address3) - release_ip(address) - release_ip(address2) - release_ip(address3) - for instance_id in instance_ids: - db.instance_destroy(context.get_admin_context(), instance_id) - self.context._project = self.projects[0] - self.context.project_id = self.projects[0].id - self.network.deallocate_fixed_ip(self.context, first) - self._deallocate_address(0, first) - release_ip(first) - - def test_vpn_ip_and_port_looks_valid(self): - """Ensure the vpn ip and port are reasonable""" - self.assert_(self.projects[0].vpn_ip) - self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start) - self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start + - FLAGS.num_networks) - - def test_too_many_networks(self): - """Ensure error is raised if we run out of networks""" - projects = [] - networks_left = (FLAGS.num_networks - - db.network_count(context.get_admin_context())) - for i in range(networks_left): - project = self.manager.create_project('many%s' % i, self.user) - projects.append(project) - db.project_get_network(context.get_admin_context(), project.id) - project = self.manager.create_project('last', self.user) - projects.append(project) - self.assertRaises(db.NoMoreNetworks, - db.project_get_network, - context.get_admin_context(), - project.id) - for project in projects: - self.manager.delete_project(project) - - def test_ips_are_reused(self): - """Makes sure that ip addresses that are deallocated get reused""" - address = self._create_address(0) - lease_ip(address) - self.network.deallocate_fixed_ip(self.context, address) - release_ip(address) - - address2 = self._create_address(0) - self.assertEqual(address, address2) - lease_ip(address) - self.network.deallocate_fixed_ip(self.context, address2) - release_ip(address) - - def test_available_ips(self): - """Make sure the number of available ips for the network is correct - - The number of available IP addresses depends on the test - environment's setup. - - Network size is set in test fixture's setUp method. - - There are ips reserved at the bottom and top of the range. - services (network, gateway, CloudPipe, broadcast) - """ - network = db.project_get_network(context.get_admin_context(), - self.projects[0].id) - net_size = flags.FLAGS.network_size - admin_context = context.get_admin_context() - total_ips = (db.network_count_available_ips(admin_context, - network['id']) + - db.network_count_reserved_ips(admin_context, - network['id']) + - db.network_count_allocated_ips(admin_context, - network['id'])) - self.assertEqual(total_ips, net_size) - - def test_too_many_addresses(self): - """Test for a NoMoreAddresses exception when all fixed ips are used. - """ - admin_context = context.get_admin_context() - network = db.project_get_network(admin_context, self.projects[0].id) - num_available_ips = db.network_count_available_ips(admin_context, - network['id']) - addresses = [] - instance_ids = [] - for i in range(num_available_ips): - instance_ref = self._create_instance(0) - instance_ids.append(instance_ref['id']) - address = self._create_address(0, instance_ref['id']) - addresses.append(address) - lease_ip(address) - - ip_count = db.network_count_available_ips(context.get_admin_context(), - network['id']) - self.assertEqual(ip_count, 0) - self.assertRaises(db.NoMoreAddresses, - self.network.allocate_fixed_ip, - self.context, - 'foo') - - for i in range(num_available_ips): - self.network.deallocate_fixed_ip(self.context, addresses[i]) - release_ip(addresses[i]) - db.instance_destroy(context.get_admin_context(), instance_ids[i]) - ip_count = db.network_count_available_ips(context.get_admin_context(), - network['id']) - self.assertEqual(ip_count, num_available_ips) - - -def is_allocated_in_project(address, project_id): - """Returns true if address is in specified project""" - project_net = db.project_get_network(context.get_admin_context(), - project_id) - network = db.fixed_ip_get_network(context.get_admin_context(), address) - instance = db.fixed_ip_get_instance(context.get_admin_context(), address) - # instance exists until release - return instance is not None and network['id'] == project_net['id'] - - -def binpath(script): - """Returns the absolute path to a script in bin""" - return os.path.abspath(os.path.join(__file__, "../../../bin", script)) - - -def lease_ip(private_ip): - """Run add command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) - LOG.debug("ISSUE_IP: %s, %s ", out, err) - - -def release_ip(private_ip): - """Run del command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) - LOG.debug("RELEASE_IP: %s, %s ", out, err) diff --git a/nova/tests/test_vlan_network.py b/nova/tests/test_vlan_network.py new file mode 100644 index 000000000..be39313bb --- /dev/null +++ b/nova/tests/test_vlan_network.py @@ -0,0 +1,373 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Unit Tests for network code +""" +import IPy +import os + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.auth import manager + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +class VlanNetworkTestCase(test.TestCase): + """Test cases for network code""" + def setUp(self): + super(VlanNetworkTestCase, self).setUp() + # NOTE(vish): if you change these flags, make sure to change the + # flags in the corresponding section in nova-dhcpbridge + self.flags(connection_type='fake', + fake_call=True, + fake_network=True) + self.manager = manager.AuthManager() + self.user = self.manager.create_user('netuser', 'netuser', 'netuser') + self.projects = [] + self.network = utils.import_object(FLAGS.network_manager) + self.context = context.RequestContext(project=None, user=self.user) + for i in range(FLAGS.num_networks): + name = 'project%s' % i + project = self.manager.create_project(name, 'netuser', name) + self.projects.append(project) + # create the necessary network data for the project + user_context = context.RequestContext(project=self.projects[i], + user=self.user) + host = self.network.get_network_host(user_context.elevated()) + instance_ref = self._create_instance(0) + self.instance_id = instance_ref['id'] + instance_ref = self._create_instance(1) + self.instance2_id = instance_ref['id'] + + def tearDown(self): + # TODO(termie): this should really be instantiating clean datastores + # in between runs, one failure kills all the tests + db.instance_destroy(context.get_admin_context(), self.instance_id) + db.instance_destroy(context.get_admin_context(), self.instance2_id) + for project in self.projects: + self.manager.delete_project(project) + self.manager.delete_user(self.user) + super(VlanNetworkTestCase, self).tearDown() + + def run(self, result=None): + if(FLAGS.network_manager == 'nova.network.manager.VlanManager'): + super(VlanNetworkTestCase, self).run(result) + + def _create_instance(self, project_num, mac=None): + if not mac: + mac = utils.generate_mac() + project = self.projects[project_num] + self.context._project = project + self.context.project_id = project.id + return db.instance_create(self.context, + {'project_id': project.id, + 'mac_address': mac}) + + def _create_address(self, project_num, instance_id=None): + """Create an address in given project num""" + if instance_id is None: + instance_id = self.instance_id + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + return self.network.allocate_fixed_ip(self.context, instance_id) + + def _deallocate_address(self, project_num, address): + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + self.network.deallocate_fixed_ip(self.context, address) + + def test_private_ipv6(self): + """Make sure ipv6 is OK""" + if FLAGS.use_ipv6: + instance_ref = self._create_instance(0) + address = self._create_address(0, instance_ref['id']) + network_ref = db.project_get_network( + context.get_admin_context(), + self.context.project_id) + address_v6 = db.instance_get_fixed_address_v6( + context.get_admin_context(), + instance_ref['id']) + self.assertEqual(instance_ref['mac_address'], + utils.to_mac(address_v6)) + instance_ref2 = db.fixed_ip_get_instance_v6( + context.get_admin_context(), + address_v6) + self.assertEqual(instance_ref['id'], instance_ref2['id']) + self.assertEqual(address_v6, + utils.to_global_ipv6( + network_ref['cidr_v6'], + instance_ref['mac_address'])) + self._deallocate_address(0, address) + db.instance_destroy(context.get_admin_context(), + instance_ref['id']) + + def test_public_network_association(self): + """Makes sure that we can allocaate a public ip""" + # TODO(vish): better way of adding floating ips + self.context._project = self.projects[0] + self.context.project_id = self.projects[0].id + pubnet = IPy.IP(flags.FLAGS.floating_range) + address = str(pubnet[0]) + try: + db.floating_ip_get_by_address(context.get_admin_context(), address) + except exception.NotFound: + db.floating_ip_create(context.get_admin_context(), + {'address': address, + 'host': FLAGS.host}) + float_addr = self.network.allocate_floating_ip(self.context, + self.projects[0].id) + fix_addr = self._create_address(0) + lease_ip(fix_addr) + self.assertEqual(float_addr, str(pubnet[0])) + self.network.associate_floating_ip(self.context, float_addr, fix_addr) + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, float_addr) + self.network.disassociate_floating_ip(self.context, float_addr) + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, None) + self.network.deallocate_floating_ip(self.context, float_addr) + self.network.deallocate_fixed_ip(self.context, fix_addr) + release_ip(fix_addr) + db.floating_ip_destroy(context.get_admin_context(), float_addr) + + def test_allocate_deallocate_fixed_ip(self): + """Makes sure that we can allocate and deallocate a fixed ip""" + address = self._create_address(0) + self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + lease_ip(address) + self._deallocate_address(0, address) + + # Doesn't go away until it's dhcp released + self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + + release_ip(address) + self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + + def test_side_effects(self): + """Ensures allocating and releasing has no side effects""" + address = self._create_address(0) + address2 = self._create_address(1, self.instance2_id) + + self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) + self.assertFalse(is_allocated_in_project(address, self.projects[1].id)) + + # Addresses are allocated before they're issued + lease_ip(address) + lease_ip(address2) + + self._deallocate_address(0, address) + release_ip(address) + self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + + # First address release shouldn't affect the second + self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) + + self._deallocate_address(1, address2) + release_ip(address2) + self.assertFalse(is_allocated_in_project(address2, + self.projects[1].id)) + + def test_subnet_edge(self): + """Makes sure that private ips don't overlap""" + first = self._create_address(0) + lease_ip(first) + instance_ids = [] + for i in range(1, FLAGS.num_networks): + instance_ref = self._create_instance(i, mac=utils.generate_mac()) + instance_ids.append(instance_ref['id']) + address = self._create_address(i, instance_ref['id']) + instance_ref = self._create_instance(i, mac=utils.generate_mac()) + instance_ids.append(instance_ref['id']) + address2 = self._create_address(i, instance_ref['id']) + instance_ref = self._create_instance(i, mac=utils.generate_mac()) + instance_ids.append(instance_ref['id']) + address3 = self._create_address(i, instance_ref['id']) + lease_ip(address) + lease_ip(address2) + lease_ip(address3) + self.context._project = self.projects[i] + self.context.project_id = self.projects[i].id + self.assertFalse(is_allocated_in_project(address, + self.projects[0].id)) + self.assertFalse(is_allocated_in_project(address2, + self.projects[0].id)) + self.assertFalse(is_allocated_in_project(address3, + self.projects[0].id)) + self.network.deallocate_fixed_ip(self.context, address) + self.network.deallocate_fixed_ip(self.context, address2) + self.network.deallocate_fixed_ip(self.context, address3) + release_ip(address) + release_ip(address2) + release_ip(address3) + for instance_id in instance_ids: + db.instance_destroy(context.get_admin_context(), instance_id) + self.context._project = self.projects[0] + self.context.project_id = self.projects[0].id + self.network.deallocate_fixed_ip(self.context, first) + self._deallocate_address(0, first) + release_ip(first) + + def test_vpn_ip_and_port_looks_valid(self): + """Ensure the vpn ip and port are reasonable""" + self.assert_(self.projects[0].vpn_ip) + self.assert_(self.projects[0].vpn_port >= FLAGS.vpn_start) + self.assert_(self.projects[0].vpn_port <= FLAGS.vpn_start + + FLAGS.num_networks) + + def test_too_many_networks(self): + """Ensure error is raised if we run out of networks""" + projects = [] + networks_left = (FLAGS.num_networks - + db.network_count(context.get_admin_context())) + for i in range(networks_left): + project = self.manager.create_project('many%s' % i, self.user) + projects.append(project) + db.project_get_network(context.get_admin_context(), project.id) + project = self.manager.create_project('last', self.user) + projects.append(project) + self.assertRaises(db.NoMoreNetworks, + db.project_get_network, + context.get_admin_context(), + project.id) + for project in projects: + self.manager.delete_project(project) + + def test_ips_are_reused(self): + """Makes sure that ip addresses that are deallocated get reused""" + address = self._create_address(0) + lease_ip(address) + self.network.deallocate_fixed_ip(self.context, address) + release_ip(address) + + address2 = self._create_address(0) + self.assertEqual(address, address2) + lease_ip(address) + self.network.deallocate_fixed_ip(self.context, address2) + release_ip(address) + + def test_available_ips(self): + """Make sure the number of available ips for the network is correct + + The number of available IP addresses depends on the test + environment's setup. + + Network size is set in test fixture's setUp method. + + There are ips reserved at the bottom and top of the range. + services (network, gateway, CloudPipe, broadcast) + """ + network = db.project_get_network(context.get_admin_context(), + self.projects[0].id) + net_size = flags.FLAGS.network_size + admin_context = context.get_admin_context() + total_ips = (db.network_count_available_ips(admin_context, + network['id']) + + db.network_count_reserved_ips(admin_context, + network['id']) + + db.network_count_allocated_ips(admin_context, + network['id'])) + self.assertEqual(total_ips, net_size) + + def test_too_many_addresses(self): + """Test for a NoMoreAddresses exception when all fixed ips are used. + """ + admin_context = context.get_admin_context() + network = db.project_get_network(admin_context, self.projects[0].id) + num_available_ips = db.network_count_available_ips(admin_context, + network['id']) + addresses = [] + instance_ids = [] + for i in range(num_available_ips): + instance_ref = self._create_instance(0) + instance_ids.append(instance_ref['id']) + address = self._create_address(0, instance_ref['id']) + addresses.append(address) + lease_ip(address) + + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, 0) + self.assertRaises(db.NoMoreAddresses, + self.network.allocate_fixed_ip, + self.context, + 'foo') + + for i in range(num_available_ips): + self.network.deallocate_fixed_ip(self.context, addresses[i]) + release_ip(addresses[i]) + db.instance_destroy(context.get_admin_context(), instance_ids[i]) + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, num_available_ips) + + +def is_allocated_in_project(address, project_id): + """Returns true if address is in specified project""" + project_net = db.project_get_network(context.get_admin_context(), + project_id) + network = db.fixed_ip_get_network(context.get_admin_context(), address) + instance = db.fixed_ip_get_instance(context.get_admin_context(), address) + # instance exists until release + return instance is not None and network['id'] == project_net['id'] + + +def binpath(script): + """Returns the absolute path to a script in bin""" + return os.path.abspath(os.path.join(__file__, "../../../bin", script)) + + +def lease_ip(private_ip): + """Run add command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'), + instance_ref['mac_address'], + private_ip) + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(cmd, addl_env=env) + LOG.debug("ISSUE_IP: %s, %s ", out, err) + + +def release_ip(private_ip): + """Run del command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'), + instance_ref['mac_address'], + private_ip) + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(cmd, addl_env=env) + LOG.debug("RELEASE_IP: %s, %s ", out, err) -- cgit From 10668b87f46a1fb5d039f6e7d7a7a55b89d7602a Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Fri, 4 Mar 2011 17:04:41 -0500 Subject: respond well if personality attribute is incomplete --- nova/tests/api/openstack/test_servers.py | 48 ++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index c125e6192..8fb5a9aec 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -272,19 +272,24 @@ class ServersTest(test.TestCase): server['personality'] = personalities return {'server': server} - def _create_personality_request_json(self, personality_files): - body_dict = self._create_personality_request_dict(personality_files) + def _get_create_request_json(self, body_dict): req = webob.Request.blank('/v1.0/servers') req.content_type = 'application/json' req.method = 'POST' req.body = json.dumps(body_dict) return req - def _create_instance_with_personality_json(self, personality): + def _run_create_instance_with_mock_compute_api(self, request): compute_api = self._setup_mock_compute_api_for_personality() - request = self._create_personality_request_json(personality) response = request.get_response(fakes.wsgi_app()) - return (request, response, compute_api.personality_files) + return compute_api, response + + def _create_instance_with_personality_json(self, personality): + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + return request, response, compute_api.personality_files def test_create_instance_with_no_personality(self): request, response, personality_files = \ @@ -302,6 +307,39 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, [(path, contents)]) + def test_create_instance_with_personality_no_path(self): + personality = [('/remove/this/path', + base64.b64encode('my\n\file\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + del body_dict['server']['personality'][0]['path'] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def test_create_instance_with_personality_no_contents(self): + personality = [('/test/path', + base64.b64encode('remove\nthese\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + del body_dict['server']['personality'][0]['contents'] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def test_create_instance_with_personality_not_a_list(self): + personality = [('/test/path', base64.b64encode('test\ncontents\n'))] + body_dict = self._create_personality_request_dict(personality) + body_dict['server']['personality'] = \ + body_dict['server']['personality'][0] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' -- cgit From a5bee00af4d6ec3eed6ed0abd866948f4510f041 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 7 Mar 2011 01:25:01 +0000 Subject: make compute get the new images properly, fix a bunch of tests, and provide conversion commands --- nova/tests/test_cloud.py | 16 ++++++++-------- nova/tests/test_compute.py | 12 ++++++------ nova/tests/test_console.py | 2 +- nova/tests/test_quota.py | 32 +++++++++++++++++++------------- nova/tests/test_scheduler.py | 4 +--- nova/tests/test_volume.py | 2 +- 6 files changed, 36 insertions(+), 32 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index 7d7b91658..8d2cd9573 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -78,10 +78,11 @@ class CloudTestCase(test.TestCase): project=self.project) host = self.network.get_network_host(self.context.elevated()) - def fake_image_show(meh, context, id): - return dict(kernelId=1, ramdiskId=1) + def fake_show(meh, context, id): + return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} - self.stubs.Set(local.LocalImageService, 'show', fake_image_show) + self.stubs.Set(local.LocalImageService, 'show', fake_show) + self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show) def tearDown(self): network_ref = db.project_get_network(self.context, @@ -195,8 +196,10 @@ class CloudTestCase(test.TestCase): def test_describe_instances(self): """Makes sure describe_instances works and filters results.""" inst1 = db.instance_create(self.context, {'reservation_id': 'a', + 'image_id': 1, 'host': 'host1'}) inst2 = db.instance_create(self.context, {'reservation_id': 'a', + 'image_id': 1, 'host': 'host2'}) comp1 = db.service_create(self.context, {'host': 'host1', 'availability_zone': 'zone1', @@ -222,11 +225,9 @@ class CloudTestCase(test.TestCase): db.service_destroy(self.context, comp2['id']) def test_console_output(self): - image_id = FLAGS.default_image - print image_id instance_type = FLAGS.default_instance_type max_count = 1 - kwargs = {'image_id': image_id, + kwargs = {'image_id': 'ami-1', 'instance_type': instance_type, 'max_count': max_count} rv = self.cloud.run_instances(self.context, **kwargs) @@ -242,8 +243,7 @@ class CloudTestCase(test.TestCase): greenthread.sleep(0.3) def test_ajax_console(self): - image_id = FLAGS.default_image - kwargs = {'image_id': image_id} + kwargs = {'image_id': 'ami-1'} rv = self.cloud.run_instances(self.context, **kwargs) instance_id = rv['instancesSet'][0]['instanceId'] greenthread.sleep(0.3) diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 1f49baaf6..8c18fafc6 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -47,16 +47,16 @@ class ComputeTestCase(test.TestCase): network_manager='nova.network.manager.FlatManager') self.compute = utils.import_object(FLAGS.compute_manager) self.compute_api = compute.API() - - def fake_image_show(meh, context, id): - return dict(kernelId=1, ramdiskId=1) - - self.stubs.Set(local.LocalImageService, 'show', fake_image_show) self.manager = manager.AuthManager() self.user = self.manager.create_user('fake', 'fake', 'fake') self.project = self.manager.create_project('fake', 'fake', 'fake') self.context = context.RequestContext('fake', 'fake', False) + def fake_show(meh, context, id): + return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}} + + self.stubs.Set(local.LocalImageService, 'show', fake_show) + def tearDown(self): self.manager.delete_user(self.user) self.manager.delete_project(self.project) @@ -65,7 +65,7 @@ class ComputeTestCase(test.TestCase): def _create_instance(self): """Create a test instance""" inst = {} - inst['image_id'] = 'ami-test' + inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['launch_time'] = '10' inst['user_id'] = self.user.id diff --git a/nova/tests/test_console.py b/nova/tests/test_console.py index 49ff24413..d47c70d88 100644 --- a/nova/tests/test_console.py +++ b/nova/tests/test_console.py @@ -57,7 +57,7 @@ class ConsoleTestCase(test.TestCase): inst = {} #inst['host'] = self.host #inst['name'] = 'instance-1234' - inst['image_id'] = 'ami-test' + inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['launch_time'] = '10' inst['user_id'] = self.user.id diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index ca8abdb36..45b544753 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -20,11 +20,12 @@ from nova import compute from nova import context from nova import db from nova import flags +from nova import network from nova import quota from nova import test from nova import utils +from nova import volume from nova.auth import manager -from nova.api.ec2 import cloud from nova.compute import instance_types @@ -41,7 +42,6 @@ class QuotaTestCase(test.TestCase): quota_gigabytes=20, quota_floating_ips=1) - self.cloud = cloud.CloudController() self.manager = manager.AuthManager() self.user = self.manager.create_user('admin', 'admin', 'admin', True) self.project = self.manager.create_project('admin', 'admin', 'admin') @@ -57,7 +57,7 @@ class QuotaTestCase(test.TestCase): def _create_instance(self, cores=2): """Create a test instance""" inst = {} - inst['image_id'] = 'ami-1' + inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['user_id'] = self.user.id inst['project_id'] = self.project.id @@ -118,12 +118,12 @@ class QuotaTestCase(test.TestCase): for i in range(FLAGS.quota_instances): instance_id = self._create_instance() instance_ids.append(instance_id) - self.assertRaises(quota.QuotaError, self.cloud.run_instances, + self.assertRaises(quota.QuotaError, compute.API().create, self.context, min_count=1, max_count=1, instance_type='m1.small', - image_id='ami-1') + image_id=1) for instance_id in instance_ids: db.instance_destroy(self.context, instance_id) @@ -131,12 +131,12 @@ class QuotaTestCase(test.TestCase): instance_ids = [] instance_id = self._create_instance(cores=4) instance_ids.append(instance_id) - self.assertRaises(quota.QuotaError, self.cloud.run_instances, + self.assertRaises(quota.QuotaError, compute.API().create, self.context, min_count=1, max_count=1, instance_type='m1.small', - image_id='ami-1') + image_id=1) for instance_id in instance_ids: db.instance_destroy(self.context, instance_id) @@ -145,9 +145,12 @@ class QuotaTestCase(test.TestCase): for i in range(FLAGS.quota_volumes): volume_id = self._create_volume() volume_ids.append(volume_id) - self.assertRaises(quota.QuotaError, self.cloud.create_volume, - self.context, - size=10) + self.assertRaises(quota.QuotaError, + volume.API().create, + self.context, + size=10, + name='', + description='') for volume_id in volume_ids: db.volume_destroy(self.context, volume_id) @@ -156,9 +159,11 @@ class QuotaTestCase(test.TestCase): volume_id = self._create_volume(size=20) volume_ids.append(volume_id) self.assertRaises(quota.QuotaError, - self.cloud.create_volume, + volume.API().create, self.context, - size=10) + size=10, + name='', + description='') for volume_id in volume_ids: db.volume_destroy(self.context, volume_id) @@ -172,7 +177,8 @@ class QuotaTestCase(test.TestCase): # make an rpc.call, the test just finishes with OK. It # appears to be something in the magic inline callbacks # that is breaking. - self.assertRaises(quota.QuotaError, self.cloud.allocate_address, + self.assertRaises(quota.QuotaError, + network.API().allocate_floating_ip, self.context) db.floating_ip_destroy(context.get_admin_context(), address) diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index b6888c4d2..bb279ac4b 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -155,7 +155,7 @@ class SimpleDriverTestCase(test.TestCase): def _create_instance(self, **kwargs): """Create a test instance""" inst = {} - inst['image_id'] = 'ami-test' + inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['user_id'] = self.user.id inst['project_id'] = self.project.id @@ -169,8 +169,6 @@ class SimpleDriverTestCase(test.TestCase): def _create_volume(self): """Create a test volume""" vol = {} - vol['image_id'] = 'ami-test' - vol['reservation_id'] = 'r-fakeres' vol['size'] = 1 vol['availability_zone'] = 'test' return db.volume_create(self.context, vol)['id'] diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index b40ca004b..f698c85b5 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -99,7 +99,7 @@ class VolumeTestCase(test.TestCase): def test_run_attach_detach_volume(self): """Make sure volume can be attached and detached from instance.""" inst = {} - inst['image_id'] = 'ami-test' + inst['image_id'] = 1 inst['reservation_id'] = 'r-fakeres' inst['launch_time'] = '10' inst['user_id'] = 'fake' -- cgit From b3d3366b8fd4eaf81bb9e03ad808c1a139e5b5b0 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 7 Mar 2011 12:07:23 -0500 Subject: Generate 'adminPass' and call set_password when creating servers. --- nova/tests/api/openstack/test_servers.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 78beb7df9..16b48a13b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -186,7 +186,7 @@ class ServersTest(test.TestCase): def test_create_instance(self): def instance_create(context, inst): - return {'id': '1', 'display_name': ''} + return {'id': '1', 'display_name': 'server_test'} def server_update(context, id, params): return instance_create(context, id) @@ -230,6 +230,12 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) + server = json.loads(res.body)['server'] + self.assertEqual('serv', server['adminPass'][:4]) + self.assertEqual(16, len(server['adminPass'])) + self.assertEqual('server_test', server['name']) + self.assertEqual('1', server['id']) + self.assertEqual(res.status_int, 200) def test_update_no_body(self): -- cgit From a775c4eee279e11268a6cc447aee24c452e4665a Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Mon, 7 Mar 2011 17:17:41 +0000 Subject: Merge prop changes and test fixes --- nova/tests/xenapi/stubs.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index caefcff34..11e89c9b4 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -227,18 +227,8 @@ class FakeSessionForMigrationTests(fake.SessionBase): def stub_out_migration_methods(stubs): - class FakeSnapshot(object): - def __getattr__(self, key): - return str(key) - - def __enter__(self): - return self - - def __exit__(self, type, value, traceback): - pass - def fake_get_snapshot(self, instance): - return FakeSnapshot() + return 'foo', 'bar' @classmethod def fake_get_vdi(cls, session, vm_ref): @@ -251,11 +241,21 @@ def stub_out_migration_methods(stubs): pass @classmethod - def fake_scan_sr(cls, session): + def fake_sr(cls, session, *args): + pass + + @classmethod + def fake_get_sr_path(cls, *args): + return "fake" + + def fake_destroy(*args, **kwargs): pass - stubs.Set(vm_utils.VMHelper, 'scan_sr', fake_scan_sr) + stubs.Set(vmops.VMOps, '_destroy', fake_destroy) + stubs.Set(vm_utils.VMHelper, 'scan_default_sr', fake_sr) + stubs.Set(vm_utils.VMHelper, 'scan_sr', fake_sr) stubs.Set(vmops.VMOps, '_get_snapshot', fake_get_snapshot) stubs.Set(vm_utils.VMHelper, 'get_vdi_for_vm_safely', fake_get_vdi) stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x, y, z: None) + stubs.Set(vm_utils.VMHelper, 'get_sr_path', fake_get_sr_path) stubs.Set(vmops.VMOps, '_shutdown', fake_shutdown) -- cgit From bcb18ee3d0d095b616c0909c92a151a599d4e17f Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Mon, 7 Mar 2011 15:05:07 -0500 Subject: Invalid values for offset and limit params in http requests now return a 400 response with a useful message in the body. Also added and updated tests. --- nova/tests/api/openstack/test_common.py | 20 ++++---------------- nova/tests/api/openstack/test_servers.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 16 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 92023362c..8f57c5b67 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -79,20 +79,14 @@ class LimiterTest(test.TestCase): Test offset key works with a blank offset. """ req = Request.blank('/?offset=') - self.assertEqual(limited(self.tiny, req), self.tiny) - self.assertEqual(limited(self.small, req), self.small) - self.assertEqual(limited(self.medium, req), self.medium) - self.assertEqual(limited(self.large, req), self.large[:1000]) + self.assertRaises(webob.exc.HTTPBadRequest, limited, self.tiny, req) def test_limiter_offset_bad(self): """ Test offset key works with a BAD offset. """ req = Request.blank(u'/?offset=\u0020aa') - self.assertEqual(limited(self.tiny, req), self.tiny) - self.assertEqual(limited(self.small, req), self.small) - self.assertEqual(limited(self.medium, req), self.medium) - self.assertEqual(limited(self.large, req), self.large[:1000]) + self.assertRaises(webob.exc.HTTPBadRequest, limited, self.tiny, req) def test_limiter_nothing(self): """ @@ -166,18 +160,12 @@ class LimiterTest(test.TestCase): """ Test a negative limit. """ - def _limit_large(): - limited(self.large, req, max_limit=2000) - req = Request.blank('/?limit=-3000') - self.assertRaises(webob.exc.HTTPBadRequest, _limit_large) + self.assertRaises(webob.exc.HTTPBadRequest, limited, self.tiny, req) def test_limiter_negative_offset(self): """ Test a negative offset. """ - def _limit_large(): - limited(self.large, req, max_limit=2000) - req = Request.blank('/?offset=-30') - self.assertRaises(webob.exc.HTTPBadRequest, _limit_large) + self.assertRaises(webob.exc.HTTPBadRequest, limited, self.tiny, req) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 78beb7df9..10fb2bafb 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -184,6 +184,34 @@ class ServersTest(test.TestCase): self.assertEqual(s.get('imageId', None), None) i += 1 + def test_get_servers_with_limit(self): + req = webob.Request.blank('/v1.0/servers?limit=3') + res = req.get_response(fakes.wsgi_app()) + servers = json.loads(res.body)['servers'] + self.assertEqual([s['id'] for s in servers], [0, 1, 2]) + + req = webob.Request.blank('/v1.0/servers?limit=aaa') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + self.assertTrue('limit' in res.body) + + def test_get_servers_with_offset(self): + req = webob.Request.blank('/v1.0/servers?offset=2') + res = req.get_response(fakes.wsgi_app()) + servers = json.loads(res.body)['servers'] + self.assertEqual([s['id'] for s in servers], [2, 3, 4]) + + req = webob.Request.blank('/v1.0/servers?offset=aaa') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + self.assertTrue('offset' in res.body) + + def test_get_servers_with_limit_and_offset(self): + req = webob.Request.blank('/v1.0/servers?limit=2&offset=1') + res = req.get_response(fakes.wsgi_app()) + servers = json.loads(res.body)['servers'] + self.assertEqual([s['id'] for s in servers], [1, 2]) + def test_create_instance(self): def instance_create(context, inst): return {'id': '1', 'display_name': ''} -- cgit From 5c7ee13b058fb954fd9bbc4a3550716b8faa0b97 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Mon, 7 Mar 2011 22:50:35 +0000 Subject: And unit tests --- nova/tests/test_xenapi.py | 5 +++++ nova/tests/xenapi/stubs.py | 4 ++++ 2 files changed, 9 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 7f437c2b8..6e458558d 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -383,6 +383,11 @@ class XenAPIMigrateInstance(test.TestCase): conn = xenapi_conn.get_connection(False) conn.attach_disk(instance, {'base_copy': 'hurr', 'cow': 'durr'}) + def test_finish_resize(self): + instance = db.instance_create(self.values) + stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) + conn = xenapi_conn.get_connection(False) + conn.finish_resize(instance, dict(base_copy='hurr', cow='durr')) class XenAPIDetermineDiskImageTestCase(test.TestCase): """ diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 11e89c9b4..28037c2ba 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -251,6 +251,9 @@ def stub_out_migration_methods(stubs): def fake_destroy(*args, **kwargs): pass + def fake_spawn_with_disk(*args, **kwargs): + pass + stubs.Set(vmops.VMOps, '_destroy', fake_destroy) stubs.Set(vm_utils.VMHelper, 'scan_default_sr', fake_sr) stubs.Set(vm_utils.VMHelper, 'scan_sr', fake_sr) @@ -259,3 +262,4 @@ def stub_out_migration_methods(stubs): stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x, y, z: None) stubs.Set(vm_utils.VMHelper, 'get_sr_path', fake_get_sr_path) stubs.Set(vmops.VMOps, '_shutdown', fake_shutdown) + stubs.Set(vmops.VMOps, 'spawn_with_disk', fake_spawn_with_disk) -- cgit From 2f0845b7b80081d18ee268b94fe38326f3c5401e Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Mon, 7 Mar 2011 23:07:05 +0000 Subject: A few more changes --- nova/tests/test_xenapi.py | 6 ------ 1 file changed, 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 6e458558d..f5b154a51 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -377,12 +377,6 @@ class XenAPIMigrateInstance(test.TestCase): conn = xenapi_conn.get_connection(False) conn.migrate_disk_and_power_off(instance, '127.0.0.1') - def test_attach_disk(self): - instance = db.instance_create(self.values) - stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) - conn = xenapi_conn.get_connection(False) - conn.attach_disk(instance, {'base_copy': 'hurr', 'cow': 'durr'}) - def test_finish_resize(self): instance = db.instance_create(self.values) stubs.stubout_session(self.stubs, stubs.FakeSessionForMigrationTests) -- cgit From e39995def6a2a11cdd430b0e6f603b493be5542b Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Mon, 7 Mar 2011 23:51:20 +0000 Subject: Some more refactoring and a tighter unit test --- nova/tests/test_xenapi.py | 14 ++++++++++---- nova/tests/xenapi/stubs.py | 15 +++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index f5b154a51..919a38c06 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -360,16 +360,22 @@ class XenAPIMigrateInstance(test.TestCase): db_fakes.stub_out_db_instance_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() + self.manager = manager.AuthManager() + self.user = self.manager.create_user('fake', 'fake', 'fake', + admin=True) + self.project = self.manager.create_project('fake', 'fake', 'fake') self.values = {'name': 1, 'id': 1, - 'project_id': 'fake', - 'user_id': 'fake', + 'project_id': self.project.id, + 'user_id': self.user.id, 'image_id': 1, - 'kernel_id': 2, - 'ramdisk_id': 3, + 'kernel_id': None, + 'ramdisk_id': None, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', } stubs.stub_out_migration_methods(self.stubs) + glance_stubs.stubout_glance_client(self.stubs, + glance_stubs.FakeGlance) def test_migrate_disk_and_power_off(self): instance = db.instance_create(self.values) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 28037c2ba..d8e358611 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -225,6 +225,17 @@ class FakeSessionForMigrationTests(fake.SessionBase): def __init__(self, uri): super(FakeSessionForMigrationTests, self).__init__(uri) + def VDI_get_by_uuid(*args): + return 'hurr' + + def VM_start(self, _1, ref, _2, _3): + vm = fake.get_record('VM', ref) + if vm['power_state'] != 'Halted': + raise fake.Failure(['VM_BAD_POWER_STATE', ref, 'Halted', + vm['power_state']]) + vm['power_state'] = 'Running' + vm['is_a_template'] = False + vm['is_control_domain'] = False def stub_out_migration_methods(stubs): def fake_get_snapshot(self, instance): @@ -251,7 +262,7 @@ def stub_out_migration_methods(stubs): def fake_destroy(*args, **kwargs): pass - def fake_spawn_with_disk(*args, **kwargs): + def fake_reset_network(*args, **kwargs): pass stubs.Set(vmops.VMOps, '_destroy', fake_destroy) @@ -261,5 +272,5 @@ def stub_out_migration_methods(stubs): stubs.Set(vm_utils.VMHelper, 'get_vdi_for_vm_safely', fake_get_vdi) stubs.Set(xenapi_conn.XenAPISession, 'wait_for_task', lambda x, y, z: None) stubs.Set(vm_utils.VMHelper, 'get_sr_path', fake_get_sr_path) + stubs.Set(vmops.VMOps, 'reset_network', fake_reset_network) stubs.Set(vmops.VMOps, '_shutdown', fake_shutdown) - stubs.Set(vmops.VMOps, 'spawn_with_disk', fake_spawn_with_disk) -- cgit From cac5881eaa35f94e004c18dd34ca78014f067976 Mon Sep 17 00:00:00 2001 From: Eric Windisch Date: Tue, 8 Mar 2011 01:01:41 -0500 Subject: execvp --- nova/tests/test_network.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index ce1c77210..6d2d8b771 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -343,13 +343,13 @@ def lease_ip(private_ip): private_ip) instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), private_ip) - cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) + cmd = (binpath('nova-dhcpbridge'), 'add' + instance_ref['mac_address'], + private_ip, 'fake') env = {'DNSMASQ_INTERFACE': network_ref['bridge'], 'TESTING': '1', 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) + (out, err) = utils.execute(*cmd, addl_env=env) LOG.debug("ISSUE_IP: %s, %s ", out, err) @@ -359,11 +359,11 @@ def release_ip(private_ip): private_ip) instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), private_ip) - cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) + cmd = (binpath('nova-dhcpbridge'), 'del', + instance_ref['mac_address'], + private_ip, 'fake') env = {'DNSMASQ_INTERFACE': network_ref['bridge'], 'TESTING': '1', 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) + (out, err) = utils.execute(*cmd, addl_env=env) LOG.debug("RELEASE_IP: %s, %s ", out, err) -- cgit From f53357d32304cd721185704fa0d48454b5627199 Mon Sep 17 00:00:00 2001 From: sateesh Date: Tue, 8 Mar 2011 16:33:49 +0530 Subject: Removed stale references to XenAPI. --- nova/tests/test_vmwareapi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index 5e8896b5a..65cdd5fcf 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -86,7 +86,7 @@ class VMWareAPIVMTestCase(test.TestCase): # Get Nova record for VM vm_info = self.conn.get_info(1) - # Get XenAPI record for VM + # Get record for VMs vms = vmwareapi_fake._get_objects("VirtualMachine") vm = vms[0] @@ -102,7 +102,7 @@ class VMWareAPIVMTestCase(test.TestCase): # Check that the VM is running according to Nova self.assertEquals(vm_info['state'], power_state.RUNNING) - # Check that the VM is running according to XenAPI. + # Check that the VM is running according to vSphere API. self.assertEquals(vm.get("runtime.powerState"), 'poweredOn') def _check_vm_info(self, info, pwr_state=power_state.RUNNING): -- cgit From b8a0fdca4df454a4d60df40d06ebd82bcc2ba3da Mon Sep 17 00:00:00 2001 From: Cory Wright Date: Tue, 8 Mar 2011 14:35:53 +0000 Subject: * pep8 cleanups in migrations * a few bugfixes --- nova/tests/test_xenapi.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 27f0e5dd7..25070e108 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -251,7 +251,7 @@ class XenAPIVMTestCase(test.TestCase): self.vm_info = vm_info self.vm = vm - def check_vm_record(self): + def check_vm_record(self, conn): # Check that m1.large above turned into the right thing. instance_type = db.instance_type_get_by_name(conn, 'm1.large') mem_kib = long(instance_type['memory_mb']) << 10 @@ -321,7 +321,7 @@ class XenAPIVMTestCase(test.TestCase): instance = db.instance_create(values) conn.spawn(instance) self.create_vm_record(conn, os_type) - self.check_vm_record() + self.check_vm_record(conn) def test_spawn_not_enough_memory(self): FLAGS.xenapi_image_service = 'glance' -- cgit From cbc2956a4e863c1bc952c7cef6045c39d293818d Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Tue, 8 Mar 2011 17:18:13 +0000 Subject: Remove addition of account to service url. --- nova/tests/api/openstack/test_accounts.py | 8 +++--- nova/tests/api/openstack/test_adminapi.py | 4 +-- nova/tests/api/openstack/test_auth.py | 2 +- nova/tests/api/openstack/test_flavors.py | 4 +-- nova/tests/api/openstack/test_images.py | 4 +-- nova/tests/api/openstack/test_servers.py | 48 +++++++++++++++---------------- nova/tests/api/openstack/test_users.py | 10 +++---- nova/tests/api/openstack/test_zones.py | 10 +++---- 8 files changed, 45 insertions(+), 45 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index b2e89824a..746f02f57 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -70,7 +70,7 @@ class AccountsTest(test.TestCase): super(AccountsTest, self).tearDown() def test_get_account(self): - req = webob.Request.blank('/v1.0/test1') + req = webob.Request.blank('/v1.0/accounts/test1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -80,7 +80,7 @@ class AccountsTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_account_delete(self): - req = webob.Request.blank('/v1.0/test1') + req = webob.Request.blank('/v1.0/accounts/test1') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertTrue('test1' not in fakes.FakeAuthManager.projects) @@ -89,7 +89,7 @@ class AccountsTest(test.TestCase): def test_account_create(self): body = dict(account=dict(description='test account', manager='guy1')) - req = webob.Request.blank('/v1.0/newacct') + req = webob.Request.blank('/v1.0/accounts/newacct') req.method = 'PUT' req.body = json.dumps(body) @@ -108,7 +108,7 @@ class AccountsTest(test.TestCase): def test_account_update(self): body = dict(account=dict(description='test account', manager='guy2')) - req = webob.Request.blank('/v1.0/test1') + req = webob.Request.blank('/v1.0/accounts/test1') req.method = 'PUT' req.body = json.dumps(body) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 7cb9e8450..4568cb9f5 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -50,7 +50,7 @@ class AdminAPITest(test.TestCase): def test_admin_enabled(self): FLAGS.allow_admin_api = True # We should still be able to access public operations. - req = webob.Request.blank('/v1.0/testacct/flavors') + req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) # TODO: Confirm admin operations are available. @@ -58,7 +58,7 @@ class AdminAPITest(test.TestCase): def test_admin_disabled(self): FLAGS.allow_admin_api = False # We should still be able to access public operations. - req = webob.Request.blank('/v1.0/testacct/flavors') + req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) # TODO: Confirm admin operations are unavailable. self.assertEqual(res.status_int, 200) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 8268a6fb9..49f90879d 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -78,7 +78,7 @@ class Test(test.TestCase): self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) self.assertEqual(result.headers['X-Server-Management-Url'], - "http://foo/v1.0/test/") + "http://foo/v1.0/") self.assertEqual(result.headers['X-CDN-Management-Url'], "") self.assertEqual(result.headers['X-Storage-Url'], "") diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index ba0785b0e..8280a505f 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -42,11 +42,11 @@ class FlavorsTest(test.TestCase): super(FlavorsTest, self).tearDown() def test_get_flavor_list(self): - req = webob.Request.blank('/v1.0/testacct/flavors') + req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) def test_get_flavor_by_id(self): - req = webob.Request.blank('/v1.0/testacct/flavors/1') + req = webob.Request.blank('/v1.0/flavors/1') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 819ca001e..dbe507f7d 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -216,7 +216,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): super(ImageControllerWithGlanceServiceTest, self).tearDown() def test_get_image_index(self): - req = webob.Request.blank('/v1.0/testacct/images') + req = webob.Request.blank('/v1.0/images') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -228,7 +228,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): "image %s not in fixture index!" % str(image)) def test_get_image_details(self): - req = webob.Request.blank('/v1.0/testacct/images/detail') + req = webob.Request.blank('/v1.0/images/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index d592e06b0..705a2f800 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -150,7 +150,7 @@ class ServersTest(test.TestCase): super(ServersTest, self).tearDown() def test_get_server_by_id(self): - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -161,7 +161,7 @@ class ServersTest(test.TestCase): public = ["1.2.3.4"] new_return_server = return_server_with_addresses(private, public) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -173,7 +173,7 @@ class ServersTest(test.TestCase): self.assertEqual(addresses["private"][0], private) def test_get_server_list(self): - req = webob.Request.blank('/v1.0/testacct/servers') + req = webob.Request.blank('/v1.0/servers') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -224,7 +224,7 @@ class ServersTest(test.TestCase): name='server_test', imageId=2, flavorId=2, metadata={'hello': 'world', 'open': 'stack'}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers') + req = webob.Request.blank('/v1.0/servers') req.method = 'POST' req.body = json.dumps(body) @@ -233,7 +233,7 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_update_no_body(self): - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 422) @@ -251,7 +251,7 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_update', server_update) - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' req.body = self.body req.get_response(fakes.wsgi_app()) @@ -267,30 +267,30 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_update', server_update) - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' req.body = self.body req.get_response(fakes.wsgi_app()) def test_create_backup_schedules(self): - req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedules') req.method = 'POST' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_delete_backup_schedules(self): - req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedules') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_get_server_backup_schedules(self): - req = webob.Request.blank('/v1.0/testacct/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedules') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') def test_get_all_server_details(self): - req = webob.Request.blank('/v1.0/testacct/servers/detail') + req = webob.Request.blank('/v1.0/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -321,7 +321,7 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.db.api, 'instance_get_all_by_user', return_servers_with_host) - req = webob.Request.blank('/v1.0/testacct/servers/detail') + req = webob.Request.blank('/v1.0/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -341,7 +341,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/pause') + req = webob.Request.blank('/v1.0/servers/1/pause') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -353,7 +353,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/unpause') + req = webob.Request.blank('/v1.0/servers/1/unpause') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -365,7 +365,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/suspend') + req = webob.Request.blank('/v1.0/servers/1/suspend') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -377,7 +377,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/resume') + req = webob.Request.blank('/v1.0/servers/1/resume') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -389,7 +389,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/reset_network') + req = webob.Request.blank('/v1.0/servers/1/reset_network') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -402,7 +402,7 @@ class ServersTest(test.TestCase): name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) req = webob.Request.blank( - '/v1.0/testacct/servers/1/inject_network_info') + '/v1.0/servers/1/inject_network_info') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -410,13 +410,13 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 202) def test_server_diagnostics(self): - req = webob.Request.blank("/v1.0/testacct/servers/1/diagnostics") + req = webob.Request.blank("/v1.0/servers/1/diagnostics") req.method = "GET" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) def test_server_actions(self): - req = webob.Request.blank("/v1.0/testacct/servers/1/actions") + req = webob.Request.blank("/v1.0/servers/1/actions") req.method = "GET" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) @@ -425,7 +425,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/action') + req = webob.Request.blank('/v1.0/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -435,7 +435,7 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/action') + req = webob.Request.blank('/v1.0/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) @@ -445,14 +445,14 @@ class ServersTest(test.TestCase): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, personality={})) - req = webob.Request.blank('/v1.0/testacct/servers/1/action') + req = webob.Request.blank('/v1.0/servers/1/action') req.method = 'POST' req.content_type = 'application/json' req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) def test_delete_server_instance(self): - req = webob.Request.blank('/v1.0/testacct/servers/1') + req = webob.Request.blank('/v1.0/servers/1') req.method = 'DELETE' self.server_delete_called = False diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index bd32254cd..14c7897f0 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -72,7 +72,7 @@ class UsersTest(test.TestCase): super(UsersTest, self).tearDown() def test_get_user_list(self): - req = webob.Request.blank('/v1.0/testacct/users') + req = webob.Request.blank('/v1.0/users') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -80,7 +80,7 @@ class UsersTest(test.TestCase): self.assertEqual(len(res_dict['users']), 2) def test_get_user_by_id(self): - req = webob.Request.blank('/v1.0/testacct/users/guy2') + req = webob.Request.blank('/v1.0/users/guy2') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -91,7 +91,7 @@ class UsersTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_user_delete(self): - req = webob.Request.blank('/v1.0/testacct/users/guy1') + req = webob.Request.blank('/v1.0/users/guy1') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertTrue('guy1' not in [u.id for u in @@ -103,7 +103,7 @@ class UsersTest(test.TestCase): access='acc3', secret='invasionIsInNormandy', admin=True)) - req = webob.Request.blank('/v1.0/testacct/users') + req = webob.Request.blank('/v1.0/users') req.method = 'POST' req.body = json.dumps(body) @@ -124,7 +124,7 @@ class UsersTest(test.TestCase): body = dict(user=dict(name='guy2', access='acc2', secret='invasionIsInNormandy')) - req = webob.Request.blank('/v1.0/testacct/users/guy2') + req = webob.Request.blank('/v1.0/users/guy2') req.method = 'PUT' req.body = json.dumps(body) diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 51f13af48..6d869dc15 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -85,7 +85,7 @@ class ZonesTest(test.TestCase): super(ZonesTest, self).tearDown() def test_get_zone_list(self): - req = webob.Request.blank('/v1.0/testacct/zones') + req = webob.Request.blank('/v1.0/zones') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -93,7 +93,7 @@ class ZonesTest(test.TestCase): self.assertEqual(len(res_dict['zones']), 2) def test_get_zone_by_id(self): - req = webob.Request.blank('/v1.0/testacct/zones/1') + req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -103,7 +103,7 @@ class ZonesTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_zone_delete(self): - req = webob.Request.blank('/v1.0/testacct/zones/1') + req = webob.Request.blank('/v1.0/zones/1') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -111,7 +111,7 @@ class ZonesTest(test.TestCase): def test_zone_create(self): body = dict(zone=dict(api_url='http://blah.zoo', username='fred', password='fubar')) - req = webob.Request.blank('/v1.0/testacct/zones') + req = webob.Request.blank('/v1.0/zones') req.method = 'POST' req.body = json.dumps(body) @@ -125,7 +125,7 @@ class ZonesTest(test.TestCase): def test_zone_update(self): body = dict(zone=dict(username='zeb', password='sneaky')) - req = webob.Request.blank('/v1.0/testacct/zones/1') + req = webob.Request.blank('/v1.0/zones/1') req.method = 'PUT' req.body = json.dumps(body) -- cgit From a74bf3381ada34f35c43d6f307fbae9abecfb255 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Tue, 8 Mar 2011 10:30:48 -0800 Subject: abstracted network code in the base class for flat and vlan --- nova/tests/network/__init__.py | 47 +++++++++ nova/tests/network/base.py | 154 ++++++++++++++++++++++++++++++ nova/tests/test_flat_network.py | 147 ++++------------------------ nova/tests/test_vlan_network.py | 205 ++++++++-------------------------------- 4 files changed, 254 insertions(+), 299 deletions(-) create mode 100644 nova/tests/network/__init__.py create mode 100644 nova/tests/network/base.py (limited to 'nova/tests') diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py new file mode 100644 index 000000000..e51065983 --- /dev/null +++ b/nova/tests/network/__init__.py @@ -0,0 +1,47 @@ +import os + +from nova import context +from nova import db +from nova import flags +from nova import log as logging +from nova import utils + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +def binpath(script): + """Returns the absolute path to a script in bin""" + return os.path.abspath(os.path.join(__file__, "../../../../bin", script)) + + +def lease_ip(private_ip): + """Run add command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'), + instance_ref['mac_address'], + private_ip) + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(cmd, addl_env=env) + LOG.debug("ISSUE_IP: %s, %s ", out, err) + + +def release_ip(private_ip): + """Run del command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'), + instance_ref['mac_address'], + private_ip) + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(cmd, addl_env=env) + LOG.debug("RELEASE_IP: %s, %s ", out, err) diff --git a/nova/tests/network/base.py b/nova/tests/network/base.py new file mode 100644 index 000000000..2dd8178ff --- /dev/null +++ b/nova/tests/network/base.py @@ -0,0 +1,154 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Base class of Unit Tests for all network models +""" +import IPy +import os + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.auth import manager + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +class NetworkTestCase(test.TestCase): + """Test cases for network code""" + def setUp(self): + super(NetworkTestCase, self).setUp() + # NOTE(vish): if you change these flags, make sure to change the + # flags in the corresponding section in nova-dhcpbridge + self.flags(connection_type='fake', + fake_call=True, + fake_network=True) + self.manager = manager.AuthManager() + self.user = self.manager.create_user('netuser', 'netuser', 'netuser') + self.projects = [] + self.network = utils.import_object(FLAGS.network_manager) + self.context = context.RequestContext(project=None, user=self.user) + for i in range(FLAGS.num_networks): + name = 'project%s' % i + project = self.manager.create_project(name, 'netuser', name) + self.projects.append(project) + # create the necessary network data for the project + user_context = context.RequestContext(project=self.projects[i], + user=self.user) + host = self.network.get_network_host(user_context.elevated()) + instance_ref = self._create_instance(0) + self.instance_id = instance_ref['id'] + instance_ref = self._create_instance(1) + self.instance2_id = instance_ref['id'] + + def tearDown(self): + # TODO(termie): this should really be instantiating clean datastores + # in between runs, one failure kills all the tests + db.instance_destroy(context.get_admin_context(), self.instance_id) + db.instance_destroy(context.get_admin_context(), self.instance2_id) + for project in self.projects: + self.manager.delete_project(project) + self.manager.delete_user(self.user) + super(NetworkTestCase, self).tearDown() + + def _create_instance(self, project_num, mac=None): + if not mac: + mac = utils.generate_mac() + project = self.projects[project_num] + self.context._project = project + self.context.project_id = project.id + return db.instance_create(self.context, + {'project_id': project.id, + 'mac_address': mac}) + + def _create_address(self, project_num, instance_id=None): + """Create an address in given project num""" + if instance_id is None: + instance_id = self.instance_id + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + return self.network.allocate_fixed_ip(self.context, instance_id) + + def _deallocate_address(self, project_num, address): + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + self.network.deallocate_fixed_ip(self.context, address) + + def _is_allocated_in_project(self, address, project_id): + """Returns true if address is in specified project""" + project_net = db.network_get_by_bridge(context.get_admin_context(), + FLAGS.flat_network_bridge) + network = db.fixed_ip_get_network(context.get_admin_context(), + address) + instance = db.fixed_ip_get_instance(context.get_admin_context(), + address) + # instance exists until release + return instance is not None and network['id'] == project_net['id'] + + def test_private_ipv6(self): + """Make sure ipv6 is OK""" + if FLAGS.use_ipv6: + instance_ref = self._create_instance(0) + address = self._create_address(0, instance_ref['id']) + network_ref = db.project_get_network( + context.get_admin_context(), + self.context.project_id) + address_v6 = db.instance_get_fixed_address_v6( + context.get_admin_context(), + instance_ref['id']) + self.assertEqual(instance_ref['mac_address'], + utils.to_mac(address_v6)) + instance_ref2 = db.fixed_ip_get_instance_v6( + context.get_admin_context(), + address_v6) + self.assertEqual(instance_ref['id'], instance_ref2['id']) + self.assertEqual(address_v6, + utils.to_global_ipv6( + network_ref['cidr_v6'], + instance_ref['mac_address'])) + self._deallocate_address(0, address) + db.instance_destroy(context.get_admin_context(), + instance_ref['id']) + + def test_available_ips(self): + """Make sure the number of available ips for the network is correct + + The number of available IP addresses depends on the test + environment's setup. + + Network size is set in test fixture's setUp method. + + There are ips reserved at the bottom and top of the range. + services (network, gateway, CloudPipe, broadcast) + """ + network = db.project_get_network(context.get_admin_context(), + self.projects[0].id) + net_size = flags.FLAGS.network_size + admin_context = context.get_admin_context() + total_ips = (db.network_count_available_ips(admin_context, + network['id']) + + db.network_count_reserved_ips(admin_context, + network['id']) + + db.network_count_allocated_ips(admin_context, + network['id'])) + self.assertEqual(total_ips, net_size) diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py index 91a49920d..a9a934158 100644 --- a/nova/tests/test_flat_network.py +++ b/nova/tests/test_flat_network.py @@ -30,96 +30,15 @@ from nova import log as logging from nova import test from nova import utils from nova.auth import manager +from nova.tests.network import base + FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.network') -class FlatNetworkTestCase(test.TestCase): +class FlatNetworkTestCase(base.NetworkTestCase): """Test cases for network code""" - def setUp(self): - super(FlatNetworkTestCase, self).setUp() - # NOTE(vish): if you change these flags, make sure to change the - # flags in the corresponding section in nova-dhcpbridge - self.flags(connection_type='fake', - fake_call=True, - fake_network=True) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('netuser', 'netuser', 'netuser') - self.projects = [] - self.network = utils.import_object(FLAGS.network_manager) - self.context = context.RequestContext(project=None, user=self.user) - for i in range(5): - name = 'project%s' % i - project = self.manager.create_project(name, 'netuser', name) - self.projects.append(project) - # create the necessary network data for the project - user_context = context.RequestContext(project=self.projects[i], - user=self.user) - host = self.network.get_network_host(user_context.elevated()) - instance_ref = self._create_instance(0) - self.instance_id = instance_ref['id'] - instance_ref = self._create_instance(1) - self.instance2_id = instance_ref['id'] - - def tearDown(self): - # TODO(termie): this should really be instantiating clean datastores - # in between runs, one failure kills all the tests - db.instance_destroy(context.get_admin_context(), self.instance_id) - db.instance_destroy(context.get_admin_context(), self.instance2_id) - for project in self.projects: - self.manager.delete_project(project) - self.manager.delete_user(self.user) - super(FlatNetworkTestCase, self).tearDown() - - def _create_instance(self, project_num, mac=None): - if not mac: - mac = utils.generate_mac() - project = self.projects[project_num] - self.context._project = project - self.context.project_id = project.id - return db.instance_create(self.context, - {'project_id': project.id, - 'mac_address': mac}) - - def _create_address(self, project_num, instance_id=None): - """Create an address in given project num""" - if instance_id is None: - instance_id = self.instance_id - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - return self.network.allocate_fixed_ip(self.context, instance_id) - - def _deallocate_address(self, project_num, address): - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - self.network.deallocate_fixed_ip(self.context, address) - - def test_private_ipv6(self): - """Make sure ipv6 is OK""" - if FLAGS.use_ipv6: - instance_ref = self._create_instance(0) - address = self._create_address(0, instance_ref['id']) - network_ref = db.project_get_network( - context.get_admin_context(), - self.context.project_id) - address_v6 = db.instance_get_fixed_address_v6( - context.get_admin_context(), - instance_ref['id']) - self.assertEqual(instance_ref['mac_address'], - utils.to_mac(address_v6)) - instance_ref2 = db.fixed_ip_get_instance_v6( - context.get_admin_context(), - address_v6) - self.assertEqual(instance_ref['id'], instance_ref2['id']) - self.assertEqual(address_v6, - utils.to_global_ipv6( - network_ref['cidr_v6'], - instance_ref['mac_address'])) - self._deallocate_address(0, address) - db.instance_destroy(context.get_admin_context(), - instance_ref['id']) - def test_public_network_association(self): """Makes sure that we can allocate a public ip""" # TODO(vish): better way of adding floating ips @@ -167,28 +86,34 @@ class FlatNetworkTestCase(test.TestCase): def test_allocate_deallocate_fixed_ip(self): """Makes sure that we can allocate and deallocate a fixed ip""" address = self._create_address(0) - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) self._deallocate_address(0, address) # check if the fixed ip address is really deallocated - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) def test_side_effects(self): """Ensures allocating and releasing has no side effects""" address = self._create_address(0) address2 = self._create_address(1, self.instance2_id) - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) - self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[1].id)) self._deallocate_address(0, address) - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) # First address release shouldn't affect the second - self.assertTrue(is_allocated_in_project(address2, self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[0].id)) self._deallocate_address(1, address2) - self.assertFalse(is_allocated_in_project(address2, + self.assertFalse(self._is_allocated_in_project(address2, self.projects[1].id)) def test_ips_are_reused(self): @@ -201,29 +126,6 @@ class FlatNetworkTestCase(test.TestCase): self.network.deallocate_fixed_ip(self.context, address2) - def test_available_ips(self): - """Make sure the number of available ips for the network is correct - - The number of available IP addresses depends on the test - environment's setup. - - Network size is set in test fixture's setUp method. - - There are ips reserved at the bottom and top of the range. - services (network, gateway, CloudPipe, broadcast) - """ - network = db.project_get_network(context.get_admin_context(), - self.projects[0].id) - net_size = flags.FLAGS.network_size - admin_context = context.get_admin_context() - total_ips = (db.network_count_available_ips(admin_context, - network['id']) + - db.network_count_reserved_ips(admin_context, - network['id']) + - db.network_count_allocated_ips(admin_context, - network['id'])) - self.assertEqual(total_ips, net_size) - def test_too_many_addresses(self): """Test for a NoMoreAddresses exception when all fixed ips are used. """ @@ -257,20 +159,3 @@ class FlatNetworkTestCase(test.TestCase): def run(self, result=None): if(FLAGS.network_manager == 'nova.network.manager.FlatManager'): super(FlatNetworkTestCase, self).run(result) - - -def is_allocated_in_project(address, project_id): - """Returns true if address is in specified project""" - #project_net = db.project_get_network(context.get_admin_context(), - # project_id) - project_net = db.network_get_by_bridge(context.get_admin_context(), - FLAGS.flat_network_bridge) - network = db.fixed_ip_get_network(context.get_admin_context(), address) - instance = db.fixed_ip_get_instance(context.get_admin_context(), address) - # instance exists until release - return instance is not None and network['id'] == project_net['id'] - - -def binpath(script): - """Returns the absolute path to a script in bin""" - return os.path.abspath(os.path.join(__file__, "../../../bin", script)) diff --git a/nova/tests/test_vlan_network.py b/nova/tests/test_vlan_network.py index be39313bb..f3478320b 100644 --- a/nova/tests/test_vlan_network.py +++ b/nova/tests/test_vlan_network.py @@ -29,100 +29,16 @@ from nova import log as logging from nova import test from nova import utils from nova.auth import manager +from nova.tests.network import base +from nova.tests.network import binpath,\ + lease_ip, release_ip FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.network') -class VlanNetworkTestCase(test.TestCase): +class VlanNetworkTestCase(base.NetworkTestCase): """Test cases for network code""" - def setUp(self): - super(VlanNetworkTestCase, self).setUp() - # NOTE(vish): if you change these flags, make sure to change the - # flags in the corresponding section in nova-dhcpbridge - self.flags(connection_type='fake', - fake_call=True, - fake_network=True) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('netuser', 'netuser', 'netuser') - self.projects = [] - self.network = utils.import_object(FLAGS.network_manager) - self.context = context.RequestContext(project=None, user=self.user) - for i in range(FLAGS.num_networks): - name = 'project%s' % i - project = self.manager.create_project(name, 'netuser', name) - self.projects.append(project) - # create the necessary network data for the project - user_context = context.RequestContext(project=self.projects[i], - user=self.user) - host = self.network.get_network_host(user_context.elevated()) - instance_ref = self._create_instance(0) - self.instance_id = instance_ref['id'] - instance_ref = self._create_instance(1) - self.instance2_id = instance_ref['id'] - - def tearDown(self): - # TODO(termie): this should really be instantiating clean datastores - # in between runs, one failure kills all the tests - db.instance_destroy(context.get_admin_context(), self.instance_id) - db.instance_destroy(context.get_admin_context(), self.instance2_id) - for project in self.projects: - self.manager.delete_project(project) - self.manager.delete_user(self.user) - super(VlanNetworkTestCase, self).tearDown() - - def run(self, result=None): - if(FLAGS.network_manager == 'nova.network.manager.VlanManager'): - super(VlanNetworkTestCase, self).run(result) - - def _create_instance(self, project_num, mac=None): - if not mac: - mac = utils.generate_mac() - project = self.projects[project_num] - self.context._project = project - self.context.project_id = project.id - return db.instance_create(self.context, - {'project_id': project.id, - 'mac_address': mac}) - - def _create_address(self, project_num, instance_id=None): - """Create an address in given project num""" - if instance_id is None: - instance_id = self.instance_id - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - return self.network.allocate_fixed_ip(self.context, instance_id) - - def _deallocate_address(self, project_num, address): - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - self.network.deallocate_fixed_ip(self.context, address) - - def test_private_ipv6(self): - """Make sure ipv6 is OK""" - if FLAGS.use_ipv6: - instance_ref = self._create_instance(0) - address = self._create_address(0, instance_ref['id']) - network_ref = db.project_get_network( - context.get_admin_context(), - self.context.project_id) - address_v6 = db.instance_get_fixed_address_v6( - context.get_admin_context(), - instance_ref['id']) - self.assertEqual(instance_ref['mac_address'], - utils.to_mac(address_v6)) - instance_ref2 = db.fixed_ip_get_instance_v6( - context.get_admin_context(), - address_v6) - self.assertEqual(instance_ref['id'], instance_ref2['id']) - self.assertEqual(address_v6, - utils.to_global_ipv6( - network_ref['cidr_v6'], - instance_ref['mac_address'])) - self._deallocate_address(0, address) - db.instance_destroy(context.get_admin_context(), - instance_ref['id']) - def test_public_network_association(self): """Makes sure that we can allocaate a public ip""" # TODO(vish): better way of adding floating ips @@ -157,24 +73,30 @@ class VlanNetworkTestCase(test.TestCase): def test_allocate_deallocate_fixed_ip(self): """Makes sure that we can allocate and deallocate a fixed ip""" address = self._create_address(0) - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) lease_ip(address) self._deallocate_address(0, address) # Doesn't go away until it's dhcp released - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) release_ip(address) - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) def test_side_effects(self): """Ensures allocating and releasing has no side effects""" address = self._create_address(0) address2 = self._create_address(1, self.instance2_id) - self.assertTrue(is_allocated_in_project(address, self.projects[0].id)) - self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) - self.assertFalse(is_allocated_in_project(address, self.projects[1].id)) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[1].id)) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[1].id)) # Addresses are allocated before they're issued lease_ip(address) @@ -182,14 +104,16 @@ class VlanNetworkTestCase(test.TestCase): self._deallocate_address(0, address) release_ip(address) - self.assertFalse(is_allocated_in_project(address, self.projects[0].id)) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) # First address release shouldn't affect the second - self.assertTrue(is_allocated_in_project(address2, self.projects[1].id)) + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[1].id)) self._deallocate_address(1, address2) release_ip(address2) - self.assertFalse(is_allocated_in_project(address2, + self.assertFalse(self._is_allocated_in_project(address2, self.projects[1].id)) def test_subnet_edge(self): @@ -212,11 +136,11 @@ class VlanNetworkTestCase(test.TestCase): lease_ip(address3) self.context._project = self.projects[i] self.context.project_id = self.projects[i].id - self.assertFalse(is_allocated_in_project(address, + self.assertFalse(self._is_allocated_in_project(address, self.projects[0].id)) - self.assertFalse(is_allocated_in_project(address2, + self.assertFalse(self._is_allocated_in_project(address2, self.projects[0].id)) - self.assertFalse(is_allocated_in_project(address3, + self.assertFalse(self._is_allocated_in_project(address3, self.projects[0].id)) self.network.deallocate_fixed_ip(self.context, address) self.network.deallocate_fixed_ip(self.context, address2) @@ -270,29 +194,6 @@ class VlanNetworkTestCase(test.TestCase): self.network.deallocate_fixed_ip(self.context, address2) release_ip(address) - def test_available_ips(self): - """Make sure the number of available ips for the network is correct - - The number of available IP addresses depends on the test - environment's setup. - - Network size is set in test fixture's setUp method. - - There are ips reserved at the bottom and top of the range. - services (network, gateway, CloudPipe, broadcast) - """ - network = db.project_get_network(context.get_admin_context(), - self.projects[0].id) - net_size = flags.FLAGS.network_size - admin_context = context.get_admin_context() - total_ips = (db.network_count_available_ips(admin_context, - network['id']) + - db.network_count_reserved_ips(admin_context, - network['id']) + - db.network_count_allocated_ips(admin_context, - network['id'])) - self.assertEqual(total_ips, net_size) - def test_too_many_addresses(self): """Test for a NoMoreAddresses exception when all fixed ips are used. """ @@ -325,49 +226,17 @@ class VlanNetworkTestCase(test.TestCase): network['id']) self.assertEqual(ip_count, num_available_ips) + def _is_allocated_in_project(self, address, project_id): + """Returns true if address is in specified project""" + project_net = db.project_get_network(context.get_admin_context(), + project_id) + network = db.fixed_ip_get_network(context.get_admin_context(), + address) + instance = db.fixed_ip_get_instance(context.get_admin_context(), + address) + # instance exists until release + return instance is not None and network['id'] == project_net['id'] -def is_allocated_in_project(address, project_id): - """Returns true if address is in specified project""" - project_net = db.project_get_network(context.get_admin_context(), - project_id) - network = db.fixed_ip_get_network(context.get_admin_context(), address) - instance = db.fixed_ip_get_instance(context.get_admin_context(), address) - # instance exists until release - return instance is not None and network['id'] == project_net['id'] - - -def binpath(script): - """Returns the absolute path to a script in bin""" - return os.path.abspath(os.path.join(__file__, "../../../bin", script)) - - -def lease_ip(private_ip): - """Run add command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = "%s add %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) - LOG.debug("ISSUE_IP: %s, %s ", out, err) - - -def release_ip(private_ip): - """Run del command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = "%s del %s %s fake" % (binpath('nova-dhcpbridge'), - instance_ref['mac_address'], - private_ip) - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(cmd, addl_env=env) - LOG.debug("RELEASE_IP: %s, %s ", out, err) + def run(self, result=None): + if(FLAGS.network_manager == 'nova.network.manager.VlanManager'): + super(VlanNetworkTestCase, self).run(result) -- cgit From 7a6833c883a04fd7920bff7367c9e28a35858d8d Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 8 Mar 2011 23:17:50 +0000 Subject: Accidentally left some bad data around --- nova/tests/test_xenapi.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 919a38c06..916555af3 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -376,6 +376,11 @@ class XenAPIMigrateInstance(test.TestCase): stubs.stub_out_migration_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) + def tearDown(self): + super(XenAPIMigrateInstance, self).tearDown() + self.manager.delete_project(self.project) + self.manager.delete_user(self.user) + self.stubs.UnsetAll() def test_migrate_disk_and_power_off(self): instance = db.instance_create(self.values) -- cgit From 698398fdc2a05a0930591d3f3d386ad24a322359 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 8 Mar 2011 23:24:19 +0000 Subject: Pep8 fixes --- nova/tests/test_xenapi.py | 2 ++ nova/tests/xenapi/stubs.py | 1 + 2 files changed, 3 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 916555af3..c26dc8639 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -376,6 +376,7 @@ class XenAPIMigrateInstance(test.TestCase): stubs.stub_out_migration_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) + def tearDown(self): super(XenAPIMigrateInstance, self).tearDown() self.manager.delete_project(self.project) @@ -394,6 +395,7 @@ class XenAPIMigrateInstance(test.TestCase): conn = xenapi_conn.get_connection(False) conn.finish_resize(instance, dict(base_copy='hurr', cow='durr')) + class XenAPIDetermineDiskImageTestCase(test.TestCase): """ Unit tests for code that detects the ImageType diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index d8e358611..70d46a1fb 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -237,6 +237,7 @@ class FakeSessionForMigrationTests(fake.SessionBase): vm['is_a_template'] = False vm['is_control_domain'] = False + def stub_out_migration_methods(stubs): def fake_get_snapshot(self, instance): return 'foo', 'bar' -- cgit From 6207abe3068964c586d06bb0e3740b8bad922dca Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 8 Mar 2011 23:26:33 +0000 Subject: Fixing tests --- nova/tests/glance/stubs.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/glance/stubs.py b/nova/tests/glance/stubs.py index 3ff8d7ce5..5872552ec 100644 --- a/nova/tests/glance/stubs.py +++ b/nova/tests/glance/stubs.py @@ -35,23 +35,28 @@ class FakeGlance(object): IMAGE_FIXTURES = { IMAGE_MACHINE: { 'image_meta': {'name': 'fakemachine', 'size': 0, - 'type': 'machine'}, + 'disk_format': 'ami', + 'container_format': 'ami'}, 'image_data': StringIO.StringIO('')}, IMAGE_KERNEL: { 'image_meta': {'name': 'fakekernel', 'size': 0, - 'type': 'kernel'}, + 'disk_format': 'aki', + 'container_format': 'aki'}, 'image_data': StringIO.StringIO('')}, IMAGE_RAMDISK: { 'image_meta': {'name': 'fakeramdisk', 'size': 0, - 'type': 'ramdisk'}, + 'disk_format': 'ari', + 'container_format': 'ari'}, 'image_data': StringIO.StringIO('')}, IMAGE_RAW: { 'image_meta': {'name': 'fakeraw', 'size': 0, - 'type': 'raw'}, + 'disk_format': 'raw', + 'container_format': 'bare'}, 'image_data': StringIO.StringIO('')}, IMAGE_VHD: { 'image_meta': {'name': 'fakevhd', 'size': 0, - 'type': 'vhd'}, + 'disk_format': 'vhd', + 'container_format': 'ovf'}, 'image_data': StringIO.StringIO('')}} def __init__(self, host, port=None, use_ssl=False): -- cgit From e4b176d41cca234082c28ba6d9188745f1d2b98a Mon Sep 17 00:00:00 2001 From: Cory Wright Date: Wed, 9 Mar 2011 00:49:56 +0000 Subject: a few fixes for the tests --- nova/tests/test_xenapi.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 383819b00..cd125a301 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -440,6 +440,7 @@ class XenAPIMigrateInstance(test.TestCase): 'ramdisk_id': None, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', + 'os_type': 'linux' } stubs.stub_out_migration_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs, -- cgit From a320b5df9f916adf8422ed312306c77570d392c2 Mon Sep 17 00:00:00 2001 From: Eric Windisch Date: Wed, 9 Mar 2011 00:30:05 -0500 Subject: execvp: almost passes tests --- nova/tests/test_network.py | 2 +- nova/tests/test_virt.py | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index 6d2d8b771..19099ff4c 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -343,7 +343,7 @@ def lease_ip(private_ip): private_ip) instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), private_ip) - cmd = (binpath('nova-dhcpbridge'), 'add' + cmd = (binpath('nova-dhcpbridge'), 'add', instance_ref['mac_address'], private_ip, 'fake') env = {'DNSMASQ_INTERFACE': network_ref['bridge'], diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index f151ae911..7f1ad002e 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -315,15 +315,16 @@ class IptablesFirewallTestCase(test.TestCase): instance_ref = db.instance_get(admin_ctxt, instance_ref['id']) # self.fw.add_instance(instance_ref) - def fake_iptables_execute(cmd, process_input=None): - if cmd == 'sudo ip6tables-save -t filter': + def fake_iptables_execute(*cmd, **kwargs): + process_input=kwargs.get('process_input', None) + if cmd == ('sudo', 'ip6tables-save', '-t', 'filter'): return '\n'.join(self.in6_rules), None - if cmd == 'sudo iptables-save -t filter': + if cmd == ('sudo', 'iptables-save', '-t', 'filter'): return '\n'.join(self.in_rules), None - if cmd == 'sudo iptables-restore': + if cmd == ('sudo', 'iptables-restore'): self.out_rules = process_input.split('\n') return '', '' - if cmd == 'sudo ip6tables-restore': + if cmd == ('sudo', 'ip6tables-restore'): self.out6_rules = process_input.split('\n') return '', '' self.fw.execute = fake_iptables_execute -- cgit From 77da93886be61230dea5a4a4c4de036a57e62550 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 9 Mar 2011 06:56:42 +0000 Subject: tests and semaphore fix for image caching --- nova/tests/test_virt.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index f151ae911..ec7498d72 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -14,12 +14,16 @@ # License for the specific language governing permissions and limitations # under the License. +import os + +import eventlet from xml.etree.ElementTree import fromstring as xml_to_tree from xml.dom.minidom import parseString as xml_to_dom from nova import context from nova import db from nova import flags +from nova import log as logging from nova import test from nova import utils from nova.api.ec2 import cloud @@ -30,6 +34,68 @@ FLAGS = flags.FLAGS flags.DECLARE('instances_path', 'nova.compute.manager') +def _concurrency(wait, done, target): + wait.wait() + done.send() + + +class CacheConcurrencyTestCase(test.TestCase): + def setUp(self): + super(CacheConcurrencyTestCase, self).setUp() + + def fake_exists(fname): + basedir = os.path.join(FLAGS.instances_path, '_base') + if fname == basedir: + return True + return False + + def fake_execute(*args, **kwargs): + pass + + self.stubs.Set(os.path, 'exists', fake_exists) + self.stubs.Set(utils, 'execute', fake_execute) + + def test_same_fname_concurrency(self): + """Ensures that the same fname cache runs at a sequentially""" + conn = libvirt_conn.get_connection(False) + wait1 = eventlet.event.Event() + done1 = eventlet.event.Event() + eventlet.spawn(conn._cache_image, _concurrency, + 'target', 'fname', False, wait1, done1) + wait2 = eventlet.event.Event() + done2 = eventlet.event.Event() + eventlet.spawn(conn._cache_image, _concurrency, + 'target', 'fname', False, wait2, done2) + wait2.send() + eventlet.sleep(0) + try: + self.assertFalse(done2.ready()) + finally: + wait1.send() + done1.wait() + eventlet.sleep(0) + self.assertTrue(done2.ready()) + + def test_different_fname_concurrency(self): + """Ensures that two different fname caches are concurrent""" + conn = libvirt_conn.get_connection(False) + wait1 = eventlet.event.Event() + done1 = eventlet.event.Event() + eventlet.spawn(conn._cache_image, _concurrency, + 'target', 'fname2', False, wait1, done1) + wait2 = eventlet.event.Event() + done2 = eventlet.event.Event() + eventlet.spawn(conn._cache_image, _concurrency, + 'target', 'fname1', False, wait2, done2) + wait2.send() + eventlet.sleep(0) + try: + self.assertTrue(done2.ready()) + finally: + wait1.send() + eventlet.sleep(0) + + class LibvirtConnTestCase(test.TestCase): def setUp(self): super(LibvirtConnTestCase, self).setUp() -- cgit From ddeab2da30bb2f74109854d982c6681e78e7a4ce Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 9 Mar 2011 07:35:58 +0000 Subject: make static method for testing without initializing libvirt --- nova/tests/test_virt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index ec7498d72..113632a0c 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -57,7 +57,7 @@ class CacheConcurrencyTestCase(test.TestCase): def test_same_fname_concurrency(self): """Ensures that the same fname cache runs at a sequentially""" - conn = libvirt_conn.get_connection(False) + conn = libvirt_conn.LibvirtConnection wait1 = eventlet.event.Event() done1 = eventlet.event.Event() eventlet.spawn(conn._cache_image, _concurrency, @@ -78,7 +78,7 @@ class CacheConcurrencyTestCase(test.TestCase): def test_different_fname_concurrency(self): """Ensures that two different fname caches are concurrent""" - conn = libvirt_conn.get_connection(False) + conn = libvirt_conn.LibvirtConnection wait1 = eventlet.event.Event() done1 = eventlet.event.Event() eventlet.spawn(conn._cache_image, _concurrency, -- cgit From 7d31fe9ef316f49379818259a55a84deb5b850cd Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 9 Mar 2011 10:30:18 +0100 Subject: Stop assuming anything about the order in which the two processes are scheduled. --- nova/tests/test_misc.py | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 9f572b58e..a658e4978 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -71,30 +71,33 @@ class LockTestCase(test.TestCase): "got mangled") def test_synchronized(self): - rpipe, wpipe = os.pipe() + rpipe1, wpipe1 = os.pipe() + rpipe2, wpipe2 = os.pipe() + + @synchronized('testlock') + def f(rpipe, wpipe): + try: + os.write(wpipe, "foo") + except OSError, e: + self.assertEquals(e.errno, errno.EPIPE) + return + + rfds, _, __ = select.select([rpipe], [], [], 1) + self.assertEquals(len(rfds), 0, "The other process, which was" + " supposed to be locked, " + "wrote on its end of the " + "pipe") + os.close(rpipe) + pid = os.fork() if pid > 0: - os.close(wpipe) - - @synchronized('testlock') - def f(): - rfds, _, __ = select.select([rpipe], [], [], 1) - self.assertEquals(len(rfds), 0, "The other process, which was" - " supposed to be locked, " - "wrote on its end of the " - "pipe") - os.close(rpipe) - - f() + os.close(wpipe1) + os.close(rpipe2) + + f(rpipe1, wpipe2) else: - os.close(rpipe) + os.close(rpipe1) + os.close(wpipe2) - @synchronized('testlock') - def g(): - try: - os.write(wpipe, "foo") - except OSError, e: - self.assertEquals(e.errno, errno.EPIPE) - return - g() + f(rpipe2, wpipe1) os._exit(0) -- cgit From f1dea606a64c9144fb723be0e5b86806891380f8 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 9 Mar 2011 11:54:21 -0500 Subject: add override to handle xml deserialization for server instance creation --- nova/tests/api/openstack/fakes.py | 2 - nova/tests/api/openstack/test_servers.py | 277 +++++++++++++++++++++++++++++++ 2 files changed, 277 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 49ce8c1b5..1d8692528 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -68,8 +68,6 @@ def fake_auth_init(self, application): @webob.dec.wsgify def fake_wsgi(self, req): req.environ['nova.context'] = context.RequestContext(1, 1) - if req.body: - req.environ['inst_dict'] = json.loads(req.body) return self.application diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 8fb5a9aec..5132d1ad3 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -18,6 +18,7 @@ import base64 import datetime import json +import unittest import stubout import webob @@ -284,6 +285,37 @@ class ServersTest(test.TestCase): response = request.get_response(fakes.wsgi_app()) return compute_api, response + def _format_xml_request_body(self, body_dict): + server = body_dict['server'] + body_parts = [] + body_parts.extend([ + '', + '' % ( + server['name'], server['imageId'], server['flavorId'])]) + if 'metadata' in server: + metadata = server['metadata'] + body_parts.append('') + for item in metadata.iteritems(): + body_parts.append('%s' % item) + body_parts.append('') + if 'personality' in server: + personalities = server['personality'] + body_parts.append('') + for file in personalities: + item = (file['path'], file['contents']) + body_parts.append('%s' % item) + body_parts.append('') + body_parts.append('') + return ''.join(body_parts) + + def _get_create_request_xml(self, body_dict): + req = webob.Request.blank('/v1.0/servers') + req.content_type = 'application/xml' + req.method = 'POST' + req.body = self._format_xml_request_body(body_dict) + return req + def _create_instance_with_personality_json(self, personality): body_dict = self._create_personality_request_dict(personality) request = self._get_create_request_json(body_dict) @@ -291,12 +323,25 @@ class ServersTest(test.TestCase): self._run_create_instance_with_mock_compute_api(request) return request, response, compute_api.personality_files + def _create_instance_with_personality_xml(self, personality): + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_xml(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + return request, response, compute_api.personality_files + def test_create_instance_with_no_personality(self): request, response, personality_files = \ self._create_instance_with_personality_json(personality=None) self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, []) + def test_create_instance_with_no_personality_xml(self): + request, response, personality_files = \ + self._create_instance_with_personality_xml(personality=None) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, []) + def test_create_instance_with_personality(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' @@ -307,6 +352,16 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, [(path, contents)]) + def test_create_instance_with_personality_xml(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Hello, World!"\n' + b64contents = base64.b64encode(contents) + personality = [(path, b64contents)] + request, response, personality_files = \ + self._create_instance_with_personality_xml(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, [(path, contents)]) + def test_create_instance_with_personality_no_path(self): personality = [('/remove/this/path', base64.b64encode('my\n\file\ncontents'))] @@ -318,6 +373,17 @@ class ServersTest(test.TestCase): self.assertEquals(response.status_int, 400) self.assertEquals(compute_api.personality_files, None) + def _test_create_instance_with_personality_no_path_xml(self): + personality = [('/remove/this/path', + base64.b64encode('my\n\file\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_xml(body_dict) + request.body = request.body.replace(' path="/remove/this/path"', '') + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + def test_create_instance_with_personality_no_contents(self): personality = [('/test/path', base64.b64encode('remove\nthese\ncontents'))] @@ -605,3 +671,214 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '202 Accepted') self.assertEqual(self.server_delete_called, True) + + +class TestServerCreateRequestXMLDeserializer(unittest.TestCase): + + def setUp(self): + self.deserializer = servers.ServerCreateRequestXMLDeserializer() + + def test_minimal_request(self): + serial_request = """ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + }} + self.assertEquals(request, expected) + + def test_request_with_empty_metadata(self): + serial_request = """ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + "metadata": {}, + }} + self.assertEquals(request, expected) + + def test_request_with_empty_personality(self): + serial_request = """ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + "personality": [], + }} + self.assertEquals(request, expected) + + def test_request_with_empty_metadata_and_personality(self): + serial_request = """ +\ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + "metadata": {}, + "personality": [], + }} + self.assertEquals(request, expected) + + def test_request_with_empty_metadata_and_personality_reversed(self): + serial_request = """ +\ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + "metadata": {}, + "personality": [], + }} + self.assertEquals(request, expected) + + def test_request_with_one_personality(self): + serial_request = """ +\ +aabbccdd""" + request = self.deserializer.deserialize(serial_request) + expected = [{"path": "/etc/conf", "contents": "aabbccdd"}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_two_personalities(self): + serial_request = """ +\ +aabbccdd\ +abcd""" + request = self.deserializer.deserialize(serial_request) + expected = [{"path": "/etc/conf", "contents": "aabbccdd"}, + {"path": "/etc/sudoers", "contents": "abcd"}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_one_personality_missing_path(self): + serial_request = """ +\ +aabbccdd""" + request = self.deserializer.deserialize(serial_request) + expected = [{"contents": "aabbccdd"}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_one_personality_empty_contents(self): + serial_request = """ +\ +""" + request = self.deserializer.deserialize(serial_request) + expected = [{"path": "/etc/conf", "contents": ""}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_one_personality_empty_contents_variation(self): + serial_request = """ +\ +""" + request = self.deserializer.deserialize(serial_request) + expected = [{"path": "/etc/conf", "contents": ""}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_one_metadata(self): + serial_request = """ +\ +beta""" + request = self.deserializer.deserialize(serial_request) + expected = {"alpha": "beta"} + self.assertEquals(request["server"]["metadata"], expected) + + def test_request_with_two_metadata(self): + serial_request = """ +\ +betabar\ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"alpha": "beta", "foo": "bar"} + self.assertEquals(request["server"]["metadata"], expected) + + def test_request_with_metadata_missing_value(self): + serial_request = """ +\ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"alpha": ""} + self.assertEquals(request["server"]["metadata"], expected) + + def test_request_with_metadata_missing_key(self): + serial_request = """ +\ +beta""" + request = self.deserializer.deserialize(serial_request) + expected = {"": "beta"} + self.assertEquals(request["server"]["metadata"], expected) + + def test_request_with_metadata_duplicate_key(self): + serial_request = """ +\ +barbaz\ +""" + request = self.deserializer.deserialize(serial_request) + expected = {"foo": "baz"} + self.assertEquals(request["server"]["metadata"], expected) + + def test_canonical_request_from_docs(self): + serial_request = """ +\ +Apache1\ +\ +ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp\ +dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k\ +IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs\ +c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g\ +QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo\ +ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\ +dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\ +c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\ +b25zLiINCg0KLVJpY2hhcmQgQmFjaA==\ +""" + expected = {"server": { + "name": "new-server-test", + "imageId": "1", + "flavorId": "1", + "metadata": { + "My Server Name": "Apache1", + }, + "personality": [ + { + "path": "/etc/banner.txt", + "contents": """\ +ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp\ +dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k\ +IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs\ +c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g\ +QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo\ +ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\ +dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\ +c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\ +b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""", + } + ], + }} + request = self.deserializer.deserialize(serial_request) + self.assertEqual(request, expected) + -- cgit From 1d74816bf705cb672d9d323398b03142297d8bec Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 9 Mar 2011 12:03:17 -0500 Subject: remove superfluous trailing blank line --- nova/tests/api/openstack/test_servers.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 5132d1ad3..51fb09b18 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -881,4 +881,3 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""", }} request = self.deserializer.deserialize(serial_request) self.assertEqual(request, expected) - -- cgit From 1166e16d08769222189e31e6de1c6019495fc743 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 9 Mar 2011 13:54:30 -0500 Subject: move my tests into their own testcase --- nova/tests/api/openstack/test_servers.py | 447 +++++++++++++++++-------------- 1 file changed, 243 insertions(+), 204 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index f2fbb04af..b0f888766 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -238,210 +238,6 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) - def _setup_mock_compute_api_for_personality(self): - - class MockComputeAPI(object): - - def __init__(self): - self.personality_files = None - - def create(self, *args, **kwargs): - if 'personality_files' in kwargs: - self.personality_files = kwargs['personality_files'] - else: - self.personality_files = None - return [{'id': '1234', 'display_name': 'fakeinstance'}] - - def make_stub_method(canned_return): - def stub_method(*args, **kwargs): - return canned_return - return stub_method - - compute_api = MockComputeAPI() - self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api)) - self.stubs.Set(nova.api.openstack.servers.Controller, - '_get_kernel_ramdisk_from_image', make_stub_method((1, 1))) - self.stubs.Set(nova.api.openstack.common, - 'get_image_id_from_image_hash', make_stub_method(2)) - return compute_api - - def _create_personality_request_dict(self, personality_files): - server = {} - server['name'] = 'new-server-test' - server['imageId'] = 1 - server['flavorId'] = 1 - if personality_files is not None: - personalities = [] - for path, contents in personality_files: - personalities.append({'path': path, 'contents': contents}) - server['personality'] = personalities - return {'server': server} - - def _get_create_request_json(self, body_dict): - req = webob.Request.blank('/v1.0/servers') - req.content_type = 'application/json' - req.method = 'POST' - req.body = json.dumps(body_dict) - return req - - def _run_create_instance_with_mock_compute_api(self, request): - compute_api = self._setup_mock_compute_api_for_personality() - response = request.get_response(fakes.wsgi_app()) - return compute_api, response - - def _format_xml_request_body(self, body_dict): - server = body_dict['server'] - body_parts = [] - body_parts.extend([ - '', - '' % ( - server['name'], server['imageId'], server['flavorId'])]) - if 'metadata' in server: - metadata = server['metadata'] - body_parts.append('') - for item in metadata.iteritems(): - body_parts.append('%s' % item) - body_parts.append('') - if 'personality' in server: - personalities = server['personality'] - body_parts.append('') - for file in personalities: - item = (file['path'], file['contents']) - body_parts.append('%s' % item) - body_parts.append('') - body_parts.append('') - return ''.join(body_parts) - - def _get_create_request_xml(self, body_dict): - req = webob.Request.blank('/v1.0/servers') - req.content_type = 'application/xml' - req.method = 'POST' - req.body = self._format_xml_request_body(body_dict) - return req - - def _create_instance_with_personality_json(self, personality): - body_dict = self._create_personality_request_dict(personality) - request = self._get_create_request_json(body_dict) - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.personality_files - - def _create_instance_with_personality_xml(self, personality): - body_dict = self._create_personality_request_dict(personality) - request = self._get_create_request_xml(body_dict) - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.personality_files - - def test_create_instance_with_no_personality(self): - request, response, personality_files = \ - self._create_instance_with_personality_json(personality=None) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, []) - - def test_create_instance_with_no_personality_xml(self): - request, response, personality_files = \ - self._create_instance_with_personality_xml(personality=None) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, []) - - def test_create_instance_with_personality(self): - path = '/my/file/path' - contents = '#!/bin/bash\necho "Hello, World!"\n' - b64contents = base64.b64encode(contents) - personality = [(path, b64contents)] - request, response, personality_files = \ - self._create_instance_with_personality_json(personality) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) - - def test_create_instance_with_personality_xml(self): - path = '/my/file/path' - contents = '#!/bin/bash\necho "Hello, World!"\n' - b64contents = base64.b64encode(contents) - personality = [(path, b64contents)] - request, response, personality_files = \ - self._create_instance_with_personality_xml(personality) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) - - def test_create_instance_with_personality_no_path(self): - personality = [('/remove/this/path', - base64.b64encode('my\n\file\ncontents'))] - body_dict = self._create_personality_request_dict(personality) - del body_dict['server']['personality'][0]['path'] - request = self._get_create_request_json(body_dict) - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) - - def _test_create_instance_with_personality_no_path_xml(self): - personality = [('/remove/this/path', - base64.b64encode('my\n\file\ncontents'))] - body_dict = self._create_personality_request_dict(personality) - request = self._get_create_request_xml(body_dict) - request.body = request.body.replace(' path="/remove/this/path"', '') - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) - - def test_create_instance_with_personality_no_contents(self): - personality = [('/test/path', - base64.b64encode('remove\nthese\ncontents'))] - body_dict = self._create_personality_request_dict(personality) - del body_dict['server']['personality'][0]['contents'] - request = self._get_create_request_json(body_dict) - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) - - def test_create_instance_with_personality_not_a_list(self): - personality = [('/test/path', base64.b64encode('test\ncontents\n'))] - body_dict = self._create_personality_request_dict(personality) - body_dict['server']['personality'] = \ - body_dict['server']['personality'][0] - request = self._get_create_request_json(body_dict) - compute_api, response = \ - self._run_create_instance_with_mock_compute_api(request) - self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) - - def test_create_instance_with_personality_with_non_b64_content(self): - path = '/my/file/path' - contents = '#!/bin/bash\necho "Oh no!"\n' - personality = [(path, contents)] - request, response, personality_files = \ - self._create_instance_with_personality_json(personality) - self.assertEquals(response.status_int, 400) - self.assertEquals(personality_files, None) - - def test_create_instance_with_three_personalities(self): - files = [ - ('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'), - ('/etc/motd', 'Enjoy your root access!\n'), - ('/etc/dovecot.conf', 'dovecot\nconfig\nstuff\n'), - ] - personality = [] - for path, content in files: - personality.append((path, base64.b64encode(content))) - request, response, personality_files = \ - self._create_instance_with_personality_json(personality) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, files) - - def test_create_instance_personality_empty_content(self): - path = '/my/file/path' - contents = '' - personality = [(path, contents)] - request, response, personality_files = \ - self._create_instance_with_personality_json(personality) - self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) - def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' @@ -980,5 +776,248 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""", self.assertEqual(request, expected) +class TestServerInstanceCreation(test.TestCase): + + def setUp(self): + super(TestServerInstanceCreation, self).setUp() + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + fakes.stub_out_key_pair_funcs(self.stubs) + fakes.stub_out_image_service(self.stubs) + self.stubs.Set(nova.db.api, 'instance_get_all', return_servers) + self.stubs.Set(nova.db.api, 'instance_get', return_server) + self.stubs.Set(nova.db.api, 'instance_get_all_by_user', + return_servers) + self.stubs.Set(nova.db.api, 'instance_add_security_group', + return_security_group) + self.stubs.Set(nova.db.api, 'instance_update', instance_update) + self.stubs.Set(nova.db.api, 'instance_get_fixed_address', + instance_address) + self.stubs.Set(nova.db.api, 'instance_get_floating_address', + instance_address) + self.stubs.Set(nova.compute.API, 'pause', fake_compute_api) + self.stubs.Set(nova.compute.API, 'unpause', fake_compute_api) + self.stubs.Set(nova.compute.API, 'suspend', fake_compute_api) + self.stubs.Set(nova.compute.API, 'resume', fake_compute_api) + self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api) + self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) + self.allow_admin = FLAGS.allow_admin_api + + self.webreq = common.webob_factory('/v1.0/servers') + + def tearDown(self): + self.stubs.UnsetAll() + FLAGS.allow_admin_api = self.allow_admin + super(TestServerInstanceCreation, self).tearDown() + + def _setup_mock_compute_api_for_personality(self): + + class MockComputeAPI(object): + + def __init__(self): + self.personality_files = None + + def create(self, *args, **kwargs): + if 'personality_files' in kwargs: + self.personality_files = kwargs['personality_files'] + else: + self.personality_files = None + return [{'id': '1234', 'display_name': 'fakeinstance'}] + + def make_stub_method(canned_return): + def stub_method(*args, **kwargs): + return canned_return + return stub_method + + compute_api = MockComputeAPI() + self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api)) + self.stubs.Set(nova.api.openstack.servers.Controller, + '_get_kernel_ramdisk_from_image', make_stub_method((1, 1))) + self.stubs.Set(nova.api.openstack.common, + 'get_image_id_from_image_hash', make_stub_method(2)) + return compute_api + + def _create_personality_request_dict(self, personality_files): + server = {} + server['name'] = 'new-server-test' + server['imageId'] = 1 + server['flavorId'] = 1 + if personality_files is not None: + personalities = [] + for path, contents in personality_files: + personalities.append({'path': path, 'contents': contents}) + server['personality'] = personalities + return {'server': server} + + def _get_create_request_json(self, body_dict): + req = webob.Request.blank('/v1.0/servers') + req.content_type = 'application/json' + req.method = 'POST' + req.body = json.dumps(body_dict) + return req + + def _run_create_instance_with_mock_compute_api(self, request): + compute_api = self._setup_mock_compute_api_for_personality() + response = request.get_response(fakes.wsgi_app()) + return compute_api, response + + def _format_xml_request_body(self, body_dict): + server = body_dict['server'] + body_parts = [] + body_parts.extend([ + '', + '' % ( + server['name'], server['imageId'], server['flavorId'])]) + if 'metadata' in server: + metadata = server['metadata'] + body_parts.append('') + for item in metadata.iteritems(): + body_parts.append('%s' % item) + body_parts.append('') + if 'personality' in server: + personalities = server['personality'] + body_parts.append('') + for file in personalities: + item = (file['path'], file['contents']) + body_parts.append('%s' % item) + body_parts.append('') + body_parts.append('') + return ''.join(body_parts) + + def _get_create_request_xml(self, body_dict): + req = webob.Request.blank('/v1.0/servers') + req.content_type = 'application/xml' + req.method = 'POST' + req.body = self._format_xml_request_body(body_dict) + return req + + def _create_instance_with_personality_json(self, personality): + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + return request, response, compute_api.personality_files + + def _create_instance_with_personality_xml(self, personality): + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_xml(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + return request, response, compute_api.personality_files + + def test_create_instance_with_no_personality(self): + request, response, personality_files = \ + self._create_instance_with_personality_json(personality=None) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, []) + + def test_create_instance_with_no_personality_xml(self): + request, response, personality_files = \ + self._create_instance_with_personality_xml(personality=None) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, []) + + def test_create_instance_with_personality(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Hello, World!"\n' + b64contents = base64.b64encode(contents) + personality = [(path, b64contents)] + request, response, personality_files = \ + self._create_instance_with_personality_json(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, [(path, contents)]) + + def test_create_instance_with_personality_xml(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Hello, World!"\n' + b64contents = base64.b64encode(contents) + personality = [(path, b64contents)] + request, response, personality_files = \ + self._create_instance_with_personality_xml(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, [(path, contents)]) + + def test_create_instance_with_personality_no_path(self): + personality = [('/remove/this/path', + base64.b64encode('my\n\file\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + del body_dict['server']['personality'][0]['path'] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def _test_create_instance_with_personality_no_path_xml(self): + personality = [('/remove/this/path', + base64.b64encode('my\n\file\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + request = self._get_create_request_xml(body_dict) + request.body = request.body.replace(' path="/remove/this/path"', '') + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def test_create_instance_with_personality_no_contents(self): + personality = [('/test/path', + base64.b64encode('remove\nthese\ncontents'))] + body_dict = self._create_personality_request_dict(personality) + del body_dict['server']['personality'][0]['contents'] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def test_create_instance_with_personality_not_a_list(self): + personality = [('/test/path', base64.b64encode('test\ncontents\n'))] + body_dict = self._create_personality_request_dict(personality) + body_dict['server']['personality'] = \ + body_dict['server']['personality'][0] + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) + self.assertEquals(response.status_int, 400) + self.assertEquals(compute_api.personality_files, None) + + def test_create_instance_with_personality_with_non_b64_content(self): + path = '/my/file/path' + contents = '#!/bin/bash\necho "Oh no!"\n' + personality = [(path, contents)] + request, response, personality_files = \ + self._create_instance_with_personality_json(personality) + self.assertEquals(response.status_int, 400) + self.assertEquals(personality_files, None) + + def test_create_instance_with_three_personalities(self): + files = [ + ('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'), + ('/etc/motd', 'Enjoy your root access!\n'), + ('/etc/dovecot.conf', 'dovecot\nconfig\nstuff\n'), + ] + personality = [] + for path, content in files: + personality.append((path, base64.b64encode(content))) + request, response, personality_files = \ + self._create_instance_with_personality_json(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, files) + + def test_create_instance_personality_empty_content(self): + path = '/my/file/path' + contents = '' + personality = [(path, contents)] + request, response, personality_files = \ + self._create_instance_with_personality_json(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(personality_files, [(path, contents)]) + + if __name__ == "__main__": unittest.main() -- cgit From 3999bb363501c6587f75255333094c9e61bf1828 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 9 Mar 2011 14:07:33 -0500 Subject: remove unneeded stubs --- nova/tests/api/openstack/test_servers.py | 22 ---------------------- 1 file changed, 22 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index b0f888766..c67ecdaae 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -783,32 +783,10 @@ class TestServerInstanceCreation(test.TestCase): self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.auth_data = {} fakes.FakeAuthDatabase.data = {} - fakes.stub_out_networking(self.stubs) - fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) - fakes.stub_out_image_service(self.stubs) - self.stubs.Set(nova.db.api, 'instance_get_all', return_servers) - self.stubs.Set(nova.db.api, 'instance_get', return_server) - self.stubs.Set(nova.db.api, 'instance_get_all_by_user', - return_servers) - self.stubs.Set(nova.db.api, 'instance_add_security_group', - return_security_group) - self.stubs.Set(nova.db.api, 'instance_update', instance_update) - self.stubs.Set(nova.db.api, 'instance_get_fixed_address', - instance_address) - self.stubs.Set(nova.db.api, 'instance_get_floating_address', - instance_address) - self.stubs.Set(nova.compute.API, 'pause', fake_compute_api) - self.stubs.Set(nova.compute.API, 'unpause', fake_compute_api) - self.stubs.Set(nova.compute.API, 'suspend', fake_compute_api) - self.stubs.Set(nova.compute.API, 'resume', fake_compute_api) - self.stubs.Set(nova.compute.API, "get_diagnostics", fake_compute_api) - self.stubs.Set(nova.compute.API, "get_actions", fake_compute_api) self.allow_admin = FLAGS.allow_admin_api - self.webreq = common.webob_factory('/v1.0/servers') - def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin -- cgit From 3f723bcf54b4d779c66373dc8f69f43923dd586a Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 9 Mar 2011 15:08:11 -0500 Subject: renaming wsgi.Request.best_match to best_match_content_type; correcting calls to that function in code from trunk --- nova/tests/api/openstack/common.py | 1 + nova/tests/api/test_wsgi.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/common.py b/nova/tests/api/openstack/common.py index 3f9c7d3cf..74bb8729a 100644 --- a/nova/tests/api/openstack/common.py +++ b/nova/tests/api/openstack/common.py @@ -28,6 +28,7 @@ def webob_factory(url): def web_request(url, method=None, body=None): req = webob.Request.blank("%s%s" % (base_url, url)) if method: + req.content_type = "application/json" req.method = method if body: req.body = json.dumps(body) diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index 7c0135656..b1a849cf9 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -139,48 +139,48 @@ class RequestTest(test.TestCase): def test_content_type_from_accept_xml(self): request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = "application/xml" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/xml") request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = "application/json" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/json") request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = "application/xml, application/json" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/json") request = wsgi.Request.blank('/tests/123') request.headers["Accept"] = \ "application/json; q=0.3, application/xml; q=0.9" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/xml") def test_content_type_from_query_extension(self): request = wsgi.Request.blank('/tests/123.xml') - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/xml") request = wsgi.Request.blank('/tests/123.json') - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/json") request = wsgi.Request.blank('/tests/123.invalid') - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/json") def test_content_type_accept_and_query_extension(self): request = wsgi.Request.blank('/tests/123.xml') request.headers["Accept"] = "application/json" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/xml") def test_content_type_accept_default(self): request = wsgi.Request.blank('/tests/123.unsupported') request.headers["Accept"] = "application/unsupported1" - result = request.best_match() + result = request.best_match_content_type() self.assertEqual(result, "application/json") -- cgit From fc9840bae6200c8f89fb8a3ba0ab45663c872b3c Mon Sep 17 00:00:00 2001 From: Eric Windisch Date: Wed, 9 Mar 2011 15:33:20 -0500 Subject: execvp passes pep8 --- nova/tests/test_virt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 7f1ad002e..dfa607f14 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -316,7 +316,7 @@ class IptablesFirewallTestCase(test.TestCase): # self.fw.add_instance(instance_ref) def fake_iptables_execute(*cmd, **kwargs): - process_input=kwargs.get('process_input', None) + process_input = kwargs.get('process_input', None) if cmd == ('sudo', 'ip6tables-save', '-t', 'filter'): return '\n'.join(self.in6_rules), None if cmd == ('sudo', 'iptables-save', '-t', 'filter'): -- cgit From 3e61bf9963d7e98e8152d2eacfc4461d8cda309c Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 9 Mar 2011 21:43:35 +0000 Subject: remove the semaphore when there is no one waiting on it --- nova/tests/test_virt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 113632a0c..56a271365 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -23,7 +23,6 @@ from xml.dom.minidom import parseString as xml_to_dom from nova import context from nova import db from nova import flags -from nova import log as logging from nova import test from nova import utils from nova.api.ec2 import cloud @@ -70,11 +69,13 @@ class CacheConcurrencyTestCase(test.TestCase): eventlet.sleep(0) try: self.assertFalse(done2.ready()) + self.assertTrue('fname' in conn._image_sems) finally: wait1.send() done1.wait() eventlet.sleep(0) self.assertTrue(done2.ready()) + self.assertFalse('fname' in conn._image_sems) def test_different_fname_concurrency(self): """Ensures that two different fname caches are concurrent""" -- cgit From f0bb6d9fc47b92d335c7d7fa238dfd43f0dbdf69 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Thu, 10 Mar 2011 13:30:52 +0900 Subject: fixed based on reviewer's comment. --- nova/tests/test_compute.py | 24 +++++++------- nova/tests/test_scheduler.py | 5 +-- nova/tests/test_service.py | 77 +++++++++++++++++--------------------------- nova/tests/test_virt.py | 6 ++-- nova/tests/test_volume.py | 7 ++-- 5 files changed, 52 insertions(+), 67 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 85c2c948b..71899ba9e 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -89,14 +89,14 @@ class ComputeTestCase(test.TestCase): Use this when any testcase executed later than test_run_terminate """ vol1 = models.Volume() - vol1.__setitem__('id', 1) + vol1['id'] = 1 vol2 = models.Volume() - vol2.__setitem__('id', 2) + vol2['id'] = 2 instance_ref = models.Instance() - instance_ref.__setitem__('id', 1) - instance_ref.__setitem__('volumes', [vol1, vol2]) - instance_ref.__setitem__('hostname', 'i-00000001') - instance_ref.__setitem__('host', 'dummy') + instance_ref['id'] = 1 + instance_ref['volumes'] = [vol1, vol2] + instance_ref['hostname'] = 'i-00000001' + instance_ref['host'] = 'dummy' return instance_ref def test_create_instance_defaults_display_name(self): @@ -114,9 +114,9 @@ class ComputeTestCase(test.TestCase): """Make sure create associates security groups""" group = self._create_group() instance_ref = models.Instance() - instance_ref.__setitem__('id', 1) - instance_ref.__setitem__('volumes', [{'id': 1}, {'id': 2}]) - instance_ref.__setitem__('hostname', 'i-00000001') + instance_ref['id'] = 1 + instance_ref['volumes'] = [{'id': 1}, {'id': 2}] + instance_ref['hostname'] = 'i-00000001' return instance_ref def test_create_instance_defaults_display_name(self): @@ -390,7 +390,7 @@ class ComputeTestCase(test.TestCase): def test_pre_live_migration_instance_has_no_volume(self): """Confirm log meg when instance doesn't mount any volumes.""" i_ref = self._get_dummy_instance() - i_ref.__setitem__('volumes', []) + i_ref['volumes'] = [] c = context.get_admin_context() self._setup_other_managers() @@ -501,7 +501,7 @@ class ComputeTestCase(test.TestCase): def test_live_migration_dest_raises_exception_no_volume(self): """Same as above test(input pattern is different) """ i_ref = self._get_dummy_instance() - i_ref.__setitem__('volumes', []) + i_ref['volumes'] = [] c = context.get_admin_context() topic = db.queue_get_for(c, FLAGS.compute_topic, i_ref['host']) @@ -526,7 +526,7 @@ class ComputeTestCase(test.TestCase): def test_live_migration_works_correctly_no_volume(self): """Confirm live_migration() works as expected correctly.""" i_ref = self._get_dummy_instance() - i_ref.__setitem__('volumes', []) + i_ref['volumes'] = [] c = context.get_admin_context() topic = db.queue_get_for(c, FLAGS.compute_topic, i_ref['host']) diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 711b66af7..8ac02c5a4 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -119,7 +119,8 @@ class SchedulerTestCase(test.TestCase): try: scheduler.show_host_resources(ctxt, dest) except exception.NotFound, e: - c1 = (0 <= e.message.find('does not exist or not compute node')) + c1 = (e.message.find(_("does not exist or is not a " + "compute node.")) >= 0) self.assertTrue(c1) def _dic_is_equal(self, dic1, dic2, keys=None): @@ -786,7 +787,7 @@ class SimpleDriverTestCase(test.TestCase): i_ref, 'somewhere') except exception.NotEmpty, e: - c = (e.message.find('is not capable to migrate') >= 0) + c = (e.message.find('Unable to migrate') >= 0) self.assertTrue(c) db.instance_destroy(self.context, instance_id) diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index d17f6a22a..666c4a11d 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -42,24 +42,6 @@ class FakeManager(manager.Manager): def test_method(self): return 'manager' -# temporary variable to store host/binary/self.mox -# from each method to fake class. -global_host = None -global_binary = None -global_mox = None - - -class FakeComputeManager(compute_manager.ComputeManager): - """Fake computemanager manager for tests""" - - def __init__(self, compute_driver=None, *args, **kwargs): - global ghost, gbinary, gmox - self.update_available_resource(mox.IgnoreArg()) - gmox.ReplayAll() - super(FakeComputeManager, self).__init__(compute_driver, - *args, - **kwargs) - class ExtendedService(service.Service): def test_method(self): @@ -275,37 +257,38 @@ class ServiceTestCase(test.TestCase): """Confirm compute updates their record of compute-service table.""" host = 'foo' binary = 'nova-compute' - topic = 'compute1' - service_create = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova'} - service_ref = {'host': host, - 'binary': binary, - 'topic': topic, - 'report_count': 0, - 'availability_zone': 'nova', - 'id': 1} - - service.db.service_get_by_args(mox.IgnoreArg(), - host, - binary).AndRaise(exception.NotFound()) - service.db.service_create(mox.IgnoreArg(), - service_create).AndReturn(service_ref) - self.mox.StubOutWithMock(compute_manager.ComputeManager, - 'update_available_resource') - - global ghost, gbinary, gmox - ghost = host - gbinary = binary - gmox = self.mox - + topic = 'compute' + + # Any mocks are not working without UnsetStubs() here. + self.mox.UnsetStubs() + ctxt = context.get_admin_context() + service_ref = db.service_create(ctxt, {'host': host, + 'binary': binary, + 'topic': topic}) serv = service.Service(host, binary, topic, - 'nova.tests.test_service.FakeComputeManager') - # ReplayAll has been executed FakeComputeManager.__init__() - #self.mox.ReplayAll() + 'nova.compute.manager.ComputeManager') + + # This testcase want to test calling update_available_resource. + # No need to call periodic call, then below variable must be set 0. + serv.report_interval = 0 + serv.periodic_interval = 0 + + # Creating mocks + self.mox.StubOutWithMock(service.rpc.Connection, 'instance') + service.rpc.Connection.instance(new=mox.IgnoreArg()) + service.rpc.Connection.instance(new=mox.IgnoreArg()) + self.mox.StubOutWithMock(serv.manager.driver, + 'update_available_resource') + serv.manager.driver.update_available_resource(mox.IgnoreArg(), host) + + # Just doing start()-stop(), not confirm new db record is created, + # because update_available_resource() works only in libvirt environment. + # This testcase confirms update_available_resource() is called. + # Otherwise, mox complains. + self.mox.ReplayAll() serv.start() serv.stop() + + db.service_destroy(ctxt, service_ref['id']) diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 7ea8c0fb5..ee41ae732 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -283,7 +283,7 @@ class LibvirtConnTestCase(test.TestCase): self.assertEquals(uri, testuri) db.instance_destroy(user_context, instance_ref['id']) - def tes1t_update_available_resource_works_correctly(self): + def test_update_available_resource_works_correctly(self): """Confirm compute_node table is updated successfully.""" org_path = FLAGS.instances_path = '' FLAGS.instances_path = '.' @@ -314,7 +314,7 @@ class LibvirtConnTestCase(test.TestCase): compute_node = service_ref['compute_node'][0] if sys.platform.upper() == 'LINUX2': - self.assertTrue(compute_node['vcpus'] > 0) + self.assertTrue(compute_node['vcpus'] >= 0) self.assertTrue(compute_node['memory_mb'] > 0) self.assertTrue(compute_node['local_gb'] > 0) self.assertTrue(compute_node['vcpus_used'] == 0) @@ -323,7 +323,7 @@ class LibvirtConnTestCase(test.TestCase): self.assertTrue(len(compute_node['hypervisor_type']) > 0) self.assertTrue(compute_node['hypervisor_version'] > 0) else: - self.assertTrue(compute_node['vcpus'] > 0) + self.assertTrue(compute_node['vcpus'] >= 0) self.assertTrue(compute_node['memory_mb'] == 0) self.assertTrue(compute_node['local_gb'] > 0) self.assertTrue(compute_node['vcpus_used'] == 0) diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index e8b4ceee8..d88e363da 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -284,9 +284,10 @@ class AOETestCase(DriverTestCase): self.volume.check_for_export(self.context, self.instance_id) except exception.ProcessExecutionError, e: volume_id = volume_id_list[0] - msg = _("""Cannot confirm exported volume id:%(volume_id)s.""" - """vblade process for e%(shelf_id)s.%(blade_id)s """ - """isn't running.""") % locals() + msg = _("Cannot confirm exported volume id:%(volume_id)s. " + "vblade process for e%(shelf_id)s.%(blade_id)s " + "isn't running.") % locals() + msg_is_match = (0 <= e.message.find(msg)) self.assertTrue(msg_is_match) -- cgit From 90f38451e5df4f0ca862401cf898f01ffede6174 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 10 Mar 2011 00:26:25 -0500 Subject: add tests to verify the serialization of adminPass in server creation response --- nova/tests/api/openstack/test_servers.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 2fc28fe67..0561ad499 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -19,6 +19,7 @@ import base64 import datetime import json import unittest +from xml.dom import minidom import stubout import webob @@ -908,6 +909,7 @@ class TestServerInstanceCreation(test.TestCase): def _get_create_request_xml(self, body_dict): req = webob.Request.blank('/v1.0/servers') req.content_type = 'application/xml' + req.accept = 'application/xml' req.method = 'POST' req.body = self._format_xml_request_body(body_dict) return req @@ -1034,6 +1036,23 @@ class TestServerInstanceCreation(test.TestCase): self.assertEquals(response.status_int, 200) self.assertEquals(personality_files, [(path, contents)]) + def test_create_instance_admin_pass_json(self): + request, response, dummy = \ + self._create_instance_with_personality_json(None) + self.assertEquals(response.status_int, 200) + response = json.loads(response.body) + self.assertTrue('adminPass' in response['server']) + self.assertTrue(response['server']['adminPass'].startswith('fake')) + + def test_create_instance_admin_pass_xml(self): + request, response, dummy = \ + self._create_instance_with_personality_xml(None) + self.assertEquals(response.status_int, 200) + dom = minidom.parseString(response.body) + server = dom.childNodes[0] + self.assertEquals(server.nodeName, 'server') + self.assertTrue(server.getAttribute('adminPass').startswith('fake')) + if __name__ == "__main__": unittest.main() -- cgit From b75ab789194f1ced801b1d68ae8cc54051716414 Mon Sep 17 00:00:00 2001 From: Kei Masumoto Date: Thu, 10 Mar 2011 15:16:03 +0900 Subject: fix pep8 check --- nova/tests/test_service.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_service.py b/nova/tests/test_service.py index 666c4a11d..393f9d20b 100644 --- a/nova/tests/test_service.py +++ b/nova/tests/test_service.py @@ -284,9 +284,9 @@ class ServiceTestCase(test.TestCase): serv.manager.driver.update_available_resource(mox.IgnoreArg(), host) # Just doing start()-stop(), not confirm new db record is created, - # because update_available_resource() works only in libvirt environment. - # This testcase confirms update_available_resource() is called. - # Otherwise, mox complains. + # because update_available_resource() works only in + # libvirt environment. This testcase confirms + # update_available_resource() is called. Otherwise, mox complains. self.mox.ReplayAll() serv.start() serv.stop() -- cgit From 6b95c5133452ae26da2cb7f08267aa4cb056e7af Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 10 Mar 2011 15:05:04 -0500 Subject: Initial support fo extension resources. Tests. --- nova/tests/api/openstack/test_extensions.py | 83 +++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 nova/tests/api/openstack/test_extensions.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py new file mode 100644 index 000000000..f5332c84a --- /dev/null +++ b/nova/tests/api/openstack/test_extensions.py @@ -0,0 +1,83 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import unittest + +import webob + +from nova.api import openstack +import nova.wsgi + +class StubController(nova.wsgi.Controller): + + def __init__(self, body): + self.body = body + + def index(self, req): + return self.body + +class StubExtensionManager(object): + + def __init__(self, resources): + self.resources = resources + + def get_resources(self): + return self.resources + +class WidgetExtensionResource(object): + + def __init__(self, name, collection, wsgi_app): + self.name = name + self.collection = collection + self.wsgi_app = wsgi_app + + def add_routes(self, mapper): + mapper.resource(self.name, self.collection, controller=self.wsgi_app) + +class ExtensionTest(unittest.TestCase): + + def test_no_extension_present(self): + manager = StubExtensionManager([]) + router = openstack.APIRouter(manager) + request = webob.Request.blank("/widgets") + response = request.get_response(router) + self.assertEqual(404, response.status_int) + + def test_get_resources(self): + response_body = "Buy more widgets!" + response = webob.Response() + response.body = response_body + resource1 = WidgetExtensionResource("widget", "widgets", response) + manager = StubExtensionManager([resource1]) + router = openstack.APIRouter(manager) + request = webob.Request.blank("/widgets") + response = request.get_response(router) + self.assertEqual(200, response.status_int) + self.assertEqual(response_body, response.body) + + def test_get_resources_with_controller(self): + response_body = "Buy more widgets!" + controller = StubController(response_body) + resource1 = WidgetExtensionResource("widget", "widgets", controller) + manager = StubExtensionManager([resource1]) + router = openstack.APIRouter(manager) + request = webob.Request.blank("/widgets") + response = request.get_response(router) + self.assertEqual(200, response.status_int) + self.assertEqual(response_body, response.body) + + -- cgit From c177074649055f1da2ca97eb3c07139571d4a664 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 12:10:49 -0800 Subject: Implements basic OpenStack API client, ready to support API tests --- nova/tests/integrated/__init__.py | 20 +++ nova/tests/integrated/api/__init__.py | 20 +++ nova/tests/integrated/api/client.py | 224 ++++++++++++++++++++++++++++++++++ 3 files changed, 264 insertions(+) create mode 100644 nova/tests/integrated/__init__.py create mode 100644 nova/tests/integrated/api/__init__.py create mode 100644 nova/tests/integrated/api/client.py (limited to 'nova/tests') diff --git a/nova/tests/integrated/__init__.py b/nova/tests/integrated/__init__.py new file mode 100644 index 000000000..10e0a91d7 --- /dev/null +++ b/nova/tests/integrated/__init__.py @@ -0,0 +1,20 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Justin Santa Barbara +# +# 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. + +""" +:mod:`integrated` -- Tests whole systems, using mock services where needed +================================= +""" diff --git a/nova/tests/integrated/api/__init__.py b/nova/tests/integrated/api/__init__.py new file mode 100644 index 000000000..5798ab3d1 --- /dev/null +++ b/nova/tests/integrated/api/__init__.py @@ -0,0 +1,20 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Justin Santa Barbara +# +# 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. + +""" +:mod:`api` -- OpenStack API client, for testing rather than production +================================= +""" diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py new file mode 100644 index 000000000..5ab247fab --- /dev/null +++ b/nova/tests/integrated/api/client.py @@ -0,0 +1,224 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright (c) 2011 Justin Santa Barbara +# +# 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. + +import json +import httplib +import urlparse + +from nova import log as logging + + +LOG = logging.getLogger('nova.tests.api') + + +class OpenstackApiException(Exception): + def __init__(self, message=None, response=None): + self.response = response + if not message: + message = 'Unspecified error' + + if response: + _status = response.status + _body = response.read() + + message = _('%(message)s\nStatus Code: %(_status)s\n' + 'Body: %(_body)s') % locals() + + super(OpenstackApiException, self).__init__(message) + + +class OpenstackApiAuthenticationException(OpenstackApiException): + def __init__(self, response=None, message=None): + if not message: + message = _("Authentication error") + super(OpenstackApiAuthenticationException, self).__init__(message, + response) + + +class OpenstackApiNotFoundException(OpenstackApiException): + def __init__(self, response=None, message=None): + if not message: + message = _("Item not found") + super(OpenstackApiNotFoundException, self).__init__(message, response) + + +class TestOpenStackClient(object): + """ A really basic OpenStack API client that is under our control, + so we can make changes / insert hooks for testing""" + + def __init__(self, auth_user, auth_key, auth_uri): + super(TestOpenStackClient, self).__init__() + self.auth_result = None + self.auth_user = auth_user + self.auth_key = auth_key + self.auth_uri = auth_uri + + def request(self, url, method='GET', body=None, headers=None): + if headers is None: + headers = {} + + parsed_url = urlparse.urlparse(url) + port = parsed_url.port + hostname = parsed_url.hostname + scheme = parsed_url.scheme + + if scheme == 'http': + conn = httplib.HTTPConnection(hostname, + port=port) + elif scheme == 'https': + conn = httplib.HTTPSConnection(hostname, + port=port) + else: + raise OpenstackApiException("Unknown scheme: %s" % url) + + relative_url = parsed_url.path + if parsed_url.query: + relative_url = relative_url + parsed_url.query + LOG.info(_("Doing %(method)s on %(relative_url)s") % locals()) + if body: + LOG.info(_("Body: %s") % body) + + conn.request(method, relative_url, body, headers) + response = conn.getresponse() + return response + + def _authenticate(self): + if self.auth_result: + return self.auth_result + + headers = {'X-Auth-User': self.auth_user, + 'X-Auth-Key': self.auth_key} + response = self.request(self.auth_uri, + headers=headers) + if not response.status in [204]: + raise OpenstackApiAuthenticationException(response=response) + + auth_headers = {} + for k, v in response.getheaders(): + auth_headers[k] = v + + self.auth_result = auth_headers + return self.auth_result + + def api_request(self, relative_uri, check_response_status=None, **kwargs): + auth_result = self._authenticate() + + base_uri = auth_result['X-Server-Management-Url'] + full_uri = base_uri + relative_uri + + headers = kwargs.setdefault('headers', {}) + headers['X-Auth-Token'] = auth_result['X-Auth-Token'] + + LOG.debug(_("HTTP request on %s") % (relative_uri)) + + response = self.request(full_uri, **kwargs) + + LOG.debug(_("Response => code %s") % (response.status)) + + if check_response_status: + if not response.status in check_response_status: + if response.status == 404: + raise OpenstackApiNotFoundException(response=response) + else: + raise OpenstackApiException( + message=_("Unexpected status code"), + response=response) + + return response + + def _decode_json(self, response): + body = response.read() + LOG.debug(_("Decoding JSON: %s") % (body)) + return json.loads(body) + + def api_get(self, relative_uri, **kwargs): + kwargs.setdefault('check_response_status', [200]) + response = self.api_request(relative_uri, **kwargs) + return self._decode_json(response) + + def api_post(self, relative_uri, body, **kwargs): + kwargs['method'] = 'POST' + if body: + headers = kwargs.setdefault('headers', {}) + headers['Content-Type'] = 'application/json' + kwargs['body'] = json.dumps(body) + + kwargs.setdefault('check_response_status', [200]) + response = self.api_request(relative_uri, **kwargs) + return self._decode_json(response) + + def api_delete(self, relative_uri, **kwargs): + kwargs['method'] = 'DELETE' + kwargs.setdefault('check_response_status', [200, 202]) + return self.api_request(relative_uri, **kwargs) + + def get_keys_detail(self): + return self.api_get('/keys/detail')['keys'] + + def post_key(self, key): + return self.api_post('/keys', key)['key'] + + def delete_key(self, key_id): + return self.api_delete('/keys/%s' % key_id) + + def get_volume(self, volume_id): + return self.api_get('/volumes/%s' % volume_id)['volume'] + + def get_volumes_detail(self): + return self.api_get('/volumes/detail')['volumes'] + + def post_volume(self, volume): + return self.api_post('/volumes', volume)['volume'] + + def delete_volume(self, volume_id): + return self.api_delete('/volumes/%s' % volume_id) + + def get_server(self, server_id): + return self.api_get('/servers/%s' % server_id)['server'] + + def get_servers(self, detail=True): + rel_url = '/servers/detail' if detail else '/servers' + return self.api_get(rel_url)['servers'] + + def post_server(self, server): + return self.api_post('/servers', server)['server'] + + def delete_server(self, server_id): + return self.api_delete('/servers/%s' % server_id) + + def get_image(self, image_id): + return self.api_get('/images/%s' % image_id)['image'] + + def get_images_detail(self): + return self.api_get('/images/detail')['images'] + + def post_image(self, image): + return self.api_post('/images', image)['image'] + + def delete_image(self, image_id): + return self.api_delete('/images/%s' % image_id) + + def get_flavor(self, flavor_id): + return self.api_get('/flavors/%s' % flavor_id)['flavor'] + + def get_flavors_detail(self): + return self.api_get('/flavors/detail')['flavors'] + + def post_flavor(self, flavor): + return self.api_post('/flavors', flavor)['flavor'] + + def delete_flavor(self, flavor_id): + return self.api_delete('/flavors/%s' % flavor_id) -- cgit From 6b4beef8093b4a7b4d42818567b5afb023af9251 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 12:55:06 -0800 Subject: Don't wrap keys and volumes till they're in the API --- nova/tests/integrated/api/client.py | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 5ab247fab..8ec46b5ae 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -165,27 +165,6 @@ class TestOpenStackClient(object): kwargs.setdefault('check_response_status', [200, 202]) return self.api_request(relative_uri, **kwargs) - def get_keys_detail(self): - return self.api_get('/keys/detail')['keys'] - - def post_key(self, key): - return self.api_post('/keys', key)['key'] - - def delete_key(self, key_id): - return self.api_delete('/keys/%s' % key_id) - - def get_volume(self, volume_id): - return self.api_get('/volumes/%s' % volume_id)['volume'] - - def get_volumes_detail(self): - return self.api_get('/volumes/detail')['volumes'] - - def post_volume(self, volume): - return self.api_post('/volumes', volume)['volume'] - - def delete_volume(self, volume_id): - return self.api_delete('/volumes/%s' % volume_id) - def get_server(self, server_id): return self.api_get('/servers/%s' % server_id)['server'] -- cgit From f81d925f86670e3ed32d815c219824f627d82bc2 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 13:51:26 -0800 Subject: Better logging, be more careful about when we throw login errors re bug732866 --- nova/tests/integrated/api/client.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 8ec46b5ae..d424a6428 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -99,11 +99,18 @@ class TestOpenStackClient(object): if self.auth_result: return self.auth_result + auth_uri = self.auth_uri headers = {'X-Auth-User': self.auth_user, 'X-Auth-Key': self.auth_key} - response = self.request(self.auth_uri, + response = self.request(auth_uri, headers=headers) - if not response.status in [204]: + + http_status = response.status + LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals()) + + # Until bug732866 is fixed, we can't check this properly... + #if http_status == 401: + if http_status != 204: raise OpenstackApiAuthenticationException(response=response) auth_headers = {} @@ -116,21 +123,21 @@ class TestOpenStackClient(object): def api_request(self, relative_uri, check_response_status=None, **kwargs): auth_result = self._authenticate() - base_uri = auth_result['X-Server-Management-Url'] + #NOTE(justinsb): httplib 'helpfully' converts headers to lower case + base_uri = auth_result['x-server-management-url'] full_uri = base_uri + relative_uri headers = kwargs.setdefault('headers', {}) - headers['X-Auth-Token'] = auth_result['X-Auth-Token'] - - LOG.debug(_("HTTP request on %s") % (relative_uri)) + headers['X-Auth-Token'] = auth_result['x-auth-token'] response = self.request(full_uri, **kwargs) - - LOG.debug(_("Response => code %s") % (response.status)) + + http_status = response.status + LOG.debug(_("%(relative_uri)s => code %(http_status)s") % locals()) if check_response_status: - if not response.status in check_response_status: - if response.status == 404: + if not http_status in check_response_status: + if http_status == 404: raise OpenstackApiNotFoundException(response=response) else: raise OpenstackApiException( @@ -181,8 +188,9 @@ class TestOpenStackClient(object): def get_image(self, image_id): return self.api_get('/images/%s' % image_id)['image'] - def get_images_detail(self): - return self.api_get('/images/detail')['images'] + def get_images(self, detail=True): + rel_url = '/images/detail' if detail else '/images' + return self.api_get(rel_url)['images'] def post_image(self, image): return self.api_post('/images', image)['image'] @@ -193,8 +201,9 @@ class TestOpenStackClient(object): def get_flavor(self, flavor_id): return self.api_get('/flavors/%s' % flavor_id)['flavor'] - def get_flavors_detail(self): - return self.api_get('/flavors/detail')['flavors'] + def get_flavors(self, detail=True): + rel_url = '/flavors/detail' if detail else '/flavors' + return self.api_get(rel_url)['flavors'] def post_flavor(self, flavor): return self.api_post('/flavors', flavor)['flavor'] -- cgit From 998975651ac2f2df7a3f8af16d62d197f451180f Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 13:53:27 -0800 Subject: Test login. Uncovered bug732866 --- nova/tests/integrated/integrated_helpers.py | 182 ++++++++++++++++++++++++++++ nova/tests/integrated/test_login.py | 77 ++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 nova/tests/integrated/integrated_helpers.py create mode 100644 nova/tests/integrated/test_login.py (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py new file mode 100644 index 000000000..691ead6e1 --- /dev/null +++ b/nova/tests/integrated/integrated_helpers.py @@ -0,0 +1,182 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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. + +""" +Provides common functionality for integrated unit tests +""" + +import random +import string + +from nova import exception +from nova import flags +from nova import service +from nova import test # For the flags +from nova.auth import manager +from nova.exception import Error +from nova.log import logging +from nova.tests.integrated.api import client + + +FLAGS = flags.FLAGS + +LOG = logging.getLogger('nova.tests.integrated') + + +def generate_random_alphanumeric(length): + """Creates a random alphanumeric string of specified length""" + return ''.join(random.choice(string.ascii_uppercase + string.digits) + for _x in range(length)) + + +def generate_random_numeric(length): + """Creates a random numeric string of specified length""" + return ''.join(random.choice(string.digits) + for _x in range(length)) + + +def generate_new_element(items, prefix, numeric=False): + """Creates a random string with prefix, that is not in 'items' list""" + while True: + if numeric: + candidate = prefix + generate_random_numeric(8) + else: + candidate = prefix + generate_random_alphanumeric(8) + if not candidate in items: + return candidate + print "Random collision on %s" % candidate + + +class TestUser(object): + def __init__(self, name, secret, auth_url): + self.name = name + self.secret = secret + self.auth_url = auth_url + + if not auth_url: + raise exception.Error("auth_url is required") + self.openstack_api = client.TestOpenStackClient(self.name, + self.secret, + self.auth_url) + + +class IntegratedUnitTestContext(object): + __INSTANCE = None + + def __init__(self): + self.auth_manager = manager.AuthManager() + + self.wsgi_server = None + self.wsgi_apps = [] + self.api_service = None + + self.services = [] + self.auth_url = None + self.project_name = None + + self.setup() + + def setup(self): + self._start_services() + + self._create_test_user() + + def _create_test_user(self): + self.test_user = self._create_unittest_user() + + # No way to currently pass this through the OpenStack API + self.project_name = 'openstack' + self._configure_project(self.project_name, self.test_user) + + def _start_services(self): + # WSGI shutdown broken :-( + if not self.api_service: + self._start_api_service() + + def cleanup(self): + for service in self.services: + service.kill() + self.services = [] + # TODO(justinsb): Shutdown WSGI & anything else we startup + # WSGI shutdown broken :-( + # self.wsgi_server.terminate() + # self.wsgi_server = None + self.test_user = None + + def _create_unittest_user(self): + users = self.auth_manager.get_users() + user_names = [user.name for user in users] + auth_name = generate_new_element(user_names, 'unittest_user_') + auth_key = generate_random_alphanumeric(16) + + # Right now there's a bug where auth_name and auth_key are reversed + auth_key = auth_name + + self.auth_manager.create_user(auth_name, auth_name, auth_key, False) + return TestUser(auth_name, auth_key, self.auth_url) + + def _configure_project(self, project_name, user): + projects = self.auth_manager.get_projects() + project_names = [project.name for project in projects] + if not project_name in project_names: + project = self.auth_manager.create_project(project_name, + user.name, + description=None, + member_users=None) + else: + self.auth_manager.add_to_project(user.name, project_name) + + def _start_api_service(self): + api_service = service.ApiService.create() + api_service.start() + + if not api_service: + raise Exception("API Service was None") + + # WSGI shutdown broken :-( + #self.services.append(volume_service) + self.api_service = api_service + + self.auth_url = 'http://localhost:8774/v1.0' + + return api_service + + # WSGI shutdown broken :-( + #@staticmethod + #def get(): + # if not IntegratedUnitTestContext.__INSTANCE: + # IntegratedUnitTestContext.startup() + # #raise Error("Must call IntegratedUnitTestContext::startup") + # return IntegratedUnitTestContext.__INSTANCE + + @staticmethod + def startup(): + # Because WSGI shutdown is broken at the moment, we have to recycle + if IntegratedUnitTestContext.__INSTANCE: + #raise Error("Multiple calls to IntegratedUnitTestContext.startup") + IntegratedUnitTestContext.__INSTANCE.setup() + else: + IntegratedUnitTestContext.__INSTANCE = IntegratedUnitTestContext() + return IntegratedUnitTestContext.__INSTANCE + + @staticmethod + def shutdown(): + if not IntegratedUnitTestContext.__INSTANCE: + raise Error("Must call IntegratedUnitTestContext::startup") + IntegratedUnitTestContext.__INSTANCE.cleanup() + # WSGI shutdown broken :-( + #IntegratedUnitTestContext.__INSTANCE = None diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py new file mode 100644 index 000000000..990dcaaf4 --- /dev/null +++ b/nova/tests/integrated/test_login.py @@ -0,0 +1,77 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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. + +import unittest + +from nova import flags +from nova.log import logging +from nova.tests.integrated import integrated_helpers +from nova.tests.integrated.api import client + +LOG = logging.getLogger('nova.tests.integrated') + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +class LoginTest(unittest.TestCase): + def setUp(self): + super(LoginTest, self).setUp() + context = integrated_helpers.IntegratedUnitTestContext.startup() + self.user = context.test_user + self.api = self.user.openstack_api + + def tearDown(self): + integrated_helpers.IntegratedUnitTestContext.shutdown() + super(LoginTest, self).tearDown() + + def test_login(self): + """Simple check - we list flavors - so we know we're logged in""" + flavors = self.api.get_flavors() + for flavor in flavors: + LOG.debug(_("flavor: %s") % flavor) + + def test_bad_login_password(self): + """Test that I get a 401 with a bad username""" + bad_credentials_api = client.TestOpenStackClient(self.user.name, + "notso_password", + self.user.auth_url) + + self.assertRaises(client.OpenstackApiAuthenticationException, + bad_credentials_api.get_flavors) + + def test_bad_login_username(self): + """Test that I get a 401 with a bad password""" + bad_credentials_api = client.TestOpenStackClient("notso_username", + self.user.secret, + self.user.auth_url) + + self.assertRaises(client.OpenstackApiAuthenticationException, + bad_credentials_api.get_flavors) + + + def test_bad_login_both_bad(self): + """Test that I get a 401 with both bad username and bad password""" + bad_credentials_api = client.TestOpenStackClient("notso_username", + "notso_password", + self.user.auth_url) + + self.assertRaises(client.OpenstackApiAuthenticationException, + bad_credentials_api.get_flavors) + +if __name__ == "__main__": + unittest.main() -- cgit From f110e718807ea4747a0ff95138c488961257aa7f Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 13:56:24 -0800 Subject: pep8 fun --- nova/tests/integrated/api/client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index d424a6428..da8d87e07 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -104,7 +104,7 @@ class TestOpenStackClient(object): 'X-Auth-Key': self.auth_key} response = self.request(auth_uri, headers=headers) - + http_status = response.status LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals()) @@ -131,7 +131,7 @@ class TestOpenStackClient(object): headers['X-Auth-Token'] = auth_result['x-auth-token'] response = self.request(full_uri, **kwargs) - + http_status = response.status LOG.debug(_("%(relative_uri)s => code %(http_status)s") % locals()) -- cgit From 3d6430ecd114daa21c72c3d215daaa94f0e87e62 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 14:12:41 -0800 Subject: Re-removed the code that was deleted upstream but somehow didn't get merged in. Bizarre! --- nova/tests/integrated/api/client.py | 21 --------------------- 1 file changed, 21 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 0ce480ae7..da8d87e07 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -172,27 +172,6 @@ class TestOpenStackClient(object): kwargs.setdefault('check_response_status', [200, 202]) return self.api_request(relative_uri, **kwargs) - def get_keys_detail(self): - return self.api_get('/keys/detail')['keys'] - - def post_key(self, key): - return self.api_post('/keys', key)['key'] - - def delete_key(self, key_id): - return self.api_delete('/keys/%s' % key_id) - - def get_volume(self, volume_id): - return self.api_get('/volumes/%s' % volume_id)['volume'] - - def get_volumes_detail(self): - return self.api_get('/volumes/detail')['volumes'] - - def post_volume(self, volume): - return self.api_post('/volumes', volume)['volume'] - - def delete_volume(self, volume_id): - return self.api_delete('/volumes/%s' % volume_id) - def get_server(self, server_id): return self.api_get('/servers/%s' % server_id)['server'] -- cgit From 29bc4f5074ca3ada98a25a745077b998b4c5509c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 14:14:01 -0800 Subject: Pep8 / Style --- nova/tests/integrated/test_login.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index 990dcaaf4..e362f92d6 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -22,6 +22,7 @@ from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client + LOG = logging.getLogger('nova.tests.integrated') FLAGS = flags.FLAGS @@ -63,7 +64,6 @@ class LoginTest(unittest.TestCase): self.assertRaises(client.OpenstackApiAuthenticationException, bad_credentials_api.get_flavors) - def test_bad_login_both_bad(self): """Test that I get a 401 with both bad username and bad password""" bad_credentials_api = client.TestOpenStackClient("notso_username", -- cgit From be66b329d5b94ffbfb782355ef342eadbaed72a5 Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Thu, 10 Mar 2011 22:14:53 +0000 Subject: Fix a fer nits jaypipes found in review. --- nova/tests/api/openstack/test_accounts.py | 6 +++--- nova/tests/api/openstack/test_auth.py | 15 ++++----------- nova/tests/api/openstack/test_users.py | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 746f02f57..78fceb47c 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -14,9 +14,10 @@ # under the License. +import json + import stubout import webob -import json import nova.api import nova.api.openstack.auth @@ -47,8 +48,7 @@ class AccountsTest(test.TestCase): fake_init) self.stubs.Set(nova.api.openstack.accounts.Controller, '_check_admin', fake_admin_check) - fakes.FakeAuthManager.auth_data = {} - fakes.FakeAuthManager.projects = {} + fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 49f90879d..437a79ec5 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,9 +51,7 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) - f.create_project('test', u) + f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' @@ -67,9 +65,7 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) - f.create_project('test', u) + f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' @@ -86,7 +82,7 @@ class Test(test.TestCase): token = result.headers['X-Auth-Token'] self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter) - req = webob.Request.blank('/v1.0/test/fake') + req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '200 OK') @@ -180,9 +176,6 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) - f.create_project('test', u) f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) req = webob.Request.blank('/v1.0/') @@ -194,7 +187,7 @@ class TestLimiter(test.TestCase): token = result.headers['X-Auth-Token'] self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter) - req = webob.Request.blank('/v1.0/test/fake') + req = webob.Request.blank'/v1.0/fake') req.method = 'POST' req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index 14c7897f0..1edefe713 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -13,10 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +import json import stubout import webob -import json import nova.api import nova.api.openstack.auth -- cgit From f251ef70bf83eebce0f851f8a1b052174be1d615 Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Thu, 10 Mar 2011 22:20:51 +0000 Subject: fix minor typo --- nova/tests/api/openstack/test_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 437a79ec5..ff8d42a14 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -187,7 +187,7 @@ class TestLimiter(test.TestCase): token = result.headers['X-Auth-Token'] self.stubs.Set(nova.api.openstack, 'APIRouter', fakes.FakeRouter) - req = webob.Request.blank'/v1.0/fake') + req = webob.Request.blank('/v1.0/fake') req.method = 'POST' req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) -- cgit From 0d3e950ed4b0c8abbd619d4ac8724b4c3ce45bf1 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 10 Mar 2011 14:21:36 -0800 Subject: Document known bug numbers by the code which is degraded until the bugs are fixed --- nova/tests/integrated/api/client.py | 1 + nova/tests/integrated/integrated_helpers.py | 6 ++++++ 2 files changed, 7 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index da8d87e07..6fba2930a 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -109,6 +109,7 @@ class TestOpenStackClient(object): LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals()) # Until bug732866 is fixed, we can't check this properly... + # bug732866 #if http_status == 401: if http_status != 204: raise OpenstackApiAuthenticationException(response=response) diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 691ead6e1..47093636e 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -104,6 +104,7 @@ class IntegratedUnitTestContext(object): def _start_services(self): # WSGI shutdown broken :-( + # bug731668 if not self.api_service: self._start_api_service() @@ -112,6 +113,7 @@ class IntegratedUnitTestContext(object): service.kill() self.services = [] # TODO(justinsb): Shutdown WSGI & anything else we startup + # bug731668 # WSGI shutdown broken :-( # self.wsgi_server.terminate() # self.wsgi_server = None @@ -124,6 +126,7 @@ class IntegratedUnitTestContext(object): auth_key = generate_random_alphanumeric(16) # Right now there's a bug where auth_name and auth_key are reversed + # bug732907 auth_key = auth_name self.auth_manager.create_user(auth_name, auth_name, auth_key, False) @@ -156,6 +159,7 @@ class IntegratedUnitTestContext(object): return api_service # WSGI shutdown broken :-( + # bug731668 #@staticmethod #def get(): # if not IntegratedUnitTestContext.__INSTANCE: @@ -166,6 +170,7 @@ class IntegratedUnitTestContext(object): @staticmethod def startup(): # Because WSGI shutdown is broken at the moment, we have to recycle + # bug731668 if IntegratedUnitTestContext.__INSTANCE: #raise Error("Multiple calls to IntegratedUnitTestContext.startup") IntegratedUnitTestContext.__INSTANCE.setup() @@ -179,4 +184,5 @@ class IntegratedUnitTestContext(object): raise Error("Must call IntegratedUnitTestContext::startup") IntegratedUnitTestContext.__INSTANCE.cleanup() # WSGI shutdown broken :-( + # bug731668 #IntegratedUnitTestContext.__INSTANCE = None -- cgit From 7e95a65ccec2336176f389d614a85c9e70da374d Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Thu, 10 Mar 2011 22:33:45 +0000 Subject: re-added a test change I removed thinking it was related to removed code. It wasn't :> --- nova/tests/api/openstack/test_auth.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index ff8d42a14..aaaa4e415 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -65,7 +65,9 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + u = nova.auth.manager.User(1, 'herp', None, None, None) + f.add_user('derp', u) + f.create_project('test', u) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'herp' @@ -176,7 +178,9 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + u = nova.auth.manager.User(1, 'herp', None, None, None) + f.add_user('derp', u) + f.create_project('test', u) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' -- cgit From c967679fa8144af57d79d89666ee29a0241d38a9 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 10 Mar 2011 17:36:41 -0500 Subject: switch to a more consistent usage of onset_files variable names --- nova/tests/api/openstack/test_servers.py | 48 ++++++++++++------------- nova/tests/test_quota.py | 60 ++++++++++++++++---------------- 2 files changed, 54 insertions(+), 54 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 0561ad499..b6d88d833 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -833,13 +833,13 @@ class TestServerInstanceCreation(test.TestCase): class MockComputeAPI(object): def __init__(self): - self.personality_files = None + self.onset_files = None def create(self, *args, **kwargs): - if 'personality_files' in kwargs: - self.personality_files = kwargs['personality_files'] + if 'onset_files' in kwargs: + self.onset_files = kwargs['onset_files'] else: - self.personality_files = None + self.onset_files = None return [{'id': '1234', 'display_name': 'fakeinstance'}] def set_admin_password(self, *args, **kwargs): @@ -919,46 +919,46 @@ class TestServerInstanceCreation(test.TestCase): request = self._get_create_request_json(body_dict) compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.personality_files + return request, response, compute_api.onset_files def _create_instance_with_personality_xml(self, personality): body_dict = self._create_personality_request_dict(personality) request = self._get_create_request_xml(body_dict) compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.personality_files + return request, response, compute_api.onset_files def test_create_instance_with_no_personality(self): - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_json(personality=None) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, []) + self.assertEquals(onset_files, []) def test_create_instance_with_no_personality_xml(self): - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_xml(personality=None) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, []) + self.assertEquals(onset_files, []) def test_create_instance_with_personality(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) personality = [(path, b64contents)] - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) + self.assertEquals(onset_files, [(path, contents)]) def test_create_instance_with_personality_xml(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) personality = [(path, b64contents)] - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_xml(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) + self.assertEquals(onset_files, [(path, contents)]) def test_create_instance_with_personality_no_path(self): personality = [('/remove/this/path', @@ -969,7 +969,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) + self.assertEquals(compute_api.onset_files, None) def _test_create_instance_with_personality_no_path_xml(self): personality = [('/remove/this/path', @@ -980,7 +980,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) + self.assertEquals(compute_api.onset_files, None) def test_create_instance_with_personality_no_contents(self): personality = [('/test/path', @@ -991,7 +991,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) + self.assertEquals(compute_api.onset_files, None) def test_create_instance_with_personality_not_a_list(self): personality = [('/test/path', base64.b64encode('test\ncontents\n'))] @@ -1002,16 +1002,16 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.personality_files, None) + self.assertEquals(compute_api.onset_files, None) def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' personality = [(path, contents)] - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 400) - self.assertEquals(personality_files, None) + self.assertEquals(onset_files, None) def test_create_instance_with_three_personalities(self): files = [ @@ -1022,19 +1022,19 @@ class TestServerInstanceCreation(test.TestCase): personality = [] for path, content in files: personality.append((path, base64.b64encode(content))) - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, files) + self.assertEquals(onset_files, files) def test_create_instance_personality_empty_content(self): path = '/my/file/path' contents = '' personality = [(path, contents)] - request, response, personality_files = \ + request, response, onset_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(personality_files, [(path, contents)]) + self.assertEquals(onset_files, [(path, contents)]) def test_create_instance_admin_pass_json(self): request, response, dummy = \ diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 86b1d40fb..d94381aa2 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -200,66 +200,66 @@ class QuotaTestCase(test.TestCase): image_id='fake', metadata=metadata) - def test_allowed_personality_files(self): + def test_allowed_onset_files(self): self.assertEqual( - quota.allowed_personality_files(self.context), - FLAGS.quota_personality_max_files) + quota.allowed_onset_files(self.context), + FLAGS.quota_max_onset_files) - def _create_with_personality(self, files): + def _create_with_onset_files(self, files): api = compute.API(image_service=self.StubImageService()) api.create(self.context, min_count=1, max_count=1, instance_type='m1.small', image_id='fake', - personality_files=files) + onset_files=files) - def test_no_personality_files(self): + def test_no_onset_files(self): api = compute.API(image_service=self.StubImageService()) api.create(self.context, instance_type='m1.small', image_id='fake') - def test_max_personality_files(self): + def test_max_onset_files(self): files = [] - for i in xrange(FLAGS.quota_personality_max_files): + for i in xrange(FLAGS.quota_max_onset_files): files.append(('/my/path%d' % i, 'config = test\n')) - self._create_with_personality(files) # no QuotaError + self._create_with_onset_files(files) # no QuotaError - def test_too_many_personality_files(self): + def test_too_many_onset_files(self): files = [] - for i in xrange(FLAGS.quota_personality_max_files + 1): + for i in xrange(FLAGS.quota_max_onset_files + 1): files.append(('/my/path%d' % i, 'my\ncontent%d\n' % i)) self.assertRaises(quota.QuotaError, - self._create_with_personality, files) + self._create_with_onset_files, files) - def test_allowed_personality_content_bytes(self): + def test_allowed_onset_file_content_bytes(self): self.assertEqual( - quota.allowed_personality_content_bytes(self.context), - FLAGS.quota_personality_max_content_bytes) + quota.allowed_onset_file_content_bytes(self.context), + FLAGS.quota_max_onset_file_content_bytes) - def test_max_personality_content_bytes(self): - max = FLAGS.quota_personality_max_content_bytes + def test_max_onset_file_content_bytes(self): + max = FLAGS.quota_max_onset_file_content_bytes content = ''.join(['a' for i in xrange(max)]) files = [('/test/path', content)] - self._create_with_personality(files) # no QuotaError + self._create_with_onset_files(files) # no QuotaError - def test_too_many_personality_content_bytes(self): - max = FLAGS.quota_personality_max_content_bytes + def test_too_many_onset_file_content_bytes(self): + max = FLAGS.quota_max_onset_file_content_bytes content = ''.join(['a' for i in xrange(max + 1)]) files = [('/test/path', content)] self.assertRaises(quota.QuotaError, - self._create_with_personality, files) + self._create_with_onset_files, files) - def test_allowed_personality_path_bytes(self): + def test_allowed_onset_file_path_bytes(self): self.assertEqual( - quota.allowed_personality_path_bytes(self.context), - FLAGS.quota_personality_max_path_bytes) + quota.allowed_onset_file_path_bytes(self.context), + FLAGS.quota_max_onset_file_path_bytes) - def test_max_personality_path_bytes(self): - max = FLAGS.quota_personality_max_path_bytes + def test_max_onset_file_path_bytes(self): + max = FLAGS.quota_max_onset_file_path_bytes path = ''.join(['a' for i in xrange(max)]) files = [(path, 'config = quotatest')] - self._create_with_personality(files) # no QuotaError + self._create_with_onset_files(files) # no QuotaError - def test_too_many_personality_path_bytes(self): - max = FLAGS.quota_personality_max_path_bytes + def test_too_many_onset_file_path_bytes(self): + max = FLAGS.quota_max_onset_file_path_bytes path = ''.join(['a' for i in xrange(max + 1)]) files = [(path, 'config = quotatest')] self.assertRaises(quota.QuotaError, - self._create_with_personality, files) + self._create_with_onset_files, files) -- cgit From 67a8d635af0a64ad220b163c00b96eadf7daf93f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 11 Mar 2011 09:54:08 +0100 Subject: Make Authors check account for tests being run with different os.getcwd() depending on how they're run. Add missing people to Authors. --- nova/tests/test_misc.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index a658e4978..1fbaf304f 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -24,18 +24,19 @@ from nova.utils import parse_mailmap, str_dict_replace, synchronized class ProjectTestCase(test.TestCase): def test_authors_up_to_date(self): - if os.path.exists('.bzr'): + topdir = os.path.normpath(os.path.dirname(__file__) + '/../../') + if os.path.exists(os.path.join(topdir, '.bzr')): contributors = set() - mailmap = parse_mailmap('.mailmap') + mailmap = parse_mailmap(os.path.join(topdir, '.mailmap')) import bzrlib.workingtree - tree = bzrlib.workingtree.WorkingTree.open('.') + tree = bzrlib.workingtree.WorkingTree.open(topdir) tree.lock_read() try: parents = tree.get_parent_ids() g = tree.branch.repository.get_graph() - for p in parents[1:]: + for p in parents: rev_ids = [r for r, _ in g.iter_ancestry(parents) if r != "null:"] revs = tree.branch.repository.get_revisions(rev_ids) @@ -44,7 +45,8 @@ class ProjectTestCase(test.TestCase): email = author.split(' ')[-1] contributors.add(str_dict_replace(email, mailmap)) - authors_file = open('Authors', 'r').read() + authors_file = open(os.path.join(topdir, 'Authors'), + 'r').read() missing = set() for contributor in contributors: -- cgit From 977fc1be4ea8af93b63975c5538462a776fbe168 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Fri, 11 Mar 2011 11:42:42 +0000 Subject: Moved vlan_interface flag in network.manager removed needless carriage return in vm_ops --- nova/tests/test_xenapi.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 7f437c2b8..0f3b9ce20 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -38,6 +38,8 @@ from nova.tests.db import fakes as db_fakes from nova.tests.xenapi import stubs from nova.tests.glance import stubs as glance_stubs +from nova import log as LOG + FLAGS = flags.FLAGS @@ -297,6 +299,16 @@ class XenAPIVMTestCase(test.TestCase): glance_stubs.FakeGlance.IMAGE_KERNEL, glance_stubs.FakeGlance.IMAGE_RAMDISK) + def test_spawn_vlanmanager(self): + self.flags(xenapi_image_service = 'glance', + network_manager='nova.network.manager.VlanManager', + network_driver='nova.network.xenapi_net') + LOG.debug("Self.network:%s",self.network) + self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, + glance_stubs.FakeGlance.IMAGE_KERNEL, + glance_stubs.FakeGlance.IMAGE_RAMDISK) + pass + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) -- cgit From a5415e8fc40eaa82761532e5ba83c3800cf9ed78 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Fri, 11 Mar 2011 12:45:53 -0500 Subject: Need to set version to '1.0' in the nova.context in test code for tests to be happy. --- nova/tests/api/openstack/fakes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 2c4e57246..8ec1629f4 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -68,7 +68,7 @@ def fake_auth_init(self, application): @webob.dec.wsgify def fake_wsgi(self, req): - req.environ['nova.context'] = context.RequestContext(1, 1) + req.environ['nova.context'] = context.RequestContext(1, 1, version='1.0') if req.body: req.environ['inst_dict'] = json.loads(req.body) return self.application -- cgit From 7d4eae131f2f844f368aa5ff79c68191756775b6 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Fri, 11 Mar 2011 14:33:12 -0500 Subject: Add config for osapi_extensions_path. Update the ExtensionManager so that it loads extensions in the osapi_extensions_path. --- nova/tests/api/openstack/extensions/widgets.py | 27 ++++++++++++++++++++++++++ nova/tests/api/openstack/test_extensions.py | 19 ++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 nova/tests/api/openstack/extensions/widgets.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py new file mode 100644 index 000000000..bc0947223 --- /dev/null +++ b/nova/tests/api/openstack/extensions/widgets.py @@ -0,0 +1,27 @@ +from nova import wsgi + +class WidgetController(wsgi.Controller): + + def index(self, req): + return "Buy more widgets!" + +class WidgetExtensionResource(object): + + def __init__(self): + pass + + def add_routes(self, mapper): + mapper.resource('widget', 'widgets', controller=WidgetController()) + + +class WidgetExtension(object): + + def __init__(self): + pass + + def get_resources(self): + return WidgetExtensionResource() + + +def get_extension(): + return WidgetExtension() diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index f5332c84a..ff41d6d99 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -16,12 +16,16 @@ # under the License. import unittest +import os.path import webob +from nova import flags from nova.api import openstack import nova.wsgi +FLAGS = flags.FLAGS + class StubController(nova.wsgi.Controller): def __init__(self, body): @@ -81,3 +85,18 @@ class ExtensionTest(unittest.TestCase): self.assertEqual(response_body, response.body) +class ExtensionManagerTest(unittest.TestCase): + + def setUp(self): + FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), + "extensions") + + def test_get_resources(self): + router = openstack.APIRouter() + request = webob.Request.blank("/widgets") + response = request.get_response(router) + self.assertEqual(200, response.status_int) + self.assertEqual("Buy more widgets!", response.body) + + + -- cgit From 6cd90a95d632d45d1c906d412e3240f730e88b95 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Fri, 11 Mar 2011 15:35:55 -0600 Subject: New migration --- nova/tests/test_compute.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 643b2e93a..3d25a8997 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -299,5 +299,3 @@ class ComputeTestCase(test.TestCase): self.assertRaises(exception.Error, self.compute.prep_resize, self.context, instance_id) self.compute.terminate_instance(self.context, instance_id) - type = instance_types.get_by_flavor_id("1") - self.assertEqual(type, 'm1.tiny') -- cgit From be9734b03bce871d32e21da2ba341dfa42aa020a Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 11 Mar 2011 17:19:14 -0500 Subject: Fixed lp732866 by catching relevant `exception.NotFound` exception. Tests did not uncover this vulnerability due to "incorrect" FakeAuthManager. I say "incorrect" because potentially different implementations (LDAP or Database driven) of AuthManager might return different errors from `get_user_from_access_key`. Also, removed all references to 'bacon', 'ham', 'herp', and 'derp' and replaced them with hopefully more helpful terms. --- nova/tests/api/openstack/fakes.py | 5 +++- nova/tests/api/openstack/test_auth.py | 56 +++++++++++++++++++++-------------- 2 files changed, 38 insertions(+), 23 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index e50d11a3d..7cb974bb2 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -321,7 +321,10 @@ class FakeAuthManager(object): (user.id == p.project_manager_id)] def get_user_from_access_key(self, key): - return FakeAuthManager.auth_data.get(key, None) + try: + return FakeAuthManager.auth_data[key] + except KeyError: + raise exc.NotFound class FakeRateLimiter(object): diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index aaaa4e415..d1b3c0e10 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,11 +51,12 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + f.add_user('user1_key', + nova.auth.manager.User(1, 'user1', None, None, None)) req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-User'] = 'herp' - req.headers['X-Auth-Key'] = 'derp' + req.headers['X-Auth-User'] = 'user1' + req.headers['X-Auth-Key'] = 'user1_key' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) @@ -65,13 +66,13 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) - f.create_project('test', u) + u = nova.auth.manager.User(1, 'user1', None, None, None) + f.add_user('user1_key', u) + f.create_project('user1_project', u) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) - req.headers['X-Auth-User'] = 'herp' - req.headers['X-Auth-Key'] = 'derp' + req.headers['X-Auth-User'] = 'user1' + req.headers['X-Auth-Key'] = 'user1_key' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '204 No Content') self.assertEqual(len(result.headers['X-Auth-Token']), 40) @@ -92,7 +93,7 @@ class Test(test.TestCase): def test_token_expiry(self): self.destroy_called = False - token_hash = 'bacon' + token_hash = 'token_hash' def destroy_token_mock(meh, context, token): self.destroy_called = True @@ -109,15 +110,26 @@ class Test(test.TestCase): bad_token) req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-Token'] = 'bacon' + req.headers['X-Auth-Token'] = 'token_hash' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '401 Unauthorized') self.assertEqual(self.destroy_called, True) - def test_bad_user(self): + def test_bad_user_bad_key(self): + req = webob.Request.blank('/v1.0/') + req.headers['X-Auth-User'] = 'unknown_user' + req.headers['X-Auth-Key'] = 'unknown_user_key' + result = req.get_response(fakes.wsgi_app()) + self.assertEqual(result.status, '401 Unauthorized') + + def test_bad_user_good_key(self): + f = fakes.FakeAuthManager() + u = nova.auth.manager.User(1, 'user1', None, None, None) + f.add_user('user1_key', u) + req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-User'] = 'herp' - req.headers['X-Auth-Key'] = 'derp' + req.headers['X-Auth-User'] = 'unknown_user' + req.headers['X-Auth-Key'] = 'user1_key' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '401 Unauthorized') @@ -128,7 +140,7 @@ class Test(test.TestCase): def test_bad_token(self): req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-Token'] = 'baconbaconbacon' + req.headers['X-Auth-Token'] = 'unknown_token' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '401 Unauthorized') @@ -137,11 +149,11 @@ class TestFunctional(test.TestCase): def test_token_expiry(self): ctx = context.get_admin_context() tok = db.auth_token_create(ctx, dict( - token_hash='bacon', + token_hash='test_token_hash', cdn_management_url='', server_management_url='', storage_url='', - user_id='ham', + user_id='user1', )) db.auth_token_update(ctx, tok.token_hash, dict( @@ -149,13 +161,13 @@ class TestFunctional(test.TestCase): )) req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-Token'] = 'bacon' + req.headers['X-Auth-Token'] = 'test_token_hash' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '401 Unauthorized') def test_token_doesnotexist(self): req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-Token'] = 'ham' + req.headers['X-Auth-Token'] = 'nonexistant_token_hash' result = req.get_response(fakes.wsgi_app()) self.assertEqual(result.status, '401 Unauthorized') @@ -178,13 +190,13 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) + u = nova.auth.manager.User(1, 'user1', None, None, None) + f.add_user('user1_key', u) f.create_project('test', u) req = webob.Request.blank('/v1.0/') - req.headers['X-Auth-User'] = 'herp' - req.headers['X-Auth-Key'] = 'derp' + req.headers['X-Auth-User'] = 'user1' + req.headers['X-Auth-Key'] = 'user1_key' result = req.get_response(fakes.wsgi_app()) self.assertEqual(len(result.headers['X-Auth-Token']), 40) -- cgit From 5d0ca375e082c702b218c26f24d8009650a319a3 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 11 Mar 2011 14:36:31 -0800 Subject: Beginning of cleanup of FakeAuthManager --- nova/tests/api/openstack/fakes.py | 41 +++++++++++++++++-------------- nova/tests/api/openstack/test_accounts.py | 4 +-- nova/tests/api/openstack/test_auth.py | 14 +++++------ nova/tests/api/openstack/test_users.py | 14 +++++------ 4 files changed, 38 insertions(+), 35 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index e50d11a3d..52ac80e3f 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -228,12 +228,14 @@ class FakeAuthDatabase(object): class FakeAuthManager(object): - auth_data = {} + #NOTE(justinsb): Accessing static variables through instances is FUBAR + #NOTE(justinsb): This should also be private! + auth_data = [] projects = {} @classmethod def clear_fakes(cls): - cls.auth_data = {} + cls.auth_data = [] cls.projects = {} @classmethod @@ -246,34 +248,40 @@ class FakeAuthManager(object): 'test', [])) - def add_user(self, key, user): - FakeAuthManager.auth_data[key] = user + def add_user(self, user): + FakeAuthManager.auth_data.append(user) def get_users(self): - return FakeAuthManager.auth_data.values() + return FakeAuthManager.auth_data def get_user(self, uid): - for k, v in FakeAuthManager.auth_data.iteritems(): - if v.id == uid: - return v + for u in FakeAuthManager.auth_data: + if u.id == uid: + return u + return None + + def get_user_from_access_key(self, key): + for u in FakeAuthManager.auth_data: + if u.access == key: + return u return None def delete_user(self, uid): - for k, v in FakeAuthManager.auth_data.items(): - if v.id == uid: - del FakeAuthManager.auth_data[k] + for u in FakeAuthManager.auth_data: + if u.id == uid: + FakeAuthManager.auth_data.remove(u) return None def create_user(self, name, access=None, secret=None, admin=False): u = User(name, name, access, secret, admin) - FakeAuthManager.auth_data[access] = u + FakeAuthManager.auth_data.append(u) return u def modify_user(self, user_id, access=None, secret=None, admin=None): user = None - for k, v in FakeAuthManager.auth_data.iteritems(): - if v.id == user_id: - user = v + for u in FakeAuthManager.auth_data: + if u.id == user_id: + user = u if user: user.access = access user.secret = secret @@ -320,9 +328,6 @@ class FakeAuthManager(object): if (user.id in p.member_ids) or (user.id == p.project_manager_id)] - def get_user_from_access_key(self, key): - return FakeAuthManager.auth_data.get(key, None) - class FakeRateLimiter(object): def __init__(self, application): diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 60edce769..1bf49b33b 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -59,8 +59,8 @@ class AccountsTest(test.TestCase): fakemgr = fakes.FakeAuthManager() joeuser = User('guy1', 'guy1', 'acc1', 'fortytwo!', False) superuser = User('guy2', 'guy2', 'acc2', 'swordfish', True) - fakemgr.add_user(joeuser.access, joeuser) - fakemgr.add_user(superuser.access, superuser) + fakemgr.add_user(joeuser) + fakemgr.add_user(superuser) fakemgr.create_project('test1', joeuser) fakemgr.create_project('test2', superuser) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index aaaa4e415..84222f0f1 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -39,7 +39,7 @@ class Test(test.TestCase): self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) self.stubs.Set(context, 'RequestContext', fakes.FakeRequestContext) - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthDatabase.data = {} fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_networking(self.stubs) @@ -51,7 +51,7 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user('derp', nova.auth.manager.User(1, 'herp', None, None, None)) + f.add_user(nova.auth.manager.User(1, 'herp', 'derp', None, None)) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'herp' @@ -65,8 +65,8 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) + u = nova.auth.manager.User(1, 'herp', 'derp', None, None) + f.add_user(u) f.create_project('test', u) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) @@ -167,7 +167,7 @@ class TestLimiter(test.TestCase): self.stubs.Set(nova.api.openstack.auth.AuthMiddleware, '__init__', fakes.fake_auth_init) self.stubs.Set(context, 'RequestContext', fakes.FakeRequestContext) - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthDatabase.data = {} fakes.stub_out_networking(self.stubs) @@ -178,8 +178,8 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'herp', None, None, None) - f.add_user('derp', u) + u = nova.auth.manager.User(1, 'herp', 'derp', None, None) + f.add_user(u) f.create_project('test', u) req = webob.Request.blank('/v1.0/') diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index 2dda4319b..a62db7efc 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -47,7 +47,7 @@ class UsersTest(test.TestCase): fake_init) self.stubs.Set(nova.api.openstack.users.Controller, '_check_admin', fake_admin_check) - fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthManager.projects = dict(testacct=Project('testacct', 'testacct', 'guy1', @@ -61,10 +61,8 @@ class UsersTest(test.TestCase): self.allow_admin = FLAGS.allow_admin_api FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() - fakemgr.add_user('acc1', User('guy1', 'guy1', 'acc1', - 'fortytwo!', False)) - fakemgr.add_user('acc2', User('guy2', 'guy2', 'acc2', - 'swordfish', True)) + fakemgr.add_user(User('guy1', 'guy1', 'acc1', 'fortytwo!', False)) + fakemgr.add_user(User('guy2', 'guy2', 'acc2', 'swordfish', True)) def tearDown(self): self.stubs.UnsetAll() @@ -95,7 +93,7 @@ class UsersTest(test.TestCase): req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) self.assertTrue('guy1' not in [u.id for u in - fakes.FakeAuthManager.auth_data.values()]) + fakes.FakeAuthManager.auth_data]) self.assertEqual(res.status_int, 200) def test_user_create(self): @@ -118,8 +116,8 @@ class UsersTest(test.TestCase): self.assertEqual(res_dict['user']['secret'], 'invasionIsInNormandy') self.assertEqual(res_dict['user']['admin'], True) self.assertTrue('test_guy' in [u.id for u in - fakes.FakeAuthManager.auth_data.values()]) - self.assertEqual(len(fakes.FakeAuthManager.auth_data.values()), 3) + fakes.FakeAuthManager.auth_data]) + self.assertEqual(len(fakes.FakeAuthManager.auth_data), 3) def test_user_update(self): body = dict(user=dict(name='guy2', -- cgit From 909b72faa77ba0a2bc787309b95fdfae9bb9ca01 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 11 Mar 2011 17:41:10 -0500 Subject: Removed EOL whitespace in accordance with PEP-8. --- nova/tests/api/openstack/test_auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index d1b3c0e10..0448ed701 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,7 +51,7 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - f.add_user('user1_key', + f.add_user('user1_key', nova.auth.manager.User(1, 'user1', None, None, None)) req = webob.Request.blank('/v1.0/') -- cgit From 29e59a96602265c5b5746865db94a3f00b8b5cf5 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 11 Mar 2011 15:21:31 -0800 Subject: Change capitalization of Openstack to OpenStack --- nova/tests/integrated/api/client.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index da8d87e07..245eb8c69 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -24,7 +24,7 @@ from nova import log as logging LOG = logging.getLogger('nova.tests.api') -class OpenstackApiException(Exception): +class OpenStackApiException(Exception): def __init__(self, message=None, response=None): self.response = response if not message: @@ -37,22 +37,22 @@ class OpenstackApiException(Exception): message = _('%(message)s\nStatus Code: %(_status)s\n' 'Body: %(_body)s') % locals() - super(OpenstackApiException, self).__init__(message) + super(OpenStackApiException, self).__init__(message) -class OpenstackApiAuthenticationException(OpenstackApiException): +class OpenStackApiAuthenticationException(OpenStackApiException): def __init__(self, response=None, message=None): if not message: message = _("Authentication error") - super(OpenstackApiAuthenticationException, self).__init__(message, + super(OpenStackApiAuthenticationException, self).__init__(message, response) -class OpenstackApiNotFoundException(OpenstackApiException): +class OpenStackApiNotFoundException(OpenStackApiException): def __init__(self, response=None, message=None): if not message: message = _("Item not found") - super(OpenstackApiNotFoundException, self).__init__(message, response) + super(OpenStackApiNotFoundException, self).__init__(message, response) class TestOpenStackClient(object): @@ -82,7 +82,7 @@ class TestOpenStackClient(object): conn = httplib.HTTPSConnection(hostname, port=port) else: - raise OpenstackApiException("Unknown scheme: %s" % url) + raise OpenStackApiException("Unknown scheme: %s" % url) relative_url = parsed_url.path if parsed_url.query: @@ -111,7 +111,7 @@ class TestOpenStackClient(object): # Until bug732866 is fixed, we can't check this properly... #if http_status == 401: if http_status != 204: - raise OpenstackApiAuthenticationException(response=response) + raise OpenStackApiAuthenticationException(response=response) auth_headers = {} for k, v in response.getheaders(): @@ -138,9 +138,9 @@ class TestOpenStackClient(object): if check_response_status: if not http_status in check_response_status: if http_status == 404: - raise OpenstackApiNotFoundException(response=response) + raise OpenStackApiNotFoundException(response=response) else: - raise OpenstackApiException( + raise OpenStackApiException( message=_("Unexpected status code"), response=response) -- cgit From 1c4afe23157233b7081872ccbc6ea5fa1ff0015a Mon Sep 17 00:00:00 2001 From: Cerberus Date: Fri, 11 Mar 2011 17:30:51 -0600 Subject: Some unit tests --- nova/tests/test_compute.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 3d25a8997..c53284216 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -287,6 +287,30 @@ class ComputeTestCase(test.TestCase): migration_ref['id']) self.compute.terminate_instance(context, instance_id) + def test_resize_invalid_flavor_fails(self): + """Ensure invalid flavors raise""" + instance_id = self._create_instance() + context = self.context.elevated() + self.compute.run_instance(self.context, instance_id) + + self.assertRaises(exception.ApiError, self.compute_api.resize, + context, instance_id, 200) + + self.compute.terminate_instance(context, instance_id) + + def test_resize_down_fails(self): + """Ensure invalid flavors raise""" + instance_id = self._create_instance() + context = self.context.elevated() + self.compute.run_instance(self.context, instance_id) + db.instance_update(self.context, instance_id, + {'instance_type': 'm1.large'}) + + self.assertRaises(exception.ApiError, self.compute_api.resize, + context, instance_id, 1) + + self.compute.terminate_instance(context, instance_id) + def test_get_by_flavor_id(self): type = instance_types.get_by_flavor_id(1) self.assertEqual(type, 'm1.tiny') -- cgit From 2bfa7b29c7882da559041cea771b9243555828fa Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Sun, 13 Mar 2011 13:51:42 -0400 Subject: The extension name is constructed from the camel cased module_name + 'Extension'. --- nova/tests/api/openstack/extensions/widgets.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py index bc0947223..e03fc7776 100644 --- a/nova/tests/api/openstack/extensions/widgets.py +++ b/nova/tests/api/openstack/extensions/widgets.py @@ -1,27 +1,23 @@ from nova import wsgi -class WidgetController(wsgi.Controller): +class WidgetsController(wsgi.Controller): def index(self, req): return "Buy more widgets!" -class WidgetExtensionResource(object): +class WidgetsExtensionResource(object): def __init__(self): pass def add_routes(self, mapper): - mapper.resource('widget', 'widgets', controller=WidgetController()) + mapper.resource('widget', 'widgets', controller=WidgetsController()) -class WidgetExtension(object): +class WidgetsExtension(object): def __init__(self): pass def get_resources(self): - return WidgetExtensionResource() - - -def get_extension(): - return WidgetExtension() + return WidgetsExtensionResource() -- cgit From 4f2d48eeffc79333afae829ea31f7eae0549b40a Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Sun, 13 Mar 2011 23:35:30 +0000 Subject: Removed excess LOG.debug line --- nova/tests/test_xenapi.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 85d804ebd..def37b377 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -268,7 +268,6 @@ class XenAPIVMTestCase(test.TestCase): mem_kib = long(instance_type['memory_mb']) << 10 mem_bytes = str(mem_kib << 10) vcpus = instance_type['vcpus'] - LOG.debug("VM:%s", self.vm) self.assertEquals(self.vm_info['max_mem'], mem_kib) self.assertEquals(self.vm_info['mem'], mem_kib) self.assertEquals(self.vm['memory_static_max'], mem_bytes) -- cgit From 9164b8d224ae6629cdac00248b98fad762bdfc10 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 14 Mar 2011 10:46:26 +0100 Subject: Make utils.execute not overwrite std{in,out,err} args to Popen on retries. Make utils.execute reject unknown kwargs. Add a couple of unit tests for utils.execute. --- nova/tests/test_utils.py | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 34a407f1a..51cd57c76 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -14,11 +14,87 @@ # License for the specific language governing permissions and limitations # under the License. +import os +import tempfile + from nova import test from nova import utils from nova import exception +class ExecuteTestCase(test.TestCase): + def test_retry_on_failure(self): + fd, tmpfilename = tempfile.mkstemp() + _, tmpfilename2 = tempfile.mkstemp() + try: + fp = os.fdopen(fd, 'w+') + fp.write('''#!/bin/sh +# If stdin fails to get passed during one of the runs, make a note. +if ! grep -q foo +then + echo 'failure' > "$1" +fi +# If stdin has failed to get passed during this or a previous run, exit early. +if grep failure "$1" +then + exit 1 +fi +runs="$(cat $1)" +if [ -z "$runs" ] +then + runs=0 +fi +runs=$(($runs + 1)) +echo $runs > "$1" +exit 1 +''') + fp.close() + os.chmod(tmpfilename, 0755) + self.assertRaises(exception.ProcessExecutionError, + utils.execute, + tmpfilename, tmpfilename2, attempts=10, + process_input='foo', + delay_on_retry=False) + fp = open(tmpfilename2, 'r+') + runs = fp.read() + fp.close() + self.assertNotEquals(runs.strip(), 'failure', 'stdin did not ' + 'always get passed ' + 'correctly') + runs = int(runs.strip()) + self.assertEquals(runs, 10, 'Ran %d times instead of 10.' % (runs,)) + finally: + os.unlink(tmpfilename) + os.unlink(tmpfilename2) + + def test_unknown_kwargs_raises_error(self): + self.assertRaises(exception.Error, + utils.execute, + '/bin/true', this_is_not_a_valid_kwarg=True) + + def test_no_retry_on_success(self): + fd, tmpfilename = tempfile.mkstemp() + _, tmpfilename2 = tempfile.mkstemp() + try: + fp = os.fdopen(fd, 'w+') + fp.write('''#!/bin/sh +# If we've already run, bail out. +grep -q foo "$1" && exit 1 +# Mark that we've run before. +echo foo > "$1" +# Check that stdin gets passed correctly. +grep foo +''') + fp.close() + os.chmod(tmpfilename, 0755) + utils.execute(tmpfilename, + tmpfilename2, + process_input='foo', + attempts=2) + finally: + os.unlink(tmpfilename) + os.unlink(tmpfilename2) + class GetFromPathTestCase(test.TestCase): def test_tolerates_nones(self): f = utils.get_from_path -- cgit From c8fc7ed48be84e3b39ab88c8c103fbe52b6718e1 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 14 Mar 2011 14:06:10 +0100 Subject: Add a unit test --- nova/tests/test_network.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_network.py b/nova/tests/test_network.py index ce1c77210..b7a76be85 100644 --- a/nova/tests/test_network.py +++ b/nova/tests/test_network.py @@ -20,6 +20,7 @@ Unit Tests for network code """ import IPy import os +import time from nova import context from nova import db @@ -29,6 +30,7 @@ from nova import log as logging from nova import test from nova import utils from nova.auth import manager +from nova.network import linux_net FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.network') @@ -321,6 +323,31 @@ class NetworkTestCase(test.TestCase): network['id']) self.assertEqual(ip_count, num_available_ips) + def test_dhcp_lease_output(self): + admin_ctxt = context.get_admin_context() + address = self._create_address(0, self.instance_id) + lease_ip(address) + network_ref = db.network_get_by_instance(admin_ctxt, self.instance_id) + leases = linux_net.get_dhcp_leases(context.get_admin_context(), + network_ref['id']) + for line in leases.split('\n'): + seconds, mac, ip, hostname, client_id = line.split(' ') + self.assertTrue(int(seconds) > time.time(), 'Lease expires in ' + 'the past') + octets = mac.split(':') + self.assertEqual(len(octets), 6, "Wrong number of octets " + "in %s" % (max,)) + for octet in octets: + self.assertEqual(len(octet), 2, "Oddly sized octet: %s" + % (octet,)) + # This will throw an exception if the octet is invalid + int(octet, 16) + + # And this will raise an exception in case of an invalid IP + IPy.IP(ip) + + release_ip(address) + def is_allocated_in_project(address, project_id): """Returns true if address is in specified project""" -- cgit From af5e752e8eb21d0e9192d9acd9e75586bdec3685 Mon Sep 17 00:00:00 2001 From: Cerberus Date: Mon, 14 Mar 2011 11:55:55 -0500 Subject: Compute test --- nova/tests/test_compute.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index c53284216..47e0f66fb 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -76,6 +76,20 @@ class ComputeTestCase(test.TestCase): inst.update(params) return db.instance_create(self.context, inst)['id'] + def _create_instance_type(self, params={}): + """Create a test instance""" + inst = {} + inst['name'] = 'm1.small' + inst['memory_mb'] = '1024' + inst['vcpus'] = '1' + inst['local_gb'] = '20' + inst['flavorid'] = '1' + inst['swap'] = '2048' + inst['rxtx_quota'] = 100 + inst['rxtx_cap'] = 200 + inst.update(params) + return db.instance_type_create(self.context, inst)['id'] + def _create_group(self): values = {'name': 'testgroup', 'description': 'testgroup', @@ -301,10 +315,17 @@ class ComputeTestCase(test.TestCase): def test_resize_down_fails(self): """Ensure invalid flavors raise""" instance_id = self._create_instance() + + small_inst_type_id = self._create_instance_type(dict(flavorid=1, + memory_mb=512)) + big_inst_type_id = self._create_instance_type(dict(flavorid=2, + name='m1.wowzers', memory_mb=8192)) + context = self.context.elevated() self.compute.run_instance(self.context, instance_id) - db.instance_update(self.context, instance_id, - {'instance_type': 'm1.large'}) + db.instance_update(self.context, instance_id, + {'instance_type': 'm1.wowzers', + 'memory_gb': 8192}) self.assertRaises(exception.ApiError, self.compute_api.resize, context, instance_id, 1) -- cgit From 1ebae577150ce64d81d102c2e162acfe5a72528b Mon Sep 17 00:00:00 2001 From: Cerberus Date: Mon, 14 Mar 2011 12:07:27 -0500 Subject: Test changes --- nova/tests/test_compute.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 47e0f66fb..265421837 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -292,14 +292,18 @@ class ComputeTestCase(test.TestCase): """Ensure instance can be migrated/resized""" instance_id = self._create_instance() context = self.context.elevated() + small_inst_type_id = self._create_instance_type(dict(flavorid=1, + memory_mb=512, name='m1.small')) + self.compute.run_instance(self.context, instance_id) db.instance_update(self.context, instance_id, {'host': 'foo'}) - self.compute.prep_resize(context, instance_id) + self.compute.prep_resize(context, instance_id, 1) migration_ref = db.migration_get_by_instance_and_status(context, instance_id, 'pre-migrating') self.compute.resize_instance(context, instance_id, migration_ref['id']) self.compute.terminate_instance(context, instance_id) + self.db.instance_type_purge(context, 'm1.small') def test_resize_invalid_flavor_fails(self): """Ensure invalid flavors raise""" @@ -317,7 +321,7 @@ class ComputeTestCase(test.TestCase): instance_id = self._create_instance() small_inst_type_id = self._create_instance_type(dict(flavorid=1, - memory_mb=512)) + memory_mb=512, name='m1.small')) big_inst_type_id = self._create_instance_type(dict(flavorid=2, name='m1.wowzers', memory_mb=8192)) @@ -331,6 +335,8 @@ class ComputeTestCase(test.TestCase): context, instance_id, 1) self.compute.terminate_instance(context, instance_id) + self.db.instance_type_purge(context, 'm1.small') + self.db.instance_type_purge(context, 'm1.wowzers') def test_get_by_flavor_id(self): type = instance_types.get_by_flavor_id(1) @@ -340,7 +346,10 @@ class ComputeTestCase(test.TestCase): """Ensure instance fails to migrate when source and destination are the same host""" instance_id = self._create_instance() + small_inst_type_id = self._create_instance_type(dict(flavorid=1, + memory_mb=512, name='m1.small')) self.compute.run_instance(self.context, instance_id) self.assertRaises(exception.Error, self.compute.prep_resize, - self.context, instance_id) + self.context, instance_id, 1) self.compute.terminate_instance(self.context, instance_id) + self.db.instance_type_purge(context, 'm1.small') -- cgit From e509cd70e7a2e8a430b2b24af50adcf1ad763564 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Mon, 14 Mar 2011 17:24:39 +0000 Subject: Test fixes and some typos --- nova/tests/test_compute.py | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 265421837..a6defd644 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -78,6 +78,7 @@ class ComputeTestCase(test.TestCase): def _create_instance_type(self, params={}): """Create a test instance""" + context = self.context.elevated() inst = {} inst['name'] = 'm1.small' inst['memory_mb'] = '1024' @@ -88,7 +89,7 @@ class ComputeTestCase(test.TestCase): inst['rxtx_quota'] = 100 inst['rxtx_cap'] = 200 inst.update(params) - return db.instance_type_create(self.context, inst)['id'] + return db.instance_type_create(context, inst)['id'] def _create_group(self): values = {'name': 'testgroup', @@ -292,8 +293,6 @@ class ComputeTestCase(test.TestCase): """Ensure instance can be migrated/resized""" instance_id = self._create_instance() context = self.context.elevated() - small_inst_type_id = self._create_instance_type(dict(flavorid=1, - memory_mb=512, name='m1.small')) self.compute.run_instance(self.context, instance_id) db.instance_update(self.context, instance_id, {'host': 'foo'}) @@ -303,7 +302,6 @@ class ComputeTestCase(test.TestCase): self.compute.resize_instance(context, instance_id, migration_ref['id']) self.compute.terminate_instance(context, instance_id) - self.db.instance_type_purge(context, 'm1.small') def test_resize_invalid_flavor_fails(self): """Ensure invalid flavors raise""" @@ -311,32 +309,24 @@ class ComputeTestCase(test.TestCase): context = self.context.elevated() self.compute.run_instance(self.context, instance_id) - self.assertRaises(exception.ApiError, self.compute_api.resize, + self.assertRaises(exception.NotFound, self.compute_api.resize, context, instance_id, 200) self.compute.terminate_instance(context, instance_id) def test_resize_down_fails(self): """Ensure invalid flavors raise""" + context = self.context.elevated() instance_id = self._create_instance() - small_inst_type_id = self._create_instance_type(dict(flavorid=1, - memory_mb=512, name='m1.small')) - big_inst_type_id = self._create_instance_type(dict(flavorid=2, - name='m1.wowzers', memory_mb=8192)) - - context = self.context.elevated() self.compute.run_instance(self.context, instance_id) db.instance_update(self.context, instance_id, - {'instance_type': 'm1.wowzers', - 'memory_gb': 8192}) + {'instance_type': 'm1.xlarge'}) self.assertRaises(exception.ApiError, self.compute_api.resize, context, instance_id, 1) self.compute.terminate_instance(context, instance_id) - self.db.instance_type_purge(context, 'm1.small') - self.db.instance_type_purge(context, 'm1.wowzers') def test_get_by_flavor_id(self): type = instance_types.get_by_flavor_id(1) @@ -346,10 +336,7 @@ class ComputeTestCase(test.TestCase): """Ensure instance fails to migrate when source and destination are the same host""" instance_id = self._create_instance() - small_inst_type_id = self._create_instance_type(dict(flavorid=1, - memory_mb=512, name='m1.small')) self.compute.run_instance(self.context, instance_id) self.assertRaises(exception.Error, self.compute.prep_resize, self.context, instance_id, 1) self.compute.terminate_instance(self.context, instance_id) - self.db.instance_type_purge(context, 'm1.small') -- cgit From 266ea0bdd1da014a3cf23c7003f7fc932f447d35 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Mon, 14 Mar 2011 15:02:59 -0400 Subject: Create v1_0 and v1_1 packages for the openstack api. Added a servers module to each. Added tests to validate the structure of ip addresses for a 1.1 request. --- nova/tests/api/openstack/fakes.py | 1 + nova/tests/api/openstack/test_servers.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 8ec1629f4..7af62c57f 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -81,6 +81,7 @@ def wsgi_app(inner_application=None): api = openstack.FaultWrapper(auth.AuthMiddleware( ratelimiting.RateLimitingMiddleware(inner_application))) mapper['/v1.0'] = api + mapper['/v1.1'] = api mapper['/'] = openstack.FaultWrapper(openstack.Versions()) return mapper diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index c1e05b18a..a2bd875a4 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -21,6 +21,7 @@ import json import stubout import webob +from nova import context from nova import db from nova import flags from nova import test @@ -176,6 +177,28 @@ class ServersTest(test.TestCase): self.assertEqual(len(addresses["private"]), 1) self.assertEqual(addresses["private"][0], private) + def test_get_server_by_id_with_addresses_v1_1(self): + class FakeRequestContext(object): + def __init__(self, user, project, *args, **kwargs): + self.user_id = 1 + self.project_id = 1 + self.version = '1.1' + self.stubs.Set(context, 'RequestContext', FakeRequestContext) + private = "192.168.0.3" + public = ["1.2.3.4"] + new_return_server = return_server_with_addresses(private, public) + self.stubs.Set(nova.db.api, 'instance_get', new_return_server) + req = webob.Request.blank('/v1.1/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['name'], 'server1') + addresses = res_dict['server']['addresses'] + self.assertEqual(len(addresses["public"]), len(public)) + self.assertEqual(addresses["public"][0], {"version": 4, "addr": public[0]}) + self.assertEqual(len(addresses["private"]), 1) + self.assertEqual(addresses["private"][0], {"version": 4, "addr": private}) + def test_get_server_list(self): req = webob.Request.blank('/v1.0/servers') res = req.get_response(fakes.wsgi_app()) -- cgit From 7fe5052f9e8dbaebce45b44a545be9707f6480a6 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Mon, 14 Mar 2011 20:38:05 +0000 Subject: Adding instance_id as Glance image_property --- nova/tests/api/openstack/fakes.py | 19 +++++++++++++-- nova/tests/api/openstack/test_images.py | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index e50d11a3d..1c7d926ba 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -132,6 +132,19 @@ def stub_out_compute_api_snapshot(stubs): stubs.Set(nova.compute.API, 'snapshot', snapshot) +def stub_out_glance_add_image(stubs, sent_to_glance): + """ + We return the metadata sent to glance by modifying the sent_to_glance dict + in place. + """ + orig_add_image = glance_client.Client.add_image + def fake_add_image(context, metadata, data=None): + sent_to_glance['metadata'] = metadata + sent_to_glance['data'] = data + return orig_add_image(metadata, data) + stubs.Set(glance_client.Client, 'add_image', fake_add_image) + + def stub_out_glance(stubs, initial_fixtures=None): class FakeGlanceClient: @@ -153,8 +166,10 @@ def stub_out_glance(stubs, initial_fixtures=None): raise glance_exc.NotFound def fake_add_image(self, image_meta, data=None): - id = ''.join(random.choice(string.letters) for _ in range(20)) - image_meta['id'] = id + if 'id' not in image_meta: + image_id = ''.join(random.choice(string.letters) + for _ in range(20)) + image_meta['id'] = image_id self.fixtures.append(image_meta) return image_meta diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..0e6d538f9 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -28,6 +28,7 @@ import tempfile import stubout import webob +from glance import client as glance_client from nova import context from nova import exception from nova import flags @@ -166,11 +167,51 @@ class GlanceImageServiceTest(test.TestCase, self.service = utils.import_object(service_class) self.context = context.RequestContext(None, None) self.service.delete_all() + self.sent_to_glance = {} + fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) def tearDown(self): self.stubs.UnsetAll() super(GlanceImageServiceTest, self).tearDown() + def test_create_propertified_images_with_instance_id(self): + """ + Some attributes are passed to Glance as image-properties (ex. + instance_id). + + This tests asserts that the ImageService exposes them as if they were + first-class attribrutes, but that they are passed to Glance as image + properties. + """ + fixture = {'id': 123, 'instance_id': 42, 'name': 'test image'} + image_id = self.service.create(self.context, fixture)['id'] + + expected = {'id': 123, + 'name': 'test image', + 'properties': {'instance_id': 42}} + self.assertDictMatch(self.sent_to_glance['metadata'], expected) + + # The ImageService shouldn't leak the fact that the instance_id + # happens to be stored as a property in Glance + expected = {'id': 123, 'instance_id': 42, 'name': 'test image'} + image_meta = self.service.show(self.context, image_id) + self.assertDictMatch(image_meta, expected) + + def test_create_propertified_images_without_instance_id(self): + """ + Some attributes are passed to Glance as image-properties (ex. + instance_id). + + This tests asserts that the ImageService exposes them as if they were + first-class attribrutes, but that they are passed to Glance as image + properties. + """ + fixture = {'id': 123, 'name': 'test image'} + image_id = self.service.create(self.context, fixture)['id'] + + expected = {'id': 123, 'name': 'test image', 'properties': {}} + self.assertDictMatch(self.sent_to_glance['metadata'], expected) + class ImageControllerWithGlanceServiceTest(test.TestCase): -- cgit From 229c5bc3324d5df39ca959d71a540a806bc5ad3e Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 14 Mar 2011 16:58:03 -0400 Subject: Implement action extensions. --- nova/tests/api/openstack/extensions/widgets.py | 22 +++++++++++++ nova/tests/api/openstack/test_extensions.py | 44 ++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py index e03fc7776..6839d2bb2 100644 --- a/nova/tests/api/openstack/extensions/widgets.py +++ b/nova/tests/api/openstack/extensions/widgets.py @@ -1,10 +1,14 @@ from nova import wsgi +from nova.api.openstack import extensions + + class WidgetsController(wsgi.Controller): def index(self, req): return "Buy more widgets!" + class WidgetsExtensionResource(object): def __init__(self): @@ -21,3 +25,21 @@ class WidgetsExtension(object): def get_resources(self): return WidgetsExtensionResource() + + def get_actions(self): + actions = [] + actions.append(extensions.ExtensionAction('server', 'servers', + 'add_widget', + self._add_widget)) + actions.append(extensions.ExtensionAction('server', 'servers', + 'delete_widget', + self._delete_widget)) + return actions + + def _add_widget(self, input_dict, req, id): + + return "Widget Added." + + def _delete_widget(self, input_dict, req, id): + + return "Widget Deleted." diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index ff41d6d99..f8d217e9c 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -15,10 +15,10 @@ # License for the specific language governing permissions and limitations # under the License. +import json import unittest -import os.path - import webob +import os.path from nova import flags from nova.api import openstack @@ -26,6 +26,7 @@ import nova.wsgi FLAGS = flags.FLAGS + class StubController(nova.wsgi.Controller): def __init__(self, body): @@ -34,6 +35,7 @@ class StubController(nova.wsgi.Controller): def index(self, req): return self.body + class StubExtensionManager(object): def __init__(self, resources): @@ -42,6 +44,7 @@ class StubExtensionManager(object): def get_resources(self): return self.resources + class WidgetExtensionResource(object): def __init__(self, name, collection, wsgi_app): @@ -52,6 +55,7 @@ class WidgetExtensionResource(object): def add_routes(self, mapper): mapper.resource(self.name, self.collection, controller=self.wsgi_app) + class ExtensionTest(unittest.TestCase): def test_no_extension_present(self): @@ -99,4 +103,40 @@ class ExtensionManagerTest(unittest.TestCase): self.assertEqual("Buy more widgets!", response.body) +class ExtendedActionTest(unittest.TestCase): + def setUp(self): + FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), + "extensions") + + def test_extended_action(self): + app = openstack.APIRouter() + ext_midware = openstack.extensions.ExtensionMiddleware(app) + body = dict(add_widget=dict(name="test")) + request = webob.Request.blank("/servers/1/action") + request.method = 'POST' + request.content_type = 'application/json' + request.body = json.dumps(body) + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + self.assertEqual("Widget Added.", response.body) + + def test_invalid_action_body(self): + app = openstack.APIRouter() + ext_midware = openstack.extensions.ExtensionMiddleware(app) + body = dict(blah=dict(name="test")) # Doesn't exist + request = webob.Request.blank("/servers/1/action") + request.method = 'POST' + request.content_type = 'application/json' + request.body = json.dumps(body) + response = request.get_response(ext_midware) + self.assertEqual(501, response.status_int) + + def test_invalid_action(self): + app = openstack.APIRouter() + ext_midware = openstack.extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/asdf/1/action") + request.method = 'POST' + request.content_type = 'application/json' + response = request.get_response(ext_midware) + self.assertEqual(404, response.status_int) -- cgit From 408a2591d60f5d238e60e4be9197ccc7262f2406 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Mon, 14 Mar 2011 16:21:33 -0500 Subject: PEP8 cleanup --- nova/tests/db/fakes.py | 4 ++-- nova/tests/test_xenapi.py | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 142f6b1c6..5e9a3aa3b 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -77,8 +77,8 @@ def stub_out_db_instance_api(stubs): 'mac_address': values['mac_address'], 'vcpus': type_data['vcpus'], 'local_gb': type_data['local_gb'], - 'os_type': values['os_type'] - } + 'os_type': values['os_type']} + return FakeModel(base_options) def fake_network_get_by_instance(context, instance_id): diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index cd125a301..8b0affd5c 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -78,8 +78,7 @@ class XenAPIVolumeTestCase(test.TestCase): 'ramdisk_id': 3, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', - 'os_type': 'linux' - } + 'os_type': 'linux'} def _create_volume(self, size='0'): """Create a volume object.""" @@ -315,8 +314,8 @@ class XenAPIVMTestCase(test.TestCase): 'ramdisk_id': ramdisk_id, 'instance_type': instance_type, 'mac_address': 'aa:bb:cc:dd:ee:ff', - 'os_type': os_type - } + 'os_type': os_type} + conn = xenapi_conn.get_connection(False) instance = db.instance_create(values) conn.spawn(instance) @@ -440,8 +439,8 @@ class XenAPIMigrateInstance(test.TestCase): 'ramdisk_id': None, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', - 'os_type': 'linux' - } + 'os_type': 'linux'} + stubs.stub_out_migration_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) -- cgit From 7c6aa5eb302637dde0d800f7155235858bbabbeb Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 14:32:15 -0700 Subject: Removed duplicated test, renamed same-named (but non-identical) tests --- nova/tests/test_compute.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index e486050be..14559d1dc 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -115,7 +115,7 @@ class ComputeTestCase(test.TestCase): finally: db.instance_destroy(self.context, ref[0]['id']) - def test_create_instance_associates_security_groups(self): + def test_create_instance_associates_security_groups_1(self): """Make sure create associates security groups""" group = self._create_group() instance_ref = models.Instance() @@ -124,18 +124,7 @@ class ComputeTestCase(test.TestCase): instance_ref['hostname'] = 'i-00000001' return instance_ref - def test_create_instance_defaults_display_name(self): - """Verify that an instance cannot be created without a display_name.""" - cases = [dict(), dict(display_name=None)] - for instance in cases: - ref = self.compute_api.create(self.context, - FLAGS.default_instance_type, None, **instance) - try: - self.assertNotEqual(ref[0]['display_name'], None) - finally: - db.instance_destroy(self.context, ref[0]['id']) - - def test_create_instance_associates_security_groups(self): + def test_create_instance_associates_security_groups_2(self): """Make sure create associates security groups""" group = self._create_group() ref = self.compute_api.create( -- cgit From 738653b6b4ac744519a050fe50e7c795a7c63579 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 15:11:14 -0700 Subject: Added test and fixed up code so that it works --- nova/tests/test_compute.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index e486050be..b9d0aa0b6 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -595,3 +595,24 @@ class ComputeTestCase(test.TestCase): db.instance_destroy(c, instance_id) db.volume_destroy(c, v_ref['id']) db.floating_ip_destroy(c, flo_addr) + + def test_run_kill_vm(self): + """Detect when a vm is terminated behind the scenes""" + instance_id = self._create_instance() + + self.compute.run_instance(self.context, instance_id) + + instances = db.instance_get_all(context.get_admin_context()) + LOG.info(_("Running instances: %s"), instances) + self.assertEqual(len(instances), 1) + + instance_name = instances[0].name + self.compute.driver.test_remove_vm(instance_name) + + # Force the compute manager to do its periodic poll + error_list = self.compute.periodic_tasks(context.get_admin_context()) + self.assertFalse(error_list) + + instances = db.instance_get_all(context.get_admin_context()) + LOG.info(_("After force-killing instances: %s"), instances) + self.assertEqual(len(instances), 0) -- cgit From 567e3bc3a7e66896482d83420190a7c4a8df1e5a Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 15:17:00 -0700 Subject: So the first of those tests doesn't pass. Removing as it looks like it was meant to be deleted. --- nova/tests/test_compute.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 14559d1dc..3651f4cef 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -115,16 +115,7 @@ class ComputeTestCase(test.TestCase): finally: db.instance_destroy(self.context, ref[0]['id']) - def test_create_instance_associates_security_groups_1(self): - """Make sure create associates security groups""" - group = self._create_group() - instance_ref = models.Instance() - instance_ref['id'] = 1 - instance_ref['volumes'] = [{'id': 1}, {'id': 2}] - instance_ref['hostname'] = 'i-00000001' - return instance_ref - - def test_create_instance_associates_security_groups_2(self): + def test_create_instance_associates_security_groups(self): """Make sure create associates security groups""" group = self._create_group() ref = self.compute_api.create( -- cgit From a56a973e9d839df5bcd956126300afd7df4c2fe9 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Mar 2011 00:37:13 +0000 Subject: Fixing API per spec, to get unit-tests to pass --- nova/tests/api/openstack/fakes.py | 13 +++-- nova/tests/api/openstack/test_images.py | 93 +++++++++++++++++---------------- 2 files changed, 58 insertions(+), 48 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 1c7d926ba..ef38b93ca 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -138,10 +138,12 @@ def stub_out_glance_add_image(stubs, sent_to_glance): in place. """ orig_add_image = glance_client.Client.add_image + def fake_add_image(context, metadata, data=None): sent_to_glance['metadata'] = metadata sent_to_glance['data'] = data return orig_add_image(metadata, data) + stubs.Set(glance_client.Client, 'add_image', fake_add_image) @@ -166,10 +168,13 @@ def stub_out_glance(stubs, initial_fixtures=None): raise glance_exc.NotFound def fake_add_image(self, image_meta, data=None): - if 'id' not in image_meta: - image_id = ''.join(random.choice(string.letters) - for _ in range(20)) - image_meta['id'] = image_id + if 'id' in image_meta: + raise Exception( + _("Cannot set id attribute for Glance image: %s") + % image_meta) + image_id = ''.join(random.choice(string.letters) + for _ in range(20)) + image_meta['id'] = image_id self.fixtures.append(image_meta) return image_meta diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 0e6d538f9..9b4b5832a 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -156,7 +156,7 @@ class LocalImageServiceTest(test.TestCase, class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): - """Tests the local image service""" + """Tests the Glance image service""" def setUp(self): super(GlanceImageServiceTest, self).setUp() @@ -183,20 +183,23 @@ class GlanceImageServiceTest(test.TestCase, first-class attribrutes, but that they are passed to Glance as image properties. """ - fixture = {'id': 123, 'instance_id': 42, 'name': 'test image'} + fixture = {'instance_id': 42, 'name': 'test image'} image_id = self.service.create(self.context, fixture)['id'] - expected = {'id': 123, + expected = {'id': image_id, 'name': 'test image', 'properties': {'instance_id': 42}} self.assertDictMatch(self.sent_to_glance['metadata'], expected) # The ImageService shouldn't leak the fact that the instance_id # happens to be stored as a property in Glance - expected = {'id': 123, 'instance_id': 42, 'name': 'test image'} + expected = {'id': image_id, 'instance_id': 42, 'name': 'test image'} image_meta = self.service.show(self.context, image_id) self.assertDictMatch(image_meta, expected) + #image_metas = self.service.detail(self.context) + #self.assertDictMatch(image_metas[0], expected) + def test_create_propertified_images_without_instance_id(self): """ Some attributes are passed to Glance as image-properties (ex. @@ -206,10 +209,10 @@ class GlanceImageServiceTest(test.TestCase, first-class attribrutes, but that they are passed to Glance as image properties. """ - fixture = {'id': 123, 'name': 'test image'} + fixture = {'name': 'test image'} image_id = self.service.create(self.context, fixture)['id'] - expected = {'id': 123, 'name': 'test image', 'properties': {}} + expected = {'id': image_id, 'name': 'test image', 'properties': {}} self.assertDictMatch(self.sent_to_glance['metadata'], expected) @@ -217,29 +220,39 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """Test of the OpenStack API /images application controller""" - # Registered images at start of each test. + # FIXME(sirp): The ImageService and API use two different formats for + # timestamps. Ultimately, the ImageService should probably use datetime + # objects + NOW_SERVICE_STR = "2010-10-11T10:30:22" + NOW_API_STR = "2010-10-11T10:30:22Z" IMAGE_FIXTURES = [ - {'id': '23g2ogk23k4hhkk4k42l', - 'imageId': '23g2ogk23k4hhkk4k42l', + {'id': 123, 'name': 'public image #1', - 'created_at': str(datetime.datetime.utcnow()), - 'updated_at': str(datetime.datetime.utcnow()), + 'created_at': NOW_SERVICE_STR, + 'updated_at': NOW_SERVICE_STR, 'deleted_at': None, 'deleted': False, 'is_public': True, - 'status': 'available', - 'image_type': 'kernel'}, - {'id': 'slkduhfas73kkaskgdas', - 'imageId': 'slkduhfas73kkaskgdas', + 'status': 'saving'}, + {'id': 124, 'name': 'public image #2', - 'created_at': str(datetime.datetime.utcnow()), - 'updated_at': str(datetime.datetime.utcnow()), + 'created_at': NOW_SERVICE_STR, + 'updated_at': NOW_SERVICE_STR, + 'deleted_at': None, + 'deleted': False, + 'is_public': True, + 'status': 'active', + 'instance_id': 42}, + {'id': 125, + 'name': 'public image #3', + 'created_at': NOW_SERVICE_STR, + 'updated_at': NOW_SERVICE_STR, 'deleted_at': None, 'deleted': False, 'is_public': True, - 'status': 'available', - 'image_type': 'ramdisk'}] + 'status': 'killed', + 'instance_id': 42}] def setUp(self): super(ImageControllerWithGlanceServiceTest, self).setUp() @@ -262,34 +275,26 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): def test_get_image_index(self): req = webob.Request.blank('/v1.0/images') res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) + image_metas = json.loads(res.body)['images'] - fixture_index = [dict(id=f['id'], name=f['name']) for f - in self.IMAGE_FIXTURES] + expected = [{'id': 123, 'name': 'public image #1'}, + {'id': 124, 'name': 'public image #2'}, + {'id': 125, 'name': 'public image #3'}] - for image in res_dict['images']: - self.assertEquals(1, fixture_index.count(image), - "image %s not in fixture index!" % str(image)) + self.assertDictListMatch(image_metas, expected) def test_get_image_details(self): req = webob.Request.blank('/v1.0/images/detail') res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) - - def _is_equivalent_subset(x, y): - if set(x) <= set(y): - for k, v in x.iteritems(): - if x[k] != y[k]: - if x[k] == 'active' and y[k] == 'available': - continue - return False - return True - return False - - for image in res_dict['images']: - for image_fixture in self.IMAGE_FIXTURES: - if _is_equivalent_subset(image, image_fixture): - break - else: - self.assertEquals(1, 2, "image %s not in fixtures!" % - str(image)) + image_metas = json.loads(res.body)['images'] + + expected = [ + {'id': 123, 'name': 'public image #1', 'updated': self.NOW_API_STR, + 'created': self.NOW_API_STR, 'status': 'SAVING', 'progress': 0}, + {'id': 124, 'name': 'public image #2', 'updated': self.NOW_API_STR, + 'created': self.NOW_API_STR, 'status': 'ACTIVE', 'serverId': 42}, + {'id': 125, 'name': 'public image #3', 'updated': self.NOW_API_STR, + 'created': self.NOW_API_STR, 'status': 'FAILED', 'serverId': 42}, + ] + + self.assertDictListMatch(image_metas, expected) -- cgit From b5a6e343bb6a15e652b3a6924e1809a04a0eb421 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Mar 2011 01:14:58 +0000 Subject: Moving fixtures to a factory --- nova/tests/api/openstack/test_images.py | 109 +++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 38 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 9b4b5832a..47cb7e74c 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -226,34 +226,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): NOW_SERVICE_STR = "2010-10-11T10:30:22" NOW_API_STR = "2010-10-11T10:30:22Z" - IMAGE_FIXTURES = [ - {'id': 123, - 'name': 'public image #1', - 'created_at': NOW_SERVICE_STR, - 'updated_at': NOW_SERVICE_STR, - 'deleted_at': None, - 'deleted': False, - 'is_public': True, - 'status': 'saving'}, - {'id': 124, - 'name': 'public image #2', - 'created_at': NOW_SERVICE_STR, - 'updated_at': NOW_SERVICE_STR, - 'deleted_at': None, - 'deleted': False, - 'is_public': True, - 'status': 'active', - 'instance_id': 42}, - {'id': 125, - 'name': 'public image #3', - 'created_at': NOW_SERVICE_STR, - 'updated_at': NOW_SERVICE_STR, - 'deleted_at': None, - 'deleted': False, - 'is_public': True, - 'status': 'killed', - 'instance_id': 42}] - def setUp(self): super(ImageControllerWithGlanceServiceTest, self).setUp() self.orig_image_service = FLAGS.image_service @@ -265,7 +237,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) - fakes.stub_out_glance(self.stubs, initial_fixtures=self.IMAGE_FIXTURES) + fixtures = self._make_image_fixtures() + fakes.stub_out_glance(self.stubs, initial_fixtures=fixtures) def tearDown(self): self.stubs.UnsetAll() @@ -277,9 +250,11 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) image_metas = json.loads(res.body)['images'] - expected = [{'id': 123, 'name': 'public image #1'}, - {'id': 124, 'name': 'public image #2'}, - {'id': 125, 'name': 'public image #3'}] + expected = [{'id': 123, 'name': 'public image'}, + {'id': 124, 'name': 'queued backup'}, + {'id': 125, 'name': 'saving backup'}, + {'id': 126, 'name': 'active backup'}, + {'id': 127, 'name': 'killed backup'}] self.assertDictListMatch(image_metas, expected) @@ -289,12 +264,70 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): image_metas = json.loads(res.body)['images'] expected = [ - {'id': 123, 'name': 'public image #1', 'updated': self.NOW_API_STR, - 'created': self.NOW_API_STR, 'status': 'SAVING', 'progress': 0}, - {'id': 124, 'name': 'public image #2', 'updated': self.NOW_API_STR, - 'created': self.NOW_API_STR, 'status': 'ACTIVE', 'serverId': 42}, - {'id': 125, 'name': 'public image #3', 'updated': self.NOW_API_STR, - 'created': self.NOW_API_STR, 'status': 'FAILED', 'serverId': 42}, + {'id': 123, 'name': 'public image', 'updated': self.NOW_API_STR, + 'created': self.NOW_API_STR, 'status': 'ACTIVE'}, + {'id': 124, 'name': 'queued backup', 'serverId': 42, + 'updated': self.NOW_API_STR, 'created': self.NOW_API_STR, + 'status': 'QUEUED'}, + {'id': 125, 'name': 'saving backup', 'serverId': 42, + 'updated': self.NOW_API_STR, 'created': self.NOW_API_STR, + 'status': 'SAVING', 'progress': 0}, + {'id': 126, 'name': 'active backup', 'serverId': 42, + 'updated': self.NOW_API_STR, 'created': self.NOW_API_STR, + 'status': 'ACTIVE'}, + {'id': 127, 'name': 'killed backup', 'serverId': 42, + 'updated': self.NOW_API_STR, 'created': self.NOW_API_STR, + 'status': 'FAILED'} ] self.assertDictListMatch(image_metas, expected) + + @classmethod + def _make_image_fixtures(cls): + """ + """ + fixtures = [] + public_image = {'id': 123, + 'name': 'public image', + 'is_public': True, + 'status': 'active'} + fixtures.append(public_image) + + queued_backup = {'id': 124, + 'name': 'queued backup', + 'is_public': False, + 'status': 'queued', + 'instance_id': 42} + fixtures.append(queued_backup) + + saving_backup = {'id': 125, + 'name': 'saving backup', + 'is_public': False, + 'status': 'saving', + 'instance_id': 42, + 'progress': 0} + fixtures.append(saving_backup) + + active_backup = {'id': 126, + 'name': 'active backup', + 'is_public': False, + 'status': 'active', + 'instance_id': 42} + fixtures.append(active_backup) + + killed_backup = {'id': 127, + 'name': 'killed backup', + 'is_public': False, + 'status': 'killed', + 'instance_id': 42} + fixtures.append(killed_backup) + + base_attrs = {'created_at': cls.NOW_SERVICE_STR, + 'updated_at': cls.NOW_SERVICE_STR, + 'deleted_at': None, + 'deleted': False} + + for fixture in fixtures: + fixture.update(base_attrs) + + return fixtures -- cgit From f0141b1616e1b1fc9e52e33b37cc3a1091c57587 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 14 Mar 2011 22:24:34 -0400 Subject: Moved extended resource code into the extensions.py module. --- nova/tests/api/openstack/extensions/widgets.py | 15 ++---- nova/tests/api/openstack/test_extensions.py | 66 +++++++++++++------------- 2 files changed, 38 insertions(+), 43 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py index 6839d2bb2..d5a2d95d9 100644 --- a/nova/tests/api/openstack/extensions/widgets.py +++ b/nova/tests/api/openstack/extensions/widgets.py @@ -9,22 +9,17 @@ class WidgetsController(wsgi.Controller): return "Buy more widgets!" -class WidgetsExtensionResource(object): - - def __init__(self): - pass - - def add_routes(self, mapper): - mapper.resource('widget', 'widgets', controller=WidgetsController()) - - class WidgetsExtension(object): def __init__(self): pass def get_resources(self): - return WidgetsExtensionResource() + resources = [] + widgets = extensions.ExtensionResource('widget', 'widgets', + WidgetsController()) + resources.append(widgets) + return resources def get_actions(self): actions = [] diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index f8d217e9c..080760c14 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -22,6 +22,7 @@ import os.path from nova import flags from nova.api import openstack +from nova.api.openstack import extensions import nova.wsgi FLAGS = flags.FLAGS @@ -38,53 +39,51 @@ class StubController(nova.wsgi.Controller): class StubExtensionManager(object): - def __init__(self, resources): - self.resources = resources + def __init__(self, resource): + self.resource = resource def get_resources(self): - return self.resources + resources = [] + if self.resource: + resources.append(self.resource) + return resources + def get_actions(self): + actions = [] + return actions -class WidgetExtensionResource(object): - def __init__(self, name, collection, wsgi_app): - self.name = name - self.collection = collection - self.wsgi_app = wsgi_app - - def add_routes(self, mapper): - mapper.resource(self.name, self.collection, controller=self.wsgi_app) - - -class ExtensionTest(unittest.TestCase): +class ExtensionResourceTest(unittest.TestCase): def test_no_extension_present(self): - manager = StubExtensionManager([]) - router = openstack.APIRouter(manager) + manager = StubExtensionManager(None) + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/widgets") - response = request.get_response(router) + response = request.get_response(ext_midware) self.assertEqual(404, response.status_int) def test_get_resources(self): response_body = "Buy more widgets!" - response = webob.Response() - response.body = response_body - resource1 = WidgetExtensionResource("widget", "widgets", response) - manager = StubExtensionManager([resource1]) - router = openstack.APIRouter(manager) + widgets = extensions.ExtensionResource('widget', 'widgets', + StubController(response_body)) + manager = StubExtensionManager(widgets) + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/widgets") - response = request.get_response(router) + response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) self.assertEqual(response_body, response.body) def test_get_resources_with_controller(self): response_body = "Buy more widgets!" - controller = StubController(response_body) - resource1 = WidgetExtensionResource("widget", "widgets", controller) - manager = StubExtensionManager([resource1]) - router = openstack.APIRouter(manager) + widgets = extensions.ExtensionResource('widget', 'widgets', + StubController(response_body)) + manager = StubExtensionManager(widgets) + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/widgets") - response = request.get_response(router) + response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) self.assertEqual(response_body, response.body) @@ -96,9 +95,10 @@ class ExtensionManagerTest(unittest.TestCase): "extensions") def test_get_resources(self): - router = openstack.APIRouter() + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/widgets") - response = request.get_response(router) + response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) self.assertEqual("Buy more widgets!", response.body) @@ -111,7 +111,7 @@ class ExtendedActionTest(unittest.TestCase): def test_extended_action(self): app = openstack.APIRouter() - ext_midware = openstack.extensions.ExtensionMiddleware(app) + ext_midware = extensions.ExtensionMiddleware(app) body = dict(add_widget=dict(name="test")) request = webob.Request.blank("/servers/1/action") request.method = 'POST' @@ -123,7 +123,7 @@ class ExtendedActionTest(unittest.TestCase): def test_invalid_action_body(self): app = openstack.APIRouter() - ext_midware = openstack.extensions.ExtensionMiddleware(app) + ext_midware = extensions.ExtensionMiddleware(app) body = dict(blah=dict(name="test")) # Doesn't exist request = webob.Request.blank("/servers/1/action") request.method = 'POST' @@ -134,7 +134,7 @@ class ExtendedActionTest(unittest.TestCase): def test_invalid_action(self): app = openstack.APIRouter() - ext_midware = openstack.extensions.ExtensionMiddleware(app) + ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/asdf/1/action") request.method = 'POST' request.content_type = 'application/json' -- cgit From d5b9391e2911ba2210a045a2af380dfc85d16919 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Mon, 14 Mar 2011 23:14:59 -0400 Subject: Added a views package and a views.servers module. For representing the response object before it is serialized. --- nova/tests/api/openstack/test_servers.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a2bd875a4..b2446f194 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -195,9 +195,11 @@ class ServersTest(test.TestCase): self.assertEqual(res_dict['server']['name'], 'server1') addresses = res_dict['server']['addresses'] self.assertEqual(len(addresses["public"]), len(public)) - self.assertEqual(addresses["public"][0], {"version": 4, "addr": public[0]}) + self.assertEqual(addresses["public"][0], + {"version": 4, "addr": public[0]}) self.assertEqual(len(addresses["private"]), 1) - self.assertEqual(addresses["private"][0], {"version": 4, "addr": private}) + self.assertEqual(addresses["private"][0], + {"version": 4, "addr": private}) def test_get_server_list(self): req = webob.Request.blank('/v1.0/servers') -- cgit From 18cd549ba8d7aa4c688a7f7a5e940acbaaa03acc Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 15 Mar 2011 00:49:20 -0400 Subject: adding flavors and images barebones view code; adding flavorRef and imageRef to v1.1 servers --- nova/tests/api/openstack/test_servers.py | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index b2446f194..b42cecfbb 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -79,7 +79,7 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None): "admin_pass": "", "user_id": user_id, "project_id": "", - "image_id": 10, + "image_id": "10", "kernel_id": "", "ramdisk_id": "", "launch_index": 0, @@ -92,7 +92,7 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None): "local_gb": 0, "hostname": "", "host": None, - "instance_type": "", + "instance_type": "1", "user_data": "", "reservation_id": "", "mac_address": "", @@ -353,7 +353,7 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status, '404 Not Found') - def test_get_all_server_details(self): + def test_get_all_server_details_v1_0(self): req = webob.Request.blank('/v1.0/servers/detail') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) @@ -363,7 +363,31 @@ class ServersTest(test.TestCase): self.assertEqual(s['id'], i) self.assertEqual(s['hostId'], '') self.assertEqual(s['name'], 'server%d' % i) - self.assertEqual(s['imageId'], 10) + self.assertEqual(s['imageId'], '10') + self.assertEqual(s['flavorId'], '1') + self.assertEqual(s['metadata']['seq'], i) + i += 1 + + def test_get_all_server_details_v1_1(self): + class FakeRequestContext(object): + def __init__(self, user, project, *args, **kwargs): + self.user_id = 1 + self.project_id = 1 + self.version = '1.1' + self.is_admin = True + + self.stubs.Set(context, 'RequestContext', FakeRequestContext) + req = webob.Request.blank('/v1.1/servers/detail') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + i = 0 + for s in res_dict['servers']: + self.assertEqual(s['id'], i) + self.assertEqual(s['hostId'], '') + self.assertEqual(s['name'], 'server%d' % i) + self.assertEqual(s['imageRef'], 'http://localhost/v1.1/images/10') + self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1') self.assertEqual(s['metadata']['seq'], i) i += 1 -- cgit From 2b20306fcaddcb6b9bc57fb55b17230d709cd1ce Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 22:23:38 -0700 Subject: Derive unit test from standard nova.test.TestCase --- nova/tests/integrated/test_login.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index e362f92d6..5fa558bdf 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -18,6 +18,7 @@ import unittest from nova import flags +from nova import test from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -29,7 +30,7 @@ FLAGS = flags.FLAGS FLAGS.verbose = True -class LoginTest(unittest.TestCase): +class LoginTest(test.TestCase): def setUp(self): super(LoginTest, self).setUp() context = integrated_helpers.IntegratedUnitTestContext.startup() @@ -73,5 +74,6 @@ class LoginTest(unittest.TestCase): self.assertRaises(client.OpenstackApiAuthenticationException, bad_credentials_api.get_flavors) + if __name__ == "__main__": unittest.main() -- cgit From db8beffc9acd90c748512c1fa9c127d39756232c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 22:36:30 -0700 Subject: Reapplied rename of Openstack -> OpenStack. Easier to do it by hand than to ask Bazaar to do it. --- nova/tests/integrated/api/client.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 6fba2930a..568e8c17e 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -24,7 +24,7 @@ from nova import log as logging LOG = logging.getLogger('nova.tests.api') -class OpenstackApiException(Exception): +class OpenStackApiException(Exception): def __init__(self, message=None, response=None): self.response = response if not message: @@ -37,22 +37,22 @@ class OpenstackApiException(Exception): message = _('%(message)s\nStatus Code: %(_status)s\n' 'Body: %(_body)s') % locals() - super(OpenstackApiException, self).__init__(message) + super(OpenStackApiException, self).__init__(message) -class OpenstackApiAuthenticationException(OpenstackApiException): +class OpenStackApiAuthenticationException(OpenStackApiException): def __init__(self, response=None, message=None): if not message: message = _("Authentication error") - super(OpenstackApiAuthenticationException, self).__init__(message, + super(OpenStackApiAuthenticationException, self).__init__(message, response) -class OpenstackApiNotFoundException(OpenstackApiException): +class OpenStackApiNotFoundException(OpenStackApiException): def __init__(self, response=None, message=None): if not message: message = _("Item not found") - super(OpenstackApiNotFoundException, self).__init__(message, response) + super(OpenStackApiNotFoundException, self).__init__(message, response) class TestOpenStackClient(object): @@ -82,7 +82,7 @@ class TestOpenStackClient(object): conn = httplib.HTTPSConnection(hostname, port=port) else: - raise OpenstackApiException("Unknown scheme: %s" % url) + raise OpenStackApiException("Unknown scheme: %s" % url) relative_url = parsed_url.path if parsed_url.query: @@ -112,7 +112,7 @@ class TestOpenStackClient(object): # bug732866 #if http_status == 401: if http_status != 204: - raise OpenstackApiAuthenticationException(response=response) + raise OpenStackApiAuthenticationException(response=response) auth_headers = {} for k, v in response.getheaders(): @@ -139,9 +139,9 @@ class TestOpenStackClient(object): if check_response_status: if not http_status in check_response_status: if http_status == 404: - raise OpenstackApiNotFoundException(response=response) + raise OpenStackApiNotFoundException(response=response) else: - raise OpenstackApiException( + raise OpenStackApiException( message=_("Unexpected status code"), response=response) -- cgit From ad6f82909060cd4d1d99a1b1a9f33aa2788d8c94 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Mar 2011 05:37:08 +0000 Subject: serverId returned as int per spec --- nova/tests/api/openstack/test_images.py | 39 ++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 47cb7e74c..4604b331e 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -156,7 +156,17 @@ class LocalImageServiceTest(test.TestCase, class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): - """Tests the Glance image service""" + """Tests the Glance image service, in particular that metadata translation + works properly. + + At a high level, the translations involved are: + + 1. Glance -> ImageService - This is needed so we can support + multple ImageServices (Glance, Local, etc) + + 2. ImageService -> API - This is needed so we can support multple + APIs (OpenStack, EC2) + """ def setUp(self): super(GlanceImageServiceTest, self).setUp() @@ -174,21 +184,17 @@ class GlanceImageServiceTest(test.TestCase, self.stubs.UnsetAll() super(GlanceImageServiceTest, self).tearDown() - def test_create_propertified_images_with_instance_id(self): + def test_create_with_instance_id(self): """ - Some attributes are passed to Glance as image-properties (ex. - instance_id). - - This tests asserts that the ImageService exposes them as if they were - first-class attribrutes, but that they are passed to Glance as image - properties. + Ensure that a instance_id is stored in Glance as a image property + string and then converted back to an instance_id integer attribute. """ fixture = {'instance_id': 42, 'name': 'test image'} image_id = self.service.create(self.context, fixture)['id'] expected = {'id': image_id, 'name': 'test image', - 'properties': {'instance_id': 42}} + 'properties': {'instance_id': '42'}} self.assertDictMatch(self.sent_to_glance['metadata'], expected) # The ImageService shouldn't leak the fact that the instance_id @@ -197,17 +203,14 @@ class GlanceImageServiceTest(test.TestCase, image_meta = self.service.show(self.context, image_id) self.assertDictMatch(image_meta, expected) - #image_metas = self.service.detail(self.context) - #self.assertDictMatch(image_metas[0], expected) + image_metas = self.service.detail(self.context) + self.assertDictMatch(image_metas[0], expected) - def test_create_propertified_images_without_instance_id(self): + def test_create_without_instance_id(self): """ - Some attributes are passed to Glance as image-properties (ex. - instance_id). - - This tests asserts that the ImageService exposes them as if they were - first-class attribrutes, but that they are passed to Glance as image - properties. + Ensure we can create an image without having to specify an + instance_id. Public images are an example of an image not tied to an + instance. """ fixture = {'name': 'test image'} image_id = self.service.create(self.context, fixture)['id'] -- cgit From e0563f49792441af106c52e662bdada3c7997feb Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 14 Mar 2011 22:43:21 -0700 Subject: Reapplied rename to another file. --- nova/tests/integrated/test_login.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index 5fa558bdf..501f8c919 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -53,7 +53,7 @@ class LoginTest(test.TestCase): "notso_password", self.user.auth_url) - self.assertRaises(client.OpenstackApiAuthenticationException, + self.assertRaises(client.OpenStackApiAuthenticationException, bad_credentials_api.get_flavors) def test_bad_login_username(self): @@ -62,7 +62,7 @@ class LoginTest(test.TestCase): self.user.secret, self.user.auth_url) - self.assertRaises(client.OpenstackApiAuthenticationException, + self.assertRaises(client.OpenStackApiAuthenticationException, bad_credentials_api.get_flavors) def test_bad_login_both_bad(self): @@ -71,7 +71,7 @@ class LoginTest(test.TestCase): "notso_password", self.user.auth_url) - self.assertRaises(client.OpenstackApiAuthenticationException, + self.assertRaises(client.OpenStackApiAuthenticationException, bad_credentials_api.get_flavors) -- cgit From e161b00349a7478ac9f51f087c9f16cd345bc2d2 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 15 Mar 2011 13:23:42 -0400 Subject: adding missing view modules; modifying a couple of servers tests to use enumerate --- nova/tests/api/openstack/test_servers.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index b42cecfbb..ad2fa2497 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -358,15 +358,13 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - i = 0 - for s in res_dict['servers']: + for i,s in enumerate(res_dict['servers']): self.assertEqual(s['id'], i) self.assertEqual(s['hostId'], '') self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageId'], '10') self.assertEqual(s['flavorId'], '1') self.assertEqual(s['metadata']['seq'], i) - i += 1 def test_get_all_server_details_v1_1(self): class FakeRequestContext(object): @@ -381,15 +379,13 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - i = 0 - for s in res_dict['servers']: + for i,s in enumerate(res_dict['servers']): self.assertEqual(s['id'], i) self.assertEqual(s['hostId'], '') self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageRef'], 'http://localhost/v1.1/images/10') self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1') self.assertEqual(s['metadata']['seq'], i) - i += 1 def test_get_all_server_details_with_host(self): ''' -- cgit From 56ff68056254610c4f0eb5cd5c5432a68ed30b2f Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 15 Mar 2011 10:42:32 -0700 Subject: Support testing the OpenStack API without key_pairs --- nova/tests/api/openstack/fakes.py | 11 +++++++++-- nova/tests/api/openstack/test_servers.py | 9 ++++++++- 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index e50d11a3d..ccc853360 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -85,10 +85,17 @@ def wsgi_app(inner_application=None): return mapper -def stub_out_key_pair_funcs(stubs): +def stub_out_key_pair_funcs(stubs, have_key_pair=True): def key_pair(context, user_id): return [dict(name='key', public_key='public_key')] - stubs.Set(nova.db, 'key_pair_get_all_by_user', key_pair) + + def no_key_pair(context, user_id): + return [] + + if have_key_pair: + stubs.Set(nova.db, 'key_pair_get_all_by_user', key_pair) + else: + stubs.Set(nova.db, 'key_pair_get_all_by_user', no_key_pair) def stub_out_image_service(stubs): diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 5d7a208e9..40026a615 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -216,7 +216,7 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [1, 2]) - def test_create_instance(self): + def _test_create_instance_helper(self, with_key_pair): def instance_create(context, inst): return {'id': '1', 'display_name': 'server_test'} @@ -271,6 +271,13 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) + def test_create_instance(self): + self._test_create_instance_helper(True) + + def test_create_instance_no_key_pair(self): + fakes.stub_out_key_pair_funcs(self.stubs, False) + self._test_create_instance_helper(False) + def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' -- cgit From 4b49df7e7232dfd3e187faac52b9eb72773be360 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 15 Mar 2011 16:49:19 -0400 Subject: Major cosmetic changes to limits, but little-to-no functional changes. MUCH better testability now, no more relying on system time to tick by for limit testing. --- nova/tests/api/openstack/__init__.py | 2 +- nova/tests/api/openstack/fakes.py | 10 +- nova/tests/api/openstack/test_adminapi.py | 1 - nova/tests/api/openstack/test_ratelimiting.py | 443 +++++++++++++++++--------- 4 files changed, 299 insertions(+), 157 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index e18120285..bac7181f7 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -20,7 +20,7 @@ from nova import test from nova import context from nova import flags -from nova.api.openstack.ratelimiting import RateLimitingMiddleware +from nova.api.openstack.limits import RateLimitingMiddleware from nova.api.openstack.common import limited from nova.tests.api.openstack import fakes from webob import Request diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 7cb974bb2..ae95c0648 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -34,7 +34,7 @@ from nova import utils import nova.api.openstack.auth from nova.api import openstack from nova.api.openstack import auth -from nova.api.openstack import ratelimiting +from nova.api.openstack import limits from nova.auth.manager import User, Project from nova.image import glance from nova.image import local @@ -79,7 +79,7 @@ def wsgi_app(inner_application=None): inner_application = openstack.APIRouter() mapper = urlmap.URLMap() api = openstack.FaultWrapper(auth.AuthMiddleware( - ratelimiting.RateLimitingMiddleware(inner_application))) + limits.RateLimitingMiddleware(inner_application))) mapper['/v1.0'] = api mapper['/'] = openstack.FaultWrapper(openstack.Versions()) return mapper @@ -110,13 +110,13 @@ def stub_out_auth(stubs): def stub_out_rate_limiting(stubs): def fake_rate_init(self, app): - super(ratelimiting.RateLimitingMiddleware, self).__init__(app) + super(limits.RateLimitingMiddleware, self).__init__(app) self.application = app - stubs.Set(nova.api.openstack.ratelimiting.RateLimitingMiddleware, + stubs.Set(nova.api.openstack.limits.RateLimitingMiddleware, '__init__', fake_rate_init) - stubs.Set(nova.api.openstack.ratelimiting.RateLimitingMiddleware, + stubs.Set(nova.api.openstack.limits.RateLimitingMiddleware, '__call__', fake_wsgi) diff --git a/nova/tests/api/openstack/test_adminapi.py b/nova/tests/api/openstack/test_adminapi.py index 4568cb9f5..e87255b18 100644 --- a/nova/tests/api/openstack/test_adminapi.py +++ b/nova/tests/api/openstack/test_adminapi.py @@ -23,7 +23,6 @@ from paste import urlmap from nova import flags from nova import test from nova.api import openstack -from nova.api.openstack import ratelimiting from nova.api.openstack import auth from nova.tests.api.openstack import fakes diff --git a/nova/tests/api/openstack/test_ratelimiting.py b/nova/tests/api/openstack/test_ratelimiting.py index 9ae90ee20..c88de2db7 100644 --- a/nova/tests/api/openstack/test_ratelimiting.py +++ b/nova/tests/api/openstack/test_ratelimiting.py @@ -1,178 +1,321 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +""" +Tests dealing with HTTP rate-limiting. +""" + import httplib +import json import StringIO +import stubout import time import webob from nova import test -import nova.api.openstack.ratelimiting as ratelimiting +from nova.api.openstack import limits +from nova.api.openstack.limits import Limit + +TEST_LIMITS = [ + Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE), + Limit("POST", "*", ".*", 7, limits.PER_MINUTE), + Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE), + Limit("PUT", "*", "", 10, limits.PER_MINUTE), + Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), +] class LimiterTest(test.TestCase): + """ + Tests for the in-memory `limits.Limiter` class. + """ def setUp(self): - super(LimiterTest, self).setUp() - self.limits = { - 'a': (5, ratelimiting.PER_SECOND), - 'b': (5, ratelimiting.PER_MINUTE), - 'c': (5, ratelimiting.PER_HOUR), - 'd': (1, ratelimiting.PER_SECOND), - 'e': (100, ratelimiting.PER_SECOND)} - self.rl = ratelimiting.Limiter(self.limits) - - def exhaust(self, action, times_until_exhausted, **kwargs): - for i in range(times_until_exhausted): - when = self.rl.perform(action, **kwargs) - self.assertEqual(when, None) - num, period = self.limits[action] - delay = period * 1.0 / num - # Verify that we are now thoroughly delayed - for i in range(10): - when = self.rl.perform(action, **kwargs) - self.assertAlmostEqual(when, delay, 2) - - def test_second(self): - self.exhaust('a', 5) - time.sleep(0.2) - self.exhaust('a', 1) - time.sleep(1) - self.exhaust('a', 5) - - def test_minute(self): - self.exhaust('b', 5) - - def test_one_per_period(self): - def allow_once_and_deny_once(): - when = self.rl.perform('d') - self.assertEqual(when, None) - when = self.rl.perform('d') - self.assertAlmostEqual(when, 1, 2) - return when - time.sleep(allow_once_and_deny_once()) - time.sleep(allow_once_and_deny_once()) - allow_once_and_deny_once() - - def test_we_can_go_indefinitely_if_we_spread_out_requests(self): - for i in range(200): - when = self.rl.perform('e') - self.assertEqual(when, None) - time.sleep(0.01) - - def test_users_get_separate_buckets(self): - self.exhaust('c', 5, username='alice') - self.exhaust('c', 5, username='bob') - self.exhaust('c', 5, username='chuck') - self.exhaust('c', 0, username='chuck') - self.exhaust('c', 0, username='bob') - self.exhaust('c', 0, username='alice') - - -class FakeLimiter(object): - """Fake Limiter class that you can tell how to behave.""" - - def __init__(self, test): - self._action = self._username = self._delay = None - self.test = test - - def mock(self, action, username, delay): - self._action = action - self._username = username - self._delay = delay - - def perform(self, action, username): - self.test.assertEqual(action, self._action) - self.test.assertEqual(username, self._username) - return self._delay - - -class WSGIAppTest(test.TestCase): + """Run before each test.""" + test.TestCase.setUp(self) + self.time = 0.0 + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(limits.Limit, "_get_time", self._get_time) + self.limiter = limits.Limiter(TEST_LIMITS) + + def tearDown(self): + """Run after each test.""" + self.stubs.UnsetAll() + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def _check(self, num, verb, url, username=None): + """Check and yield results from checks.""" + for x in xrange(num): + yield self.limiter.check_for_delay(verb, url, username) + + def _check_sum(self, num, verb, url, username=None): + """Check and sum results from checks.""" + results = self._check(num, verb, url, username) + return sum(filter(lambda x: x != None, results)) + + def test_no_delay_GET(self): + """ + Simple test to ensure no delay on a single call for a limit verb we + didn"t set. + """ + delay = self.limiter.check_for_delay("GET", "/anything") + self.assertEqual(delay, None) + + def test_no_delay_PUT(self): + """ + Simple test to ensure no delay on a single call for a known limit. + """ + delay = self.limiter.check_for_delay("PUT", "/anything") + self.assertEqual(delay, None) + + def test_delay_PUT(self): + """ + Ensure the 11th PUT will result in a delay of 6.0 seconds until + the next request will be granced. + """ + expected = [None] * 10 + [6.0] + results = list(self._check(11, "PUT", "/anything")) + + self.assertEqual(expected, results) + + def test_delay_POST(self): + """ + Ensure the 8th POST will result in a delay of 6.0 seconds until + the next request will be granced. + """ + expected = [None] * 7 + results = list(self._check(7, "POST", "/anything")) + self.assertEqual(expected, results) + + expected = 60.0 / 7.0 + results = self._check_sum(1, "POST", "/anything") + self.failUnlessAlmostEqual(expected, results, 8) + + def test_delay_GET(self): + """ + Ensure the 11th GET will result in NO delay. + """ + expected = [None] * 11 + results = list(self._check(11, "GET", "/anything")) + + self.assertEqual(expected, results) + + def test_delay_PUT_servers(self): + """ + Ensure PUT on /servers limits at 5 requests, and PUT elsewhere is still + OK after 5 requests...but then after 11 total requests, PUT limiting + kicks in. + """ + # First 6 requests on PUT /servers + expected = [None] * 5 + [12.0] + results = list(self._check(6, "PUT", "/servers")) + self.assertEqual(expected, results) + + # Next 5 request on PUT /anything + expected = [None] * 4 + [6.0] + results = list(self._check(5, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_delay_PUT_wait(self): + """ + Ensure after hitting the limit and then waiting for the correct + amount of time, the limit will be lifted. + """ + expected = [None] * 10 + [6.0] + results = list(self._check(11, "PUT", "/anything")) + self.assertEqual(expected, results) + + # Advance time + self.time += 6.0 + + expected = [None, 6.0] + results = list(self._check(2, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_multiple_delays(self): + """ + Ensure multiple requests still get a delay. + """ + expected = [None] * 10 + [6.0] * 10 + results = list(self._check(20, "PUT", "/anything")) + self.assertEqual(expected, results) + + self.time += 1.0 + + expected = [5.0] * 10 + results = list(self._check(10, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_multiple_users(self): + """ + Tests involving multiple users. + """ + # User1 + expected = [None] * 10 + [6.0] * 10 + results = list(self._check(20, "PUT", "/anything", "user1")) + self.assertEqual(expected, results) + + # User2 + expected = [None] * 10 + [6.0] * 5 + results = list(self._check(15, "PUT", "/anything", "user2")) + self.assertEqual(expected, results) + + self.time += 1.0 + + # User1 again + expected = [5.0] * 10 + results = list(self._check(10, "PUT", "/anything", "user1")) + self.assertEqual(expected, results) + + self.time += 1.0 + + # User1 again + expected = [4.0] * 5 + results = list(self._check(5, "PUT", "/anything", "user2")) + self.assertEqual(expected, results) + + +class WsgiLimiterTest(test.TestCase): + """ + Tests for `limits.WsgiLimiter` class. + """ def setUp(self): - super(WSGIAppTest, self).setUp() - self.limiter = FakeLimiter(self) - self.app = ratelimiting.WSGIApp(self.limiter) + """Run before each test.""" + test.TestCase.setUp(self) + self.time = 0.0 + self.app = limits.WsgiLimiter(TEST_LIMITS) + self.app._limiter._get_time = self._get_time - def test_invalid_methods(self): - requests = [] - for method in ['GET', 'PUT', 'DELETE']: - req = webob.Request.blank('/limits/michael/breakdance', - dict(REQUEST_METHOD=method)) - requests.append(req) - for req in requests: - self.assertEqual(req.get_response(self.app).status_int, 405) - - def test_invalid_urls(self): - requests = [] - for prefix in ['limit', '', 'limiter2', 'limiter/limits', 'limiter/1']: - req = webob.Request.blank('/%s/michael/breakdance' % prefix, - dict(REQUEST_METHOD='POST')) - requests.append(req) - for req in requests: - self.assertEqual(req.get_response(self.app).status_int, 404) - - def verify(self, url, username, action, delay=None): + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def _request_data(self, verb, path): + """Get data decribing a limit request verb/path.""" + return json.dumps({"verb":verb, "path":path}) + + def _request(self, verb, url, username=None): """Make sure that POSTing to the given url causes the given username to perform the given action. Make the internal rate limiter return delay and make sure that the WSGI app returns the correct response. """ - req = webob.Request.blank(url, dict(REQUEST_METHOD='POST')) - self.limiter.mock(action, username, delay) - resp = req.get_response(self.app) - if not delay: - self.assertEqual(resp.status_int, 200) + if username: + request = webob.Request.blank("/%s" % username) else: - self.assertEqual(resp.status_int, 403) - self.assertEqual(resp.headers['X-Wait-Seconds'], "%.2f" % delay) + request = webob.Request.blank("/") + + request.method = "POST" + request.body = self._request_data(verb, url) + response = request.get_response(self.app) + + if "X-Wait-Seconds" in response.headers: + self.assertEqual(response.status_int, 403) + return response.headers["X-Wait-Seconds"] + + self.assertEqual(response.status_int, 204) - def test_good_urls(self): - self.verify('/limiter/michael/hoot', 'michael', 'hoot') + def test_invalid_methods(self): + """Only POSTs should work.""" + requests = [] + for method in ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]: + request = webob.Request.blank("/") + request.body = self._request_data("GET", "/something") + response = request.get_response(self.app) + self.assertEqual(response.status_int, 405) + + def test_good_url(self): + delay = self._request("GET", "/something") + self.assertEqual(delay, None) def test_escaping(self): - self.verify('/limiter/michael/jump%20up', 'michael', 'jump up') + delay = self._request("GET", "/something/jump%20up") + self.assertEqual(delay, None) def test_response_to_delays(self): - self.verify('/limiter/michael/hoot', 'michael', 'hoot', 1) - self.verify('/limiter/michael/hoot', 'michael', 'hoot', 1.56) - self.verify('/limiter/michael/hoot', 'michael', 'hoot', 1000) + delay = self._request("GET", "/delayed") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed") + self.assertEqual(delay, '60.00') + + def test_response_to_delays_usernames(self): + delay = self._request("GET", "/delayed", "user1") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed", "user2") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed", "user1") + self.assertEqual(delay, '60.00') + + delay = self._request("GET", "/delayed", "user2") + self.assertEqual(delay, '60.00') class FakeHttplibSocket(object): - """a fake socket implementation for httplib.HTTPResponse, trivial""" + """ + Fake `httplib.HTTPResponse` replacement. + """ def __init__(self, response_string): + """Initialize new `FakeHttplibSocket`.""" self._buffer = StringIO.StringIO(response_string) def makefile(self, _mode, _other): - """Returns the socket's internal buffer""" + """Returns the socket's internal buffer.""" return self._buffer class FakeHttplibConnection(object): - """A fake httplib.HTTPConnection - - Requests made via this connection actually get translated and routed into - our WSGI app, we then wait for the response and turn it back into - an httplib.HTTPResponse. """ - def __init__(self, app, host, is_secure=False): + Fake `httplib.HTTPConnection`. + """ + + def __init__(self, app, host): + """ + Initialize `FakeHttplibConnection`. + """ self.app = app self.host = host - def request(self, method, path, data='', headers={}): + def request(self, method, path, body="", headers={}): + """ + Requests made via this connection actually get translated and routed into + our WSGI app, we then wait for the response and turn it back into + an `httplib.HTTPResponse`. + """ req = webob.Request.blank(path) req.method = method - req.body = data req.headers = headers req.host = self.host - # Call the WSGI app, get the HTTP response + req.body = body + resp = str(req.get_response(self.app)) - # For some reason, the response doesn't have "HTTP/1.0 " prepended; I - # guess that's a function the web server usually provides. resp = "HTTP/1.0 %s" % resp sock = FakeHttplibSocket(resp) self.http_response = httplib.HTTPResponse(sock) self.http_response.begin() def getresponse(self): + """Return our generated response from the request.""" return self.http_response @@ -208,36 +351,36 @@ def wire_HTTPConnection_to_WSGI(host, app): httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) -class WSGIAppProxyTest(test.TestCase): +class WsgiLimiterProxyTest(test.TestCase): + """ + Tests for the `limits.WsgiLimiterProxy` class. + """ def setUp(self): - """Our WSGIAppProxy is going to call across an HTTPConnection to a - WSGIApp running a limiter. The proxy will send input, and the proxy - should receive that same input, pass it to the limiter who gives a - result, and send the expected result back. - - The HTTPConnection isn't real -- it's monkeypatched to point straight - at the WSGIApp. And the limiter isn't real -- it's a fake that - behaves the way we tell it to. """ - super(WSGIAppProxyTest, self).setUp() - self.limiter = FakeLimiter(self) - app = ratelimiting.WSGIApp(self.limiter) - wire_HTTPConnection_to_WSGI('100.100.100.100:80', app) - self.proxy = ratelimiting.WSGIAppProxy('100.100.100.100:80') + Do some nifty HTTP/WSGI magic which allows for WSGI to be called + directly by something like the `httplib` library. + """ + test.TestCase.setUp(self) + self.time = 0.0 + self.app = limits.WsgiLimiter(TEST_LIMITS) + self.app._limiter._get_time = self._get_time + wire_HTTPConnection_to_WSGI("169.254.0.1:80", self.app) + self.proxy = limits.WsgiLimiterProxy("169.254.0.1:80") + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time def test_200(self): - self.limiter.mock('conquer', 'caesar', None) - when = self.proxy.perform('conquer', 'caesar') - self.assertEqual(when, None) + """Successful request test.""" + delay = self.proxy.check_for_delay("GET", "/anything") + self.assertEqual(delay, None) def test_403(self): - self.limiter.mock('grumble', 'proletariat', 1.5) - when = self.proxy.perform('grumble', 'proletariat') - self.assertEqual(when, 1.5) - - def test_failure(self): - def shouldRaise(): - self.limiter.mock('murder', 'brutus', None) - self.proxy.perform('stab', 'brutus') - self.assertRaises(AssertionError, shouldRaise) + """Forbidden request test.""" + delay = self.proxy.check_for_delay("GET", "/delayed") + self.assertEqual(delay, None) + + delay = self.proxy.check_for_delay("GET", "/delayed") + self.assertEqual(delay, '60.00') -- cgit From f1acc3d199a1a92b531a3e74ed54a8b2fcdb999c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 15 Mar 2011 13:52:03 -0700 Subject: Now that the fix for 732866, stop working around the bug --- nova/tests/integrated/api/client.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 568e8c17e..fc7c344e7 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -108,10 +108,7 @@ class TestOpenStackClient(object): http_status = response.status LOG.debug(_("%(auth_uri)s => code %(http_status)s") % locals()) - # Until bug732866 is fixed, we can't check this properly... - # bug732866 - #if http_status == 401: - if http_status != 204: + if http_status == 401: raise OpenStackApiAuthenticationException(response=response) auth_headers = {} -- cgit From 1b477c2225816ea8f05595a8812932d516828e01 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 15 Mar 2011 17:47:34 -0400 Subject: pep8 fixes --- nova/tests/api/openstack/test_ratelimiting.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_ratelimiting.py b/nova/tests/api/openstack/test_ratelimiting.py index c88de2db7..a706364b4 100644 --- a/nova/tests/api/openstack/test_ratelimiting.py +++ b/nova/tests/api/openstack/test_ratelimiting.py @@ -39,6 +39,7 @@ TEST_LIMITS = [ Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), ] + class LimiterTest(test.TestCase): """ Tests for the in-memory `limits.Limiter` class. @@ -107,7 +108,7 @@ class LimiterTest(test.TestCase): expected = 60.0 / 7.0 results = self._check_sum(1, "POST", "/anything") self.failUnlessAlmostEqual(expected, results, 8) - + def test_delay_GET(self): """ Ensure the 11th GET will result in NO delay. @@ -144,7 +145,7 @@ class LimiterTest(test.TestCase): # Advance time self.time += 6.0 - + expected = [None, 6.0] results = list(self._check(2, "PUT", "/anything")) self.assertEqual(expected, results) @@ -190,8 +191,8 @@ class LimiterTest(test.TestCase): expected = [4.0] * 5 results = list(self._check(5, "PUT", "/anything", "user2")) self.assertEqual(expected, results) - - + + class WsgiLimiterTest(test.TestCase): """ Tests for `limits.WsgiLimiter` class. @@ -210,7 +211,7 @@ class WsgiLimiterTest(test.TestCase): def _request_data(self, verb, path): """Get data decribing a limit request verb/path.""" - return json.dumps({"verb":verb, "path":path}) + return json.dumps({"verb": verb, "path": path}) def _request(self, verb, url, username=None): """Make sure that POSTing to the given url causes the given username @@ -221,7 +222,7 @@ class WsgiLimiterTest(test.TestCase): request = webob.Request.blank("/%s" % username) else: request = webob.Request.blank("/") - + request.method = "POST" request.body = self._request_data(verb, url) response = request.get_response(self.app) @@ -229,7 +230,7 @@ class WsgiLimiterTest(test.TestCase): if "X-Wait-Seconds" in response.headers: self.assertEqual(response.status_int, 403) return response.headers["X-Wait-Seconds"] - + self.assertEqual(response.status_int, 204) def test_invalid_methods(self): @@ -298,8 +299,8 @@ class FakeHttplibConnection(object): def request(self, method, path, body="", headers={}): """ - Requests made via this connection actually get translated and routed into - our WSGI app, we then wait for the response and turn it back into + Requests made via this connection actually get translated and routed + into our WSGI app, we then wait for the response and turn it back into an `httplib.HTTPResponse`. """ req = webob.Request.blank(path) -- cgit From e9ef6e04786a40d20f8022bec5d23d2e4503ce3a Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 15 Mar 2011 17:56:00 -0400 Subject: s/onset_files/injected_files/g --- nova/tests/api/openstack/test_servers.py | 48 ++++++++++++------------- nova/tests/test_quota.py | 60 ++++++++++++++++---------------- 2 files changed, 54 insertions(+), 54 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 7027c7ea3..253b84be9 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -834,13 +834,13 @@ class TestServerInstanceCreation(test.TestCase): class MockComputeAPI(object): def __init__(self): - self.onset_files = None + self.injected_files = None def create(self, *args, **kwargs): - if 'onset_files' in kwargs: - self.onset_files = kwargs['onset_files'] + if 'injected_files' in kwargs: + self.injected_files = kwargs['injected_files'] else: - self.onset_files = None + self.injected_files = None return [{'id': '1234', 'display_name': 'fakeinstance'}] def set_admin_password(self, *args, **kwargs): @@ -920,46 +920,46 @@ class TestServerInstanceCreation(test.TestCase): request = self._get_create_request_json(body_dict) compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.onset_files + return request, response, compute_api.injected_files def _create_instance_with_personality_xml(self, personality): body_dict = self._create_personality_request_dict(personality) request = self._get_create_request_xml(body_dict) compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) - return request, response, compute_api.onset_files + return request, response, compute_api.injected_files def test_create_instance_with_no_personality(self): - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_json(personality=None) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, []) + self.assertEquals(injected_files, []) def test_create_instance_with_no_personality_xml(self): - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_xml(personality=None) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, []) + self.assertEquals(injected_files, []) def test_create_instance_with_personality(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) personality = [(path, b64contents)] - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(injected_files, [(path, contents)]) def test_create_instance_with_personality_xml(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Hello, World!"\n' b64contents = base64.b64encode(contents) personality = [(path, b64contents)] - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_xml(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(injected_files, [(path, contents)]) def test_create_instance_with_personality_no_path(self): personality = [('/remove/this/path', @@ -970,7 +970,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.onset_files, None) + self.assertEquals(compute_api.injected_files, None) def _test_create_instance_with_personality_no_path_xml(self): personality = [('/remove/this/path', @@ -981,7 +981,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.onset_files, None) + self.assertEquals(compute_api.injected_files, None) def test_create_instance_with_personality_no_contents(self): personality = [('/test/path', @@ -992,7 +992,7 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.onset_files, None) + self.assertEquals(compute_api.injected_files, None) def test_create_instance_with_personality_not_a_list(self): personality = [('/test/path', base64.b64encode('test\ncontents\n'))] @@ -1003,16 +1003,16 @@ class TestServerInstanceCreation(test.TestCase): compute_api, response = \ self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 400) - self.assertEquals(compute_api.onset_files, None) + self.assertEquals(compute_api.injected_files, None) def test_create_instance_with_personality_with_non_b64_content(self): path = '/my/file/path' contents = '#!/bin/bash\necho "Oh no!"\n' personality = [(path, contents)] - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 400) - self.assertEquals(onset_files, None) + self.assertEquals(injected_files, None) def test_create_instance_with_three_personalities(self): files = [ @@ -1023,19 +1023,19 @@ class TestServerInstanceCreation(test.TestCase): personality = [] for path, content in files: personality.append((path, base64.b64encode(content))) - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, files) + self.assertEquals(injected_files, files) def test_create_instance_personality_empty_content(self): path = '/my/file/path' contents = '' personality = [(path, contents)] - request, response, onset_files = \ + request, response, injected_files = \ self._create_instance_with_personality_json(personality) self.assertEquals(response.status_int, 200) - self.assertEquals(onset_files, [(path, contents)]) + self.assertEquals(injected_files, [(path, contents)]) def test_create_instance_admin_pass_json(self): request, response, dummy = \ diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index d94381aa2..c65bc459d 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -200,66 +200,66 @@ class QuotaTestCase(test.TestCase): image_id='fake', metadata=metadata) - def test_allowed_onset_files(self): + def test_allowed_injected_files(self): self.assertEqual( - quota.allowed_onset_files(self.context), - FLAGS.quota_max_onset_files) + quota.allowed_injected_files(self.context), + FLAGS.quota_max_injected_files) - def _create_with_onset_files(self, files): + def _create_with_injected_files(self, files): api = compute.API(image_service=self.StubImageService()) api.create(self.context, min_count=1, max_count=1, instance_type='m1.small', image_id='fake', - onset_files=files) + injected_files=files) - def test_no_onset_files(self): + def test_no_injected_files(self): api = compute.API(image_service=self.StubImageService()) api.create(self.context, instance_type='m1.small', image_id='fake') - def test_max_onset_files(self): + def test_max_injected_files(self): files = [] - for i in xrange(FLAGS.quota_max_onset_files): + for i in xrange(FLAGS.quota_max_injected_files): files.append(('/my/path%d' % i, 'config = test\n')) - self._create_with_onset_files(files) # no QuotaError + self._create_with_injected_files(files) # no QuotaError - def test_too_many_onset_files(self): + def test_too_many_injected_files(self): files = [] - for i in xrange(FLAGS.quota_max_onset_files + 1): + for i in xrange(FLAGS.quota_max_injected_files + 1): files.append(('/my/path%d' % i, 'my\ncontent%d\n' % i)) self.assertRaises(quota.QuotaError, - self._create_with_onset_files, files) + self._create_with_injected_files, files) - def test_allowed_onset_file_content_bytes(self): + def test_allowed_injected_file_content_bytes(self): self.assertEqual( - quota.allowed_onset_file_content_bytes(self.context), - FLAGS.quota_max_onset_file_content_bytes) + quota.allowed_injected_file_content_bytes(self.context), + FLAGS.quota_max_injected_file_content_bytes) - def test_max_onset_file_content_bytes(self): - max = FLAGS.quota_max_onset_file_content_bytes + def test_max_injected_file_content_bytes(self): + max = FLAGS.quota_max_injected_file_content_bytes content = ''.join(['a' for i in xrange(max)]) files = [('/test/path', content)] - self._create_with_onset_files(files) # no QuotaError + self._create_with_injected_files(files) # no QuotaError - def test_too_many_onset_file_content_bytes(self): - max = FLAGS.quota_max_onset_file_content_bytes + def test_too_many_injected_file_content_bytes(self): + max = FLAGS.quota_max_injected_file_content_bytes content = ''.join(['a' for i in xrange(max + 1)]) files = [('/test/path', content)] self.assertRaises(quota.QuotaError, - self._create_with_onset_files, files) + self._create_with_injected_files, files) - def test_allowed_onset_file_path_bytes(self): + def test_allowed_injected_file_path_bytes(self): self.assertEqual( - quota.allowed_onset_file_path_bytes(self.context), - FLAGS.quota_max_onset_file_path_bytes) + quota.allowed_injected_file_path_bytes(self.context), + FLAGS.quota_max_injected_file_path_bytes) - def test_max_onset_file_path_bytes(self): - max = FLAGS.quota_max_onset_file_path_bytes + def test_max_injected_file_path_bytes(self): + max = FLAGS.quota_max_injected_file_path_bytes path = ''.join(['a' for i in xrange(max)]) files = [(path, 'config = quotatest')] - self._create_with_onset_files(files) # no QuotaError + self._create_with_injected_files(files) # no QuotaError - def test_too_many_onset_file_path_bytes(self): - max = FLAGS.quota_max_onset_file_path_bytes + def test_too_many_injected_file_path_bytes(self): + max = FLAGS.quota_max_injected_file_path_bytes path = ''.join(['a' for i in xrange(max + 1)]) files = [(path, 'config = quotatest')] self.assertRaises(quota.QuotaError, - self._create_with_onset_files, files) + self._create_with_injected_files, files) -- cgit From 74068a7b504a95dc8e0339faa04c8c5520417f32 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Tue, 15 Mar 2011 18:10:25 -0400 Subject: Per Eric Day's suggest, the verson is not store in the request environ instead of the nova.context. --- nova/tests/api/openstack/fakes.py | 4 +++- nova/tests/api/openstack/test_servers.py | 16 ++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 9f8ee9b56..9c3b53ac7 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -68,7 +68,9 @@ def fake_auth_init(self, application): @webob.dec.wsgify def fake_wsgi(self, req): - req.environ['nova.context'] = context.RequestContext(1, 1, version='1.0') + req.environ['nova.context'] = context.RequestContext(1, 1) + if not req.environ.get('version'): + req.environ['version'] = '1.0' if req.body: req.environ['inst_dict'] = json.loads(req.body) return self.application diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index ac115ebf7..6b804d3b4 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -178,17 +178,12 @@ class ServersTest(test.TestCase): self.assertEqual(addresses["private"][0], private) def test_get_server_by_id_with_addresses_v1_1(self): - class FakeRequestContext(object): - def __init__(self, user, project, *args, **kwargs): - self.user_id = 1 - self.project_id = 1 - self.version = '1.1' - self.stubs.Set(context, 'RequestContext', FakeRequestContext) private = "192.168.0.3" public = ["1.2.3.4"] new_return_server = return_server_with_addresses(private, public) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) req = webob.Request.blank('/v1.1/servers/1') + req.environ['version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -367,15 +362,8 @@ class ServersTest(test.TestCase): self.assertEqual(s['metadata']['seq'], i) def test_get_all_server_details_v1_1(self): - class FakeRequestContext(object): - def __init__(self, user, project, *args, **kwargs): - self.user_id = 1 - self.project_id = 1 - self.version = '1.1' - self.is_admin = True - - self.stubs.Set(context, 'RequestContext', FakeRequestContext) req = webob.Request.blank('/v1.1/servers/detail') + req.environ['version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) -- cgit From 70769dbe239c979d97154b88a33cb34d377d1196 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 15 Mar 2011 18:12:46 -0400 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 253b84be9..a92c0f590 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -806,7 +806,7 @@ ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\ dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\ c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""", - } + }, ], }} request = self.deserializer.deserialize(serial_request) -- cgit From 6d984c3097252f9f97ef10e48be390fdf756b391 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 15 Mar 2011 16:08:22 -0700 Subject: wrap errors getting image ids from local image store --- nova/tests/api/openstack/test_images.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..2c4918117 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -151,6 +151,13 @@ class LocalImageServiceTest(test.TestCase, self.stubs.UnsetAll() super(LocalImageServiceTest, self).tearDown() + def test_get_all_ids_with_incorrect_directory_formats(self): + # create some old-style image directories (starting with 'ami-') + for x in [1, 2, 3]: + tempfile.mkstemp(prefix='ami-', dir=self.tempdir) + found_images = self.service._ids() + self.assertEqual(True, isinstance(found_images, list)) + class GlanceImageServiceTest(test.TestCase, BaseImageServiceTests): -- cgit From e237b4a5653384688b16f7fd2c0708eaec4b9ec7 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 15 Mar 2011 19:11:21 -0400 Subject: ignore differently-named nodes in personality and metadata parsing --- nova/tests/api/openstack/test_servers.py | 164 ++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 46 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index a92c0f590..ed37cb705 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -610,7 +610,7 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_minimal_request(self): serial_request = """ -""" request = self.deserializer.deserialize(serial_request) expected = {"server": { @@ -622,8 +622,10 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_empty_metadata(self): serial_request = """ -""" + + +""" request = self.deserializer.deserialize(serial_request) expected = {"server": { "name": "new-server-test", @@ -635,8 +637,10 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_empty_personality(self): serial_request = """ -""" + + +""" request = self.deserializer.deserialize(serial_request) expected = {"server": { "name": "new-server-test", @@ -648,9 +652,11 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_empty_metadata_and_personality(self): serial_request = """ -\ -""" + + + +""" request = self.deserializer.deserialize(serial_request) expected = {"server": { "name": "new-server-test", @@ -663,9 +669,11 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_empty_metadata_and_personality_reversed(self): serial_request = """ -\ -""" + + + +""" request = self.deserializer.deserialize(serial_request) expected = {"server": { "name": "new-server-test", @@ -678,28 +686,47 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_one_personality(self): serial_request = """ -\ -aabbccdd""" + + + aabbccdd + +""" request = self.deserializer.deserialize(serial_request) expected = [{"path": "/etc/conf", "contents": "aabbccdd"}] self.assertEquals(request["server"]["personality"], expected) def test_request_with_two_personalities(self): serial_request = """ -\ -aabbccdd\ + +aabbccdd abcd""" request = self.deserializer.deserialize(serial_request) expected = [{"path": "/etc/conf", "contents": "aabbccdd"}, {"path": "/etc/sudoers", "contents": "abcd"}] self.assertEquals(request["server"]["personality"], expected) + def test_request_second_personality_node_ignored(self): + serial_request = """ + + + aabbccdd + + + anything + +""" + request = self.deserializer.deserialize(serial_request) + expected = [{"path": "/etc/conf", "contents": "aabbccdd"}] + self.assertEquals(request["server"]["personality"], expected) + + def test_request_with_one_personality_missing_path(self): serial_request = """ -\ + aabbccdd""" request = self.deserializer.deserialize(serial_request) expected = [{"contents": "aabbccdd"}] @@ -707,8 +734,8 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_one_personality_empty_contents(self): serial_request = """ -\ + """ request = self.deserializer.deserialize(serial_request) expected = [{"path": "/etc/conf", "contents": ""}] @@ -716,8 +743,8 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_one_personality_empty_contents_variation(self): serial_request = """ -\ + """ request = self.deserializer.deserialize(serial_request) expected = [{"path": "/etc/conf", "contents": ""}] @@ -725,57 +752,101 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): def test_request_with_one_metadata(self): serial_request = """ -\ -beta""" + + + beta + +""" request = self.deserializer.deserialize(serial_request) expected = {"alpha": "beta"} self.assertEquals(request["server"]["metadata"], expected) def test_request_with_two_metadata(self): serial_request = """ -\ -betabar\ -""" + + + beta + bar + +""" request = self.deserializer.deserialize(serial_request) expected = {"alpha": "beta", "foo": "bar"} self.assertEquals(request["server"]["metadata"], expected) def test_request_with_metadata_missing_value(self): serial_request = """ -\ -""" + + + + +""" request = self.deserializer.deserialize(serial_request) expected = {"alpha": ""} self.assertEquals(request["server"]["metadata"], expected) + def test_request_with_two_metadata_missing_value(self): + serial_request = """ + + + + + +""" + request = self.deserializer.deserialize(serial_request) + expected = {"alpha": "", "delta": ""} + self.assertEquals(request["server"]["metadata"], expected) + def test_request_with_metadata_missing_key(self): serial_request = """ -\ -beta""" + + + beta + +""" request = self.deserializer.deserialize(serial_request) expected = {"": "beta"} self.assertEquals(request["server"]["metadata"], expected) + def test_request_with_two_metadata_missing_key(self): + serial_request = """ + + + beta + gamma + +""" + request = self.deserializer.deserialize(serial_request) + expected = {"":"gamma"} + self.assertEquals(request["server"]["metadata"], expected) + def test_request_with_metadata_duplicate_key(self): serial_request = """ -\ -barbaz\ -""" + + + bar + baz + +""" request = self.deserializer.deserialize(serial_request) expected = {"foo": "baz"} self.assertEquals(request["server"]["metadata"], expected) def test_canonical_request_from_docs(self): serial_request = """ -\ -Apache1\ -\ + + + Apache1 + + + \ ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp\ dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k\ IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs\ @@ -784,8 +855,9 @@ QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo\ ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv\ dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy\ c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6\ -b25zLiINCg0KLVJpY2hhcmQgQmFjaA==\ -""" +b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + +""" expected = {"server": { "name": "new-server-test", "imageId": "1", -- cgit From fc07caece79e379b6d6f2a3220806af9271e349b Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Tue, 15 Mar 2011 19:23:46 -0400 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index ed37cb705..9a6f2c052 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -722,7 +722,6 @@ class TestServerCreateRequestXMLDeserializer(unittest.TestCase): expected = [{"path": "/etc/conf", "contents": "aabbccdd"}] self.assertEquals(request["server"]["personality"], expected) - def test_request_with_one_personality_missing_path(self): serial_request = """ """ request = self.deserializer.deserialize(serial_request) - expected = {"":"gamma"} + expected = {"": "gamma"} self.assertEquals(request["server"]["metadata"], expected) def test_request_with_metadata_duplicate_key(self): -- cgit From bee1951ac78688e49939aee4e2285ef0ff89adb2 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Tue, 15 Mar 2011 19:55:13 -0400 Subject: As suggested by Eric Day: * changed request.environ version key to more descriptive 'api.version' * removed python3 string formatting * added licenses to headers on new files --- nova/tests/api/openstack/fakes.py | 4 ++-- nova/tests/api/openstack/test_servers.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 9c3b53ac7..a3968b57b 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -69,8 +69,8 @@ def fake_auth_init(self, application): @webob.dec.wsgify def fake_wsgi(self, req): req.environ['nova.context'] = context.RequestContext(1, 1) - if not req.environ.get('version'): - req.environ['version'] = '1.0' + if not req.environ.get('api.version'): + req.environ['api.version'] = '1.0' if req.body: req.environ['inst_dict'] = json.loads(req.body) return self.application diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6b804d3b4..27d174fe9 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -183,7 +183,7 @@ class ServersTest(test.TestCase): new_return_server = return_server_with_addresses(private, public) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) req = webob.Request.blank('/v1.1/servers/1') - req.environ['version'] = '1.1' + req.environ['api.version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], '1') @@ -363,7 +363,7 @@ class ServersTest(test.TestCase): def test_get_all_server_details_v1_1(self): req = webob.Request.blank('/v1.1/servers/detail') - req.environ['version'] = '1.1' + req.environ['api.version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) -- cgit From 5e45d0ba921566e98817cb9e62e383f84c30c5f6 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 15 Mar 2011 20:51:17 -0400 Subject: Limits controller and testing with XML and JSON serialization. --- nova/tests/api/openstack/test_limits.py | 524 ++++++++++++++++++++++++++ nova/tests/api/openstack/test_ratelimiting.py | 387 ------------------- 2 files changed, 524 insertions(+), 387 deletions(-) create mode 100644 nova/tests/api/openstack/test_limits.py delete mode 100644 nova/tests/api/openstack/test_ratelimiting.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py new file mode 100644 index 000000000..cf4389c1d --- /dev/null +++ b/nova/tests/api/openstack/test_limits.py @@ -0,0 +1,524 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +""" +Tests dealing with HTTP rate-limiting. +""" + +import httplib +import json +import StringIO +import stubout +import time +import webob + +from xml.dom.minidom import parseString + +from nova import test +from nova.api.openstack import limits +from nova.api.openstack.limits import Limit + + +TEST_LIMITS = [ + Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE), + Limit("POST", "*", ".*", 7, limits.PER_MINUTE), + Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE), + Limit("PUT", "*", "", 10, limits.PER_MINUTE), + Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), +] + + +class LimitsControllerTest(test.TestCase): + """ + Tests for `limits.LimitsController` class. + """ + + def setUp(self): + """Run before each test.""" + test.TestCase.setUp(self) + self.time = 0.0 + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(limits.Limit, "_get_time", self._get_time) + self.controller = limits.LimitsController() + + def tearDown(self): + """Run after each test.""" + self.stubs.UnsetAll() + test.TestCase.tearDown(self) + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def _get_index_request(self, accept_header="application/json"): + """Helper to set routing arguments.""" + request = webob.Request.blank("/") + request.accept = accept_header + request.environ["wsgiorg.routing_args"] = (None, { + "action": "index", + "controller": "", + }) + return request + + def _populate_limits(self, request): + """Put limit info into a request.""" + limits = [ + Limit("GET", "*", ".*", 10, 60).display(), + Limit("POST", "*", ".*", 5, 60 * 60).display(), + ] + request.environ["nova.limits"] = limits + return request + + def test_empty_index_json(self): + """Test getting empty limit details in JSON.""" + request = self._get_index_request() + response = request.get_response(self.controller) + expected = { + "limits": { + "rate": [], + "absolute": {}, + }, + } + body = json.loads(response.body) + self.assertEqual(expected, body) + + def test_index_json(self): + """Test getting limit details in JSON.""" + request = self._get_index_request() + request = self._populate_limits(request) + response = request.get_response(self.controller) + expected = { + "limits": { + "rate": [{ + "regex": ".*", + "resetTime": 0, + "URI": "*", + "value": 10, + "verb": "GET", + "remaining": 10, + "unit": "MINUTE", + }, + { + "regex": ".*", + "resetTime": 0, + "URI": "*", + "value": 5, + "verb": "POST", + "remaining": 5, + "unit": "HOUR", + }], + "absolute": {}, + }, + } + body = json.loads(response.body) + self.assertEqual(expected, body) + + def test_empty_index_xml(self): + """Test getting limit details in XML.""" + request = self._get_index_request("application/xml") + response = request.get_response(self.controller) + + expected = "" + body = response.body.replace("\n","").replace(" ", "") + + self.assertEqual(expected, body) + + def test_index_xml(self): + """Test getting limit details in XML.""" + request = self._get_index_request("application/xml") + request = self._populate_limits(request) + response = request.get_response(self.controller) + + expected = parseString(""" + + + + + + + + """.replace(" ", "")) + body = parseString(response.body.replace(" ", "")) + + self.assertEqual(expected.toxml(), body.toxml()) + + +class LimiterTest(test.TestCase): + """ + Tests for the in-memory `limits.Limiter` class. + """ + + def setUp(self): + """Run before each test.""" + test.TestCase.setUp(self) + self.time = 0.0 + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(limits.Limit, "_get_time", self._get_time) + self.limiter = limits.Limiter(TEST_LIMITS) + + def tearDown(self): + """Run after each test.""" + self.stubs.UnsetAll() + test.TestCase.tearDown(self) + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def _check(self, num, verb, url, username=None): + """Check and yield results from checks.""" + for x in xrange(num): + yield self.limiter.check_for_delay(verb, url, username)[0] + + def _check_sum(self, num, verb, url, username=None): + """Check and sum results from checks.""" + results = self._check(num, verb, url, username) + return sum(filter(lambda x: x != None, results)) + + def test_no_delay_GET(self): + """ + Simple test to ensure no delay on a single call for a limit verb we + didn"t set. + """ + delay = self.limiter.check_for_delay("GET", "/anything") + self.assertEqual(delay, (None, None)) + + def test_no_delay_PUT(self): + """ + Simple test to ensure no delay on a single call for a known limit. + """ + delay = self.limiter.check_for_delay("PUT", "/anything") + self.assertEqual(delay, (None, None)) + + def test_delay_PUT(self): + """ + Ensure the 11th PUT will result in a delay of 6.0 seconds until + the next request will be granced. + """ + expected = [None] * 10 + [6.0] + results = list(self._check(11, "PUT", "/anything")) + + self.assertEqual(expected, results) + + def test_delay_POST(self): + """ + Ensure the 8th POST will result in a delay of 6.0 seconds until + the next request will be granced. + """ + expected = [None] * 7 + results = list(self._check(7, "POST", "/anything")) + self.assertEqual(expected, results) + + expected = 60.0 / 7.0 + results = self._check_sum(1, "POST", "/anything") + self.failUnlessAlmostEqual(expected, results, 8) + + def test_delay_GET(self): + """ + Ensure the 11th GET will result in NO delay. + """ + expected = [None] * 11 + results = list(self._check(11, "GET", "/anything")) + + self.assertEqual(expected, results) + + def test_delay_PUT_servers(self): + """ + Ensure PUT on /servers limits at 5 requests, and PUT elsewhere is still + OK after 5 requests...but then after 11 total requests, PUT limiting + kicks in. + """ + # First 6 requests on PUT /servers + expected = [None] * 5 + [12.0] + results = list(self._check(6, "PUT", "/servers")) + self.assertEqual(expected, results) + + # Next 5 request on PUT /anything + expected = [None] * 4 + [6.0] + results = list(self._check(5, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_delay_PUT_wait(self): + """ + Ensure after hitting the limit and then waiting for the correct + amount of time, the limit will be lifted. + """ + expected = [None] * 10 + [6.0] + results = list(self._check(11, "PUT", "/anything")) + self.assertEqual(expected, results) + + # Advance time + self.time += 6.0 + + expected = [None, 6.0] + results = list(self._check(2, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_multiple_delays(self): + """ + Ensure multiple requests still get a delay. + """ + expected = [None] * 10 + [6.0] * 10 + results = list(self._check(20, "PUT", "/anything")) + self.assertEqual(expected, results) + + self.time += 1.0 + + expected = [5.0] * 10 + results = list(self._check(10, "PUT", "/anything")) + self.assertEqual(expected, results) + + def test_multiple_users(self): + """ + Tests involving multiple users. + """ + # User1 + expected = [None] * 10 + [6.0] * 10 + results = list(self._check(20, "PUT", "/anything", "user1")) + self.assertEqual(expected, results) + + # User2 + expected = [None] * 10 + [6.0] * 5 + results = list(self._check(15, "PUT", "/anything", "user2")) + self.assertEqual(expected, results) + + self.time += 1.0 + + # User1 again + expected = [5.0] * 10 + results = list(self._check(10, "PUT", "/anything", "user1")) + self.assertEqual(expected, results) + + self.time += 1.0 + + # User1 again + expected = [4.0] * 5 + results = list(self._check(5, "PUT", "/anything", "user2")) + self.assertEqual(expected, results) + + +class WsgiLimiterTest(test.TestCase): + """ + Tests for `limits.WsgiLimiter` class. + """ + + def setUp(self): + """Run before each test.""" + test.TestCase.setUp(self) + self.time = 0.0 + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(limits.Limit, "_get_time", self._get_time) + self.app = limits.WsgiLimiter(TEST_LIMITS) + + def tearDown(self): + """Run after each test.""" + self.stubs.UnsetAll() + test.TestCase.tearDown(self) + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def _request_data(self, verb, path): + """Get data decribing a limit request verb/path.""" + return json.dumps({"verb": verb, "path": path}) + + def _request(self, verb, url, username=None): + """Make sure that POSTing to the given url causes the given username + to perform the given action. Make the internal rate limiter return + delay and make sure that the WSGI app returns the correct response. + """ + if username: + request = webob.Request.blank("/%s" % username) + else: + request = webob.Request.blank("/") + + request.method = "POST" + request.body = self._request_data(verb, url) + response = request.get_response(self.app) + + if "X-Wait-Seconds" in response.headers: + self.assertEqual(response.status_int, 403) + return response.headers["X-Wait-Seconds"] + + self.assertEqual(response.status_int, 204) + + def test_invalid_methods(self): + """Only POSTs should work.""" + requests = [] + for method in ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]: + request = webob.Request.blank("/") + request.body = self._request_data("GET", "/something") + response = request.get_response(self.app) + self.assertEqual(response.status_int, 405) + + def test_good_url(self): + delay = self._request("GET", "/something") + self.assertEqual(delay, None) + + def test_escaping(self): + delay = self._request("GET", "/something/jump%20up") + self.assertEqual(delay, None) + + def test_response_to_delays(self): + delay = self._request("GET", "/delayed") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed") + self.assertEqual(delay, '60.00') + + def test_response_to_delays_usernames(self): + delay = self._request("GET", "/delayed", "user1") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed", "user2") + self.assertEqual(delay, None) + + delay = self._request("GET", "/delayed", "user1") + self.assertEqual(delay, '60.00') + + delay = self._request("GET", "/delayed", "user2") + self.assertEqual(delay, '60.00') + + +class FakeHttplibSocket(object): + """ + Fake `httplib.HTTPResponse` replacement. + """ + + def __init__(self, response_string): + """Initialize new `FakeHttplibSocket`.""" + self._buffer = StringIO.StringIO(response_string) + + def makefile(self, _mode, _other): + """Returns the socket's internal buffer.""" + return self._buffer + + +class FakeHttplibConnection(object): + """ + Fake `httplib.HTTPConnection`. + """ + + def __init__(self, app, host): + """ + Initialize `FakeHttplibConnection`. + """ + self.app = app + self.host = host + + def request(self, method, path, body="", headers={}): + """ + Requests made via this connection actually get translated and routed + into our WSGI app, we then wait for the response and turn it back into + an `httplib.HTTPResponse`. + """ + req = webob.Request.blank(path) + req.method = method + req.headers = headers + req.host = self.host + req.body = body + + resp = str(req.get_response(self.app)) + resp = "HTTP/1.0 %s" % resp + sock = FakeHttplibSocket(resp) + self.http_response = httplib.HTTPResponse(sock) + self.http_response.begin() + + def getresponse(self): + """Return our generated response from the request.""" + return self.http_response + + +def wire_HTTPConnection_to_WSGI(host, app): + """Monkeypatches HTTPConnection so that if you try to connect to host, you + are instead routed straight to the given WSGI app. + + After calling this method, when any code calls + + httplib.HTTPConnection(host) + + the connection object will be a fake. Its requests will be sent directly + to the given WSGI app rather than through a socket. + + Code connecting to hosts other than host will not be affected. + + This method may be called multiple times to map different hosts to + different apps. + """ + class HTTPConnectionDecorator(object): + """Wraps the real HTTPConnection class so that when you instantiate + the class you might instead get a fake instance.""" + + def __init__(self, wrapped): + self.wrapped = wrapped + + def __call__(self, connection_host, *args, **kwargs): + if connection_host == host: + return FakeHttplibConnection(app, host) + else: + return self.wrapped(connection_host, *args, **kwargs) + + httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) + + +class WsgiLimiterProxyTest(test.TestCase): + """ + Tests for the `limits.WsgiLimiterProxy` class. + """ + + def setUp(self): + """ + Do some nifty HTTP/WSGI magic which allows for WSGI to be called + directly by something like the `httplib` library. + """ + test.TestCase.setUp(self) + self.time = 0.0 + self.stubs = stubout.StubOutForTesting() + self.stubs.Set(limits.Limit, "_get_time", self._get_time) + self.app = limits.WsgiLimiter(TEST_LIMITS) + wire_HTTPConnection_to_WSGI("169.254.0.1:80", self.app) + self.proxy = limits.WsgiLimiterProxy("169.254.0.1:80") + + def tearDown(self): + """Run after each test.""" + self.stubs.UnsetAll() + test.TestCase.tearDown(self) + + def _get_time(self): + """Return the "time" according to this test suite.""" + return self.time + + def test_200(self): + """Successful request test.""" + delay = self.proxy.check_for_delay("GET", "/anything") + self.assertEqual(delay, (None, None)) + + def test_403(self): + """Forbidden request test.""" + delay = self.proxy.check_for_delay("GET", "/delayed") + self.assertEqual(delay, (None, None)) + + delay, error = self.proxy.check_for_delay("GET", "/delayed") + error = error.strip() + + expected = ("60.00", "403 Forbidden\n\nOnly 1 GET request(s) can be "\ + "made to /delayed every minute.") + + self.assertEqual((delay, error), expected) diff --git a/nova/tests/api/openstack/test_ratelimiting.py b/nova/tests/api/openstack/test_ratelimiting.py deleted file mode 100644 index a706364b4..000000000 --- a/nova/tests/api/openstack/test_ratelimiting.py +++ /dev/null @@ -1,387 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -""" -Tests dealing with HTTP rate-limiting. -""" - -import httplib -import json -import StringIO -import stubout -import time -import webob - -from nova import test -from nova.api.openstack import limits -from nova.api.openstack.limits import Limit - - -TEST_LIMITS = [ - Limit("GET", "/delayed", "^/delayed", 1, limits.PER_MINUTE), - Limit("POST", "*", ".*", 7, limits.PER_MINUTE), - Limit("POST", "/servers", "^/servers", 3, limits.PER_MINUTE), - Limit("PUT", "*", "", 10, limits.PER_MINUTE), - Limit("PUT", "/servers", "^/servers", 5, limits.PER_MINUTE), -] - - -class LimiterTest(test.TestCase): - """ - Tests for the in-memory `limits.Limiter` class. - """ - - def setUp(self): - """Run before each test.""" - test.TestCase.setUp(self) - self.time = 0.0 - self.stubs = stubout.StubOutForTesting() - self.stubs.Set(limits.Limit, "_get_time", self._get_time) - self.limiter = limits.Limiter(TEST_LIMITS) - - def tearDown(self): - """Run after each test.""" - self.stubs.UnsetAll() - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - - def _check(self, num, verb, url, username=None): - """Check and yield results from checks.""" - for x in xrange(num): - yield self.limiter.check_for_delay(verb, url, username) - - def _check_sum(self, num, verb, url, username=None): - """Check and sum results from checks.""" - results = self._check(num, verb, url, username) - return sum(filter(lambda x: x != None, results)) - - def test_no_delay_GET(self): - """ - Simple test to ensure no delay on a single call for a limit verb we - didn"t set. - """ - delay = self.limiter.check_for_delay("GET", "/anything") - self.assertEqual(delay, None) - - def test_no_delay_PUT(self): - """ - Simple test to ensure no delay on a single call for a known limit. - """ - delay = self.limiter.check_for_delay("PUT", "/anything") - self.assertEqual(delay, None) - - def test_delay_PUT(self): - """ - Ensure the 11th PUT will result in a delay of 6.0 seconds until - the next request will be granced. - """ - expected = [None] * 10 + [6.0] - results = list(self._check(11, "PUT", "/anything")) - - self.assertEqual(expected, results) - - def test_delay_POST(self): - """ - Ensure the 8th POST will result in a delay of 6.0 seconds until - the next request will be granced. - """ - expected = [None] * 7 - results = list(self._check(7, "POST", "/anything")) - self.assertEqual(expected, results) - - expected = 60.0 / 7.0 - results = self._check_sum(1, "POST", "/anything") - self.failUnlessAlmostEqual(expected, results, 8) - - def test_delay_GET(self): - """ - Ensure the 11th GET will result in NO delay. - """ - expected = [None] * 11 - results = list(self._check(11, "GET", "/anything")) - - self.assertEqual(expected, results) - - def test_delay_PUT_servers(self): - """ - Ensure PUT on /servers limits at 5 requests, and PUT elsewhere is still - OK after 5 requests...but then after 11 total requests, PUT limiting - kicks in. - """ - # First 6 requests on PUT /servers - expected = [None] * 5 + [12.0] - results = list(self._check(6, "PUT", "/servers")) - self.assertEqual(expected, results) - - # Next 5 request on PUT /anything - expected = [None] * 4 + [6.0] - results = list(self._check(5, "PUT", "/anything")) - self.assertEqual(expected, results) - - def test_delay_PUT_wait(self): - """ - Ensure after hitting the limit and then waiting for the correct - amount of time, the limit will be lifted. - """ - expected = [None] * 10 + [6.0] - results = list(self._check(11, "PUT", "/anything")) - self.assertEqual(expected, results) - - # Advance time - self.time += 6.0 - - expected = [None, 6.0] - results = list(self._check(2, "PUT", "/anything")) - self.assertEqual(expected, results) - - def test_multiple_delays(self): - """ - Ensure multiple requests still get a delay. - """ - expected = [None] * 10 + [6.0] * 10 - results = list(self._check(20, "PUT", "/anything")) - self.assertEqual(expected, results) - - self.time += 1.0 - - expected = [5.0] * 10 - results = list(self._check(10, "PUT", "/anything")) - self.assertEqual(expected, results) - - def test_multiple_users(self): - """ - Tests involving multiple users. - """ - # User1 - expected = [None] * 10 + [6.0] * 10 - results = list(self._check(20, "PUT", "/anything", "user1")) - self.assertEqual(expected, results) - - # User2 - expected = [None] * 10 + [6.0] * 5 - results = list(self._check(15, "PUT", "/anything", "user2")) - self.assertEqual(expected, results) - - self.time += 1.0 - - # User1 again - expected = [5.0] * 10 - results = list(self._check(10, "PUT", "/anything", "user1")) - self.assertEqual(expected, results) - - self.time += 1.0 - - # User1 again - expected = [4.0] * 5 - results = list(self._check(5, "PUT", "/anything", "user2")) - self.assertEqual(expected, results) - - -class WsgiLimiterTest(test.TestCase): - """ - Tests for `limits.WsgiLimiter` class. - """ - - def setUp(self): - """Run before each test.""" - test.TestCase.setUp(self) - self.time = 0.0 - self.app = limits.WsgiLimiter(TEST_LIMITS) - self.app._limiter._get_time = self._get_time - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - - def _request_data(self, verb, path): - """Get data decribing a limit request verb/path.""" - return json.dumps({"verb": verb, "path": path}) - - def _request(self, verb, url, username=None): - """Make sure that POSTing to the given url causes the given username - to perform the given action. Make the internal rate limiter return - delay and make sure that the WSGI app returns the correct response. - """ - if username: - request = webob.Request.blank("/%s" % username) - else: - request = webob.Request.blank("/") - - request.method = "POST" - request.body = self._request_data(verb, url) - response = request.get_response(self.app) - - if "X-Wait-Seconds" in response.headers: - self.assertEqual(response.status_int, 403) - return response.headers["X-Wait-Seconds"] - - self.assertEqual(response.status_int, 204) - - def test_invalid_methods(self): - """Only POSTs should work.""" - requests = [] - for method in ["GET", "PUT", "DELETE", "HEAD", "OPTIONS"]: - request = webob.Request.blank("/") - request.body = self._request_data("GET", "/something") - response = request.get_response(self.app) - self.assertEqual(response.status_int, 405) - - def test_good_url(self): - delay = self._request("GET", "/something") - self.assertEqual(delay, None) - - def test_escaping(self): - delay = self._request("GET", "/something/jump%20up") - self.assertEqual(delay, None) - - def test_response_to_delays(self): - delay = self._request("GET", "/delayed") - self.assertEqual(delay, None) - - delay = self._request("GET", "/delayed") - self.assertEqual(delay, '60.00') - - def test_response_to_delays_usernames(self): - delay = self._request("GET", "/delayed", "user1") - self.assertEqual(delay, None) - - delay = self._request("GET", "/delayed", "user2") - self.assertEqual(delay, None) - - delay = self._request("GET", "/delayed", "user1") - self.assertEqual(delay, '60.00') - - delay = self._request("GET", "/delayed", "user2") - self.assertEqual(delay, '60.00') - - -class FakeHttplibSocket(object): - """ - Fake `httplib.HTTPResponse` replacement. - """ - - def __init__(self, response_string): - """Initialize new `FakeHttplibSocket`.""" - self._buffer = StringIO.StringIO(response_string) - - def makefile(self, _mode, _other): - """Returns the socket's internal buffer.""" - return self._buffer - - -class FakeHttplibConnection(object): - """ - Fake `httplib.HTTPConnection`. - """ - - def __init__(self, app, host): - """ - Initialize `FakeHttplibConnection`. - """ - self.app = app - self.host = host - - def request(self, method, path, body="", headers={}): - """ - Requests made via this connection actually get translated and routed - into our WSGI app, we then wait for the response and turn it back into - an `httplib.HTTPResponse`. - """ - req = webob.Request.blank(path) - req.method = method - req.headers = headers - req.host = self.host - req.body = body - - resp = str(req.get_response(self.app)) - resp = "HTTP/1.0 %s" % resp - sock = FakeHttplibSocket(resp) - self.http_response = httplib.HTTPResponse(sock) - self.http_response.begin() - - def getresponse(self): - """Return our generated response from the request.""" - return self.http_response - - -def wire_HTTPConnection_to_WSGI(host, app): - """Monkeypatches HTTPConnection so that if you try to connect to host, you - are instead routed straight to the given WSGI app. - - After calling this method, when any code calls - - httplib.HTTPConnection(host) - - the connection object will be a fake. Its requests will be sent directly - to the given WSGI app rather than through a socket. - - Code connecting to hosts other than host will not be affected. - - This method may be called multiple times to map different hosts to - different apps. - """ - class HTTPConnectionDecorator(object): - """Wraps the real HTTPConnection class so that when you instantiate - the class you might instead get a fake instance.""" - - def __init__(self, wrapped): - self.wrapped = wrapped - - def __call__(self, connection_host, *args, **kwargs): - if connection_host == host: - return FakeHttplibConnection(app, host) - else: - return self.wrapped(connection_host, *args, **kwargs) - - httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) - - -class WsgiLimiterProxyTest(test.TestCase): - """ - Tests for the `limits.WsgiLimiterProxy` class. - """ - - def setUp(self): - """ - Do some nifty HTTP/WSGI magic which allows for WSGI to be called - directly by something like the `httplib` library. - """ - test.TestCase.setUp(self) - self.time = 0.0 - self.app = limits.WsgiLimiter(TEST_LIMITS) - self.app._limiter._get_time = self._get_time - wire_HTTPConnection_to_WSGI("169.254.0.1:80", self.app) - self.proxy = limits.WsgiLimiterProxy("169.254.0.1:80") - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - - def test_200(self): - """Successful request test.""" - delay = self.proxy.check_for_delay("GET", "/anything") - self.assertEqual(delay, None) - - def test_403(self): - """Forbidden request test.""" - delay = self.proxy.check_for_delay("GET", "/delayed") - self.assertEqual(delay, None) - - delay = self.proxy.check_for_delay("GET", "/delayed") - self.assertEqual(delay, '60.00') -- cgit From 5ba3e21875d3cf3b71082477311902891706eee4 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 15 Mar 2011 21:09:26 -0400 Subject: Removed VIM specific stuff and changed copyright from 2010 to 2011. --- nova/tests/api/openstack/test_limits.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index cf4389c1d..40178e671 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -1,6 +1,4 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 OpenStack LLC. +# Copyright 2011 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may -- cgit From 60c7ce60826becb1ebe7f75a0a0d28b2893d70c0 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Tue, 15 Mar 2011 18:54:51 -0700 Subject: revised per code review --- nova/tests/api/openstack/test_images.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 2c4918117..a674ccefe 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -22,6 +22,7 @@ and as a WSGI layer import json import datetime +import os import shutil import tempfile @@ -155,8 +156,12 @@ class LocalImageServiceTest(test.TestCase, # create some old-style image directories (starting with 'ami-') for x in [1, 2, 3]: tempfile.mkstemp(prefix='ami-', dir=self.tempdir) - found_images = self.service._ids() - self.assertEqual(True, isinstance(found_images, list)) + # create some valid image directories names + for x in ["1485baed", "1a60f0ee", "3123a73d"]: + os.makedirs(os.path.join(self.tempdir, x)) + found_image_ids = self.service._ids() + self.assertEqual(True, isinstance(found_image_ids, list)) + self.assertEqual(3, len(found_image_ids), len(found_image_ids)) class GlanceImageServiceTest(test.TestCase, -- cgit From 0053b776276e9cac617c812931c248be7e49fea2 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Tue, 15 Mar 2011 23:00:09 -0400 Subject: Add ResponseExtensions. --- nova/tests/api/openstack/extensions/widgets.py | 26 +++++-- nova/tests/api/openstack/test_extensions.py | 103 ++++++++++++++++++------- 2 files changed, 95 insertions(+), 34 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py index d5a2d95d9..f463721f1 100644 --- a/nova/tests/api/openstack/extensions/widgets.py +++ b/nova/tests/api/openstack/extensions/widgets.py @@ -1,3 +1,5 @@ +import json + from nova import wsgi from nova.api.openstack import extensions @@ -9,28 +11,40 @@ class WidgetsController(wsgi.Controller): return "Buy more widgets!" -class WidgetsExtension(object): +class Widgets(object): def __init__(self): pass def get_resources(self): resources = [] - widgets = extensions.ExtensionResource('widget', 'widgets', + widgets = extensions.ResourceExtension('widgets', WidgetsController()) resources.append(widgets) return resources def get_actions(self): actions = [] - actions.append(extensions.ExtensionAction('server', 'servers', - 'add_widget', + actions.append(extensions.ActionExtension('servers', 'add_widget', self._add_widget)) - actions.append(extensions.ExtensionAction('server', 'servers', - 'delete_widget', + actions.append(extensions.ActionExtension('servers', 'delete_widget', self._delete_widget)) return actions + def get_response_extensions(self): + response_exts = [] + + def _resp_handler(res): + # only handle JSON responses + data = json.loads(res.body) + data['flavor']['widgets'] = "Buy more widgets!" + return data + + widgets = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + _resp_handler) + response_exts.append(widgets) + return response_exts + def _add_widget(self, input_dict, req, id): return "Widget Added." diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 080760c14..8725c8f0e 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -16,13 +16,17 @@ # under the License. import json +import stubout import unittest import webob import os.path +from nova import context from nova import flags from nova.api import openstack from nova.api.openstack import extensions +from nova.api.openstack import flavors +from nova.tests.api.openstack import fakes import nova.wsgi FLAGS = flags.FLAGS @@ -39,21 +43,31 @@ class StubController(nova.wsgi.Controller): class StubExtensionManager(object): - def __init__(self, resource): - self.resource = resource + def __init__(self, resource_ext=None, action_ext=None, response_ext=None): + self.resource_ext = resource_ext + self.action_ext = action_ext + self.response_ext = response_ext def get_resources(self): - resources = [] - if self.resource: - resources.append(self.resource) - return resources + resource_exts = [] + if self.resource_ext: + resource_exts.append(self.resource_ext) + return resource_exts def get_actions(self): - actions = [] - return actions + action_exts = [] + if self.action_ext: + action_exts.append(self.action_ext) + return action_exts + def get_response_extensions(self): + response_exts = [] + if self.response_ext: + response_exts.append(self.response_ext) + return response_exts -class ExtensionResourceTest(unittest.TestCase): + +class ResourceExtensionTest(unittest.TestCase): def test_no_extension_present(self): manager = StubExtensionManager(None) @@ -65,7 +79,7 @@ class ExtensionResourceTest(unittest.TestCase): def test_get_resources(self): response_body = "Buy more widgets!" - widgets = extensions.ExtensionResource('widget', 'widgets', + widgets = extensions.ResourceExtension('widgets', StubController(response_body)) manager = StubExtensionManager(widgets) app = openstack.APIRouter() @@ -77,7 +91,7 @@ class ExtensionResourceTest(unittest.TestCase): def test_get_resources_with_controller(self): response_body = "Buy more widgets!" - widgets = extensions.ExtensionResource('widget', 'widgets', + widgets = extensions.ResourceExtension('widgets', StubController(response_body)) manager = StubExtensionManager(widgets) app = openstack.APIRouter() @@ -103,40 +117,73 @@ class ExtensionManagerTest(unittest.TestCase): self.assertEqual("Buy more widgets!", response.body) -class ExtendedActionTest(unittest.TestCase): +class ActionExtensionTest(unittest.TestCase): def setUp(self): FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), "extensions") - def test_extended_action(self): + def _send_server_action_request(self, url, body): app = openstack.APIRouter() ext_midware = extensions.ExtensionMiddleware(app) - body = dict(add_widget=dict(name="test")) - request = webob.Request.blank("/servers/1/action") + request = webob.Request.blank(url) request.method = 'POST' request.content_type = 'application/json' request.body = json.dumps(body) response = request.get_response(ext_midware) + return response + + def test_extended_action(self): + body = dict(add_widget=dict(name="test")) + response = self._send_server_action_request("/servers/1/action", body) self.assertEqual(200, response.status_int) self.assertEqual("Widget Added.", response.body) + body = dict(delete_widget=dict(name="test")) + response = self._send_server_action_request("/servers/1/action", body) + self.assertEqual(200, response.status_int) + self.assertEqual("Widget Deleted.", response.body) + def test_invalid_action_body(self): - app = openstack.APIRouter() - ext_midware = extensions.ExtensionMiddleware(app) body = dict(blah=dict(name="test")) # Doesn't exist - request = webob.Request.blank("/servers/1/action") - request.method = 'POST' - request.content_type = 'application/json' - request.body = json.dumps(body) - response = request.get_response(ext_midware) + response = self._send_server_action_request("/servers/1/action", body) self.assertEqual(501, response.status_int) def test_invalid_action(self): - app = openstack.APIRouter() - ext_midware = extensions.ExtensionMiddleware(app) - request = webob.Request.blank("/asdf/1/action") - request.method = 'POST' - request.content_type = 'application/json' - response = request.get_response(ext_midware) + body = dict(blah=dict(name="test")) + response = self._send_server_action_request("/asdf/1/action", body) self.assertEqual(404, response.status_int) + + +class ResponseExtensionTest(unittest.TestCase): + + def setUp(self): + super(ResponseExtensionTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.reset_fake_data() + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + fakes.stub_out_auth(self.stubs) + self.context = context.get_admin_context() + + def test_get_resources(self): + + test_resp = "Buy more widgets!" + + def _resp_handler(res): + # only handle JSON responses + data = json.loads(res.body) + data['flavor']['widgets'] = test_resp + return data + + widgets = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + _resp_handler) + manager = StubExtensionManager(None, None, widgets) + app = fakes.wsgi_app() + ext_midware = extensions.ExtensionMiddleware(app, manager) + request = webob.Request.blank("/v1.0/flavors/1") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + response_data = json.loads(response.body) + self.assertEqual(test_resp, response_data['flavor']['widgets']) -- cgit From be9a218e2e4b01fe19722fb0073731d8ae6a7eea Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 15 Mar 2011 23:13:05 -0400 Subject: Added tests back for RateLimitingMiddleware which now throw correctly serialized errors with correct error codes. Removed some error printing, and simplified some other parts of the code with suggestions from teammates. --- nova/tests/api/openstack/test_limits.py | 172 ++++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 55 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index 40178e671..d1db93a59 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -22,11 +22,11 @@ import json import StringIO import stubout import time +import unittest import webob from xml.dom.minidom import parseString -from nova import test from nova.api.openstack import limits from nova.api.openstack.limits import Limit @@ -40,28 +40,34 @@ TEST_LIMITS = [ ] -class LimitsControllerTest(test.TestCase): - """ - Tests for `limits.LimitsController` class. - """ +class BaseLimitTestSuite(unittest.TestCase): + """Base test suite which provides relevant stubs and time abstraction.""" def setUp(self): """Run before each test.""" - test.TestCase.setUp(self) self.time = 0.0 self.stubs = stubout.StubOutForTesting() self.stubs.Set(limits.Limit, "_get_time", self._get_time) - self.controller = limits.LimitsController() def tearDown(self): """Run after each test.""" self.stubs.UnsetAll() - test.TestCase.tearDown(self) def _get_time(self): """Return the "time" according to this test suite.""" return self.time + +class LimitsControllerTest(BaseLimitTestSuite): + """ + Tests for `limits.LimitsController` class. + """ + + def setUp(self): + """Run before each test.""" + BaseLimitTestSuite.setUp(self) + self.controller = limits.LimitsController() + def _get_index_request(self, accept_header="application/json"): """Helper to set routing arguments.""" request = webob.Request.blank("/") @@ -74,11 +80,11 @@ class LimitsControllerTest(test.TestCase): def _populate_limits(self, request): """Put limit info into a request.""" - limits = [ + _limits = [ Limit("GET", "*", ".*", 10, 60).display(), Limit("POST", "*", ".*", 5, 60 * 60).display(), ] - request.environ["nova.limits"] = limits + request.environ["nova.limits"] = _limits return request def test_empty_index_json(self): @@ -131,7 +137,7 @@ class LimitsControllerTest(test.TestCase): response = request.get_response(self.controller) expected = "" - body = response.body.replace("\n","").replace(" ", "") + body = response.body.replace("\n", "").replace(" ", "") self.assertEqual(expected, body) @@ -144,7 +150,7 @@ class LimitsControllerTest(test.TestCase): expected = parseString(""" - @@ -157,28 +163,108 @@ class LimitsControllerTest(test.TestCase): self.assertEqual(expected.toxml(), body.toxml()) -class LimiterTest(test.TestCase): +class LimitMiddlewareTest(BaseLimitTestSuite): + """ + Tests for the `limits.RateLimitingMiddleware` class. + """ + + @webob.dec.wsgify + def _empty_app(self, request): + """Do-nothing WSGI app.""" + pass + + def setUp(self): + """Prepare middleware for use through fake WSGI app.""" + BaseLimitTestSuite.setUp(self) + _limits = [ + Limit("GET", "*", ".*", 1, 60), + ] + self.app = limits.RateLimitingMiddleware(self._empty_app, _limits) + + def test_good_request(self): + """Test successful GET request through middleware.""" + request = webob.Request.blank("/") + response = request.get_response(self.app) + self.assertEqual(200, response.status_int) + + def test_limited_request_json(self): + """Test a rate-limited (403) GET request through middleware.""" + request = webob.Request.blank("/") + response = request.get_response(self.app) + self.assertEqual(200, response.status_int) + + request = webob.Request.blank("/") + response = request.get_response(self.app) + self.assertEqual(response.status_int, 403) + + body = json.loads(response.body) + expected = "Only 1 GET request(s) can be made to * every minute." + value = body["overLimitFault"]["details"].strip() + self.assertEqual(value, expected) + + def test_limited_request_xml(self): + """Test a rate-limited (403) response as XML""" + request = webob.Request.blank("/") + response = request.get_response(self.app) + self.assertEqual(200, response.status_int) + + request = webob.Request.blank("/") + request.accept = "application/xml" + response = request.get_response(self.app) + self.assertEqual(response.status_int, 403) + + root = parseString(response.body).childNodes[0] + expected = "Only 1 GET request(s) can be made to * every minute." + + details = root.getElementsByTagName("details") + self.assertEqual(details.length, 1) + + value = details.item(0).firstChild.data.strip() + self.assertEqual(value, expected) + + +class LimitTest(BaseLimitTestSuite): + """ + Tests for the `limits.Limit` class. + """ + + def test_GET_no_delay(self): + """Test a limit handles 1 GET per second.""" + limit = Limit("GET", "*", ".*", 1, 1) + delay = limit("GET", "/anything") + self.assertEqual(None, delay) + self.assertEqual(0, limit.next_request) + self.assertEqual(0, limit.last_request) + + def test_GET_delay(self): + """Test two calls to 1 GET per second limit.""" + limit = Limit("GET", "*", ".*", 1, 1) + delay = limit("GET", "/anything") + self.assertEqual(None, delay) + + delay = limit("GET", "/anything") + self.assertEqual(1, delay) + self.assertEqual(1, limit.next_request) + self.assertEqual(0, limit.last_request) + + self.time += 4 + + delay = limit("GET", "/anything") + self.assertEqual(None, delay) + self.assertEqual(4, limit.next_request) + self.assertEqual(4, limit.last_request) + + +class LimiterTest(BaseLimitTestSuite): """ Tests for the in-memory `limits.Limiter` class. """ def setUp(self): """Run before each test.""" - test.TestCase.setUp(self) - self.time = 0.0 - self.stubs = stubout.StubOutForTesting() - self.stubs.Set(limits.Limit, "_get_time", self._get_time) + BaseLimitTestSuite.setUp(self) self.limiter = limits.Limiter(TEST_LIMITS) - def tearDown(self): - """Run after each test.""" - self.stubs.UnsetAll() - test.TestCase.tearDown(self) - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - def _check(self, num, verb, url, username=None): """Check and yield results from checks.""" for x in xrange(num): @@ -311,28 +397,16 @@ class LimiterTest(test.TestCase): self.assertEqual(expected, results) -class WsgiLimiterTest(test.TestCase): +class WsgiLimiterTest(BaseLimitTestSuite): """ Tests for `limits.WsgiLimiter` class. """ def setUp(self): """Run before each test.""" - test.TestCase.setUp(self) - self.time = 0.0 - self.stubs = stubout.StubOutForTesting() - self.stubs.Set(limits.Limit, "_get_time", self._get_time) + BaseLimitTestSuite.setUp(self) self.app = limits.WsgiLimiter(TEST_LIMITS) - def tearDown(self): - """Run after each test.""" - self.stubs.UnsetAll() - test.TestCase.tearDown(self) - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - def _request_data(self, verb, path): """Get data decribing a limit request verb/path.""" return json.dumps({"verb": verb, "path": path}) @@ -476,7 +550,7 @@ def wire_HTTPConnection_to_WSGI(host, app): httplib.HTTPConnection = HTTPConnectionDecorator(httplib.HTTPConnection) -class WsgiLimiterProxyTest(test.TestCase): +class WsgiLimiterProxyTest(BaseLimitTestSuite): """ Tests for the `limits.WsgiLimiterProxy` class. """ @@ -486,23 +560,11 @@ class WsgiLimiterProxyTest(test.TestCase): Do some nifty HTTP/WSGI magic which allows for WSGI to be called directly by something like the `httplib` library. """ - test.TestCase.setUp(self) - self.time = 0.0 - self.stubs = stubout.StubOutForTesting() - self.stubs.Set(limits.Limit, "_get_time", self._get_time) + BaseLimitTestSuite.setUp(self) self.app = limits.WsgiLimiter(TEST_LIMITS) wire_HTTPConnection_to_WSGI("169.254.0.1:80", self.app) self.proxy = limits.WsgiLimiterProxy("169.254.0.1:80") - def tearDown(self): - """Run after each test.""" - self.stubs.UnsetAll() - test.TestCase.tearDown(self) - - def _get_time(self): - """Return the "time" according to this test suite.""" - return self.time - def test_200(self): """Successful request test.""" delay = self.proxy.check_for_delay("GET", "/anything") @@ -519,4 +581,4 @@ class WsgiLimiterProxyTest(test.TestCase): expected = ("60.00", "403 Forbidden\n\nOnly 1 GET request(s) can be "\ "made to /delayed every minute.") - self.assertEqual((delay, error), expected) + self.assertEqual((delay, error), expected) -- cgit From 659cb8bd43e2091c61f44dacf21274a677ea3146 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 15 Mar 2011 23:35:44 -0400 Subject: openstack api 1.0 flavors resource now implemented; adding flavors request value testing --- nova/tests/api/openstack/test_flavors.py | 71 +++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 8280a505f..8f53d14cc 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -15,17 +15,38 @@ # License for the specific language governing permissions and limitations # under the License. +import json import stubout import webob from nova import test import nova.api from nova import context -from nova import db from nova.api.openstack import flavors +from nova import db from nova.tests.api.openstack import fakes +def stub_flavor(flavorid, name, memory_mb="256", local_gb="10"): + return { + "flavorid": str(flavorid), + "name": name, + "memory_mb": memory_mb, + "local_gb": local_gb, + } + + +def return_instance_type_by_flavor_id(context, flavorid): + return stub_flavor(flavorid, "flavor %s" % (flavorid,)) + +def return_instance_types(context, num=2): + instance_types = {} + for i in xrange(1,num+1): + name = "flavor %s" % (i,) + instance_types[name] = stub_flavor(i, name) + return instance_types + + class FlavorsTest(test.TestCase): def setUp(self): super(FlavorsTest, self).setUp() @@ -35,6 +56,10 @@ class FlavorsTest(test.TestCase): fakes.stub_out_networking(self.stubs) fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) + self.stubs.Set(nova.db.api, "instance_type_get_all", + return_instance_types) + self.stubs.Set(nova.db.api, "instance_type_get_by_flavor_id", + return_instance_type_by_flavor_id) self.context = context.get_admin_context() def tearDown(self): @@ -45,8 +70,50 @@ class FlavorsTest(test.TestCase): req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) + flavors = json.loads(res.body)["flavors"] + expected = [ + { + "id": "1", + "name": "flavor 1", + }, + { + "id": "2", + "name": "flavor 2", + }, + ] + self.assertEqual(flavors, expected) + + def test_get_flavor_list_detail(self): + req = webob.Request.blank('/v1.0/flavors/detail') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + flavors = json.loads(res.body)["flavors"] + expected = [ + { + "id": "1", + "name": "flavor 1", + "ram": "256", + "disk": "10", + }, + { + "id": "2", + "name": "flavor 2", + "ram": "256", + "disk": "10", + }, + ] + self.assertEqual(flavors, expected) + def test_get_flavor_by_id(self): - req = webob.Request.blank('/v1.0/flavors/1') + req = webob.Request.blank('/v1.0/flavors/12') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) + flavor = json.loads(res.body)["flavor"] + expected = { + "id": "12", + "name": "flavor 12", + "ram": "256", + "disk": "10", + } + self.assertEqual(flavor, expected) -- cgit From 33419a2f84ea6bfbf6ff47fb1f01ef0c21389a54 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 16 Mar 2011 00:22:34 -0400 Subject: pep8 fixes --- nova/tests/api/openstack/test_flavors.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 8f53d14cc..4f504808c 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -39,9 +39,10 @@ def stub_flavor(flavorid, name, memory_mb="256", local_gb="10"): def return_instance_type_by_flavor_id(context, flavorid): return stub_flavor(flavorid, "flavor %s" % (flavorid,)) + def return_instance_types(context, num=2): instance_types = {} - for i in xrange(1,num+1): + for i in xrange(1, num + 1): name = "flavor %s" % (i,) instance_types[name] = stub_flavor(i, name) return instance_types @@ -103,7 +104,6 @@ class FlavorsTest(test.TestCase): }, ] self.assertEqual(flavors, expected) - def test_get_flavor_by_id(self): req = webob.Request.blank('/v1.0/flavors/12') -- cgit From 20031162372329b40ca90b1bc39cebb4f187cace Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 15 Mar 2011 23:22:17 -0700 Subject: Use integer ids for (fake) users --- nova/tests/api/openstack/fakes.py | 3 +-- nova/tests/api/openstack/test_accounts.py | 4 ++-- nova/tests/api/openstack/test_users.py | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 52ac80e3f..c2ae48ce4 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -240,8 +240,7 @@ class FakeAuthManager(object): @classmethod def reset_fake_data(cls): - cls.auth_data = dict(acc1=User('guy1', 'guy1', 'acc1', - 'fortytwo!', False)) + cls.auth_data = dict(acc1=User(1, 'guy1', 'acc1', 'fortytwo!', False)) cls.projects = dict(testacct=Project('testacct', 'testacct', 'guy1', diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 1bf49b33b..5cb08ffd2 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -57,8 +57,8 @@ class AccountsTest(test.TestCase): self.allow_admin = FLAGS.allow_admin_api FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() - joeuser = User('guy1', 'guy1', 'acc1', 'fortytwo!', False) - superuser = User('guy2', 'guy2', 'acc2', 'swordfish', True) + joeuser = User(1, 'guy1', 'acc1', 'fortytwo!', False) + superuser = User(2, 'guy2', 'acc2', 'swordfish', True) fakemgr.add_user(joeuser) fakemgr.add_user(superuser) fakemgr.create_project('test1', joeuser) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index a62db7efc..652aac936 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -61,8 +61,8 @@ class UsersTest(test.TestCase): self.allow_admin = FLAGS.allow_admin_api FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() - fakemgr.add_user(User('guy1', 'guy1', 'acc1', 'fortytwo!', False)) - fakemgr.add_user(User('guy2', 'guy2', 'acc2', 'swordfish', True)) + fakemgr.add_user(User(1, 'guy1', 'acc1', 'fortytwo!', False)) + fakemgr.add_user(User(2, 'guy2', 'acc2', 'swordfish', True)) def tearDown(self): self.stubs.UnsetAll() -- cgit From bb52b51d0e4f9b297dcc489562f38d1647e10856 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Wed, 16 Mar 2011 12:34:39 +0000 Subject: Adding unit test --- nova/tests/db/fakes.py | 45 ++++++++++++++++++++++++++++++++++++++++----- nova/tests/test_xenapi.py | 22 +++++++++++++++++++--- 2 files changed, 59 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index d760dc456..88daa82c3 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -23,8 +23,9 @@ from nova import db from nova import test from nova import utils +from nova import log as LOG -def stub_out_db_instance_api(stubs): +def stub_out_db_instance_api(stubs, injected=True): """ Stubs out the db API for creating Instances """ INSTANCE_TYPES = { @@ -36,6 +37,29 @@ def stub_out_db_instance_api(stubs): 'm1.xlarge': dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} + flat_network_fields = { + 'id': 'fake_flat', + 'bridge': 'xenbr0', + 'label': 'fake_flat_network', + 'netmask': '255.255.255.0', + 'gateway': '10.0.0.1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2', + 'ra_server': None, + 'injected': injected} + + vlan_network_fields = { + 'id': 'fake_vlan', + 'bridge': 'br111', + 'label': 'fake_vlan_network', + 'netmask': '255.255.255.0', + 'gateway': '10.0.0.1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2', + 'ra_server': None, + 'vlan': 111, + 'injected': False} + class FakeModel(object): """ Stubs out for model """ def __init__(self, values): @@ -81,12 +105,23 @@ def stub_out_db_instance_api(stubs): return FakeModel(base_options) def fake_network_get_by_instance(context, instance_id): - fields = { - 'bridge': 'xenbr0', - } - return FakeModel(fields) + #even instance numbers are on vlan networks + if instance_id % 2 == 0: + return FakeModel(vlan_network_fields) + else: + return FakeModel(flat_network_fields) + + def fake_network_get_all_by_instance(context, instance_id): + l = [] + #even instance numbers are on vlan networks + if instance_id % 2 == 0: + l.append(FakeModel(vlan_network_fields)) + else: + l.append(FakeModel(flat_network_fields)) + return l stubs.Set(db, 'instance_create', fake_instance_create) stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) + stubs.Set(db, 'network_get_all_by_instance', fake_network_get_all_by_instance) stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all) stubs.Set(db, 'instance_type_get_by_name', fake_instance_type_get_by_name) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 26fad39d1..2cdc84882 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -165,6 +165,7 @@ class XenAPIVMTestCase(test.TestCase): FLAGS.xenapi_connection_password = 'test_pass' xenapi_fake.reset() xenapi_fake.create_local_srs() + xenapi_fake.create_local_pifs() db_fakes.stub_out_db_instance_api(self.stubs) xenapi_fake.create_network('fake', FLAGS.flat_network_bridge) stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests) @@ -252,6 +253,9 @@ class XenAPIVMTestCase(test.TestCase): # Check that the VM is running according to XenAPI. self.assertEquals(vm['power_state'], 'Running') + + # Check that VM network is consistent with nova network + LOG.debug("VM INFO - NETWORK:%s", vm_info) def _test_spawn(self, image_id, kernel_id, ramdisk_id, instance_type="m1.large"): @@ -301,13 +305,25 @@ class XenAPIVMTestCase(test.TestCase): def test_spawn_vlanmanager(self): self.flags(xenapi_image_service = 'glance', - network_manager='nova.network.manager.VlanManager', - network_driver='nova.network.xenapi_net') + network_manager = 'nova.network.manager.VlanManager', + network_driver = 'nova.network.xenapi_net', + vlan_interface = 'fake0') LOG.debug("Self.network:%s",self.network) + LOG.debug("network driver:%s",FLAGS.network_driver) + fake_instance_id = 2 + network_bk=self.network + #ensure we use xenapi_net driver + self.network = utils.import_object(FLAGS.network_manager) + self.network.setup_compute_network(None, fake_instance_id) self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, glance_stubs.FakeGlance.IMAGE_KERNEL, glance_stubs.FakeGlance.IMAGE_RAMDISK) - pass + url = FLAGS.xenapi_connection_url + username = FLAGS.xenapi_connection_username + password = FLAGS.xenapi_connection_password + session = xenapi_conn.XenAPISession(url, username, password) + + self.network = network_bk def tearDown(self): super(XenAPIVMTestCase, self).tearDown() -- cgit From 7fbf061666516705e74592c3660155e86d3da895 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Wed, 16 Mar 2011 09:15:46 -0400 Subject: Fix up testsuite for lxc --- nova/tests/test_virt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index c149c9307..b3ca241cb 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -256,9 +256,9 @@ class LibvirtConnTestCase(test.TestCase): 'uml': ('uml:///system', [(lambda t: t.find('.').get('type'), 'uml'), (lambda t: t.find('./os/type').text, 'uml')]), - 'lxc': ('lxc://', + 'lxc': ('lxc://;', [(lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'lxc')]), + (lambda t: t.find('./os/type').text, 'exe')]), 'xen': ('xen:///', [(lambda t: t.find('.').get('type'), 'xen'), (lambda t: t.find('./os/type').text, 'linux')]), -- cgit From a21efc63be6bad3bbde41eb96d6a1752e6d8174d Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Wed, 16 Mar 2011 09:26:37 -0400 Subject: Really fix testcase --- nova/tests/test_virt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b3ca241cb..fed8ff803 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -256,7 +256,7 @@ class LibvirtConnTestCase(test.TestCase): 'uml': ('uml:///system', [(lambda t: t.find('.').get('type'), 'uml'), (lambda t: t.find('./os/type').text, 'uml')]), - 'lxc': ('lxc://;', + 'lxc': ('lxc:///', [(lambda t: t.find('.').get('type'), 'lxc'), (lambda t: t.find('./os/type').text, 'exe')]), 'xen': ('xen:///', -- cgit From d714df5ed4a6a1d4f1c0f7680c2fbb6a6abb81a5 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 16 Mar 2011 11:02:22 -0400 Subject: Implement top level extensions. --- nova/tests/api/openstack/extensions/foxinsocks.py | 70 +++++++++++++++++++++++ nova/tests/api/openstack/extensions/widgets.py | 54 ----------------- nova/tests/api/openstack/test_extensions.py | 68 +++++++++++++++------- 3 files changed, 118 insertions(+), 74 deletions(-) create mode 100644 nova/tests/api/openstack/extensions/foxinsocks.py delete mode 100644 nova/tests/api/openstack/extensions/widgets.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py new file mode 100644 index 000000000..09a328273 --- /dev/null +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -0,0 +1,70 @@ +import json + +from nova import wsgi + +from nova.api.openstack import extensions + + +class FoxInSocksController(wsgi.Controller): + + def index(self, req): + return "Try to say this Mr. Knox, sir..." + + +class Foxinsocks(object): + + def __init__(self): + pass + + def get_name(self): + return "Fox In Socks" + + def get_alias(self): + return "FOXNSOX" + + def get_description(self): + return "The Fox In Socks Extension" + + def get_namespace(self): + return "http://www.fox.in.socks/api/ext/pie/v1.0" + + def get_updated(self): + return "2011-01-22T13:25:27-06:00" + + def get_resources(self): + resources = [] + resource = extensions.ResourceExtension('foxnsocks', + FoxInSocksController()) + resources.append(resource) + return resources + + def get_actions(self): + actions = [] + actions.append(extensions.ActionExtension('servers', 'add_tweedle', + self._add_tweedle)) + actions.append(extensions.ActionExtension('servers', 'delete_tweedle', + self._delete_tweedle)) + return actions + + def get_response_extensions(self): + response_exts = [] + + def _resp_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['flavor']['googoose'] = "Gooey goo for chewy chewing!" + return data + + resp_ext = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + _resp_handler) + response_exts.append(resp_ext) + return response_exts + + def _add_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Added." + + def _delete_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Deleted." diff --git a/nova/tests/api/openstack/extensions/widgets.py b/nova/tests/api/openstack/extensions/widgets.py deleted file mode 100644 index f463721f1..000000000 --- a/nova/tests/api/openstack/extensions/widgets.py +++ /dev/null @@ -1,54 +0,0 @@ -import json - -from nova import wsgi - -from nova.api.openstack import extensions - - -class WidgetsController(wsgi.Controller): - - def index(self, req): - return "Buy more widgets!" - - -class Widgets(object): - - def __init__(self): - pass - - def get_resources(self): - resources = [] - widgets = extensions.ResourceExtension('widgets', - WidgetsController()) - resources.append(widgets) - return resources - - def get_actions(self): - actions = [] - actions.append(extensions.ActionExtension('servers', 'add_widget', - self._add_widget)) - actions.append(extensions.ActionExtension('servers', 'delete_widget', - self._delete_widget)) - return actions - - def get_response_extensions(self): - response_exts = [] - - def _resp_handler(res): - # only handle JSON responses - data = json.loads(res.body) - data['flavor']['widgets'] = "Buy more widgets!" - return data - - widgets = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', - _resp_handler) - response_exts.append(widgets) - return response_exts - - def _add_widget(self, input_dict, req, id): - - return "Widget Added." - - def _delete_widget(self, input_dict, req, id): - - return "Widget Deleted." diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 8725c8f0e..0f99dec55 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -48,6 +48,15 @@ class StubExtensionManager(object): self.action_ext = action_ext self.response_ext = response_ext + def get_name(self): + return "Tweedle Beetle Extension" + + def get_alias(self): + return "TWDLBETL" + + def get_description(self): + return "Provides access to Tweedle Beetles" + def get_resources(self): resource_exts = [] if self.resource_ext: @@ -67,36 +76,53 @@ class StubExtensionManager(object): return response_exts +class ExtensionControllerTest(unittest.TestCase): + + def test_index(self): + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/extensions") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + + def test_get_by_alias(self): + app = openstack.APIRouter() + ext_midware = extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/extensions/FOXNSOX") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + +response_body = "Try to say this Mr. Knox, sir..." + class ResourceExtensionTest(unittest.TestCase): + def test_no_extension_present(self): manager = StubExtensionManager(None) app = openstack.APIRouter() ext_midware = extensions.ExtensionMiddleware(app, manager) - request = webob.Request.blank("/widgets") + request = webob.Request.blank("/blah") response = request.get_response(ext_midware) self.assertEqual(404, response.status_int) def test_get_resources(self): - response_body = "Buy more widgets!" - widgets = extensions.ResourceExtension('widgets', + res_ext = extensions.ResourceExtension('tweedles', StubController(response_body)) - manager = StubExtensionManager(widgets) + manager = StubExtensionManager(res_ext) app = openstack.APIRouter() ext_midware = extensions.ExtensionMiddleware(app, manager) - request = webob.Request.blank("/widgets") + request = webob.Request.blank("/tweedles") response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) self.assertEqual(response_body, response.body) def test_get_resources_with_controller(self): - response_body = "Buy more widgets!" - widgets = extensions.ResourceExtension('widgets', + res_ext = extensions.ResourceExtension('tweedles', StubController(response_body)) - manager = StubExtensionManager(widgets) + manager = StubExtensionManager(res_ext) app = openstack.APIRouter() ext_midware = extensions.ExtensionMiddleware(app, manager) - request = webob.Request.blank("/widgets") + request = webob.Request.blank("/tweedles") response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) self.assertEqual(response_body, response.body) @@ -104,6 +130,8 @@ class ResourceExtensionTest(unittest.TestCase): class ExtensionManagerTest(unittest.TestCase): + response_body = "Try to say this Mr. Knox, sir..." + def setUp(self): FLAGS.osapi_extensions_path = os.path.join(os.path.dirname(__file__), "extensions") @@ -111,10 +139,10 @@ class ExtensionManagerTest(unittest.TestCase): def test_get_resources(self): app = openstack.APIRouter() ext_midware = extensions.ExtensionMiddleware(app) - request = webob.Request.blank("/widgets") + request = webob.Request.blank("/foxnsocks") response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) - self.assertEqual("Buy more widgets!", response.body) + self.assertEqual(response_body, response.body) class ActionExtensionTest(unittest.TestCase): @@ -134,15 +162,15 @@ class ActionExtensionTest(unittest.TestCase): return response def test_extended_action(self): - body = dict(add_widget=dict(name="test")) + body = dict(add_tweedle=dict(name="test")) response = self._send_server_action_request("/servers/1/action", body) self.assertEqual(200, response.status_int) - self.assertEqual("Widget Added.", response.body) + self.assertEqual("Tweedle Beetle Added.", response.body) - body = dict(delete_widget=dict(name="test")) + body = dict(delete_tweedle=dict(name="test")) response = self._send_server_action_request("/servers/1/action", body) self.assertEqual(200, response.status_int) - self.assertEqual("Widget Deleted.", response.body) + self.assertEqual("Tweedle Beetle Deleted.", response.body) def test_invalid_action_body(self): body = dict(blah=dict(name="test")) # Doesn't exist @@ -169,21 +197,21 @@ class ResponseExtensionTest(unittest.TestCase): def test_get_resources(self): - test_resp = "Buy more widgets!" + test_resp = "Gooey goo for chewy chewing!" def _resp_handler(res): # only handle JSON responses data = json.loads(res.body) - data['flavor']['widgets'] = test_resp + data['flavor']['googoose'] = test_resp return data - widgets = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + resp_ext = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', _resp_handler) - manager = StubExtensionManager(None, None, widgets) + manager = StubExtensionManager(None, None, resp_ext) app = fakes.wsgi_app() ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/v1.0/flavors/1") response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) response_data = json.loads(response.body) - self.assertEqual(test_resp, response_data['flavor']['widgets']) + self.assertEqual(test_resp, response_data['flavor']['googoose']) -- cgit From 45ca7b71a8e749cbd9b7729b922190e9aaa53744 Mon Sep 17 00:00:00 2001 From: sateesh Date: Wed, 16 Mar 2011 21:54:02 +0530 Subject: * Updated document vmware_readme.rst to mention VLAN networking * Corrected docstrings as per pep0257 recommentations. * Stream-lined the comments. * Updated code with locals() where ever applicable. * VIM : It stands for VMware Virtual Infrastructure Methodology. We have used the terminology from VMware. we have added a question in FAQ inside vmware_readme.rst in doc/source * New fake db: vmwareapi fake module uses a different set of fields and hence the structures required are different. Ex: bridge : 'xenbr0' does not hold good for VMware environment and bridge : 'vmnic0' is used instead. Also return values varies, hence went for implementing separate fake db. * Now using eventlet library instead and removed io_utils.py from branch. * Now using glance.client.Client instead of homegrown code to talk to Glance server to handle images. * Corrected all mis-spelled function names and corresponding calls. Yeah, an auto-complete side-effect! --- nova/tests/test_vmwareapi.py | 28 ++++++++++++++++------------ nova/tests/vmwareapi/__init__.py | 5 +++++ nova/tests/vmwareapi/db_fakes.py | 12 ++++++------ nova/tests/vmwareapi/stubs.py | 6 +++--- 4 files changed, 30 insertions(+), 21 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index 65cdd5fcf..b22d8b7b9 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -16,8 +16,9 @@ # under the License. """ -Test suite for VMWareAPI +Test suite for VMWareAPI. """ + import stubout from nova import context @@ -38,9 +39,7 @@ FLAGS = flags.FLAGS class VMWareAPIVMTestCase(test.TestCase): - """ - Unit tests for Vmware API connection calls - """ + """Unit tests for Vmware API connection calls.""" def setUp(self): super(VMWareAPIVMTestCase, self).setUp() @@ -61,7 +60,7 @@ class VMWareAPIVMTestCase(test.TestCase): self.conn = vmwareapi_conn.get_connection(False) def _create_vm(self): - """ Create and spawn the VM """ + """Create and spawn the VM.""" values = {'name': 1, 'id': 1, 'project_id': self.project.id, @@ -78,15 +77,17 @@ class VMWareAPIVMTestCase(test.TestCase): self._check_vm_record() def _check_vm_record(self): - """ Check if the spawned VM's properties corresponds to the instance in - the db """ + """ + Check if the spawned VM's properties correspond to the instance in + the db. + """ instances = self.conn.list_instances() self.assertEquals(len(instances), 1) # Get Nova record for VM vm_info = self.conn.get_info(1) - # Get record for VMs + # Get record for VM vms = vmwareapi_fake._get_objects("VirtualMachine") vm = vms[0] @@ -106,8 +107,10 @@ class VMWareAPIVMTestCase(test.TestCase): self.assertEquals(vm.get("runtime.powerState"), 'poweredOn') def _check_vm_info(self, info, pwr_state=power_state.RUNNING): - """ Check if the get_info returned values correspond to the instance - object in the db """ + """ + Check if the get_info returned values correspond to the instance + object in the db. + """ mem_kib = long(self.type_data['memory_mb']) << 10 self.assertEquals(info["state"], pwr_state) self.assertEquals(info["max_mem"], mem_kib) @@ -194,8 +197,9 @@ class VMWareAPIVMTestCase(test.TestCase): pass def dummy_callback_handler(self, ret): - """ Dummy callback function to be passed to suspend, resume, etc. - calls """ + """ + Dummy callback function to be passed to suspend, resume, etc., calls. + """ pass def tearDown(self): diff --git a/nova/tests/vmwareapi/__init__.py b/nova/tests/vmwareapi/__init__.py index f346c053b..478ee742b 100644 --- a/nova/tests/vmwareapi/__init__.py +++ b/nova/tests/vmwareapi/__init__.py @@ -14,3 +14,8 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. + +""" +:mod:`vmwareapi` -- Stubs for VMware API +======================================= +""" diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py index 026a2038e..0addd5573 100644 --- a/nova/tests/vmwareapi/db_fakes.py +++ b/nova/tests/vmwareapi/db_fakes.py @@ -26,7 +26,7 @@ from nova import utils def stub_out_db_instance_api(stubs): - """ Stubs out the db API for creating Instances """ + """Stubs out the db API for creating Instances.""" INSTANCE_TYPES = { 'm1.tiny': dict(memory_mb=512, vcpus=1, local_gb=0, flavorid=1), @@ -38,7 +38,7 @@ def stub_out_db_instance_api(stubs): dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} class FakeModel(object): - """ Stubs out for model """ + """Stubs out for model.""" def __init__(self, values): self.values = values @@ -53,7 +53,7 @@ def stub_out_db_instance_api(stubs): raise NotImplementedError() def fake_instance_create(values): - """ Stubs out the db.instance_create method """ + """Stubs out the db.instance_create method.""" type_data = INSTANCE_TYPES[values['instance_type']] @@ -77,7 +77,7 @@ def stub_out_db_instance_api(stubs): return FakeModel(base_options) def fake_network_get_by_instance(context, instance_id): - """ Stubs out the db.network_get_by_instance method """ + """Stubs out the db.network_get_by_instance method.""" fields = { 'bridge': 'vmnet0', @@ -87,11 +87,11 @@ def stub_out_db_instance_api(stubs): return FakeModel(fields) def fake_instance_action_create(context, action): - """ Stubs out the db.instance_action_create method """ + """Stubs out the db.instance_action_create method.""" pass def fake_instance_get_fixed_address(context, instance_id): - """ Stubs out the db.instance_get_fixed_address method """ + """Stubs out the db.instance_get_fixed_address method.""" return '10.10.10.10' def fake_instance_type_get_all(context, inactive=0): diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py index da2d43c29..a648efb16 100644 --- a/nova/tests/vmwareapi/stubs.py +++ b/nova/tests/vmwareapi/stubs.py @@ -25,17 +25,17 @@ from nova.virt.vmwareapi import vmware_images def fake_get_vim_object(arg): - """ Stubs out the VMWareAPISession's get_vim_object method """ + """Stubs out the VMWareAPISession's get_vim_object method.""" return fake.FakeVim() def fake_is_vim_object(arg, module): - """ Stubs out the VMWareAPISession's is_vim_object method """ + """Stubs out the VMWareAPISession's is_vim_object method.""" return isinstance(module, fake.FakeVim) def set_stubs(stubs): - """ Set the stubs """ + """Set the stubs.""" stubs.Set(vmware_images, 'fetch_image', fake.fake_fetch_image) stubs.Set(vmware_images, 'get_vmdk_size_and_properties', fake.fake_get_vmdk_size_and_properties) -- cgit From b2456e983178b97ad94f48c77ef210000d6d6ca4 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 16 Mar 2011 14:03:38 -0400 Subject: Move mapper code into the _action_ext_controllers and _response_ext_controllers methods. --- nova/tests/api/openstack/extensions/foxinsocks.py | 2 +- nova/tests/api/openstack/test_extensions.py | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py index 09a328273..2e93d8a55 100644 --- a/nova/tests/api/openstack/extensions/foxinsocks.py +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -56,7 +56,7 @@ class Foxinsocks(object): data['flavor']['googoose'] = "Gooey goo for chewy chewing!" return data - resp_ext = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + resp_ext = extensions.ResponseExtension('GET', '/flavors/:(id)', _resp_handler) response_exts.append(resp_ext) return response_exts diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 0f99dec55..149f1973e 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -31,6 +31,8 @@ import nova.wsgi FLAGS = flags.FLAGS +response_body = "Try to say this Mr. Knox, sir..." + class StubController(nova.wsgi.Controller): @@ -92,11 +94,9 @@ class ExtensionControllerTest(unittest.TestCase): response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) -response_body = "Try to say this Mr. Knox, sir..." class ResourceExtensionTest(unittest.TestCase): - def test_no_extension_present(self): manager = StubExtensionManager(None) app = openstack.APIRouter() @@ -205,7 +205,8 @@ class ResponseExtensionTest(unittest.TestCase): data['flavor']['googoose'] = test_resp return data - resp_ext = extensions.ResponseExtension('/v1.0/flavors/:(id)', 'GET', + resp_ext = extensions.ResponseExtension('GET', + '/v1.0/flavors/:(id)', _resp_handler) manager = StubExtensionManager(None, None, resp_ext) app = fakes.wsgi_app() -- cgit From 7fa96f6292ff7d63621fe024b1ef45b1a1996121 Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Wed, 16 Mar 2011 14:49:18 -0400 Subject: Re-commit r804 --- nova/tests/api/openstack/test_servers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 40026a615..cde2fc036 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -216,7 +216,7 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [1, 2]) - def _test_create_instance_helper(self, with_key_pair): + def _test_create_instance_helper(self): def instance_create(context, inst): return {'id': '1', 'display_name': 'server_test'} @@ -272,11 +272,11 @@ class ServersTest(test.TestCase): self.assertEqual(res.status_int, 200) def test_create_instance(self): - self._test_create_instance_helper(True) + self._test_create_instance_helper() def test_create_instance_no_key_pair(self): - fakes.stub_out_key_pair_funcs(self.stubs, False) - self._test_create_instance_helper(False) + fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False) + self._test_create_instance_helper() def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') -- cgit From 663c1726d9a96540b8fd729223fcb34d7cf3cdf7 Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Wed, 16 Mar 2011 14:49:25 -0400 Subject: Re-commit r805 --- nova/tests/api/openstack/test_servers.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index cde2fc036..ad36fa551 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -217,6 +217,7 @@ class ServersTest(test.TestCase): self.assertEqual([s['id'] for s in servers], [1, 2]) def _test_create_instance_helper(self): + """Shared implementation for tests below that create instance""" def instance_create(context, inst): return {'id': '1', 'display_name': 'server_test'} -- cgit From 7de1ef791296d547c2691454d5cb5451087cd76b Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 16 Mar 2011 12:15:57 -0700 Subject: User ids are strings, and are not necessarily == name. Also fix so that non-existent user gives a 404, not a 500. --- nova/tests/api/openstack/fakes.py | 4 +-- nova/tests/api/openstack/test_accounts.py | 22 ++++++------ nova/tests/api/openstack/test_auth.py | 8 ++--- nova/tests/api/openstack/test_users.py | 58 +++++++++++++++++++++---------- 4 files changed, 55 insertions(+), 37 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index c2ae48ce4..5decb2bad 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -240,10 +240,10 @@ class FakeAuthManager(object): @classmethod def reset_fake_data(cls): - cls.auth_data = dict(acc1=User(1, 'guy1', 'acc1', 'fortytwo!', False)) + cls.auth_data = dict(u1=User('id1', 'guy1', 'acc1', 'secret1', False)) cls.projects = dict(testacct=Project('testacct', 'testacct', - 'guy1', + 'id1', 'test', [])) diff --git a/nova/tests/api/openstack/test_accounts.py b/nova/tests/api/openstack/test_accounts.py index 5cb08ffd2..64abcf48c 100644 --- a/nova/tests/api/openstack/test_accounts.py +++ b/nova/tests/api/openstack/test_accounts.py @@ -19,11 +19,9 @@ import json import stubout import webob -import nova.api -import nova.api.openstack.auth -from nova import context from nova import flags from nova import test +from nova.api.openstack import accounts from nova.auth.manager import User from nova.tests.api.openstack import fakes @@ -44,9 +42,9 @@ class AccountsTest(test.TestCase): def setUp(self): super(AccountsTest, self).setUp() self.stubs = stubout.StubOutForTesting() - self.stubs.Set(nova.api.openstack.accounts.Controller, '__init__', + self.stubs.Set(accounts.Controller, '__init__', fake_init) - self.stubs.Set(nova.api.openstack.accounts.Controller, '_check_admin', + self.stubs.Set(accounts.Controller, '_check_admin', fake_admin_check) fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthDatabase.data = {} @@ -57,8 +55,8 @@ class AccountsTest(test.TestCase): self.allow_admin = FLAGS.allow_admin_api FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() - joeuser = User(1, 'guy1', 'acc1', 'fortytwo!', False) - superuser = User(2, 'guy2', 'acc2', 'swordfish', True) + joeuser = User('id1', 'guy1', 'acc1', 'secret1', False) + superuser = User('id2', 'guy2', 'acc2', 'secret2', True) fakemgr.add_user(joeuser) fakemgr.add_user(superuser) fakemgr.create_project('test1', joeuser) @@ -76,7 +74,7 @@ class AccountsTest(test.TestCase): self.assertEqual(res_dict['account']['id'], 'test1') self.assertEqual(res_dict['account']['name'], 'test1') - self.assertEqual(res_dict['account']['manager'], 'guy1') + self.assertEqual(res_dict['account']['manager'], 'id1') self.assertEqual(res.status_int, 200) def test_account_delete(self): @@ -88,7 +86,7 @@ class AccountsTest(test.TestCase): def test_account_create(self): body = dict(account=dict(description='test account', - manager='guy1')) + manager='id1')) req = webob.Request.blank('/v1.0/accounts/newacct') req.headers["Content-Type"] = "application/json" req.method = 'PUT' @@ -101,14 +99,14 @@ class AccountsTest(test.TestCase): self.assertEqual(res_dict['account']['id'], 'newacct') self.assertEqual(res_dict['account']['name'], 'newacct') self.assertEqual(res_dict['account']['description'], 'test account') - self.assertEqual(res_dict['account']['manager'], 'guy1') + self.assertEqual(res_dict['account']['manager'], 'id1') self.assertTrue('newacct' in fakes.FakeAuthManager.projects) self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 3) def test_account_update(self): body = dict(account=dict(description='test account', - manager='guy2')) + manager='id2')) req = webob.Request.blank('/v1.0/accounts/test1') req.headers["Content-Type"] = "application/json" req.method = 'PUT' @@ -121,5 +119,5 @@ class AccountsTest(test.TestCase): self.assertEqual(res_dict['account']['id'], 'test1') self.assertEqual(res_dict['account']['name'], 'test1') self.assertEqual(res_dict['account']['description'], 'test account') - self.assertEqual(res_dict['account']['manager'], 'guy2') + self.assertEqual(res_dict['account']['manager'], 'id2') self.assertEqual(len(fakes.FakeAuthManager.projects.values()), 2) diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index e1f936bb1..446c5c149 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,7 +51,7 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'user1', 'user1_key', None, None) + u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) f.add_user(u) req = webob.Request.blank('/v1.0/') @@ -66,7 +66,7 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'user1', 'user1_key', None, None) + u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) f.add_user(u) f.create_project('user1_project', u) @@ -124,7 +124,7 @@ class Test(test.TestCase): def test_bad_user_good_key(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'user1', 'user1_key', None, None) + u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) f.add_user(u) req = webob.Request.blank('/v1.0/') @@ -190,7 +190,7 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User(1, 'user1', 'user1_key', None, None) + u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) f.add_user(u) f.create_project('test', u) diff --git a/nova/tests/api/openstack/test_users.py b/nova/tests/api/openstack/test_users.py index 652aac936..effb2f592 100644 --- a/nova/tests/api/openstack/test_users.py +++ b/nova/tests/api/openstack/test_users.py @@ -18,11 +18,10 @@ import json import stubout import webob -import nova.api -import nova.api.openstack.auth -from nova import context from nova import flags from nova import test +from nova import utils +from nova.api.openstack import users from nova.auth.manager import User, Project from nova.tests.api.openstack import fakes @@ -43,14 +42,14 @@ class UsersTest(test.TestCase): def setUp(self): super(UsersTest, self).setUp() self.stubs = stubout.StubOutForTesting() - self.stubs.Set(nova.api.openstack.users.Controller, '__init__', + self.stubs.Set(users.Controller, '__init__', fake_init) - self.stubs.Set(nova.api.openstack.users.Controller, '_check_admin', + self.stubs.Set(users.Controller, '_check_admin', fake_admin_check) fakes.FakeAuthManager.clear_fakes() fakes.FakeAuthManager.projects = dict(testacct=Project('testacct', 'testacct', - 'guy1', + 'id1', 'test', [])) fakes.FakeAuthDatabase.data = {} @@ -61,8 +60,8 @@ class UsersTest(test.TestCase): self.allow_admin = FLAGS.allow_admin_api FLAGS.allow_admin_api = True fakemgr = fakes.FakeAuthManager() - fakemgr.add_user(User(1, 'guy1', 'acc1', 'fortytwo!', False)) - fakemgr.add_user(User(2, 'guy2', 'acc2', 'swordfish', True)) + fakemgr.add_user(User('id1', 'guy1', 'acc1', 'secret1', False)) + fakemgr.add_user(User('id2', 'guy2', 'acc2', 'secret2', True)) def tearDown(self): self.stubs.UnsetAll() @@ -78,28 +77,44 @@ class UsersTest(test.TestCase): self.assertEqual(len(res_dict['users']), 2) def test_get_user_by_id(self): - req = webob.Request.blank('/v1.0/users/guy2') + req = webob.Request.blank('/v1.0/users/id2') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - self.assertEqual(res_dict['user']['id'], 'guy2') + self.assertEqual(res_dict['user']['id'], 'id2') self.assertEqual(res_dict['user']['name'], 'guy2') - self.assertEqual(res_dict['user']['secret'], 'swordfish') + self.assertEqual(res_dict['user']['secret'], 'secret2') self.assertEqual(res_dict['user']['admin'], True) self.assertEqual(res.status_int, 200) def test_user_delete(self): - req = webob.Request.blank('/v1.0/users/guy1') + # Check the user exists + req = webob.Request.blank('/v1.0/users/id1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + self.assertEqual(res_dict['user']['id'], 'id1') + self.assertEqual(res.status_int, 200) + + # Delete the user + req = webob.Request.blank('/v1.0/users/id1') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) - self.assertTrue('guy1' not in [u.id for u in + self.assertTrue('id1' not in [u.id for u in fakes.FakeAuthManager.auth_data]) self.assertEqual(res.status_int, 200) + # Check the user is not returned (and returns 404) + req = webob.Request.blank('/v1.0/users/id1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res.status_int, 404) + def test_user_create(self): + secret = utils.generate_password() body = dict(user=dict(name='test_guy', access='acc3', - secret='invasionIsInNormandy', + secret=secret, admin=True)) req = webob.Request.blank('/v1.0/users') req.headers["Content-Type"] = "application/json" @@ -110,20 +125,25 @@ class UsersTest(test.TestCase): res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) + + # NOTE(justinsb): This is a questionable assertion in general + # fake sets id=name, but others might not... self.assertEqual(res_dict['user']['id'], 'test_guy') + self.assertEqual(res_dict['user']['name'], 'test_guy') self.assertEqual(res_dict['user']['access'], 'acc3') - self.assertEqual(res_dict['user']['secret'], 'invasionIsInNormandy') + self.assertEqual(res_dict['user']['secret'], secret) self.assertEqual(res_dict['user']['admin'], True) self.assertTrue('test_guy' in [u.id for u in fakes.FakeAuthManager.auth_data]) self.assertEqual(len(fakes.FakeAuthManager.auth_data), 3) def test_user_update(self): + new_secret = utils.generate_password() body = dict(user=dict(name='guy2', access='acc2', - secret='invasionIsInNormandy')) - req = webob.Request.blank('/v1.0/users/guy2') + secret=new_secret)) + req = webob.Request.blank('/v1.0/users/id2') req.headers["Content-Type"] = "application/json" req.method = 'PUT' req.body = json.dumps(body) @@ -132,8 +152,8 @@ class UsersTest(test.TestCase): res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) - self.assertEqual(res_dict['user']['id'], 'guy2') + self.assertEqual(res_dict['user']['id'], 'id2') self.assertEqual(res_dict['user']['name'], 'guy2') self.assertEqual(res_dict['user']['access'], 'acc2') - self.assertEqual(res_dict['user']['secret'], 'invasionIsInNormandy') + self.assertEqual(res_dict['user']['secret'], new_secret) self.assertEqual(res_dict['user']['admin'], True) -- cgit From 227957e31d75b24bb8afa078c8d3f2bc447a8215 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Wed, 16 Mar 2011 19:40:16 +0000 Subject: Unit test update --- nova/tests/api/openstack/test_flavors.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 8280a505f..30326dc50 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import json import stubout import webob @@ -50,3 +51,5 @@ class FlavorsTest(test.TestCase): req = webob.Request.blank('/v1.0/flavors/1') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) + body = json.loads(res.body) + self.assertEqual(body['flavor']['id'], 1) -- cgit From 77a48cdd8a22cc84ed67a6b3d1c3793dd93e44a8 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 16 Mar 2011 16:15:56 -0400 Subject: expanding osapi flavors tests; rewriting flavors resource with view builders; adding 1.1 specific links to flavors resources --- nova/tests/api/openstack/test_flavors.py | 107 +++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 4f504808c..197e907c4 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -19,11 +19,10 @@ import json import stubout import webob -from nova import test -import nova.api +import nova.db.api from nova import context -from nova.api.openstack import flavors -from nova import db +from nova import exception +from nova import test from nova.tests.api.openstack import fakes @@ -47,6 +46,9 @@ def return_instance_types(context, num=2): instance_types[name] = stub_flavor(i, name) return instance_types +def return_instance_type_not_found(context, flavorid): + raise exception.NotFound() + class FlavorsTest(test.TestCase): def setUp(self): @@ -67,7 +69,7 @@ class FlavorsTest(test.TestCase): self.stubs.UnsetAll() super(FlavorsTest, self).tearDown() - def test_get_flavor_list(self): + def test_get_flavor_list_v1_0(self): req = webob.Request.blank('/v1.0/flavors') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -84,7 +86,7 @@ class FlavorsTest(test.TestCase): ] self.assertEqual(flavors, expected) - def test_get_flavor_list_detail(self): + def test_get_flavor_list_detail_v1_0(self): req = webob.Request.blank('/v1.0/flavors/detail') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -105,7 +107,7 @@ class FlavorsTest(test.TestCase): ] self.assertEqual(flavors, expected) - def test_get_flavor_by_id(self): + def test_get_flavor_by_id_v1_0(self): req = webob.Request.blank('/v1.0/flavors/12') res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) @@ -117,3 +119,94 @@ class FlavorsTest(test.TestCase): "disk": "10", } self.assertEqual(flavor, expected) + + def test_get_flavor_by_invalid_id(self): + self.stubs.Set(nova.db.api, "instance_type_get_by_flavor_id", + return_instance_type_not_found) + req = webob.Request.blank('/v1.0/flavors/asdf') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) + + def test_get_flavor_by_id_v1_1(self): + req = webob.Request.blank('/v1.1/flavors/12') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + flavor = json.loads(res.body)["flavor"] + expected = { + "id": "12", + "name": "flavor 12", + "ram": "256", + "disk": "10", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/flavors/12", + }, + ], + } + self.assertEqual(flavor, expected) + + def test_get_flavor_list_v1_1(self): + req = webob.Request.blank('/v1.1/flavors') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + flavor = json.loads(res.body)["flavors"] + expected = [ + { + "id": "1", + "name": "flavor 1", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/flavors/1", + }, + ], + }, + { + "id": "2", + "name": "flavor 2", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/flavors/2", + }, + ], + }, + ] + self.assertEqual(flavor, expected) + + def test_get_flavor_list_detail_v1_1(self): + req = webob.Request.blank('/v1.1/flavors/detail') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + flavor = json.loads(res.body)["flavors"] + expected = [ + { + "id": "1", + "name": "flavor 1", + "ram": "256", + "disk": "10", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/flavors/1", + }, + ], + }, + { + "id": "2", + "name": "flavor 2", + "ram": "256", + "disk": "10", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1/flavors/2", + }, + ], + }, + ] + self.assertEqual(flavor, expected) -- cgit From bb606c7ba42fc567f2e9989e0f560783743e5ddd Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 16 Mar 2011 16:58:38 -0400 Subject: adding bookmarks links to 1.1 flavor entities --- nova/tests/api/openstack/test_flavors.py | 50 ++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 197e907c4..8dfcfe293 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -143,6 +143,16 @@ class FlavorsTest(test.TestCase): "rel": "self", "href": "http://localhost/v1.1/flavors/12", }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/flavors/12", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/flavors/12", + }, ], } self.assertEqual(flavor, expected) @@ -162,6 +172,16 @@ class FlavorsTest(test.TestCase): "rel": "self", "href": "http://localhost/v1.1/flavors/1", }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/flavors/1", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/flavors/1", + }, ], }, { @@ -172,6 +192,16 @@ class FlavorsTest(test.TestCase): "rel": "self", "href": "http://localhost/v1.1/flavors/2", }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/flavors/2", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/flavors/2", + }, ], }, ] @@ -194,6 +224,16 @@ class FlavorsTest(test.TestCase): "rel": "self", "href": "http://localhost/v1.1/flavors/1", }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/flavors/1", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/flavors/1", + }, ], }, { @@ -206,6 +246,16 @@ class FlavorsTest(test.TestCase): "rel": "self", "href": "http://localhost/v1.1/flavors/2", }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/flavors/2", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/flavors/2", + }, ], }, ] -- cgit From d95187aaf144cb40558f48d584a6bb8e07c6937d Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Wed, 16 Mar 2011 14:13:57 -0700 Subject: converted new lines from CRLF to LF --- nova/tests/network/__init__.py | 94 ++++++------ nova/tests/network/base.py | 308 +++++++++++++++++++------------------- nova/tests/test_flat_network.py | 322 ++++++++++++++++++++-------------------- 3 files changed, 362 insertions(+), 362 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py index 8f71a30ba..e0d479f8c 100644 --- a/nova/tests/network/__init__.py +++ b/nova/tests/network/__init__.py @@ -1,47 +1,47 @@ -import os - -from nova import context -from nova import db -from nova import flags -from nova import log as logging -from nova import utils - -FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.tests.network') - - -def binpath(script): - """Returns the absolute path to a script in bin""" - return os.path.abspath(os.path.join(__file__, "../../../../bin", script)) - - -def lease_ip(private_ip): - """Run add command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = (binpath('nova-dhcpbridge'), 'add', - instance_ref['mac_address'], - private_ip, 'fake') - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(*cmd, addl_env=env) - LOG.debug("ISSUE_IP: %s, %s ", out, err) - - -def release_ip(private_ip): - """Run del command on dhcpbridge""" - network_ref = db.fixed_ip_get_network(context.get_admin_context(), - private_ip) - instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), - private_ip) - cmd = (binpath('nova-dhcpbridge'), 'del', - instance_ref['mac_address'], - private_ip, 'fake') - env = {'DNSMASQ_INTERFACE': network_ref['bridge'], - 'TESTING': '1', - 'FLAGFILE': FLAGS.dhcpbridge_flagfile} - (out, err) = utils.execute(*cmd, addl_env=env) - LOG.debug("RELEASE_IP: %s, %s ", out, err) +import os + +from nova import context +from nova import db +from nova import flags +from nova import log as logging +from nova import utils + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +def binpath(script): + """Returns the absolute path to a script in bin""" + return os.path.abspath(os.path.join(__file__, "../../../../bin", script)) + + +def lease_ip(private_ip): + """Run add command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = (binpath('nova-dhcpbridge'), 'add', + instance_ref['mac_address'], + private_ip, 'fake') + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(*cmd, addl_env=env) + LOG.debug("ISSUE_IP: %s, %s ", out, err) + + +def release_ip(private_ip): + """Run del command on dhcpbridge""" + network_ref = db.fixed_ip_get_network(context.get_admin_context(), + private_ip) + instance_ref = db.fixed_ip_get_instance(context.get_admin_context(), + private_ip) + cmd = (binpath('nova-dhcpbridge'), 'del', + instance_ref['mac_address'], + private_ip, 'fake') + env = {'DNSMASQ_INTERFACE': network_ref['bridge'], + 'TESTING': '1', + 'FLAGFILE': FLAGS.dhcpbridge_flagfile} + (out, err) = utils.execute(*cmd, addl_env=env) + LOG.debug("RELEASE_IP: %s, %s ", out, err) diff --git a/nova/tests/network/base.py b/nova/tests/network/base.py index 2dd8178ff..988a1de72 100644 --- a/nova/tests/network/base.py +++ b/nova/tests/network/base.py @@ -1,154 +1,154 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. -""" -Base class of Unit Tests for all network models -""" -import IPy -import os - -from nova import context -from nova import db -from nova import exception -from nova import flags -from nova import log as logging -from nova import test -from nova import utils -from nova.auth import manager - -FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.tests.network') - - -class NetworkTestCase(test.TestCase): - """Test cases for network code""" - def setUp(self): - super(NetworkTestCase, self).setUp() - # NOTE(vish): if you change these flags, make sure to change the - # flags in the corresponding section in nova-dhcpbridge - self.flags(connection_type='fake', - fake_call=True, - fake_network=True) - self.manager = manager.AuthManager() - self.user = self.manager.create_user('netuser', 'netuser', 'netuser') - self.projects = [] - self.network = utils.import_object(FLAGS.network_manager) - self.context = context.RequestContext(project=None, user=self.user) - for i in range(FLAGS.num_networks): - name = 'project%s' % i - project = self.manager.create_project(name, 'netuser', name) - self.projects.append(project) - # create the necessary network data for the project - user_context = context.RequestContext(project=self.projects[i], - user=self.user) - host = self.network.get_network_host(user_context.elevated()) - instance_ref = self._create_instance(0) - self.instance_id = instance_ref['id'] - instance_ref = self._create_instance(1) - self.instance2_id = instance_ref['id'] - - def tearDown(self): - # TODO(termie): this should really be instantiating clean datastores - # in between runs, one failure kills all the tests - db.instance_destroy(context.get_admin_context(), self.instance_id) - db.instance_destroy(context.get_admin_context(), self.instance2_id) - for project in self.projects: - self.manager.delete_project(project) - self.manager.delete_user(self.user) - super(NetworkTestCase, self).tearDown() - - def _create_instance(self, project_num, mac=None): - if not mac: - mac = utils.generate_mac() - project = self.projects[project_num] - self.context._project = project - self.context.project_id = project.id - return db.instance_create(self.context, - {'project_id': project.id, - 'mac_address': mac}) - - def _create_address(self, project_num, instance_id=None): - """Create an address in given project num""" - if instance_id is None: - instance_id = self.instance_id - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - return self.network.allocate_fixed_ip(self.context, instance_id) - - def _deallocate_address(self, project_num, address): - self.context._project = self.projects[project_num] - self.context.project_id = self.projects[project_num].id - self.network.deallocate_fixed_ip(self.context, address) - - def _is_allocated_in_project(self, address, project_id): - """Returns true if address is in specified project""" - project_net = db.network_get_by_bridge(context.get_admin_context(), - FLAGS.flat_network_bridge) - network = db.fixed_ip_get_network(context.get_admin_context(), - address) - instance = db.fixed_ip_get_instance(context.get_admin_context(), - address) - # instance exists until release - return instance is not None and network['id'] == project_net['id'] - - def test_private_ipv6(self): - """Make sure ipv6 is OK""" - if FLAGS.use_ipv6: - instance_ref = self._create_instance(0) - address = self._create_address(0, instance_ref['id']) - network_ref = db.project_get_network( - context.get_admin_context(), - self.context.project_id) - address_v6 = db.instance_get_fixed_address_v6( - context.get_admin_context(), - instance_ref['id']) - self.assertEqual(instance_ref['mac_address'], - utils.to_mac(address_v6)) - instance_ref2 = db.fixed_ip_get_instance_v6( - context.get_admin_context(), - address_v6) - self.assertEqual(instance_ref['id'], instance_ref2['id']) - self.assertEqual(address_v6, - utils.to_global_ipv6( - network_ref['cidr_v6'], - instance_ref['mac_address'])) - self._deallocate_address(0, address) - db.instance_destroy(context.get_admin_context(), - instance_ref['id']) - - def test_available_ips(self): - """Make sure the number of available ips for the network is correct - - The number of available IP addresses depends on the test - environment's setup. - - Network size is set in test fixture's setUp method. - - There are ips reserved at the bottom and top of the range. - services (network, gateway, CloudPipe, broadcast) - """ - network = db.project_get_network(context.get_admin_context(), - self.projects[0].id) - net_size = flags.FLAGS.network_size - admin_context = context.get_admin_context() - total_ips = (db.network_count_available_ips(admin_context, - network['id']) + - db.network_count_reserved_ips(admin_context, - network['id']) + - db.network_count_allocated_ips(admin_context, - network['id'])) - self.assertEqual(total_ips, net_size) +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Base class of Unit Tests for all network models +""" +import IPy +import os + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.auth import manager + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +class NetworkTestCase(test.TestCase): + """Test cases for network code""" + def setUp(self): + super(NetworkTestCase, self).setUp() + # NOTE(vish): if you change these flags, make sure to change the + # flags in the corresponding section in nova-dhcpbridge + self.flags(connection_type='fake', + fake_call=True, + fake_network=True) + self.manager = manager.AuthManager() + self.user = self.manager.create_user('netuser', 'netuser', 'netuser') + self.projects = [] + self.network = utils.import_object(FLAGS.network_manager) + self.context = context.RequestContext(project=None, user=self.user) + for i in range(FLAGS.num_networks): + name = 'project%s' % i + project = self.manager.create_project(name, 'netuser', name) + self.projects.append(project) + # create the necessary network data for the project + user_context = context.RequestContext(project=self.projects[i], + user=self.user) + host = self.network.get_network_host(user_context.elevated()) + instance_ref = self._create_instance(0) + self.instance_id = instance_ref['id'] + instance_ref = self._create_instance(1) + self.instance2_id = instance_ref['id'] + + def tearDown(self): + # TODO(termie): this should really be instantiating clean datastores + # in between runs, one failure kills all the tests + db.instance_destroy(context.get_admin_context(), self.instance_id) + db.instance_destroy(context.get_admin_context(), self.instance2_id) + for project in self.projects: + self.manager.delete_project(project) + self.manager.delete_user(self.user) + super(NetworkTestCase, self).tearDown() + + def _create_instance(self, project_num, mac=None): + if not mac: + mac = utils.generate_mac() + project = self.projects[project_num] + self.context._project = project + self.context.project_id = project.id + return db.instance_create(self.context, + {'project_id': project.id, + 'mac_address': mac}) + + def _create_address(self, project_num, instance_id=None): + """Create an address in given project num""" + if instance_id is None: + instance_id = self.instance_id + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + return self.network.allocate_fixed_ip(self.context, instance_id) + + def _deallocate_address(self, project_num, address): + self.context._project = self.projects[project_num] + self.context.project_id = self.projects[project_num].id + self.network.deallocate_fixed_ip(self.context, address) + + def _is_allocated_in_project(self, address, project_id): + """Returns true if address is in specified project""" + project_net = db.network_get_by_bridge(context.get_admin_context(), + FLAGS.flat_network_bridge) + network = db.fixed_ip_get_network(context.get_admin_context(), + address) + instance = db.fixed_ip_get_instance(context.get_admin_context(), + address) + # instance exists until release + return instance is not None and network['id'] == project_net['id'] + + def test_private_ipv6(self): + """Make sure ipv6 is OK""" + if FLAGS.use_ipv6: + instance_ref = self._create_instance(0) + address = self._create_address(0, instance_ref['id']) + network_ref = db.project_get_network( + context.get_admin_context(), + self.context.project_id) + address_v6 = db.instance_get_fixed_address_v6( + context.get_admin_context(), + instance_ref['id']) + self.assertEqual(instance_ref['mac_address'], + utils.to_mac(address_v6)) + instance_ref2 = db.fixed_ip_get_instance_v6( + context.get_admin_context(), + address_v6) + self.assertEqual(instance_ref['id'], instance_ref2['id']) + self.assertEqual(address_v6, + utils.to_global_ipv6( + network_ref['cidr_v6'], + instance_ref['mac_address'])) + self._deallocate_address(0, address) + db.instance_destroy(context.get_admin_context(), + instance_ref['id']) + + def test_available_ips(self): + """Make sure the number of available ips for the network is correct + + The number of available IP addresses depends on the test + environment's setup. + + Network size is set in test fixture's setUp method. + + There are ips reserved at the bottom and top of the range. + services (network, gateway, CloudPipe, broadcast) + """ + network = db.project_get_network(context.get_admin_context(), + self.projects[0].id) + net_size = flags.FLAGS.network_size + admin_context = context.get_admin_context() + total_ips = (db.network_count_available_ips(admin_context, + network['id']) + + db.network_count_reserved_ips(admin_context, + network['id']) + + db.network_count_allocated_ips(admin_context, + network['id'])) + self.assertEqual(total_ips, net_size) diff --git a/nova/tests/test_flat_network.py b/nova/tests/test_flat_network.py index b6f7762c5..dcc617e25 100644 --- a/nova/tests/test_flat_network.py +++ b/nova/tests/test_flat_network.py @@ -1,161 +1,161 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. -""" -Unit Tests for flat network code -""" -import IPy -import os -import unittest - -from nova import context -from nova import db -from nova import exception -from nova import flags -from nova import log as logging -from nova import test -from nova import utils -from nova.auth import manager -from nova.tests.network import base - - -FLAGS = flags.FLAGS -LOG = logging.getLogger('nova.tests.network') - - -class FlatNetworkTestCase(base.NetworkTestCase): - """Test cases for network code""" - def test_public_network_association(self): - """Makes sure that we can allocate a public ip""" - # TODO(vish): better way of adding floating ips - - self.context._project = self.projects[0] - self.context.project_id = self.projects[0].id - pubnet = IPy.IP(flags.FLAGS.floating_range) - address = str(pubnet[0]) - try: - db.floating_ip_get_by_address(context.get_admin_context(), address) - except exception.NotFound: - db.floating_ip_create(context.get_admin_context(), - {'address': address, - 'host': FLAGS.host}) - - self.assertRaises(NotImplementedError, - self.network.allocate_floating_ip, - self.context, self.projects[0].id) - - fix_addr = self._create_address(0) - float_addr = address - self.assertRaises(NotImplementedError, - self.network.associate_floating_ip, - self.context, float_addr, fix_addr) - - address = db.instance_get_floating_address(context.get_admin_context(), - self.instance_id) - self.assertEqual(address, None) - - self.assertRaises(NotImplementedError, - self.network.disassociate_floating_ip, - self.context, float_addr) - - address = db.instance_get_floating_address(context.get_admin_context(), - self.instance_id) - self.assertEqual(address, None) - - self.assertRaises(NotImplementedError, - self.network.deallocate_floating_ip, - self.context, float_addr) - - self.network.deallocate_fixed_ip(self.context, fix_addr) - db.floating_ip_destroy(context.get_admin_context(), float_addr) - - def test_allocate_deallocate_fixed_ip(self): - """Makes sure that we can allocate and deallocate a fixed ip""" - address = self._create_address(0) - self.assertTrue(self._is_allocated_in_project(address, - self.projects[0].id)) - self._deallocate_address(0, address) - - # check if the fixed ip address is really deallocated - self.assertFalse(self._is_allocated_in_project(address, - self.projects[0].id)) - - def test_side_effects(self): - """Ensures allocating and releasing has no side effects""" - address = self._create_address(0) - address2 = self._create_address(1, self.instance2_id) - - self.assertTrue(self._is_allocated_in_project(address, - self.projects[0].id)) - self.assertTrue(self._is_allocated_in_project(address2, - self.projects[1].id)) - - self._deallocate_address(0, address) - self.assertFalse(self._is_allocated_in_project(address, - self.projects[0].id)) - - # First address release shouldn't affect the second - self.assertTrue(self._is_allocated_in_project(address2, - self.projects[0].id)) - - self._deallocate_address(1, address2) - self.assertFalse(self._is_allocated_in_project(address2, - self.projects[1].id)) - - def test_ips_are_reused(self): - """Makes sure that ip addresses that are deallocated get reused""" - address = self._create_address(0) - self.network.deallocate_fixed_ip(self.context, address) - - address2 = self._create_address(0) - self.assertEqual(address, address2) - - self.network.deallocate_fixed_ip(self.context, address2) - - def test_too_many_addresses(self): - """Test for a NoMoreAddresses exception when all fixed ips are used. - """ - admin_context = context.get_admin_context() - network = db.project_get_network(admin_context, self.projects[0].id) - num_available_ips = db.network_count_available_ips(admin_context, - network['id']) - addresses = [] - instance_ids = [] - for i in range(num_available_ips): - instance_ref = self._create_instance(0) - instance_ids.append(instance_ref['id']) - address = self._create_address(0, instance_ref['id']) - addresses.append(address) - - ip_count = db.network_count_available_ips(context.get_admin_context(), - network['id']) - self.assertEqual(ip_count, 0) - self.assertRaises(db.NoMoreAddresses, - self.network.allocate_fixed_ip, - self.context, - 'foo') - - for i in range(num_available_ips): - self.network.deallocate_fixed_ip(self.context, addresses[i]) - db.instance_destroy(context.get_admin_context(), instance_ids[i]) - ip_count = db.network_count_available_ips(context.get_admin_context(), - network['id']) - self.assertEqual(ip_count, num_available_ips) - - def run(self, result=None): - if(FLAGS.network_manager == 'nova.network.manager.FlatManager'): - super(FlatNetworkTestCase, self).run(result) +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Unit Tests for flat network code +""" +import IPy +import os +import unittest + +from nova import context +from nova import db +from nova import exception +from nova import flags +from nova import log as logging +from nova import test +from nova import utils +from nova.auth import manager +from nova.tests.network import base + + +FLAGS = flags.FLAGS +LOG = logging.getLogger('nova.tests.network') + + +class FlatNetworkTestCase(base.NetworkTestCase): + """Test cases for network code""" + def test_public_network_association(self): + """Makes sure that we can allocate a public ip""" + # TODO(vish): better way of adding floating ips + + self.context._project = self.projects[0] + self.context.project_id = self.projects[0].id + pubnet = IPy.IP(flags.FLAGS.floating_range) + address = str(pubnet[0]) + try: + db.floating_ip_get_by_address(context.get_admin_context(), address) + except exception.NotFound: + db.floating_ip_create(context.get_admin_context(), + {'address': address, + 'host': FLAGS.host}) + + self.assertRaises(NotImplementedError, + self.network.allocate_floating_ip, + self.context, self.projects[0].id) + + fix_addr = self._create_address(0) + float_addr = address + self.assertRaises(NotImplementedError, + self.network.associate_floating_ip, + self.context, float_addr, fix_addr) + + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, None) + + self.assertRaises(NotImplementedError, + self.network.disassociate_floating_ip, + self.context, float_addr) + + address = db.instance_get_floating_address(context.get_admin_context(), + self.instance_id) + self.assertEqual(address, None) + + self.assertRaises(NotImplementedError, + self.network.deallocate_floating_ip, + self.context, float_addr) + + self.network.deallocate_fixed_ip(self.context, fix_addr) + db.floating_ip_destroy(context.get_admin_context(), float_addr) + + def test_allocate_deallocate_fixed_ip(self): + """Makes sure that we can allocate and deallocate a fixed ip""" + address = self._create_address(0) + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) + self._deallocate_address(0, address) + + # check if the fixed ip address is really deallocated + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) + + def test_side_effects(self): + """Ensures allocating and releasing has no side effects""" + address = self._create_address(0) + address2 = self._create_address(1, self.instance2_id) + + self.assertTrue(self._is_allocated_in_project(address, + self.projects[0].id)) + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[1].id)) + + self._deallocate_address(0, address) + self.assertFalse(self._is_allocated_in_project(address, + self.projects[0].id)) + + # First address release shouldn't affect the second + self.assertTrue(self._is_allocated_in_project(address2, + self.projects[0].id)) + + self._deallocate_address(1, address2) + self.assertFalse(self._is_allocated_in_project(address2, + self.projects[1].id)) + + def test_ips_are_reused(self): + """Makes sure that ip addresses that are deallocated get reused""" + address = self._create_address(0) + self.network.deallocate_fixed_ip(self.context, address) + + address2 = self._create_address(0) + self.assertEqual(address, address2) + + self.network.deallocate_fixed_ip(self.context, address2) + + def test_too_many_addresses(self): + """Test for a NoMoreAddresses exception when all fixed ips are used. + """ + admin_context = context.get_admin_context() + network = db.project_get_network(admin_context, self.projects[0].id) + num_available_ips = db.network_count_available_ips(admin_context, + network['id']) + addresses = [] + instance_ids = [] + for i in range(num_available_ips): + instance_ref = self._create_instance(0) + instance_ids.append(instance_ref['id']) + address = self._create_address(0, instance_ref['id']) + addresses.append(address) + + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, 0) + self.assertRaises(db.NoMoreAddresses, + self.network.allocate_fixed_ip, + self.context, + 'foo') + + for i in range(num_available_ips): + self.network.deallocate_fixed_ip(self.context, addresses[i]) + db.instance_destroy(context.get_admin_context(), instance_ids[i]) + ip_count = db.network_count_available_ips(context.get_admin_context(), + network['id']) + self.assertEqual(ip_count, num_available_ips) + + def run(self, result=None): + if(FLAGS.network_manager == 'nova.network.manager.FlatManager'): + super(FlatNetworkTestCase, self).run(result) -- cgit From 05ccc91bdb3ad47ffecee29d21835ded17f65816 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 16 Mar 2011 17:24:32 -0400 Subject: pep8 --- nova/tests/api/openstack/test_flavors.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_flavors.py b/nova/tests/api/openstack/test_flavors.py index 8dfcfe293..954d72adf 100644 --- a/nova/tests/api/openstack/test_flavors.py +++ b/nova/tests/api/openstack/test_flavors.py @@ -46,6 +46,7 @@ def return_instance_types(context, num=2): instance_types[name] = stub_flavor(i, name) return instance_types + def return_instance_type_not_found(context, flavorid): raise exception.NotFound() @@ -205,7 +206,7 @@ class FlavorsTest(test.TestCase): ], }, ] - self.assertEqual(flavor, expected) + self.assertEqual(flavor, expected) def test_get_flavor_list_detail_v1_1(self): req = webob.Request.blank('/v1.1/flavors/detail') -- cgit From cc2d4728d32d016ef803d0def456cac6e315e8fa Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 16 Mar 2011 17:56:40 -0400 Subject: get started testing --- nova/tests/image/__init__.py | 0 nova/tests/image/test_glance.py | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 nova/tests/image/__init__.py create mode 100644 nova/tests/image/test_glance.py (limited to 'nova/tests') diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py new file mode 100644 index 000000000..b568f593d --- /dev/null +++ b/nova/tests/image/test_glance.py @@ -0,0 +1,18 @@ +import unittest + +from nova.image import glance + +class StubGlanceClient(object): + + def __init__(self, images): + self._images = images + + def get_image_meta(id): + return self._images[id] + +class TestGlance(unittest.TestCase): + + def test(self): + images = {'xyz': "image"} + client = StubGlanceClient(images) + service = glance.GlanceImageService(client) -- cgit From a7990e0263f2113e3814209118ecb2afc140826e Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 16 Mar 2011 15:01:10 -0700 Subject: Use _ trick to hide base test class, thereby avoiding mixins and helping PyLint --- nova/tests/test_auth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 2a7817032..0d24e5db2 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -80,10 +80,10 @@ class user_and_project_generator(object): self.manager.delete_project(self.project) -class AuthManagerTestCase(object): +class _AuthManagerBaseTestCase(test.TestCase): def setUp(self): FLAGS.auth_driver = self.auth_driver - super(AuthManagerTestCase, self).setUp() + super(_AuthManagerBaseTestCase, self).setUp() self.flags(connection_type='fake') self.manager = manager.AuthManager(new=True) @@ -324,11 +324,11 @@ class AuthManagerTestCase(object): self.assertTrue(user.is_admin()) -class AuthManagerLdapTestCase(AuthManagerTestCase, test.TestCase): +class AuthManagerLdapTestCase(_AuthManagerBaseTestCase): auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' -class AuthManagerDbTestCase(AuthManagerTestCase, test.TestCase): +class AuthManagerDbTestCase(_AuthManagerBaseTestCase): auth_driver = 'nova.auth.dbdriver.DbDriver' -- cgit From 65b11b3b9c76db2440d480bbc41b72f24bee8afc Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 16 Mar 2011 15:11:39 -0700 Subject: Avoid mixins on image tests, keeping pylint much happier --- nova/tests/api/openstack/test_images.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..9a33236af 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -41,10 +41,15 @@ from nova.tests.api.openstack import fakes FLAGS = flags.FLAGS -class BaseImageServiceTests(object): +class _BaseImageServiceTests(test.TestCase): """Tasks to test for all image services""" + def __init__(self): + super(_BaseImageServiceTests, self).__init__() + self.service = None + self.context = None + def test_create(self): fixture = {'name': 'test image', @@ -132,8 +137,7 @@ class BaseImageServiceTests(object): self.assertEquals(1, num_images) -class LocalImageServiceTest(test.TestCase, - BaseImageServiceTests): +class LocalImageServiceTest(_BaseImageServiceTests): """Tests the local image service""" @@ -152,8 +156,7 @@ class LocalImageServiceTest(test.TestCase, super(LocalImageServiceTest, self).tearDown() -class GlanceImageServiceTest(test.TestCase, - BaseImageServiceTests): +class GlanceImageServiceTest(_BaseImageServiceTests): """Tests the local image service""" -- cgit From aecd4eb9d363875cd84be5aa6fdb9afeb500b4f4 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Wed, 16 Mar 2011 15:44:45 -0700 Subject: Fix __init__ method on unit tests (they take a method_name kwarg) --- nova/tests/api/openstack/test_images.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 9a33236af..8814b9b1a 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -45,8 +45,8 @@ class _BaseImageServiceTests(test.TestCase): """Tasks to test for all image services""" - def __init__(self): - super(_BaseImageServiceTests, self).__init__() + def __init__(self, *args, **kwargs): + super(_BaseImageServiceTests, self).__init__(*args, **kwargs) self.service = None self.context = None -- cgit From c44ab013f5f5a078b27c4965e2e3c4abbfe30c59 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Wed, 16 Mar 2011 20:42:39 -0400 Subject: Revert testsuite changes --- nova/tests/test_virt.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index fed8ff803..b214f5ce7 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -256,15 +256,12 @@ class LibvirtConnTestCase(test.TestCase): 'uml': ('uml:///system', [(lambda t: t.find('.').get('type'), 'uml'), (lambda t: t.find('./os/type').text, 'uml')]), - 'lxc': ('lxc:///', - [(lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'exe')]), 'xen': ('xen:///', [(lambda t: t.find('.').get('type'), 'xen'), (lambda t: t.find('./os/type').text, 'linux')]), } - for hypervisor_type in ['qemu', 'kvm', 'lxc', 'xen']: + for hypervisor_type in ['qemu', 'kvm', 'xen']: check_list = type_uri_map[hypervisor_type][1] if rescue: -- cgit From fea850245835f867aa4cc741b612445e56e64236 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Wed, 16 Mar 2011 20:52:14 -0400 Subject: Add basic tests for lxc containers. --- nova/tests/test_virt.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b214f5ce7..fab05de10 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -227,6 +227,42 @@ class LibvirtConnTestCase(test.TestCase): self._check_xml_and_uri(instance_data, expect_kernel=True, expect_ramdisk=True, rescue=True) + def test_lxc_container_and_uri(self): + instance_data = dict(self.test_instace) + self._check_xml_and_container(instance_data) + + def _check_xml_and_container(self, instance): + user_context = context.RequestContext(project=self.project, + user=self.user) + instance_ref = db.instance_create(user_context,instance) + host = self.network.get_network_host(user_context.elevated()) + network_ref= db.project_get_network(context.get_admin_context(), + self.project.id) + + fixed_ip = {'address': self.test_ip, + 'network_id': network_ref['id']} + + ctxt = context.get_admin_context() + fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) + db.fixed_ip_update(ctxt, self.test_ip, + {'allocated': True, + 'instance_id': instance_ref['id']}) + + FLAGS.libvirt_type = 'lxc' + self.assertEquals(uri, 'lxc:///') + + xml = conn.to_xml(instance_ref) + tree = xml_to_tree(xml) + + check = [ + (lambda t: t.find('.').get('type'), 'lxc'), + (lambda t: t.find('./os/type').text, 'exe') + ] + + for i (check, expected_result) in enumerate(check): + self.aseertEqual(check(time), + expected_result, + '%s failed common check %d' % (xml, i)) def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): user_context = context.RequestContext(project=self.project, -- cgit From a766b4111addad804e47b8be3e6dedb5f80a83c4 Mon Sep 17 00:00:00 2001 From: Monsyne Dragon Date: Thu, 17 Mar 2011 02:20:18 +0000 Subject: added in network qos support for xenserver. Pull qos settings from flavor, use when creating instance. --- nova/tests/db/fakes.py | 30 +++++++++++++++++++++++++----- nova/tests/test_xenapi.py | 8 ++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 5e9a3aa3b..2d25d5fc5 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -28,13 +28,33 @@ def stub_out_db_instance_api(stubs): """ Stubs out the db API for creating Instances """ INSTANCE_TYPES = { - 'm1.tiny': dict(memory_mb=512, vcpus=1, local_gb=0, flavorid=1), - 'm1.small': dict(memory_mb=2048, vcpus=1, local_gb=20, flavorid=2), + 'm1.tiny': dict(memory_mb=512, + vcpus=1, + local_gb=0, + flavorid=1, + rxtx_cap=1), + 'm1.small': dict(memory_mb=2048, + vcpus=1, + local_gb=20, + flavorid=2, + rxtx_cap=2), 'm1.medium': - dict(memory_mb=4096, vcpus=2, local_gb=40, flavorid=3), - 'm1.large': dict(memory_mb=8192, vcpus=4, local_gb=80, flavorid=4), + dict(memory_mb=4096, + vcpus=2, + local_gb=40, + flavorid=3, + rxtx_cap=3), + 'm1.large': dict(memory_mb=8192, + vcpus=4, + local_gb=80, + flavorid=4, + rxtx_cap=4), 'm1.xlarge': - dict(memory_mb=16384, vcpus=8, local_gb=160, flavorid=5)} + dict(memory_mb=16384, + vcpus=8, + local_gb=160, + flavorid=5, + rxtx_cap=5)} class FakeModel(object): """ Stubs out for model """ diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 8b0affd5c..66a973a78 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -361,6 +361,14 @@ class XenAPIVMTestCase(test.TestCase): glance_stubs.FakeGlance.IMAGE_RAMDISK) self.check_vm_params_for_linux_with_external_kernel() + def test_spawn_with_network_qos(self): + self._create_instance() + for vif_ref in xenapi_fake.get_all('VIF'): + vif_rec = xenapi_fake.get_record('VIF', vif_ref) + self.assertEquals(vif_rec['qos_algorithm_type'], 'ratelimit') + self.assertEquals(vif_rec['qos_algorithm_params']['kbps'], + str(4 * 1024)) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) -- cgit From 11698a131fe6b99bfd91a977a975b07bcd4c2b2b Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Thu, 17 Mar 2011 03:21:09 -0400 Subject: Added mechanism for versioned controllers for openstack api versions 1.0/1.1. Create servers in the 1.1 api now supports imageRef/flavorRef instead of imageId/flavorId. --- nova/tests/api/openstack/fakes.py | 18 +++++--- nova/tests/api/openstack/test_auth.py | 6 +-- nova/tests/api/openstack/test_servers.py | 73 +++++++++++++++++++++++++++++--- 3 files changed, 79 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index a3968b57b..370eb68cb 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -76,14 +76,18 @@ def fake_wsgi(self, req): return self.application -def wsgi_app(inner_application=None): - if not inner_application: - inner_application = openstack.APIRouter() +def wsgi_app(inner_app10=None, inner_app11=None): + if not inner_app10: + inner_app10 = openstack.APIRouterV10() + if not inner_app11: + inner_app11 = openstack.APIRouterV11() mapper = urlmap.URLMap() - api = openstack.FaultWrapper(auth.AuthMiddleware( - ratelimiting.RateLimitingMiddleware(inner_application))) - mapper['/v1.0'] = api - mapper['/v1.1'] = api + api10 = openstack.FaultWrapper(auth.AuthMiddleware( + ratelimiting.RateLimitingMiddleware(inner_app10))) + api11 = openstack.FaultWrapper(auth.AuthMiddleware( + ratelimiting.RateLimitingMiddleware(inner_app11))) + mapper['/v1.0'] = api10 + mapper['/v1.1'] = api11 mapper['/'] = openstack.FaultWrapper(openstack.Versions()) return mapper diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index aaaa4e415..b7f0dfbe5 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -82,8 +82,7 @@ class Test(test.TestCase): self.assertEqual(result.headers['X-Storage-Url'], "") token = result.headers['X-Auth-Token'] - self.stubs.Set(nova.api.openstack, 'APIRouter', - fakes.FakeRouter) + self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter) req = webob.Request.blank('/v1.0/fake') req.headers['X-Auth-Token'] = token result = req.get_response(fakes.wsgi_app()) @@ -189,8 +188,7 @@ class TestLimiter(test.TestCase): self.assertEqual(len(result.headers['X-Auth-Token']), 40) token = result.headers['X-Auth-Token'] - self.stubs.Set(nova.api.openstack, 'APIRouter', - fakes.FakeRouter) + self.stubs.Set(nova.api.openstack, 'APIRouterV10', fakes.FakeRouter) req = webob.Request.blank('/v1.0/fake') req.method = 'POST' req.headers['X-Auth-Token'] = token diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 27d174fe9..0116bbed1 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -158,7 +158,7 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.0/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['id'], 1) self.assertEqual(res_dict['server']['name'], 'server1') def test_get_server_by_id_with_addresses(self): @@ -169,7 +169,7 @@ class ServersTest(test.TestCase): req = webob.Request.blank('/v1.0/servers/1') res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['id'], 1) self.assertEqual(res_dict['server']['name'], 'server1') addresses = res_dict['server']['addresses'] self.assertEqual(len(addresses["public"]), len(public)) @@ -177,7 +177,7 @@ class ServersTest(test.TestCase): self.assertEqual(len(addresses["private"]), 1) self.assertEqual(addresses["private"][0], private) - def test_get_server_by_id_with_addresses_v1_1(self): + def test_get_server_by_id_with_addresses_v11(self): private = "192.168.0.3" public = ["1.2.3.4"] new_return_server = return_server_with_addresses(private, public) @@ -186,7 +186,7 @@ class ServersTest(test.TestCase): req.environ['api.version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - self.assertEqual(res_dict['server']['id'], '1') + self.assertEqual(res_dict['server']['id'], 1) self.assertEqual(res_dict['server']['name'], 'server1') addresses = res_dict['server']['addresses'] self.assertEqual(len(addresses["public"]), len(public)) @@ -273,13 +273,13 @@ class ServersTest(test.TestCase): "get_image_id_from_image_hash", image_id_from_hash) body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, + name='server_test', imageId=3, flavorId=2, metadata={'hello': 'world', 'open': 'stack'}, personality={})) req = webob.Request.blank('/v1.0/servers') req.method = 'POST' req.body = json.dumps(body) - req.headers["Content-Type"] = "application/json" + req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) @@ -287,8 +287,67 @@ class ServersTest(test.TestCase): self.assertEqual('serv', server['adminPass'][:4]) self.assertEqual(16, len(server['adminPass'])) self.assertEqual('server_test', server['name']) - self.assertEqual('1', server['id']) + self.assertEqual(1, server['id']) + self.assertEqual(2, server['flavorId']) + self.assertEqual(3, server['imageId']) + self.assertEqual(res.status_int, 200) + + def test_create_instance_v11(self): + def instance_create(context, inst): + return {'id': '1', 'display_name': 'server_test'} + + def server_update(context, id, params): + return instance_create(context, id) + + def fake_method(*args, **kwargs): + pass + + def project_get_network(context, user_id): + return dict(id='1', host='localhost') + + def queue_get_for(context, *args): + return 'network_topic' + + def kernel_ramdisk_mapping(*args, **kwargs): + return (1, 1) + + def image_id_from_hash(*args, **kwargs): + return 2 + + self.stubs.Set(nova.db.api, 'project_get_network', project_get_network) + self.stubs.Set(nova.db.api, 'instance_create', instance_create) + self.stubs.Set(nova.rpc, 'cast', fake_method) + self.stubs.Set(nova.rpc, 'call', fake_method) + self.stubs.Set(nova.db.api, 'instance_update', + server_update) + self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for) + self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip', + fake_method) + self.stubs.Set(nova.api.openstack.servers.Controller, + "_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping) + self.stubs.Set(nova.api.openstack.common, + "get_image_id_from_image_hash", image_id_from_hash) + imageRef = 'http://localhost/v1.1/images/2' + flavorRef = 'http://localhost/v1.1/flavors/3' + body = dict(server=dict( + name='server_test', imageRef=imageRef, flavorRef=flavorRef, + metadata={'hello': 'world', 'open': 'stack'}, + personality={})) + req = webob.Request.blank('/v1.1/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + + res = req.get_response(fakes.wsgi_app()) + + server = json.loads(res.body)['server'] + self.assertEqual('serv', server['adminPass'][:4]) + self.assertEqual(16, len(server['adminPass'])) + self.assertEqual('server_test', server['name']) + self.assertEqual(1, server['id']) + self.assertEqual(flavorRef, server['flavorRef']) + self.assertEqual(imageRef, server['imageRef']) self.assertEqual(res.status_int, 200) def test_update_no_body(self): -- cgit From 7f837b1f22922cb968b0ffb42bdb4d56c0d9f3c3 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 07:06:58 -0400 Subject: Update Authors and testsuite --- nova/tests/test_virt.py | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index fab05de10..92c80272b 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -228,16 +228,16 @@ class LibvirtConnTestCase(test.TestCase): expect_ramdisk=True, rescue=True) def test_lxc_container_and_uri(self): - instance_data = dict(self.test_instace) + instance_data = dict(self.test_instance) self._check_xml_and_container(instance_data) def _check_xml_and_container(self, instance): user_context = context.RequestContext(project=self.project, user=self.user) - instance_ref = db.instance_create(user_context,instance) + instance_ref = db.instance_create(user_context, instance) host = self.network.get_network_host(user_context.elevated()) - network_ref= db.project_get_network(context.get_admin_context(), - self.project.id) + network_ref = db.project_get_network(context.get_admin_context(), + self.project.id) fixed_ip = {'address': self.test_ip, 'network_id': network_ref['id']} @@ -245,24 +245,28 @@ class LibvirtConnTestCase(test.TestCase): ctxt = context.get_admin_context() fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) db.fixed_ip_update(ctxt, self.test_ip, - {'allocated': True, - 'instance_id': instance_ref['id']}) + {'allocated': True, + 'instance_id': instance_ref['id']}) FLAGS.libvirt_type = 'lxc' + conn = libvirt_conn.LibvirtConnection(True) + + uri = conn.get_uri() self.assertEquals(uri, 'lxc:///') xml = conn.to_xml(instance_ref) tree = xml_to_tree(xml) check = [ - (lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'exe') + (lambda t: t.find('.').get('type'), 'lxc'), + (lambda t: t.find('./os/type').text, 'exe'), ] - for i (check, expected_result) in enumerate(check): - self.aseertEqual(check(time), + for i, (check, expected_result) in enumerate(check): + self.assertEqual(check(tree), expected_result, '%s failed common check %d' % (xml, i)) + def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): user_context = context.RequestContext(project=self.project, @@ -322,6 +326,7 @@ class LibvirtConnTestCase(test.TestCase): check = (lambda t: t.find('./os/initrd'), None) check_list.append(check) + common_checks = [ (lambda t: t.find('.').tag, 'domain'), (lambda t: t.find( @@ -338,8 +343,9 @@ class LibvirtConnTestCase(test.TestCase): (lambda t: t.find('./devices/serial/source').get( 'path').split('/')[1], 'console.log'), (lambda t: t.find('./memory').text, '2097152')] + if rescue: - common_checks += [ + common_checks = [ (lambda t: t.findall('./devices/disk/source')[0].get( 'file').split('/')[1], 'disk.rescue'), (lambda t: t.findall('./devices/disk/source')[1].get( @@ -362,14 +368,15 @@ class LibvirtConnTestCase(test.TestCase): xml = conn.to_xml(instance_ref, rescue) tree = xml_to_tree(xml) for i, (check, expected_result) in enumerate(checks): - self.assertEqual(check(tree), - expected_result, - '%s failed check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed check %d' % (xml, i)) + for i, (check, expected_result) in enumerate(common_checks): - self.assertEqual(check(tree), - expected_result, - '%s failed common check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed common check %d' % (xml, i)) # This test is supposed to make sure we don't # override a specifically set uri -- cgit From 9ba500c304595dff037da296f26cb13d02bfbc04 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 07:57:06 -0400 Subject: Fix pep8 errors --- nova/tests/test_virt.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 92c80272b..7d50960a3 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -326,7 +326,6 @@ class LibvirtConnTestCase(test.TestCase): check = (lambda t: t.find('./os/initrd'), None) check_list.append(check) - common_checks = [ (lambda t: t.find('.').tag, 'domain'), (lambda t: t.find( @@ -372,7 +371,6 @@ class LibvirtConnTestCase(test.TestCase): expected_result, '%s failed check %d' % (xml, i)) - for i, (check, expected_result) in enumerate(common_checks): self.assertEqual(check(tree), expected_result, -- cgit From cc716f9648355bc3737dd749a35dc327ebda1e6f Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 09:15:33 -0400 Subject: Fixed typo when I was trying to add test cases for lxc --- nova/tests/test_virt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 7d50960a3..c2b8ba0a1 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -344,7 +344,7 @@ class LibvirtConnTestCase(test.TestCase): (lambda t: t.find('./memory').text, '2097152')] if rescue: - common_checks = [ + common_checks += [ (lambda t: t.findall('./devices/disk/source')[0].get( 'file').split('/')[1], 'disk.rescue'), (lambda t: t.findall('./devices/disk/source')[1].get( -- cgit From 732633c93f8d8cf71875d2caf096c9efbcf9dbce Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 17 Mar 2011 09:55:41 -0400 Subject: Update the Openstack API to handle case where personality is set but null in the request to create a server. --- nova/tests/api/openstack/test_servers.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 03e00af2a..230c9d03c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -943,11 +943,13 @@ class TestServerInstanceCreation(test.TestCase): server['name'] = 'new-server-test' server['imageId'] = 1 server['flavorId'] = 1 - if personality_files is not None: + if personality_files: personalities = [] for path, contents in personality_files: personalities.append({'path': path, 'contents': contents}) server['personality'] = personalities + else: + server['personality'] = None return {'server': server} def _get_create_request_json(self, body_dict): @@ -976,7 +978,7 @@ class TestServerInstanceCreation(test.TestCase): for item in metadata.iteritems(): body_parts.append('%s' % item) body_parts.append('') - if 'personality' in server: + if 'personality' in server and server['personality'] is not None: personalities = server['personality'] body_parts.append('') for file in personalities: @@ -1093,6 +1095,13 @@ class TestServerInstanceCreation(test.TestCase): self.assertEquals(response.status_int, 400) self.assertEquals(injected_files, None) + def test_create_instance_with_null_personality(self): + personality = None + request, response, injected_files = \ + self._create_instance_with_personality_json(personality) + self.assertEquals(response.status_int, 200) + self.assertEquals(injected_files, []) + def test_create_instance_with_three_personalities(self): files = [ ('/etc/sudoers', 'ALL ALL=NOPASSWD: ALL\n'), -- cgit From 36285d3acb940c39dc1827699c1e3c0cc9846529 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 10:22:57 -0400 Subject: Fix more pep8 errors --- nova/tests/test_virt.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index c2b8ba0a1..222975adc 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -367,14 +367,14 @@ class LibvirtConnTestCase(test.TestCase): xml = conn.to_xml(instance_ref, rescue) tree = xml_to_tree(xml) for i, (check, expected_result) in enumerate(checks): - self.assertEqual(check(tree), - expected_result, - '%s failed check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed check %d' % (xml, i)) for i, (check, expected_result) in enumerate(common_checks): - self.assertEqual(check(tree), - expected_result, - '%s failed common check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed common check %d' % (xml, i)) # This test is supposed to make sure we don't # override a specifically set uri -- cgit From abc6c82449dfc46a33dcd8190840e51f44b5b930 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 17 Mar 2011 07:30:22 -0700 Subject: Replaced capability flags with List --- nova/tests/api/openstack/test_zones.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 5e3aee4a7..12d39fd29 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -178,7 +178,7 @@ class ZonesTest(test.TestCase): def test_zone_info(self): FLAGS.zone_name = 'darksecret' - FLAGS.zone_capabilities = 'cap1:a,b;cap2:c,d' + FLAGS.zone_capabilities = ['cap1=a;b', 'cap2=c;d'] self.stubs.Set(api, '_call_scheduler', zone_caps) body = dict(zone=dict(username='zeb', password='sneaky')) @@ -188,5 +188,5 @@ class ZonesTest(test.TestCase): res_dict = json.loads(res.body) self.assertEqual(res.status_int, 200) self.assertEqual(res_dict['zone']['name'], 'darksecret') - self.assertEqual(res_dict['zone']['cap1'], 'a,b') - self.assertEqual(res_dict['zone']['cap2'], 'c,d') + self.assertEqual(res_dict['zone']['cap1'], 'a;b') + self.assertEqual(res_dict['zone']['cap2'], 'c;d') -- cgit From a06203c66af05c96c161b80511f4a6607ffe4905 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 10:41:55 -0400 Subject: Fix up tests --- nova/tests/test_virt.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 222975adc..fefc11f0d 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -239,8 +239,8 @@ class LibvirtConnTestCase(test.TestCase): network_ref = db.project_get_network(context.get_admin_context(), self.project.id) - fixed_ip = {'address': self.test_ip, - 'network_id': network_ref['id']} + fixed_ip = {'address': self.test_ip, + 'network_id': network_ref['id']} ctxt = context.get_admin_context() fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) @@ -259,13 +259,13 @@ class LibvirtConnTestCase(test.TestCase): check = [ (lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'exe'), + (lambda t: t.find('./os/type').text, 'exe') ] for i, (check, expected_result) in enumerate(check): - self.assertEqual(check(tree), - expected_result, - '%s failed common check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed common check %d' % (xml, i)) def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): @@ -342,7 +342,6 @@ class LibvirtConnTestCase(test.TestCase): (lambda t: t.find('./devices/serial/source').get( 'path').split('/')[1], 'console.log'), (lambda t: t.find('./memory').text, '2097152')] - if rescue: common_checks += [ (lambda t: t.findall('./devices/disk/source')[0].get( -- cgit From dee8a59b5d575a0327464e27115d0d870cde97be Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 10:43:48 -0400 Subject: more pep8 fixes --- nova/tests/test_virt.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index fefc11f0d..2510525fc 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -263,9 +263,9 @@ class LibvirtConnTestCase(test.TestCase): ] for i, (check, expected_result) in enumerate(check): - self.assertEqual(check(tree), - expected_result, - '%s failed common check %d' % (xml, i)) + self.assertEqual(check(tree), + expected_result, + '%s failed common check %d' % (xml, i)) def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): -- cgit From cbcda1ec466fd498fb8e9fe47c72b52c2d4b3dde Mon Sep 17 00:00:00 2001 From: sateesh Date: Thu, 17 Mar 2011 20:13:48 +0530 Subject: 1) Update few comments where whitespace is missing after '#' 2) Update document so that copy right notice doesn't appear in generated document 3) Now using self.flag(...) instead of setting the flags like FLAGS.vmwareapi_username by direct assignment. 4) Added the missing double quote at the end a string in vim_util.py --- nova/tests/test_vmwareapi.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index b22d8b7b9..d17805b99 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -43,15 +43,15 @@ class VMWareAPIVMTestCase(test.TestCase): def setUp(self): super(VMWareAPIVMTestCase, self).setUp() + self.flags(vmwareapi_host_ip='test_url', + vmwareapi_host_username='test_username', + vmware_host_password='test_pass') self.manager = manager.AuthManager() self.user = self.manager.create_user('fake', 'fake', 'fake', admin=True) self.project = self.manager.create_project('fake', 'fake', 'fake') self.network = utils.import_object(FLAGS.network_manager) self.stubs = stubout.StubOutForTesting() - FLAGS.vmwareapi_host_ip = 'test_url' - FLAGS.vmwareapi_host_username = 'test_username' - FLAGS.vmwareapi_host_password = 'test_pass' vmwareapi_fake.reset() db_fakes.stub_out_db_instance_api(self.stubs) stubs.set_stubs(self.stubs) -- cgit From 4364a158fd31bdfcfa3ae835a2fd9c0f47d3632f Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Thu, 17 Mar 2011 10:45:31 -0400 Subject: pep8 fixes --- nova/tests/test_virt.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 2510525fc..45f98fcde 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -259,8 +259,7 @@ class LibvirtConnTestCase(test.TestCase): check = [ (lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'exe') - ] + (lambda t: t.find('./os/type').text, 'exe')] for i, (check, expected_result) in enumerate(check): self.assertEqual(check(tree), -- cgit From f8aa9485fe2048ff916d9dd40478ef0b1486077f Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 17 Mar 2011 10:45:46 -0400 Subject: Switch back to 'is not None' for personality_files check. (makes mark happy) --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 230c9d03c..71c57bfbf 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -943,7 +943,7 @@ class TestServerInstanceCreation(test.TestCase): server['name'] = 'new-server-test' server['imageId'] = 1 server['flavorId'] = 1 - if personality_files: + if personality_files is not None: personalities = [] for path, contents in personality_files: personalities.append({'path': path, 'contents': contents}) -- cgit From 66d9c0d51d410998de86508359135a7d978997ef Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 17 Mar 2011 11:05:31 -0400 Subject: Call _create_personality_request_dict within the personalities_null test. --- nova/tests/api/openstack/test_servers.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 71c57bfbf..6969e88c7 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -948,8 +948,6 @@ class TestServerInstanceCreation(test.TestCase): for path, contents in personality_files: personalities.append({'path': path, 'contents': contents}) server['personality'] = personalities - else: - server['personality'] = None return {'server': server} def _get_create_request_json(self, body_dict): @@ -1097,10 +1095,12 @@ class TestServerInstanceCreation(test.TestCase): def test_create_instance_with_null_personality(self): personality = None - request, response, injected_files = \ - self._create_instance_with_personality_json(personality) + body_dict = self._create_personality_request_dict(personality) + body_dict['server']['personality'] = None + request = self._get_create_request_json(body_dict) + compute_api, response = \ + self._run_create_instance_with_mock_compute_api(request) self.assertEquals(response.status_int, 200) - self.assertEquals(injected_files, []) def test_create_instance_with_three_personalities(self): files = [ -- cgit From 137bbc37e9fb664d0b97a607b5f69c38df938077 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 17 Mar 2011 11:10:58 -0400 Subject: No need to modify this test case function as well. --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6969e88c7..d0b07b7ae 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -976,7 +976,7 @@ class TestServerInstanceCreation(test.TestCase): for item in metadata.iteritems(): body_parts.append('%s' % item) body_parts.append('') - if 'personality' in server and server['personality'] is not None: + if 'personality' in server: personalities = server['personality'] body_parts.append('') for file in personalities: -- cgit From 41c097000c1eeb4f1532b22f136c383b8174e6cc Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 17 Mar 2011 11:35:32 -0400 Subject: Add tests and code to handle multiple ResponseExtension objects. --- nova/tests/api/openstack/extensions/foxinsocks.py | 17 ++++++++++++++--- nova/tests/api/openstack/test_extensions.py | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py index 2e93d8a55..fa979c7b5 100644 --- a/nova/tests/api/openstack/extensions/foxinsocks.py +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -49,16 +49,27 @@ class Foxinsocks(object): def get_response_extensions(self): response_exts = [] - def _resp_handler(res): + def _goose_handler(res): #NOTE: This only handles JSON responses. # You can use content type header to test for XML. data = json.loads(res.body) data['flavor']['googoose'] = "Gooey goo for chewy chewing!" return data - resp_ext = extensions.ResponseExtension('GET', '/flavors/:(id)', - _resp_handler) + resp_ext = extensions.ResponseExtension('GET', '/v1.0/flavors/:(id)', + _goose_handler) response_exts.append(resp_ext) + + def _bands_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['big_bands'] = 'Pig Bands!' + return data + + resp_ext2 = extensions.ResponseExtension('GET', '/v1.0/flavors/:(id)', + _bands_handler) + response_exts.append(resp_ext2) return response_exts def _add_tweedle(self, input_dict, req, id): diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 149f1973e..11ed61e0d 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -195,7 +195,7 @@ class ResponseExtensionTest(unittest.TestCase): fakes.stub_out_auth(self.stubs) self.context = context.get_admin_context() - def test_get_resources(self): + def test_get_resources_with_stub_mgr(self): test_resp = "Gooey goo for chewy chewing!" @@ -208,6 +208,7 @@ class ResponseExtensionTest(unittest.TestCase): resp_ext = extensions.ResponseExtension('GET', '/v1.0/flavors/:(id)', _resp_handler) + manager = StubExtensionManager(None, None, resp_ext) app = fakes.wsgi_app() ext_midware = extensions.ExtensionMiddleware(app, manager) @@ -216,3 +217,17 @@ class ResponseExtensionTest(unittest.TestCase): self.assertEqual(200, response.status_int) response_data = json.loads(response.body) self.assertEqual(test_resp, response_data['flavor']['googoose']) + + def test_get_resources_with_mgr(self): + + test_resp = "Gooey goo for chewy chewing!" + + app = fakes.wsgi_app() + ext_midware = extensions.ExtensionMiddleware(app) + request = webob.Request.blank("/v1.0/flavors/1") + response = request.get_response(ext_midware) + self.assertEqual(200, response.status_int) + response_data = json.loads(response.body) + print response_data + self.assertEqual(test_resp, response_data['flavor']['googoose']) + self.assertEqual("Pig Bands!", response_data['big_bands']) -- cgit From e79eaca86c4073cc8bc6c59be83d0f1bf5e2cea4 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 12:20:22 -0400 Subject: glance image service show testcases --- nova/tests/image/test_glance.py | 64 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index b568f593d..971a32a17 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -1,3 +1,4 @@ +import datetime as dt import unittest from nova.image import glance @@ -5,14 +6,63 @@ from nova.image import glance class StubGlanceClient(object): def __init__(self, images): - self._images = images + self.images = images - def get_image_meta(id): - return self._images[id] + def get_image_meta(self, id): + return self.images[id] + + def get_images_detailed(self): + return self.images class TestGlance(unittest.TestCase): - def test(self): - images = {'xyz': "image"} - client = StubGlanceClient(images) - service = glance.GlanceImageService(client) + def setUp(self): + self.client = StubGlanceClient(None) + self.service = glance.GlanceImageService(self.client) + + def test_show_passes_through_to_client(self): + self.client.images = {'xyz': "image"} + self.assertEqual(self.service.show({}, 'xyz'), "image") + + def test_detail_passes_through_to_client(self): + self.client.images = "these are the images" + self.assertEqual(self.service.detail({}), self.client.images) + + def test_show_makes_create_datetimes(self): + create_time = dt.datetime.utcnow() + self.client.images = {'xyz': { + 'id': "id", + 'name': "my awesome image", + 'created_at': create_time.isoformat(), + }} + actual = self.service.show({}, 'xyz') + self.assertEqual(actual['created_at'], create_time) + + def test_show_makes_update_datetimes(self): + update_time = dt.datetime.utcnow() + self.client.images = {'abc': { + 'id': "id", + 'name': "my okay image", + 'updated_at': update_time.isoformat(), + }} + actual = self.service.show({}, 'abc') + self.assertEqual(actual['updated_at'], update_time) + + def test_show_makes_delete_datetimes(self): + delete_time = dt.datetime.utcnow() + self.client.images = {'123': { + 'id': "123", + 'name': "my lame image", + 'deleted_at': delete_time.isoformat(), + }} + actual = self.service.show({}, '123') + self.assertEqual(actual['deleted_at'], delete_time) + + def test_show_handles_deleted_at_none(self): + self.client.images = {'747': { + 'id': "747", + 'name': "not deleted", + 'deleted_at': None, + }} + actual = self.service.show({}, '747') + self.assertEqual(actual['deleted_at'], None) -- cgit From 3ee835c60d2b43086b1e324501025d1f0221da27 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 13:50:41 -0400 Subject: handle timestamps in glance service detail --- nova/tests/image/test_glance.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 971a32a17..16fe0e7c0 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -12,7 +12,7 @@ class StubGlanceClient(object): return self.images[id] def get_images_detailed(self): - return self.images + return self.images.itervalues() class TestGlance(unittest.TestCase): @@ -25,8 +25,8 @@ class TestGlance(unittest.TestCase): self.assertEqual(self.service.show({}, 'xyz'), "image") def test_detail_passes_through_to_client(self): - self.client.images = "these are the images" - self.assertEqual(self.service.detail({}), self.client.images) + self.client.images = {1: "an image"} + self.assertEqual(list(self.service.detail({})), ["an image"]) def test_show_makes_create_datetimes(self): create_time = dt.datetime.utcnow() @@ -66,3 +66,24 @@ class TestGlance(unittest.TestCase): }} actual = self.service.show({}, '747') self.assertEqual(actual['deleted_at'], None) + + def test_detail_handles_timestamps(self): + now = dt.datetime.utcnow() + image1 = { + 'id': 1, + 'name': 'image 1', + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), + 'deleted_at': None, + } + image2 = { + 'id': 2, + 'name': 'image 2', + 'deleted_at': now.isoformat(), + } + self.client.images = {1: image1, 2: image2} + i1, i2 = self.service.detail({}) + self.assertEqual(i1['created_at'], now) + self.assertEqual(i1['updated_at'], now) + self.assertEqual(i1['deleted_at'], None) + self.assertEqual(i2['deleted_at'], now) -- cgit From 66c237a4d321887830e5282781870525abf00365 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 14:04:31 -0400 Subject: teach glance image server get to handle timestamps --- nova/tests/image/test_glance.py | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 16fe0e7c0..1e6c45219 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -14,7 +14,17 @@ class StubGlanceClient(object): def get_images_detailed(self): return self.images.itervalues() -class TestGlance(unittest.TestCase): + def get_image(self, id): + return self.images[id], [] + + +class NullWriter(object): + + def write(self, *arg, **kwargs): + pass + + +class TestGlanceImageServiceDatetimes(unittest.TestCase): def setUp(self): self.client = StubGlanceClient(None) @@ -87,3 +97,21 @@ class TestGlance(unittest.TestCase): self.assertEqual(i1['updated_at'], now) self.assertEqual(i1['deleted_at'], None) self.assertEqual(i2['deleted_at'], now) + + def test_get_handles_timestamps(self): + now = dt.datetime.utcnow() + self.client.images = {'abcd': { + 'id': 'abcd', + 'name': 'nifty image', + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), + 'deleted_at': now.isoformat(), + }} + actual = self.service.get({}, 'abcd', NullWriter()) + for attr in ('created_at', 'updated_at', 'deleted_at'): + self.assertEqual(actual[attr], now) + + def test_get_handles_deleted_at_none(self): + self.client.images = {'abcd': {'deleted_at': None}} + actual = self.service.get({}, 'abcd', NullWriter()) + self.assertEqual(actual['deleted_at'], None) -- cgit From c8e474d04dce462650c2a9f57cbcb106ce3ef0c9 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 14:05:08 -0400 Subject: pep8 --- nova/tests/image/test_glance.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 1e6c45219..9b17cf261 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -3,6 +3,7 @@ import unittest from nova.image import glance + class StubGlanceClient(object): def __init__(self, images): -- cgit From 4334ca9d6b0ac8a9b2edb1fbcbf0bc4df28b2961 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 15:04:28 -0400 Subject: get api openstack test_images working --- nova/tests/api/openstack/test_images.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..47dd11e5b 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -182,8 +182,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): {'id': '23g2ogk23k4hhkk4k42l', 'imageId': '23g2ogk23k4hhkk4k42l', 'name': 'public image #1', - 'created_at': str(datetime.datetime.utcnow()), - 'updated_at': str(datetime.datetime.utcnow()), + 'created_at': datetime.datetime.utcnow().isoformat(), + 'updated_at': datetime.datetime.utcnow().isoformat(), 'deleted_at': None, 'deleted': False, 'is_public': True, @@ -192,8 +192,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): {'id': 'slkduhfas73kkaskgdas', 'imageId': 'slkduhfas73kkaskgdas', 'name': 'public image #2', - 'created_at': str(datetime.datetime.utcnow()), - 'updated_at': str(datetime.datetime.utcnow()), + 'created_at': datetime.datetime.utcnow().isoformat(), + 'updated_at': datetime.datetime.utcnow().isoformat(), 'deleted_at': None, 'deleted': False, 'is_public': True, -- cgit From 2f1a1d293915cde6e15c85e0bb43fb21ae26f7b0 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 17 Mar 2011 15:29:54 -0400 Subject: handle create and update requests, and update the base image service documentation to reflect the (defacto) behavior --- nova/tests/image/test_glance.py | 54 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 9b17cf261..6e94aa909 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -6,8 +6,10 @@ from nova.image import glance class StubGlanceClient(object): - def __init__(self, images): + def __init__(self, images, add_response=None, update_response=None): self.images = images + self.add_response = add_response + self.update_response = update_response def get_image_meta(self, id): return self.images[id] @@ -18,6 +20,12 @@ class StubGlanceClient(object): def get_image(self, id): return self.images[id], [] + def add_image(self, metadata, data): + return self.add_response + + def update_image(self, image_id, metadata, data): + return self.update_response + class NullWriter(object): @@ -116,3 +124,47 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.client.images = {'abcd': {'deleted_at': None}} actual = self.service.get({}, 'abcd', NullWriter()) self.assertEqual(actual['deleted_at'], None) + + def test_create_handles_timestamps(self): + now = dt.datetime.utcnow() + self.client.add_response = { + 'id': 'abcd', + 'name': 'blah', + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), + 'deleted_at': now.isoformat(), + } + actual = self.service.create({}, {}) + for attr in ('created_at', 'updated_at', 'deleted_at'): + self.assertEqual(actual[attr], now) + + def test_create_handles_deleted_at_none(self): + self.client.add_response = { + 'id': 'abcd', + 'name': 'blah', + 'deleted_at': None, + } + actual = self.service.create({}, {}) + self.assertEqual(actual['deleted_at'], None) + + def test_update_handles_timestamps(self): + now = dt.datetime.utcnow() + self.client.update_response = { + 'id': 'abcd', + 'name': 'blah', + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), + 'deleted_at': now.isoformat(), + } + actual = self.service.update({}, 'dummy_id', {}) + for attr in ('created_at', 'updated_at', 'deleted_at'): + self.assertEqual(actual[attr], now) + + def test_create_handles_deleted_at_none(self): + self.client.update_response = { + 'id': 'abcd', + 'name': 'blah', + 'deleted_at': None, + } + actual = self.service.update({}, 'dummy_id', {}) + self.assertEqual(actual['deleted_at'], None) -- cgit From 35bd58bd9dc6441f5620b262d1f65b852f56c67c Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 17 Mar 2011 15:43:56 -0400 Subject: moving Versions app out of __init__.py into its own module; adding openstack versions tests; adding links to version entities --- nova/tests/api/openstack/fakes.py | 3 +- nova/tests/api/openstack/test_versions.py | 61 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 nova/tests/api/openstack/test_versions.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index a08fe385a..3b7e558b6 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -35,6 +35,7 @@ import nova.api.openstack.auth from nova.api import openstack from nova.api.openstack import auth from nova.api.openstack import ratelimiting +from nova.api.openstack import versions from nova.auth.manager import User, Project from nova.image import glance from nova.image import local @@ -80,7 +81,7 @@ def wsgi_app(inner_application=None): ratelimiting.RateLimitingMiddleware(inner_application))) mapper['/v1.0'] = api mapper['/v1.1'] = api - mapper['/'] = openstack.FaultWrapper(openstack.Versions()) + mapper['/'] = openstack.FaultWrapper(versions.Versions()) return mapper diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py new file mode 100644 index 000000000..330d74dde --- /dev/null +++ b/nova/tests/api/openstack/test_versions.py @@ -0,0 +1,61 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json +import webob + +from nova import context +from nova import test +from nova.tests.api.openstack import fakes + + +class VersionsTest(test.TestCase): + def setUp(self): + super(VersionsTest, self).setUp() + self.context = context.get_admin_context() + + def tearDown(self): + super(VersionsTest, self).tearDown() + + def test_get_version_list(self): + req = webob.Request.blank('/') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + versions = json.loads(res.body)["versions"] + expected = [ + { + "id": "v1.1", + "status": "CURRENT", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.1", + } + ], + }, + { + "id": "v1.0", + "status": "DEPRECATED", + "links": [ + { + "rel": "self", + "href": "http://localhost/v1.0", + } + ], + }, + ] + self.assertEqual(versions, expected) -- cgit From e138e0836922ee0608feefbff5e4e5d03ad14197 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Thu, 17 Mar 2011 16:02:37 -0400 Subject: Now returns a 400 for a create server request with invalid hrefs for imageRef/flavorRef values. Also added tests. --- nova/tests/api/openstack/test_servers.py | 64 +++++++++++++------------------- 1 file changed, 25 insertions(+), 39 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 846af5c3a..6e78db9da 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -239,7 +239,7 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [1, 2]) - def _test_create_instance_helper(self): + def _setup_for_create_instance(self): """Shared implementation for tests below that create instance""" def instance_create(context, inst): return {'id': '1', 'display_name': 'server_test'} @@ -276,6 +276,9 @@ class ServersTest(test.TestCase): self.stubs.Set(nova.api.openstack.common, "get_image_id_from_image_hash", image_id_from_hash) + def _test_create_instance_helper(self): + self._setup_for_create_instance() + body = dict(server=dict( name='server_test', imageId=3, flavorId=2, metadata={'hello': 'world', 'open': 'stack'}, @@ -296,41 +299,15 @@ class ServersTest(test.TestCase): self.assertEqual(3, server['imageId']) self.assertEqual(res.status_int, 200) - def test_create_instance_v11(self): - def instance_create(context, inst): - return {'id': '1', 'display_name': 'server_test'} - - def server_update(context, id, params): - return instance_create(context, id) - - def fake_method(*args, **kwargs): - pass - - def project_get_network(context, user_id): - return dict(id='1', host='localhost') - - def queue_get_for(context, *args): - return 'network_topic' - - def kernel_ramdisk_mapping(*args, **kwargs): - return (1, 1) + def test_create_instance(self): + self._test_create_instance_helper() - def image_id_from_hash(*args, **kwargs): - return 2 + def test_create_instance_no_key_pair(self): + fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False) + self._test_create_instance_helper() - self.stubs.Set(nova.db.api, 'project_get_network', project_get_network) - self.stubs.Set(nova.db.api, 'instance_create', instance_create) - self.stubs.Set(nova.rpc, 'cast', fake_method) - self.stubs.Set(nova.rpc, 'call', fake_method) - self.stubs.Set(nova.db.api, 'instance_update', - server_update) - self.stubs.Set(nova.db.api, 'queue_get_for', queue_get_for) - self.stubs.Set(nova.network.manager.VlanManager, 'allocate_fixed_ip', - fake_method) - self.stubs.Set(nova.api.openstack.servers.Controller, - "_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping) - self.stubs.Set(nova.api.openstack.common, - "get_image_id_from_image_hash", image_id_from_hash) + def test_create_instance_v11(self): + self._setup_for_create_instance() imageRef = 'http://localhost/v1.1/images/2' flavorRef = 'http://localhost/v1.1/flavors/3' @@ -354,12 +331,21 @@ class ServersTest(test.TestCase): self.assertEqual(imageRef, server['imageRef']) self.assertEqual(res.status_int, 200) - def test_create_instance(self): - self._test_create_instance_helper() + def test_create_instance_v11_bad_href(self): + self._setup_for_create_instance() - def test_create_instance_no_key_pair(self): - fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False) - self._test_create_instance_helper() + imageRef = 'http://localhost/v1.1/images/asdf' + flavorRef = 'http://localhost/v1.1/flavors/3' + body = dict(server=dict( + name='server_test', imageRef=imageRef, flavorRef=flavorRef, + metadata={'hello': 'world', 'open': 'stack'}, + personality={})) + req = webob.Request.blank('/v1.1/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) def test_update_no_body(self): req = webob.Request.blank('/v1.0/servers/1') -- cgit From 3628f50b4ecd2db0377fd9c158248d3b7e8e98ff Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 17 Mar 2011 16:26:52 -0400 Subject: Better comment for fault. Improved readability of two small sections. --- nova/tests/api/openstack/test_limits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_limits.py b/nova/tests/api/openstack/test_limits.py index d1db93a59..05cfacc60 100644 --- a/nova/tests/api/openstack/test_limits.py +++ b/nova/tests/api/openstack/test_limits.py @@ -273,7 +273,7 @@ class LimiterTest(BaseLimitTestSuite): def _check_sum(self, num, verb, url, username=None): """Check and sum results from checks.""" results = self._check(num, verb, url, username) - return sum(filter(lambda x: x != None, results)) + return sum(item for item in results if item) def test_no_delay_GET(self): """ -- cgit From b331a3df4d921414409ebb7a738d97e34f782102 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 17 Mar 2011 21:39:55 +0100 Subject: Adjust test cases. --- nova/tests/test_volume.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index 1b1d72092..5d68ca2ae 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -336,8 +336,8 @@ class ISCSITestCase(DriverTestCase): self.mox.StubOutWithMock(self.volume.driver, '_execute') for i in volume_id_list: tid = db.volume_get_iscsi_target_num(self.context, i) - self.volume.driver._execute("sudo ietadm --op show --tid=%(tid)d" - % locals()) + self.volume.driver._execute("sudo", "ietadm", "--op", "show", + "--tid=%(tid)d" % locals()) self.stream.truncate(0) self.mox.ReplayAll() @@ -355,8 +355,9 @@ class ISCSITestCase(DriverTestCase): # the first vblade process isn't running tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0]) self.mox.StubOutWithMock(self.volume.driver, '_execute') - self.volume.driver._execute("sudo ietadm --op show --tid=%(tid)d" - % locals()).AndRaise(exception.ProcessExecutionError()) + self.volume.driver._execute("sudo", "ietadm", "--op", "show", + "--tid=%(tid)d" % locals() + ).AndRaise(exception.ProcessExecutionError()) self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, -- cgit From 06c0b81e54adf3fb0635a7cd7679bcdb051e6263 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Thu, 17 Mar 2011 21:43:22 +0100 Subject: pep8 --- nova/tests/test_utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 51cd57c76..e08d229b0 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -62,7 +62,8 @@ exit 1 'always get passed ' 'correctly') runs = int(runs.strip()) - self.assertEquals(runs, 10, 'Ran %d times instead of 10.' % (runs,)) + self.assertEquals(runs, 10, + 'Ran %d times instead of 10.' % (runs,)) finally: os.unlink(tmpfilename) os.unlink(tmpfilename2) @@ -95,6 +96,7 @@ grep foo os.unlink(tmpfilename) os.unlink(tmpfilename2) + class GetFromPathTestCase(test.TestCase): def test_tolerates_nones(self): f = utils.get_from_path -- cgit From b605b53e4b652e0a3f364d505b5fd7240fd4ea36 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Thu, 17 Mar 2011 20:44:15 +0000 Subject: Test changes --- nova/tests/api/openstack/test_servers.py | 22 ++++++++++++---------- nova/tests/xenapi/stubs.py | 7 +++++-- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 03e00af2a..14b72e097 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -491,16 +491,6 @@ class ServersTest(test.TestCase): req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) - def test_server_resize(self): - body = dict(server=dict( - name='server_test', imageId=2, flavorId=2, metadata={}, - personality={})) - req = webob.Request.blank('/v1.0/servers/1/action') - req.method = 'POST' - req.content_type = 'application/json' - req.body = json.dumps(body) - res = req.get_response(fakes.wsgi_app()) - def test_delete_server_instance(self): req = webob.Request.blank('/v1.0/servers/1') req.method = 'DELETE' @@ -556,6 +546,18 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) + def test_resized_server_has_correct_status(self): + req = self.webreq('/1', 'GET', dict(resize=dict(flavorId=3))) + def fake_migration_get(*args): + return {} + + self.stubs.Set(nova.db, 'migration_get_by_instance_and_status', + fake_migration_get) + res = req.get_response(fakes.wsgi_app()) + body = json.loads(res.body) + self.assertEqual(body['server']['status'], 'resize-confirm') + + def test_confirm_resize_server(self): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 70d46a1fb..7f9706a3d 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -228,6 +228,9 @@ class FakeSessionForMigrationTests(fake.SessionBase): def VDI_get_by_uuid(*args): return 'hurr' + def VDI_resize_online(*args): + pass + def VM_start(self, _1, ref, _2, _3): vm = fake.get_record('VM', ref) if vm['power_state'] != 'Halted': @@ -240,7 +243,7 @@ class FakeSessionForMigrationTests(fake.SessionBase): def stub_out_migration_methods(stubs): def fake_get_snapshot(self, instance): - return 'foo', 'bar' + return 'vm_ref', dict(image='foo', snap='bar') @classmethod def fake_get_vdi(cls, session, vm_ref): @@ -249,7 +252,7 @@ def stub_out_migration_methods(stubs): vdi_rec = session.get_xenapi().VDI.get_record(vdi_ref) return vdi_ref, {'uuid': vdi_rec['uuid'], } - def fake_shutdown(self, inst, vm, method='clean'): + def fake_shutdown(self, inst, vm, hard=True): pass @classmethod -- cgit From 8d5ffa079e768adec969a4e8ab540c24a7faaaa6 Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Thu, 17 Mar 2011 20:45:18 +0000 Subject: Pep8 --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 14b72e097..07ebfdd88 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -548,6 +548,7 @@ class ServersTest(test.TestCase): def test_resized_server_has_correct_status(self): req = self.webreq('/1', 'GET', dict(resize=dict(flavorId=3))) + def fake_migration_get(*args): return {} @@ -556,7 +557,6 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) body = json.loads(res.body) self.assertEqual(body['server']['status'], 'resize-confirm') - def test_confirm_resize_server(self): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) -- cgit From 4940654f04c50c8593f8e5486fa9e4998f2a3fc7 Mon Sep 17 00:00:00 2001 From: Todd Willey Date: Thu, 17 Mar 2011 19:32:25 -0400 Subject: Changing project manager should make sure that user is a project member. --- nova/tests/test_auth.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_auth.py b/nova/tests/test_auth.py index 2a7817032..885596f56 100644 --- a/nova/tests/test_auth.py +++ b/nova/tests/test_auth.py @@ -299,6 +299,13 @@ class AuthManagerTestCase(object): self.assertEqual('test2', project.project_manager_id) self.assertEqual('new desc', project.description) + def test_modify_project_adds_new_manager(self): + with user_and_project_generator(self.manager): + with user_generator(self.manager, name='test2'): + self.manager.modify_project('testproj', 'test2', 'new desc') + project = self.manager.get_project('testproj') + self.assertTrue('test2' in project.member_ids) + def test_can_delete_project(self): with user_generator(self.manager): self.manager.create_project('testproj', 'test1') -- cgit From af67fba36436feeede4dcc5720e51d2b66c3094a Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 17 Mar 2011 22:30:34 -0400 Subject: Images now v1.1 supported...mostly. --- nova/tests/api/openstack/test_images.py | 171 +++++++++++++++++++++++++------- 1 file changed, 134 insertions(+), 37 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 76f758929..c313192b7 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -42,8 +42,9 @@ FLAGS = flags.FLAGS class BaseImageServiceTests(object): - - """Tasks to test for all image services""" + """ + Tasks to test for all image services. + """ def test_create(self): @@ -173,10 +174,9 @@ class GlanceImageServiceTest(test.TestCase, class ImageControllerWithGlanceServiceTest(test.TestCase): - - """Test of the OpenStack API /images application controller""" - - # Registered images at start of each test. + """ + Test of the OpenStack API /images application controller w/Glance. + """ IMAGE_FIXTURES = [ {'id': '23g2ogk23k4hhkk4k42l', @@ -198,7 +198,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'deleted': False, 'is_public': True, 'status': 'available', - 'image_type': 'ramdisk'}] + 'image_type': 'ramdisk'}, + ] def setUp(self): super(ImageControllerWithGlanceServiceTest, self).setUp() @@ -219,36 +220,132 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): super(ImageControllerWithGlanceServiceTest, self).tearDown() def test_get_image_index(self): - req = webob.Request.blank('/v1.0/images') - res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) + request = webob.Request.blank('/v1.0/images') + response = request.get_response(fakes.wsgi_app()) + + response_dict = json.loads(response.body) + response_list = response_dict["images"] + + for image in self.IMAGE_FIXTURES: + test_image = { + "id": image["id"], + "name": image["name"], + } + self.assertTrue(test_image in response_list) + + self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) + + def test_get_image_index_v1_1(self): + request = webob.Request.blank('/v1.1/images') + response = request.get_response(fakes.wsgi_app()) + + response_dict = json.loads(response.body) + response_list = response_dict["images"] + + for image in self.IMAGE_FIXTURES: + href = "http://localhost/v1.1/images/%s" % image["id"] + test_image = { + "id": image["id"], + "name": image["name"], + "links": [{ + "rel": "self", + "href": "http://localhost/v1.1/images/%s" % image["id"], + }, + { + "rel": "bookmark", + "type": "application/json", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": href, + }], + } + print test_image + print + print response_list + self.assertTrue(test_image in response_list) + + self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) - fixture_index = [dict(id=f['id'], name=f['name']) for f - in self.IMAGE_FIXTURES] + def test_get_image_details(self): + request = webob.Request.blank('/v1.0/images/detail') + response = request.get_response(fakes.wsgi_app()) + + response_dict = json.loads(response.body) + response_list = response_dict["images"] + + for image in self.IMAGE_FIXTURES: + test_image = { + "id": image["id"], + "name": image["name"], + "updated": image["updated_at"], + "created": image["created_at"], + "status": image["status"], + } + self.assertTrue(test_image in response_list) + + self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) + + def test_get_image_details_v1_1(self): + request = webob.Request.blank('/v1.1/images/detail') + response = request.get_response(fakes.wsgi_app()) + + response_dict = json.loads(response.body) + response_list = response_dict["images"] + + for image in self.IMAGE_FIXTURES: + href = "http://localhost/v1.1/images/%s" % image["id"] + test_image = { + "id": image["id"], + "name": image["name"], + "updated": image["updated_at"], + "created": image["created_at"], + "status": image["status"], + "links": [{ + "rel": "self", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/json", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": href, + }], + } + self.assertTrue(test_image in response_list) + + self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) + + def test_get_image_create_empty(self): + request = webob.Request.blank('/v1.1/images') + request.method = "POST" + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(400, response.status_int) + + def test_get_image_create_bad_no_name(self): + request = webob.Request.blank('/v1.1/images') + request.method = "POST" + request.content_type = "application/json" + request.body = json.dumps({ + "serverId": 1, + }) + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(400, response.status_int) + + def test_get_image_create_bad_no_id(self): + request = webob.Request.blank('/v1.1/images') + request.method = "POST" + request.content_type = "application/json" + request.body = json.dumps({ + "name" : "Snapshot Test", + }) + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(400, response.status_int) - for image in res_dict['images']: - self.assertEquals(1, fixture_index.count(image), - "image %s not in fixture index!" % str(image)) - def test_get_image_details(self): - req = webob.Request.blank('/v1.0/images/detail') - res = req.get_response(fakes.wsgi_app()) - res_dict = json.loads(res.body) - - def _is_equivalent_subset(x, y): - if set(x) <= set(y): - for k, v in x.iteritems(): - if x[k] != y[k]: - if x[k] == 'active' and y[k] == 'available': - continue - return False - return True - return False - - for image in res_dict['images']: - for image_fixture in self.IMAGE_FIXTURES: - if _is_equivalent_subset(image, image_fixture): - break - else: - self.assertEquals(1, 2, "image %s not in fixtures!" % - str(image)) -- cgit From 47bec2abb39f76d5b3ea634dbb7012d55d7f99ce Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 17 Mar 2011 23:07:40 -0400 Subject: adding servers container to openstack api v1.1 servers entities --- nova/tests/api/openstack/test_servers.py | 58 ++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6e78db9da..17689d405 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -164,6 +164,32 @@ class ServersTest(test.TestCase): self.assertEqual(res_dict['server']['id'], 1) self.assertEqual(res_dict['server']['name'], 'server1') + def test_get_server_by_id_v11(self): + req = webob.Request.blank('/v1.1/servers/1') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(res_dict['server']['id'], 1) + self.assertEqual(res_dict['server']['name'], 'server1') + + expected_links = [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/servers/1", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/servers/1", + }, + ] + + self.assertEqual(res_dict['server']['links'], expected_links) + def test_get_server_by_id_with_addresses(self): private = "192.168.0.3" public = ["1.2.3.4"] @@ -186,7 +212,6 @@ class ServersTest(test.TestCase): new_return_server = return_server_with_addresses(private, public) self.stubs.Set(nova.db.api, 'instance_get', new_return_server) req = webob.Request.blank('/v1.1/servers/1') - req.environ['api.version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) self.assertEqual(res_dict['server']['id'], 1) @@ -211,6 +236,36 @@ class ServersTest(test.TestCase): self.assertEqual(s.get('imageId', None), None) i += 1 + def test_get_server_list_v11(self): + req = webob.Request.blank('/v1.1/servers') + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + + for i,s in enumerate(res_dict['servers']): + self.assertEqual(s['id'], i) + self.assertEqual(s['name'], 'server%d' % i) + self.assertEqual(s.get('imageId', None), None) + + expected_links = [ + { + "rel": "self", + "href": "http://localhost/v1.1/servers/%d" % (i,), + }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/servers/%d" % (i,), + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/servers/%d" % (i,), + }, + ] + + self.assertEqual(s['links'], expected_links) + + def test_get_servers_with_limit(self): req = webob.Request.blank('/v1.0/servers?limit=3') res = req.get_response(fakes.wsgi_app()) @@ -419,7 +474,6 @@ class ServersTest(test.TestCase): def test_get_all_server_details_v1_1(self): req = webob.Request.blank('/v1.1/servers/detail') - req.environ['api.version'] = '1.1' res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) -- cgit From febbfd45a0c1dbd16093ab38897e94ddb331e9ea Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 17 Mar 2011 23:34:12 -0400 Subject: Updated naming, removed some prints, and removed some invalid tests. --- nova/tests/api/openstack/test_images.py | 31 ------------------------------- 1 file changed, 31 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index c313192b7..c5a866bc7 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -262,9 +262,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): "href": href, }], } - print test_image - print - print response_list self.assertTrue(test_image in response_list) self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) @@ -321,31 +318,3 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertTrue(test_image in response_list) self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) - - def test_get_image_create_empty(self): - request = webob.Request.blank('/v1.1/images') - request.method = "POST" - response = request.get_response(fakes.wsgi_app()) - self.assertEqual(400, response.status_int) - - def test_get_image_create_bad_no_name(self): - request = webob.Request.blank('/v1.1/images') - request.method = "POST" - request.content_type = "application/json" - request.body = json.dumps({ - "serverId": 1, - }) - response = request.get_response(fakes.wsgi_app()) - self.assertEqual(400, response.status_int) - - def test_get_image_create_bad_no_id(self): - request = webob.Request.blank('/v1.1/images') - request.method = "POST" - request.content_type = "application/json" - request.body = json.dumps({ - "name" : "Snapshot Test", - }) - response = request.get_response(fakes.wsgi_app()) - self.assertEqual(400, response.status_int) - - -- cgit From 0845d7081bc912e7eefa2d98e8c53033d872ef5e Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Thu, 17 Mar 2011 23:58:23 -0400 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 17689d405..9be68eb8d 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -241,7 +241,7 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - for i,s in enumerate(res_dict['servers']): + for i, s in enumerate(res_dict['servers']): self.assertEqual(s['id'], i) self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s.get('imageId', None), None) @@ -265,7 +265,6 @@ class ServersTest(test.TestCase): self.assertEqual(s['links'], expected_links) - def test_get_servers_with_limit(self): req = webob.Request.blank('/v1.0/servers?limit=3') res = req.get_response(fakes.wsgi_app()) -- cgit From acb7a7355055e04b9bb05fbba5f6590e57d681fa Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Fri, 18 Mar 2011 00:18:55 -0400 Subject: Support for markers for pagination as defined in the 1.1 spec. --- nova/tests/api/openstack/test_servers.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6e78db9da..e1cadcef6 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -239,6 +239,13 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [1, 2]) + def test_get_servers_with_marker(self): + req = webob.Request.blank('/v1.1/servers?marker=2') + res = req.get_response(fakes.wsgi_app()) + print 'body:', res.body + servers = json.loads(res.body)['servers'] + self.assertEqual([s['id'] for s in servers], [2, 3, 4]) + def _setup_for_create_instance(self): """Shared implementation for tests below that create instance""" def instance_create(context, inst): -- cgit From 1abcdbea89e69013c193d2eb0b4b7a0bc2e2fa58 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Fri, 18 Mar 2011 02:14:36 -0400 Subject: Implement metadata resource for Openstack API v1.1. Includes: -GET /servers/id/meta -POST /servers/id/meta -GET /servers/id/meta/key -PUT /servers/id/meta/key -DELETE /servers/id/meta/key --- nova/tests/api/openstack/test_server_metadata.py | 150 +++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 nova/tests/api/openstack/test_server_metadata.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py new file mode 100644 index 000000000..b280ae94c --- /dev/null +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -0,0 +1,150 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json +import stubout +import unittest +import webob + + +from nova.api import openstack +from nova.tests.api.openstack import fakes +import nova.wsgi + + +def return_create_instance_metadata(context, server_id, metadata): + return stub_server_metadata() + + +def return_server_metadata(context, server_id): + return stub_server_metadata() + + +def return_empty_server_metadata(context, server_id): + return {} + + +def delete_server_metadata(context, server_id, key): + pass + + +def stub_server_metadata(): + metadata = { + "key1": "value1", + "key2": "value2", + "key3": "value3", + "key4": "value4", + "key5": "value5" + } + return metadata + + +class ServerMetaDataTest(unittest.TestCase): + + def setUp(self): + super(ServerMetaDataTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_auth(self.stubs) + fakes.stub_out_key_pair_funcs(self.stubs) + #self.allow_admin = FLAGS.allow_admin_api + + def test_index(self): + self.stubs.Set(nova.db.api, 'get_instance_metadata', + return_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value1', res_dict['metadata']['key1']) + + def test_index_no_data(self): + self.stubs.Set(nova.db.api, 'get_instance_metadata', + return_empty_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual(0, len(res_dict['metadata'])) + + def test_show(self): + self.stubs.Set(nova.db.api, 'get_instance_metadata', + return_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/key5') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value5', res_dict['key5']) + + def test_show_meta_not_found(self): + self.stubs.Set(nova.db.api, 'get_instance_metadata', + return_empty_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/key6') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(404, res.status_int) + + def test_delete(self): + self.stubs.Set(nova.db.api, 'delete_instance_metadata', + delete_server_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/key5') + req.environ['api.version'] = '1.1' + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + + def test_create(self): + self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta') + req.environ['api.version'] = '1.1' + req.method = 'POST' + req.body = '{"metadata": {"key1": "value1"}}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value1', res_dict['metadata']['key1']) + + def test_update_item(self): + self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/key1') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "value1"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + res_dict = json.loads(res.body) + self.assertEqual('value1', res_dict['key1']) + + def test_update_item_body_uri_mismatch(self): + self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/bad') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "value1"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) -- cgit From c57908241e68a3f2a9f5eb4ee0fff6207962023d Mon Sep 17 00:00:00 2001 From: sateesh Date: Fri, 18 Mar 2011 17:20:46 +0530 Subject: Using eventlets greenthreads for optimized image processing. Fixed minor issues and style related nits. --- nova/tests/test_vmwareapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index d17805b99..b31ac11f1 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -45,7 +45,7 @@ class VMWareAPIVMTestCase(test.TestCase): super(VMWareAPIVMTestCase, self).setUp() self.flags(vmwareapi_host_ip='test_url', vmwareapi_host_username='test_username', - vmware_host_password='test_pass') + vmwareapi_host_password='test_pass') self.manager = manager.AuthManager() self.user = self.manager.create_user('fake', 'fake', 'fake', admin=True) -- cgit From 6e9a95fe81c389c672b5150d64749b274975f7bc Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 18 Mar 2011 09:56:05 -0400 Subject: disable-msg -> disable --- nova/tests/api/test_wsgi.py | 2 +- nova/tests/hyperv_unittest.py | 2 +- nova/tests/objectstore_unittest.py | 8 ++++---- nova/tests/test_api.py | 2 +- nova/tests/test_middleware.py | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index b1a849cf9..1ecdd1cfb 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -80,7 +80,7 @@ class ControllerTest(test.TestCase): "attributes": { "test": ["id"]}}} - def show(self, req, id): # pylint: disable-msg=W0622,C0103 + def show(self, req, id): # pylint: disable=W0622,C0103 return {"test": {"id": id}} def __init__(self): diff --git a/nova/tests/hyperv_unittest.py b/nova/tests/hyperv_unittest.py index 3980ae3cb..042819b9c 100644 --- a/nova/tests/hyperv_unittest.py +++ b/nova/tests/hyperv_unittest.py @@ -51,7 +51,7 @@ class HyperVTestCase(test.TestCase): instance_ref = db.instance_create(self.context, instance) conn = hyperv.get_connection(False) - conn._create_vm(instance_ref) # pylint: disable-msg=W0212 + conn._create_vm(instance_ref) # pylint: disable=W0212 found = [n for n in conn.list_instances() if n == instance_ref['name']] self.assertTrue(len(found) == 1) diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py index 5a1be08eb..5d160bdf8 100644 --- a/nova/tests/objectstore_unittest.py +++ b/nova/tests/objectstore_unittest.py @@ -179,7 +179,7 @@ class ObjectStoreTestCase(test.TestCase): class TestHTTPChannel(http.HTTPChannel): """Dummy site required for twisted.web""" - def checkPersistence(self, _, __): # pylint: disable-msg=C0103 + def checkPersistence(self, _, __): # pylint: disable=C0103 """Otherwise we end up with an unclean reactor.""" return False @@ -209,7 +209,7 @@ class S3APITestCase(test.TestCase): root = S3() self.site = TestSite(root) - # pylint: disable-msg=E1101 + # pylint: disable=E1101 self.listening_port = reactor.listenTCP(0, self.site, interface='127.0.0.1') # pylint: enable-msg=E1101 @@ -231,11 +231,11 @@ class S3APITestCase(test.TestCase): self.conn.get_http_connection = get_http_connection - def _ensure_no_buckets(self, buckets): # pylint: disable-msg=C0111 + def _ensure_no_buckets(self, buckets): # pylint: disable=C0111 self.assertEquals(len(buckets), 0, "Bucket list was not empty") return True - def _ensure_one_bucket(self, buckets, name): # pylint: disable-msg=C0111 + def _ensure_one_bucket(self, buckets, name): # pylint: disable=C0111 self.assertEquals(len(buckets), 1, "Bucket list didn't have exactly one element in it") self.assertEquals(buckets[0].name, name, "Wrong name") diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index d5c54a1c3..b67d6b12c 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -124,7 +124,7 @@ class ApiEc2TestCase(test.TestCase): self.mox.StubOutWithMock(self.ec2, 'new_http_connection') self.http = FakeHttplibConnection( self.app, '%s:8773' % (self.host), False) - # pylint: disable-msg=E1103 + # pylint: disable=E1103 self.ec2.new_http_connection(host, is_secure).AndReturn(self.http) return self.http diff --git a/nova/tests/test_middleware.py b/nova/tests/test_middleware.py index 9d49167ba..6564a6955 100644 --- a/nova/tests/test_middleware.py +++ b/nova/tests/test_middleware.py @@ -40,12 +40,12 @@ def conditional_forbid(req): class LockoutTestCase(test.TestCase): """Test case for the Lockout middleware.""" - def setUp(self): # pylint: disable-msg=C0103 + def setUp(self): # pylint: disable=C0103 super(LockoutTestCase, self).setUp() utils.set_time_override() self.lockout = ec2.Lockout(conditional_forbid) - def tearDown(self): # pylint: disable-msg=C0103 + def tearDown(self): # pylint: disable=C0103 utils.clear_time_override() super(LockoutTestCase, self).tearDown() -- cgit From 204ec967ee46079fb95a18fcfb1167ff57458015 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 18 Mar 2011 09:56:38 -0400 Subject: enable-msg -> enable --- nova/tests/objectstore_unittest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py index 5d160bdf8..4e2ac205e 100644 --- a/nova/tests/objectstore_unittest.py +++ b/nova/tests/objectstore_unittest.py @@ -212,7 +212,7 @@ class S3APITestCase(test.TestCase): # pylint: disable=E1101 self.listening_port = reactor.listenTCP(0, self.site, interface='127.0.0.1') - # pylint: enable-msg=E1101 + # pylint: enable=E1101 self.tcp_port = self.listening_port.getHost().port if not boto.config.has_section('Boto'): -- cgit From dba79cdf18f20f1e4e0758ae19b33de94881e440 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Fri, 18 Mar 2011 11:12:44 -0400 Subject: Added test case. --- nova/tests/test_api.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_api.py b/nova/tests/test_api.py index d5c54a1c3..7023eb410 100644 --- a/nova/tests/test_api.py +++ b/nova/tests/test_api.py @@ -20,6 +20,7 @@ import boto from boto.ec2 import regioninfo +from boto.exception import EC2ResponseError import datetime import httplib import random @@ -177,6 +178,17 @@ class ApiEc2TestCase(test.TestCase): self.manager.delete_project(project) self.manager.delete_user(user) + def test_terminate_invalid_instance(self): + """Attempt to terminate an invalid instance""" + self.expect_http() + self.mox.ReplayAll() + user = self.manager.create_user('fake', 'fake', 'fake') + project = self.manager.create_project('fake', 'fake', 'fake') + self.assertRaises(EC2ResponseError, self.ec2.terminate_instances, + "i-00000005") + self.manager.delete_project(project) + self.manager.delete_user(user) + def test_get_all_key_pairs(self): """Test that, after creating a user and project and generating a key pair, that the API call to list key pairs works properly""" -- cgit From 4f5dc6314f9dd7bb136a38fa07b109eb2e12734d Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 18 Mar 2011 10:06:36 -0700 Subject: auth_data is a list now (thanks Rick!) --- nova/tests/api/openstack/fakes.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 5decb2bad..020682093 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -240,7 +240,8 @@ class FakeAuthManager(object): @classmethod def reset_fake_data(cls): - cls.auth_data = dict(u1=User('id1', 'guy1', 'acc1', 'secret1', False)) + u1 = User('id1', 'guy1', 'acc1', 'secret1', False) + cls.auth_data = [u1] cls.projects = dict(testacct=Project('testacct', 'testacct', 'id1', -- cgit From ee09125e31a3afe64f0a9540a88fdb5febd7ddd4 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 18 Mar 2011 10:14:42 -0700 Subject: Avoid single-letter variable names --- nova/tests/api/openstack/fakes.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 020682093..9b5ed8a15 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -255,21 +255,21 @@ class FakeAuthManager(object): return FakeAuthManager.auth_data def get_user(self, uid): - for u in FakeAuthManager.auth_data: - if u.id == uid: - return u + for user in FakeAuthManager.auth_data: + if user.id == uid: + return user return None def get_user_from_access_key(self, key): - for u in FakeAuthManager.auth_data: - if u.access == key: - return u + for user in FakeAuthManager.auth_data: + if user.access == key: + return user return None def delete_user(self, uid): - for u in FakeAuthManager.auth_data: - if u.id == uid: - FakeAuthManager.auth_data.remove(u) + for user in FakeAuthManager.auth_data: + if user.id == uid: + FakeAuthManager.auth_data.remove(user) return None def create_user(self, name, access=None, secret=None, admin=False): @@ -278,10 +278,7 @@ class FakeAuthManager(object): return u def modify_user(self, user_id, access=None, secret=None, admin=None): - user = None - for u in FakeAuthManager.auth_data: - if u.id == user_id: - user = u + user = self.get_user(user_id) if user: user.access = access user.secret = secret -- cgit From 48a1423081355b49340aa1a4a37361654d9c0d87 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 18 Mar 2011 10:24:06 -0700 Subject: A few more single-letter variable names bite the dust --- nova/tests/api/openstack/test_auth.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_auth.py b/nova/tests/api/openstack/test_auth.py index 446c5c149..21596fb25 100644 --- a/nova/tests/api/openstack/test_auth.py +++ b/nova/tests/api/openstack/test_auth.py @@ -51,8 +51,8 @@ class Test(test.TestCase): def test_authorize_user(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) - f.add_user(u) + user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) + f.add_user(user) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'user1' @@ -66,9 +66,9 @@ class Test(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) - f.add_user(u) - f.create_project('user1_project', u) + user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) + f.add_user(user) + f.create_project('user1_project', user) req = webob.Request.blank('/v1.0/', {'HTTP_HOST': 'foo'}) req.headers['X-Auth-User'] = 'user1' @@ -124,8 +124,8 @@ class Test(test.TestCase): def test_bad_user_good_key(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) - f.add_user(u) + user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) + f.add_user(user) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'unknown_user' @@ -190,9 +190,9 @@ class TestLimiter(test.TestCase): def test_authorize_token(self): f = fakes.FakeAuthManager() - u = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) - f.add_user(u) - f.create_project('test', u) + user = nova.auth.manager.User('id1', 'user1', 'user1_key', None, None) + f.add_user(user) + f.create_project('test', user) req = webob.Request.blank('/v1.0/') req.headers['X-Auth-User'] = 'user1' -- cgit From 2f4c1802c7e482a447d348f049ff429b3d1a640c Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Fri, 18 Mar 2011 16:06:43 -0400 Subject: fix date formatting in images controller show --- nova/tests/api/openstack/fakes.py | 20 +++++++++----- nova/tests/api/openstack/test_images.py | 46 ++++++++++++++++----------------- 2 files changed, 37 insertions(+), 29 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 15f8a5b56..9573cf128 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +import copy import datetime import json import random @@ -151,22 +152,23 @@ def stub_out_glance(stubs, initial_fixtures=None): for f in self.fixtures] def fake_get_images_detailed(self): - return self.fixtures + return copy.deepcopy(self.fixtures) def fake_get_image_meta(self, image_id): - for f in self.fixtures: - if f['id'] == image_id: - return f + image = self._find_image(image_id) + if image: + return copy.deepcopy(image) raise glance_exc.NotFound def fake_add_image(self, image_meta, data=None): + image_meta = copy.deepcopy(image_meta) id = ''.join(random.choice(string.letters) for _ in range(20)) image_meta['id'] = id self.fixtures.append(image_meta) return image_meta def fake_update_image(self, image_id, image_meta, data=None): - f = self.fake_get_image_meta(image_id) + f = self._find_image(image_id) if not f: raise glance_exc.NotFound @@ -174,7 +176,7 @@ def stub_out_glance(stubs, initial_fixtures=None): return f def fake_delete_image(self, image_id): - f = self.fake_get_image_meta(image_id) + f = self._find_image(image_id) if not f: raise glance_exc.NotFound @@ -183,6 +185,12 @@ def stub_out_glance(stubs, initial_fixtures=None): ##def fake_delete_all(self): ## self.fixtures = [] + def _find_image(self, image_id): + for f in self.fixtures: + if f['id'] == image_id: + return f + return None + GlanceClient = glance_client.Client fake = FakeGlanceClient(initial_fixtures) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 47dd11e5b..b771966f1 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -21,7 +21,7 @@ and as a WSGI layer """ import json -import datetime +import datetime as dt import shutil import tempfile @@ -177,13 +177,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """Test of the OpenStack API /images application controller""" # Registered images at start of each test. - + now = dt.datetime.utcnow() IMAGE_FIXTURES = [ {'id': '23g2ogk23k4hhkk4k42l', 'imageId': '23g2ogk23k4hhkk4k42l', 'name': 'public image #1', - 'created_at': datetime.datetime.utcnow().isoformat(), - 'updated_at': datetime.datetime.utcnow().isoformat(), + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), 'deleted_at': None, 'deleted': False, 'is_public': True, @@ -192,8 +192,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): {'id': 'slkduhfas73kkaskgdas', 'imageId': 'slkduhfas73kkaskgdas', 'name': 'public image #2', - 'created_at': datetime.datetime.utcnow().isoformat(), - 'updated_at': datetime.datetime.utcnow().isoformat(), + 'created_at': now.isoformat(), + 'updated_at': now.isoformat(), 'deleted_at': None, 'deleted': False, 'is_public': True, @@ -235,20 +235,20 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) res_dict = json.loads(res.body) - def _is_equivalent_subset(x, y): - if set(x) <= set(y): - for k, v in x.iteritems(): - if x[k] != y[k]: - if x[k] == 'active' and y[k] == 'available': - continue - return False - return True - return False - - for image in res_dict['images']: - for image_fixture in self.IMAGE_FIXTURES: - if _is_equivalent_subset(image, image_fixture): - break - else: - self.assertEquals(1, 2, "image %s not in fixtures!" % - str(image)) + for image in self.IMAGE_FIXTURES: + expected = { + 'id': abs(hash(image['imageId'])), + 'name': image['name'], + 'status': 'active', + } + self.assertTrue(expected in res_dict['images']) + + def test_show_image(self): + expected = self.IMAGE_FIXTURES[0] + id = abs(hash(expected['id'])) + expected_time = self.now.strftime('%Y-%m-%dT%H:%M:%SZ') + req = webob.Request.blank('/v1.0/images/%s' % id) + res = req.get_response(fakes.wsgi_app()) + actual = json.loads(res.body)['image'] + self.assertEqual(expected_time, actual['created_at']) + self.assertEqual(expected_time, actual['updated_at']) -- cgit From a3fe673108602e27cca132209e87369fa8bf1323 Mon Sep 17 00:00:00 2001 From: Tushar Patil Date: Fri, 18 Mar 2011 19:46:04 -0700 Subject: Changed Copyright to NTT for newly added files for flatmanager ipv6 --- nova/tests/network/__init__.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py index e0d479f8c..97f96b6fa 100644 --- a/nova/tests/network/__init__.py +++ b/nova/tests/network/__init__.py @@ -1,3 +1,23 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. +""" +Utility methods +""" import os from nova import context -- cgit From 98b0fd564ca86a7b38bca149b28a837c8aa2d1e8 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Sun, 20 Mar 2011 20:06:22 +0100 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index bb33ec03d..efba2970f 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1174,5 +1174,3 @@ class TestServerInstanceCreation(test.TestCase): server = dom.childNodes[0] self.assertEquals(server.nodeName, 'server') self.assertTrue(server.getAttribute('adminPass').startswith('fake')) - - -- cgit From 8f0b60f598c28b2f558f3ecdaa2f9604926393e6 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 07:49:58 -0700 Subject: remove scheduler.api.API. naming changes. --- nova/tests/api/openstack/test_zones.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_zones.py b/nova/tests/api/openstack/test_zones.py index 12d39fd29..a3f191aaa 100644 --- a/nova/tests/api/openstack/test_zones.py +++ b/nova/tests/api/openstack/test_zones.py @@ -75,7 +75,7 @@ def zone_get_all_db(context): ] -def zone_caps(method, context, params): +def zone_capabilities(method, context, params): return dict() @@ -98,13 +98,13 @@ class ZonesTest(test.TestCase): self.stubs.Set(nova.db, 'zone_delete', zone_delete) self.old_zone_name = FLAGS.zone_name - self.old_zone_caps = FLAGS.zone_capabilities + self.old_zone_capabilities = FLAGS.zone_capabilities def tearDown(self): self.stubs.UnsetAll() FLAGS.allow_admin_api = self.allow_admin FLAGS.zone_name = self.old_zone_name - FLAGS.zone_capabilities = self.old_zone_caps + FLAGS.zone_capabilities = self.old_zone_capabilities super(ZonesTest, self).tearDown() def test_get_zone_list_scheduler(self): @@ -179,7 +179,7 @@ class ZonesTest(test.TestCase): def test_zone_info(self): FLAGS.zone_name = 'darksecret' FLAGS.zone_capabilities = ['cap1=a;b', 'cap2=c;d'] - self.stubs.Set(api, '_call_scheduler', zone_caps) + self.stubs.Set(api, '_call_scheduler', zone_capabilities) body = dict(zone=dict(username='zeb', password='sneaky')) req = webob.Request.blank('/v1.0/zones/info') -- cgit From 012c94e5304b9e00477409b92bf73f4316b19260 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 21 Mar 2011 13:56:55 -0400 Subject: Fix limit unit tests (reconciles w/ trunk changes). --- nova/tests/api/openstack/test_extensions.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 11ed61e0d..d1f8c659e 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -190,8 +190,6 @@ class ResponseExtensionTest(unittest.TestCase): self.stubs = stubout.StubOutForTesting() fakes.FakeAuthManager.reset_fake_data() fakes.FakeAuthDatabase.data = {} - fakes.stub_out_networking(self.stubs) - fakes.stub_out_rate_limiting(self.stubs) fakes.stub_out_auth(self.stubs) self.context = context.get_admin_context() -- cgit From fbd94f236adaa906fcc9c90de94e491e3d75653b Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Mon, 21 Mar 2011 13:59:26 -0400 Subject: Added copyright header. --- nova/tests/api/openstack/extensions/foxinsocks.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py index fa979c7b5..249dd81bf 100644 --- a/nova/tests/api/openstack/extensions/foxinsocks.py +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -1,3 +1,20 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + import json from nova import wsgi -- cgit From ffd2bc759af4f53019838bf20a4f016a566fbbd6 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Mon, 21 Mar 2011 13:21:26 -0500 Subject: Added XenAPI rescue unit tests --- nova/tests/test_xenapi.py | 12 ++++++++++++ nova/tests/xenapi/stubs.py | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 66a973a78..e54ffe712 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -186,6 +186,7 @@ class XenAPIVMTestCase(test.TestCase): stubs.stubout_stream_disk(self.stubs) stubs.stubout_is_vdi_pv(self.stubs) self.stubs.Set(VMOps, 'reset_network', reset_network) + stubs.stub_out_vm_methods(self.stubs) glance_stubs.stubout_glance_client(self.stubs, glance_stubs.FakeGlance) self.conn = xenapi_conn.get_connection(False) @@ -369,6 +370,17 @@ class XenAPIVMTestCase(test.TestCase): self.assertEquals(vif_rec['qos_algorithm_params']['kbps'], str(4 * 1024)) + def test_rescue(self): + instance = self._create_instance() + conn = xenapi_conn.get_connection(False) + conn.rescue(instance, None) + + def test_unrescue(self): + instance = self._create_instance() + conn = xenapi_conn.get_connection(False) + # Ensure that it will not unrescue a non-rescued instance. + self.assertRaises(Exception, conn.unrescue, instance, None) + def tearDown(self): super(XenAPIVMTestCase, self).tearDown() self.manager.delete_project(self.project) diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index 70d46a1fb..a0370a2ec 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -185,6 +185,25 @@ class FakeSessionForVMTests(fake.SessionBase): pass +def stub_out_vm_methods(stubs): + def fake_shutdown(self, inst, vm, method="clean"): + pass + + def fake_acquire_bootlock(self, vm): + pass + + def fake_release_bootlock(self, vm): + pass + + def fake_spawn_rescue(self, inst): + pass + + stubs.Set(vmops.VMOps, "_shutdown", fake_shutdown) + stubs.Set(vmops.VMOps, "_acquire_bootlock", fake_acquire_bootlock) + stubs.Set(vmops.VMOps, "_release_bootlock", fake_release_bootlock) + stubs.Set(vmops.VMOps, "spawn_rescue", fake_spawn_rescue) + + class FakeSessionForVolumeTests(fake.SessionBase): """ Stubs out a XenAPISession for Volume tests """ def __init__(self, uri): -- cgit From 85f50cf496e2c193ddc715f3019b4a4769ab5bd9 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 21 Mar 2011 15:14:24 -0400 Subject: pep8; various fixes --- nova/tests/api/openstack/test_servers.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 6e78db9da..a9e76b244 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -311,10 +311,19 @@ class ServersTest(test.TestCase): imageRef = 'http://localhost/v1.1/images/2' flavorRef = 'http://localhost/v1.1/flavors/3' - body = dict(server=dict( - name='server_test', imageRef=imageRef, flavorRef=flavorRef, - metadata={'hello': 'world', 'open': 'stack'}, - personality={})) + body = { + 'server': { + 'name': 'server_test', + 'imageRef': imageRef, + 'flavorRef': flavorRef, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': {}, + }, + } + req = webob.Request.blank('/v1.1/servers') req.method = 'POST' req.body = json.dumps(body) -- cgit From 27ae9700739bd6a1e6f9db90e407f450ff3e770b Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 21 Mar 2011 16:35:38 -0400 Subject: added licenses --- nova/tests/image/__init__.py | 17 +++++++++++++++++ nova/tests/image/test_glance.py | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py index e69de29bb..fae25bca7 100644 --- a/nova/tests/image/__init__.py +++ b/nova/tests/image/__init__.py @@ -0,0 +1,17 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 6e94aa909..fcd686c84 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -1,3 +1,22 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. + + import datetime as dt import unittest -- cgit From 414c615a3ac2e61f312f8383f764114e7d782de1 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 21 Mar 2011 16:40:26 -0400 Subject: fix licenses --- nova/tests/image/__init__.py | 3 +-- nova/tests/image/test_glance.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py index fae25bca7..b94e2e54e 100644 --- a/nova/tests/image/__init__.py +++ b/nova/tests/image/__init__.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 Openstack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index fcd686c84..d49b3dfdb 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 Openstack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may -- cgit From 39783f386a473ed28c786bb72a29e8403503c40c Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 21 Mar 2011 17:09:53 -0400 Subject: make bcwaldon happy --- nova/tests/api/openstack/test_images.py | 4 ++-- nova/tests/image/test_glance.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index b771966f1..a866c764d 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -21,7 +21,7 @@ and as a WSGI layer """ import json -import datetime as dt +import datetime import shutil import tempfile @@ -177,7 +177,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """Test of the OpenStack API /images application controller""" # Registered images at start of each test. - now = dt.datetime.utcnow() + now = datetime.datetime.utcnow() IMAGE_FIXTURES = [ {'id': '23g2ogk23k4hhkk4k42l', 'imageId': '23g2ogk23k4hhkk4k42l', diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index d49b3dfdb..30021dbc1 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -58,12 +58,12 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.service = glance.GlanceImageService(self.client) def test_show_passes_through_to_client(self): - self.client.images = {'xyz': "image"} - self.assertEqual(self.service.show({}, 'xyz'), "image") + self.client.images = {'xyz': {'foo': 'bar'}} + self.assertEqual(self.service.show({}, 'xyz'), {'foo': 'bar'}) def test_detail_passes_through_to_client(self): - self.client.images = {1: "an image"} - self.assertEqual(list(self.service.detail({})), ["an image"]) + self.client.images = {1: {'foo': 'bar'}} + self.assertEqual(list(self.service.detail({})), [{'foo': 'bar'}]) def test_show_makes_create_datetimes(self): create_time = dt.datetime.utcnow() -- cgit From e1b9db2ac1af8f38084f9794a430e0292f110ed6 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 21 Mar 2011 17:23:36 -0400 Subject: get rid of another datetime alias --- nova/tests/image/test_glance.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index 30021dbc1..f1f8504f3 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -16,7 +16,7 @@ # under the License. -import datetime as dt +import datetime import unittest from nova.image import glance @@ -66,7 +66,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(list(self.service.detail({})), [{'foo': 'bar'}]) def test_show_makes_create_datetimes(self): - create_time = dt.datetime.utcnow() + create_time = datetime.datetime.utcnow() self.client.images = {'xyz': { 'id': "id", 'name': "my awesome image", @@ -76,7 +76,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(actual['created_at'], create_time) def test_show_makes_update_datetimes(self): - update_time = dt.datetime.utcnow() + update_time = datetime.datetime.utcnow() self.client.images = {'abc': { 'id': "id", 'name': "my okay image", @@ -86,7 +86,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(actual['updated_at'], update_time) def test_show_makes_delete_datetimes(self): - delete_time = dt.datetime.utcnow() + delete_time = datetime.datetime.utcnow() self.client.images = {'123': { 'id': "123", 'name': "my lame image", @@ -105,7 +105,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(actual['deleted_at'], None) def test_detail_handles_timestamps(self): - now = dt.datetime.utcnow() + now = datetime.datetime.utcnow() image1 = { 'id': 1, 'name': 'image 1', @@ -126,7 +126,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(i2['deleted_at'], now) def test_get_handles_timestamps(self): - now = dt.datetime.utcnow() + now = datetime.datetime.utcnow() self.client.images = {'abcd': { 'id': 'abcd', 'name': 'nifty image', @@ -144,7 +144,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(actual['deleted_at'], None) def test_create_handles_timestamps(self): - now = dt.datetime.utcnow() + now = datetime.datetime.utcnow() self.client.add_response = { 'id': 'abcd', 'name': 'blah', @@ -166,7 +166,7 @@ class TestGlanceImageServiceDatetimes(unittest.TestCase): self.assertEqual(actual['deleted_at'], None) def test_update_handles_timestamps(self): - now = dt.datetime.utcnow() + now = datetime.datetime.utcnow() self.client.update_response = { 'id': 'abcd', 'name': 'blah', -- cgit From 08d06d1219a00b90ae211fb44fc7e33ba71c7a76 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 18:16:35 -0700 Subject: better comments. First redirect test --- nova/tests/test_scheduler.py | 70 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 244e43bd9..50e2429ba 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -21,6 +21,8 @@ Tests For Scheduler import datetime import mox +import stubout +import webob from mox import IgnoreArg from nova import context @@ -32,6 +34,7 @@ from nova import test from nova import rpc from nova import utils from nova.auth import manager as auth_manager +from nova.scheduler import api from nova.scheduler import manager from nova.scheduler import driver from nova.compute import power_state @@ -937,3 +940,70 @@ class SimpleDriverTestCase(test.TestCase): db.instance_destroy(self.context, instance_id) db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref2['id']) + + +class FakeZone(object): + def __init__(self, api_url, username, password): + self.api_url = api_url + self.username = username + self.password = password + +def zone_get_all(context): + return [ + FakeZone('http://example.com', 'bob', 'xxx'), + ] + + +def go_boom(self, context, instance): + raise exception.InstanceNotFound("boom message", instance) + + +def fake_openstack_init(self, username, password, api): + servers=[] + + +def fake_auth(self): + pass + +class FakeServer: + def foo(self): + pass + +class FakeManager: + def get(self, id): + return FakeServer() + +class FakeOpenStack: + + def __init__(self, username, api, auth): + self.servers = FakeManager() + + def authenticate(self): + pass + + +class ZoneRedirectTest(test.TestCase): + def setUp(self): + super(ZoneRedirectTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + + self.stubs.Set(api.novaclient, 'OpenStack', FakeOpenStack) + self.stubs.Set(db, 'zone_get_all', zone_get_all) + + self.enable_zone_routing = FLAGS.enable_zone_routing + FLAGS.enable_zone_routing = True + + def tearDown(self): + self.stubs.UnsetAll() + FLAGS.enable_zone_routing = self.enable_zone_routing + super(ZoneRedirectTest, self).tearDown() + + def test_trap_found_locally(self): + decorator = api.reroute_compute("foo") + try: + wrapper = decorator(go_boom) + result = wrapper(None, None, 1) # self, context, id + except api.RedirectResult, e: + pass + + -- cgit From 380731ce71e8909615da6138bb7d5e7226e375ac Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 18:56:59 -0700 Subject: better comments. First redirect test --- nova/tests/test_scheduler.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 50e2429ba..6d55cad04 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -958,23 +958,23 @@ def go_boom(self, context, instance): raise exception.InstanceNotFound("boom message", instance) -def fake_openstack_init(self, username, password, api): - servers=[] +class FakeServer(object): + def __init__(self): + self.name = 'myserver' + self.kvm = 'kvm' + self.manager = 100 + self._hidden = True - -def fake_auth(self): - pass - -class FakeServer: def foo(self): - pass + return None + -class FakeManager: +class FakeManager(object): def get(self, id): return FakeServer() -class FakeOpenStack: +class FakeOpenStack: def __init__(self, username, api, auth): self.servers = FakeManager() @@ -987,7 +987,6 @@ class ZoneRedirectTest(test.TestCase): super(ZoneRedirectTest, self).setUp() self.stubs = stubout.StubOutForTesting() - self.stubs.Set(api.novaclient, 'OpenStack', FakeOpenStack) self.stubs.Set(db, 'zone_get_all', zone_get_all) self.enable_zone_routing = FLAGS.enable_zone_routing @@ -999,11 +998,12 @@ class ZoneRedirectTest(test.TestCase): super(ZoneRedirectTest, self).tearDown() def test_trap_found_locally(self): + self.stubs.Set(api.novaclient, 'OpenStack', FakeOpenStack) decorator = api.reroute_compute("foo") try: wrapper = decorator(go_boom) result = wrapper(None, None, 1) # self, context, id except api.RedirectResult, e: - pass + self.assertTrue(e.results, {}) -- cgit From 8303d0f280a7bfbc5c5fb128465549b03badc1f1 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 21:41:41 -0700 Subject: routing test coverage --- nova/tests/test_scheduler.py | 121 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 98 insertions(+), 23 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 6d55cad04..0aebd0380 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -21,6 +21,7 @@ Tests For Scheduler import datetime import mox +import novaclient.exceptions import stubout import webob @@ -954,34 +955,33 @@ def zone_get_all(context): ] -def go_boom(self, context, instance): - raise exception.InstanceNotFound("boom message", instance) +class FakeRerouteCompute(api.reroute_compute): + def _call_child_zones(self, zones, function): + return [ ] + + def get_collection_context_and_id(self, args, kwargs): + return ("servers", None, 1) + def unmarshall_result(self, zone_responses): + return dict(magic="found me") -class FakeServer(object): - def __init__(self): - self.name = 'myserver' - self.kvm = 'kvm' - self.manager = 100 - self._hidden = True - def foo(self): - return None +def go_boom(self, context, instance): + raise exception.InstanceNotFound("boom message", instance) -class FakeManager(object): - def get(self, id): - return FakeServer() +def found_instance(self, context, instance): + return dict(name='myserver') -class FakeOpenStack: - def __init__(self, username, api, auth): - self.servers = FakeManager() +class FakeResource(object): + def __init__(self, attribute_dict): + for k, v in attribute_dict.iteritems(): + setattr(self, k, v) - def authenticate(self): + def pause(self): pass - class ZoneRedirectTest(test.TestCase): def setUp(self): super(ZoneRedirectTest, self).setUp() @@ -998,12 +998,87 @@ class ZoneRedirectTest(test.TestCase): super(ZoneRedirectTest, self).tearDown() def test_trap_found_locally(self): - self.stubs.Set(api.novaclient, 'OpenStack', FakeOpenStack) - decorator = api.reroute_compute("foo") + decorator = FakeRerouteCompute("foo") try: - wrapper = decorator(go_boom) - result = wrapper(None, None, 1) # self, context, id + result = decorator(found_instance)(None, None, 1) except api.RedirectResult, e: - self.assertTrue(e.results, {}) + self.fail(_("Successful database hit should succeed")) + def test_trap_not_found_locally(self): + decorator = FakeRerouteCompute("foo") + try: + result = decorator(go_boom)(None, None, 1) + except api.RedirectResult, e: + self.assertEquals(e.results['magic'], 'found me') + def test_get_collection_context_and_id(self): + decorator = api.reroute_compute("foo") + self.assertEquals(decorator.get_collection_context_and_id( + (None, 10, 20), {}), ("servers", 10, 20)) + self.assertEquals(decorator.get_collection_context_and_id( + (None, 11,), dict(instance_id=21)), ("servers", 11, 21)) + self.assertEquals(decorator.get_collection_context_and_id( + (None,), dict(context=12, instance_id=22)), ("servers", 12, 22)) + + def test_unmarshal_single_server(self): + decorator = api.reroute_compute("foo") + self.assertEquals(decorator.unmarshall_result([]), {}) + self.assertEquals(decorator.unmarshall_result( + [FakeResource(dict(a=1, b=2)),]), + dict(server=dict(a=1, b=2))) + self.assertEquals(decorator.unmarshall_result( + [FakeResource(dict(a=1, _b=2)),]), + dict(server=dict(a=1,))) + self.assertEquals(decorator.unmarshall_result( + [FakeResource(dict(a=1, manager=2)),]), + dict(server=dict(a=1,))) + self.assertEquals(decorator.unmarshall_result( + [FakeResource(dict(_a=1, manager=2)),]), + dict(server={})) + +class FakeServerCollection(object): + def get(self, instance_id): + return FakeResource(dict(a=10, b=20)) + + def find(self, name): + return FakeResource(dict(a=11, b=22)) + +class FakeEmptyServerCollection(object): + def get(self, f): + raise novaclient.NotFound(1) + + def find(self, name): + raise novaclient.NotFound(2) + +class FakeNovaClient(object): + def __init__(self, collection): + self.servers = collection + +class DynamicNovaClientTest(test.TestCase): + def test_issue_novaclient_command_found(self): + zone = FakeZone('http://example.com', 'bob', 'xxx') + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeServerCollection()), + zone, "servers", "get", 100).a, 10) + + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeServerCollection()), + zone, "servers", "find", "name").b, 22) + + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeServerCollection()), + zone, "servers", "pause", 100), None) + + def test_issue_novaclient_command_not_found(self): + zone = FakeZone('http://example.com', 'bob', 'xxx') + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeEmptyServerCollection()), + zone, "servers", "get", 100), None) + + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeEmptyServerCollection()), + zone, "servers", "find", "name"), None) + + self.assertEquals(api._issue_novaclient_command( + FakeNovaClient(FakeEmptyServerCollection()), + zone, "servers", "any", "name"), None) -- cgit From e74482f30c602530313faf15e0d429acefee7bde Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 21:47:58 -0700 Subject: routing test coverage --- nova/tests/test_scheduler.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 0aebd0380..8434f5a43 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -1008,9 +1008,18 @@ class ZoneRedirectTest(test.TestCase): decorator = FakeRerouteCompute("foo") try: result = decorator(go_boom)(None, None, 1) + self.assertFail(_("Should have rerouted.")) except api.RedirectResult, e: self.assertEquals(e.results['magic'], 'found me') + def test_routing_flags(self): + FLAGS.enable_zone_routing = False + decorator = FakeRerouteCompute("foo") + try: + result = decorator(go_boom)(None, None, 1) + except exception.InstanceNotFound, e: + self.assertEquals(e.message, 'boom message') + def test_get_collection_context_and_id(self): decorator = api.reroute_compute("foo") self.assertEquals(decorator.get_collection_context_and_id( -- cgit From 65482f5d9513c3dda64171d0460001e299be9673 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 21 Mar 2011 21:51:14 -0700 Subject: added zone routing flag test --- nova/tests/test_scheduler.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 8434f5a43..277ffe367 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -1017,6 +1017,7 @@ class ZoneRedirectTest(test.TestCase): decorator = FakeRerouteCompute("foo") try: result = decorator(go_boom)(None, None, 1) + self.assertFail(_("Should have thrown exception.")) except exception.InstanceNotFound, e: self.assertEquals(e.message, 'boom message') -- cgit From d1860ce5d26fbbadb2310e8225e924879cde9a6c Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 10:35:43 +0100 Subject: Make synchronized support both external (file based) locks as well as internal (semaphore based) locks. Attempt to make it native thread safe at the expense of never cleaning up semaphores. --- nova/tests/test_misc.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 1fbaf304f..961499a60 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -16,8 +16,12 @@ import errno import os +import random import select +from eventlet import greenpool +from eventlet import greenthread + from nova import test from nova.utils import parse_mailmap, str_dict_replace, synchronized @@ -72,11 +76,37 @@ class LockTestCase(test.TestCase): self.assertEquals(foo.__name__, 'foo', "Wrapped function's name " "got mangled") - def test_synchronized(self): + def test_synchronized_internally(self): + """We can lock across multiple green threads""" + seen_threads = list() + @synchronized('testlock', external=False) + def f(id): + for x in range(10): + seen_threads.append(id) + greenthread.sleep(0) + + threads = [] + pool = greenpool.GreenPool(10) + for i in range(10): + threads.append(pool.spawn(f, i)) + + for thread in threads: + thread.wait() + + self.assertEquals(len(seen_threads), 100) + # Looking at the seen threads, split it into chunks of 10, and verify + # that the last 9 match the first in each chunk. + for i in range(10): + for j in range(9): + self.assertEquals(seen_threads[i*10], seen_threads[i*10+1+j]) + + + def test_synchronized_externally(self): + """We can lock across multiple processes""" rpipe1, wpipe1 = os.pipe() rpipe2, wpipe2 = os.pipe() - @synchronized('testlock') + @synchronized('testlock', external=True) def f(rpipe, wpipe): try: os.write(wpipe, "foo") -- cgit From 60a3aa86db1d0e1ea2f680c9587881e45fa99336 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 14:14:47 +0100 Subject: Make synchronized decorator not leak semaphores, at the expense of not being truly thread safe (but safe enough for Eventlet style green threads). --- nova/tests/test_misc.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 961499a60..c0c72bb12 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -16,7 +16,6 @@ import errno import os -import random import select from eventlet import greenpool -- cgit From 62f9cc7cee30332143bf4e6e54fd21335db3c8da Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 14:36:32 +0100 Subject: Convert _cache_image to use utils.synchronized decorator. Disable its test case, since I think it is no longer needed with the tests for synchronized. --- nova/tests/test_virt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b214f5ce7..b9cd30a79 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -62,7 +62,7 @@ class CacheConcurrencyTestCase(test.TestCase): self.stubs.Set(os.path, 'exists', fake_exists) self.stubs.Set(utils, 'execute', fake_execute) - def test_same_fname_concurrency(self): + def notest_same_fname_concurrency(self): """Ensures that the same fname cache runs at a sequentially""" conn = libvirt_conn.LibvirtConnection wait1 = eventlet.event.Event() -- cgit From 3ae9a489667ed6f4b03a19d5e14bec8e1d4eb20d Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Tue, 22 Mar 2011 09:52:59 -0400 Subject: Add call to unset all stubs. --- nova/tests/api/openstack/test_server_metadata.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index b280ae94c..ed60d4b36 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -62,7 +62,10 @@ class ServerMetaDataTest(unittest.TestCase): fakes.FakeAuthDatabase.data = {} fakes.stub_out_auth(self.stubs) fakes.stub_out_key_pair_funcs(self.stubs) - #self.allow_admin = FLAGS.allow_admin_api + + def tearDown(self): + self.stubs.UnsetAll() + super(ServerMetaDataTest, self).tearDown() def test_index(self): self.stubs.Set(nova.db.api, 'get_instance_metadata', -- cgit From 7aa027b2005ff24f7308e1ec23eddb44bf352628 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Tue, 22 Mar 2011 10:01:18 -0400 Subject: Add unit test and code updates to ensure that a PUT requests to create/update server metadata only contain a single key. --- nova/tests/api/openstack/test_server_metadata.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index ed60d4b36..97cb57ebd 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -141,6 +141,17 @@ class ServerMetaDataTest(unittest.TestCase): res_dict = json.loads(res.body) self.assertEqual('value1', res_dict['key1']) + def test_update_item_too_many_keys(self): + self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + return_create_instance_metadata) + req = webob.Request.blank('/v1.1/servers/1/meta/key1') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "value1", "key2": "value2"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) + def test_update_item_body_uri_mismatch(self): self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', return_create_instance_metadata) -- cgit From b82d548d0357f73ff446f5bf24e27fbefd98e4b3 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 22 Mar 2011 10:58:31 -0400 Subject: adding view builder tests --- nova/tests/api/openstack/test_versions.py | 36 +++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index 330d74dde..f730fc8e4 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -21,6 +21,7 @@ import webob from nova import context from nova import test from nova.tests.api.openstack import fakes +from nova.api.openstack import views class VersionsTest(test.TestCase): @@ -59,3 +60,38 @@ class VersionsTest(test.TestCase): }, ] self.assertEqual(versions, expected) + + def test_view_builder(self): + base_url = "http://example.org/" + + version_data = { + "id": "3.2.1", + "status": "CURRENT", + } + + expected = { + "id": "3.2.1", + "status": "CURRENT", + "links": [ + { + "rel": "self", + "href": "http://example.org/3.2.1", + }, + ], + } + + builder = views.versions.ViewBuilder(base_url) + output = builder.build(version_data) + + self.assertEqual(output, expected) + + def test_generate_href(self): + base_url = "http://example.org/app/" + version_number = "v1.4.6" + + expected = "http://example.org/app/v1.4.6" + + builder = views.versions.ViewBuilder(base_url) + actual = builder.generate_href(version_number) + + self.assertEqual(actual, expected) -- cgit From d2494199df440809bbfbc55868b0dd57053868ed Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:23:47 +0100 Subject: Remove checks in _cache_image tests that were too implementation specific. --- nova/tests/test_virt.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b9cd30a79..6bafac39f 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -62,7 +62,7 @@ class CacheConcurrencyTestCase(test.TestCase): self.stubs.Set(os.path, 'exists', fake_exists) self.stubs.Set(utils, 'execute', fake_execute) - def notest_same_fname_concurrency(self): + def test_same_fname_concurrency(self): """Ensures that the same fname cache runs at a sequentially""" conn = libvirt_conn.LibvirtConnection wait1 = eventlet.event.Event() @@ -77,13 +77,11 @@ class CacheConcurrencyTestCase(test.TestCase): eventlet.sleep(0) try: self.assertFalse(done2.ready()) - self.assertTrue('fname' in conn._image_sems) finally: wait1.send() done1.wait() eventlet.sleep(0) self.assertTrue(done2.ready()) - self.assertFalse('fname' in conn._image_sems) def test_different_fname_concurrency(self): """Ensures that two different fname caches are concurrent""" -- cgit From 9aac55b650e9f39c5771d4683e51af5eac6204bb Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:24:03 +0100 Subject: Add a test for leaked semaphores. --- nova/tests/test_misc.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index c0c72bb12..8fc5d67c0 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -22,7 +22,8 @@ from eventlet import greenpool from eventlet import greenthread from nova import test -from nova.utils import parse_mailmap, str_dict_replace, synchronized +from nova import utils +from nova.utils import parse_mailmap, str_dict_replace class ProjectTestCase(test.TestCase): @@ -66,7 +67,7 @@ class ProjectTestCase(test.TestCase): class LockTestCase(test.TestCase): def test_synchronized_wrapped_function_metadata(self): - @synchronized('whatever') + @utils.synchronized('whatever') def foo(): """Bar""" pass @@ -77,8 +78,9 @@ class LockTestCase(test.TestCase): def test_synchronized_internally(self): """We can lock across multiple green threads""" + saved_sem_num = len(utils._semaphores) seen_threads = list() - @synchronized('testlock', external=False) + @utils.synchronized('testlock2', external=False) def f(id): for x in range(10): seen_threads.append(id) @@ -99,13 +101,15 @@ class LockTestCase(test.TestCase): for j in range(9): self.assertEquals(seen_threads[i*10], seen_threads[i*10+1+j]) + self.assertEqual(saved_sem_num, len(utils._semaphores), + "Semaphore leak detected") def test_synchronized_externally(self): """We can lock across multiple processes""" rpipe1, wpipe1 = os.pipe() rpipe2, wpipe2 = os.pipe() - @synchronized('testlock', external=True) + @utils.synchronized('testlock1', external=True) def f(rpipe, wpipe): try: os.write(wpipe, "foo") -- cgit From b2bdeb82024b1a015ccb2ad14606d6e9ccf80aa8 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:29:37 +0100 Subject: pep8 --- nova/tests/test_misc.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 8fc5d67c0..4e17e1ce0 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -80,6 +80,7 @@ class LockTestCase(test.TestCase): """We can lock across multiple green threads""" saved_sem_num = len(utils._semaphores) seen_threads = list() + @utils.synchronized('testlock2', external=False) def f(id): for x in range(10): @@ -99,7 +100,8 @@ class LockTestCase(test.TestCase): # that the last 9 match the first in each chunk. for i in range(10): for j in range(9): - self.assertEquals(seen_threads[i*10], seen_threads[i*10+1+j]) + self.assertEquals(seen_threads[i * 10], + seen_threads[i * 10 + 1 + j]) self.assertEqual(saved_sem_num, len(utils._semaphores), "Semaphore leak detected") -- cgit From 3c7de6db490a8482f6d1fb5fefc750050cb1e269 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:42:37 +0100 Subject: Pass a fake timing source to test_ensure_filtering_rules_for_instance_timeout, shaving off 30 seconds of test run time. --- nova/tests/test_virt.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b214f5ce7..a754f451a 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -429,6 +429,15 @@ class LibvirtConnTestCase(test.TestCase): def fake_raise(self): raise libvirt.libvirtError('ERR') + class FakeTime(object): + def __init__(self): + self.counter = 0 + + def sleep(self, t): + self.counter += t + + fake_timer = FakeTime() + self.create_fake_libvirt_mock(nwfilterLookupByName=fake_raise) instance_ref = db.instance_create(self.context, self.test_instance) @@ -438,11 +447,15 @@ class LibvirtConnTestCase(test.TestCase): conn = libvirt_conn.LibvirtConnection(False) conn.firewall_driver.setattr('setup_basic_filtering', fake_none) conn.firewall_driver.setattr('prepare_instance_filter', fake_none) - conn.ensure_filtering_rules_for_instance(instance_ref) + conn.ensure_filtering_rules_for_instance(instance_ref, + time=fake_timer) except exception.Error, e: c1 = (0 <= e.message.find('Timeout migrating for')) self.assertTrue(c1) + self.assertEqual(29, fake_timer.counter, "Didn't wait the expected " + "amount of time") + db.instance_destroy(self.context, instance_ref['id']) def test_live_migration_raises_exception(self): -- cgit From 7ae8f5563c42d7c5dc67047dd9c42e982281d80b Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 22 Mar 2011 16:53:43 +0100 Subject: Apparantly a more common problem than first thought. --- nova/tests/test_compute.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 3651f4cef..0209dd9ca 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -44,6 +44,14 @@ flags.DECLARE('stub_network', 'nova.compute.manager') flags.DECLARE('live_migration_retry_count', 'nova.compute.manager') +class FakeTime(object): + def __init__(self): + self.counter = 0 + + def sleep(self, t): + self.counter += t + + class ComputeTestCase(test.TestCase): """Test case for compute""" def setUp(self): @@ -342,7 +350,7 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() self.assertRaises(exception.NotFound, self.compute.pre_live_migration, - c, instance_ref['id']) + c, instance_ref['id'], time=FakeTime()) def test_pre_live_migration_instance_has_volume(self): """Confirm setup_compute_volume is called when volume is mounted.""" @@ -395,7 +403,7 @@ class ComputeTestCase(test.TestCase): self.compute.driver = drivermock self.mox.ReplayAll() - ret = self.compute.pre_live_migration(c, i_ref['id']) + ret = self.compute.pre_live_migration(c, i_ref['id'], time=FakeTime()) self.assertEqual(ret, None) def test_pre_live_migration_setup_compute_node_fail(self): @@ -428,7 +436,7 @@ class ComputeTestCase(test.TestCase): self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, self.compute.pre_live_migration, - c, i_ref['id']) + c, i_ref['id'], time=FakeTime()) def test_live_migration_works_correctly_with_volume(self): """Confirm check_for_export to confirm volume health check.""" -- cgit From e648698bd171357228881a10d76e7853938e8feb Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 22 Mar 2011 17:00:36 +0000 Subject: Fix --- nova/tests/test_localization.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_localization.py b/nova/tests/test_localization.py index 393d71038..132a308fd 100644 --- a/nova/tests/test_localization.py +++ b/nova/tests/test_localization.py @@ -21,9 +21,9 @@ import sys import unittest import nova +from nova import test - -class LocalizationTestCase(unittest.TestCase): +class LocalizationTestCase(test.TestCase): def test_multiple_positional_format_placeholders(self): pat = re.compile("\W_\(") single_pat = re.compile("\W%\W") -- cgit From 8792383dfbd630388e6a51a76910e73203a3793f Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Tue, 22 Mar 2011 18:24:00 +0000 Subject: Tweak --- nova/tests/test_localization.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_localization.py b/nova/tests/test_localization.py index 132a308fd..a25809a79 100644 --- a/nova/tests/test_localization.py +++ b/nova/tests/test_localization.py @@ -23,6 +23,7 @@ import unittest import nova from nova import test + class LocalizationTestCase(test.TestCase): def test_multiple_positional_format_placeholders(self): pat = re.compile("\W_\(") -- cgit From aa4183064e15033ce2cc35773e86809b5f8224fd Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 22 Mar 2011 14:34:46 -0400 Subject: one more copyright fix --- nova/tests/api/openstack/test_versions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index f730fc8e4..ebb59a9a6 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010-2011 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may -- cgit From 789fcb46915dce5fa533357ac462040ec6aa8968 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 22 Mar 2011 20:26:45 +0000 Subject: Adding BASE_IMAGE_ATTRS to ImageService --- nova/tests/api/openstack/test_images.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 4604b331e..03f22842b 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -185,11 +185,10 @@ class GlanceImageServiceTest(test.TestCase, super(GlanceImageServiceTest, self).tearDown() def test_create_with_instance_id(self): - """ - Ensure that a instance_id is stored in Glance as a image property - string and then converted back to an instance_id integer attribute. - """ - fixture = {'instance_id': 42, 'name': 'test image'} + """Ensure instance_id is persisted as an image-property""" + fixture = {'name': 'test image', + 'properties': {'instance_id': '42'}} + image_id = self.service.create(self.context, fixture)['id'] expected = {'id': image_id, @@ -197,9 +196,6 @@ class GlanceImageServiceTest(test.TestCase, 'properties': {'instance_id': '42'}} self.assertDictMatch(self.sent_to_glance['metadata'], expected) - # The ImageService shouldn't leak the fact that the instance_id - # happens to be stored as a property in Glance - expected = {'id': image_id, 'instance_id': 42, 'name': 'test image'} image_meta = self.service.show(self.context, image_id) self.assertDictMatch(image_meta, expected) -- cgit From 209da18033a49062bbcfaf7739db5959be87b142 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 22 Mar 2011 20:36:49 -0700 Subject: pep8 and fixed up zone-list --- nova/tests/test_scheduler.py | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py index 277ffe367..6df74dd61 100644 --- a/nova/tests/test_scheduler.py +++ b/nova/tests/test_scheduler.py @@ -949,6 +949,7 @@ class FakeZone(object): self.username = username self.password = password + def zone_get_all(context): return [ FakeZone('http://example.com', 'bob', 'xxx'), @@ -957,8 +958,8 @@ def zone_get_all(context): class FakeRerouteCompute(api.reroute_compute): def _call_child_zones(self, zones, function): - return [ ] - + return [] + def get_collection_context_and_id(self, args, kwargs): return ("servers", None, 1) @@ -982,6 +983,7 @@ class FakeResource(object): def pause(self): pass + class ZoneRedirectTest(test.TestCase): def setUp(self): super(ZoneRedirectTest, self).setUp() @@ -1024,27 +1026,28 @@ class ZoneRedirectTest(test.TestCase): def test_get_collection_context_and_id(self): decorator = api.reroute_compute("foo") self.assertEquals(decorator.get_collection_context_and_id( - (None, 10, 20), {}), ("servers", 10, 20)) + (None, 10, 20), {}), ("servers", 10, 20)) self.assertEquals(decorator.get_collection_context_and_id( - (None, 11,), dict(instance_id=21)), ("servers", 11, 21)) + (None, 11,), dict(instance_id=21)), ("servers", 11, 21)) self.assertEquals(decorator.get_collection_context_and_id( (None,), dict(context=12, instance_id=22)), ("servers", 12, 22)) def test_unmarshal_single_server(self): decorator = api.reroute_compute("foo") - self.assertEquals(decorator.unmarshall_result([]), {}) + self.assertEquals(decorator.unmarshall_result([]), {}) self.assertEquals(decorator.unmarshall_result( - [FakeResource(dict(a=1, b=2)),]), - dict(server=dict(a=1, b=2))) + [FakeResource(dict(a=1, b=2)), ]), + dict(server=dict(a=1, b=2))) self.assertEquals(decorator.unmarshall_result( - [FakeResource(dict(a=1, _b=2)),]), - dict(server=dict(a=1,))) + [FakeResource(dict(a=1, _b=2)), ]), + dict(server=dict(a=1,))) self.assertEquals(decorator.unmarshall_result( - [FakeResource(dict(a=1, manager=2)),]), - dict(server=dict(a=1,))) + [FakeResource(dict(a=1, manager=2)), ]), + dict(server=dict(a=1,))) self.assertEquals(decorator.unmarshall_result( - [FakeResource(dict(_a=1, manager=2)),]), - dict(server={})) + [FakeResource(dict(_a=1, manager=2)), ]), + dict(server={})) + class FakeServerCollection(object): def get(self, instance_id): @@ -1053,6 +1056,7 @@ class FakeServerCollection(object): def find(self, name): return FakeResource(dict(a=11, b=22)) + class FakeEmptyServerCollection(object): def get(self, f): raise novaclient.NotFound(1) @@ -1060,10 +1064,12 @@ class FakeEmptyServerCollection(object): def find(self, name): raise novaclient.NotFound(2) + class FakeNovaClient(object): def __init__(self, collection): self.servers = collection + class DynamicNovaClientTest(test.TestCase): def test_issue_novaclient_command_found(self): zone = FakeZone('http://example.com', 'bob', 'xxx') @@ -1078,17 +1084,17 @@ class DynamicNovaClientTest(test.TestCase): self.assertEquals(api._issue_novaclient_command( FakeNovaClient(FakeServerCollection()), zone, "servers", "pause", 100), None) - + def test_issue_novaclient_command_not_found(self): zone = FakeZone('http://example.com', 'bob', 'xxx') self.assertEquals(api._issue_novaclient_command( FakeNovaClient(FakeEmptyServerCollection()), - zone, "servers", "get", 100), None) + zone, "servers", "get", 100), None) self.assertEquals(api._issue_novaclient_command( FakeNovaClient(FakeEmptyServerCollection()), - zone, "servers", "find", "name"), None) + zone, "servers", "find", "name"), None) self.assertEquals(api._issue_novaclient_command( FakeNovaClient(FakeEmptyServerCollection()), - zone, "servers", "any", "name"), None) + zone, "servers", "any", "name"), None) -- cgit From a7c9ad393f72b49515a445504a5bc87f8a26932c Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 05:50:53 +0000 Subject: Filtering images by user_id now --- nova/tests/api/openstack/test_images.py | 91 ++++++++++++++++----------------- 1 file changed, 43 insertions(+), 48 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 57a9819e8..797bbef8f 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -44,18 +44,10 @@ FLAGS = flags.FLAGS class BaseImageServiceTests(object): - """Tasks to test for all image services""" def test_create(self): - - fixture = {'name': 'test image', - 'updated': None, - 'created': None, - 'status': None, - 'instance_id': None, - 'progress': None} - + fixture = self._make_fixture('test image') num_images = len(self.service.index(self.context)) id = self.service.create(self.context, fixture)['id'] @@ -65,14 +57,7 @@ class BaseImageServiceTests(object): len(self.service.index(self.context))) def test_create_and_show_non_existing_image(self): - - fixture = {'name': 'test image', - 'updated': None, - 'created': None, - 'status': None, - 'instance_id': None, - 'progress': None} - + fixture = self._make_fixture('test image') num_images = len(self.service.index(self.context)) id = self.service.create(self.context, fixture)['id'] @@ -85,14 +70,7 @@ class BaseImageServiceTests(object): 'bad image id') def test_update(self): - - fixture = {'name': 'test image', - 'updated': None, - 'created': None, - 'status': None, - 'instance_id': None, - 'progress': None} - + fixture = self._make_fixture('test image') id = self.service.create(self.context, fixture)['id'] fixture['status'] = 'in progress' @@ -102,20 +80,9 @@ class BaseImageServiceTests(object): self.assertEquals('in progress', new_image_data['status']) def test_delete(self): - - fixtures = [ - {'name': 'test image 1', - 'updated': None, - 'created': None, - 'status': None, - 'instance_id': None, - 'progress': None}, - {'name': 'test image 2', - 'updated': None, - 'created': None, - 'status': None, - 'instance_id': None, - 'progress': None}] + fixture1 = self._make_fixture('test image 1') + fixture2 = self._make_fixture('test image 2') + fixtures = [fixture1, fixture2] num_images = len(self.service.index(self.context)) self.assertEquals(0, num_images, str(self.service.index(self.context))) @@ -133,6 +100,24 @@ class BaseImageServiceTests(object): num_images = len(self.service.index(self.context)) self.assertEquals(1, num_images) + def test_index(self): + fixture = self._make_fixture('test image') + image_id = self.service.create(self.context, fixture)['id'] + image_metas = self.service.index(self.context) + expected = [{'id': 'DONTCARE', 'name': 'test image'}] + self.assertDictListMatch(image_metas, expected) + + @staticmethod + def _make_fixture(name): + fixture = {'name': 'test image', + 'updated': None, + 'created': None, + 'status': None, + 'is_public': True, + 'instance_id': None, + 'progress': None} + return fixture + class LocalImageServiceTest(test.TestCase, BaseImageServiceTests): @@ -187,7 +172,7 @@ class GlanceImageServiceTest(test.TestCase, fakes.stub_out_compute_api_snapshot(self.stubs) service_class = 'nova.image.glance.GlanceImageService' self.service = utils.import_object(service_class) - self.context = context.RequestContext(None, None) + self.context = context.RequestContext(1, None) self.service.delete_all() self.sent_to_glance = {} fakes.stub_out_glance_add_image(self.stubs, self.sent_to_glance) @@ -199,13 +184,15 @@ class GlanceImageServiceTest(test.TestCase, def test_create_with_instance_id(self): """Ensure instance_id is persisted as an image-property""" fixture = {'name': 'test image', - 'properties': {'instance_id': '42'}} + 'is_public': False, + 'properties': {'instance_id': '42', 'user_id': '1'}} image_id = self.service.create(self.context, fixture)['id'] expected = {'id': image_id, 'name': 'test image', - 'properties': {'instance_id': '42'}} + 'is_public': False, + 'properties': {'instance_id': '42', 'user_id': '1'}} self.assertDictMatch(self.sent_to_glance['metadata'], expected) image_meta = self.service.show(self.context, image_id) @@ -301,38 +288,46 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): public_image = {'id': 123, 'name': 'public image', 'is_public': True, - 'status': 'active'} + 'status': 'active', + 'properties': {}} fixtures.append(public_image) queued_backup = {'id': 124, 'name': 'queued backup', 'is_public': False, 'status': 'queued', - 'instance_id': 42} + 'properties': {'instance_id': 42, 'user_id': 1}} fixtures.append(queued_backup) saving_backup = {'id': 125, 'name': 'saving backup', 'is_public': False, 'status': 'saving', - 'instance_id': 42, - 'progress': 0} + 'properties': {'instance_id': 42, 'user_id': 1}} fixtures.append(saving_backup) active_backup = {'id': 126, 'name': 'active backup', 'is_public': False, 'status': 'active', - 'instance_id': 42} + 'properties': {'instance_id': 42, 'user_id': 1}} fixtures.append(active_backup) killed_backup = {'id': 127, 'name': 'killed backup', 'is_public': False, 'status': 'killed', - 'instance_id': 42} + 'properties': {'instance_id': 42, 'user_id': 1}} fixtures.append(killed_backup) + someone_elses_backup = {'id': 127, + 'name': 'somone elses backup', + 'is_public': False, + 'status': 'active', + 'properties': {'instance_id': 43, + 'user_id': 2}} + fixtures.append(someone_elses_backup) + base_attrs = {'created_at': cls.NOW_SERVICE_STR, 'updated_at': cls.NOW_SERVICE_STR, 'deleted_at': None, -- cgit From 1f02ec1df57acfd06b2c241d1d9c18b936509b3c Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 06:20:24 +0000 Subject: Cleaning up make_image_fixutres --- nova/tests/api/openstack/test_images.py | 72 +++++++++++---------------------- 1 file changed, 24 insertions(+), 48 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 797bbef8f..2c0c75104 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -282,58 +282,34 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): @classmethod def _make_image_fixtures(cls): - """ - """ - fixtures = [] - public_image = {'id': 123, - 'name': 'public image', - 'is_public': True, - 'status': 'active', - 'properties': {}} - fixtures.append(public_image) - - queued_backup = {'id': 124, - 'name': 'queued backup', - 'is_public': False, - 'status': 'queued', - 'properties': {'instance_id': 42, 'user_id': 1}} - fixtures.append(queued_backup) - - saving_backup = {'id': 125, - 'name': 'saving backup', - 'is_public': False, - 'status': 'saving', - 'properties': {'instance_id': 42, 'user_id': 1}} - fixtures.append(saving_backup) - - active_backup = {'id': 126, - 'name': 'active backup', - 'is_public': False, - 'status': 'active', - 'properties': {'instance_id': 42, 'user_id': 1}} - fixtures.append(active_backup) - - killed_backup = {'id': 127, - 'name': 'killed backup', - 'is_public': False, - 'status': 'killed', - 'properties': {'instance_id': 42, 'user_id': 1}} - fixtures.append(killed_backup) - - someone_elses_backup = {'id': 127, - 'name': 'somone elses backup', - 'is_public': False, - 'status': 'active', - 'properties': {'instance_id': 43, - 'user_id': 2}} - fixtures.append(someone_elses_backup) - + image_id = 123 base_attrs = {'created_at': cls.NOW_SERVICE_STR, 'updated_at': cls.NOW_SERVICE_STR, 'deleted_at': None, 'deleted': False} - for fixture in fixtures: - fixture.update(base_attrs) + fixtures = [] + def add_fixture(**kwargs): + kwargs.update(base_attrs) + fixtures.append(kwargs) + + # Public image + add_fixture(id=image_id, name='public image', is_public=True, + status='active', properties={}) + image_id += 1 + + # Backup for User 1 + backup_properties = {'instance_id': '42', 'user_id': '1'} + for status in ('queued', 'saving', 'active', 'killed'): + add_fixture(id=image_id, name='%s backup' % status, + is_public=False, status=status, + properties=backup_properties) + image_id += 1 + + # Backup for User 2 + other_backup_properties = {'instance_id': '43', 'user_id': '2'} + add_fixture(id=image_id, name='someone elses backup', is_public=False, + status='active', properties=other_backup_properties) + image_id += 1 return fixtures -- cgit From dfa1e6eec0da81d5eedd303ef32442dc5c2a09d7 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 06:26:36 +0000 Subject: More small cleanups --- nova/tests/api/openstack/test_images.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 2c0c75104..785e104dc 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -50,9 +50,9 @@ class BaseImageServiceTests(object): fixture = self._make_fixture('test image') num_images = len(self.service.index(self.context)) - id = self.service.create(self.context, fixture)['id'] + image_id = self.service.create(self.context, fixture)['id'] - self.assertNotEquals(None, id) + self.assertNotEquals(None, image_id) self.assertEquals(num_images + 1, len(self.service.index(self.context))) @@ -60,10 +60,9 @@ class BaseImageServiceTests(object): fixture = self._make_fixture('test image') num_images = len(self.service.index(self.context)) - id = self.service.create(self.context, fixture)['id'] - - self.assertNotEquals(None, id) + image_id = self.service.create(self.context, fixture)['id'] + self.assertNotEquals(None, image_id) self.assertRaises(exception.NotFound, self.service.show, self.context, @@ -71,12 +70,12 @@ class BaseImageServiceTests(object): def test_update(self): fixture = self._make_fixture('test image') - id = self.service.create(self.context, fixture)['id'] - + image_id = self.service.create(self.context, fixture)['id'] fixture['status'] = 'in progress' - self.service.update(self.context, id, fixture) - new_image_data = self.service.show(self.context, id) + self.service.update(self.context, image_id, fixture) + + new_image_data = self.service.show(self.context, image_id) self.assertEquals('in progress', new_image_data['status']) def test_delete(self): @@ -113,9 +112,7 @@ class BaseImageServiceTests(object): 'updated': None, 'created': None, 'status': None, - 'is_public': True, - 'instance_id': None, - 'progress': None} + 'is_public': True} return fixture -- cgit From 32e1c38ef9539be6f914adc69f30e409b159a9e6 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 06:55:28 +0000 Subject: Adding tests for owned and non-existent images --- nova/tests/api/openstack/test_images.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 785e104dc..817778e1e 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -277,6 +277,28 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertDictListMatch(image_metas, expected) + def test_get_image_found(self): + req = webob.Request.blank('/v1.0/images/123') + res = req.get_response(fakes.wsgi_app()) + image_meta = json.loads(res.body)['image'] + expected = {'id': 123, 'name': 'public image', + 'updated': self.NOW_API_STR, 'created': self.NOW_API_STR, + 'status': 'ACTIVE'} + self.assertDictMatch(image_meta, expected) + + def test_get_image_non_existent(self): + req = webob.Request.blank('/v1.0/images/4242') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) + + def test_get_image_not_owned(self): + """We should return a 404 if we request an image that doesn't belong + to us + """ + req = webob.Request.blank('/v1.0/images/128') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) + @classmethod def _make_image_fixtures(cls): image_id = 123 -- cgit From 07c9626d91c217ad63e866d41b49db672887022e Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 06:59:26 +0000 Subject: Pep8 fixes --- nova/tests/api/openstack/test_images.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 817778e1e..ea8d96ea7 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -308,6 +308,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'deleted': False} fixtures = [] + def add_fixture(**kwargs): kwargs.update(base_attrs) fixtures.append(kwargs) -- cgit From 9902daf888ad369eb38e381d255eebda76aab106 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 23 Mar 2011 07:27:04 +0000 Subject: Removing dead code --- nova/tests/api/openstack/fakes.py | 8 -------- 1 file changed, 8 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index b81a09971..190efad0c 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -174,10 +174,6 @@ def stub_out_glance(stubs, initial_fixtures=None): raise glance_exc.NotFound def fake_add_image(self, image_meta, data=None): - if 'id' in image_meta: - raise Exception( - _("Cannot set id attribute for Glance image: %s") - % image_meta) image_id = ''.join(random.choice(string.letters) for _ in range(20)) image_meta['id'] = image_id @@ -199,9 +195,6 @@ def stub_out_glance(stubs, initial_fixtures=None): self.fixtures.remove(f) - ##def fake_delete_all(self): - ## self.fixtures = [] - GlanceClient = glance_client.Client fake = FakeGlanceClient(initial_fixtures) @@ -212,7 +205,6 @@ def stub_out_glance(stubs, initial_fixtures=None): stubs.Set(GlanceClient, 'add_image', fake.fake_add_image) stubs.Set(GlanceClient, 'update_image', fake.fake_update_image) stubs.Set(GlanceClient, 'delete_image', fake.fake_delete_image) - #stubs.Set(GlanceClient, 'delete_all', fake.fake_delete_all) class FakeToken(object): -- cgit From ff9e29e3ef56ec8b28f28d328ca010ce25f0c7b0 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 23 Mar 2011 09:47:22 -0400 Subject: Removed some un-needed code, and started adding tests for show(), which I forgot\! --- nova/tests/api/openstack/test_images.py | 61 +++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index c5a866bc7..8828b0e34 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -235,6 +235,67 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) + def test_get_image(self): + request = webob.Request.blank('/v1.0/images/23g2ogk23k4hhkk4k42l') + response = request.get_response(fakes.wsgi_app()) + + actual_image = json.loads(response.body) + + expected = self.IMAGE_FIXTURES[0] + expected_image = { + "id": expected["id"], + "name": expected["name"], + "updated": expected["updated_at"], + "created": expected["created_at"], + "status": expected["status"], + } + + self.assertEqual(expected_image, actual_image) + + def test_get_image_v1_1(self): + request = webob.Request.blank('/v1.1/images/23g2ogk23k4hhkk4k42l') + response = request.get_response(fakes.wsgi_app()) + + actual_image = json.loads(response.body) + + expected = self.IMAGE_FIXTURES[0] + href = "http://localhost/v1.1/images/%s" % expected["id"] + + expected_image = { + "id": expected["id"], + "name": expected["name"], + "updated": expected["updated_at"], + "created": expected["created_at"], + "status": expected["status"], + "links": [{ + "rel": "self", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/json", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": href, + }], + } + + self.assertEqual(expected_image, actual_image) + + def test_get_image_404(self): + request = webob.Request.blank('/v1.0/images/NonExistantImage') + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(404, response.status_int) + self.assertEqual("", response.body) + + def test_get_image_v1_1_404(self): + request = webob.Request.blank('/v1.1/images/NonExistantImage') + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(404, response.status_int) + def test_get_image_index_v1_1(self): request = webob.Request.blank('/v1.1/images') response = request.get_response(fakes.wsgi_app()) -- cgit From e9800364853078115cfb205bae263c3a55410b02 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 23 Mar 2011 11:04:20 -0400 Subject: Fixed tests. --- nova/tests/api/openstack/fakes.py | 4 ++-- nova/tests/api/openstack/test_images.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 16c7bc163..911eeaaad 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -79,9 +79,9 @@ def wsgi_app(inner_app10=None, inner_app11=None): inner_app11 = openstack.APIRouterV11() mapper = urlmap.URLMap() api10 = openstack.FaultWrapper(auth.AuthMiddleware( - ratelimiting.RateLimitingMiddleware(inner_app10))) + limits.RateLimitingMiddleware(inner_app10))) api11 = openstack.FaultWrapper(auth.AuthMiddleware( - ratelimiting.RateLimitingMiddleware(inner_app11))) + limits.RateLimitingMiddleware(inner_app11))) mapper['/v1.0'] = api10 mapper['/v1.1'] = api11 mapper['/'] = openstack.FaultWrapper(openstack.Versions()) diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index a6ee23e1d..e93a1ea40 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -301,7 +301,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): request = webob.Request.blank('/v1.0/images/NonExistantImage') response = request.get_response(fakes.wsgi_app()) self.assertEqual(404, response.status_int) - self.assertEqual("", response.body) def test_get_image_v1_1_404(self): request = webob.Request.blank('/v1.1/images/NonExistantImage') -- cgit From 572b6d30c809af6e117d96de9a5a2d845c1eeda0 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 23 Mar 2011 11:52:43 -0400 Subject: Testing of XML and JSON for show(), and conformance to API spec for JSON. --- nova/tests/api/openstack/test_images.py | 159 +++++++++++++++++++++++++++----- 1 file changed, 134 insertions(+), 25 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index e93a1ea40..deb8f1744 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -26,6 +26,8 @@ import os import shutil import tempfile +from xml.dom.minidom import parseString + import stubout import webob @@ -255,11 +257,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): expected = self.IMAGE_FIXTURES[0] expected_image = { - "id": expected["id"], - "name": expected["name"], - "updated": expected["updated_at"], - "created": expected["created_at"], - "status": expected["status"], + "image": { + "id": expected["id"], + "name": expected["name"], + "updated": expected["updated_at"], + "created": expected["created_at"], + "status": expected["status"], + }, } self.assertEqual(expected_image, actual_image) @@ -274,39 +278,142 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): href = "http://localhost/v1.1/images/%s" % expected["id"] expected_image = { - "id": expected["id"], - "name": expected["name"], - "updated": expected["updated_at"], - "created": expected["created_at"], - "status": expected["status"], - "links": [{ - "rel": "self", - "href": href, - }, - { - "rel": "bookmark", - "type": "application/json", - "href": href, + "image": { + "id": expected["id"], + "name": expected["name"], + "updated": expected["updated_at"], + "created": expected["created_at"], + "status": expected["status"], + "links": [{ + "rel": "self", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/json", + "href": href, + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": href, + }], }, - { - "rel": "bookmark", - "type": "application/xml", - "href": href, - }], } self.assertEqual(expected_image, actual_image) - def test_get_image_404(self): + def test_get_image_xml(self): + request = webob.Request.blank('/v1.0/images/23g2ogk23k4hhkk4k42l') + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + + actual_image = parseString(response.body.replace(" ", "")) + + expected = self.IMAGE_FIXTURES[0] + expected_image = parseString(""" + + """ % (expected)) + + self.assertEqual(expected_image.toxml(), actual_image.toxml()) + + def test_get_image_v1_1_xml(self): + request = webob.Request.blank('/v1.1/images/23g2ogk23k4hhkk4k42l') + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + + actual_image = parseString(response.body.replace(" ", "")) + + expected = self.IMAGE_FIXTURES[0] + expected["href"] = "http://localhost/v1.1/images/23g2ogk23k4hhkk4k42l" + expected_image = parseString(""" + + + + + + + + """.replace(" ", "") % (expected)) + + self.assertEqual(expected_image.toxml(), actual_image.toxml()) + + def test_get_image_404_json(self): + request = webob.Request.blank('/v1.0/images/NonExistantImage') + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(404, response.status_int) + + expected = { + "itemNotFound": { + "message": "Image not found.", + "code": 404, + }, + } + + actual = json.loads(response.body) + + self.assertEqual(expected, actual) + + def test_get_image_404_xml(self): request = webob.Request.blank('/v1.0/images/NonExistantImage') + request.accept = "application/xml" response = request.get_response(fakes.wsgi_app()) self.assertEqual(404, response.status_int) - def test_get_image_v1_1_404(self): + expected = parseString(""" + + + Image not found. + + + """.replace(" ", "")) + + actual = parseString(response.body.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + + def test_get_image_404_v1_1_json(self): request = webob.Request.blank('/v1.1/images/NonExistantImage') response = request.get_response(fakes.wsgi_app()) self.assertEqual(404, response.status_int) + expected = { + "itemNotFound": { + "message": "Image not found.", + "code": 404, + }, + } + + actual = json.loads(response.body) + + self.assertEqual(expected, actual) + + def test_get_image_404_v1_1_xml(self): + request = webob.Request.blank('/v1.1/images/NonExistantImage') + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + self.assertEqual(404, response.status_int) + + expected = parseString(""" + + + Image not found. + + + """.replace(" ", "")) + + actual = parseString(response.body.replace(" ", "")) + + self.assertEqual(expected.toxml(), actual.toxml()) + def test_get_image_index_v1_1(self): request = webob.Request.blank('/v1.1/images') response = request.get_response(fakes.wsgi_app()) @@ -338,6 +445,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertEqual(len(response_list), len(self.IMAGE_FIXTURES)) + + def test_get_image_details(self): request = webob.Request.blank('/v1.0/images/detail') response = request.get_response(fakes.wsgi_app()) -- cgit From 48c04eb35fae704913e9ed05868d1334ee5458fa Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Wed, 23 Mar 2011 12:17:48 -0400 Subject: add changePassword action to os api v1.1 --- nova/tests/api/openstack/test_servers.py | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index e21637ea4..dc5fedb8c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -558,6 +558,52 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 404) + def test_server_change_password(self): + body = {'changePassword': {'adminPass': '1234pass'}} + req = webob.Request.blank('/v1.0/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) + + def test_server_change_password_v1_1(self): + + class MockSetAdminPassword(object): + + def __init__(self): + self.called = False + self.instance_id = None + self.password = None + + def __call__(self, context, instance_id, password): + self.called = True + self.instance_id = instance_id + self.password = password + + mock_method = MockSetAdminPassword() + self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method) + + body = {'changePassword': {'adminPass': '1234pass'}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 202) + self.assertTrue(mock_method.called) + self.assertEqual(mock_method.instance_id, '1') + self.assertEqual(mock_method.password, '1234pass') + + def test_server_change_password_bad_request_v1_1(self): + body = {'changePassword': {'pass': '12345'}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_server_reboot(self): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, -- cgit From 1f90c7c6555e042cda1371a22c9891713a3f6430 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Wed, 23 Mar 2011 13:01:59 -0400 Subject: Implement v1.1 image metadata. --- nova/tests/api/openstack/test_image_metadata.py | 166 ++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 nova/tests/api/openstack/test_image_metadata.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py new file mode 100644 index 000000000..81280bd97 --- /dev/null +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -0,0 +1,166 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json +import stubout +import unittest +import webob + + +from nova import flags +from nova.api import openstack +from nova.tests.api.openstack import fakes +import nova.wsgi + + +FLAGS = flags.FLAGS + + +class ImageMetaDataTest(unittest.TestCase): + + IMAGE_FIXTURES = [ + {'status': 'active', + 'name': 'image1', + 'deleted': False, + 'container_format': None, + 'created_at': '2011-03-22T17: 40: 15.492626', + 'disk_format': None, + 'updated_at': '2011-03-22T17: 40: 15.591556', + 'id': '1', + 'location': 'file: ///var/lib/glance/images/1', + 'is_public': True, + 'deleted_at': None, + 'properties': { + 'type': 'ramdisk', + 'key1': 'value1', + 'key2': 'value2' + }, + 'size': 5882349}, + {'status': 'active', + 'name': 'image2', + 'deleted': False, + 'container_format': None, + 'created_at': '2011-03-22T17: 40: 15.492626', + 'disk_format': None, + 'updated_at': '2011-03-22T17: 40: 15.591556', + 'id': '2', + 'location': 'file: ///var/lib/glance/images/2', + 'is_public': True, + 'deleted_at': None, + 'properties': { + 'type': 'ramdisk', + 'key1': 'value1', + 'key2': 'value2' + }, + 'size': 5882349} + ] + + def setUp(self): + super(ImageMetaDataTest, self).setUp() + self.stubs = stubout.StubOutForTesting() + self.orig_image_service = FLAGS.image_service + FLAGS.image_service = 'nova.image.glance.GlanceImageService' + fakes.FakeAuthManager.auth_data = {} + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_auth(self.stubs) + fakes.stub_out_glance(self.stubs, self.IMAGE_FIXTURES) + + def tearDown(self): + self.stubs.UnsetAll() + FLAGS.image_service = self.orig_image_service + super(ImageMetaDataTest, self).tearDown() + + def test_index(self): + req = webob.Request.blank('/v1.1/images/1/meta') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value1', res_dict['metadata']['key1']) + + def test_show(self): + req = webob.Request.blank('/v1.1/images/1/meta/key1') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value1', res_dict['key1']) + + def test_show_not_found(self): + req = webob.Request.blank('/v1.1/images/1/meta/key9') + req.environ['api.version'] = '1.1' + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(404, res.status_int) + + def test_create(self): + req = webob.Request.blank('/v1.1/images/2/meta') + req.environ['api.version'] = '1.1' + req.method = 'POST' + req.body = '{"metadata": {"key9": "value9"}}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + res_dict = json.loads(res.body) + self.assertEqual(200, res.status_int) + self.assertEqual('value9', res_dict['metadata']['key9']) + # other items should not be modified + self.assertEqual('value1', res_dict['metadata']['key1']) + self.assertEqual('value2', res_dict['metadata']['key2']) + self.assertEqual(1, len(res_dict)) + + def test_update_item(self): + req = webob.Request.blank('/v1.1/images/1/meta/key1') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "zz"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + res_dict = json.loads(res.body) + self.assertEqual('zz', res_dict['key1']) + + def test_update_item_too_many_keys(self): + req = webob.Request.blank('/v1.1/images/1/meta/key1') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "value1", "key2": "value2"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) + + def test_update_item_body_uri_mismatch(self): + req = webob.Request.blank('/v1.1/images/1/meta/bad') + req.environ['api.version'] = '1.1' + req.method = 'PUT' + req.body = '{"key1": "value1"}' + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(400, res.status_int) + + def test_delete(self): + req = webob.Request.blank('/v1.1/images/2/meta/key1') + req.environ['api.version'] = '1.1' + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(200, res.status_int) + + def test_delete_not_found(self): + req = webob.Request.blank('/v1.1/images/2/meta/blah') + req.environ['api.version'] = '1.1' + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(404, res.status_int) -- cgit From 05e6f82aa971606f7d33fb1de8f2c1c170d030de Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Wed, 23 Mar 2011 12:31:15 -0700 Subject: indenting cleanup --- nova/tests/test_zones.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_zones.py b/nova/tests/test_zones.py index 48e1442cf..688dc704d 100644 --- a/nova/tests/test_zones.py +++ b/nova/tests/test_zones.py @@ -96,7 +96,7 @@ class ZoneManagerTestCase(test.TestCase): zm.update_service_capabilities("svc10", "host1", dict(a=99, b=99)) caps = zm.get_zone_capabilities(self, None) self.assertEquals(caps, dict(svc1_a=(2, 20), svc1_b=(3, 30), - svc10_a=(99, 99), svc10_b=(99, 99))) + svc10_a=(99, 99), svc10_b=(99, 99))) zm.update_service_capabilities("svc1", "host3", dict(c=5)) caps = zm.get_zone_capabilities(self, None) -- cgit From 3c0fcc47be08ac4f3d508fd46f3b95036899aaad Mon Sep 17 00:00:00 2001 From: termie Date: Wed, 23 Mar 2011 13:39:01 -0700 Subject: fix utils.execute retries for osx also some minor misc cleanups --- nova/tests/test_volume.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py index 5d68ca2ae..d71b75f3f 100644 --- a/nova/tests/test_volume.py +++ b/nova/tests/test_volume.py @@ -356,8 +356,8 @@ class ISCSITestCase(DriverTestCase): tid = db.volume_get_iscsi_target_num(self.context, volume_id_list[0]) self.mox.StubOutWithMock(self.volume.driver, '_execute') self.volume.driver._execute("sudo", "ietadm", "--op", "show", - "--tid=%(tid)d" % locals() - ).AndRaise(exception.ProcessExecutionError()) + "--tid=%(tid)d" % locals()).AndRaise( + exception.ProcessExecutionError()) self.mox.ReplayAll() self.assertRaises(exception.ProcessExecutionError, -- cgit From 98b4f0924257dcfa12e4881950472e983f08ef1d Mon Sep 17 00:00:00 2001 From: "matt.dietz@rackspace.com" <> Date: Wed, 23 Mar 2011 21:04:42 +0000 Subject: merge prop fixes --- nova/tests/test_compute.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 444be5dd8..44d04a12f 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -336,7 +336,7 @@ class ComputeTestCase(test.TestCase): self.compute.terminate_instance(context, instance_id) def test_resize_down_fails(self): - """Ensure invalid flavors raise""" + """Ensure resizing down raises and fails""" context = self.context.elevated() instance_id = self._create_instance() @@ -349,6 +349,18 @@ class ComputeTestCase(test.TestCase): self.compute.terminate_instance(context, instance_id) + def test_resize_same_size_fails(self): + """Ensure invalid flavors raise""" + context = self.context.elevated() + instance_id = self._create_instance() + + self.compute.run_instance(self.context, instance_id) + + self.assertRaises(exception.ApiError, self.compute_api.resize, + context, instance_id, 1) + + self.compute.terminate_instance(context, instance_id) + def test_get_by_flavor_id(self): type = instance_types.get_by_flavor_id(1) self.assertEqual(type, 'm1.tiny') -- cgit From 95fa499f1a7718694e37a747a6a5a0e309ce877d Mon Sep 17 00:00:00 2001 From: Eldar Nugaev Date: Thu, 24 Mar 2011 00:36:07 +0300 Subject: migration gateway_v6 to network_info --- nova/tests/test_virt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index b214f5ce7..98bb11526 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -785,7 +785,8 @@ class NWFilterTestCase(test.TestCase): instance_ref = db.instance_create(self.context, {'user_id': 'fake', - 'project_id': 'fake'}) + 'project_id': 'fake', + 'mac_address': '00:A0:C9:14:C8:29'}) inst_id = instance_ref['id'] ip = '10.11.12.13' -- cgit From 52bd70d500e7e82acea55c8d23c3fd1d66555cc0 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 24 Mar 2011 02:01:46 +0000 Subject: Addressing Rick Clark's comments. --- nova/tests/db/fakes.py | 4 +--- nova/tests/fake_utils.py | 16 ++++++++-------- nova/tests/test_xenapi.py | 4 ++-- nova/tests/xenapi/stubs.py | 4 ++-- 4 files changed, 13 insertions(+), 15 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 62c7cd794..c46b75aa2 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -99,9 +99,7 @@ def stub_out_db_instance_api(stubs, injected=True): return FakeModel(network_fields) def fake_network_get_all_by_instance(context, instance_id): - l = [] - l.append(FakeModel(network_fields)) - return l + return [FakeModel(network_fields)] def fake_instance_get_fixed_address(context, instance_id): return FakeModel(fixed_ip_fields).address diff --git a/nova/tests/fake_utils.py b/nova/tests/fake_utils.py index 8982f50be..823c775cb 100644 --- a/nova/tests/fake_utils.py +++ b/nova/tests/fake_utils.py @@ -33,7 +33,6 @@ _fake_execute_log = [] def fake_execute_get_log(): - global _fake_execute_log return _fake_execute_log @@ -55,7 +54,7 @@ def fake_execute_default_reply_handler(*ignore_args, **ignore_kwargs): return '', '' -def fake_execute(*cmd, **kwargs): +def fake_execute(*cmd_parts, **kwargs): """This function stubs out execute, optionally executing a preconfigued function to return expected data """ @@ -64,8 +63,7 @@ def fake_execute(*cmd, **kwargs): process_input = kwargs.get('process_input', None) addl_env = kwargs.get('addl_env', None) check_exit_code = kwargs.get('check_exit_code', 0) - cmd_map = map(str, cmd) - cmd_str = ' '.join(cmd_map) + cmd_str = ' '.join(str(part) for part in cmd_parts) LOG.debug(_("Faking execution of cmd (subprocess): %s"), cmd_str) _fake_execute_log.append(cmd_str) @@ -78,13 +76,13 @@ def fake_execute(*cmd, **kwargs): LOG.debug(_('Faked command matched %s') % fake_replier[0]) break - if isinstance(reply_handler, types.StringTypes): + if isinstance(reply_handler, basestring): # If the reply handler is a string, return it as stdout reply = reply_handler, '' else: try: # Alternative is a function, so call it - reply = reply_handler(cmd, + reply = reply_handler(cmd_parts, process_input=process_input, addl_env=addl_env, check_exit_code=check_exit_code) @@ -92,8 +90,10 @@ def fake_execute(*cmd, **kwargs): LOG.debug(_('Faked command raised an exception %s' % str(e))) raise - LOG.debug(_("Reply to faked command is stdout='%(0)s' stderr='%(1)s'") % - {'0': reply[0], '1': reply[1]}) + stdout = reply[0] + stderr = reply[1] + LOG.debug(_("Reply to faked command is stdout='%(stdout)s' " + "stderr='%(stderr)s'") % locals()) # Replicate the sleep call in the real function greenthread.sleep(0) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index b22163e9b..d31fa27ac 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -76,7 +76,6 @@ class XenAPIVolumeTestCase(test.TestCase): FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_password = 'test_pass' db_fakes.stub_out_db_instance_api(self.stubs) - #db_fakes.stub_out_db_network_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() self.values = {'id': 1, @@ -333,7 +332,8 @@ class XenAPIVMTestCase(test.TestCase): self.assertEquals(self.vm['HVM_boot_policy'], '') def _test_spawn(self, image_id, kernel_id, ramdisk_id, - instance_type="m1.large", os_type="linux", check_injection=False): + instance_type="m1.large", os_type="linux", + check_injection=False): stubs.stubout_loopingcall_start(self.stubs) values = {'id': 1, 'project_id': self.project.id, diff --git a/nova/tests/xenapi/stubs.py b/nova/tests/xenapi/stubs.py index d278934c6..0f559b7f9 100644 --- a/nova/tests/xenapi/stubs.py +++ b/nova/tests/xenapi/stubs.py @@ -139,9 +139,9 @@ def stubout_is_vdi_pv(stubs): def stubout_loopingcall_start(stubs): - def f_1(self, interval, now=True): + def fake_start(self, interval, now=True): self.f(*self.args, **self.kw) - stubs.Set(utils.LoopingCall, 'start', f_1) + stubs.Set(utils.LoopingCall, 'start', fake_start) class FakeSessionForVMTests(fake.SessionBase): -- cgit From 694c2cfd2afdc0ed293f205890bda977968dc079 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 01:13:20 -0700 Subject: Created simple test case for server creation, so that we can have something to attach to... --- nova/tests/integrated/integrated_helpers.py | 22 +++ nova/tests/integrated/test_servers.py | 218 ++++++++++++++++++++++++++++ 2 files changed, 240 insertions(+) create mode 100644 nova/tests/integrated/test_servers.py (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 47093636e..dc6897e08 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -73,6 +73,28 @@ class TestUser(object): self.secret, self.auth_url) + def get_unused_server_name(self): + servers = self.openstack_api.get_servers() + server_names = [server['name'] for server in servers] + return generate_new_element(server_names, 'server') + + def get_invalid_image(self): + images = self.openstack_api.get_images() + image_ids = [image['id'] for image in images] + return generate_new_element(image_ids, '', numeric=True) + + def get_valid_image(self, create=False): + images = self.openstack_api.get_images() + if create and not images: + # TODO(justinsb): No way to create an image through API??? + #created_image = self.openstack_api.post_image(image) + #images.append(created_image) + raise exception.Error("No way to create an image through API??") + + if images: + return images[0] + return None + class IntegratedUnitTestContext(object): __INSTANCE = None diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py new file mode 100644 index 000000000..3c38295c5 --- /dev/null +++ b/nova/tests/integrated/test_servers.py @@ -0,0 +1,218 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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. + +import time +import unittest + +from nova import flags +from nova import test +from nova.log import logging +from nova.tests.integrated import integrated_helpers +from nova.tests.integrated.api import client + + +LOG = logging.getLogger('nova.tests.integrated') + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +class ServersTest(test.TestCase): + def setUp(self): + super(ServersTest, self).setUp() + + self.flags(image_service='nova.image.fake.MockImageService') + + context = integrated_helpers.IntegratedUnitTestContext.startup() + self.user = context.test_user + self.api = self.user.openstack_api + + def tearDown(self): + integrated_helpers.IntegratedUnitTestContext.shutdown() + super(ServersTest, self).tearDown() + + def test_get_servers(self): + """Simple check that listing servers works.""" + servers = self.api.get_servers() + for server in servers: + LOG.debug("server: %s" % server) + + def test_create_and_delete_server(self): + """Creates and deletes a server""" + + # Create server + + # Build the server data gradually, checking errors along the way + server = {} + good_server = self._build_minimal_create_server_request() + + post = {'server': server} + + # Without an imageId, this throws 500. + # TODO(justinsb): Check whatever the spec says should be thrown here + self.assertRaises(client.OpenStackApiException, + self.api.post_server, post) + + # With an invalid imageId, this throws 500. + server['imageId'] = self.user.get_invalid_image() + # TODO(justinsb): Check whatever the spec says should be thrown here + self.assertRaises(client.OpenStackApiException, + self.api.post_server, post) + + # Add a valid imageId + server['imageId'] = good_server['imageId'] + + # Without flavorId, this throws 500 + # TODO(justinsb): Check whatever the spec says should be thrown here + self.assertRaises(client.OpenStackApiException, + self.api.post_server, post) + + # Set a valid flavorId + server['flavorId'] = good_server['flavorId'] + + # Without a name, this throws 500 + # TODO(justinsb): Check whatever the spec says should be thrown here + self.assertRaises(client.OpenStackApiException, + self.api.post_server, post) + + # Set a valid server name + server['name'] = good_server['name'] + + created_server = self.api.post_server(post) + LOG.debug("created_server: %s" % created_server) + self.assertTrue(created_server['id']) + created_server_id = created_server['id'] + + # Check it's there + found_server = self.api.get_server(created_server_id) + self.assertEqual(created_server_id, found_server['id']) + + # It should also be in the all-servers list + servers = self.api.get_servers() + server_ids = [server['id'] for server in servers] + self.assertTrue(created_server_id in server_ids) + + # Wait (briefly) for creation + retries = 0 + while found_server['status'] == 'build': + LOG.debug("found server: %s" % found_server) + time.sleep(1) + found_server = self.api.get_server(created_server_id) + retries = retries + 1 + if retries > 5: + break + + # It should be available... + # TODO(justinsb): Mock doesn't yet do this... + #self.assertEqual('available', found_server['status']) + + self._delete_server(created_server_id) + + def _delete_server(self, server_id): + # Delete the server + self.api.delete_server(server_id) + + # Wait (briefly) for deletion + for _retries in range(5): + try: + found_server = self.api.get_server(server_id) + except client.OpenStackApiNotFoundException: + found_server = None + LOG.debug("Got 404, proceeding") + break + + LOG.debug("Found_server=%s" % found_server) + + # TODO(justinsb): Mock doesn't yet do accurate state changes + #if found_server['status'] != 'deleting': + # break + time.sleep(1) + + # Should be gone + self.assertFalse(found_server) + + def _build_minimal_create_server_request(self): + server = {} + + image = self.user.get_valid_image(create=True) + image_id = image['id'] + + #TODO(justinsb): This is FUBAR + image_id = abs(hash(image_id)) + + # We now have a valid imageId + server['imageId'] = image_id + + # Set a valid flavorId + flavor = self.api.get_flavors()[0] + LOG.debug("Using flavor: %s" % flavor) + server['flavorId'] = flavor['id'] + + # Set a valid server name + server_name = self.user.get_unused_server_name() + server['name'] = server_name + + return server + +# TODO(justinsb): Enable this unit test when the metadata bug is fixed +# def test_create_server_with_metadata(self): +# """Creates a server with metadata""" +# +# # Build the server data gradually, checking errors along the way +# server = self._build_minimal_create_server_request() +# +# for metadata_count in range(30): +# metadata = {} +# for i in range(metadata_count): +# metadata['key_%s' % i] = 'value_%s' % i +# server['metadata'] = metadata +# +# post = {'server': server} +# created_server = self.api.post_server(post) +# LOG.debug("created_server: %s" % created_server) +# self.assertTrue(created_server['id']) +# created_server_id = created_server['id'] +# # Reenable when bug fixed +# # self.assertEqual(metadata, created_server.get('metadata')) +# +# # Check it's there +# found_server = self.api.get_server(created_server_id) +# self.assertEqual(created_server_id, found_server['id']) +# self.assertEqual(metadata, found_server.get('metadata')) +# +# # The server should also be in the all-servers details list +# servers = self.api.get_servers(detail=True) +# server_map = dict((server['id'], server) for server in servers) +# found_server = server_map.get(created_server_id) +# self.assertTrue(found_server) +# # Details do include metadata +# self.assertEqual(metadata, found_server.get('metadata')) +# +# # The server should also be in the all-servers summary list +# servers = self.api.get_servers(detail=False) +# server_map = dict((server['id'], server) for server in servers) +# found_server = server_map.get(created_server_id) +# self.assertTrue(found_server) +# # Summary should not include metadata +# self.assertFalse(found_server.get('metadata')) +# +# # Cleanup +# self._delete_server(created_server_id) + + +if __name__ == "__main__": + unittest.main() -- cgit From 699adb4311fdd86525fae022f4119401fd1c0168 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 01:37:14 -0700 Subject: Added simple nova volume tests --- nova/tests/integrated/api/client.py | 15 +++ nova/tests/integrated/integrated_helpers.py | 17 +++- nova/tests/integrated/test_volumes.py | 137 ++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 nova/tests/integrated/test_volumes.py (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index fc7c344e7..7a4c3198e 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -90,6 +90,7 @@ class TestOpenStackClient(object): LOG.info(_("Doing %(method)s on %(relative_url)s") % locals()) if body: LOG.info(_("Body: %s") % body) + headers.setdefault('Content-Type', 'application/json') conn.request(method, relative_url, body, headers) response = conn.getresponse() @@ -208,3 +209,17 @@ class TestOpenStackClient(object): def delete_flavor(self, flavor_id): return self.api_delete('/flavors/%s' % flavor_id) + + def get_volume(self, volume_id): + return self.api_get('/volumes/%s' % volume_id)['volume'] + + def get_volumes(self, detail=True): + rel_url = '/volumes/detail' if detail else '/volumes' + return self.api_get(rel_url)['volumes'] + + def post_volume(self, volume): + return self.api_post('/volumes', volume)['volume'] + + def delete_volume(self, volume_id): + return self.api_delete('/volumes/%s' % volume_id) + diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index dc6897e08..f24759032 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -58,7 +58,7 @@ def generate_new_element(items, prefix, numeric=False): candidate = prefix + generate_random_alphanumeric(8) if not candidate in items: return candidate - print "Random collision on %s" % candidate + LOG.debug("Random collision on %s" % candidate) class TestUser(object): @@ -125,11 +125,26 @@ class IntegratedUnitTestContext(object): self._configure_project(self.project_name, self.test_user) def _start_services(self): + self._start_volume_service() + self._start_scheduler_service() + # WSGI shutdown broken :-( # bug731668 if not self.api_service: self._start_api_service() + def _start_volume_service(self): + volume_service = service.Service.create(binary='nova-volume') + volume_service.start() + self.services.append(volume_service) + return volume_service + + def _start_scheduler_service(self): + scheduler_service = service.Service.create(binary='nova-scheduler') + scheduler_service.start() + self.services.append(scheduler_service) + return scheduler_service + def cleanup(self): for service in self.services: service.kill() diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py new file mode 100644 index 000000000..66b773db2 --- /dev/null +++ b/nova/tests/integrated/test_volumes.py @@ -0,0 +1,137 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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. + +import unittest +import time + +from nova import flags +from nova import test +from nova.log import logging +from nova.tests.integrated import integrated_helpers +from nova.tests.integrated.api import client +from nova.volume import driver + + +LOG = logging.getLogger('nova.tests.integrated') + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +class VolumesTest(test.TestCase): + def setUp(self): + super(VolumesTest, self).setUp() + + self.flags(image_service='nova.image.fake.MockImageService', + volume_driver='nova.volume.driver.LoggingVolumeDriver') + + context = integrated_helpers.IntegratedUnitTestContext.startup() + self.user = context.test_user + self.api = self.user.openstack_api + + def tearDown(self): + integrated_helpers.IntegratedUnitTestContext.shutdown() + super(VolumesTest, self).tearDown() + + def test_get_volumes(self): + """Simple check that listing volumes works""" + volumes = self.api.get_volumes() + for volume in volumes: + LOG.debug("volume: %s" % volume) + + def test_create_and_delete_volume(self): + """Creates and deletes a volume""" + + # Create volume with name + created_volume = self.api.post_volume({'volume': {'size': 1}}) + LOG.debug("created_volume: %s" % created_volume) + self.assertTrue(created_volume['id']) + created_volume_id = created_volume['id'] + + # Check it's there + found_volume = self.api.get_volume(created_volume_id) + self.assertEqual(created_volume_id, found_volume['id']) + + # It should also be in the all-volume list + volumes = self.api.get_volumes() + volume_names = [volume['id'] for volume in volumes] + self.assertTrue(created_volume_id in volume_names) + + # Wait (briefly) for creation. Delay is due to the 'message queue' + retries = 0 + while found_volume['status'] == 'creating': + LOG.debug("Found %s" % found_volume) + time.sleep(1) + found_volume = self.api.get_volume(created_volume_id) + retries = retries + 1 + if retries > 5: + break + + # It should be available... + self.assertEqual('available', found_volume['status']) + + # Delete the volume + self.api.delete_volume(created_volume_id) + + # Wait (briefly) for deletion. Delay is due to the 'message queue' + for retries in range(5): + try: + found_volume = self.api.get_volume(created_volume_id) + except client.OpenStackApiNotFoundException: + found_volume = None + LOG.debug("Got 404, proceeding") + break + + LOG.debug("Found_volume=%s" % found_volume) + if found_volume['status'] != 'deleting': + break + time.sleep(1) + + # Should be gone + self.assertFalse(found_volume) + + LOG.debug("Logs: %s" % driver.LoggingVolumeDriver.all_logs()) + + create_actions = driver.LoggingVolumeDriver.logs_like( + 'create_volume', + id=created_volume_id) + LOG.debug("Create_Actions: %s" % create_actions) + + self.assertEquals(1, len(create_actions)) + create_action = create_actions[0] + self.assertEquals(create_action['id'], created_volume_id) + self.assertEquals(create_action['availability_zone'], 'nova') + self.assertEquals(create_action['size'], 1) + + export_actions = driver.LoggingVolumeDriver.logs_like( + 'create_export', + id=created_volume_id) + self.assertEquals(1, len(export_actions)) + export_action = export_actions[0] + self.assertEquals(export_action['id'], created_volume_id) + self.assertEquals(export_action['availability_zone'], 'nova') + + delete_actions = driver.LoggingVolumeDriver.logs_like( + 'delete_volume', + id=created_volume_id) + self.assertEquals(1, len(delete_actions)) + delete_action = export_actions[0] + self.assertEquals(delete_action['id'], created_volume_id) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file -- cgit From 230d07e9002371bdb0030c9199df35fc6360a0a2 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 03:26:32 -0700 Subject: Test for attach / detach (and associated fixes) --- nova/tests/integrated/api/client.py | 15 ++ nova/tests/integrated/integrated_helpers.py | 49 +++++++ nova/tests/integrated/test_login.py | 12 +- nova/tests/integrated/test_servers.py | 37 +---- nova/tests/integrated/test_volumes.py | 215 +++++++++++++++++++++++----- 5 files changed, 250 insertions(+), 78 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 7a4c3198e..deb7fd981 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -223,3 +223,18 @@ class TestOpenStackClient(object): def delete_volume(self, volume_id): return self.api_delete('/volumes/%s' % volume_id) + def get_server_volume(self, server_id, attachment_id): + return self.api_get('/servers/%s/volume_attachments/%s' % + (server_id, attachment_id))['volumeAttachment'] + + def get_server_volumes(self, server_id): + return self.api_get('/servers/%s/volume_attachments' % + (server_id))['volumeAttachments'] + + def post_server_volume(self, server_id, volume_attachment): + return self.api_post('/servers/%s/volume_attachments' % + (server_id), volume_attachment)['volumeAttachment'] + + def delete_server_volume(self, server_id, attachment_id): + return self.api_delete('/servers/%s/volume_attachments/%s' % + (server_id, attachment_id)) diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index f24759032..b520cc5d3 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -125,6 +125,7 @@ class IntegratedUnitTestContext(object): self._configure_project(self.project_name, self.test_user) def _start_services(self): + self._start_compute_service() self._start_volume_service() self._start_scheduler_service() @@ -133,6 +134,12 @@ class IntegratedUnitTestContext(object): if not self.api_service: self._start_api_service() + def _start_compute_service(self): + compute_service = service.Service.create(binary='nova-compute') + compute_service.start() + self.services.append(compute_service) + return compute_service + def _start_volume_service(self): volume_service = service.Service.create(binary='nova-volume') volume_service.start() @@ -223,3 +230,45 @@ class IntegratedUnitTestContext(object): # WSGI shutdown broken :-( # bug731668 #IntegratedUnitTestContext.__INSTANCE = None + + +class _IntegratedTestBase(test.TestCase): + def setUp(self): + super(_IntegratedTestBase, self).setUp() + + self._setup_flags() + + context = IntegratedUnitTestContext.startup() + self.user = context.test_user + self.api = self.user.openstack_api + + def tearDown(self): + IntegratedUnitTestContext.shutdown() + super(_IntegratedTestBase, self).tearDown() + + def _setup_flags(self): + """An opportunity to setup flags, before the services are started""" + pass + + def _build_minimal_create_server_request(self): + server = {} + + image = self.user.get_valid_image(create=True) + image_id = image['id'] + + #TODO(justinsb): This is FUBAR + image_id = abs(hash(image_id)) + + # We now have a valid imageId + server['imageId'] = image_id + + # Set a valid flavorId + flavor = self.api.get_flavors()[0] + LOG.debug("Using flavor: %s" % flavor) + server['flavorId'] = flavor['id'] + + # Set a valid server name + server_name = self.user.get_unused_server_name() + server['name'] = server_name + + return server diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index 501f8c919..cc3d555d0 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -30,17 +30,7 @@ FLAGS = flags.FLAGS FLAGS.verbose = True -class LoginTest(test.TestCase): - def setUp(self): - super(LoginTest, self).setUp() - context = integrated_helpers.IntegratedUnitTestContext.startup() - self.user = context.test_user - self.api = self.user.openstack_api - - def tearDown(self): - integrated_helpers.IntegratedUnitTestContext.shutdown() - super(LoginTest, self).tearDown() - +class LoginTest(integrated_helpers._IntegratedTestBase): def test_login(self): """Simple check - we list flavors - so we know we're logged in""" flavors = self.api.get_flavors() diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 3c38295c5..2b5d3324a 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -31,20 +31,10 @@ FLAGS = flags.FLAGS FLAGS.verbose = True -class ServersTest(test.TestCase): - def setUp(self): - super(ServersTest, self).setUp() - +class ServersTest(integrated_helpers._IntegratedTestBase): + def _setup_flags(self): self.flags(image_service='nova.image.fake.MockImageService') - context = integrated_helpers.IntegratedUnitTestContext.startup() - self.user = context.test_user - self.api = self.user.openstack_api - - def tearDown(self): - integrated_helpers.IntegratedUnitTestContext.shutdown() - super(ServersTest, self).tearDown() - def test_get_servers(self): """Simple check that listing servers works.""" servers = self.api.get_servers() @@ -145,29 +135,6 @@ class ServersTest(test.TestCase): # Should be gone self.assertFalse(found_server) - def _build_minimal_create_server_request(self): - server = {} - - image = self.user.get_valid_image(create=True) - image_id = image['id'] - - #TODO(justinsb): This is FUBAR - image_id = abs(hash(image_id)) - - # We now have a valid imageId - server['imageId'] = image_id - - # Set a valid flavorId - flavor = self.api.get_flavors()[0] - LOG.debug("Using flavor: %s" % flavor) - server['flavorId'] = flavor['id'] - - # Set a valid server name - server_name = self.user.get_unused_server_name() - server['name'] = server_name - - return server - # TODO(justinsb): Enable this unit test when the metadata bug is fixed # def test_create_server_with_metadata(self): # """Creates a server with metadata""" diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index 66b773db2..f69361fb0 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -32,20 +32,15 @@ FLAGS = flags.FLAGS FLAGS.verbose = True -class VolumesTest(test.TestCase): +class VolumesTest(integrated_helpers._IntegratedTestBase): def setUp(self): super(VolumesTest, self).setUp() + driver.LoggingVolumeDriver.clear_logs() + def _setup_flags(self): self.flags(image_service='nova.image.fake.MockImageService', volume_driver='nova.volume.driver.LoggingVolumeDriver') - - context = integrated_helpers.IntegratedUnitTestContext.startup() - self.user = context.test_user - self.api = self.user.openstack_api - - def tearDown(self): - integrated_helpers.IntegratedUnitTestContext.shutdown() - super(VolumesTest, self).tearDown() + self.flags(use_local_volumes=False) # Avoids calling local_path def test_get_volumes(self): """Simple check that listing volumes works""" @@ -53,10 +48,34 @@ class VolumesTest(test.TestCase): for volume in volumes: LOG.debug("volume: %s" % volume) + def _poll_while(self, volume_id, continue_states, max_retries=5): + """ Poll (briefly) while the state is in continue_states""" + retries = 0 + while True: + try: + found_volume = self.api.get_volume(volume_id) + except client.OpenStackApiNotFoundException: + found_volume = None + LOG.debug("Got 404, proceeding") + break + + LOG.debug("Found %s" % found_volume) + + self.assertEqual(volume_id, found_volume['id']) + + if not found_volume['status'] in continue_states: + break + + time.sleep(1) + retries = retries + 1 + if retries > max_retries: + break + return found_volume + def test_create_and_delete_volume(self): """Creates and deletes a volume""" - # Create volume with name + # Create volume created_volume = self.api.post_volume({'volume': {'size': 1}}) LOG.debug("created_volume: %s" % created_volume) self.assertTrue(created_volume['id']) @@ -72,14 +91,7 @@ class VolumesTest(test.TestCase): self.assertTrue(created_volume_id in volume_names) # Wait (briefly) for creation. Delay is due to the 'message queue' - retries = 0 - while found_volume['status'] == 'creating': - LOG.debug("Found %s" % found_volume) - time.sleep(1) - found_volume = self.api.get_volume(created_volume_id) - retries = retries + 1 - if retries > 5: - break + found_volume = self._poll_while(created_volume_id, ['creating']) # It should be available... self.assertEqual('available', found_volume['status']) @@ -88,18 +100,7 @@ class VolumesTest(test.TestCase): self.api.delete_volume(created_volume_id) # Wait (briefly) for deletion. Delay is due to the 'message queue' - for retries in range(5): - try: - found_volume = self.api.get_volume(created_volume_id) - except client.OpenStackApiNotFoundException: - found_volume = None - LOG.debug("Got 404, proceeding") - break - - LOG.debug("Found_volume=%s" % found_volume) - if found_volume['status'] != 'deleting': - break - time.sleep(1) + found_volume = self._poll_while(created_volume_id, ['deleting']) # Should be gone self.assertFalse(found_volume) @@ -110,7 +111,7 @@ class VolumesTest(test.TestCase): 'create_volume', id=created_volume_id) LOG.debug("Create_Actions: %s" % create_actions) - + self.assertEquals(1, len(create_actions)) create_action = create_actions[0] self.assertEquals(create_action['id'], created_volume_id) @@ -132,6 +133,156 @@ class VolumesTest(test.TestCase): delete_action = export_actions[0] self.assertEquals(delete_action['id'], created_volume_id) + def test_attach_and_detach_volume(self): + """Creates, attaches, detaches and deletes a volume""" + + # Create server + server_req = {'server': self._build_minimal_create_server_request()} + # NOTE(justinsb): Create an extra server so that server_id != volume_id + self.api.post_server(server_req) + created_server = self.api.post_server(server_req) + LOG.debug("created_server: %s" % created_server) + server_id = created_server['id'] + + # Create volume + created_volume = self.api.post_volume({'volume': {'size': 1}}) + LOG.debug("created_volume: %s" % created_volume) + volume_id = created_volume['id'] + self._poll_while(volume_id, ['creating']) + + # Check we've got different IDs + self.assertNotEqual(server_id, volume_id) + + # List current server attachments - should be none + attachments = self.api.get_server_volumes(server_id) + self.assertEquals([], attachments) + + # Template attach request + device = '/dev/sdc' + attach_req = { 'device': device } + post_req = { 'volumeAttachment': attach_req } + + # Try to attach to a non-existent volume; should fail + attach_req['volumeId'] = 3405691582 + self.assertRaises(client.OpenStackApiNotFoundException, + self.api.post_server_volume, server_id, post_req) + + # Try to attach to a non-existent server; should fail + attach_req['volumeId'] = volume_id + self.assertRaises(client.OpenStackApiNotFoundException, + self.api.post_server_volume, 3405691582, post_req) + + # Should still be no attachments... + attachments = self.api.get_server_volumes(server_id) + self.assertEquals([], attachments) + + # Do a real attach + attach_req['volumeId'] = volume_id + attach_result = self.api.post_server_volume(server_id, post_req) + LOG.debug(_("Attachment = %s") % attach_result) + + attachment_id = attach_result['id'] + self.assertEquals(volume_id, attach_result['volumeId']) + + # These fields aren't set because it's async + #self.assertEquals(server_id, attach_result['serverId']) + #self.assertEquals(device, attach_result['device']) + + # This is just an implementation detail, but let's check it... + self.assertEquals(volume_id, attachment_id) + + # NOTE(justinsb): There's an issue with the attach code, in that + # it's currently asynchronous and not recorded until the attach + # completes. So the caller must be 'smart', like this... + attach_done = None + retries = 0 + while True: + try: + attach_done = self.api.get_server_volume(server_id, + attachment_id) + break + except client.OpenStackApiNotFoundException: + LOG.debug("Got 404, waiting") + + time.sleep(1) + retries = retries + 1 + if retries > 10: + break + + expect_attach = {} + expect_attach['id'] = volume_id + expect_attach['volumeId'] = volume_id + expect_attach['serverId'] = server_id + expect_attach['device'] = device + + self.assertEqual(expect_attach, attach_done) + + # Should be one attachemnt + attachments = self.api.get_server_volumes(server_id) + self.assertEquals([expect_attach], attachments) + + # Should be able to get details + attachment_info = self.api.get_server_volume(server_id, attachment_id) + self.assertEquals(expect_attach, attachment_info) + + # Getting details on a different id should fail + self.assertRaises(client.OpenStackApiNotFoundException, + self.api.get_server_volume, server_id, 3405691582) + self.assertRaises(client.OpenStackApiNotFoundException, + self.api.get_server_volume, + 3405691582, attachment_id) + + # Trying to detach a different id should fail + self.assertRaises(client.OpenStackApiNotFoundException, + self.api.delete_server_volume, server_id, 3405691582) + + # Detach should work + self.api.delete_server_volume(server_id, attachment_id) + + # Again, it's async, so wait... + retries = 0 + while True: + try: + attachment = self.api.get_server_volume(server_id, + attachment_id) + LOG.debug("Attachment still there: %s" % attachment) + except client.OpenStackApiNotFoundException: + LOG.debug("Got 404, delete done") + break + + time.sleep(1) + retries = retries + 1 + self.assertTrue(retries < 10) + + # Should be no attachments again + attachments = self.api.get_server_volumes(server_id) + self.assertEquals([], attachments) + + LOG.debug("Logs: %s" % driver.LoggingVolumeDriver.all_logs()) + + # Discover_volume and undiscover_volume are called from compute + # on attach/detach + + disco_moves = driver.LoggingVolumeDriver.logs_like( + 'discover_volume', + id=volume_id) + LOG.debug("discover_volume actions: %s" % disco_moves) + + self.assertEquals(1, len(disco_moves)) + disco_move = disco_moves[0] + self.assertEquals(disco_move['id'], volume_id) + + last_days_of_disco_moves = driver.LoggingVolumeDriver.logs_like( + 'undiscover_volume', + id=volume_id) + LOG.debug("undiscover_volume actions: %s" % last_days_of_disco_moves) + + self.assertEquals(1, len(last_days_of_disco_moves)) + undisco_move = last_days_of_disco_moves[0] + self.assertEquals(undisco_move['id'], volume_id) + self.assertEquals(undisco_move['mountpoint'], device) + self.assertEquals(undisco_move['instance_id'], server_id) + if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() -- cgit From d49219f8b6dd626b868b99bee8a22c4ac5495af1 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 03:28:59 -0700 Subject: pep8 fixes --- nova/tests/integrated/api/client.py | 2 +- nova/tests/integrated/test_volumes.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index deb7fd981..023871bda 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -226,7 +226,7 @@ class TestOpenStackClient(object): def get_server_volume(self, server_id, attachment_id): return self.api_get('/servers/%s/volume_attachments/%s' % (server_id, attachment_id))['volumeAttachment'] - + def get_server_volumes(self, server_id): return self.api_get('/servers/%s/volume_attachments' % (server_id))['volumeAttachments'] diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index f69361fb0..aa90301a5 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -159,8 +159,8 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): # Template attach request device = '/dev/sdc' - attach_req = { 'device': device } - post_req = { 'volumeAttachment': attach_req } + attach_req = {'device': device} + post_req = {'volumeAttachment': attach_req} # Try to attach to a non-existent volume; should fail attach_req['volumeId'] = 3405691582 -- cgit From d8052812cb5b9d3d3578c0e6651e56b4313d5f85 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 24 Mar 2011 10:32:22 +0000 Subject: Sorted out a problem occurred with units tests for VM migration --- nova/tests/test_xenapi.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index d31fa27ac..fd8ed39d8 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -553,6 +553,7 @@ class XenAPIMigrateInstance(test.TestCase): 'image_id': 1, 'kernel_id': None, 'ramdisk_id': None, + 'local_gb': 5, 'instance_type': 'm1.large', 'mac_address': 'aa:bb:cc:dd:ee:ff', 'os_type': 'linux'} -- cgit From bebc9504bb34934147705512413267d1ae4af170 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 04:02:31 -0700 Subject: Fake out network service as well, otherwise we can't terminate the instance in test_servers now that we've started a compute service --- nova/tests/integrated/integrated_helpers.py | 17 ++++++++++++++--- nova/tests/integrated/test_login.py | 1 - nova/tests/integrated/test_servers.py | 7 ++++--- nova/tests/integrated/test_volumes.py | 11 ++++++----- 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index b520cc5d3..3b7caecd6 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -128,6 +128,7 @@ class IntegratedUnitTestContext(object): self._start_compute_service() self._start_volume_service() self._start_scheduler_service() + self._start_network_service() # WSGI shutdown broken :-( # bug731668 @@ -140,6 +141,12 @@ class IntegratedUnitTestContext(object): self.services.append(compute_service) return compute_service + def _start_network_service(self): + network_service = service.Service.create(binary='nova-network') + network_service.start() + self.services.append(network_service) + return network_service + def _start_volume_service(self): volume_service = service.Service.create(binary='nova-volume') volume_service.start() @@ -236,7 +243,8 @@ class _IntegratedTestBase(test.TestCase): def setUp(self): super(_IntegratedTestBase, self).setUp() - self._setup_flags() + f = self._get_flags() + self.flags(**f) context = IntegratedUnitTestContext.startup() self.user = context.test_user @@ -246,9 +254,12 @@ class _IntegratedTestBase(test.TestCase): IntegratedUnitTestContext.shutdown() super(_IntegratedTestBase, self).tearDown() - def _setup_flags(self): + def _get_flags(self): """An opportunity to setup flags, before the services are started""" - pass + f = {} + #f['network_driver'] = 'nova.network.fake.FakeNetworkDriver' + f['fake_network'] = True + return f def _build_minimal_create_server_request(self): server = {} diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index cc3d555d0..d6e067c29 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -18,7 +18,6 @@ import unittest from nova import flags -from nova import test from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 2b5d3324a..ed6522c38 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -19,7 +19,6 @@ import time import unittest from nova import flags -from nova import test from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -32,8 +31,10 @@ FLAGS.verbose = True class ServersTest(integrated_helpers._IntegratedTestBase): - def _setup_flags(self): - self.flags(image_service='nova.image.fake.MockImageService') + def _get_flags(self): + f = super(ServersTest, self)._get_flags() + f['image_service'] = 'nova.image.fake.MockImageService' + return f def test_get_servers(self): """Simple check that listing servers works.""" diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index aa90301a5..701e9fe3c 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -19,7 +19,6 @@ import unittest import time from nova import flags -from nova import test from nova.log import logging from nova.tests.integrated import integrated_helpers from nova.tests.integrated.api import client @@ -37,10 +36,12 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): super(VolumesTest, self).setUp() driver.LoggingVolumeDriver.clear_logs() - def _setup_flags(self): - self.flags(image_service='nova.image.fake.MockImageService', - volume_driver='nova.volume.driver.LoggingVolumeDriver') - self.flags(use_local_volumes=False) # Avoids calling local_path + def _get_flags(self): + f = super(VolumesTest, self)._get_flags() + f['use_local_volumes'] = False # Avoids calling local_path + f['image_service'] = 'nova.image.fake.MockImageService' + f['volume_driver'] = 'nova.volume.driver.LoggingVolumeDriver' + return f def test_get_volumes(self): """Simple check that listing volumes works""" -- cgit From 83b25c2c8214462ab7f6b6ba76efdfba8c1de937 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 04:37:21 -0700 Subject: Grrr... because we're not recycling the API yet, we have to configure flags the first time it's called. --- nova/tests/integrated/integrated_helpers.py | 7 +++++-- nova/tests/integrated/test_volumes.py | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 3b7caecd6..953af2e75 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -19,6 +19,7 @@ Provides common functionality for integrated unit tests """ +import os import random import string @@ -255,9 +256,11 @@ class _IntegratedTestBase(test.TestCase): super(_IntegratedTestBase, self).tearDown() def _get_flags(self): - """An opportunity to setup flags, before the services are started""" + """An opportunity to setup flags, before the services are started + + Warning - this is a bit flaky till the WSGI recycle code lands""" f = {} - #f['network_driver'] = 'nova.network.fake.FakeNetworkDriver' + f['image_service'] = 'nova.image.fake.MockImageService' f['fake_network'] = True return f diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index 701e9fe3c..f173efea7 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -39,7 +39,6 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): def _get_flags(self): f = super(VolumesTest, self)._get_flags() f['use_local_volumes'] = False # Avoids calling local_path - f['image_service'] = 'nova.image.fake.MockImageService' f['volume_driver'] = 'nova.volume.driver.LoggingVolumeDriver' return f -- cgit From 4e5b511b422501167161c3bbe4dd755c0370c93f Mon Sep 17 00:00:00 2001 From: Ilya Alekseyev Date: Thu, 24 Mar 2011 16:53:32 +0300 Subject: couple of bugs fixed --- nova/tests/test_virt.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 98bb11526..12f97383e 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -803,7 +803,8 @@ class NWFilterTestCase(test.TestCase): 'instance_id': instance_ref['id']}) def _ensure_all_called(): - instance_filter = 'nova-instance-%s' % instance_ref['name'] + instance_filter = 'nova-instance-%s-%s' % (instance_ref['name'], + '00A0C914C829') secgroup_filter = 'nova-secgroup-%s' % self.security_group['id'] for required in [secgroup_filter, 'allow-dhcp-server', 'no-arp-spoofing', 'no-ip-spoofing', -- cgit From 96e8ef1049848563b60e457ab88adfb37b2dc473 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 24 Mar 2011 10:25:36 -0400 Subject: Couple of pep8 fixes. --- nova/tests/api/openstack/test_image_metadata.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index 81280bd97..46f7e5490 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -41,7 +41,7 @@ class ImageMetaDataTest(unittest.TestCase): 'disk_format': None, 'updated_at': '2011-03-22T17: 40: 15.591556', 'id': '1', - 'location': 'file: ///var/lib/glance/images/1', + 'location': 'file:///var/lib/glance/images/1', 'is_public': True, 'deleted_at': None, 'properties': { @@ -58,7 +58,7 @@ class ImageMetaDataTest(unittest.TestCase): 'disk_format': None, 'updated_at': '2011-03-22T17: 40: 15.591556', 'id': '2', - 'location': 'file: ///var/lib/glance/images/2', + 'location': 'file:///var/lib/glance/images/2', 'is_public': True, 'deleted_at': None, 'properties': { @@ -66,7 +66,7 @@ class ImageMetaDataTest(unittest.TestCase): 'key1': 'value1', 'key2': 'value2' }, - 'size': 5882349} + 'size': 5882349}, ] def setUp(self): -- cgit From fa6b969a2a7c9252aaebc4a56d82f9b04e46910c Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Thu, 24 Mar 2011 10:34:34 -0400 Subject: Merged trunk and fixed tests. --- nova/tests/api/openstack/test_images.py | 40 +++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index f64ee16a1..3a5d821d3 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -20,6 +20,7 @@ Tests of the new image services, both as a service layer, and as a WSGI layer """ +import copy import json import datetime import os @@ -193,6 +194,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """ # Registered images at start of each test. now = datetime.datetime.utcnow() + formated_date = now.strftime('%Y-%m-%dT%H:%M:%SZ') IMAGE_FIXTURES = [ {'id': '23g2ogk23k4hhkk4k42l', 'imageId': '23g2ogk23k4hhkk4k42l', @@ -256,13 +258,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): actual_image = json.loads(response.body) - expected = self.IMAGE_FIXTURES[0] + expected = copy.copy(self.IMAGE_FIXTURES[0]) expected_image = { "image": { "id": expected["id"], "name": expected["name"], - "updated": expected["updated_at"], - "created": expected["created_at"], + "updated": self.formated_date, + "created": self.formated_date, "status": expected["status"], }, } @@ -275,15 +277,15 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): actual_image = json.loads(response.body) - expected = self.IMAGE_FIXTURES[0] + expected = copy.copy(self.IMAGE_FIXTURES[0]) href = "http://localhost/v1.1/images/%s" % expected["id"] expected_image = { "image": { "id": expected["id"], "name": expected["name"], - "updated": expected["updated_at"], - "created": expected["created_at"], + "updated": self.formated_date, + "created": self.formated_date, "status": expected["status"], "links": [{ "rel": "self", @@ -311,7 +313,9 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): actual_image = parseString(response.body.replace(" ", "")) - expected = self.IMAGE_FIXTURES[0] + expected = copy.copy(self.IMAGE_FIXTURES[0]) + expected["updated_at"] = self.formated_date + expected["created_at"] = self.formated_date expected_image = parseString(""" Date: Thu, 24 Mar 2011 12:16:06 -0400 Subject: removing old Versions application and correcting fakes to use new controller --- nova/tests/api/openstack/fakes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 39e6db165..285f89efc 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -86,7 +86,7 @@ def wsgi_app(inner_app10=None, inner_app11=None): limits.RateLimitingMiddleware(inner_app11))) mapper['/v1.0'] = api10 mapper['/v1.1'] = api11 - mapper['/'] = openstack.FaultWrapper(openstack.Versions()) + mapper['/'] = openstack.FaultWrapper(versions.Versions()) return mapper -- cgit From 7baaace446c441fdd699018912ef7604265000ce Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 24 Mar 2011 16:36:37 +0000 Subject: Stubbing out utils.execute for migrate tests --- nova/tests/test_xenapi.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index fd8ed39d8..2ee385cff 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -558,6 +558,7 @@ class XenAPIMigrateInstance(test.TestCase): 'mac_address': 'aa:bb:cc:dd:ee:ff', 'os_type': 'linux'} + fake_utils.stub_out_utils_execute(self.stubs) stubs.stub_out_migration_methods(self.stubs) stubs.stubout_get_this_vm_uuid(self.stubs) glance_stubs.stubout_glance_client(self.stubs, -- cgit From b7150a461ab2aaee3c0a0f7e2b6588ddd4324b52 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Thu, 24 Mar 2011 16:38:31 +0000 Subject: Addressed issues raised by Rick Harris' review --- nova/tests/test_vmwareapi.py | 50 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index b31ac11f1..22b66010a 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -59,8 +59,7 @@ class VMWareAPIVMTestCase(test.TestCase): glance_stubs.FakeGlance) self.conn = vmwareapi_conn.get_connection(False) - def _create_vm(self): - """Create and spawn the VM.""" + def _create_instance_in_the_db(self): values = {'name': 1, 'id': 1, 'project_id': self.project.id, @@ -72,6 +71,10 @@ class VMWareAPIVMTestCase(test.TestCase): 'mac_address': 'aa:bb:cc:dd:ee:ff', } self.instance = db.instance_create(values) + + def _create_vm(self): + """Create and spawn the VM.""" + self._create_instance_in_the_db() self.type_data = db.instance_type_get_by_name(None, 'm1.large') self.conn.spawn(self.instance) self._check_vm_record() @@ -139,6 +142,11 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) + def test_snapshot_non_existent(self): + self._create_instance_in_the_db() + self.assertRaises(Exception, self.conn.snapshot, self.instance, + "Test-Snapshot") + def test_reboot(self): self._create_vm() info = self.conn.get_info(1) @@ -147,6 +155,19 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) + def test_reboot_non_existent(self): + self._create_instance_in_the_db() + self.assertRaises(Exception, self.conn.reboot, self.instance) + + def test_reboot_not_poweredon(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.conn.suspend(self.instance, self.dummy_callback_handler) + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.PAUSED) + self.assertRaises(Exception, self.conn.reboot, self.instance) + def test_suspend(self): self._create_vm() info = self.conn.get_info(1) @@ -155,6 +176,11 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.PAUSED) + def test_suspend_non_existent(self): + self._create_instance_in_the_db() + self.assertRaises(Exception, self.conn.suspend, self.instance, + self.dummy_callback_handler) + def test_resume(self): self._create_vm() info = self.conn.get_info(1) @@ -166,6 +192,18 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) + def test_resume_non_existent(self): + self._create_instance_in_the_db() + self.assertRaises(Exception, self.conn.resume, self.instance, + self.dummy_callback_handler) + + def test_resume_not_suspended(self): + self._create_vm() + info = self.conn.get_info(1) + self._check_vm_info(info, power_state.RUNNING) + self.assertRaises(Exception, self.conn.resume, self.instance, + self.dummy_callback_handler) + def test_get_info(self): self._create_vm() info = self.conn.get_info(1) @@ -176,10 +214,14 @@ class VMWareAPIVMTestCase(test.TestCase): info = self.conn.get_info(1) self._check_vm_info(info, power_state.RUNNING) instances = self.conn.list_instances() - self.assertTrue(len(instances) == 1) + self.assertEquals(len(instances), 1) self.conn.destroy(self.instance) instances = self.conn.list_instances() - self.assertTrue(len(instances) == 0) + self.assertEquals(len(instances), 0) + + def test_destroy_non_existent(self): + self._create_instance_in_the_db() + self.assertEquals(self.conn.destroy(self.instance), None) def test_pause(self): pass -- cgit From d91102e1ce73b5b2e1f5fbcc380814f1673cefa3 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 24 Mar 2011 12:46:41 -0400 Subject: get image metadata tests working after the datetime interface change in image services --- nova/tests/api/openstack/fakes.py | 8 ++++++-- nova/tests/api/openstack/test_image_metadata.py | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index 56143114d..7002c3a74 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -168,15 +168,19 @@ def stub_out_glance(stubs, initial_fixtures=None): id = ''.join(random.choice(string.letters) for _ in range(20)) image_meta['id'] = id self.fixtures.append(image_meta) - return image_meta + return copy.deepcopy(image_meta) def fake_update_image(self, image_id, image_meta, data=None): + for attr in ('created_at', 'updated_at', 'deleted_at', 'deleted'): + if attr in image_meta: + del image_meta[attr] + f = self._find_image(image_id) if not f: raise glance_exc.NotFound f.update(image_meta) - return f + return copy.deepcopy(f) def fake_delete_image(self, image_id): f = self._find_image(image_id) diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index 46f7e5490..33ef1a0a3 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -37,9 +37,9 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image1', 'deleted': False, 'container_format': None, - 'created_at': '2011-03-22T17: 40: 15.492626', + 'created_at': '2011-03-22T17:40:15.492626', 'disk_format': None, - 'updated_at': '2011-03-22T17: 40: 15.591556', + 'updated_at': '2011-03-22T17:40:15.591556', 'id': '1', 'location': 'file:///var/lib/glance/images/1', 'is_public': True, @@ -54,9 +54,9 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image2', 'deleted': False, 'container_format': None, - 'created_at': '2011-03-22T17: 40: 15.492626', + 'created_at': '2011-03-22T17:40:15.492626', 'disk_format': None, - 'updated_at': '2011-03-22T17: 40: 15.591556', + 'updated_at': '2011-03-22T17:40:15.591556', 'id': '2', 'location': 'file:///var/lib/glance/images/2', 'is_public': True, -- cgit From 12184874da4369891b2eae49982623fc6c9315e3 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 24 Mar 2011 13:26:57 -0400 Subject: Updated to use new APIRouterV11 class in tests. --- nova/tests/api/openstack/test_extensions.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index d1f8c659e..4bc823d15 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -81,14 +81,14 @@ class StubExtensionManager(object): class ExtensionControllerTest(unittest.TestCase): def test_index(self): - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/extensions") response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) def test_get_by_alias(self): - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/extensions/FOXNSOX") response = request.get_response(ext_midware) @@ -99,7 +99,7 @@ class ResourceExtensionTest(unittest.TestCase): def test_no_extension_present(self): manager = StubExtensionManager(None) - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/blah") response = request.get_response(ext_midware) @@ -109,7 +109,7 @@ class ResourceExtensionTest(unittest.TestCase): res_ext = extensions.ResourceExtension('tweedles', StubController(response_body)) manager = StubExtensionManager(res_ext) - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/tweedles") response = request.get_response(ext_midware) @@ -120,7 +120,7 @@ class ResourceExtensionTest(unittest.TestCase): res_ext = extensions.ResourceExtension('tweedles', StubController(response_body)) manager = StubExtensionManager(res_ext) - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app, manager) request = webob.Request.blank("/tweedles") response = request.get_response(ext_midware) @@ -137,7 +137,7 @@ class ExtensionManagerTest(unittest.TestCase): "extensions") def test_get_resources(self): - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank("/foxnsocks") response = request.get_response(ext_midware) @@ -152,7 +152,7 @@ class ActionExtensionTest(unittest.TestCase): "extensions") def _send_server_action_request(self, url, body): - app = openstack.APIRouter() + app = openstack.APIRouterV11() ext_midware = extensions.ExtensionMiddleware(app) request = webob.Request.blank(url) request.method = 'POST' -- cgit From 1ad0faf980ac89e904a246f1dfeddf51a21fd740 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Thu, 24 Mar 2011 13:48:04 -0400 Subject: Paginated results should not include the item starting at marker. Improved implementation of common.limited_by_marker as suggested by Matt Dietz. Added flag osapi_max_limit. --- nova/tests/api/openstack/test_servers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 09b08ce8d..cfed78b90 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -242,9 +242,8 @@ class ServersTest(test.TestCase): def test_get_servers_with_marker(self): req = webob.Request.blank('/v1.1/servers?marker=2') res = req.get_response(fakes.wsgi_app()) - print 'body:', res.body servers = json.loads(res.body)['servers'] - self.assertEqual([s['id'] for s in servers], [2, 3, 4]) + self.assertEqual([s['id'] for s in servers], [3, 4]) def _setup_for_create_instance(self): """Shared implementation for tests below that create instance""" -- cgit From a10f719cdbc666171d8923ae1fd65bac3d6ebda7 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 24 Mar 2011 10:49:19 -0700 Subject: Forgot one set of flags --- nova/tests/integrated/test_servers.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index ed6522c38..c4676adc8 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -31,11 +31,6 @@ FLAGS.verbose = True class ServersTest(integrated_helpers._IntegratedTestBase): - def _get_flags(self): - f = super(ServersTest, self)._get_flags() - f['image_service'] = 'nova.image.fake.MockImageService' - return f - def test_get_servers(self): """Simple check that listing servers works.""" servers = self.api.get_servers() -- cgit From 6254069cdf0262e128bfa877f0c56e5aeba2b4c2 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Thu, 24 Mar 2011 13:52:20 -0400 Subject: change names for consistency with existing db api --- nova/tests/api/openstack/test_server_metadata.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_server_metadata.py b/nova/tests/api/openstack/test_server_metadata.py index 97cb57ebd..c8d456472 100644 --- a/nova/tests/api/openstack/test_server_metadata.py +++ b/nova/tests/api/openstack/test_server_metadata.py @@ -68,7 +68,7 @@ class ServerMetaDataTest(unittest.TestCase): super(ServerMetaDataTest, self).tearDown() def test_index(self): - self.stubs.Set(nova.db.api, 'get_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) req = webob.Request.blank('/v1.1/servers/1/meta') req.environ['api.version'] = '1.1' @@ -78,7 +78,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual('value1', res_dict['metadata']['key1']) def test_index_no_data(self): - self.stubs.Set(nova.db.api, 'get_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_get', return_empty_server_metadata) req = webob.Request.blank('/v1.1/servers/1/meta') req.environ['api.version'] = '1.1' @@ -88,7 +88,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual(0, len(res_dict['metadata'])) def test_show(self): - self.stubs.Set(nova.db.api, 'get_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_get', return_server_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/key5') req.environ['api.version'] = '1.1' @@ -98,7 +98,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual('value5', res_dict['key5']) def test_show_meta_not_found(self): - self.stubs.Set(nova.db.api, 'get_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_get', return_empty_server_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/key6') req.environ['api.version'] = '1.1' @@ -107,7 +107,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual(404, res.status_int) def test_delete(self): - self.stubs.Set(nova.db.api, 'delete_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_delete', delete_server_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/key5') req.environ['api.version'] = '1.1' @@ -116,7 +116,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual(200, res.status_int) def test_create(self): - self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/meta') req.environ['api.version'] = '1.1' @@ -129,7 +129,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual('value1', res_dict['metadata']['key1']) def test_update_item(self): - self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/key1') req.environ['api.version'] = '1.1' @@ -142,7 +142,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual('value1', res_dict['key1']) def test_update_item_too_many_keys(self): - self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/key1') req.environ['api.version'] = '1.1' @@ -153,7 +153,7 @@ class ServerMetaDataTest(unittest.TestCase): self.assertEqual(400, res.status_int) def test_update_item_body_uri_mismatch(self): - self.stubs.Set(nova.db.api, 'update_or_create_instance_metadata', + self.stubs.Set(nova.db.api, 'instance_metadata_update_or_create', return_create_instance_metadata) req = webob.Request.blank('/v1.1/servers/1/meta/bad') req.environ['api.version'] = '1.1' -- cgit From e5069f27cd9e6551a6b035d6fff1b02a6bf0b492 Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Thu, 24 Mar 2011 13:56:25 -0400 Subject: Reconcile tests with latest trunk merges. --- nova/tests/api/openstack/extensions/foxinsocks.py | 4 ++-- nova/tests/api/openstack/test_extensions.py | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py index 249dd81bf..0860b51ac 100644 --- a/nova/tests/api/openstack/extensions/foxinsocks.py +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -73,7 +73,7 @@ class Foxinsocks(object): data['flavor']['googoose'] = "Gooey goo for chewy chewing!" return data - resp_ext = extensions.ResponseExtension('GET', '/v1.0/flavors/:(id)', + resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', _goose_handler) response_exts.append(resp_ext) @@ -84,7 +84,7 @@ class Foxinsocks(object): data['big_bands'] = 'Pig Bands!' return data - resp_ext2 = extensions.ResponseExtension('GET', '/v1.0/flavors/:(id)', + resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', _bands_handler) response_exts.append(resp_ext2) return response_exts diff --git a/nova/tests/api/openstack/test_extensions.py b/nova/tests/api/openstack/test_extensions.py index 4bc823d15..481d34ed1 100644 --- a/nova/tests/api/openstack/test_extensions.py +++ b/nova/tests/api/openstack/test_extensions.py @@ -193,6 +193,10 @@ class ResponseExtensionTest(unittest.TestCase): fakes.stub_out_auth(self.stubs) self.context = context.get_admin_context() + def tearDown(self): + self.stubs.UnsetAll() + super(ResponseExtensionTest, self).tearDown() + def test_get_resources_with_stub_mgr(self): test_resp = "Gooey goo for chewy chewing!" @@ -204,13 +208,14 @@ class ResponseExtensionTest(unittest.TestCase): return data resp_ext = extensions.ResponseExtension('GET', - '/v1.0/flavors/:(id)', + '/v1.1/flavors/:(id)', _resp_handler) manager = StubExtensionManager(None, None, resp_ext) app = fakes.wsgi_app() ext_midware = extensions.ExtensionMiddleware(app, manager) - request = webob.Request.blank("/v1.0/flavors/1") + request = webob.Request.blank("/v1.1/flavors/1") + request.environ['api.version'] = '1.1' response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) response_data = json.loads(response.body) @@ -222,10 +227,10 @@ class ResponseExtensionTest(unittest.TestCase): app = fakes.wsgi_app() ext_midware = extensions.ExtensionMiddleware(app) - request = webob.Request.blank("/v1.0/flavors/1") + request = webob.Request.blank("/v1.1/flavors/1") + request.environ['api.version'] = '1.1' response = request.get_response(ext_midware) self.assertEqual(200, response.status_int) response_data = json.loads(response.body) - print response_data self.assertEqual(test_resp, response_data['flavor']['googoose']) self.assertEqual("Pig Bands!", response_data['big_bands']) -- cgit From c7ccbd7a16a546cbd0717427772691ce7d8b4da6 Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 12:42:46 -0700 Subject: support volume and network in the direct api --- nova/tests/test_direct.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 80e4d2e1f..001246fc4 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -25,7 +25,9 @@ import webob from nova import compute from nova import context from nova import exception +from nova import network from nova import test +from nova import volume from nova import utils from nova.api import direct from nova.tests import test_cloud @@ -93,12 +95,20 @@ class DirectTestCase(test.TestCase): class DirectCloudTestCase(test_cloud.CloudTestCase): def setUp(self): super(DirectCloudTestCase, self).setUp() - compute_handle = compute.API(network_api=self.cloud.network_api, - volume_api=self.cloud.volume_api) + compute_handle = compute.API(image_service=self.cloud.image_service) + volume_handle = volume.API() + network_handle = network.API() direct.register_service('compute', compute_handle) + direct.register_service('volume', volume_handle) + direct.register_service('network', network_handle) + self.router = direct.JsonParamsMiddleware(direct.Router()) proxy = direct.Proxy(self.router) self.cloud.compute_api = proxy.compute + self.cloud.volume_api = proxy.volume + self.cloud.network_api = proxy.network + compute_handle.volume_api = proxy.volume + compute_handle.network_api = proxy.network def tearDown(self): super(DirectCloudTestCase, self).tearDown() -- cgit From 4a6db815b01c71076bae96c155396e5adbe8af90 Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 12:42:47 -0700 Subject: better error handling and serialization --- nova/tests/test_direct.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 001246fc4..383840234 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -33,6 +33,9 @@ from nova.api import direct from nova.tests import test_cloud +class ArbitraryObject(object): + pass + class FakeService(object): def echo(self, context, data): return {'data': data} @@ -41,6 +44,9 @@ class FakeService(object): return {'user': context.user_id, 'project': context.project_id} + def invalid_return(self, context): + return ArbitraryObject() + class DirectTestCase(test.TestCase): def setUp(self): @@ -86,6 +92,12 @@ class DirectTestCase(test.TestCase): resp_parsed = json.loads(resp.body) self.assertEqual(resp_parsed['data'], 'foo') + def test_invalid(self): + req = webob.Request.blank('/fake/invalid_return') + req.environ['openstack.context'] = self.context + req.method = 'POST' + self.assertRaises(exception.Error, req.get_response, self.router) + def test_proxy(self): proxy = direct.Proxy(self.router) rv = proxy.fake.echo(self.context, data='baz') -- cgit From c50e6c3879109d2e2e0c2f6b9c42195e9559993d Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Thu, 24 Mar 2011 16:18:50 -0400 Subject: Added test_get_servers_with_limit_and_marker to test pagination with marker and limit request params. --- nova/tests/api/openstack/test_servers.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index cfed78b90..c3ece939e 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -245,6 +245,12 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [3, 4]) + def test_get_servers_with_limit_and_marker(self): + req = webob.Request.blank('/v1.1/servers?limit=2&marker=1') + res = req.get_response(fakes.wsgi_app()) + servers = json.loads(res.body)['servers'] + self.assertEqual([s['id'] for s in servers], [2, 3]) + def _setup_for_create_instance(self): """Shared implementation for tests below that create instance""" def instance_create(context, inst): -- cgit From c5cbec20d2785d3060d57b55a264fbf936709500 Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 13:20:15 -0700 Subject: pep8 cleanups --- nova/tests/test_direct.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/tests') diff --git a/nova/tests/test_direct.py b/nova/tests/test_direct.py index 383840234..588a24b35 100644 --- a/nova/tests/test_direct.py +++ b/nova/tests/test_direct.py @@ -36,6 +36,7 @@ from nova.tests import test_cloud class ArbitraryObject(object): pass + class FakeService(object): def echo(self, context, data): return {'data': data} -- cgit From a6174e64b541560989c305b50787c96fb5890679 Mon Sep 17 00:00:00 2001 From: Naveed Massjouni Date: Thu, 24 Mar 2011 16:31:04 -0400 Subject: Added test_get_servers_with_bad_limit, test_get_servers_with_bad_offset and test_get_servers_with_bad_marker. --- nova/tests/api/openstack/test_servers.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index c3ece939e..c48cc5179 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -239,6 +239,18 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [1, 2]) + def test_get_servers_with_bad_limit(self): + req = webob.Request.blank('/v1.0/servers?limit=asdf&offset=1') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + self.assertTrue(res.body.find('limit param') > -1) + + def test_get_servers_with_bad_offset(self): + req = webob.Request.blank('/v1.0/servers?limit=2&offset=asdf') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + self.assertTrue(res.body.find('offset param') > -1) + def test_get_servers_with_marker(self): req = webob.Request.blank('/v1.1/servers?marker=2') res = req.get_response(fakes.wsgi_app()) @@ -251,6 +263,12 @@ class ServersTest(test.TestCase): servers = json.loads(res.body)['servers'] self.assertEqual([s['id'] for s in servers], [2, 3]) + def test_get_servers_with_bad_marker(self): + req = webob.Request.blank('/v1.1/servers?limit=2&marker=asdf') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + self.assertTrue(res.body.find('marker param') > -1) + def _setup_for_create_instance(self): """Shared implementation for tests below that create instance""" def instance_create(context, inst): -- cgit From acad7a627b92ffffb6bc76d9d72640e1d43f7e26 Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 16:37:35 -0700 Subject: rename objectstore tests --- nova/tests/objectstore_unittest.py | 315 ------------------------------------- nova/tests/test_objectstore.py | 315 +++++++++++++++++++++++++++++++++++++ 2 files changed, 315 insertions(+), 315 deletions(-) delete mode 100644 nova/tests/objectstore_unittest.py create mode 100644 nova/tests/test_objectstore.py (limited to 'nova/tests') diff --git a/nova/tests/objectstore_unittest.py b/nova/tests/objectstore_unittest.py deleted file mode 100644 index 4e2ac205e..000000000 --- a/nova/tests/objectstore_unittest.py +++ /dev/null @@ -1,315 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# 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. - -""" -Unittets for S3 objectstore clone. -""" - -import boto -import glob -import hashlib -import os -import shutil -import tempfile - -from boto.s3.connection import S3Connection, OrdinaryCallingFormat -from twisted.internet import reactor, threads, defer -from twisted.web import http, server - -from nova import context -from nova import flags -from nova import objectstore -from nova import test -from nova.auth import manager -from nova.exception import NotEmpty, NotFound -from nova.objectstore import image -from nova.objectstore.handler import S3 - - -FLAGS = flags.FLAGS - -# Create a unique temporary directory. We don't delete after test to -# allow checking the contents after running tests. Users and/or tools -# running the tests need to remove the tests directories. -OSS_TEMPDIR = tempfile.mkdtemp(prefix='test_oss-') - -# Create bucket/images path -os.makedirs(os.path.join(OSS_TEMPDIR, 'images')) -os.makedirs(os.path.join(OSS_TEMPDIR, 'buckets')) - - -class ObjectStoreTestCase(test.TestCase): - """Test objectstore API directly.""" - - def setUp(self): - """Setup users and projects.""" - super(ObjectStoreTestCase, self).setUp() - self.flags(buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), - images_path=os.path.join(OSS_TEMPDIR, 'images'), - ca_path=os.path.join(os.path.dirname(__file__), 'CA')) - - self.auth_manager = manager.AuthManager() - self.auth_manager.create_user('user1') - self.auth_manager.create_user('user2') - self.auth_manager.create_user('admin_user', admin=True) - self.auth_manager.create_project('proj1', 'user1', 'a proj', ['user1']) - self.auth_manager.create_project('proj2', 'user2', 'a proj', ['user2']) - self.context = context.RequestContext('user1', 'proj1') - - def tearDown(self): - """Tear down users and projects.""" - self.auth_manager.delete_project('proj1') - self.auth_manager.delete_project('proj2') - self.auth_manager.delete_user('user1') - self.auth_manager.delete_user('user2') - self.auth_manager.delete_user('admin_user') - super(ObjectStoreTestCase, self).tearDown() - - def test_buckets(self): - """Test the bucket API.""" - objectstore.bucket.Bucket.create('new_bucket', self.context) - bucket = objectstore.bucket.Bucket('new_bucket') - - # creator is authorized to use bucket - self.assert_(bucket.is_authorized(self.context)) - - # another user is not authorized - context2 = context.RequestContext('user2', 'proj2') - self.assertFalse(bucket.is_authorized(context2)) - - # admin is authorized to use bucket - admin_context = context.RequestContext('admin_user', None) - self.assertTrue(bucket.is_authorized(admin_context)) - - # new buckets are empty - self.assertTrue(bucket.list_keys()['Contents'] == []) - - # storing keys works - bucket['foo'] = "bar" - - self.assertEquals(len(bucket.list_keys()['Contents']), 1) - - self.assertEquals(bucket['foo'].read(), 'bar') - - # md5 of key works - self.assertEquals(bucket['foo'].md5, hashlib.md5('bar').hexdigest()) - - # deleting non-empty bucket should throw a NotEmpty exception - self.assertRaises(NotEmpty, bucket.delete) - - # deleting key - del bucket['foo'] - - # deleting empty bucket - bucket.delete() - - # accessing deleted bucket throws exception - self.assertRaises(NotFound, objectstore.bucket.Bucket, 'new_bucket') - - def test_images(self): - self.do_test_images('1mb.manifest.xml', True, - 'image_bucket1', 'i-testing1') - - def test_images_no_kernel_or_ramdisk(self): - self.do_test_images('1mb.no_kernel_or_ramdisk.manifest.xml', - False, 'image_bucket2', 'i-testing2') - - def do_test_images(self, manifest_file, expect_kernel_and_ramdisk, - image_bucket, image_name): - "Test the image API." - - # create a bucket for our bundle - objectstore.bucket.Bucket.create(image_bucket, self.context) - bucket = objectstore.bucket.Bucket(image_bucket) - - # upload an image manifest/parts - bundle_path = os.path.join(os.path.dirname(__file__), 'bundle') - for path in glob.glob(bundle_path + '/*'): - bucket[os.path.basename(path)] = open(path, 'rb').read() - - # register an image - image.Image.register_aws_image(image_name, - '%s/%s' % (image_bucket, manifest_file), - self.context) - - # verify image - my_img = image.Image(image_name) - result_image_file = os.path.join(my_img.path, 'image') - self.assertEqual(os.stat(result_image_file).st_size, 1048576) - - sha = hashlib.sha1(open(result_image_file).read()).hexdigest() - self.assertEqual(sha, '3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3') - - if expect_kernel_and_ramdisk: - # Verify the default kernel and ramdisk are set - self.assertEqual(my_img.metadata['kernelId'], 'aki-test') - self.assertEqual(my_img.metadata['ramdiskId'], 'ari-test') - else: - # Verify that the default kernel and ramdisk (the one from FLAGS) - # doesn't get embedded in the metadata - self.assertFalse('kernelId' in my_img.metadata) - self.assertFalse('ramdiskId' in my_img.metadata) - - # verify image permissions - context2 = context.RequestContext('user2', 'proj2') - self.assertFalse(my_img.is_authorized(context2)) - - # change user-editable fields - my_img.update_user_editable_fields({'display_name': 'my cool image'}) - self.assertEqual('my cool image', my_img.metadata['displayName']) - my_img.update_user_editable_fields({'display_name': ''}) - self.assert_(not my_img.metadata['displayName']) - - -class TestHTTPChannel(http.HTTPChannel): - """Dummy site required for twisted.web""" - - def checkPersistence(self, _, __): # pylint: disable=C0103 - """Otherwise we end up with an unclean reactor.""" - return False - - -class TestSite(server.Site): - """Dummy site required for twisted.web""" - protocol = TestHTTPChannel - - -class S3APITestCase(test.TestCase): - """Test objectstore through S3 API.""" - - def setUp(self): - """Setup users, projects, and start a test server.""" - super(S3APITestCase, self).setUp() - - FLAGS.auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' - FLAGS.buckets_path = os.path.join(OSS_TEMPDIR, 'buckets') - - self.auth_manager = manager.AuthManager() - self.admin_user = self.auth_manager.create_user('admin', admin=True) - self.admin_project = self.auth_manager.create_project('admin', - self.admin_user) - - shutil.rmtree(FLAGS.buckets_path) - os.mkdir(FLAGS.buckets_path) - - root = S3() - self.site = TestSite(root) - # pylint: disable=E1101 - self.listening_port = reactor.listenTCP(0, self.site, - interface='127.0.0.1') - # pylint: enable=E1101 - self.tcp_port = self.listening_port.getHost().port - - if not boto.config.has_section('Boto'): - boto.config.add_section('Boto') - boto.config.set('Boto', 'num_retries', '0') - self.conn = S3Connection(aws_access_key_id=self.admin_user.access, - aws_secret_access_key=self.admin_user.secret, - host='127.0.0.1', - port=self.tcp_port, - is_secure=False, - calling_format=OrdinaryCallingFormat()) - - def get_http_connection(host, is_secure): - """Get a new S3 connection, don't attempt to reuse connections.""" - return self.conn.new_http_connection(host, is_secure) - - self.conn.get_http_connection = get_http_connection - - def _ensure_no_buckets(self, buckets): # pylint: disable=C0111 - self.assertEquals(len(buckets), 0, "Bucket list was not empty") - return True - - def _ensure_one_bucket(self, buckets, name): # pylint: disable=C0111 - self.assertEquals(len(buckets), 1, - "Bucket list didn't have exactly one element in it") - self.assertEquals(buckets[0].name, name, "Wrong name") - return True - - def test_000_list_buckets(self): - """Make sure we are starting with no buckets.""" - deferred = threads.deferToThread(self.conn.get_all_buckets) - deferred.addCallback(self._ensure_no_buckets) - return deferred - - def test_001_create_and_delete_bucket(self): - """Test bucket creation and deletion.""" - bucket_name = 'testbucket' - - deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_all_buckets)) - - deferred.addCallback(self._ensure_one_bucket, bucket_name) - - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.delete_bucket, - bucket_name)) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_all_buckets)) - deferred.addCallback(self._ensure_no_buckets) - return deferred - - def test_002_create_bucket_and_key_and_delete_key_again(self): - """Test key operations on buckets.""" - bucket_name = 'testbucket' - key_name = 'somekey' - key_contents = 'somekey' - - deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) - deferred.addCallback(lambda b: - threads.deferToThread(b.new_key, key_name)) - deferred.addCallback(lambda k: - threads.deferToThread(k.set_contents_from_string, - key_contents)) - - def ensure_key_contents(bucket_name, key_name, contents): - """Verify contents for a key in the given bucket.""" - bucket = self.conn.get_bucket(bucket_name) - key = bucket.get_key(key_name) - self.assertEquals(key.get_contents_as_string(), contents, - "Bad contents") - - deferred.addCallback(lambda _: - threads.deferToThread(ensure_key_contents, - bucket_name, key_name, - key_contents)) - - def delete_key(bucket_name, key_name): - """Delete a key for the given bucket.""" - bucket = self.conn.get_bucket(bucket_name) - key = bucket.get_key(key_name) - key.delete() - - deferred.addCallback(lambda _: - threads.deferToThread(delete_key, bucket_name, - key_name)) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_bucket, - bucket_name)) - deferred.addCallback(lambda b: threads.deferToThread(b.get_all_keys)) - deferred.addCallback(self._ensure_no_buckets) - return deferred - - def tearDown(self): - """Tear down auth and test server.""" - self.auth_manager.delete_user('admin') - self.auth_manager.delete_project('admin') - stop_listening = defer.maybeDeferred(self.listening_port.stopListening) - super(S3APITestCase, self).tearDown() - return defer.DeferredList([stop_listening]) diff --git a/nova/tests/test_objectstore.py b/nova/tests/test_objectstore.py new file mode 100644 index 000000000..4e2ac205e --- /dev/null +++ b/nova/tests/test_objectstore.py @@ -0,0 +1,315 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# 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. + +""" +Unittets for S3 objectstore clone. +""" + +import boto +import glob +import hashlib +import os +import shutil +import tempfile + +from boto.s3.connection import S3Connection, OrdinaryCallingFormat +from twisted.internet import reactor, threads, defer +from twisted.web import http, server + +from nova import context +from nova import flags +from nova import objectstore +from nova import test +from nova.auth import manager +from nova.exception import NotEmpty, NotFound +from nova.objectstore import image +from nova.objectstore.handler import S3 + + +FLAGS = flags.FLAGS + +# Create a unique temporary directory. We don't delete after test to +# allow checking the contents after running tests. Users and/or tools +# running the tests need to remove the tests directories. +OSS_TEMPDIR = tempfile.mkdtemp(prefix='test_oss-') + +# Create bucket/images path +os.makedirs(os.path.join(OSS_TEMPDIR, 'images')) +os.makedirs(os.path.join(OSS_TEMPDIR, 'buckets')) + + +class ObjectStoreTestCase(test.TestCase): + """Test objectstore API directly.""" + + def setUp(self): + """Setup users and projects.""" + super(ObjectStoreTestCase, self).setUp() + self.flags(buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), + images_path=os.path.join(OSS_TEMPDIR, 'images'), + ca_path=os.path.join(os.path.dirname(__file__), 'CA')) + + self.auth_manager = manager.AuthManager() + self.auth_manager.create_user('user1') + self.auth_manager.create_user('user2') + self.auth_manager.create_user('admin_user', admin=True) + self.auth_manager.create_project('proj1', 'user1', 'a proj', ['user1']) + self.auth_manager.create_project('proj2', 'user2', 'a proj', ['user2']) + self.context = context.RequestContext('user1', 'proj1') + + def tearDown(self): + """Tear down users and projects.""" + self.auth_manager.delete_project('proj1') + self.auth_manager.delete_project('proj2') + self.auth_manager.delete_user('user1') + self.auth_manager.delete_user('user2') + self.auth_manager.delete_user('admin_user') + super(ObjectStoreTestCase, self).tearDown() + + def test_buckets(self): + """Test the bucket API.""" + objectstore.bucket.Bucket.create('new_bucket', self.context) + bucket = objectstore.bucket.Bucket('new_bucket') + + # creator is authorized to use bucket + self.assert_(bucket.is_authorized(self.context)) + + # another user is not authorized + context2 = context.RequestContext('user2', 'proj2') + self.assertFalse(bucket.is_authorized(context2)) + + # admin is authorized to use bucket + admin_context = context.RequestContext('admin_user', None) + self.assertTrue(bucket.is_authorized(admin_context)) + + # new buckets are empty + self.assertTrue(bucket.list_keys()['Contents'] == []) + + # storing keys works + bucket['foo'] = "bar" + + self.assertEquals(len(bucket.list_keys()['Contents']), 1) + + self.assertEquals(bucket['foo'].read(), 'bar') + + # md5 of key works + self.assertEquals(bucket['foo'].md5, hashlib.md5('bar').hexdigest()) + + # deleting non-empty bucket should throw a NotEmpty exception + self.assertRaises(NotEmpty, bucket.delete) + + # deleting key + del bucket['foo'] + + # deleting empty bucket + bucket.delete() + + # accessing deleted bucket throws exception + self.assertRaises(NotFound, objectstore.bucket.Bucket, 'new_bucket') + + def test_images(self): + self.do_test_images('1mb.manifest.xml', True, + 'image_bucket1', 'i-testing1') + + def test_images_no_kernel_or_ramdisk(self): + self.do_test_images('1mb.no_kernel_or_ramdisk.manifest.xml', + False, 'image_bucket2', 'i-testing2') + + def do_test_images(self, manifest_file, expect_kernel_and_ramdisk, + image_bucket, image_name): + "Test the image API." + + # create a bucket for our bundle + objectstore.bucket.Bucket.create(image_bucket, self.context) + bucket = objectstore.bucket.Bucket(image_bucket) + + # upload an image manifest/parts + bundle_path = os.path.join(os.path.dirname(__file__), 'bundle') + for path in glob.glob(bundle_path + '/*'): + bucket[os.path.basename(path)] = open(path, 'rb').read() + + # register an image + image.Image.register_aws_image(image_name, + '%s/%s' % (image_bucket, manifest_file), + self.context) + + # verify image + my_img = image.Image(image_name) + result_image_file = os.path.join(my_img.path, 'image') + self.assertEqual(os.stat(result_image_file).st_size, 1048576) + + sha = hashlib.sha1(open(result_image_file).read()).hexdigest() + self.assertEqual(sha, '3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3') + + if expect_kernel_and_ramdisk: + # Verify the default kernel and ramdisk are set + self.assertEqual(my_img.metadata['kernelId'], 'aki-test') + self.assertEqual(my_img.metadata['ramdiskId'], 'ari-test') + else: + # Verify that the default kernel and ramdisk (the one from FLAGS) + # doesn't get embedded in the metadata + self.assertFalse('kernelId' in my_img.metadata) + self.assertFalse('ramdiskId' in my_img.metadata) + + # verify image permissions + context2 = context.RequestContext('user2', 'proj2') + self.assertFalse(my_img.is_authorized(context2)) + + # change user-editable fields + my_img.update_user_editable_fields({'display_name': 'my cool image'}) + self.assertEqual('my cool image', my_img.metadata['displayName']) + my_img.update_user_editable_fields({'display_name': ''}) + self.assert_(not my_img.metadata['displayName']) + + +class TestHTTPChannel(http.HTTPChannel): + """Dummy site required for twisted.web""" + + def checkPersistence(self, _, __): # pylint: disable=C0103 + """Otherwise we end up with an unclean reactor.""" + return False + + +class TestSite(server.Site): + """Dummy site required for twisted.web""" + protocol = TestHTTPChannel + + +class S3APITestCase(test.TestCase): + """Test objectstore through S3 API.""" + + def setUp(self): + """Setup users, projects, and start a test server.""" + super(S3APITestCase, self).setUp() + + FLAGS.auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' + FLAGS.buckets_path = os.path.join(OSS_TEMPDIR, 'buckets') + + self.auth_manager = manager.AuthManager() + self.admin_user = self.auth_manager.create_user('admin', admin=True) + self.admin_project = self.auth_manager.create_project('admin', + self.admin_user) + + shutil.rmtree(FLAGS.buckets_path) + os.mkdir(FLAGS.buckets_path) + + root = S3() + self.site = TestSite(root) + # pylint: disable=E1101 + self.listening_port = reactor.listenTCP(0, self.site, + interface='127.0.0.1') + # pylint: enable=E1101 + self.tcp_port = self.listening_port.getHost().port + + if not boto.config.has_section('Boto'): + boto.config.add_section('Boto') + boto.config.set('Boto', 'num_retries', '0') + self.conn = S3Connection(aws_access_key_id=self.admin_user.access, + aws_secret_access_key=self.admin_user.secret, + host='127.0.0.1', + port=self.tcp_port, + is_secure=False, + calling_format=OrdinaryCallingFormat()) + + def get_http_connection(host, is_secure): + """Get a new S3 connection, don't attempt to reuse connections.""" + return self.conn.new_http_connection(host, is_secure) + + self.conn.get_http_connection = get_http_connection + + def _ensure_no_buckets(self, buckets): # pylint: disable=C0111 + self.assertEquals(len(buckets), 0, "Bucket list was not empty") + return True + + def _ensure_one_bucket(self, buckets, name): # pylint: disable=C0111 + self.assertEquals(len(buckets), 1, + "Bucket list didn't have exactly one element in it") + self.assertEquals(buckets[0].name, name, "Wrong name") + return True + + def test_000_list_buckets(self): + """Make sure we are starting with no buckets.""" + deferred = threads.deferToThread(self.conn.get_all_buckets) + deferred.addCallback(self._ensure_no_buckets) + return deferred + + def test_001_create_and_delete_bucket(self): + """Test bucket creation and deletion.""" + bucket_name = 'testbucket' + + deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) + deferred.addCallback(lambda _: + threads.deferToThread(self.conn.get_all_buckets)) + + deferred.addCallback(self._ensure_one_bucket, bucket_name) + + deferred.addCallback(lambda _: + threads.deferToThread(self.conn.delete_bucket, + bucket_name)) + deferred.addCallback(lambda _: + threads.deferToThread(self.conn.get_all_buckets)) + deferred.addCallback(self._ensure_no_buckets) + return deferred + + def test_002_create_bucket_and_key_and_delete_key_again(self): + """Test key operations on buckets.""" + bucket_name = 'testbucket' + key_name = 'somekey' + key_contents = 'somekey' + + deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) + deferred.addCallback(lambda b: + threads.deferToThread(b.new_key, key_name)) + deferred.addCallback(lambda k: + threads.deferToThread(k.set_contents_from_string, + key_contents)) + + def ensure_key_contents(bucket_name, key_name, contents): + """Verify contents for a key in the given bucket.""" + bucket = self.conn.get_bucket(bucket_name) + key = bucket.get_key(key_name) + self.assertEquals(key.get_contents_as_string(), contents, + "Bad contents") + + deferred.addCallback(lambda _: + threads.deferToThread(ensure_key_contents, + bucket_name, key_name, + key_contents)) + + def delete_key(bucket_name, key_name): + """Delete a key for the given bucket.""" + bucket = self.conn.get_bucket(bucket_name) + key = bucket.get_key(key_name) + key.delete() + + deferred.addCallback(lambda _: + threads.deferToThread(delete_key, bucket_name, + key_name)) + deferred.addCallback(lambda _: + threads.deferToThread(self.conn.get_bucket, + bucket_name)) + deferred.addCallback(lambda b: threads.deferToThread(b.get_all_keys)) + deferred.addCallback(self._ensure_no_buckets) + return deferred + + def tearDown(self): + """Tear down auth and test server.""" + self.auth_manager.delete_user('admin') + self.auth_manager.delete_project('admin') + stop_listening = defer.maybeDeferred(self.listening_port.stopListening) + super(S3APITestCase, self).tearDown() + return defer.DeferredList([stop_listening]) -- cgit From 2b243dbb2e12a7f510a7c6c01298884fa8927c12 Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 16:38:30 -0700 Subject: port the objectstore tests to the new tests --- nova/tests/test_objectstore.py | 247 +++++++---------------------------------- 1 file changed, 41 insertions(+), 206 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_objectstore.py b/nova/tests/test_objectstore.py index 4e2ac205e..c4d344503 100644 --- a/nova/tests/test_objectstore.py +++ b/nova/tests/test_objectstore.py @@ -27,18 +27,18 @@ import os import shutil import tempfile -from boto.s3.connection import S3Connection, OrdinaryCallingFormat -from twisted.internet import reactor, threads, defer -from twisted.web import http, server +from boto import exception as boto_exception +from boto.s3 import connection as s3 from nova import context +from nova import exception from nova import flags from nova import objectstore +from nova import wsgi from nova import test from nova.auth import manager -from nova.exception import NotEmpty, NotFound -from nova.objectstore import image -from nova.objectstore.handler import S3 +#from nova.exception import NotEmpty, NotFound +from nova.objectstore import s3server FLAGS = flags.FLAGS @@ -53,151 +53,15 @@ os.makedirs(os.path.join(OSS_TEMPDIR, 'images')) os.makedirs(os.path.join(OSS_TEMPDIR, 'buckets')) -class ObjectStoreTestCase(test.TestCase): - """Test objectstore API directly.""" - - def setUp(self): - """Setup users and projects.""" - super(ObjectStoreTestCase, self).setUp() - self.flags(buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), - images_path=os.path.join(OSS_TEMPDIR, 'images'), - ca_path=os.path.join(os.path.dirname(__file__), 'CA')) - - self.auth_manager = manager.AuthManager() - self.auth_manager.create_user('user1') - self.auth_manager.create_user('user2') - self.auth_manager.create_user('admin_user', admin=True) - self.auth_manager.create_project('proj1', 'user1', 'a proj', ['user1']) - self.auth_manager.create_project('proj2', 'user2', 'a proj', ['user2']) - self.context = context.RequestContext('user1', 'proj1') - - def tearDown(self): - """Tear down users and projects.""" - self.auth_manager.delete_project('proj1') - self.auth_manager.delete_project('proj2') - self.auth_manager.delete_user('user1') - self.auth_manager.delete_user('user2') - self.auth_manager.delete_user('admin_user') - super(ObjectStoreTestCase, self).tearDown() - - def test_buckets(self): - """Test the bucket API.""" - objectstore.bucket.Bucket.create('new_bucket', self.context) - bucket = objectstore.bucket.Bucket('new_bucket') - - # creator is authorized to use bucket - self.assert_(bucket.is_authorized(self.context)) - - # another user is not authorized - context2 = context.RequestContext('user2', 'proj2') - self.assertFalse(bucket.is_authorized(context2)) - - # admin is authorized to use bucket - admin_context = context.RequestContext('admin_user', None) - self.assertTrue(bucket.is_authorized(admin_context)) - - # new buckets are empty - self.assertTrue(bucket.list_keys()['Contents'] == []) - - # storing keys works - bucket['foo'] = "bar" - - self.assertEquals(len(bucket.list_keys()['Contents']), 1) - - self.assertEquals(bucket['foo'].read(), 'bar') - - # md5 of key works - self.assertEquals(bucket['foo'].md5, hashlib.md5('bar').hexdigest()) - - # deleting non-empty bucket should throw a NotEmpty exception - self.assertRaises(NotEmpty, bucket.delete) - - # deleting key - del bucket['foo'] - - # deleting empty bucket - bucket.delete() - - # accessing deleted bucket throws exception - self.assertRaises(NotFound, objectstore.bucket.Bucket, 'new_bucket') - - def test_images(self): - self.do_test_images('1mb.manifest.xml', True, - 'image_bucket1', 'i-testing1') - - def test_images_no_kernel_or_ramdisk(self): - self.do_test_images('1mb.no_kernel_or_ramdisk.manifest.xml', - False, 'image_bucket2', 'i-testing2') - - def do_test_images(self, manifest_file, expect_kernel_and_ramdisk, - image_bucket, image_name): - "Test the image API." - - # create a bucket for our bundle - objectstore.bucket.Bucket.create(image_bucket, self.context) - bucket = objectstore.bucket.Bucket(image_bucket) - - # upload an image manifest/parts - bundle_path = os.path.join(os.path.dirname(__file__), 'bundle') - for path in glob.glob(bundle_path + '/*'): - bucket[os.path.basename(path)] = open(path, 'rb').read() - - # register an image - image.Image.register_aws_image(image_name, - '%s/%s' % (image_bucket, manifest_file), - self.context) - - # verify image - my_img = image.Image(image_name) - result_image_file = os.path.join(my_img.path, 'image') - self.assertEqual(os.stat(result_image_file).st_size, 1048576) - - sha = hashlib.sha1(open(result_image_file).read()).hexdigest() - self.assertEqual(sha, '3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3') - - if expect_kernel_and_ramdisk: - # Verify the default kernel and ramdisk are set - self.assertEqual(my_img.metadata['kernelId'], 'aki-test') - self.assertEqual(my_img.metadata['ramdiskId'], 'ari-test') - else: - # Verify that the default kernel and ramdisk (the one from FLAGS) - # doesn't get embedded in the metadata - self.assertFalse('kernelId' in my_img.metadata) - self.assertFalse('ramdiskId' in my_img.metadata) - - # verify image permissions - context2 = context.RequestContext('user2', 'proj2') - self.assertFalse(my_img.is_authorized(context2)) - - # change user-editable fields - my_img.update_user_editable_fields({'display_name': 'my cool image'}) - self.assertEqual('my cool image', my_img.metadata['displayName']) - my_img.update_user_editable_fields({'display_name': ''}) - self.assert_(not my_img.metadata['displayName']) - - -class TestHTTPChannel(http.HTTPChannel): - """Dummy site required for twisted.web""" - - def checkPersistence(self, _, __): # pylint: disable=C0103 - """Otherwise we end up with an unclean reactor.""" - return False - - -class TestSite(server.Site): - """Dummy site required for twisted.web""" - protocol = TestHTTPChannel - - class S3APITestCase(test.TestCase): """Test objectstore through S3 API.""" def setUp(self): """Setup users, projects, and start a test server.""" super(S3APITestCase, self).setUp() - - FLAGS.auth_driver = 'nova.auth.ldapdriver.FakeLdapDriver' - FLAGS.buckets_path = os.path.join(OSS_TEMPDIR, 'buckets') + self.flags(auth_driver='nova.auth.ldapdriver.FakeLdapDriver', + buckets_path=os.path.join(OSS_TEMPDIR, 'buckets'), + s3_host='127.0.0.1') self.auth_manager = manager.AuthManager() self.admin_user = self.auth_manager.create_user('admin', admin=True) @@ -207,23 +71,20 @@ class S3APITestCase(test.TestCase): shutil.rmtree(FLAGS.buckets_path) os.mkdir(FLAGS.buckets_path) - root = S3() - self.site = TestSite(root) - # pylint: disable=E1101 - self.listening_port = reactor.listenTCP(0, self.site, - interface='127.0.0.1') - # pylint: enable=E1101 - self.tcp_port = self.listening_port.getHost().port + router = s3server.S3Application(FLAGS.buckets_path) + server = wsgi.Server() + server.start(router, FLAGS.s3_port, host=FLAGS.s3_host) if not boto.config.has_section('Boto'): boto.config.add_section('Boto') boto.config.set('Boto', 'num_retries', '0') - self.conn = S3Connection(aws_access_key_id=self.admin_user.access, - aws_secret_access_key=self.admin_user.secret, - host='127.0.0.1', - port=self.tcp_port, - is_secure=False, - calling_format=OrdinaryCallingFormat()) + conn = s3.S3Connection(aws_access_key_id=self.admin_user.access, + aws_secret_access_key=self.admin_user.secret, + host=FLAGS.s3_host, + port=FLAGS.s3_port, + is_secure=False, + calling_format=s3.OrdinaryCallingFormat()) + self.conn = conn def get_http_connection(host, is_secure): """Get a new S3 connection, don't attempt to reuse connections.""" @@ -243,27 +104,16 @@ class S3APITestCase(test.TestCase): def test_000_list_buckets(self): """Make sure we are starting with no buckets.""" - deferred = threads.deferToThread(self.conn.get_all_buckets) - deferred.addCallback(self._ensure_no_buckets) - return deferred + self._ensure_no_buckets(self.conn.get_all_buckets()) def test_001_create_and_delete_bucket(self): """Test bucket creation and deletion.""" bucket_name = 'testbucket' - deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_all_buckets)) - - deferred.addCallback(self._ensure_one_bucket, bucket_name) - - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.delete_bucket, - bucket_name)) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_all_buckets)) - deferred.addCallback(self._ensure_no_buckets) - return deferred + self.conn.create_bucket(bucket_name) + self._ensure_one_bucket(self.conn.get_all_buckets(), bucket_name) + self.conn.delete_bucket(bucket_name) + self._ensure_no_buckets(self.conn.get_all_buckets()) def test_002_create_bucket_and_key_and_delete_key_again(self): """Test key operations on buckets.""" @@ -271,45 +121,30 @@ class S3APITestCase(test.TestCase): key_name = 'somekey' key_contents = 'somekey' - deferred = threads.deferToThread(self.conn.create_bucket, bucket_name) - deferred.addCallback(lambda b: - threads.deferToThread(b.new_key, key_name)) - deferred.addCallback(lambda k: - threads.deferToThread(k.set_contents_from_string, - key_contents)) + b = self.conn.create_bucket(bucket_name) + k = b.new_key(key_name) + k.set_contents_from_string(key_contents) + + bucket = self.conn.get_bucket(bucket_name) - def ensure_key_contents(bucket_name, key_name, contents): - """Verify contents for a key in the given bucket.""" - bucket = self.conn.get_bucket(bucket_name) - key = bucket.get_key(key_name) - self.assertEquals(key.get_contents_as_string(), contents, - "Bad contents") + # make sure the contents are correct + key = bucket.get_key(key_name) + self.assertEquals(key.get_contents_as_string(), key_contents, + "Bad contents") - deferred.addCallback(lambda _: - threads.deferToThread(ensure_key_contents, - bucket_name, key_name, - key_contents)) + # delete the key + key.delete() - def delete_key(bucket_name, key_name): - """Delete a key for the given bucket.""" - bucket = self.conn.get_bucket(bucket_name) - key = bucket.get_key(key_name) - key.delete() + self._ensure_no_buckets(bucket.get_all_keys()) - deferred.addCallback(lambda _: - threads.deferToThread(delete_key, bucket_name, - key_name)) - deferred.addCallback(lambda _: - threads.deferToThread(self.conn.get_bucket, - bucket_name)) - deferred.addCallback(lambda b: threads.deferToThread(b.get_all_keys)) - deferred.addCallback(self._ensure_no_buckets) - return deferred + def test_unknown_bucket(self): + bucket_name = 'falalala' + self.assertRaises(boto_exception.S3ResponseError, + self.conn.get_bucket, + bucket_name) def tearDown(self): """Tear down auth and test server.""" self.auth_manager.delete_user('admin') self.auth_manager.delete_project('admin') - stop_listening = defer.maybeDeferred(self.listening_port.stopListening) super(S3APITestCase, self).tearDown() - return defer.DeferredList([stop_listening]) -- cgit From bab306061618e911971c4f7275824df60d1b42fd Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 16:38:30 -0700 Subject: remove twisted objectstore --- nova/tests/test_cloud.py | 49 +++--------------------------------------- nova/tests/test_objectstore.py | 2 -- 2 files changed, 3 insertions(+), 48 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py index cf8ee7eff..00803d0ad 100644 --- a/nova/tests/test_cloud.py +++ b/nova/tests/test_cloud.py @@ -35,31 +35,22 @@ from nova import log as logging from nova import rpc from nova import service from nova import test +from nova import utils 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.objectstore import image FLAGS = flags.FLAGS LOG = logging.getLogger('nova.tests.cloud') -# Temp dirs for working with image attributes through the cloud controller -# (stole this from objectstore_unittest.py) -OSS_TEMPDIR = tempfile.mkdtemp(prefix='test_oss-') -IMAGES_PATH = os.path.join(OSS_TEMPDIR, 'images') -os.makedirs(IMAGES_PATH) - -# TODO(termie): these tests are rather fragile, they should at the lest be -# wiping database state after each run class CloudTestCase(test.TestCase): def setUp(self): super(CloudTestCase, self).setUp() - self.flags(connection_type='fake', - images_path=IMAGES_PATH) + self.flags(connection_type='fake') self.conn = rpc.Connection.instance() @@ -70,6 +61,7 @@ class CloudTestCase(test.TestCase): self.compute = self.start_service('compute') self.scheduter = self.start_service('scheduler') self.network = self.start_service('network') + self.image_service = utils.import_object(FLAGS.image_service) self.manager = manager.AuthManager() self.user = self.manager.create_user('admin', 'admin', 'admin', True) @@ -318,41 +310,6 @@ class CloudTestCase(test.TestCase): LOG.debug(_("Terminating instance %s"), instance_id) rv = self.compute.terminate_instance(instance_id) - @staticmethod - def _fake_set_image_description(ctxt, image_id, description): - from nova.objectstore import handler - - class req: - pass - - request = req() - request.context = ctxt - request.args = {'image_id': [image_id], - 'description': [description]} - - resource = handler.ImagesResource() - resource.render_POST(request) - - def test_user_editable_image_endpoint(self): - pathdir = os.path.join(FLAGS.images_path, 'ami-testing') - os.mkdir(pathdir) - info = {'isPublic': False} - with open(os.path.join(pathdir, 'info.json'), 'w') as f: - json.dump(info, f) - img = image.Image('ami-testing') - # self.cloud.set_image_description(self.context, 'ami-testing', - # 'Foo Img') - # NOTE(vish): Above won't work unless we start objectstore or create - # a fake version of api/ec2/images.py conn that can - # call methods directly instead of going through boto. - # for now, just cheat and call the method directly - self._fake_set_image_description(self.context, 'ami-testing', - 'Foo Img') - self.assertEqual('Foo Img', img.metadata['description']) - self._fake_set_image_description(self.context, 'ami-testing', '') - self.assertEqual('', img.metadata['description']) - shutil.rmtree(pathdir) - def test_update_of_instance_display_fields(self): inst = db.instance_create(self.context, {}) ec2_id = ec2utils.id_to_ec2_id(inst['id']) diff --git a/nova/tests/test_objectstore.py b/nova/tests/test_objectstore.py index c4d344503..c78772f27 100644 --- a/nova/tests/test_objectstore.py +++ b/nova/tests/test_objectstore.py @@ -33,11 +33,9 @@ from boto.s3 import connection as s3 from nova import context from nova import exception from nova import flags -from nova import objectstore from nova import wsgi from nova import test from nova.auth import manager -#from nova.exception import NotEmpty, NotFound from nova.objectstore import s3server -- cgit From 9da833ff9298a00ba33ca67885a7a663a3b9e35f Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 24 Mar 2011 16:38:31 -0700 Subject: don't require integrated tests to recycle connections --- nova/tests/integrated/integrated_helpers.py | 42 ----------------------------- nova/tests/integrated/test_login.py | 6 ++--- 2 files changed, 3 insertions(+), 45 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 47093636e..cc7326e73 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -75,8 +75,6 @@ class TestUser(object): class IntegratedUnitTestContext(object): - __INSTANCE = None - def __init__(self): self.auth_manager = manager.AuthManager() @@ -92,7 +90,6 @@ class IntegratedUnitTestContext(object): def setup(self): self._start_services() - self._create_test_user() def _create_test_user(self): @@ -109,14 +106,6 @@ class IntegratedUnitTestContext(object): self._start_api_service() def cleanup(self): - for service in self.services: - service.kill() - self.services = [] - # TODO(justinsb): Shutdown WSGI & anything else we startup - # bug731668 - # WSGI shutdown broken :-( - # self.wsgi_server.terminate() - # self.wsgi_server = None self.test_user = None def _create_unittest_user(self): @@ -150,39 +139,8 @@ class IntegratedUnitTestContext(object): if not api_service: raise Exception("API Service was None") - # WSGI shutdown broken :-( - #self.services.append(volume_service) self.api_service = api_service self.auth_url = 'http://localhost:8774/v1.0' return api_service - - # WSGI shutdown broken :-( - # bug731668 - #@staticmethod - #def get(): - # if not IntegratedUnitTestContext.__INSTANCE: - # IntegratedUnitTestContext.startup() - # #raise Error("Must call IntegratedUnitTestContext::startup") - # return IntegratedUnitTestContext.__INSTANCE - - @staticmethod - def startup(): - # Because WSGI shutdown is broken at the moment, we have to recycle - # bug731668 - if IntegratedUnitTestContext.__INSTANCE: - #raise Error("Multiple calls to IntegratedUnitTestContext.startup") - IntegratedUnitTestContext.__INSTANCE.setup() - else: - IntegratedUnitTestContext.__INSTANCE = IntegratedUnitTestContext() - return IntegratedUnitTestContext.__INSTANCE - - @staticmethod - def shutdown(): - if not IntegratedUnitTestContext.__INSTANCE: - raise Error("Must call IntegratedUnitTestContext::startup") - IntegratedUnitTestContext.__INSTANCE.cleanup() - # WSGI shutdown broken :-( - # bug731668 - #IntegratedUnitTestContext.__INSTANCE = None diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index 501f8c919..6b241f240 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -33,12 +33,12 @@ FLAGS.verbose = True class LoginTest(test.TestCase): def setUp(self): super(LoginTest, self).setUp() - context = integrated_helpers.IntegratedUnitTestContext.startup() - self.user = context.test_user + self.context = integrated_helpers.IntegratedUnitTestContext() + self.user = self.context.test_user self.api = self.user.openstack_api def tearDown(self): - integrated_helpers.IntegratedUnitTestContext.shutdown() + self.context.cleanup() super(LoginTest, self).tearDown() def test_login(self): -- cgit From 73df3e0cd54dc3b5409fba7b38ada6ee07bd911d Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Fri, 25 Mar 2011 01:23:33 +0000 Subject: minor pep8 fix in db/fakes.py --- nova/tests/db/fakes.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index c46b75aa2..21a5481bd 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -108,9 +108,7 @@ def stub_out_db_instance_api(stubs, injected=True): return FakeModel(fixed_ip_fields).address def fake_fixed_ip_get_all_by_instance(context, instance_id): - l = [] - l.append(FakeModel(fixed_ip_fields)) - return l + return [FakeModel(fixed_ip_fields)] stubs.Set(db, 'network_get_by_instance', fake_network_get_by_instance) stubs.Set(db, 'instance_type_get_all', fake_instance_type_get_all) -- cgit From ccf4727ca16d7a67c6a35950ab378ab4615dbdad Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Fri, 25 Mar 2011 04:41:47 +0000 Subject: disk_format is now an ImageService property --- nova/tests/api/openstack/test_servers.py | 57 ++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index c48cc5179..3c117f10c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -26,6 +26,7 @@ import webob from nova import context from nova import db +from nova import exception from nova import flags from nova import test import nova.api.openstack @@ -1260,3 +1261,59 @@ class TestServerInstanceCreation(test.TestCase): server = dom.childNodes[0] self.assertEquals(server.nodeName, 'server') self.assertTrue(server.getAttribute('adminPass').startswith('fake')) + + +class TestGetKernelRamdiskFromImage(test.TestCase): + """ + If we're building from an AMI-style image, we need to be able to fetch the + kernel and ramdisk associated with the machine image. This information is + stored with the image metadata and return via the ImageService. + + These tests ensure that we parse the metadata return the ImageService + correctly and that we handle failure modes appropriately. + """ + + def test_status_not_active(self): + """We should only allow fetching of kernel and ramdisk information if + we have a 'fully-formed' image, aka 'active' + """ + image_meta = {'id': 1, 'status': 'queued'} + self.assertRaises(exception.Invalid, self._get_k_r, image_meta) + + def test_not_ami(self): + """Anything other than ami should return no kernel and no ramdisk""" + image_meta = {'id': 1, 'status': 'active', + 'properties': {'disk_format': 'vhd'}} + kernel_id, ramdisk_id = self._get_k_r(image_meta) + self.assertEqual(kernel_id, None) + self.assertEqual(ramdisk_id, None) + + def test_ami_no_kernel(self): + """If an ami is missing a kernel it should raise NotFound""" + image_meta = {'id': 1, 'status': 'active', + 'properties': {'disk_format': 'ami', 'ramdisk_id': 1}} + self.assertRaises(exception.NotFound, self._get_k_r, image_meta) + + def test_ami_no_ramdisk(self): + """If an ami is missing a ramdisk it should raise NotFound""" + image_meta = {'id': 1, 'status': 'active', + 'properties': {'disk_format': 'ami', 'kernel_id': 1}} + self.assertRaises(exception.NotFound, self._get_k_r, image_meta) + + def test_ami_kernel_ramdisk_present(self): + """Return IDs if both kernel and ramdisk are present""" + image_meta = {'id': 1, 'status': 'active', + 'properties': {'disk_format': 'ami', 'kernel_id': 1, + 'ramdisk_id': 2}} + kernel_id, ramdisk_id = self._get_k_r(image_meta) + self.assertEqual(kernel_id, 1) + self.assertEqual(ramdisk_id, 2) + + @staticmethod + def _get_k_r(image_meta): + """Rebinding function to a shorter name for convenience""" + kernel_id, ramdisk_id = \ + servers.Controller._do_get_kernel_ramdisk_from_image(image_meta) + return kernel_id, ramdisk_id + + -- cgit From b6745341ec06cb0a0de7963f6b4606f4ad6f8c89 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 24 Mar 2011 23:49:14 -0500 Subject: pep8 fix --- nova/tests/api/openstack/test_servers.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 3c117f10c..3dac7a1b1 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -1315,5 +1315,3 @@ class TestGetKernelRamdiskFromImage(test.TestCase): kernel_id, ramdisk_id = \ servers.Controller._do_get_kernel_ramdisk_from_image(image_meta) return kernel_id, ramdisk_id - - -- cgit From f533c441c0062d05c7c361208016e56ca8f5e9df Mon Sep 17 00:00:00 2001 From: Dan Prince Date: Fri, 25 Mar 2011 09:28:36 -0400 Subject: Fix unit tests w/ latest trunk merge. --- nova/tests/api/openstack/test_image_metadata.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_image_metadata.py b/nova/tests/api/openstack/test_image_metadata.py index 33ef1a0a3..9be753f84 100644 --- a/nova/tests/api/openstack/test_image_metadata.py +++ b/nova/tests/api/openstack/test_image_metadata.py @@ -37,9 +37,9 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image1', 'deleted': False, 'container_format': None, - 'created_at': '2011-03-22T17:40:15.492626', + 'created_at': '2011-03-22T17:40:15', 'disk_format': None, - 'updated_at': '2011-03-22T17:40:15.591556', + 'updated_at': '2011-03-22T17:40:15', 'id': '1', 'location': 'file:///var/lib/glance/images/1', 'is_public': True, @@ -54,9 +54,9 @@ class ImageMetaDataTest(unittest.TestCase): 'name': 'image2', 'deleted': False, 'container_format': None, - 'created_at': '2011-03-22T17:40:15.492626', + 'created_at': '2011-03-22T17:40:15', 'disk_format': None, - 'updated_at': '2011-03-22T17:40:15.591556', + 'updated_at': '2011-03-22T17:40:15', 'id': '2', 'location': 'file:///var/lib/glance/images/2', 'is_public': True, -- cgit From ec524aae3224a806fa41f6ae6c2975a1ba124f15 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 25 Mar 2011 15:18:57 +0100 Subject: Toss an __init__ in the test extensions dir. This gets it included in the tarball. --- nova/tests/api/openstack/extensions/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 nova/tests/api/openstack/extensions/__init__.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/__init__.py b/nova/tests/api/openstack/extensions/__init__.py new file mode 100644 index 000000000..e69de29bb -- cgit From af8aa36ca07c5e51016df68c0acc7449378fac2f Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Fri, 25 Mar 2011 18:23:36 +0100 Subject: Add license and copyright to nova/tests/api/openstack/extensions/__init__.py --- nova/tests/api/openstack/extensions/__init__.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/__init__.py b/nova/tests/api/openstack/extensions/__init__.py index e69de29bb..848908a95 100644 --- a/nova/tests/api/openstack/extensions/__init__.py +++ b/nova/tests/api/openstack/extensions/__init__.py @@ -0,0 +1,15 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC +# +# 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. -- cgit From 51c07f77686473bc73c700aacc7baeecf278a948 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 25 Mar 2011 16:57:21 -0400 Subject: Removed print. --- nova/tests/api/openstack/test_images.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index b51a52cfe..3bf710d1a 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -642,7 +642,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): def test_get_image_found(self): req = webob.Request.blank('/v1.0/images/123') res = req.get_response(fakes.wsgi_app()) - print self.fixtures image_meta = json.loads(res.body)['image'] expected = {'id': 123, 'name': 'public image', 'updated': self.NOW_API_FORMAT, -- cgit From cd1bac4deff367131d43f87cdfbc3b6b34bbdc1e Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 25 Mar 2011 16:39:43 -0700 Subject: Initial extensification of volumes --- nova/tests/api/openstack/extensions/foxinsocks.py | 98 ---------------------- .../openstack/extensions/foxinsocks/__init__.py | 19 +++++ .../openstack/extensions/foxinsocks/foxinsocks.py | 98 ++++++++++++++++++++++ 3 files changed, 117 insertions(+), 98 deletions(-) delete mode 100644 nova/tests/api/openstack/extensions/foxinsocks.py create mode 100644 nova/tests/api/openstack/extensions/foxinsocks/__init__.py create mode 100644 nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py deleted file mode 100644 index 0860b51ac..000000000 --- a/nova/tests/api/openstack/extensions/foxinsocks.py +++ /dev/null @@ -1,98 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -import json - -from nova import wsgi - -from nova.api.openstack import extensions - - -class FoxInSocksController(wsgi.Controller): - - def index(self, req): - return "Try to say this Mr. Knox, sir..." - - -class Foxinsocks(object): - - def __init__(self): - pass - - def get_name(self): - return "Fox In Socks" - - def get_alias(self): - return "FOXNSOX" - - def get_description(self): - return "The Fox In Socks Extension" - - def get_namespace(self): - return "http://www.fox.in.socks/api/ext/pie/v1.0" - - def get_updated(self): - return "2011-01-22T13:25:27-06:00" - - def get_resources(self): - resources = [] - resource = extensions.ResourceExtension('foxnsocks', - FoxInSocksController()) - resources.append(resource) - return resources - - def get_actions(self): - actions = [] - actions.append(extensions.ActionExtension('servers', 'add_tweedle', - self._add_tweedle)) - actions.append(extensions.ActionExtension('servers', 'delete_tweedle', - self._delete_tweedle)) - return actions - - def get_response_extensions(self): - response_exts = [] - - def _goose_handler(res): - #NOTE: This only handles JSON responses. - # You can use content type header to test for XML. - data = json.loads(res.body) - data['flavor']['googoose'] = "Gooey goo for chewy chewing!" - return data - - resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', - _goose_handler) - response_exts.append(resp_ext) - - def _bands_handler(res): - #NOTE: This only handles JSON responses. - # You can use content type header to test for XML. - data = json.loads(res.body) - data['big_bands'] = 'Pig Bands!' - return data - - resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', - _bands_handler) - response_exts.append(resp_ext2) - return response_exts - - def _add_tweedle(self, input_dict, req, id): - - return "Tweedle Beetle Added." - - def _delete_tweedle(self, input_dict, req, id): - - return "Tweedle Beetle Deleted." diff --git a/nova/tests/api/openstack/extensions/foxinsocks/__init__.py b/nova/tests/api/openstack/extensions/foxinsocks/__init__.py new file mode 100644 index 000000000..fe505359d --- /dev/null +++ b/nova/tests/api/openstack/extensions/foxinsocks/__init__.py @@ -0,0 +1,19 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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.import datetime + +"""Example Fox-in-Socks extension.""" diff --git a/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py new file mode 100644 index 000000000..442707714 --- /dev/null +++ b/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py @@ -0,0 +1,98 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json + +from nova import wsgi + +from nova.api.openstack import extensions + + +class FoxInSocksController(wsgi.Controller): + + def index(self, req): + return "Try to say this Mr. Knox, sir..." + + +class Foxinsocks(extensions.ExtensionDescriptor): + + def __init__(self): + pass + + def get_name(self): + return "Fox In Socks" + + def get_alias(self): + return "FOXNSOX" + + def get_description(self): + return "The Fox In Socks Extension" + + def get_namespace(self): + return "http://www.fox.in.socks/api/ext/pie/v1.0" + + def get_updated(self): + return "2011-01-22T13:25:27-06:00" + + def get_resources(self): + resources = [] + resource = extensions.ResourceExtension('foxnsocks', + FoxInSocksController()) + resources.append(resource) + return resources + + def get_actions(self): + actions = [] + actions.append(extensions.ActionExtension('servers', 'add_tweedle', + self._add_tweedle)) + actions.append(extensions.ActionExtension('servers', 'delete_tweedle', + self._delete_tweedle)) + return actions + + def get_response_extensions(self): + response_exts = [] + + def _goose_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['flavor']['googoose'] = "Gooey goo for chewy chewing!" + return data + + resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', + _goose_handler) + response_exts.append(resp_ext) + + def _bands_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['big_bands'] = 'Pig Bands!' + return data + + resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', + _bands_handler) + response_exts.append(resp_ext2) + return response_exts + + def _add_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Added." + + def _delete_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Deleted." -- cgit From 5936449d99b852897fddbbb140465db0ad9a330c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 25 Mar 2011 17:48:59 -0700 Subject: Now that it's an extension, it has to be v1.1. Also fixed up all the things that changed in v1.1 --- nova/tests/integrated/integrated_helpers.py | 21 ++++++++++---- nova/tests/integrated/test_extensions.py | 43 +++++++++++++++++++++++++++++ nova/tests/integrated/test_servers.py | 16 ++++++----- nova/tests/integrated/test_volumes.py | 6 ++++ 4 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 nova/tests/integrated/test_extensions.py (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 99d597f9a..c64f6945d 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -196,7 +196,7 @@ class IntegratedUnitTestContext(object): # so we treat it separately self.api_service = api_service - self.auth_url = 'http://localhost:8774/v1.0' + self.auth_url = 'http://localhost:8774/v1.1' return api_service @@ -229,18 +229,27 @@ class _IntegratedTestBase(test.TestCase): server = {} image = self.user.get_valid_image(create=True) - image_id = image['id'] + LOG.debug("Image: %s" % image) - #TODO(justinsb): This is FUBAR - image_id = abs(hash(image_id)) + if 'imageRef' in image: + image_ref = image['imageRef'] + else: + #NOTE(justinsb): The imageRef code hasn't yet landed + LOG.warning("imageRef not yet in images output") + image_ref = image['id'] + + #TODO(justinsb): This is FUBAR + image_ref = abs(hash(image_ref)) + + image_ref = 'http://fake.server/%s' % image_ref # We now have a valid imageId - server['imageId'] = image_id + server['imageRef'] = image_ref # Set a valid flavorId flavor = self.api.get_flavors()[0] LOG.debug("Using flavor: %s" % flavor) - server['flavorId'] = flavor['id'] + server['flavorRef'] = 'http://fake.server/%s' % flavor['id'] # Set a valid server name server_name = self.user.get_unused_server_name() diff --git a/nova/tests/integrated/test_extensions.py b/nova/tests/integrated/test_extensions.py new file mode 100644 index 000000000..39906e8d0 --- /dev/null +++ b/nova/tests/integrated/test_extensions.py @@ -0,0 +1,43 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# 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. + +import os + +from nova import flags +from nova.log import logging +from nova.tests.integrated import integrated_helpers + + +LOG = logging.getLogger('nova.tests.integrated') + +FLAGS = flags.FLAGS +FLAGS.verbose = True + + +class ExtensionsTest(integrated_helpers._IntegratedTestBase): + def _get_flags(self): + f = super(ExtensionsTest, self)._get_flags() + f['osapi_extensions_path'] = os.path.join(os.path.dirname(__file__), + "../api/openstack/extensions") + return f + + def test_get_foxnsocks(self): + """Simple check that fox-n-socks works""" + response = self.api.api_request('/foxnsocks') + foxnsocks = response.read() + LOG.debug("foxnsocks: %s" % foxnsocks) + self.assertEqual('Try to say this Mr. Knox, sir...', foxnsocks) diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index c4676adc8..a0a6e333a 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -48,27 +48,29 @@ class ServersTest(integrated_helpers._IntegratedTestBase): post = {'server': server} - # Without an imageId, this throws 500. + # Without an imageRef, this throws 500. # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) - # With an invalid imageId, this throws 500. - server['imageId'] = self.user.get_invalid_image() + # With an invalid imageRef, this throws 500. + server['imageRef'] = self.user.get_invalid_image() # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) - # Add a valid imageId - server['imageId'] = good_server['imageId'] + # Add a valid imageId/imageRef + server['imageId'] = good_server.get('imageId') + server['imageRef'] = good_server.get('imageRef') # Without flavorId, this throws 500 # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) - # Set a valid flavorId - server['flavorId'] = good_server['flavorId'] + # Set a valid flavorId/flavorRef + server['flavorRef'] = good_server.get('flavorRef') + server['flavorId'] = good_server.get('flavorId') # Without a name, this throws 500 # TODO(justinsb): Check whatever the spec says should be thrown here diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index f173efea7..9ddfe85f7 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -42,6 +42,12 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): f['volume_driver'] = 'nova.volume.driver.LoggingVolumeDriver' return f + def test_get_volumes_summary(self): + """Simple check that listing volumes works""" + volumes = self.api.get_volumes(False) + for volume in volumes: + LOG.debug("volume: %s" % volume) + def test_get_volumes(self): """Simple check that listing volumes works""" volumes = self.api.get_volumes() -- cgit From a78c1bd3e862700dbab68cc5011197270abd4b38 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Fri, 25 Mar 2011 21:46:14 -0400 Subject: Replaced import of an object with module import as per suggestion. --- nova/tests/api/openstack/test_images.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 3bf710d1a..5279ca77c 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -26,8 +26,7 @@ import datetime import os import shutil import tempfile - -from xml.dom.minidom import parseString +import xml.dom.minidom as minidom import stubout import webob @@ -326,10 +325,10 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): request.accept = "application/xml" response = request.get_response(fakes.wsgi_app()) - actual_image = parseString(response.body.replace(" ", "")) + actual_image = minidom.parseString(response.body.replace(" ", "")) expected_now = self.NOW_API_FORMAT - expected_image = parseString(""" + expected_image = minidom.parseString(""" Image not found. @@ -396,7 +395,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """.replace(" ", "")) - actual = parseString(response.body.replace(" ", "")) + actual = minidom.parseString(response.body.replace(" ", "")) self.assertEqual(expected.toxml(), actual.toxml()) @@ -422,7 +421,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): response = request.get_response(fakes.wsgi_app()) self.assertEqual(404, response.status_int) - expected = parseString(""" + expected = minidom.parseString(""" Image not found. @@ -430,7 +429,7 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): """.replace(" ", "")) - actual = parseString(response.body.replace(" ", "")) + actual = minidom.parseString(response.body.replace(" ", "")) self.assertEqual(expected.toxml(), actual.toxml()) -- cgit From b3f8e9fb546c621946563af0908e43cb01c50431 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sun, 27 Mar 2011 18:48:32 -0700 Subject: Bunch of style fixes --- nova/tests/integrated/api/client.py | 4 +++- nova/tests/integrated/integrated_helpers.py | 12 +++++------- nova/tests/integrated/test_extensions.py | 1 + nova/tests/integrated/test_servers.py | 15 ++++++++------- nova/tests/integrated/test_volumes.py | 7 ++++--- 5 files changed, 21 insertions(+), 18 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 023871bda..688ba8778 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -56,7 +56,9 @@ class OpenStackApiNotFoundException(OpenStackApiException): class TestOpenStackClient(object): - """ A really basic OpenStack API client that is under our control, + """Simple OpenStack API Client. + + This is a really basic OpenStack API client that is under our control, so we can make changes / insert hooks for testing""" def __init__(self, auth_user, auth_key, auth_uri): diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index c64f6945d..7aed69099 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -85,10 +85,10 @@ class TestUser(object): def get_valid_image(self, create=False): images = self.openstack_api.get_images() if create and not images: - # TODO(justinsb): No way to create an image through API??? + #TODO(justinsb): No way currently to create an image through API #created_image = self.openstack_api.post_image(image) #images.append(created_image) - raise exception.Error("No way to create an image through API??") + raise exception.Error("No way to create an image through API") if images: return images[0] @@ -124,7 +124,7 @@ class IntegratedUnitTestContext(object): self._start_volume_service() self._start_scheduler_service() - # NOTE(justinsb): There's a bug here which is eluding me... + #NOTE(justinsb): There's a bug here which is eluding me... # If we start the network_service, all is good, but then subsequent # tests fail: CloudTestCase.test_ajax_console in particular. #self._start_network_service() @@ -192,7 +192,7 @@ class IntegratedUnitTestContext(object): if not api_service: raise Exception("API Service was None") - # NOTE(justinsb): The API service doesn't have a kill method yet, + #NOTE(justinsb): The API service doesn't have a kill method yet, # so we treat it separately self.api_service = api_service @@ -217,9 +217,7 @@ class _IntegratedTestBase(test.TestCase): super(_IntegratedTestBase, self).tearDown() def _get_flags(self): - """An opportunity to setup flags, before the services are started - - Warning - this is a bit flaky till the WSGI recycle code lands""" + """An opportunity to setup flags, before the services are started""" f = {} f['image_service'] = 'nova.image.fake.MockImageService' f['fake_network'] = True diff --git a/nova/tests/integrated/test_extensions.py b/nova/tests/integrated/test_extensions.py index 39906e8d0..1aa471f49 100644 --- a/nova/tests/integrated/test_extensions.py +++ b/nova/tests/integrated/test_extensions.py @@ -24,6 +24,7 @@ from nova.tests.integrated import integrated_helpers LOG = logging.getLogger('nova.tests.integrated') + FLAGS = flags.FLAGS FLAGS.verbose = True diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index a0a6e333a..59e5dde14 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -26,6 +26,7 @@ from nova.tests.integrated.api import client LOG = logging.getLogger('nova.tests.integrated') + FLAGS = flags.FLAGS FLAGS.verbose = True @@ -49,13 +50,13 @@ class ServersTest(integrated_helpers._IntegratedTestBase): post = {'server': server} # Without an imageRef, this throws 500. - # TODO(justinsb): Check whatever the spec says should be thrown here + #TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) # With an invalid imageRef, this throws 500. server['imageRef'] = self.user.get_invalid_image() - # TODO(justinsb): Check whatever the spec says should be thrown here + #TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -64,7 +65,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): server['imageRef'] = good_server.get('imageRef') # Without flavorId, this throws 500 - # TODO(justinsb): Check whatever the spec says should be thrown here + #TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -73,7 +74,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): server['flavorId'] = good_server.get('flavorId') # Without a name, this throws 500 - # TODO(justinsb): Check whatever the spec says should be thrown here + #TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -105,7 +106,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): break # It should be available... - # TODO(justinsb): Mock doesn't yet do this... + #TODO(justinsb): Mock doesn't yet do this... #self.assertEqual('available', found_server['status']) self._delete_server(created_server_id) @@ -125,7 +126,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): LOG.debug("Found_server=%s" % found_server) - # TODO(justinsb): Mock doesn't yet do accurate state changes + #TODO(justinsb): Mock doesn't yet do accurate state changes #if found_server['status'] != 'deleting': # break time.sleep(1) @@ -133,7 +134,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): # Should be gone self.assertFalse(found_server) -# TODO(justinsb): Enable this unit test when the metadata bug is fixed +#TODO(justinsb): Enable this unit test when the metadata bug is fixed # def test_create_server_with_metadata(self): # """Creates a server with metadata""" # diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index 9ddfe85f7..89480618d 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -27,6 +27,7 @@ from nova.volume import driver LOG = logging.getLogger('nova.tests.integrated') + FLAGS = flags.FLAGS FLAGS.verbose = True @@ -55,7 +56,7 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): LOG.debug("volume: %s" % volume) def _poll_while(self, volume_id, continue_states, max_retries=5): - """ Poll (briefly) while the state is in continue_states""" + """Poll (briefly) while the state is in continue_states""" retries = 0 while True: try: @@ -144,7 +145,7 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): # Create server server_req = {'server': self._build_minimal_create_server_request()} - # NOTE(justinsb): Create an extra server so that server_id != volume_id + #NOTE(justinsb): Create an extra server so that server_id != volume_id self.api.post_server(server_req) created_server = self.api.post_server(server_req) LOG.debug("created_server: %s" % created_server) @@ -197,7 +198,7 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): # This is just an implementation detail, but let's check it... self.assertEquals(volume_id, attachment_id) - # NOTE(justinsb): There's an issue with the attach code, in that + #NOTE(justinsb): There's an issue with the attach code, in that # it's currently asynchronous and not recorded until the attach # completes. So the caller must be 'smart', like this... attach_done = None -- cgit From a1accc23427347205f7f6c49402a4f366e5256b6 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sun, 27 Mar 2011 19:38:20 -0700 Subject: pep8 fixes --- nova/tests/integrated/api/client.py | 2 +- nova/tests/integrated/integrated_helpers.py | 85 +++++++++-------------------- 2 files changed, 26 insertions(+), 61 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index 688ba8778..b9ed7b03b 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -57,7 +57,7 @@ class OpenStackApiNotFoundException(OpenStackApiException): class TestOpenStackClient(object): """Simple OpenStack API Client. - + This is a really basic OpenStack API client that is under our control, so we can make changes / insert hooks for testing""" diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index 7aed69099..bc516b4b3 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -96,12 +96,10 @@ class TestUser(object): class IntegratedUnitTestContext(object): - def __init__(self): + def __init__(self, auth_url): self.auth_manager = manager.AuthManager() - self.api_service = None - self.services = [] - self.auth_url = None + self.auth_url = auth_url self.project_name = None self.test_user = None @@ -109,7 +107,6 @@ class IntegratedUnitTestContext(object): self.setup() def setup(self): - self._start_services() self._create_test_user() def _create_test_user(self): @@ -119,47 +116,8 @@ class IntegratedUnitTestContext(object): self.project_name = 'openstack' self._configure_project(self.project_name, self.test_user) - def _start_services(self): - self._start_compute_service() - self._start_volume_service() - self._start_scheduler_service() - - #NOTE(justinsb): There's a bug here which is eluding me... - # If we start the network_service, all is good, but then subsequent - # tests fail: CloudTestCase.test_ajax_console in particular. - #self._start_network_service() - - self._start_api_service() - - def _start_compute_service(self): - compute_service = service.Service.create(binary='nova-compute') - compute_service.start() - self.services.append(compute_service) - return compute_service - - def _start_network_service(self): - network_service = service.Service.create(binary='nova-network') - network_service.start() - self.services.append(network_service) - return network_service - - def _start_volume_service(self): - volume_service = service.Service.create(binary='nova-volume') - volume_service.start() - self.services.append(volume_service) - return volume_service - - def _start_scheduler_service(self): - scheduler_service = service.Service.create(binary='nova-scheduler') - scheduler_service.start() - self.services.append(scheduler_service) - return scheduler_service - def cleanup(self): self.test_user = None - for svc in self.services: - svc.kill() - self.services = [] def _create_unittest_user(self): users = self.auth_manager.get_users() @@ -185,21 +143,6 @@ class IntegratedUnitTestContext(object): else: self.auth_manager.add_to_project(user.name, project_name) - def _start_api_service(self): - api_service = service.ApiService.create() - api_service.start() - - if not api_service: - raise Exception("API Service was None") - - #NOTE(justinsb): The API service doesn't have a kill method yet, - # so we treat it separately - self.api_service = api_service - - self.auth_url = 'http://localhost:8774/v1.1' - - return api_service - class _IntegratedTestBase(test.TestCase): def setUp(self): @@ -208,10 +151,32 @@ class _IntegratedTestBase(test.TestCase): f = self._get_flags() self.flags(**f) - self.context = IntegratedUnitTestContext() + # set up services + self.start_service('compute') + self.start_service('volume') + #NOTE(justinsb): There's a bug here which is eluding me... + # If we start the network_service, all is good, but then subsequent + # tests fail: CloudTestCase.test_ajax_console in particular. + #self.start_service('network') + self.start_service('scheduler') + + self.auth_url = self._start_api_service() + + self.context = IntegratedUnitTestContext(self.auth_url) + self.user = self.context.test_user self.api = self.user.openstack_api + def _start_api_service(self): + api_service = service.ApiService.create() + api_service.start() + + if not api_service: + raise Exception("API Service was None") + + auth_url = 'http://localhost:8774/v1.1' + return auth_url + def tearDown(self): self.context.cleanup() super(_IntegratedTestBase, self).tearDown() -- cgit From 8957914ad9dd7691b2a43d977d845e00f7dd48c4 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Mon, 28 Mar 2011 10:54:29 +0100 Subject: addressed termies review (first round) --- nova/tests/db/fakes.py | 8 ++-- nova/tests/fake_utils.py | 11 ++--- nova/tests/fake_utils.py.moved | 106 ----------------------------------------- nova/tests/test_xenapi.py | 37 +++++++------- 4 files changed, 26 insertions(+), 136 deletions(-) delete mode 100644 nova/tests/fake_utils.py.moved (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index 05a47d4c9..f7610aa56 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -25,7 +25,7 @@ from nova import utils def stub_out_db_instance_api(stubs, injected=True): - """ Stubs out the db API for creating Instances """ + """Stubs out the db API for creating Instances.""" INSTANCE_TYPES = { 'm1.tiny': dict(memory_mb=512, @@ -91,7 +91,7 @@ def stub_out_db_instance_api(stubs, injected=True): 'network_id': 'fake_flat'} class FakeModel(object): - """ Stubs out for model """ + """Stubs out for model.""" def __init__(self, values): self.values = values @@ -111,7 +111,7 @@ def stub_out_db_instance_api(stubs, injected=True): return INSTANCE_TYPES[name] def fake_network_get_by_instance(context, instance_id): - #even instance numbers are on vlan networks + # Even instance numbers are on vlan networks if instance_id % 2 == 0: return FakeModel(vlan_network_fields) else: @@ -119,7 +119,7 @@ def stub_out_db_instance_api(stubs, injected=True): return FakeModel(network_fields) def fake_network_get_all_by_instance(context, instance_id): - #even instance numbers are on vlan networks + # Even instance numbers are on vlan networks if instance_id % 2 == 0: return [FakeModel(vlan_network_fields)] else: diff --git a/nova/tests/fake_utils.py b/nova/tests/fake_utils.py index 823c775cb..23996ba95 100644 --- a/nova/tests/fake_utils.py +++ b/nova/tests/fake_utils.py @@ -14,8 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. -"""This modules stubs out functions in nova.utils -""" +"""This modules stubs out functions in nova.utils.""" import re import types @@ -42,22 +41,20 @@ def fake_execute_clear_log(): def fake_execute_set_repliers(repliers): - """Allows the client to configure replies to commands""" + """Allows the client to configure replies to commands.""" global _fake_execute_repliers _fake_execute_repliers = repliers def fake_execute_default_reply_handler(*ignore_args, **ignore_kwargs): """A reply handler for commands that haven't been added to the reply - list. Returns empty strings for stdout and stderr - """ + list. Returns empty strings for stdout and stderr.""" return '', '' def fake_execute(*cmd_parts, **kwargs): """This function stubs out execute, optionally executing - a preconfigued function to return expected data - """ + a preconfigued function to return expected data.""" global _fake_execute_repliers process_input = kwargs.get('process_input', None) diff --git a/nova/tests/fake_utils.py.moved b/nova/tests/fake_utils.py.moved deleted file mode 100644 index 8982f50be..000000000 --- a/nova/tests/fake_utils.py.moved +++ /dev/null @@ -1,106 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright (c) 2011 Citrix Systems, 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. - -"""This modules stubs out functions in nova.utils -""" - -import re -import types - -from eventlet import greenthread - -from nova import exception -from nova import log as logging -from nova import utils - -LOG = logging.getLogger('nova.tests.fake_utils') - -_fake_execute_repliers = [] -_fake_execute_log = [] - - -def fake_execute_get_log(): - global _fake_execute_log - return _fake_execute_log - - -def fake_execute_clear_log(): - global _fake_execute_log - _fake_execute_log = [] - - -def fake_execute_set_repliers(repliers): - """Allows the client to configure replies to commands""" - global _fake_execute_repliers - _fake_execute_repliers = repliers - - -def fake_execute_default_reply_handler(*ignore_args, **ignore_kwargs): - """A reply handler for commands that haven't been added to the reply - list. Returns empty strings for stdout and stderr - """ - return '', '' - - -def fake_execute(*cmd, **kwargs): - """This function stubs out execute, optionally executing - a preconfigued function to return expected data - """ - global _fake_execute_repliers - - process_input = kwargs.get('process_input', None) - addl_env = kwargs.get('addl_env', None) - check_exit_code = kwargs.get('check_exit_code', 0) - cmd_map = map(str, cmd) - cmd_str = ' '.join(cmd_map) - - LOG.debug(_("Faking execution of cmd (subprocess): %s"), cmd_str) - _fake_execute_log.append(cmd_str) - - reply_handler = fake_execute_default_reply_handler - - for fake_replier in _fake_execute_repliers: - if re.match(fake_replier[0], cmd_str): - reply_handler = fake_replier[1] - LOG.debug(_('Faked command matched %s') % fake_replier[0]) - break - - if isinstance(reply_handler, types.StringTypes): - # If the reply handler is a string, return it as stdout - reply = reply_handler, '' - else: - try: - # Alternative is a function, so call it - reply = reply_handler(cmd, - process_input=process_input, - addl_env=addl_env, - check_exit_code=check_exit_code) - except exception.ProcessExecutionError as e: - LOG.debug(_('Faked command raised an exception %s' % str(e))) - raise - - LOG.debug(_("Reply to faked command is stdout='%(0)s' stderr='%(1)s'") % - {'0': reply[0], '1': reply[1]}) - - # Replicate the sleep call in the real function - greenthread.sleep(0) - return reply - - -def stub_out_utils_execute(stubs): - fake_execute_set_repliers([]) - fake_execute_clear_log() - stubs.Set(utils, 'execute', fake_execute) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index f91f37d4b..6ec0525a7 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -15,7 +15,7 @@ # under the License. """ -Test suite for XenAPI +Test suite for XenAPI. """ import functools @@ -66,7 +66,7 @@ def stub_vm_utils_with_vdi_attached_here(function, should_return=True): class XenAPIVolumeTestCase(test.TestCase): """ - Unit tests for Volume operations + Unit tests for Volume operations. """ def setUp(self): super(XenAPIVolumeTestCase, self).setUp() @@ -76,7 +76,6 @@ class XenAPIVolumeTestCase(test.TestCase): FLAGS.xenapi_connection_url = 'test_url' FLAGS.xenapi_connection_password = 'test_pass' db_fakes.stub_out_db_instance_api(self.stubs) - #db_fakes.stub_out_db_network_api(self.stubs) stubs.stub_out_get_target(self.stubs) xenapi_fake.reset() self.values = {'id': 1, @@ -102,7 +101,7 @@ class XenAPIVolumeTestCase(test.TestCase): return db.volume_create(self.context, vol) def test_create_iscsi_storage(self): - """ This shows how to test helper classes' methods """ + """This shows how to test helper classes' methods.""" stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests) session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass') helper = volume_utils.VolumeHelper @@ -117,7 +116,7 @@ class XenAPIVolumeTestCase(test.TestCase): db.volume_destroy(context.get_admin_context(), vol['id']) def test_parse_volume_info_raise_exception(self): - """ This shows how to test helper classes' methods """ + """This shows how to test helper classes' methods.""" stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests) session = xenapi_conn.XenAPISession('test_url', 'root', 'test_pass') helper = volume_utils.VolumeHelper @@ -131,7 +130,7 @@ class XenAPIVolumeTestCase(test.TestCase): db.volume_destroy(context.get_admin_context(), vol['id']) def test_attach_volume(self): - """ This shows how to test Ops classes' methods """ + """This shows how to test Ops classes' methods.""" stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeTests) conn = xenapi_conn.get_connection(False) volume = self._create_volume() @@ -150,7 +149,7 @@ class XenAPIVolumeTestCase(test.TestCase): check() def test_attach_volume_raise_exception(self): - """ This shows how to test when exceptions are raised """ + """This shows how to test when exceptions are raised.""" stubs.stubout_session(self.stubs, stubs.FakeSessionForVolumeFailedTests) conn = xenapi_conn.get_connection(False) @@ -174,7 +173,7 @@ def reset_network(*args): class XenAPIVMTestCase(test.TestCase): """ - Unit tests for VM operations + Unit tests for VM operations. """ def setUp(self): super(XenAPIVMTestCase, self).setUp() @@ -475,21 +474,21 @@ class XenAPIVMTestCase(test.TestCase): network_manager='nova.network.manager.VlanManager', network_driver='nova.network.xenapi_net', vlan_interface='fake0') - #reset network table + # Reset network table xenapi_fake.reset_table('network') - #instance id = 2 will use vlan network (see db/fakes.py) + # Instance id = 2 will use vlan network (see db/fakes.py) fake_instance_id = 2 network_bk = self.network - #ensure we use xenapi_net driver + # Ensure we use xenapi_net driver self.network = utils.import_object(FLAGS.network_manager) self.network.setup_compute_network(None, fake_instance_id) self._test_spawn(glance_stubs.FakeGlance.IMAGE_MACHINE, glance_stubs.FakeGlance.IMAGE_KERNEL, glance_stubs.FakeGlance.IMAGE_RAMDISK, instance_id=fake_instance_id) - #TODO(salvatore-orlando): a complete test here would require - #a check for making sure the bridge for the VM's VIF is - #consistent with bridge specified in nova db + # TODO(salvatore-orlando): a complete test here would require + # A check for making sure the bridge for the VM's VIF is + # consistent with bridge specified in nova db self.network = network_bk def test_spawn_with_network_qos(self): @@ -521,7 +520,7 @@ class XenAPIVMTestCase(test.TestCase): self.stubs.UnsetAll() def _create_instance(self): - """Creates and spawns a test instance""" + """Creates and spawns a test instance.""" stubs.stubout_loopingcall_start(self.stubs) values = { 'id': 1, @@ -540,7 +539,7 @@ class XenAPIVMTestCase(test.TestCase): class XenAPIDiffieHellmanTestCase(test.TestCase): """ - Unit tests for Diffie-Hellman code + Unit tests for Diffie-Hellman code. """ def setUp(self): super(XenAPIDiffieHellmanTestCase, self).setUp() @@ -566,7 +565,7 @@ class XenAPIDiffieHellmanTestCase(test.TestCase): class XenAPIMigrateInstance(test.TestCase): """ - Unit test for verifying migration-related actions + Unit test for verifying migration-related actions. """ def setUp(self): @@ -623,7 +622,7 @@ class XenAPIMigrateInstance(test.TestCase): class XenAPIDetermineDiskImageTestCase(test.TestCase): """ - Unit tests for code that detects the ImageType + Unit tests for code that detects the ImageType. """ def setUp(self): super(XenAPIDetermineDiskImageTestCase, self).setUp() @@ -644,7 +643,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase): def test_instance_disk(self): """ - If a kernel is specified then the image type is DISK (aka machine) + If a kernel is specified then the image type is DISK (aka machine). """ FLAGS.xenapi_image_service = 'objectstore' self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_MACHINE -- cgit From df946c08acba6fe1234b13f04d3c46c3973647c2 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Mon, 28 Mar 2011 11:52:28 +0100 Subject: addressed termie's review (second round) --- nova/tests/test_xenapi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 6ec0525a7..9fdd1feeb 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -487,7 +487,7 @@ class XenAPIVMTestCase(test.TestCase): glance_stubs.FakeGlance.IMAGE_RAMDISK, instance_id=fake_instance_id) # TODO(salvatore-orlando): a complete test here would require - # A check for making sure the bridge for the VM's VIF is + # a check for making sure the bridge for the VM's VIF is # consistent with bridge specified in nova db self.network = network_bk -- cgit From 184fa8239d54d20ff294cdb019d07989ed3d6c4d Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Mon, 28 Mar 2011 12:08:43 +0100 Subject: addressed termies review (third round) --- nova/tests/db/fakes.py | 63 ++++++++++++++++++++++------------------------- nova/tests/test_xenapi.py | 26 +++++++++---------- 2 files changed, 43 insertions(+), 46 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index f7610aa56..7ddfe377a 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -56,39 +56,36 @@ def stub_out_db_instance_api(stubs, injected=True): flavorid=5, rxtx_cap=5)} - flat_network_fields = { - 'id': 'fake_flat', - 'bridge': 'xenbr0', - 'label': 'fake_flat_network', - 'netmask': '255.255.255.0', - 'cidr_v6': 'fe80::a00:0/120', - 'netmask_v6': '120', - 'gateway': '10.0.0.1', - 'gateway_v6': 'fe80::a00:1', - 'broadcast': '10.0.0.255', - 'dns': '10.0.0.2', - 'ra_server': None, - 'injected': injected} - - vlan_network_fields = { - 'id': 'fake_vlan', - 'bridge': 'br111', - 'label': 'fake_vlan_network', - 'netmask': '255.255.255.0', - 'cidr_v6': 'fe80::a00:0/120', - 'netmask_v6': '120', - 'gateway': '10.0.0.1', - 'gateway_v6': 'fe80::a00:1', - 'broadcast': '10.0.0.255', - 'dns': '10.0.0.2', - 'ra_server': None, - 'vlan': 111, - 'injected': False} - - fixed_ip_fields = { - 'address': '10.0.0.3', - 'address_v6': 'fe80::a00:3', - 'network_id': 'fake_flat'} + flat_network_fields = {'id': 'fake_flat', + 'bridge': 'xenbr0', + 'label': 'fake_flat_network', + 'netmask': '255.255.255.0', + 'cidr_v6': 'fe80::a00:0/120', + 'netmask_v6': '120', + 'gateway': '10.0.0.1', + 'gateway_v6': 'fe80::a00:1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2', + 'ra_server': None, + 'injected': injected} + + vlan_network_fields = {'id': 'fake_vlan', + 'bridge': 'br111', + 'label': 'fake_vlan_network', + 'netmask': '255.255.255.0', + 'cidr_v6': 'fe80::a00:0/120', + 'netmask_v6': '120', + 'gateway': '10.0.0.1', + 'gateway_v6': 'fe80::a00:1', + 'broadcast': '10.0.0.255', + 'dns': '10.0.0.2', + 'ra_server': None, + 'vlan': 111, + 'injected': False} + + fixed_ip_fields = {'address': '10.0.0.3', + 'address_v6': 'fe80::a00:3', + 'network_id': 'fake_flat'} class FakeModel(object): """Stubs out for model.""" diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 9fdd1feeb..bc1469223 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -287,19 +287,19 @@ class XenAPIVMTestCase(test.TestCase): key = 'vm-data/networking/aabbccddeeff' xenstore_value = xenstore_data[key] tcpip_data = ast.literal_eval(xenstore_value) - self.assertEquals(tcpip_data, { - 'label': 'fake_flat_network', - 'broadcast': '10.0.0.255', - 'ips': [{'ip': '10.0.0.3', - 'netmask':'255.255.255.0', - 'enabled':'1'}], - 'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff', - 'netmask': '120', - 'enabled': '1', - 'gateway': 'fe80::a00:1'}], - 'mac': 'aa:bb:cc:dd:ee:ff', - 'dns': ['10.0.0.2'], - 'gateway': '10.0.0.1'}) + self.assertEquals(tcpip_data, + {'label': 'fake_flat_network', + 'broadcast': '10.0.0.255', + 'ips': [{'ip': '10.0.0.3', + 'netmask':'255.255.255.0', + 'enabled':'1'}], + 'ip6s': [{'ip': 'fe80::a8bb:ccff:fedd:eeff', + 'netmask': '120', + 'enabled': '1', + 'gateway': 'fe80::a00:1'}], + 'mac': 'aa:bb:cc:dd:ee:ff', + 'dns': ['10.0.0.2'], + 'gateway': '10.0.0.1'}) def check_vm_params_for_windows(self): self.assertEquals(self.vm['platform']['nx'], 'true') -- cgit From 4aad5721bff628ef8b34e0c536e0e2415f2b63f4 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 28 Mar 2011 11:16:59 -0400 Subject: Removed 'is not None' to do more general truth-checking. Added rather verbose testing. --- nova/tests/api/openstack/test_images.py | 69 +++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 1cdccadd6..88dd8f506 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -197,6 +197,73 @@ class GlanceImageServiceTest(test.TestCase, image_metas = self.service.detail(self.context) self.assertDictMatch(image_metas[0], expected) + def test_image_valid_date_format(self): + """ + Ensure 'created_at', 'updated_at', and 'deleted_at' can be valid + ISO strings. + """ + fixture = { + 'name': 'test image', + 'is_public': False, + 'properties': { + 'instance_id': '42', + 'user_id': '1', + }, + } + + valid_dates = ['2010-10-11T10:30:22', '2012-12-21T00:00:00'] + + for date in valid_dates: + fixture["created_at"] = date + fixture["updated_at"] = date + fixture["deleted_at"] = date + image_id = self.service.create(self.context, fixture)['id'] + self.assertDictMatch(self.sent_to_glance['metadata'], fixture) + + def test_image_invalid_date_format(self): + """ + Ensure `created_at`, `modified_at` can't be invalid dates. + """ + fixture = { + 'name': 'test image', + 'is_public': False, + 'properties': { + 'instance_id': '42', + 'user_id': '1', + }, + } + + invalid_dates = ['Not a date.', 4] + + for date in invalid_dates: + fixture["created_at"] = date + fixture["updated_at"] = date + fixture["deleted_at"] = date + self.assertRaises((TypeError, ValueError), self.service.create, + self.context, fixture) + + def test_image_blank_date_format(self): + """ + Ensure `created_at`, `modified_at` can be blank dates. + """ + fixture = { + 'name': 'test image', + 'is_public': False, + 'properties': { + 'instance_id': '42', + 'user_id': '1', + }, + } + + blank_dates = [None, ''] + + for date in blank_dates: + fixture["created_at"] = date + fixture["updated_at"] = date + fixture["deleted_at"] = date + image_id = self.service.create(self.context, fixture)['id'] + self.assertDictMatch(self.sent_to_glance['metadata'], fixture) + def test_create_without_instance_id(self): """ Ensure we can create an image without having to specify an @@ -235,6 +302,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): FLAGS.image_service = self.orig_image_service super(ImageControllerWithGlanceServiceTest, self).tearDown() + + def test_get_image_index(self): req = webob.Request.blank('/v1.0/images') res = req.get_response(fakes.wsgi_app()) -- cgit From 23bed216dbbd512e733ecf6065105b2d20703531 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 28 Mar 2011 13:04:02 -0400 Subject: Added MUCH more flexiable iso8601 parser dep for added stability. --- nova/tests/api/openstack/test_images.py | 69 --------------------------------- nova/tests/image/test_glance.py | 50 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 69 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 88dd8f506..1cdccadd6 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -197,73 +197,6 @@ class GlanceImageServiceTest(test.TestCase, image_metas = self.service.detail(self.context) self.assertDictMatch(image_metas[0], expected) - def test_image_valid_date_format(self): - """ - Ensure 'created_at', 'updated_at', and 'deleted_at' can be valid - ISO strings. - """ - fixture = { - 'name': 'test image', - 'is_public': False, - 'properties': { - 'instance_id': '42', - 'user_id': '1', - }, - } - - valid_dates = ['2010-10-11T10:30:22', '2012-12-21T00:00:00'] - - for date in valid_dates: - fixture["created_at"] = date - fixture["updated_at"] = date - fixture["deleted_at"] = date - image_id = self.service.create(self.context, fixture)['id'] - self.assertDictMatch(self.sent_to_glance['metadata'], fixture) - - def test_image_invalid_date_format(self): - """ - Ensure `created_at`, `modified_at` can't be invalid dates. - """ - fixture = { - 'name': 'test image', - 'is_public': False, - 'properties': { - 'instance_id': '42', - 'user_id': '1', - }, - } - - invalid_dates = ['Not a date.', 4] - - for date in invalid_dates: - fixture["created_at"] = date - fixture["updated_at"] = date - fixture["deleted_at"] = date - self.assertRaises((TypeError, ValueError), self.service.create, - self.context, fixture) - - def test_image_blank_date_format(self): - """ - Ensure `created_at`, `modified_at` can be blank dates. - """ - fixture = { - 'name': 'test image', - 'is_public': False, - 'properties': { - 'instance_id': '42', - 'user_id': '1', - }, - } - - blank_dates = [None, ''] - - for date in blank_dates: - fixture["created_at"] = date - fixture["updated_at"] = date - fixture["deleted_at"] = date - image_id = self.service.create(self.context, fixture)['id'] - self.assertDictMatch(self.sent_to_glance['metadata'], fixture) - def test_create_without_instance_id(self): """ Ensure we can create an image without having to specify an @@ -302,8 +235,6 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): FLAGS.image_service = self.orig_image_service super(ImageControllerWithGlanceServiceTest, self).tearDown() - - def test_get_image_index(self): req = webob.Request.blank('/v1.0/images') res = req.get_response(fakes.wsgi_app()) diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index d03aa9cc8..dfdce7584 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -57,6 +57,7 @@ class NullWriter(object): class BaseGlanceTest(unittest.TestCase): NOW_GLANCE_FORMAT = "2010-10-11T10:30:22" NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22) + NOW_ISO_FORMAT = "2010-10-11T10:30:22.000000" def setUp(self): # FIXME(sirp): we can probably use stubs library here rather than @@ -74,6 +75,10 @@ class BaseGlanceTest(unittest.TestCase): self.assertEqual(image_meta['updated_at'], None) self.assertEqual(image_meta['deleted_at'], None) + def assertDateTimesBlank(self, image_meta): + self.assertEqual(image_meta['updated_at'], '') + self.assertEqual(image_meta['deleted_at'], '') + class TestGlanceImageServiceProperties(BaseGlanceTest): def test_show_passes_through_to_client(self): @@ -108,33 +113,65 @@ class TestGetterDateTimeNoneTests(BaseGlanceTest): image_meta = self.service.show(self.context, 'image1') self.assertDateTimesEmpty(image_meta) + def test_show_handles_blank_datetimes(self): + self.client.images = self._make_blank_datetime_fixtures() + image_meta = self.service.show(self.context, 'image1') + self.assertDateTimesBlank(image_meta) + def test_detail_handles_none_datetimes(self): self.client.images = self._make_none_datetime_fixtures() image_meta = self.service.detail(self.context)[0] self.assertDateTimesEmpty(image_meta) + def test_detail_handles_blank_datetimes(self): + self.client.images = self._make_blank_datetime_fixtures() + image_meta = self.service.detail(self.context)[0] + self.assertDateTimesBlank(image_meta) + def test_get_handles_none_datetimes(self): self.client.images = self._make_none_datetime_fixtures() writer = NullWriter() image_meta = self.service.get(self.context, 'image1', writer) self.assertDateTimesEmpty(image_meta) + def test_get_handles_blank_datetimes(self): + self.client.images = self._make_blank_datetime_fixtures() + writer = NullWriter() + image_meta = self.service.get(self.context, 'image1', writer) + self.assertDateTimesBlank(image_meta) + def test_show_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() image_meta = self.service.show(self.context, 'image1') self.assertDateTimesFilled(image_meta) + def test_show_makes_datetimes_iso(self): + self.client.images = self._make_iso_fixtures() + image_meta = self.service.show(self.context, 'image1') + self.assertDateTimesFilled(image_meta) + def test_detail_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() image_meta = self.service.detail(self.context)[0] self.assertDateTimesFilled(image_meta) + def test_detail_makes_datetimes_iso(self): + self.client.images = self._make_iso_fixtures() + image_meta = self.service.detail(self.context)[0] + self.assertDateTimesFilled(image_meta) + def test_get_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() writer = NullWriter() image_meta = self.service.get(self.context, 'image1', writer) self.assertDateTimesFilled(image_meta) + def test_get_makes_datetimes_iso(self): + self.client.images = self._make_iso_fixtures() + writer = NullWriter() + image_meta = self.service.get(self.context, 'image1', writer) + self.assertDateTimesFilled(image_meta) + def _make_datetime_fixtures(self): fixtures = {'image1': {'name': 'image1', 'is_public': True, 'created_at': self.NOW_GLANCE_FORMAT, @@ -142,12 +179,25 @@ class TestGetterDateTimeNoneTests(BaseGlanceTest): 'deleted_at': self.NOW_GLANCE_FORMAT}} return fixtures + def _make_iso_fixtures(self): + fixtures = {'image1': {'name': 'image1', 'is_public': True, + 'created_at': self.NOW_ISO_FORMAT, + 'updated_at': self.NOW_ISO_FORMAT, + 'deleted_at': self.NOW_ISO_FORMAT}} + return fixtures + def _make_none_datetime_fixtures(self): fixtures = {'image1': {'name': 'image1', 'is_public': True, 'updated_at': None, 'deleted_at': None}} return fixtures + def _make_blank_datetime_fixtures(self): + fixtures = {'image1': {'name': 'image1', 'is_public': True, + 'updated_at': '', + 'deleted_at': ''}} + return fixtures + class TestMutatorDateTimeTests(BaseGlanceTest): """Tests create(), update()""" -- cgit From 56b4dd3929448585c15c8d11c5fe1569ce21ea7d Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 28 Mar 2011 13:18:47 -0400 Subject: Removed extra dependency as per suggestion, although it fixes the issue much better IMO, we should be safe sticking with using the format from python's isoformat() --- nova/tests/image/test_glance.py | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index dfdce7584..dfa754b89 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -55,9 +55,8 @@ class NullWriter(object): class BaseGlanceTest(unittest.TestCase): - NOW_GLANCE_FORMAT = "2010-10-11T10:30:22" + NOW_GLANCE_FORMAT = "2010-10-11T10:30:22.000000" NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22) - NOW_ISO_FORMAT = "2010-10-11T10:30:22.000000" def setUp(self): # FIXME(sirp): we can probably use stubs library here rather than @@ -145,33 +144,17 @@ class TestGetterDateTimeNoneTests(BaseGlanceTest): image_meta = self.service.show(self.context, 'image1') self.assertDateTimesFilled(image_meta) - def test_show_makes_datetimes_iso(self): - self.client.images = self._make_iso_fixtures() - image_meta = self.service.show(self.context, 'image1') - self.assertDateTimesFilled(image_meta) - def test_detail_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() image_meta = self.service.detail(self.context)[0] self.assertDateTimesFilled(image_meta) - def test_detail_makes_datetimes_iso(self): - self.client.images = self._make_iso_fixtures() - image_meta = self.service.detail(self.context)[0] - self.assertDateTimesFilled(image_meta) - def test_get_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() writer = NullWriter() image_meta = self.service.get(self.context, 'image1', writer) self.assertDateTimesFilled(image_meta) - def test_get_makes_datetimes_iso(self): - self.client.images = self._make_iso_fixtures() - writer = NullWriter() - image_meta = self.service.get(self.context, 'image1', writer) - self.assertDateTimesFilled(image_meta) - def _make_datetime_fixtures(self): fixtures = {'image1': {'name': 'image1', 'is_public': True, 'created_at': self.NOW_GLANCE_FORMAT, @@ -179,13 +162,6 @@ class TestGetterDateTimeNoneTests(BaseGlanceTest): 'deleted_at': self.NOW_GLANCE_FORMAT}} return fixtures - def _make_iso_fixtures(self): - fixtures = {'image1': {'name': 'image1', 'is_public': True, - 'created_at': self.NOW_ISO_FORMAT, - 'updated_at': self.NOW_ISO_FORMAT, - 'deleted_at': self.NOW_ISO_FORMAT}} - return fixtures - def _make_none_datetime_fixtures(self): fixtures = {'image1': {'name': 'image1', 'is_public': True, 'updated_at': None, -- cgit From 5977a511ed202fcf396e7c60d713eb5329d6883b Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 28 Mar 2011 13:30:15 -0400 Subject: style changes --- nova/tests/api/openstack/test_servers.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index d2a72dd10..25d69401d 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -655,20 +655,16 @@ class ServersTest(test.TestCase): def test_server_change_password_v1_1(self): class MockSetAdminPassword(object): - def __init__(self): - self.called = False self.instance_id = None self.password = None def __call__(self, context, instance_id, password): - self.called = True self.instance_id = instance_id self.password = password mock_method = MockSetAdminPassword() self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method) - body = {'changePassword': {'adminPass': '1234pass'}} req = webob.Request.blank('/v1.1/servers/1/action') req.method = 'POST' @@ -676,7 +672,6 @@ class ServersTest(test.TestCase): req.body = json.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202) - self.assertTrue(mock_method.called) self.assertEqual(mock_method.instance_id, '1') self.assertEqual(mock_method.password, '1234pass') -- cgit From 71347f2e9d6195a25cabff782c7058bed006e286 Mon Sep 17 00:00:00 2001 From: Mark Washenberger Date: Mon, 28 Mar 2011 13:40:16 -0400 Subject: lock down requirements for change password --- nova/tests/api/openstack/test_servers.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 25d69401d..6d6be817a 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -684,6 +684,33 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) + def test_server_change_password_empty_string_v1_1(self): + body = {'changePassword': {'adminPass': ''}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_change_password_none_v1_1(self): + body = {'changePassword': {'adminPass': None}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_server_change_password_not_a_string_v1_1(self): + body = {'changePassword': {'adminPass': 1234}} + req = webob.Request.blank('/v1.1/servers/1/action') + req.method = 'POST' + req.content_type = 'application/json' + req.body = json.dumps(body) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_server_reboot(self): body = dict(server=dict( name='server_test', imageId=2, flavorId=2, metadata={}, -- cgit From de07a6409d575af5db748bdbfa2cc57881136d66 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 28 Mar 2011 13:47:18 -0400 Subject: Decided to not break old format so this should work with the way Glance used to work and the way glace works now..The best of both worlds? --- nova/tests/image/test_glance.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index dfa754b89..9d0b14613 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -55,6 +55,7 @@ class NullWriter(object): class BaseGlanceTest(unittest.TestCase): + NOW_GLANCE_OLD_FORMAT = "2010-10-11T10:30:22" NOW_GLANCE_FORMAT = "2010-10-11T10:30:22.000000" NOW_DATETIME = datetime.datetime(2010, 10, 11, 10, 30, 22) @@ -143,23 +144,41 @@ class TestGetterDateTimeNoneTests(BaseGlanceTest): self.client.images = self._make_datetime_fixtures() image_meta = self.service.show(self.context, 'image1') self.assertDateTimesFilled(image_meta) + image_meta = self.service.show(self.context, 'image2') + self.assertDateTimesFilled(image_meta) def test_detail_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() image_meta = self.service.detail(self.context)[0] self.assertDateTimesFilled(image_meta) + image_meta = self.service.detail(self.context)[1] + self.assertDateTimesFilled(image_meta) def test_get_makes_datetimes(self): self.client.images = self._make_datetime_fixtures() writer = NullWriter() image_meta = self.service.get(self.context, 'image1', writer) self.assertDateTimesFilled(image_meta) + image_meta = self.service.get(self.context, 'image2', writer) + self.assertDateTimesFilled(image_meta) def _make_datetime_fixtures(self): - fixtures = {'image1': {'name': 'image1', 'is_public': True, - 'created_at': self.NOW_GLANCE_FORMAT, - 'updated_at': self.NOW_GLANCE_FORMAT, - 'deleted_at': self.NOW_GLANCE_FORMAT}} + fixtures = { + 'image1': { + 'name': 'image1', + 'is_public': True, + 'created_at': self.NOW_GLANCE_FORMAT, + 'updated_at': self.NOW_GLANCE_FORMAT, + 'deleted_at': self.NOW_GLANCE_FORMAT, + }, + 'image2': { + 'name': 'image2', + 'is_public': True, + 'created_at': self.NOW_GLANCE_OLD_FORMAT, + 'updated_at': self.NOW_GLANCE_OLD_FORMAT, + 'deleted_at': self.NOW_GLANCE_OLD_FORMAT, + }, + } return fixtures def _make_none_datetime_fixtures(self): -- cgit From 9c61085ea9612be24e9975ac3fba456874b89f08 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 28 Mar 2011 13:49:51 -0400 Subject: Add more unit tests for lxc --- nova/tests/test_virt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index cee044279..ed7943ace 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -257,7 +257,9 @@ class LibvirtConnTestCase(test.TestCase): check = [ (lambda t: t.find('.').get('type'), 'lxc'), - (lambda t: t.find('./os/type').text, 'exe')] + (lambda t: t.find('./os/type').text, 'exe'), + (lambda t: t.find('./devices/filesystem/source').get('dir'), 'rootfs'), + (lambda t: t.find('./devices/filesystem/target').get('dir'), '/')] for i, (check, expected_result) in enumerate(check): self.assertEqual(check(tree), -- cgit From 14337b0a31c8f04d8044e234eb295b41a9a9c5ce Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 28 Mar 2011 14:02:53 -0400 Subject: adding shared_ip_groups testing; replacing all shared_ip_groups contoller code with HTTPNotImplemented; moving shared_ip_groups controller to APIRouterV10 --- nova/tests/api/openstack/test_shared_ip_groups.py | 30 ++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_shared_ip_groups.py b/nova/tests/api/openstack/test_shared_ip_groups.py index b4de2ef41..c2bd7e45a 100644 --- a/nova/tests/api/openstack/test_shared_ip_groups.py +++ b/nova/tests/api/openstack/test_shared_ip_groups.py @@ -16,25 +16,49 @@ # under the License. import stubout +import webob from nova import test from nova.api.openstack import shared_ip_groups +from nova.tests.api.openstack import fakes class SharedIpGroupsTest(test.TestCase): def setUp(self): super(SharedIpGroupsTest, self).setUp() self.stubs = stubout.StubOutForTesting() + fakes.FakeAuthManager.reset_fake_data() + fakes.FakeAuthDatabase.data = {} + fakes.stub_out_auth(self.stubs) def tearDown(self): self.stubs.UnsetAll() super(SharedIpGroupsTest, self).tearDown() def test_get_shared_ip_groups(self): - pass + req = webob.Request.blank('/v1.0/shared_ip_groups') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) def test_create_shared_ip_group(self): - pass + req = webob.Request.blank('/v1.0/shared_ip_groups') + req.method = 'POST' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) + + def test_update_shared_ip_group(self): + req = webob.Request.blank('/v1.0/shared_ip_groups/12') + req.method = 'PUT' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) def test_delete_shared_ip_group(self): - pass + req = webob.Request.blank('/v1.0/shared_ip_groups/12') + req.method = 'DELETE' + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) + + def test_deprecated_v11(self): + req = webob.Request.blank('/v1.1/shared_ip_groups') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) -- cgit From e44ce1a95baddd4f6d511d8be253167436395cb2 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 28 Mar 2011 14:07:33 -0400 Subject: More pep8 corrections --- nova/tests/test_virt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index ed7943ace..8cee55576 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -258,8 +258,8 @@ class LibvirtConnTestCase(test.TestCase): check = [ (lambda t: t.find('.').get('type'), 'lxc'), (lambda t: t.find('./os/type').text, 'exe'), - (lambda t: t.find('./devices/filesystem/source').get('dir'), 'rootfs'), - (lambda t: t.find('./devices/filesystem/target').get('dir'), '/')] + (lambda t: t.find('./devices/filesystem/source').get('dir'), 'rootfs'), + (lambda t: t.find('./devices/filesystem/target').get('dir'), '/')] for i, (check, expected_result) in enumerate(check): self.assertEqual(check(tree), -- cgit From b6df504c33cfa0fe02e31962578b77d841e1e6d8 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 28 Mar 2011 14:31:12 -0400 Subject: backup_schedule tests corrected; controller moved to APIRouterV10; making controller fully HTTPNotImplemented --- nova/tests/api/openstack/test_servers.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 737b43c7b..989385a8c 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -483,21 +483,31 @@ class ServersTest(test.TestCase): req.get_response(fakes.wsgi_app()) def test_create_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedule') req.method = 'POST' res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status, '404 Not Found') + self.assertEqual(res.status_int, 501) def test_delete_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedule/1') req.method = 'DELETE' res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status, '404 Not Found') + self.assertEqual(res.status_int, 501) def test_get_server_backup_schedules(self): - req = webob.Request.blank('/v1.0/servers/1/backup_schedules') + req = webob.Request.blank('/v1.0/servers/1/backup_schedule') res = req.get_response(fakes.wsgi_app()) - self.assertEqual(res.status, '404 Not Found') + self.assertEqual(res.status_int, 501) + + def test_get_server_backup_schedule(self): + req = webob.Request.blank('/v1.0/servers/1/backup_schedule/1') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 501) + + def test_server_backup_schedule_deprecated_v11(self): + req = webob.Request.blank('/v1.1/servers/1/backup_schedule') + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 404) def test_get_all_server_details_v1_0(self): req = webob.Request.blank('/v1.0/servers/detail') -- cgit From c8e708af1789fda97674fb4c3904d86de8473a7e Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 28 Mar 2011 14:32:03 -0400 Subject: Dont make the test fail --- nova/tests/test_virt.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index 8cee55576..df29e69c2 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -258,7 +258,6 @@ class LibvirtConnTestCase(test.TestCase): check = [ (lambda t: t.find('.').get('type'), 'lxc'), (lambda t: t.find('./os/type').text, 'exe'), - (lambda t: t.find('./devices/filesystem/source').get('dir'), 'rootfs'), (lambda t: t.find('./devices/filesystem/target').get('dir'), '/')] for i, (check, expected_result) in enumerate(check): @@ -266,6 +265,9 @@ class LibvirtConnTestCase(test.TestCase): expected_result, '%s failed common check %d' % (xml, i)) + target = tree.find('./devices/filesystem/source').get('dir') + self.assertTrue(len(target) > 0) + def _check_xml_and_uri(self, instance, expect_ramdisk, expect_kernel, rescue=False): user_context = context.RequestContext(project=self.project, -- cgit From bb7ed6cb9cf625b675a666866a7f9fb762ca6bd2 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Mon, 28 Mar 2011 14:47:25 -0400 Subject: use self.flags in virt test --- nova/tests/test_virt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index df29e69c2..e6beb8e2e 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -246,7 +246,7 @@ class LibvirtConnTestCase(test.TestCase): {'allocated': True, 'instance_id': instance_ref['id']}) - FLAGS.libvirt_type = 'lxc' + self.flags(libvirt_type='lxc') conn = libvirt_conn.LibvirtConnection(True) uri = conn.get_uri() -- cgit From c1ed5fc3dfeecef281df45cd2e6779fa21c63bf5 Mon Sep 17 00:00:00 2001 From: Armando Migliaccio Date: Mon, 28 Mar 2011 22:00:17 +0100 Subject: style fixes --- nova/tests/fake_utils.py | 14 ++++++++++---- nova/tests/test_xenapi.py | 28 +++++++--------------------- 2 files changed, 17 insertions(+), 25 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/fake_utils.py b/nova/tests/fake_utils.py index 23996ba95..be59970c9 100644 --- a/nova/tests/fake_utils.py +++ b/nova/tests/fake_utils.py @@ -47,14 +47,20 @@ def fake_execute_set_repliers(repliers): def fake_execute_default_reply_handler(*ignore_args, **ignore_kwargs): - """A reply handler for commands that haven't been added to the reply - list. Returns empty strings for stdout and stderr.""" + """A reply handler for commands that haven't been added to the reply list. + + Returns empty strings for stdout and stderr. + + """ return '', '' def fake_execute(*cmd_parts, **kwargs): - """This function stubs out execute, optionally executing - a preconfigued function to return expected data.""" + """This function stubs out execute. + + It optionally executes a preconfigued function to return expected data. + + """ global _fake_execute_repliers process_input = kwargs.get('process_input', None) diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index bc1469223..17e3f55e9 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -14,9 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. -""" -Test suite for XenAPI. -""" +"""Test suite for XenAPI.""" import functools import os @@ -65,9 +63,7 @@ def stub_vm_utils_with_vdi_attached_here(function, should_return=True): class XenAPIVolumeTestCase(test.TestCase): - """ - Unit tests for Volume operations. - """ + """Unit tests for Volume operations.""" def setUp(self): super(XenAPIVolumeTestCase, self).setUp() self.stubs = stubout.StubOutForTesting() @@ -172,9 +168,7 @@ def reset_network(*args): class XenAPIVMTestCase(test.TestCase): - """ - Unit tests for VM operations. - """ + """Unit tests for VM operations.""" def setUp(self): super(XenAPIVMTestCase, self).setUp() self.manager = manager.AuthManager() @@ -538,9 +532,7 @@ class XenAPIVMTestCase(test.TestCase): class XenAPIDiffieHellmanTestCase(test.TestCase): - """ - Unit tests for Diffie-Hellman code. - """ + """Unit tests for Diffie-Hellman code.""" def setUp(self): super(XenAPIDiffieHellmanTestCase, self).setUp() self.alice = SimpleDH() @@ -564,9 +556,7 @@ class XenAPIDiffieHellmanTestCase(test.TestCase): class XenAPIMigrateInstance(test.TestCase): - """ - Unit test for verifying migration-related actions. - """ + """Unit test for verifying migration-related actions.""" def setUp(self): super(XenAPIMigrateInstance, self).setUp() @@ -621,9 +611,7 @@ class XenAPIMigrateInstance(test.TestCase): class XenAPIDetermineDiskImageTestCase(test.TestCase): - """ - Unit tests for code that detects the ImageType. - """ + """Unit tests for code that detects the ImageType.""" def setUp(self): super(XenAPIDetermineDiskImageTestCase, self).setUp() glance_stubs.stubout_glance_client(self.stubs, @@ -642,9 +630,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase): self.assertEqual(disk_type, dt) def test_instance_disk(self): - """ - If a kernel is specified then the image type is DISK (aka machine). - """ + """If a kernel is specified, the image type is DISK (aka machine).""" FLAGS.xenapi_image_service = 'objectstore' self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_MACHINE self.fake_instance.kernel_id = glance_stubs.FakeGlance.IMAGE_KERNEL -- cgit From c439309fddb7e6ebc14ab6b82ac9960f459c5aed Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 28 Mar 2011 17:40:45 -0400 Subject: osapi servers update tests actually assert now; enforcing server name being a string of length > 0; moving server update adminPass support to be v1.0-specific --- nova/tests/api/openstack/test_servers.py | 34 +++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 989385a8c..1043838eb 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -448,39 +448,55 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 422) - def test_update_bad_params(self): + def test_update_bad_name(self): """ Confirm that update is filtering params """ - inst_dict = dict(cat='leopard', name='server_test', adminPass='bacon') + inst_dict = dict(name='', adminPass='bacon') + self.body = json.dumps(dict(server=inst_dict)) + + req = webob.Request.blank('/v1.0/servers/1') + req.method = 'PUT' + req.content_type = "application/json" + req.body = self.body + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_update_server_v10(self): + inst_dict = dict(name='server_test', adminPass='bacon') self.body = json.dumps(dict(server=inst_dict)) def server_update(context, id, params): - self.update_called = True - filtered_dict = dict(name='server_test', admin_pass='bacon') + filtered_dict = dict(display_name='server_test', admin_pass='bacon') self.assertEqual(params, filtered_dict) + return filtered_dict self.stubs.Set(nova.db.api, 'instance_update', server_update) req = webob.Request.blank('/v1.0/servers/1') req.method = 'PUT' + req.content_type = "application/json" req.body = self.body - req.get_response(fakes.wsgi_app()) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 204) - def test_update_server(self): + def test_update_server_adminPass_ignored_v11(self): inst_dict = dict(name='server_test', adminPass='bacon') self.body = json.dumps(dict(server=inst_dict)) def server_update(context, id, params): - filtered_dict = dict(name='server_test', admin_pass='bacon') + filtered_dict = dict(display_name='server_test') self.assertEqual(params, filtered_dict) + return filtered_dict self.stubs.Set(nova.db.api, 'instance_update', server_update) - req = webob.Request.blank('/v1.0/servers/1') + req = webob.Request.blank('/v1.1/servers/1') req.method = 'PUT' + req.content_type = "application/json" req.body = self.body - req.get_response(fakes.wsgi_app()) + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 204) def test_create_backup_schedules(self): req = webob.Request.blank('/v1.0/servers/1/backup_schedule') -- cgit From f460d75ae355ee76b6c51d884162f00076140716 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 28 Mar 2011 17:45:48 -0400 Subject: pep8 --- nova/tests/api/openstack/test_servers.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 1043838eb..506b24b8b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -465,7 +465,10 @@ class ServersTest(test.TestCase): self.body = json.dumps(dict(server=inst_dict)) def server_update(context, id, params): - filtered_dict = dict(display_name='server_test', admin_pass='bacon') + filtered_dict = dict( + display_name='server_test', + admin_pass='bacon', + ) self.assertEqual(params, filtered_dict) return filtered_dict -- cgit From 94092e3d896732fa1a97627f0fa504c3af70b3c5 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Mon, 28 Mar 2011 15:38:09 -0700 Subject: address some of termie's recommendations --- nova/tests/test_compute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 0be08a778..038824ef8 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -290,7 +290,7 @@ class ComputeTestCase(test.TestCase): self.compute.terminate_instance(self.context, instance_id) def test_vnc_console(self): - """Make sure we can a vnc console for an instance""" + """Make sure we can a vnc console for an instance.""" instance_id = self._create_instance() self.compute.run_instance(self.context, instance_id) -- cgit From 276c153f44734e78cae25deb9fc9e79a604c6219 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 28 Mar 2011 16:42:28 -0700 Subject: More fixes to keep the stylebot happy --- nova/tests/integrated/api/client.py | 2 +- nova/tests/integrated/integrated_helpers.py | 20 ++++++++++---------- nova/tests/integrated/test_extensions.py | 2 +- nova/tests/integrated/test_login.py | 8 ++++---- nova/tests/integrated/test_servers.py | 16 ++++++++-------- nova/tests/integrated/test_volumes.py | 18 +++++++++--------- 6 files changed, 33 insertions(+), 33 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index b9ed7b03b..b40ff58e3 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -124,7 +124,7 @@ class TestOpenStackClient(object): def api_request(self, relative_uri, check_response_status=None, **kwargs): auth_result = self._authenticate() - #NOTE(justinsb): httplib 'helpfully' converts headers to lower case + # NOTE(justinsb): httplib 'helpfully' converts headers to lower case base_uri = auth_result['x-server-management-url'] full_uri = base_uri + relative_uri diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index bc516b4b3..e0fe2d2a2 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -37,19 +37,19 @@ LOG = logging.getLogger('nova.tests.integrated') def generate_random_alphanumeric(length): - """Creates a random alphanumeric string of specified length""" + """Creates a random alphanumeric string of specified length.""" return ''.join(random.choice(string.ascii_uppercase + string.digits) for _x in range(length)) def generate_random_numeric(length): - """Creates a random numeric string of specified length""" + """Creates a random numeric string of specified length.""" return ''.join(random.choice(string.digits) for _x in range(length)) def generate_new_element(items, prefix, numeric=False): - """Creates a random string with prefix, that is not in 'items' list""" + """Creates a random string with prefix, that is not in 'items' list.""" while True: if numeric: candidate = prefix + generate_random_numeric(8) @@ -85,7 +85,7 @@ class TestUser(object): def get_valid_image(self, create=False): images = self.openstack_api.get_images() if create and not images: - #TODO(justinsb): No way currently to create an image through API + # TODO(justinsb): No way currently to create an image through API #created_image = self.openstack_api.post_image(image) #images.append(created_image) raise exception.Error("No way to create an image through API") @@ -154,9 +154,9 @@ class _IntegratedTestBase(test.TestCase): # set up services self.start_service('compute') self.start_service('volume') - #NOTE(justinsb): There's a bug here which is eluding me... - # If we start the network_service, all is good, but then subsequent - # tests fail: CloudTestCase.test_ajax_console in particular. + # NOTE(justinsb): There's a bug here which is eluding me... + # If we start the network_service, all is good, but then subsequent + # tests fail: CloudTestCase.test_ajax_console in particular. #self.start_service('network') self.start_service('scheduler') @@ -182,7 +182,7 @@ class _IntegratedTestBase(test.TestCase): super(_IntegratedTestBase, self).tearDown() def _get_flags(self): - """An opportunity to setup flags, before the services are started""" + """An opportunity to setup flags, before the services are started.""" f = {} f['image_service'] = 'nova.image.fake.MockImageService' f['fake_network'] = True @@ -197,11 +197,11 @@ class _IntegratedTestBase(test.TestCase): if 'imageRef' in image: image_ref = image['imageRef'] else: - #NOTE(justinsb): The imageRef code hasn't yet landed + # NOTE(justinsb): The imageRef code hasn't yet landed LOG.warning("imageRef not yet in images output") image_ref = image['id'] - #TODO(justinsb): This is FUBAR + # TODO(justinsb): This is FUBAR image_ref = abs(hash(image_ref)) image_ref = 'http://fake.server/%s' % image_ref diff --git a/nova/tests/integrated/test_extensions.py b/nova/tests/integrated/test_extensions.py index 1aa471f49..0d4ee8cab 100644 --- a/nova/tests/integrated/test_extensions.py +++ b/nova/tests/integrated/test_extensions.py @@ -37,7 +37,7 @@ class ExtensionsTest(integrated_helpers._IntegratedTestBase): return f def test_get_foxnsocks(self): - """Simple check that fox-n-socks works""" + """Simple check that fox-n-socks works.""" response = self.api.api_request('/foxnsocks') foxnsocks = response.read() LOG.debug("foxnsocks: %s" % foxnsocks) diff --git a/nova/tests/integrated/test_login.py b/nova/tests/integrated/test_login.py index d6e067c29..a5180b6bc 100644 --- a/nova/tests/integrated/test_login.py +++ b/nova/tests/integrated/test_login.py @@ -31,13 +31,13 @@ FLAGS.verbose = True class LoginTest(integrated_helpers._IntegratedTestBase): def test_login(self): - """Simple check - we list flavors - so we know we're logged in""" + """Simple check - we list flavors - so we know we're logged in.""" flavors = self.api.get_flavors() for flavor in flavors: LOG.debug(_("flavor: %s") % flavor) def test_bad_login_password(self): - """Test that I get a 401 with a bad username""" + """Test that I get a 401 with a bad username.""" bad_credentials_api = client.TestOpenStackClient(self.user.name, "notso_password", self.user.auth_url) @@ -46,7 +46,7 @@ class LoginTest(integrated_helpers._IntegratedTestBase): bad_credentials_api.get_flavors) def test_bad_login_username(self): - """Test that I get a 401 with a bad password""" + """Test that I get a 401 with a bad password.""" bad_credentials_api = client.TestOpenStackClient("notso_username", self.user.secret, self.user.auth_url) @@ -55,7 +55,7 @@ class LoginTest(integrated_helpers._IntegratedTestBase): bad_credentials_api.get_flavors) def test_bad_login_both_bad(self): - """Test that I get a 401 with both bad username and bad password""" + """Test that I get a 401 with both bad username and bad password.""" bad_credentials_api = client.TestOpenStackClient("notso_username", "notso_password", self.user.auth_url) diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 59e5dde14..749ea8955 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -39,7 +39,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): LOG.debug("server: %s" % server) def test_create_and_delete_server(self): - """Creates and deletes a server""" + """Creates and deletes a server.""" # Create server @@ -50,13 +50,13 @@ class ServersTest(integrated_helpers._IntegratedTestBase): post = {'server': server} # Without an imageRef, this throws 500. - #TODO(justinsb): Check whatever the spec says should be thrown here + # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) # With an invalid imageRef, this throws 500. server['imageRef'] = self.user.get_invalid_image() - #TODO(justinsb): Check whatever the spec says should be thrown here + # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -65,7 +65,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): server['imageRef'] = good_server.get('imageRef') # Without flavorId, this throws 500 - #TODO(justinsb): Check whatever the spec says should be thrown here + # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -74,7 +74,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): server['flavorId'] = good_server.get('flavorId') # Without a name, this throws 500 - #TODO(justinsb): Check whatever the spec says should be thrown here + # TODO(justinsb): Check whatever the spec says should be thrown here self.assertRaises(client.OpenStackApiException, self.api.post_server, post) @@ -106,7 +106,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): break # It should be available... - #TODO(justinsb): Mock doesn't yet do this... + # TODO(justinsb): Mock doesn't yet do this... #self.assertEqual('available', found_server['status']) self._delete_server(created_server_id) @@ -126,7 +126,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): LOG.debug("Found_server=%s" % found_server) - #TODO(justinsb): Mock doesn't yet do accurate state changes + # TODO(justinsb): Mock doesn't yet do accurate state changes #if found_server['status'] != 'deleting': # break time.sleep(1) @@ -134,7 +134,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): # Should be gone self.assertFalse(found_server) -#TODO(justinsb): Enable this unit test when the metadata bug is fixed +# TODO(justinsb): Enable this unit test when the metadata bug is fixed # def test_create_server_with_metadata(self): # """Creates a server with metadata""" # diff --git a/nova/tests/integrated/test_volumes.py b/nova/tests/integrated/test_volumes.py index 89480618d..e9fb3c4d1 100644 --- a/nova/tests/integrated/test_volumes.py +++ b/nova/tests/integrated/test_volumes.py @@ -44,19 +44,19 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): return f def test_get_volumes_summary(self): - """Simple check that listing volumes works""" + """Simple check that listing volumes works.""" volumes = self.api.get_volumes(False) for volume in volumes: LOG.debug("volume: %s" % volume) def test_get_volumes(self): - """Simple check that listing volumes works""" + """Simple check that listing volumes works.""" volumes = self.api.get_volumes() for volume in volumes: LOG.debug("volume: %s" % volume) def _poll_while(self, volume_id, continue_states, max_retries=5): - """Poll (briefly) while the state is in continue_states""" + """Poll (briefly) while the state is in continue_states.""" retries = 0 while True: try: @@ -80,7 +80,7 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): return found_volume def test_create_and_delete_volume(self): - """Creates and deletes a volume""" + """Creates and deletes a volume.""" # Create volume created_volume = self.api.post_volume({'volume': {'size': 1}}) @@ -141,11 +141,11 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): self.assertEquals(delete_action['id'], created_volume_id) def test_attach_and_detach_volume(self): - """Creates, attaches, detaches and deletes a volume""" + """Creates, attaches, detaches and deletes a volume.""" # Create server server_req = {'server': self._build_minimal_create_server_request()} - #NOTE(justinsb): Create an extra server so that server_id != volume_id + # NOTE(justinsb): Create an extra server so that server_id != volume_id self.api.post_server(server_req) created_server = self.api.post_server(server_req) LOG.debug("created_server: %s" % created_server) @@ -198,9 +198,9 @@ class VolumesTest(integrated_helpers._IntegratedTestBase): # This is just an implementation detail, but let's check it... self.assertEquals(volume_id, attachment_id) - #NOTE(justinsb): There's an issue with the attach code, in that - # it's currently asynchronous and not recorded until the attach - # completes. So the caller must be 'smart', like this... + # NOTE(justinsb): There's an issue with the attach code, in that + # it's currently asynchronous and not recorded until the attach + # completes. So the caller must be 'smart', like this... attach_done = None retries = 0 while True: -- cgit From 87bc3bca7904135656ed3a99efc19952be95dcbf Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 28 Mar 2011 16:54:17 -0700 Subject: Multi-line comments should end in a blankline --- nova/tests/integrated/api/client.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/api/client.py b/nova/tests/integrated/api/client.py index b40ff58e3..7e20c9b00 100644 --- a/nova/tests/integrated/api/client.py +++ b/nova/tests/integrated/api/client.py @@ -59,7 +59,9 @@ class TestOpenStackClient(object): """Simple OpenStack API Client. This is a really basic OpenStack API client that is under our control, - so we can make changes / insert hooks for testing""" + so we can make changes / insert hooks for testing + + """ def __init__(self, auth_user, auth_key, auth_uri): super(TestOpenStackClient, self).__init__() -- cgit From 5c74862a08a82b7db3e11fbcbec63293ea903e00 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 28 Mar 2011 23:11:42 -0700 Subject: make all openstack status uppercase --- nova/tests/api/openstack/test_servers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 989385a8c..27cbd28c1 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -738,7 +738,7 @@ class ServersTest(test.TestCase): fake_migration_get) res = req.get_response(fakes.wsgi_app()) body = json.loads(res.body) - self.assertEqual(body['server']['status'], 'resize-confirm') + self.assertEqual(body['server']['status'], 'RESIZE-CONFIRM') def test_confirm_resize_server(self): req = self.webreq('/1/action', 'POST', dict(confirmResize=None)) -- cgit From 793de5cef9fb539a4fb3ba976d83adde38a589c1 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 29 Mar 2011 10:40:35 -0400 Subject: adding more tests; making name checks more robust --- nova/tests/api/openstack/test_servers.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 506b24b8b..ef4cf55b8 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -448,7 +448,31 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 422) - def test_update_bad_name(self): + def test_update_nonstring_name(self): + """ Confirm that update is filtering params """ + inst_dict = dict(name=12, adminPass='bacon') + self.body = json.dumps(dict(server=inst_dict)) + + req = webob.Request.blank('/v1.0/servers/1') + req.method = 'PUT' + req.content_type = "application/json" + req.body = self.body + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_update_whitespace_name(self): + """ Confirm that update is filtering params """ + inst_dict = dict(name=' ', adminPass='bacon') + self.body = json.dumps(dict(server=inst_dict)) + + req = webob.Request.blank('/v1.0/servers/1') + req.method = 'PUT' + req.content_type = "application/json" + req.body = self.body + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_update_null_name(self): """ Confirm that update is filtering params """ inst_dict = dict(name='', adminPass='bacon') self.body = json.dumps(dict(server=inst_dict)) -- cgit From f624d2e35dab0d87a289a346999c0cb01ed0aa55 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 29 Mar 2011 11:11:57 -0400 Subject: adding server name validation to create method; adding tests --- nova/tests/api/openstack/test_servers.py | 68 ++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index ef4cf55b8..130b8c5d5 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -392,6 +392,74 @@ class ServersTest(test.TestCase): fakes.stub_out_key_pair_funcs(self.stubs, have_key_pair=False) self._test_create_instance_helper() + def test_create_instance_no_name(self): + self._setup_for_create_instance() + + body = { + 'server': { + 'imageId': 3, + 'flavorId': 1, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': {}, + }, + } + + req = webob.Request.blank('/v1.0/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_create_instance_nonstring_name(self): + self._setup_for_create_instance() + + body = { + 'server': { + 'name': 12, + 'imageId': 3, + 'flavorId': 1, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': {}, + }, + } + + req = webob.Request.blank('/v1.0/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + + def test_create_instance_whitespace_name(self): + self._setup_for_create_instance() + + body = { + 'server': { + 'name': ' ', + 'imageId': 3, + 'flavorId': 1, + 'metadata': { + 'hello': 'world', + 'open': 'stack', + }, + 'personality': {}, + }, + } + + req = webob.Request.blank('/v1.0/servers') + req.method = 'POST' + req.body = json.dumps(body) + req.headers["content-type"] = "application/json" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 400) + def test_create_instance_v11(self): self._setup_for_create_instance() -- cgit From d1ef69edb8da18c5c7e56b6006e22022d55d6664 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 29 Mar 2011 11:41:33 -0400 Subject: adding code to explicitly set the content-type in versions controller; updating test --- nova/tests/api/openstack/test_versions.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index ebb59a9a6..ee922a8d3 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -34,8 +34,10 @@ class VersionsTest(test.TestCase): def test_get_version_list(self): req = webob.Request.blank('/') + req.accept = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/json") versions = json.loads(res.body)["versions"] expected = [ { -- cgit From 343b969f7d790282b7b76bcb23b9d0d578d716b9 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Tue, 29 Mar 2011 12:04:43 -0400 Subject: adding xml test case --- nova/tests/api/openstack/test_versions.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_versions.py b/nova/tests/api/openstack/test_versions.py index ee922a8d3..2640a4ddb 100644 --- a/nova/tests/api/openstack/test_versions.py +++ b/nova/tests/api/openstack/test_versions.py @@ -63,6 +63,30 @@ class VersionsTest(test.TestCase): ] self.assertEqual(versions, expected) + def test_get_version_list_xml(self): + req = webob.Request.blank('/') + req.accept = "application/xml" + res = req.get_response(fakes.wsgi_app()) + self.assertEqual(res.status_int, 200) + self.assertEqual(res.content_type, "application/xml") + + expected = """ + + + + + + + + + + + """.replace(" ", "").replace("\n", "") + + actual = res.body.replace(" ", "").replace("\n", "") + + self.assertEqual(expected, actual) + def test_view_builder(self): base_url = "http://example.org/" -- cgit From 2af6fb2a4d3659e9882a6f6d1c8e71bc8f040aba Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Tue, 29 Mar 2011 14:56:18 -0400 Subject: Added content_type to OSAPI faults. --- nova/tests/api/openstack/test_faults.py | 122 ++++++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 20 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index 7667753f4..0cda542de 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -15,6 +15,8 @@ # License for the specific language governing permissions and limitations # under the License. +import json + import webob import webob.dec import webob.exc @@ -24,35 +26,115 @@ from nova.api.openstack import faults class TestFaults(test.TestCase): + """Tests covering `nova.api.openstack.faults:Fault` class.""" - def test_fault_parts(self): - req = webob.Request.blank('/.xml') - f = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram')) - resp = req.get_response(f) + def _prepare_xml(self, xml_string): + """Remove characters from string which hinder XML equality testing.""" + xml_string = xml_string.replace(" ", "") + xml_string = xml_string.replace("\n", "") + xml_string = xml_string.replace("\t", "") + return xml_string - first_two_words = resp.body.strip().split()[:2] - self.assertEqual(first_two_words, ['']) - body_without_spaces = ''.join(resp.body.split()) - self.assertTrue('scram' in body_without_spaces) + def test_400_fault_xml(self): + """Test fault serialized to XML via file-extension and/or header.""" + requests = [ + webob.Request.blank('/.xml'), + webob.Request.blank('/', headers={"Accept": "application/xml"}), + ] - def test_retry_header(self): - req = webob.Request.blank('/.xml') - exc = webob.exc.HTTPRequestEntityTooLarge(explanation='sorry', - headers={'Retry-After': 4}) - f = faults.Fault(exc) - resp = req.get_response(f) - first_two_words = resp.body.strip().split()[:2] - self.assertEqual(first_two_words, ['']) - body_sans_spaces = ''.join(resp.body.split()) - self.assertTrue('sorry' in body_sans_spaces) - self.assertTrue('4' in body_sans_spaces) - self.assertEqual(resp.headers['Retry-After'], 4) + for request in requests: + fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram')) + response = request.get_response(fault) + + expected = self._prepare_xml(""" + + scram + + """) + actual = self._prepare_xml(response.body) + + self.assertEqual(response.content_type, "application/xml") + self.assertEqual(expected, actual) + + def test_400_fault_json(self): + """Test fault serialized to JSON via file-extension and/or header.""" + requests = [ + webob.Request.blank('/.json'), + webob.Request.blank('/', headers={"Accept": "application/json"}), + ] + + for request in requests: + fault = faults.Fault(webob.exc.HTTPBadRequest(explanation='scram')) + response = request.get_response(fault) + + expected = { + "badRequest": { + "message": "scram", + "code": 400, + }, + } + actual = json.loads(response.body) + + self.assertEqual(response.content_type, "application/json") + self.assertEqual(expected, actual) + + def test_413_fault_xml(self): + requests = [ + webob.Request.blank('/.xml'), + webob.Request.blank('/', headers={"Accept": "application/xml"}), + ] + + for request in requests: + exc = webob.exc.HTTPRequestEntityTooLarge + fault = faults.Fault(exc(explanation='sorry', + headers={'Retry-After': 4})) + response = request.get_response(fault) + + expected = self._prepare_xml(""" + + sorry + 4 + + """) + actual = self._prepare_xml(response.body) + + self.assertEqual(expected, actual) + self.assertEqual(response.content_type, "application/xml") + self.assertEqual(response.headers['Retry-After'], 4) + + def test_413_fault_json(self): + """Test fault serialized to JSON via file-extension and/or header.""" + requests = [ + webob.Request.blank('/.json'), + webob.Request.blank('/', headers={"Accept": "application/json"}), + ] + + for request in requests: + exc = webob.exc.HTTPRequestEntityTooLarge + fault = faults.Fault(exc(explanation='sorry', + headers={'Retry-After': 4})) + response = request.get_response(fault) + + expected = { + "overLimit": { + "message": "sorry", + "code": 413, + "retryAfter": 4, + }, + } + actual = json.loads(response.body) + + self.assertEqual(response.content_type, "application/json") + self.assertEqual(expected, actual) def test_raise(self): + """Ensure the ability to raise exceptions in WSGI-ified methods.""" @webob.dec.wsgify def raiser(req): raise faults.Fault(webob.exc.HTTPNotFound(explanation='whut?')) + req = webob.Request.blank('/.xml') resp = req.get_response(raiser) + self.assertEqual(resp.content_type, "application/xml") self.assertEqual(resp.status_int, 404) self.assertTrue('whut?' in resp.body) -- cgit From 05a654211ab902cbb5b1b345dd3285efb1c6bf71 Mon Sep 17 00:00:00 2001 From: Chuck Short Date: Tue, 29 Mar 2011 15:48:02 -0400 Subject: Style fixes --- nova/tests/test_virt.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py index e6beb8e2e..958c8e3e2 100644 --- a/nova/tests/test_virt.py +++ b/nova/tests/test_virt.py @@ -237,13 +237,13 @@ class LibvirtConnTestCase(test.TestCase): network_ref = db.project_get_network(context.get_admin_context(), self.project.id) - fixed_ip = {'address': self.test_ip, - 'network_id': network_ref['id']} + fixed_ip = {'address': self.test_ip, + 'network_id': network_ref['id']} ctxt = context.get_admin_context() fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) db.fixed_ip_update(ctxt, self.test_ip, - {'allocated': True, + {'allocated': True, 'instance_id': instance_ref['id']}) self.flags(libvirt_type='lxc') -- cgit From 93a7a7b94a0d9e4100abb3a4309a3546ab532535 Mon Sep 17 00:00:00 2001 From: Anthony Young Date: Tue, 29 Mar 2011 15:22:16 -0700 Subject: clarify test --- nova/tests/test_compute.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py index 038824ef8..1b0f426d2 100644 --- a/nova/tests/test_compute.py +++ b/nova/tests/test_compute.py @@ -286,7 +286,7 @@ class ComputeTestCase(test.TestCase): console = self.compute.get_ajax_console(self.context, instance_id) - self.assert_(console) + self.assert_(set(['token', 'host', 'port']).issubset(console.keys())) self.compute.terminate_instance(self.context, instance_id) def test_vnc_console(self): -- cgit From e86f58261ee6acb8705106d3de61be0de488d94b Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 29 Mar 2011 15:37:45 -0700 Subject: Reverted extension loading tweaks --- nova/tests/api/openstack/extensions/foxinsocks.py | 98 ++++++++++++++++++++++ .../openstack/extensions/foxinsocks/__init__.py | 19 ----- .../openstack/extensions/foxinsocks/foxinsocks.py | 98 ---------------------- 3 files changed, 98 insertions(+), 117 deletions(-) create mode 100644 nova/tests/api/openstack/extensions/foxinsocks.py delete mode 100644 nova/tests/api/openstack/extensions/foxinsocks/__init__.py delete mode 100644 nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/extensions/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks.py new file mode 100644 index 000000000..0860b51ac --- /dev/null +++ b/nova/tests/api/openstack/extensions/foxinsocks.py @@ -0,0 +1,98 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# 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. + +import json + +from nova import wsgi + +from nova.api.openstack import extensions + + +class FoxInSocksController(wsgi.Controller): + + def index(self, req): + return "Try to say this Mr. Knox, sir..." + + +class Foxinsocks(object): + + def __init__(self): + pass + + def get_name(self): + return "Fox In Socks" + + def get_alias(self): + return "FOXNSOX" + + def get_description(self): + return "The Fox In Socks Extension" + + def get_namespace(self): + return "http://www.fox.in.socks/api/ext/pie/v1.0" + + def get_updated(self): + return "2011-01-22T13:25:27-06:00" + + def get_resources(self): + resources = [] + resource = extensions.ResourceExtension('foxnsocks', + FoxInSocksController()) + resources.append(resource) + return resources + + def get_actions(self): + actions = [] + actions.append(extensions.ActionExtension('servers', 'add_tweedle', + self._add_tweedle)) + actions.append(extensions.ActionExtension('servers', 'delete_tweedle', + self._delete_tweedle)) + return actions + + def get_response_extensions(self): + response_exts = [] + + def _goose_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['flavor']['googoose'] = "Gooey goo for chewy chewing!" + return data + + resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', + _goose_handler) + response_exts.append(resp_ext) + + def _bands_handler(res): + #NOTE: This only handles JSON responses. + # You can use content type header to test for XML. + data = json.loads(res.body) + data['big_bands'] = 'Pig Bands!' + return data + + resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', + _bands_handler) + response_exts.append(resp_ext2) + return response_exts + + def _add_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Added." + + def _delete_tweedle(self, input_dict, req, id): + + return "Tweedle Beetle Deleted." diff --git a/nova/tests/api/openstack/extensions/foxinsocks/__init__.py b/nova/tests/api/openstack/extensions/foxinsocks/__init__.py deleted file mode 100644 index fe505359d..000000000 --- a/nova/tests/api/openstack/extensions/foxinsocks/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# Copyright 2011 Justin Santa Barbara -# All Rights Reserved. -# -# 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.import datetime - -"""Example Fox-in-Socks extension.""" diff --git a/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py b/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py deleted file mode 100644 index 442707714..000000000 --- a/nova/tests/api/openstack/extensions/foxinsocks/foxinsocks.py +++ /dev/null @@ -1,98 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# 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. - -import json - -from nova import wsgi - -from nova.api.openstack import extensions - - -class FoxInSocksController(wsgi.Controller): - - def index(self, req): - return "Try to say this Mr. Knox, sir..." - - -class Foxinsocks(extensions.ExtensionDescriptor): - - def __init__(self): - pass - - def get_name(self): - return "Fox In Socks" - - def get_alias(self): - return "FOXNSOX" - - def get_description(self): - return "The Fox In Socks Extension" - - def get_namespace(self): - return "http://www.fox.in.socks/api/ext/pie/v1.0" - - def get_updated(self): - return "2011-01-22T13:25:27-06:00" - - def get_resources(self): - resources = [] - resource = extensions.ResourceExtension('foxnsocks', - FoxInSocksController()) - resources.append(resource) - return resources - - def get_actions(self): - actions = [] - actions.append(extensions.ActionExtension('servers', 'add_tweedle', - self._add_tweedle)) - actions.append(extensions.ActionExtension('servers', 'delete_tweedle', - self._delete_tweedle)) - return actions - - def get_response_extensions(self): - response_exts = [] - - def _goose_handler(res): - #NOTE: This only handles JSON responses. - # You can use content type header to test for XML. - data = json.loads(res.body) - data['flavor']['googoose'] = "Gooey goo for chewy chewing!" - return data - - resp_ext = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', - _goose_handler) - response_exts.append(resp_ext) - - def _bands_handler(res): - #NOTE: This only handles JSON responses. - # You can use content type header to test for XML. - data = json.loads(res.body) - data['big_bands'] = 'Pig Bands!' - return data - - resp_ext2 = extensions.ResponseExtension('GET', '/v1.1/flavors/:(id)', - _bands_handler) - response_exts.append(resp_ext2) - return response_exts - - def _add_tweedle(self, input_dict, req, id): - - return "Tweedle Beetle Added." - - def _delete_tweedle(self, input_dict, req, id): - - return "Tweedle Beetle Deleted." -- cgit From 4c16db6ad330b0c3a1bdde098bbdcf958fc23bdf Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 29 Mar 2011 18:13:04 -0700 Subject: Rename MockImageService -> FakeImageService --- nova/tests/integrated/integrated_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/integrated/integrated_helpers.py b/nova/tests/integrated/integrated_helpers.py index e0fe2d2a2..2e5d67017 100644 --- a/nova/tests/integrated/integrated_helpers.py +++ b/nova/tests/integrated/integrated_helpers.py @@ -184,7 +184,7 @@ class _IntegratedTestBase(test.TestCase): def _get_flags(self): """An opportunity to setup flags, before the services are started.""" f = {} - f['image_service'] = 'nova.image.fake.MockImageService' + f['image_service'] = 'nova.image.fake.FakeImageService' f['fake_network'] = True return f -- cgit From b1589b5f034db95b1d18910e27cae516258a4311 Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Wed, 30 Mar 2011 09:39:35 -0400 Subject: exception -> Fault --- nova/tests/api/openstack/test_faults.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index 0cda542de..9746e8168 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -128,7 +128,7 @@ class TestFaults(test.TestCase): self.assertEqual(expected, actual) def test_raise(self): - """Ensure the ability to raise exceptions in WSGI-ified methods.""" + """Ensure the ability to raise `Fault`s in WSGI-ified methods.""" @webob.dec.wsgify def raiser(req): raise faults.Fault(webob.exc.HTTPNotFound(explanation='whut?')) -- cgit From 032acaab1fd9a3823e203ddaf9c50857acd25ac7 Mon Sep 17 00:00:00 2001 From: Josh Kearney Date: Thu, 31 Mar 2011 15:32:31 -0500 Subject: Don't include first 4 chars of instance name in adminPass --- nova/tests/api/openstack/test_servers.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index 130b8c5d5..5fbc9837b 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -377,7 +377,6 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) server = json.loads(res.body)['server'] - self.assertEqual('serv', server['adminPass'][:4]) self.assertEqual(16, len(server['adminPass'])) self.assertEqual('server_test', server['name']) self.assertEqual(1, server['id']) @@ -486,7 +485,6 @@ class ServersTest(test.TestCase): res = req.get_response(fakes.wsgi_app()) server = json.loads(res.body)['server'] - self.assertEqual('serv', server['adminPass'][:4]) self.assertEqual(16, len(server['adminPass'])) self.assertEqual('server_test', server['name']) self.assertEqual(1, server['id']) @@ -1426,7 +1424,7 @@ class TestServerInstanceCreation(test.TestCase): self.assertEquals(response.status_int, 200) response = json.loads(response.body) self.assertTrue('adminPass' in response['server']) - self.assertTrue(response['server']['adminPass'].startswith('fake')) + self.assertEqual(16, len(response['server']['adminPass'])) def test_create_instance_admin_pass_xml(self): request, response, dummy = \ @@ -1435,7 +1433,7 @@ class TestServerInstanceCreation(test.TestCase): dom = minidom.parseString(response.body) server = dom.childNodes[0] self.assertEquals(server.nodeName, 'server') - self.assertTrue(server.getAttribute('adminPass').startswith('fake')) + self.assertEqual(16, len(server.getAttribute('adminPass'))) class TestGetKernelRamdiskFromImage(test.TestCase): -- cgit From bd64c4f6bebb50528b87bf6e3f64d7d1cba053df Mon Sep 17 00:00:00 2001 From: Brian Lamar Date: Mon, 4 Apr 2011 10:59:44 -0400 Subject: Fixes error which occurs when no name is specified for an image. --- nova/tests/api/openstack/test_images.py | 57 +++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_images.py b/nova/tests/api/openstack/test_images.py index 57e447dce..69cc3116d 100644 --- a/nova/tests/api/openstack/test_images.py +++ b/nova/tests/api/openstack/test_images.py @@ -263,7 +263,8 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): {'id': 124, 'name': 'queued backup'}, {'id': 125, 'name': 'saving backup'}, {'id': 126, 'name': 'active backup'}, - {'id': 127, 'name': 'killed backup'}] + {'id': 127, 'name': 'killed backup'}, + {'id': 129, 'name': None}] self.assertDictListMatch(response_list, expected) @@ -339,6 +340,24 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): self.assertEqual(expected_image.toxml(), actual_image.toxml()) + def test_get_image_xml_no_name(self): + request = webob.Request.blank('/v1.0/images/129') + request.accept = "application/xml" + response = request.get_response(fakes.wsgi_app()) + + actual_image = minidom.parseString(response.body.replace(" ", "")) + + expected_now = self.NOW_API_FORMAT + expected_image = minidom.parseString(""" + + """ % (locals())) + + self.assertEqual(expected_image.toxml(), actual_image.toxml()) + def test_get_image_v1_1_xml(self): request = webob.Request.blank('/v1.1/images/123') request.accept = "application/xml" @@ -516,6 +535,13 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): 'updated': self.NOW_API_FORMAT, 'created': self.NOW_API_FORMAT, 'status': 'FAILED', + }, + { + 'id': 129, + 'name': None, + 'updated': self.NOW_API_FORMAT, + 'created': self.NOW_API_FORMAT, + 'status': 'ACTIVE', }] self.assertDictListMatch(expected, response_list) @@ -635,7 +661,29 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): "type": "application/xml", "href": "http://localhost/v1.1/images/127", }], - }] + }, + { + 'id': 129, + 'name': None, + 'updated': self.NOW_API_FORMAT, + 'created': self.NOW_API_FORMAT, + 'status': 'ACTIVE', + "links": [{ + "rel": "self", + "href": "http://localhost/v1.1/images/129", + }, + { + "rel": "bookmark", + "type": "application/json", + "href": "http://localhost/v1.1/images/129", + }, + { + "rel": "bookmark", + "type": "application/xml", + "href": "http://localhost/v1.1/images/129", + }], + }, + ] self.assertDictListMatch(expected, response_list) @@ -694,4 +742,9 @@ class ImageControllerWithGlanceServiceTest(test.TestCase): status='active', properties=other_backup_properties) image_id += 1 + # Image without a name + add_fixture(id=image_id, is_public=True, status='active', + properties={}) + image_id += 1 + return fixtures -- cgit From fc53de592fb903f8a7e3741fa98d03140aca9066 Mon Sep 17 00:00:00 2001 From: Ken Pepple Date: Mon, 4 Apr 2011 09:45:26 -0700 Subject: corrected capitalization of openstack api status and added tests --- nova/tests/api/openstack/test_servers.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/tests') diff --git a/nova/tests/api/openstack/test_servers.py b/nova/tests/api/openstack/test_servers.py index d32e8eea8..cf55c8383 100644 --- a/nova/tests/api/openstack/test_servers.py +++ b/nova/tests/api/openstack/test_servers.py @@ -631,6 +631,7 @@ class ServersTest(test.TestCase): self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageId'], '10') self.assertEqual(s['flavorId'], '1') + self.assertEqual(s['status'], 'BUILD') self.assertEqual(s['metadata']['seq'], i) def test_get_all_server_details_v1_1(self): @@ -644,6 +645,7 @@ class ServersTest(test.TestCase): self.assertEqual(s['name'], 'server%d' % i) self.assertEqual(s['imageRef'], 'http://localhost/v1.1/images/10') self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1') + self.assertEqual(s['status'], 'BUILD') self.assertEqual(s['metadata']['seq'], i) def test_get_all_server_details_with_host(self): -- cgit