diff options
author | Kevin_Zheng <zhengzhenyu@huawei.com> | 2017-11-29 11:37:43 +0800 |
---|---|---|
committer | Matt Riedemann <mriedem.os@gmail.com> | 2017-12-08 15:19:54 -0500 |
commit | 0aa7aafdd754629e1b3922853fa0b441ace76330 (patch) | |
tree | fa111a6f347c1d1dba331b4c37fa4598acaf99b7 | |
parent | 1d88440eb421929438e77c637caf502075b43f56 (diff) | |
download | nova-0aa7aafdd754629e1b3922853fa0b441ace76330.tar.gz |
Add instance action record for backup instances
We currently don't record backup instance
actions. This is useful for auditing and debugging.
This patch adds instance backup actions.
Note that because of how backup works for cellsv1, the API
call from the top isn't replayed in the child cell, so we
have to create the instance action in nova/cells/messaging
so the action is in the child cell database when nova-compute
looks it up via wrap_instance_event.
Change-Id: I878015fa211a5f2b5062902b3bfbd571d56efb76
partial-implements: blueprint fill-the-gap-for-instance-action-records
-rw-r--r-- | nova/cells/messaging.py | 6 | ||||
-rw-r--r-- | nova/compute/api.py | 3 | ||||
-rw-r--r-- | nova/compute/instance_actions.py | 1 | ||||
-rw-r--r-- | nova/compute/manager.py | 1 | ||||
-rw-r--r-- | nova/tests/unit/cells/test_cells_messaging.py | 9 | ||||
-rw-r--r-- | nova/tests/unit/compute/test_compute.py | 15 | ||||
-rw-r--r-- | nova/tests/unit/compute/test_compute_api.py | 6 | ||||
-rw-r--r-- | releasenotes/notes/fill-instance-action-record-gaps-14b36eba313d6d87.yaml | 1 |
8 files changed, 34 insertions, 8 deletions
diff --git a/nova/cells/messaging.py b/nova/cells/messaging.py index 75fb015cb7..f7e7c575fc 100644 --- a/nova/cells/messaging.py +++ b/nova/cells/messaging.py @@ -44,6 +44,7 @@ from six.moves import range from nova.cells import state as cells_state from nova.cells import utils as cells_utils from nova import compute +from nova.compute import instance_actions from nova.compute import rpcapi as compute_rpcapi from nova.compute import task_states from nova.compute import vm_states @@ -918,6 +919,11 @@ class _TargetedMessageMethods(_BaseMessageMethods): instance.refresh() instance.task_state = task_states.IMAGE_BACKUP instance.save(expected_task_state=[None]) + + objects.InstanceAction.action_start( + message.ctxt, instance.uuid, instance_actions.BACKUP, + want_result=False) + self.compute_rpcapi.backup_instance(message.ctxt, instance, image_id, diff --git a/nova/compute/api.py b/nova/compute/api.py index 85a4a8d429..7b1b94b37b 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2597,6 +2597,9 @@ class API(base.Base): instance.task_state = task_states.IMAGE_BACKUP instance.save(expected_task_state=[None]) + self._record_action_start(context, instance, + instance_actions.BACKUP) + self.compute_rpcapi.backup_instance(context, instance, image_meta['id'], backup_type, diff --git a/nova/compute/instance_actions.py b/nova/compute/instance_actions.py index fe5e5448f6..ec6e0e77a3 100644 --- a/nova/compute/instance_actions.py +++ b/nova/compute/instance_actions.py @@ -68,3 +68,4 @@ DETACH_VOLUME = 'detach_volume' SWAP_VOLUME = 'swap_volume' LOCK = 'lock' UNLOCK = 'unlock' +BACKUP = 'createBackup' diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 046e443db8..fbb19dde65 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -3215,6 +3215,7 @@ class ComputeManager(manager.Manager): @wrap_exception() @reverts_task_state + @wrap_instance_event(prefix='compute') @wrap_instance_fault def backup_instance(self, context, image_id, instance, backup_type, rotation): diff --git a/nova/tests/unit/cells/test_cells_messaging.py b/nova/tests/unit/cells/test_cells_messaging.py index 3e3640727a..5d6d5f2cd6 100644 --- a/nova/tests/unit/cells/test_cells_messaging.py +++ b/nova/tests/unit/cells/test_cells_messaging.py @@ -26,6 +26,7 @@ from oslo_utils import timeutils from nova.cells import messaging from nova.cells import rpcapi as cells_rpcapi from nova.cells import utils as cells_utils +from nova.compute import instance_actions from nova.compute import task_states from nova.compute import vm_states import nova.conf @@ -1371,8 +1372,9 @@ class CellsTargetedMethodsTestCase(test.NoDBTestCase): meth_cls.snapshot_instance(message, inst, image_id='image-id') - def test_backup_instance(self): - inst = objects.Instance() + @mock.patch.object(objects.InstanceAction, 'action_start') + def test_backup_instance(self, action_start): + inst = objects.Instance(uuid=uuids.instance) meth_cls = self.tgt_methods_cls self.mox.StubOutWithMock(inst, 'refresh') @@ -1404,6 +1406,9 @@ class CellsTargetedMethodsTestCase(test.NoDBTestCase): image_id='image-id', backup_type='backup-type', rotation='rotation') + action_start.assert_called_once_with( + message.ctxt, inst.uuid, instance_actions.BACKUP, + want_result=False) def test_set_admin_password(self): args = ['fake-password'] diff --git a/nova/tests/unit/compute/test_compute.py b/nova/tests/unit/compute/test_compute.py index 220a873c26..3f74ca25f6 100644 --- a/nova/tests/unit/compute/test_compute.py +++ b/nova/tests/unit/compute/test_compute.py @@ -3398,11 +3398,16 @@ class ComputeTestCase(BaseTestCase, self.context, image_id='fakesnap', instance=inst_obj) else: - self.assertRaises(test.TestingException, - self.compute.backup_instance, - self.context, image_id='fakesnap', - instance=inst_obj, backup_type='fake', - rotation=1) + with mock.patch.object(compute_utils, + 'EventReporter') as mock_event: + self.assertRaises(test.TestingException, + self.compute.backup_instance, + self.context, image_id='fakesnap', + instance=inst_obj, backup_type='fake', + rotation=1) + mock_event.assert_called_once_with(self.context, + 'compute_backup_instance', + inst_obj.uuid) self.assertEqual(expected_state, self.fake_image_delete_called) self._assert_state({'task_state': None}) diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index abc5ded184..8eb4aee888 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -2485,7 +2485,8 @@ class _ComputeAPIUnitTestMixIn(object): _do_test() - def _test_snapshot_and_backup(self, is_snapshot=True, + @mock.patch.object(compute_api.API, '_record_action_start') + def _test_snapshot_and_backup(self, mock_record, is_snapshot=True, with_base_ref=False, min_ram=None, min_disk=None, create_fails=False, @@ -2599,6 +2600,9 @@ class _ComputeAPIUnitTestMixIn(object): 'fake-backup-type', 'fake-rotation', extra_properties=extra_props) + mock_record.assert_called_once_with(self.context, + instance, + instance_actions.BACKUP) self.assertEqual(fake_image, res) except test.TestingException: got_exc = True diff --git a/releasenotes/notes/fill-instance-action-record-gaps-14b36eba313d6d87.yaml b/releasenotes/notes/fill-instance-action-record-gaps-14b36eba313d6d87.yaml index a60a723acd..817117d91e 100644 --- a/releasenotes/notes/fill-instance-action-record-gaps-14b36eba313d6d87.yaml +++ b/releasenotes/notes/fill-instance-action-record-gaps-14b36eba313d6d87.yaml @@ -11,3 +11,4 @@ features: * lock * unlock * shelveOffload + * createBackup |