diff --git a/ironic_inspector/process.py b/ironic_inspector/process.py index e7bc57546..b95c0fdcb 100644 --- a/ironic_inspector/process.py +++ b/ironic_inspector/process.py @@ -23,6 +23,7 @@ import json from oslo_config import cfg from oslo_serialization import base64 from oslo_utils import excutils +from oslo_utils import timeutils from ironic_inspector.common.i18n import _, _LE, _LI, _LW from ironic_inspector.common import ironic as ir_utils @@ -389,6 +390,8 @@ def reapply(node_ident): def _reapply(node_info): # runs in background try: + node_info.started_at = timeutils.utcnow() + node_info.commit() introspection_data = _get_unprocessed_data(node_info.uuid) except Exception as exc: LOG.exception(_LE('Encountered exception while fetching ' diff --git a/ironic_inspector/test/functional.py b/ironic_inspector/test/functional.py index 665a36f42..efe531f8c 100644 --- a/ironic_inspector/test/functional.py +++ b/ironic_inspector/test/functional.py @@ -561,6 +561,7 @@ class Test(Base): eventlet.greenthread.sleep(DEFAULT_SLEEP) status = self.call_get_status(self.uuid) + inspect_started_at = timeutils.parse_isotime(status['started_at']) self.check_status(status, finished=True) res = self.call_reapply(self.uuid) @@ -568,6 +569,13 @@ class Test(Base): self.assertEqual('', res.text) eventlet.greenthread.sleep(DEFAULT_SLEEP) + status = self.call_get_status(self.uuid) + self.check_status(status, finished=True) + + # checks the started_at updated in DB is correct + reapply_started_at = timeutils.parse_isotime(status['started_at']) + self.assertLess(inspect_started_at, reapply_started_at) + # reapply request data get_mock.assert_called_once_with(self.uuid, suffix='UNPROCESSED') diff --git a/ironic_inspector/test/unit/test_process.py b/ironic_inspector/test/unit/test_process.py index 6d38f2558..c830141d3 100644 --- a/ironic_inspector/test/unit/test_process.py +++ b/ironic_inspector/test/unit/test_process.py @@ -613,6 +613,9 @@ class TestReapplyNode(BaseTest): self.cli.node.update.return_value = self.node self.cli.node.list_ports.return_value = [] self.node_info._state = istate.States.finished + self.commit_fixture = self.useFixture( + fixtures.MockPatchObject(node_cache.NodeInfo, 'commit', + autospec=True)) db.Node(uuid=self.node_info.uuid, state=self.node_info._state, started_at=self.node_info.started_at, finished_at=self.node_info.finished_at, @@ -641,6 +644,8 @@ class TestReapplyNode(BaseTest): self.call() + self.commit_fixture.mock.assert_called_once_with(self.node_info) + post_hook_mock.assert_called_once_with(mock.ANY, self.node_info) swift_mock.create_object.assert_called_once_with(swift_name, mock.ANY) @@ -668,13 +673,14 @@ class TestReapplyNode(BaseTest): @prepare_mocks def test_get_incomming_data_exception(self, finished_mock, swift_mock, apply_mock, - post_hook_mock, ): + post_hook_mock): exc = Exception('Oops') expected_error = ('Unexpected exception Exception while fetching ' 'unprocessed introspection data from Swift: Oops') swift_mock.get_object.side_effect = exc self.call() + self.commit_fixture.mock.assert_called_once_with(self.node_info) self.assertFalse(swift_mock.create_object.called) self.assertFalse(apply_mock.called) self.assertFalse(post_hook_mock.called) @@ -683,7 +689,7 @@ class TestReapplyNode(BaseTest): @prepare_mocks def test_prehook_failure(self, finished_mock, swift_mock, - apply_mock, post_hook_mock, ): + apply_mock, post_hook_mock): CONF.set_override('processing_hooks', 'example', 'processing') plugins_base._HOOKS_MGR = None diff --git a/releasenotes/notes/Reapply_update_started_at-8af8cf254cdf8cde.yaml b/releasenotes/notes/Reapply_update_started_at-8af8cf254cdf8cde.yaml new file mode 100644 index 000000000..45c6869c8 --- /dev/null +++ b/releasenotes/notes/Reapply_update_started_at-8af8cf254cdf8cde.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - The POST /v1/introspection//data/unprocessed API updates the + started_at time when ironic inspector begins processing the node.