1
1
import logging
2
2
from uuid import UUID
3
3
4
- import neutron_lib .api .definitions .portbindings as portbindings
5
4
from neutron_lib import constants as p_const
5
+ from neutron_lib .api .definitions import portbindings
6
6
from neutron_lib .api .definitions import segment as segment_def
7
7
from neutron_lib .callbacks import events
8
8
from neutron_lib .callbacks import registry
12
12
from oslo_config import cfg
13
13
14
14
from neutron_understack import config
15
+ from neutron_understack import routers
15
16
from neutron_understack import utils
16
17
from neutron_understack .ironic import IronicClient
17
18
from neutron_understack .nautobot import Nautobot
20
21
from neutron_understack .undersync import Undersync
21
22
22
23
from .ml2_type_annotations import NetworkContext
23
- from .ml2_type_annotations import NetworkSegmentDict
24
24
from .ml2_type_annotations import PortContext
25
25
26
26
LOG = logging .getLogger (__name__ )
29
29
config .register_ml2_understack_opts (cfg .CONF )
30
30
31
31
32
+ SUPPORTED_VNIC_TYPES = [portbindings .VNIC_BAREMETAL , portbindings .VNIC_NORMAL ]
33
+
34
+
32
35
class UnderstackDriver (MechanismDriver ):
33
36
# See MechanismDriver docs for resource_provider_uuid5_namespace
34
37
resource_provider_uuid5_namespace = UUID ("6eae3046-4072-11ef-9bcf-d6be6370a162" )
@@ -58,6 +61,12 @@ def subscribe(self):
58
61
events .BEFORE_DELETE ,
59
62
cancellable = True ,
60
63
)
64
+ registry .subscribe (
65
+ routers .handle_router_interface_removal ,
66
+ resources .PORT ,
67
+ events .BEFORE_DELETE ,
68
+ cancellable = True ,
69
+ )
61
70
62
71
def create_network_precommit (self , context ):
63
72
pass
@@ -221,11 +230,14 @@ def delete_subnet_postcommit(self, context):
221
230
{"prefix" : prefix , "uuid" : subnet_uuid },
222
231
)
223
232
224
- def create_port_precommit (self , context ):
233
+ def create_port_precommit (self , context : PortContext ):
225
234
pass
226
235
227
- def create_port_postcommit (self , context ):
228
- pass
236
+ def create_port_postcommit (self , context : PortContext ) -> None :
237
+ # Provide network node(s) with connectivity to the networks where this
238
+ # router port is attached to.
239
+ if utils .is_router_interface (context ):
240
+ routers .create_port_postcommit (context )
229
241
230
242
def update_port_precommit (self , context ):
231
243
pass
@@ -263,7 +275,7 @@ def _tenant_network_port_cleanup(self, context: PortContext):
263
275
"""
264
276
trunk_details = context .current .get ("trunk_details" , {})
265
277
segment_id = context .original_top_bound_segment ["id" ]
266
- original_binding = context .original ["binding:profile" ]
278
+ original_binding = context .original [portbindings . PROFILE ]
267
279
connected_interface_uuid = utils .fetch_connected_interface_uuid (
268
280
original_binding , self .nb
269
281
)
@@ -338,7 +350,18 @@ def bind_port(self, context: PortContext) -> None:
338
350
which means that changes made here will get pushed to the switch at that
339
351
time.
340
352
"""
341
- if is_provisioning_network (context .current ["network_id" ]):
353
+ port = context .current
354
+ LOG .debug (
355
+ "Attempting to bind port %(port)s on network %(net)s" ,
356
+ {"port" : port ["id" ], "net" : port ["network_id" ]},
357
+ )
358
+
359
+ vnic_type = port .get (portbindings .VNIC_TYPE , portbindings .VNIC_NORMAL )
360
+ if vnic_type not in SUPPORTED_VNIC_TYPES :
361
+ LOG .debug ("Refusing to bind due to unsupported vnic_type: %s" , vnic_type )
362
+ return
363
+
364
+ if is_provisioning_network (port ["network_id" ]):
342
365
self ._set_nautobot_port_status (context , "Provisioning-Interface" )
343
366
344
367
for segment in context .network .network_segments :
@@ -349,7 +372,7 @@ def bind_port(self, context: PortContext) -> None:
349
372
def _bind_port_segment (self , context : PortContext , segment ):
350
373
network_id = context .current ["network_id" ]
351
374
connected_interface_uuid = utils .fetch_connected_interface_uuid (
352
- context .current ["binding:profile" ], self .nb
375
+ context .current [portbindings . PROFILE ], self .nb
353
376
)
354
377
mac_address = context .current ["mac_address" ]
355
378
@@ -372,13 +395,20 @@ def _bind_port_segment(self, context: PortContext, segment):
372
395
vlan_group_name ,
373
396
)
374
397
375
- current_vlan_segment = self ._vlan_segment_for_physnet (context , vlan_group_name )
376
- dynamic_segment = current_vlan_segment or context .allocate_dynamic_segment (
377
- segment = {
378
- "network_type" : p_const .TYPE_VLAN ,
379
- "physical_network" : vlan_group_name ,
380
- },
381
- )
398
+ current_vlan_segment = utils .vlan_segment_for_physnet (context , vlan_group_name )
399
+ if current_vlan_segment :
400
+ LOG .info (
401
+ "vlan segment: %(segment)s already preset for physnet: " "%(physnet)s" ,
402
+ {"segment" : current_vlan_segment , "physnet" : vlan_group_name },
403
+ )
404
+ dynamic_segment = current_vlan_segment
405
+ else :
406
+ dynamic_segment = context .allocate_dynamic_segment (
407
+ segment = {
408
+ "network_type" : p_const .TYPE_VLAN ,
409
+ "physical_network" : vlan_group_name ,
410
+ },
411
+ )
382
412
383
413
LOG .debug ("bind_port_segment: Native VLAN segment %s" , dynamic_segment )
384
414
dynamic_segment_vlan_id = dynamic_segment ["segmentation_id" ]
@@ -403,21 +433,6 @@ def _bind_port_segment(self, context: PortContext, segment):
403
433
status = p_const .PORT_STATUS_ACTIVE ,
404
434
)
405
435
406
- def _vlan_segment_for_physnet (
407
- self , context : PortContext , physnet : str
408
- ) -> NetworkSegmentDict | None :
409
- for segment in context .network .network_segments :
410
- if (
411
- segment [api .NETWORK_TYPE ] == p_const .TYPE_VLAN
412
- and segment [api .PHYSICAL_NETWORK ] == physnet
413
- ):
414
- LOG .info (
415
- "vlan segment: %(segment)s already preset for physnet: "
416
- "%(physnet)s" ,
417
- {"segment" : segment , "physnet" : physnet },
418
- )
419
- return segment
420
-
421
436
def invoke_undersync (self , vlan_group_name : str ):
422
437
self .undersync .sync_devices (
423
438
vlan_group = vlan_group_name ,
@@ -496,7 +511,7 @@ def _delete_vlan(self, segment):
496
511
)
497
512
498
513
def _set_nautobot_port_status (self , context : PortContext , status : str ):
499
- profile = context .current ["binding:profile" ]
514
+ profile = context .current [portbindings . PROFILE ]
500
515
interface_uuid = utils .fetch_connected_interface_uuid (profile , self .nb )
501
516
LOG .debug ("Set interface %s to %s status" , interface_uuid , status )
502
517
self .nb .configure_port_status (interface_uuid , status = status )
0 commit comments