Skip to content
Draft
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
18 changes: 13 additions & 5 deletions python/neutron-understack/neutron_understack/routers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from neutron.objects.network import NetworkSegment
from neutron.objects.ports import Port
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.ovn_client import OVNClient
from neutron.services.trunk import exceptions as trunk_exc
from neutron_lib import constants as p_const
from neutron_lib import context as n_context
from neutron_lib.api.definitions import segment as segment_def
Expand Down Expand Up @@ -97,11 +98,18 @@ def add_subport_to_trunk(shared_port: PortDict, segment: NetworkSegmentDict) ->
}
trunk_id = utils.fetch_network_node_trunk_id()

utils.fetch_trunk_plugin().add_subports(
context=n_context.get_admin_context(),
trunk_id=trunk_id,
subports=subports,
)
try:
utils.fetch_trunk_plugin().add_subports(
context=n_context.get_admin_context(),
trunk_id=trunk_id,
subports=subports,
)
except trunk_exc.DuplicateSubPort:
LOG.debug(
"subport with segmentation_id %(seg_id)s already exists on trunk "
"%(trunk_id)s, skipping",
{"seg_id": segment["segmentation_id"], "trunk_id": trunk_id},
)


def fetch_or_create_router_segment(context: PortContext) -> NetworkSegmentDict:
Expand Down
20 changes: 20 additions & 0 deletions python/neutron-understack/neutron_understack/tests/test_routers.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from neutron.services.trunk import exceptions as trunk_exc
from neutron_lib import constants as p_const

from neutron_understack.routers import add_subport_to_trunk
Expand Down Expand Up @@ -66,6 +67,25 @@ def test_when_successful(self, mocker):
},
)

def test_duplicate_subport_is_ignored(self, mocker):
"""A stranded sub-port from a previous failed attempt must not block retries."""
mocker.patch(
"neutron_understack.utils.fetch_network_node_trunk_id",
return_value="trunk-uuid",
)
mocker.patch(
"neutron_lib.context.get_admin_context", return_value="admin_context"
)
mock_trunk_plugin = mocker.Mock()
mock_trunk_plugin.add_subports.side_effect = trunk_exc.DuplicateSubPort()
mocker.patch(
"neutron_understack.utils.fetch_trunk_plugin",
return_value=mock_trunk_plugin,
)

# should not raise
add_subport_to_trunk({"id": "port-123"}, {"segmentation_id": 42})


class TestHandleSubportRemoval:
def test_when_successful(self, mocker, port_id, trunk_id):
Expand Down
Loading