Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions neutron/agent/ovn/extensions/qos_hwol.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ class PortBindingChassisCreatedEvent(_PortBindingChassisEvent):
LOG_MSG = 'Port ID %s, datapath %s, OVS port name: %s (event: %s)'

def __init__(self, ovn_agent):
events = (self.ROW_UPDATE,)
events = (self.ROW_CREATE, self.ROW_UPDATE,)
super().__init__(ovn_agent, events)

def match_fn(self, event, row, old):
try:
return (row.chassis[0].name == self.ovn_agent.chassis and
not old.chassis)
(event == self.ROW_CREATE or not old.chassis))
except (IndexError, AttributeError):
return False

Expand Down
21 changes: 17 additions & 4 deletions neutron/agent/ovn/metadata/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ def run(self, event, row, old):
self.agent.resync()


class PortBindingCreateWithChassis(PortBindingEvent):
EVENT = PortBindingEvent.ROW_CREATE

def match_fn(self, event, row, old):
self._log_msg = "Port %s in datapath %s bound to our chassis on insert"
if not (super().match_fn(event, row, old) and row.chassis):
return False
return row.chassis[0].name == self.agent.chassis


class PortBindingUpdatedEvent(PortBindingEvent):
EVENT = PortBindingEvent.ROW_UPDATE

Expand Down Expand Up @@ -316,6 +326,7 @@ def start(self):
tables = ('Encap', 'Port_Binding', 'Datapath_Binding', 'SB_Global',
'Chassis')
events = (PortBindingUpdatedEvent(self),
PortBindingCreateWithChassis(self),
PortBindingDeletedEvent(self),
SbGlobalUpdateEvent(self),
)
Expand Down Expand Up @@ -345,7 +356,8 @@ def start(self):
self._proxy.run()

# Do the initial sync.
self.sync()
# Provisioning handled by PortBindingCreateWithChassis
self.sync(provision=False)

# Register the agent with its corresponding Chassis
self.register_metadata_agent()
Expand Down Expand Up @@ -396,7 +408,7 @@ def get_networks_datapaths(self):
return set(p.datapath for p in self._vif_ports(ports))

@_sync_lock
def sync(self):
def sync(self, provision=True):
"""Agent sync.

This function will make sure that all networks with ports in our
Expand All @@ -423,8 +435,9 @@ def sync(self):
# resync all network namespaces based on the associated datapaths,
# even those that are already running. This is to make sure
# everything within each namespace is up to date.
for datapath in net_datapaths:
self.provision_datapath(datapath)
if provision:
for datapath in net_datapaths:
self.provision_datapath(datapath)

@staticmethod
def _get_veth_name(datapath):
Expand Down
5 changes: 5 additions & 0 deletions neutron/conf/agent/database/agents_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
from neutron.common import _constants

AGENT_OPTS = [
# The agent_down_time value can only be a max of INT_MAX (as defined in C),
# where int is usually 32 bits. The agent_down_time will be passed to
# eventlet in milliseconds and any number higher will produce an OverFlow
# error. More details here: https://bugs.launchpad.net/neutron/+bug/2028724
cfg.IntOpt('agent_down_time', default=75,
max=((2**32 / 2 - 1) // 1000),
help=_("Seconds to regard the agent is down; should be at "
"least twice report_interval, to be sure the "
"agent is down for good.")),
Expand Down
49 changes: 31 additions & 18 deletions neutron/tests/functional/agent/ovn/extensions/test_qos_hwol.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,52 +17,65 @@

from oslo_utils import uuidutils

from neutron.agent.common import ovs_lib
from neutron.agent.ovn.agent import ovsdb as agent_ovsdb
from neutron.agent.ovn.extensions import qos_hwol
from neutron.common.ovn import constants as ovn_const
from neutron.common.ovn import utils
from neutron.common import utils as n_utils
from neutron.tests import base as test_base
from neutron.tests.common import net_helpers
from neutron.tests.functional import base


class OVSInterfaceEventTestCase(base.TestOVNFunctionalBase):

@test_base.unstable_test(
'LP#2006603, it is being addressed in '
'https://review.opendev.org/c/openstack/neutron/+/873118')
def _cleanup(self):
self.ovs_idl.del_port(self.port_name, bridge=self.br_name).execute(
check_error=False)
self.ovs_idl.del_br(self.br_name).execute(check_error=False)

@test_base.unstable_test('bug 2006603')
def test_port_creation_and_deletion(self):
def check_add_port_called():
try:
mock_agent.qos_hwol_ext.add_port.assert_has_calls(
[mock.call('port_iface-id', port_name)])
[mock.call(port_iface_id, self.port_name)])
return True
except AssertionError:
return False

def check_remove_egress_called():
try:
mock_agent.qos_hwol_ext.remove_egress.assert_has_calls(
[mock.call('port_iface-id')])
[mock.call(port_iface_id)])
return True
except AssertionError:
return False

port_iface_id = 'port_iface-id'
mock_agent = mock.Mock()
events = [qos_hwol.OVSInterfaceEvent(mock_agent)]
agent_ovsdb.MonitorAgentOvsIdl(events=events).start()
br = self.useFixture(net_helpers.OVSBridgeFixture()).bridge
self.ovs_bridge = ovs_lib.OVSBridge(br.br_name)
port_name = ('port-' + uuidutils.generate_uuid())[:8]

self.ovs_bridge.add_port(
port_name, ('external_ids', {'iface-id': 'port_iface-id'}))
n_utils.wait_until_true(check_add_port_called, timeout=5)

self.ovs_bridge.delete_port(port_name)
n_utils.wait_until_true(check_remove_egress_called, timeout=5)
self.ovs_idl = agent_ovsdb.MonitorAgentOvsIdl(events=events).start()
self.br_name = ('brtest-' + uuidutils.generate_uuid())[:13]
self.port_name = ('port-' + uuidutils.generate_uuid())[:13]
self.addCleanup(self._cleanup)
with self.ovs_idl.transaction() as txn:
txn.add(self.ovs_idl.add_br(self.br_name))
txn.add(self.ovs_idl.add_port(self.br_name, self.port_name))
txn.add(self.ovs_idl.iface_set_external_id(
self.port_name, 'iface-id', port_iface_id))
txn.add(self.ovs_idl.db_set(
'Interface', self.port_name, ('type', 'internal')))

exc = Exception('Port %s was not added to the bridge %s' %
(self.port_name, self.br_name))
n_utils.wait_until_true(check_add_port_called, timeout=5,
exception=exc)

self.ovs_idl.del_port(self.port_name).execute(check_error=True)
exc = Exception('Port %s was not deleted from the bridge %s' %
(self.port_name, self.br_name))
n_utils.wait_until_true(check_remove_egress_called, timeout=5,
exception=exc)


class QoSBandwidthLimitEventTestCase(base.TestOVNFunctionalBase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
The config option ``agent_down_time`` is now limited to a maximum value of
`2147483`, as neutron-server will fail to start if it is configured higher.
See bug `2028724 <https://bugs.launchpad.net/neutron/+bug/2028724>`_ for more information.