1
+ from neutron .objects .trunk import SubPort
1
2
from neutron .services .trunk .drivers import base as trunk_base
3
+ from neutron_lib import exceptions as exc
2
4
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
3
8
from neutron_lib .services .trunk import constants as trunk_consts
4
9
from oslo_config import cfg
10
+ from oslo_log import log
11
+
12
+ from neutron_understack import utils
13
+
14
+ LOG = log .getLogger (__name__ )
5
15
6
16
SUPPORTED_INTERFACES = (portbindings .VIF_TYPE_OTHER ,)
7
17
8
18
SUPPORTED_SEGMENTATION_TYPES = (trunk_consts .SEGMENTATION_TYPE_VLAN ,)
9
19
10
20
21
+ class SubportSegmentationIDError (exc .NeutronException ):
22
+ message = (
23
+ "Segmentation ID: %(seg_id)s cannot be set to the Subport: "
24
+ "%(subport_id)s as there is already another Segmentation ID: "
25
+ "%(nb_seg_id)s in use by the Network: %(net_id)s that is "
26
+ "attached to the Subport. Please use %(nb_seg_id)s as "
27
+ "segmentation_id for this subport."
28
+ )
29
+
30
+
11
31
class UnderStackTrunkDriver (trunk_base .DriverBase ):
32
+ def __init__ (
33
+ self ,
34
+ name ,
35
+ interfaces ,
36
+ segmentation_types ,
37
+ agent_type = None ,
38
+ can_trunk_bound_port = False ,
39
+ ):
40
+ super ().__init__ (
41
+ name ,
42
+ interfaces ,
43
+ segmentation_types ,
44
+ agent_type = agent_type ,
45
+ can_trunk_bound_port = can_trunk_bound_port ,
46
+ )
47
+ self .nb = self .plugin_driver .nb
48
+
12
49
@property
13
50
def is_loaded (self ):
14
51
try :
@@ -26,3 +63,68 @@ def create(cls, plugin_driver):
26
63
None ,
27
64
can_trunk_bound_port = True ,
28
65
)
66
+
67
+ @registry .receives (resources .TRUNK_PLUGIN , [events .AFTER_INIT ])
68
+ def register (self , resource , event , trigger , payload = None ):
69
+ super ().register (resource , event , trigger , payload = payload )
70
+
71
+ registry .subscribe (
72
+ self .subports_added ,
73
+ resources .SUBPORTS ,
74
+ events .AFTER_CREATE ,
75
+ cancellable = True ,
76
+ )
77
+ registry .subscribe (
78
+ self .trunk_created , resources .TRUNK , events .AFTER_CREATE , cancellable = True
79
+ )
80
+
81
+ def _handle_segmentation_id_mismatch (
82
+ self , subport : SubPort , ucvni_uuid : str , tenant_vlan_id : int
83
+ ) -> None :
84
+ subport .delete ()
85
+ raise SubportSegmentationIDError (
86
+ seg_id = subport .segmentation_id ,
87
+ net_id = ucvni_uuid ,
88
+ nb_seg_id = tenant_vlan_id ,
89
+ subport_id = subport .port_id ,
90
+ )
91
+
92
+ def _configure_tenant_vlan_id (self , ucvni_uuid : str , subport : SubPort ) -> None :
93
+ subport_seg_id = subport .segmentation_id
94
+ self .nb .add_tenant_vlan_tag_to_ucvni (
95
+ network_uuid = ucvni_uuid , vlan_tag = subport_seg_id
96
+ )
97
+ LOG .info (
98
+ "Segmentation ID: %(seg_id)s is now set on Nautobot's UCVNI "
99
+ "UUID: %(ucvni_uuid)s in the tenant_vlan_id custom field" ,
100
+ {"seg_id" : subport_seg_id , "ucvni_uuid" : ucvni_uuid },
101
+ )
102
+
103
+ def _subports_added (self , subports : list [SubPort ]) -> None :
104
+ for subport in subports :
105
+ subport_network_id = utils .fetch_subport_network_id (
106
+ subport_id = subport .port_id
107
+ )
108
+ ucvni_tenant_vlan_id = self .nb .fetch_ucvni_tenant_vlan_id (
109
+ network_id = subport_network_id
110
+ )
111
+ if not ucvni_tenant_vlan_id :
112
+ self ._configure_tenant_vlan_id (
113
+ ucvni_uuid = subport_network_id , subport = subport
114
+ )
115
+ elif ucvni_tenant_vlan_id != subport .segmentation_id :
116
+ self ._handle_segmentation_id_mismatch (
117
+ subport = subport ,
118
+ ucvni_uuid = subport_network_id ,
119
+ tenant_vlan_id = ucvni_tenant_vlan_id ,
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 )
0 commit comments