Merge "Add upgrade check for compute-object-ids linkage"
This commit is contained in:
		@@ -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),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
		Reference in New Issue
	
	Block a user