Do not fail if the agent load is not bumped

When a new network and its first subnet is created, the DHCP agent
bumps the "load" parameter to reflect the number of networks handled.
This "load" parameter is modified when:
- As commented, when the first subnet of a network is created. The
  "load" value is bumped.
- When periodically the DHCP agent sends the status, informing about
  the current number of networks handled.

If during the subnet creation this "load" value is not updated, it will
be in the next periodic update of the agent.

This "load" value is used by the scheduler to equally distribute the
objects to be managed by any agent type (DHCP agents manage networks).

The bug refers to DHCP but is valid for any other agent.

Conflicts:
      neutron/common/utils.py
      neutron/scheduler/base_resource_filter.py

Change-Id: Ief402048d99d40b64d81fcf58eb2e39b1ba7ebbb
Closes-Bug: #1939432
(cherry picked from commit 668b1cc652)
(cherry picked from commit 816aca60b9)
(cherry picked from commit 1eb6b8926a)
This commit is contained in:
Rodolfo Alonso Hernandez 2021-08-11 09:13:55 +00:00
parent 8e581d31cd
commit f315f85a7b
3 changed files with 48 additions and 0 deletions

View File

@ -927,3 +927,25 @@ class SingletonDecorator(object):
if self._instance is None: if self._instance is None:
self._instance = self._klass(*args, **kwargs) self._instance = self._klass(*args, **kwargs)
return self._instance return self._instance
def skip_exceptions(exceptions):
"""Decorator to catch and hide any provided exception in the argument"""
# NOTE(ralonsoh): could be rehomed to neutron-lib.
if not isinstance(exceptions, list):
exceptions = [exceptions]
def decorator(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
try:
return function(*args, **kwargs)
except Exception as exc:
with excutils.save_and_reraise_exception() as ctx:
if issubclass(type(exc), tuple(exceptions)):
LOG.info('Skipped exception %s when calling method %s',
ctx.value.__repr__(), function.__repr__())
ctx.reraise = False
return wrapper
return decorator

View File

@ -16,8 +16,11 @@
import abc import abc
from neutron_lib.db import api as db_api from neutron_lib.db import api as db_api
from oslo_db import exception as db_exc
import six import six
from neutron.common import utils as n_utils
@six.add_metaclass(abc.ABCMeta) @six.add_metaclass(abc.ABCMeta)
class BaseResourceFilter(object): class BaseResourceFilter(object):
@ -26,6 +29,7 @@ class BaseResourceFilter(object):
def filter_agents(self, plugin, context, resource): def filter_agents(self, plugin, context, resource):
"""Return the agents that can host the resource.""" """Return the agents that can host the resource."""
@n_utils.skip_exceptions(db_exc.DBError)
def bind(self, context, agents, resource_id, force_scheduling=False): def bind(self, context, agents, resource_id, force_scheduling=False):
"""Bind the resource to the agents.""" """Bind the resource to the agents."""
with db_api.CONTEXT_WRITER.using(context): with db_api.CONTEXT_WRITER.using(context):

View File

@ -606,3 +606,25 @@ class SingletonDecoratorTestCase(base.BaseTestCase):
instance_2 = _TestSingletonClass() instance_2 = _TestSingletonClass()
self.assertEqual(instance_1.__hash__(), instance_2.__hash__()) self.assertEqual(instance_1.__hash__(), instance_2.__hash__())
self.assertEqual('value1', instance_2.variable) self.assertEqual('value1', instance_2.variable)
class SkipDecoratorTestCase(base.BaseTestCase):
def test_skip_exception(self):
@utils.skip_exceptions(AttributeError)
def raise_attribute_error_single_exception():
raise AttributeError()
@utils.skip_exceptions([AttributeError, IndexError])
def raise_attribute_error_exception_list():
raise AttributeError()
raise_attribute_error_single_exception()
raise_attribute_error_exception_list()
def test_skip_exception_fail(self):
@utils.skip_exceptions(IndexError)
def raise_attribute_error():
raise AttributeError()
self.assertRaises(AttributeError, raise_attribute_error)