diff --git a/ironic/db/sqlalchemy/api.py b/ironic/db/sqlalchemy/api.py index de39343181..a3d671f50c 100644 --- a/ironic/db/sqlalchemy/api.py +++ b/ironic/db/sqlalchemy/api.py @@ -904,11 +904,13 @@ class Connection(api.Connection): if values['provision_state'] == states.INSPECTING: values['inspection_started_at'] = timeutils.utcnow() values['inspection_finished_at'] = None - elif (ref.provision_state == states.INSPECTING + elif ((ref.provision_state == states.INSPECTING + or ref.provision_state == states.INSPECTWAIT) and values['provision_state'] == states.MANAGEABLE): values['inspection_finished_at'] = timeutils.utcnow() values['inspection_started_at'] = None - elif (ref.provision_state == states.INSPECTING + elif ((ref.provision_state == states.INSPECTING + or ref.provision_state == states.INSPECTWAIT) and values['provision_state'] == states.INSPECTFAIL): values['inspection_started_at'] = None diff --git a/ironic/tests/unit/db/test_nodes.py b/ironic/tests/unit/db/test_nodes.py index 78bba0a35d..e234fc634c 100644 --- a/ironic/tests/unit/db/test_nodes.py +++ b/ironic/tests/unit/db/test_nodes.py @@ -884,6 +884,53 @@ class DbNodeTestCase(base.DbTestCase): timeutils.normalize_time(result)) self.assertIsNone(res['inspection_started_at']) + @mock.patch.object(timeutils, 'utcnow', autospec=True) + def test_update_node_inspection_finished_at_inspecting(self, mock_utcnow): + mocked_time = datetime.datetime(2000, 1, 1, 0, 0) + mock_utcnow.return_value = mocked_time + node = utils.create_test_node(uuid=uuidutils.generate_uuid(), + inspection_finished_at=mocked_time, + provision_state=states.INSPECTING) + res = self.dbapi.update_node(node.id, + {'provision_state': states.MANAGEABLE}) + result = res['inspection_finished_at'] + self.assertEqual(mocked_time, + timeutils.normalize_time(result)) + self.assertIsNone(res['inspection_started_at']) + + @mock.patch.object(timeutils, 'utcnow', autospec=True) + def test_update_node_inspection_finished_at_inspectwait(self, + mock_utcnow): + mocked_time = datetime.datetime(2000, 1, 1, 0, 0) + mock_utcnow.return_value = mocked_time + node = utils.create_test_node(uuid=uuidutils.generate_uuid(), + inspection_finished_at=mocked_time, + provision_state=states.INSPECTWAIT) + res = self.dbapi.update_node(node.id, + {'provision_state': states.MANAGEABLE}) + result = res['inspection_finished_at'] + self.assertEqual(mocked_time, + timeutils.normalize_time(result)) + self.assertIsNone(res['inspection_started_at']) + + def test_update_node_inspection_started_at_inspecting(self): + mocked_time = datetime.datetime(2000, 1, 1, 0, 0) + node = utils.create_test_node(uuid=uuidutils.generate_uuid(), + inspection_started_at=mocked_time, + provision_state=states.INSPECTING) + res = self.dbapi.update_node(node.id, + {'provision_state': states.INSPECTFAIL}) + self.assertIsNone(res['inspection_started_at']) + + def test_update_node_inspection_started_at_inspectwait(self): + mocked_time = datetime.datetime(2000, 1, 1, 0, 0) + node = utils.create_test_node(uuid=uuidutils.generate_uuid(), + inspection_started_at=mocked_time, + provision_state=states.INSPECTWAIT) + res = self.dbapi.update_node(node.id, + {'provision_state': states.INSPECTFAIL}) + self.assertIsNone(res['inspection_started_at']) + def test_reserve_node(self): node = utils.create_test_node() self.dbapi.set_node_tags(node.id, ['tag1', 'tag2']) diff --git a/releasenotes/notes/fix-inspectwait-finished-at-4b817af4bf4c30c2.yaml b/releasenotes/notes/fix-inspectwait-finished-at-4b817af4bf4c30c2.yaml new file mode 100644 index 0000000000..167a7f4a5e --- /dev/null +++ b/releasenotes/notes/fix-inspectwait-finished-at-4b817af4bf4c30c2.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + Fixes a database API internal check to update the + ``inspection_finished_at`` field upon the completion of inspection.