From 27f384b7ac4f19ffaf884d77484814a220b2d51d Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 26 Jul 2023 09:44:49 -0700 Subject: [PATCH] Add upgrade check for compute-object-ids linkage Related to blueprint compute-object-ids Change-Id: I6e837b9086fe20a9135712bca2d711843d39739a --- nova/cmd/status.py | 25 ++++++++++++++++ nova/db/main/api.py | 2 +- nova/tests/unit/cmd/test_status.py | 29 +++++++++++++++++++ .../compute-object-ids-e6dee31eb7f1ce34.yaml | 8 +++++ 4 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 releasenotes/notes/compute-object-ids-e6dee31eb7f1ce34.yaml diff --git a/nova/cmd/status.py b/nova/cmd/status.py index 4a4e28d7e89a..cb7fa9882101 100644 --- a/nova/cmd/status.py +++ b/nova/cmd/status.py @@ -280,6 +280,29 @@ https://docs.openstack.org/latest/nova/admin/configuration/service-user-token.ht return upgradecheck.Result(upgradecheck.Code.FAILURE, msg) return upgradecheck.Result(upgradecheck.Code.SUCCESS) + def _check_compute_object_linkage(self): + ctxt = nova_context.get_admin_context() + try: + cn_no_service = main_db_api.compute_nodes_get_by_service_id( + ctxt, None) + except exception.ServiceNotFound: + cn_no_service = [] + if cn_no_service: + msg = (_('Compute node objects without service_id linkage were ' + 'found in the database. Ensure all non-deleted compute ' + 'services have started with upgraded code.')) + return upgradecheck.Result(upgradecheck.Code.FAILURE, msg) + + inst_no_compute = main_db_api.instance_get_all_by_filters( + ctxt, filters={'compute_id': None}, limit=1) + if inst_no_compute: + msg = (_('Non-deleted instances missing compute node linkage ' + 'were found in the database. Online data migrations ' + 'should be run.')) + return upgradecheck.Result(upgradecheck.Code.FAILURE, msg) + + return upgradecheck.Result(upgradecheck.Code.SUCCESS) + # The format of the check functions is to return an upgradecheck.Result # object with the appropriate upgradecheck.Code and details set. If the # check hits warnings or failures then those should be stored in the @@ -305,6 +328,8 @@ https://docs.openstack.org/latest/nova/admin/configuration/service-user-token.ht (_('hw_machine_type unset'), _check_machine_type_set), # Added in Bobcat (_('Service User Token Configuration'), _check_service_user_token), + # Added in 2023.2 + (_('Object ID linkage'), _check_compute_object_linkage), ) diff --git a/nova/db/main/api.py b/nova/db/main/api.py index ca1071bdef99..a2f715792de4 100644 --- a/nova/db/main/api.py +++ b/nova/db/main/api.py @@ -1809,7 +1809,7 @@ def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None, # For other filters that don't match this, we will do regexp matching exact_match_filter_names = ['project_id', 'user_id', 'image_ref', 'vm_state', 'instance_type_id', 'uuid', - 'metadata', 'host', 'task_state', + 'metadata', 'host', 'task_state', 'compute_id', 'system_metadata', 'locked', 'hidden'] # Filter the query diff --git a/nova/tests/unit/cmd/test_status.py b/nova/tests/unit/cmd/test_status.py index c6a0ab2d521d..0c3063597d15 100644 --- a/nova/tests/unit/cmd/test_status.py +++ b/nova/tests/unit/cmd/test_status.py @@ -462,3 +462,32 @@ class TestUpgradeCheckServiceUserToken(test.NoDBTestCase): self.flags(send_service_user_token=True, group='service_user') result = self.cmd._check_service_user_token() self.assertEqual(upgradecheck.Code.SUCCESS, result.code) + + +class TestObjectLinkage(test.NoDBTestCase): + + def setUp(self): + super().setUp() + self.cmd = status.UpgradeCommands() + + @mock.patch('nova.db.main.api.compute_nodes_get_by_service_id') + @mock.patch('nova.db.main.api.instance_get_all_by_filters') + def test_all_good(self, mock_get_inst, mock_get_cn): + mock_get_inst.return_value = [] + mock_get_cn.side_effect = exception.ServiceNotFound(service_id=None) + result = self.cmd._check_compute_object_linkage() + self.assertEqual(upgradecheck.Code.SUCCESS, result.code) + + @mock.patch('nova.db.main.api.compute_nodes_get_by_service_id') + def test_missing_service_id(self, mock_get): + mock_get.return_value = ['foo'] + result = self.cmd._check_compute_object_linkage() + self.assertEqual(upgradecheck.Code.FAILURE, result.code) + + @mock.patch('nova.db.main.api.compute_nodes_get_by_service_id') + @mock.patch('nova.db.main.api.instance_get_all_by_filters') + def test_missing_compute_id(self, mock_get_inst, mock_get_cn): + mock_get_cn.side_effect = exception.ServiceNotFound(service_id=None) + mock_get_inst.return_value = ['foo'] + result = self.cmd._check_compute_object_linkage() + self.assertEqual(upgradecheck.Code.FAILURE, result.code) diff --git a/releasenotes/notes/compute-object-ids-e6dee31eb7f1ce34.yaml b/releasenotes/notes/compute-object-ids-e6dee31eb7f1ce34.yaml new file mode 100644 index 000000000000..46eeeb78e48b --- /dev/null +++ b/releasenotes/notes/compute-object-ids-e6dee31eb7f1ce34.yaml @@ -0,0 +1,8 @@ +--- +upgrade: + - | + A new database schema migration has been added that requires an online + data migration after upgrade. The change involves stricter linkage between + compute nodes, service records, and instances. A status check has been + added, which should pass once the schema *and* online data migrations have + been completed.