Refactor test_rescue_unrescue into compute api/manager unit tests

As part of converting the rescue/unrescue compute API flows to using
objects, i.e. dot notation for accessing attributes on the instance
object and updating the database via instance.save() rather than
compute_api.update, we want to move some of the integration-style tests
found in test_compute.py to test_compute_api.py and test_compute_mgr.py.

This is to help with the conversion so we don't have to use exotic stubs
in the cells API flows to make integration tests work.

This change is mainly concerned with moving test_rescue_unrescue out of
test_compute.py and into the api/manager specific test modules and then
later changes will build on top of the new tests.

Part of blueprint compute-manager-objects-juno

Change-Id: I2a9b1c6b5a1f41272e26c20de134a2a8b71c88f3
This commit is contained in:
Matt Riedemann
2014-05-28 13:09:44 -07:00
parent 5a7eb3aa68
commit 13ad851e49
3 changed files with 172 additions and 29 deletions

View File

@@ -7443,35 +7443,6 @@ class ComputeAPITestCase(BaseTestCase):
self.compute.terminate_instance(self.context,
self._objectify(inst_ref), [], [])
def test_rescue_unrescue(self):
instance = jsonutils.to_primitive(self._create_fake_instance())
instance_uuid = instance['uuid']
self.compute.run_instance(self.context, instance, {}, {}, None, None,
None, True, None, False)
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
self.assertIsNone(instance['task_state'])
self.compute_api.rescue(self.context, self._objectify(instance))
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['vm_state'], vm_states.ACTIVE)
self.assertEqual(instance['task_state'], task_states.RESCUING)
params = {'vm_state': vm_states.RESCUED, 'task_state': None}
db.instance_update(self.context, instance_uuid, params)
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.compute_api.unrescue(self.context, self._objectify(instance))
instance = db.instance_get_by_uuid(self.context, instance_uuid)
self.assertEqual(instance['vm_state'], vm_states.RESCUED)
self.assertEqual(instance['task_state'], task_states.UNRESCUING)
self.compute.terminate_instance(self.context,
self._objectify(instance), [], [])
def _fake_rescue_block_devices(self, instance, status="in-use"):
fake_bdms = block_device_obj.block_device_make_list(self.context,
[fake_block_device.FakeDbBlockDeviceDict(

View File

@@ -13,6 +13,7 @@
"""Unit tests for compute API."""
import contextlib
import copy
import datetime
import iso8601
@@ -2004,6 +2005,67 @@ class _ComputeAPIUnitTestMixIn(object):
fake_index)
destroy.assert_called_once_with(self.context)
def _test_rescue(self, vm_state):
instance = self._create_instance_obj(params={'vm_state': vm_state})
bdms = []
with contextlib.nested(
mock.patch.object(block_device_obj.BlockDeviceMappingList,
'get_by_instance_uuid', return_value=bdms),
mock.patch.object(self.compute_api, 'is_volume_backed_instance',
return_value=False),
mock.patch.object(self.compute_api, 'update'),
mock.patch.object(self.compute_api, '_record_action_start'),
mock.patch.object(self.compute_api.compute_rpcapi,
'rescue_instance')
) as (
bdm_get_by_instance_uuid, volume_backed_inst, compute_api_update,
record_action_start, rpcapi_rescue_instance
):
self.compute_api.rescue(self.context, instance)
# assert our mock calls
bdm_get_by_instance_uuid.assert_called_once_with(
self.context, instance.uuid)
volume_backed_inst.assert_called_once_with(
self.context, instance, bdms)
compute_api_update.assert_called_once_with(
self.context, instance, task_state=task_states.RESCUING,
expected_task_state=[None])
record_action_start.assert_called_once_with(
self.context, instance, instance_actions.RESCUE)
rpcapi_rescue_instance.assert_called_once_with(
self.context, instance=instance, rescue_password=None,
rescue_image_ref=None)
def test_rescue_active(self):
self._test_rescue(vm_state=vm_states.ACTIVE)
def test_rescue_stopped(self):
self._test_rescue(vm_state=vm_states.STOPPED)
def test_rescue_error(self):
self._test_rescue(vm_state=vm_states.ERROR)
def test_unrescue(self):
instance = self._create_instance_obj(
params={'vm_state': vm_states.RESCUED})
with contextlib.nested(
mock.patch.object(self.compute_api, 'update'),
mock.patch.object(self.compute_api, '_record_action_start'),
mock.patch.object(self.compute_api.compute_rpcapi,
'unrescue_instance')
) as (
compute_api_update, record_action_start, rpcapi_unrescue_instance
):
self.compute_api.unrescue(self.context, instance)
# assert our mock calls
compute_api_update.assert_called_once_with(
self.context, instance, task_state=task_states.UNRESCUING,
expected_task_state=[None])
record_action_start.assert_called_once_with(
self.context, instance, instance_actions.UNRESCUE)
rpcapi_unrescue_instance.assert_called_once_with(
self.context, instance=instance)
class ComputeAPIUnitTestCase(_ComputeAPIUnitTestMixIn, test.NoDBTestCase):
def setUp(self):

View File

@@ -1211,6 +1211,116 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase):
{'uuid': 'fake-inst'})
detach.assert_called_once_with(self.context, inst_obj, bdm)
def test_rescue(self):
instance = fake_instance.fake_instance_obj(
self.context, vm_state=vm_states.ACTIVE)
fake_nw_info = network_model.NetworkInfo()
rescue_image_meta = {'id': 'fake', 'name': 'fake'}
with contextlib.nested(
mock.patch.object(instance_action_obj.InstanceActionEvent,
'event_start'),
mock.patch.object(instance_action_obj.InstanceActionEvent,
'event_finish_with_failure'),
mock.patch.object(self.context, 'elevated',
return_value=self.context),
mock.patch.object(self.compute, '_get_instance_nw_info',
return_value=fake_nw_info),
mock.patch.object(self.compute, '_get_rescue_image',
return_value=rescue_image_meta),
mock.patch.object(self.compute, '_notify_about_instance_usage'),
mock.patch.object(self.compute.driver, 'rescue'),
mock.patch.object(self.compute.conductor_api,
'notify_usage_exists'),
mock.patch.object(self.compute, '_get_power_state',
return_value=power_state.RUNNING),
mock.patch.object(instance, 'save')
) as (
event_start, event_finish, elevated_context, get_nw_info,
get_rescue_image, notify_instance_usage, driver_rescue,
notify_usage_exists, get_power_state, instance_save
):
self.compute.rescue_instance(
self.context, instance, rescue_password='verybadpass',
rescue_image_ref=None)
# assert the field values on the instance object
self.assertEqual(vm_states.RESCUED, instance.vm_state)
self.assertIsNone(instance.task_state)
self.assertEqual(power_state.RUNNING, instance.power_state)
self.assertIsNotNone(instance.launched_at)
# assert our mock calls
get_nw_info.assert_called_once_with(self.context, instance)
get_rescue_image.assert_called_once_with(
self.context, instance, None)
extra_usage_info = {'rescue_image_name': 'fake'}
notify_calls = [
mock.call(self.context, instance, "rescue.start",
extra_usage_info=extra_usage_info,
network_info=fake_nw_info),
mock.call(self.context, instance, "rescue.end",
extra_usage_info=extra_usage_info,
network_info=fake_nw_info)
]
notify_instance_usage.assert_has_calls(notify_calls)
driver_rescue.assert_called_once_with(
self.context, instance, fake_nw_info, rescue_image_meta,
'verybadpass')
notify_usage_exists.assert_called_once_with(
self.context, instance, current_period=True)
instance_save.assert_called_once_with(
expected_task_state=task_states.RESCUING)
def test_unrescue(self):
instance = fake_instance.fake_instance_obj(
self.context, vm_state=vm_states.RESCUED)
fake_nw_info = network_model.NetworkInfo()
with contextlib.nested(
mock.patch.object(instance_action_obj.InstanceActionEvent,
'event_start'),
mock.patch.object(instance_action_obj.InstanceActionEvent,
'event_finish_with_failure'),
mock.patch.object(self.context, 'elevated',
return_value=self.context),
mock.patch.object(self.compute, '_get_instance_nw_info',
return_value=fake_nw_info),
mock.patch.object(self.compute, '_notify_about_instance_usage'),
mock.patch.object(self.compute.driver, 'unrescue'),
mock.patch.object(self.compute, '_get_power_state',
return_value=power_state.RUNNING),
mock.patch.object(instance, 'save')
) as (
event_start, event_finish, elevated_context, get_nw_info,
notify_instance_usage, driver_unrescue, get_power_state,
instance_save
):
self.compute.unrescue_instance(self.context, instance)
# assert the field values on the instance object
self.assertEqual(vm_states.ACTIVE, instance.vm_state)
self.assertIsNone(instance.task_state)
self.assertEqual(power_state.RUNNING, instance.power_state)
# assert our mock calls
get_nw_info.assert_called_once_with(self.context, instance)
notify_calls = [
mock.call(self.context, instance, "unrescue.start",
network_info=fake_nw_info),
mock.call(self.context, instance, "unrescue.end",
network_info=fake_nw_info)
]
notify_instance_usage.assert_has_calls(notify_calls)
driver_unrescue.assert_called_once_with(instance, fake_nw_info)
instance_save.assert_called_once_with(
expected_task_state=task_states.UNRESCUING)
class ComputeManagerBuildInstanceTestCase(test.NoDBTestCase):
def setUp(self):