def test_get_inconsistent_resources(self):
     # Set the intial revision to -1 to force it to be incosistent
     self._create_initial_revision(
         self.net['id'], ovn_rn_db.TYPE_NETWORKS, revision_number=-1)
     res = ovn_rn_db.get_inconsistent_resources(self.ctx)
     self.assertEqual(1, len(res))
     self.assertEqual(self.net['id'], res[0].resource_uuid)
 def test_get_inconsistent_resources_consistent(self):
     # Set the initial revision to 0 which is the initial revision_number
     # for recently created resources
     self._create_initial_revision(
         self.net['id'], ovn_rn_db.TYPE_NETWORKS, revision_number=0)
     res = ovn_rn_db.get_inconsistent_resources(self.ctx)
     # Assert nothing is inconsistent
     self.assertEqual([], res)
    def test_get_inconsistent_resources_older_than(self):
        # Stop the mock so the INCONSISTENCIES_OLDER_THAN will have
        # it's default value
        self.older_than_mock.stop()
        self._create_initial_revision(
            self.net['id'], ovn_rn_db.TYPE_NETWORKS, revision_number=-1)
        res = ovn_rn_db.get_inconsistent_resources(self.ctx)

        # Assert that nothing is returned because the entry is not old
        # enough to be picked as an inconsistency
        self.assertEqual(0, len(res))

        # Start the mock again and make sure it nows shows up as an
        # inconsistency
        self.older_than_mock.start()
        res = ovn_rn_db.get_inconsistent_resources(self.ctx)
        self.assertEqual(1, len(res))
        self.assertEqual(self.net['id'], res[0].resource_uuid)
Пример #4
0
    def check_for_inconsistencies(self):
        # Only the worker holding a valid lock within OVSDB will run
        # this periodic
        if not self.has_lock:
            return

        admin_context = n_context.get_admin_context()
        create_update_inconsistencies = (
            revision_numbers_db.get_inconsistent_resources(admin_context))
        delete_inconsistencies = (
            revision_numbers_db.get_deleted_resources(admin_context))
        if not any([create_update_inconsistencies, delete_inconsistencies]):
            LOG.debug('Maintenance task: No inconsistencies found. Skipping')
            return

        LOG.debug('Maintenance task: Synchronizing Neutron '
                  'and OVN databases')
        self._log_maintenance_inconsistencies(create_update_inconsistencies,
                                              delete_inconsistencies)
        self._sync_timer.restart()

        dbg_log_msg = ('Maintenance task: Fixing resource %(res_uuid)s '
                       '(type: %(res_type)s) at %(type_)s')
        # Fix the create/update resources inconsistencies
        for row in create_update_inconsistencies:
            LOG.debug(dbg_log_msg, {'res_uuid': row.resource_uuid,
                                    'res_type': row.resource_type,
                                    'type_': INCONSISTENCY_TYPE_CREATE_UPDATE})
            try:
                # NOTE(lucasagomes): The way to fix subnets is bit
                # different than other resources. A subnet in OVN language
                # is just a DHCP rule but, this rule only exist if the
                # subnet in Neutron has the "enable_dhcp" attribute set
                # to True. So, it's possible to have a consistent subnet
                # resource even when it does not exist in the OVN database.
                if row.resource_type == ovn_const.TYPE_SUBNETS:
                    self._fix_create_update_subnet(admin_context, row)
                else:
                    self._fix_create_update(admin_context, row)
            except Exception:
                LOG.exception('Maintenance task: Failed to fix resource '
                              '%(res_uuid)s (type: %(res_type)s)',
                              {'res_uuid': row.resource_uuid,
                               'res_type': row.resource_type})

        # Fix the deleted resources inconsistencies
        for row in delete_inconsistencies:
            LOG.debug(dbg_log_msg, {'res_uuid': row.resource_uuid,
                                    'res_type': row.resource_type,
                                    'type_': INCONSISTENCY_TYPE_DELETE})
            try:
                if row.resource_type == ovn_const.TYPE_SUBNETS:
                    self._ovn_client.delete_subnet(admin_context,
                                                   row.resource_uuid)
                elif row.resource_type == ovn_const.TYPE_PORTS:
                    self._ovn_client.delete_port(admin_context,
                                                 row.resource_uuid)
                else:
                    self._fix_delete(admin_context, row)
            except Exception:
                LOG.exception('Maintenance task: Failed to fix deleted '
                              'resource %(res_uuid)s (type: %(res_type)s)',
                              {'res_uuid': row.resource_uuid,
                               'res_type': row.resource_type})

        self._sync_timer.stop()
        LOG.info('Maintenance task: Synchronization finished '
                 '(took %.2f seconds)', self._sync_timer.elapsed())
 def test_get_inconsistent_resources_order(self):
     self._prepare_resources_for_ordering_test()
     res = ovn_rn_db.get_inconsistent_resources(self.ctx)
     actual_order = tuple(r.resource_type for r in res)
     self.assertEqual(ovn_rn_db._TYPES_PRIORITY_ORDER, actual_order)