Skip to content

Commit 26c34b4

Browse files
committed
add subports_added and trunk_created methods to UnderStackTrunkDriver
1 parent a0a56ee commit 26c34b4

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed

python/neutron-understack/neutron_understack/trunk.py

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,56 @@
1+
from neutron.objects.trunk import SubPort
12
from neutron.services.trunk.drivers import base as trunk_base
3+
from neutron_lib import exceptions as exc
24
from neutron_lib.api.definitions import portbindings
5+
from neutron_lib.callbacks import events
6+
from neutron_lib.callbacks import registry
7+
from neutron_lib.callbacks import resources
38
from neutron_lib.services.trunk import constants as trunk_consts
49
from oslo_config import cfg
10+
from oslo_log import log
11+
12+
from neutron_understack import config
13+
from neutron_understack import utils
14+
from neutron_understack.nautobot import Nautobot
15+
16+
config.register_ml2_understack_opts(cfg.CONF)
17+
18+
LOG = log.getLogger(__name__)
519

620
SUPPORTED_INTERFACES = (portbindings.VIF_TYPE_OTHER,)
721

822
SUPPORTED_SEGMENTATION_TYPES = (trunk_consts.SEGMENTATION_TYPE_VLAN,)
923

1024

25+
class SubportSegmentationIDError(exc.NeutronException):
26+
message = (
27+
"Segmentation ID: %(seg_id)s cannot be set to the Subport: "
28+
"%(subport_id)s as there is already another Segmentation ID: "
29+
"%(nb_seg_id)s in use by the Network: %(net_id)s that is "
30+
"attached to the Subport. Please use %(nb_seg_id)s as "
31+
"segmentation_id for this subport."
32+
)
33+
34+
1135
class UnderStackTrunkDriver(trunk_base.DriverBase):
36+
def __init__(
37+
self,
38+
name,
39+
interfaces,
40+
segmentation_types,
41+
agent_type=None,
42+
can_trunk_bound_port=False,
43+
):
44+
super().__init__(
45+
name,
46+
interfaces,
47+
segmentation_types,
48+
agent_type=agent_type,
49+
can_trunk_bound_port=can_trunk_bound_port,
50+
)
51+
conf = cfg.CONF.ml2_understack
52+
self.nb = Nautobot(conf.nb_url, conf.nb_token)
53+
1254
@property
1355
def is_loaded(self):
1456
try:
@@ -26,3 +68,63 @@ def create(cls, plugin_driver):
2668
None,
2769
can_trunk_bound_port=True,
2870
)
71+
72+
@registry.receives(resources.TRUNK_PLUGIN, [events.AFTER_INIT])
73+
def register(self, resource, event, trigger, payload=None):
74+
super().register(resource, event, trigger, payload=payload)
75+
76+
registry.subscribe(
77+
self.subports_added,
78+
resources.SUBPORTS,
79+
events.AFTER_CREATE,
80+
cancellable=True,
81+
)
82+
registry.subscribe(
83+
self.trunk_created, resources.TRUNK, events.AFTER_CREATE, cancellable=True
84+
)
85+
86+
def _configure_tenant_vlan_id(
87+
self, tenant_vlan_id: int | None, ucvni_uuid: str, subport: SubPort
88+
) -> None:
89+
subport_seg_id = subport.segmentation_id
90+
if not tenant_vlan_id:
91+
self.nb.add_tenant_vlan_tag_to_ucvni(
92+
network_uuid=ucvni_uuid, vlan_tag=subport_seg_id
93+
)
94+
LOG.info(
95+
"Segmentation ID: %(seg_id)s is now set on Nautobot's UCVNI "
96+
"UUID: %(ucvni_uuid)s in the tenant_vlan_id custom field",
97+
{"seg_id": subport_seg_id, "ucvni_uuid": ucvni_uuid},
98+
)
99+
elif tenant_vlan_id != subport_seg_id:
100+
subport.delete()
101+
raise SubportSegmentationIDError(
102+
seg_id=subport_seg_id,
103+
net_id=ucvni_uuid,
104+
nb_seg_id=tenant_vlan_id,
105+
subport_id=subport.port_id,
106+
)
107+
108+
def _subports_added(self, subports: list[SubPort]) -> None:
109+
for subport in subports:
110+
subport_id = subport.port_id
111+
subport_network_id = utils.fetch_subport_network_id(subport_id=subport_id)
112+
ucvni_tenant_vlan_id = self.nb.fetch_ucvni_tenant_vlan_id(
113+
network_id=subport_network_id
114+
)
115+
116+
self._configure_tenant_vlan_id(
117+
tenant_vlan_id=ucvni_tenant_vlan_id,
118+
ucvni_uuid=subport_network_id,
119+
subport=subport,
120+
)
121+
122+
def subports_added(self, resource, event, trunk_plugin, payload):
123+
subports = payload.metadata["subports"]
124+
self._subports_added(subports)
125+
126+
def trunk_created(self, resource, event, trunk_plugin, payload):
127+
trunk = payload.states[0]
128+
subports = trunk.sub_ports
129+
if subports:
130+
self._subports_added(subports)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from neutron.objects import ports as port_obj
2+
from neutron_lib import context as n_context
3+
4+
5+
def fetch_subport_network_id(subport_id):
6+
context = n_context.get_admin_context()
7+
neutron_port = port_obj.Port.get_object(context, id=subport_id)
8+
return neutron_port.network_id

0 commit comments

Comments
 (0)