Merge "Move registration "ChassisBandwidthConfigEvent" to OvnSbIdl init"

This commit is contained in:
Zuul 2022-12-11 22:36:19 +00:00 committed by Gerrit Code Review
commit e2d14b4209
3 changed files with 68 additions and 17 deletions

View File

@ -110,8 +110,8 @@ def dict_chassis_config(state):
class ChassisBandwidthConfigEvent(row_event.RowEvent): class ChassisBandwidthConfigEvent(row_event.RowEvent):
"""Chassis create update event to track the bandwidth config changes.""" """Chassis create update event to track the bandwidth config changes."""
def __init__(self, placement_extension): def __init__(self, driver):
self._placement_extension = placement_extension self._driver = driver
# NOTE(ralonsoh): BW resource provider information is stored in # NOTE(ralonsoh): BW resource provider information is stored in
# "Chassis", not "Chassis_Private". # "Chassis", not "Chassis_Private".
table = 'Chassis' table = 'Chassis'
@ -119,9 +119,30 @@ class ChassisBandwidthConfigEvent(row_event.RowEvent):
super().__init__(events, table, None) super().__init__(events, table, None)
self.event_name = 'ChassisBandwidthConfigEvent' self.event_name = 'ChassisBandwidthConfigEvent'
@property
def placement_extension(self):
if self._driver._post_fork_event.is_set():
return self._driver._ovn_client.placement_extension
def match_fn(self, event, row, old=None):
# If the OVNMechanismDriver OVNClient has not been instantiated, the
# event is skipped. All chassis configurations are read during the
# OVN placement extension initialization.
if (not self.placement_extension or
not self.placement_extension.enabled):
return False
elif event == self.ROW_CREATE:
return True
elif event == self.ROW_UPDATE and old and hasattr(old, 'other_config'):
row_bw = _parse_ovn_cms_options(row)
old_bw = _parse_ovn_cms_options(old)
if row_bw != old_bw:
return True
return False
def run(self, event, row, old): def run(self, event, row, old):
name2uuid = self._placement_extension.name2uuid() name2uuid = self.placement_extension.name2uuid()
state = self._placement_extension.build_placement_state(row, name2uuid) state = self.placement_extension.build_placement_state(row, name2uuid)
if not state: if not state:
return return
@ -153,18 +174,6 @@ class OVNClientPlacementExtension(object):
self._plugin = None self._plugin = None
self.uuid_ns = ovn_const.OVN_RP_UUID self.uuid_ns = ovn_const.OVN_RP_UUID
self.supported_vnic_types = ovn_const.OVN_SUPPORTED_VNIC_TYPES self.supported_vnic_types = ovn_const.OVN_SUPPORTED_VNIC_TYPES
if not self.enabled:
return
if not self._config_event:
self._config_event = ChassisBandwidthConfigEvent(self)
try:
self._driver._sb_idl.idl.notify_handler.watch_events(
[self._config_event])
except AttributeError:
# "sb_idl.idl.notify_handler" is not present in the
# MaintenanceWorker.
pass
@property @property
def placement_plugin(self): def placement_plugin(self):

View File

@ -35,6 +35,8 @@ from neutron.common.ovn import utils
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf
from neutron.db import ovn_hash_ring_db from neutron.db import ovn_hash_ring_db
from neutron.plugins.ml2.drivers.ovn.agent import neutron_agent as n_agent from neutron.plugins.ml2.drivers.ovn.agent import neutron_agent as n_agent
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.extensions import \
placement
CONF = cfg.CONF CONF = cfg.CONF
@ -808,6 +810,7 @@ class OvnSbIdl(OvnIdlDistributedLock):
ChassisAgentTypeChangeEvent(self.driver), ChassisAgentTypeChangeEvent(self.driver),
ChassisMetadataAgentWriteEvent(self.driver), ChassisMetadataAgentWriteEvent(self.driver),
PortBindingUpdateVirtualPortsEvent(driver), PortBindingUpdateVirtualPortsEvent(driver),
placement.ChassisBandwidthConfigEvent(driver),
]) ])
@classmethod @classmethod

View File

@ -16,15 +16,18 @@ from unittest import mock
from neutron_lib import constants as n_const from neutron_lib import constants as n_const
from neutron_lib.plugins import constants as plugins_constants from neutron_lib.plugins import constants as plugins_constants
from oslo_utils import uuidutils
from neutron.common.ovn import constants as ovn_const from neutron.common.ovn import constants as ovn_const
from neutron.common import utils as common_utils from neutron.common import utils as common_utils
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.extensions \ from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.extensions \
import placement as placement_extension import placement as placement_extension
from neutron.tests.functional import base from neutron.tests.functional import base
from neutron.tests.functional.plugins.ml2.drivers.ovn.mech_driver.ovsdb \
import test_ovsdb_monitor
class TestOVNClientQosExtension(base.TestOVNFunctionalBase): class TestOVNClientPlacementExtension(base.TestOVNFunctionalBase):
EMPTY_CHASSIS = {n_const.RP_BANDWIDTHS: {}, EMPTY_CHASSIS = {n_const.RP_BANDWIDTHS: {},
n_const.RP_INVENTORY_DEFAULTS: {}, n_const.RP_INVENTORY_DEFAULTS: {},
@ -186,3 +189,39 @@ class TestOVNClientQosExtension(base.TestOVNFunctionalBase):
inventory_defaults='allocation_ratio:1.1;min_unit:1', inventory_defaults='allocation_ratio:1.1;min_unit:1',
hypervisors='br-provider0:host2') hypervisors='br-provider0:host2')
self._check_placement_config({**self.CHASSIS1, **self.CHASSIS2_B}) self._check_placement_config({**self.CHASSIS1, **self.CHASSIS2_B})
@mock.patch.object(placement_extension, '_send_deferred_batch')
def test_chassis_bandwidth_config_event(self, mock_send_placement):
ch_host = 'fake-chassis-host'
ch_name = uuidutils.generate_uuid()
ch_event = test_ovsdb_monitor.WaitForChassisPrivateCreateEvent(
ch_name, self.mech_driver.agent_chassis_table)
self.mech_driver.sb_ovn.idl.notify_handler.watch_event(ch_event)
self.chassis_name = self.add_fake_chassis(ch_host, name=ch_name)
self.assertTrue(ch_event.wait())
common_utils.wait_until_true(lambda: mock_send_placement.called,
timeout=2)
mock_send_placement.reset_mock()
# Once the chassis registger has been created, this new event will
# catch any chassis BW update.
self._update_chassis(
ch_name,
bandwidths='br-provider0:3000:4000',
inventory_defaults='allocation_ratio:3.0;min_unit:1',
hypervisors='br-provider0:host2')
common_utils.wait_until_true(lambda: mock_send_placement.called,
timeout=2)
mock_send_placement.reset_mock()
# The chassis BW information is written again without any change.
# That should not trigger the placement update.
self._update_chassis(
ch_name,
bandwidths='br-provider0:3000:4000',
inventory_defaults='allocation_ratio:3.0;min_unit:1',
hypervisors='br-provider0:host2')
self.assertRaises(common_utils.WaitTimeout,
common_utils.wait_until_true,
lambda: mock_send_placement.called,
timeout=2)