From 43d811bc86b8bf7342ce108e175f3cbd67d14cda Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Mon, 1 Jul 2013 20:54:30 +0000 Subject: Break out compute API unit tests As we convert things to objects, it'll be easier to convert our compute API tests to be true unit tests if they are in their own class. This also allows us to move away from the hacks needed to simulate 2 DBs in order to test ComputeCellsAPI(). There are currently a handful of tests that are true unit tests and require no DB access. These are now moved, subclassing from test.NoDBTestCase. Related to blueprint unified-object-model Change-Id: I72f4f6ada8d0586e813e551a1b361bcebb16ee66 --- nova/tests/compute/test_compute.py | 119 ------------------ nova/tests/compute/test_compute_api.py | 214 +++++++++++++++++++++++++++++++++ 2 files changed, 214 insertions(+), 119 deletions(-) create mode 100644 nova/tests/compute/test_compute_api.py diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 2ac8b22b8..73e260990 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -35,7 +35,6 @@ from nova import block_device from nova import compute from nova.compute import api as compute_api from nova.compute import flavors -from nova.compute import instance_actions from nova.compute import manager as compute_manager from nova.compute import power_state from nova.compute import rpcapi as compute_rpcapi @@ -273,24 +272,6 @@ class BaseTestCase(test.TestCase): {'fake_zone': [inst['host']]}) return db.instance_create(self.context, inst) - def _create_instance_obj(self, params=None, type_name='m1.tiny'): - """Create a test instance object.""" - instance = instance_obj.Instance() - instance.uuid = uuidutils.generate_uuid() - instance.cell_name = 'api!child' - - def _fake_db_create(_ctxt, inst): - for k, v in inst.items(): - if k == 'security_groups': - setattr(instance, k, v or None) - else: - setattr(instance, k, v) - return instance - - self.stubs.Set(db, 'instance_create', _fake_db_create) - return self._create_fake_instance(params=params, - type_name=type_name) - def _create_instance(self, params=None, type_name='m1.tiny'): """Create a test instance. Returns uuid.""" return self._create_fake_instance(params, type_name=type_name) @@ -5780,106 +5761,6 @@ class ComputeAPITestCase(BaseTestCase): finally: db.instance_destroy(self.context, ref[0]['uuid']) - def test_start(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.vm_state = vm_states.STOPPED - - self.mox.StubOutWithMock(instance, 'save') - self.mox.StubOutWithMock(self.compute_api, - '_record_action_start') - self.mox.StubOutWithMock( - self.compute_api.compute_rpcapi, - 'start_instance') - - instance.save(expected_task_state=None) - self.compute_api._record_action_start(self.context, - instance, instance_actions.START) - self.compute_api.compute_rpcapi.start_instance( - self.context, instance) - - self.mox.ReplayAll() - - self.compute_api.start(self.context, instance) - self.assertEqual(task_states.POWERING_ON, - instance.task_state) - - def test_start_invalid_state(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.vm_state = vm_states.ACTIVE - self.assertRaises(exception.InstanceInvalidState, - self.compute_api.start, - self.context, instance) - - def test_start_no_host(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.vm_state = vm_states.STOPPED - instance.host = '' - self.assertRaises(exception.InstanceNotReady, - self.compute_api.start, - self.context, instance) - - def test_stop(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.task_state = None - # Make sure this gets reset - instance.progress = 99 - - self.mox.StubOutWithMock(instance, 'save') - self.mox.StubOutWithMock(self.compute_api, - '_record_action_start') - self.mox.StubOutWithMock( - self.compute_api.compute_rpcapi, - 'stop_instance') - - instance.save(expected_task_state=None) - self.compute_api._record_action_start(self.context, - instance, instance_actions.STOP) - self.compute_api.compute_rpcapi.stop_instance( - self.context, instance, cast=True) - - self.mox.ReplayAll() - - self.compute_api.stop(self.context, instance) - self.assertEqual(task_states.POWERING_OFF, - instance.task_state) - self.assertEqual(0, instance.progress) - - def test_stop_invalid_state(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.vm_state = vm_states.PAUSED - self.assertRaises(exception.InstanceInvalidState, - self.compute_api.stop, - self.context, instance) - - def test_stop_a_stopped_inst(self): - instance = jsonutils.to_primitive(self._create_fake_instance( - {'vm_state': vm_states.STOPPED})) - - self.assertRaises(exception.InstanceInvalidState, - self.compute_api.stop, - self.context, instance) - - db.instance_destroy(self.context, instance['uuid']) - - def test_stop_no_host(self): - # Undo setUp() stubs (test_compute_cells) - self.stubs.UnsetAll() - instance = self._create_instance_obj() - instance.host = '' - self.assertRaises(exception.InstanceNotReady, - self.compute_api.stop, - self.context, instance) - def test_delete(self): instance, instance_uuid = self._run_instance(params={ 'host': CONF.host}) diff --git a/nova/tests/compute/test_compute_api.py b/nova/tests/compute/test_compute_api.py new file mode 100644 index 000000000..1463af6dd --- /dev/null +++ b/nova/tests/compute/test_compute_api.py @@ -0,0 +1,214 @@ +# +# 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 compute API.""" + +from nova.compute import api as compute_api +from nova.compute import cells_api as compute_cells_api +from nova.compute import flavors +from nova.compute import instance_actions +from nova.compute import task_states +from nova.compute import vm_states +from nova import context +from nova import exception +from nova.objects import instance as instance_obj +from nova.openstack.common import timeutils +from nova.openstack.common import uuidutils +from nova import test + + +FAKE_IMAGE_REF = 'fake-image-ref' +NODENAME = 'fakenode1' + + +class _ComputeAPIUnitTestMixIn(object): + def setUp(self): + super(_ComputeAPIUnitTestMixIn, self).setUp() + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, + self.project_id) + + def _create_flavor(self, params=None): + flavor = {'id': 1, + 'flavorid': 1, + 'name': 'm1.tiny', + 'memory_mb': 512, + 'vcpus': 1, + 'vcpu_weight': None, + 'root_gb': 1, + 'ephemeral_gb': 0, + 'rxtx_factor': 1, + 'swap': 0, + 'deleted': 0, + 'disabled': False, + 'is_public': True, + } + if params: + flavor.update(params) + return flavor + + def _create_instance_obj(self, params=None, flavor=None): + """Create a test instance.""" + if not params: + params = {} + + if flavor is None: + flavor = self._create_flavor() + + def make_fake_sys_meta(): + sys_meta = {} + for key in flavors.system_metadata_flavor_props: + sys_meta['instance_type_%s' % key] = flavor[key] + return sys_meta + + now = timeutils.utcnow() + + instance = instance_obj.Instance() + instance.id = 1 + instance.uuid = uuidutils.generate_uuid() + instance.cell_name = 'api!child' + instance.vm_state = vm_states.ACTIVE + instance.task_state = None + instance.image_ref = FAKE_IMAGE_REF + instance.reservation_id = 'r-fakeres' + instance.user_id = self.user_id + instance.project_id = self.project_id + instance.host = 'fake_host' + instance.node = NODENAME + instance.instance_type_id = flavor['id'] + instance.ami_launch_index = 0 + instance.memory_mb = 0 + instance.vcpus = 0 + instance.root_gb = 0 + instance.ephemeral_gb = 0 + instance.architecture = 'x86_64' + instance.os_type = 'Linux' + instance.system_metadata = make_fake_sys_meta() + instance.locked = False + instance.created_at = now + instance.updated_at = now + instance.launched_at = now + + if params: + instance.update(params) + instance.obj_reset_changes() + return instance + + def test_start(self): + params = dict(vm_state=vm_states.STOPPED) + instance = self._create_instance_obj(params=params) + + self.mox.StubOutWithMock(instance, 'save') + self.mox.StubOutWithMock(self.compute_api, + '_record_action_start') + self.mox.StubOutWithMock( + self.compute_api.compute_rpcapi, + 'start_instance') + + instance.save(expected_task_state=None) + self.compute_api._record_action_start(self.context, + instance, instance_actions.START) + self.compute_api.compute_rpcapi.start_instance( + self.context, instance) + + if self.is_cells: + self.mox.StubOutWithMock(self.compute_api, '_cast_to_cells') + self.compute_api._cast_to_cells( + self.context, instance, 'start') + + self.mox.ReplayAll() + + self.compute_api.start(self.context, instance) + self.assertEqual(task_states.POWERING_ON, + instance.task_state) + + def test_start_invalid_state(self): + instance = self._create_instance_obj() + self.assertEqual(instance.vm_state, vm_states.ACTIVE) + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.start, + self.context, instance) + + def test_start_no_host(self): + params = dict(vm_state=vm_states.STOPPED, host='') + instance = self._create_instance_obj(params=params) + self.assertRaises(exception.InstanceNotReady, + self.compute_api.start, + self.context, instance) + + def test_stop(self): + # Make sure 'progress' gets reset + params = dict(task_state=None, progress=99) + instance = self._create_instance_obj(params=params) + + self.mox.StubOutWithMock(instance, 'save') + self.mox.StubOutWithMock(self.compute_api, + '_record_action_start') + self.mox.StubOutWithMock( + self.compute_api.compute_rpcapi, + 'stop_instance') + + instance.save(expected_task_state=None) + self.compute_api._record_action_start(self.context, + instance, instance_actions.STOP) + self.compute_api.compute_rpcapi.stop_instance( + self.context, instance, cast=True) + + if self.is_cells: + self.mox.StubOutWithMock(self.compute_api, '_cast_to_cells') + self.compute_api._cast_to_cells( + self.context, instance, 'stop', do_cast=True) + + self.mox.ReplayAll() + + self.compute_api.stop(self.context, instance) + self.assertEqual(task_states.POWERING_OFF, + instance.task_state) + self.assertEqual(0, instance.progress) + + def test_stop_invalid_state(self): + params = dict(vm_state=vm_states.PAUSED) + instance = self._create_instance_obj(params=params) + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.stop, + self.context, instance) + + def test_stop_a_stopped_inst(self): + params = {'vm_state': vm_states.STOPPED} + instance = self._create_instance_obj(params=params) + + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.stop, + self.context, instance) + + def test_stop_no_host(self): + params = {'host': ''} + instance = self._create_instance_obj(params=params) + self.assertRaises(exception.InstanceNotReady, + self.compute_api.stop, + self.context, instance) + + +class ComputeAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase): + def setUp(self): + super(ComputeAPIUnitTestCase, self).setUp() + self.compute_api = compute_api.API() + self.is_cells = False + + +class ComputeCellsAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase): + def setUp(self): + super(ComputeCellsAPIUnitTestCase, self).setUp() + self.compute_api = compute_cells_api.ComputeCellsAPI() + self.is_cells = True -- cgit