@@ -212,49 +212,87 @@ def add_tenant_vlan_tag_to_ucvni(self, network_uuid: str, vlan_tag: int) -> dict
212
212
def subnet_delete (self , uuid : str ) -> dict :
213
213
return self .make_api_request ("DELETE" , f"/api/ipam/prefixes/{ uuid } /" )
214
214
215
- def prep_switch_interface (
215
+ def configure_port_status (self , interface_uuid : str , status : str ) -> dict :
216
+ url = f"/api/dcim/interfaces/{ interface_uuid } /"
217
+ payload = {"status" : {"name" : status }}
218
+ return self .make_api_request ("PATCH" , url , payload )
219
+
220
+ def set_port_vlan_associations (
216
221
self ,
217
- connected_interface_id : str ,
218
- ucvni_uuid : str ,
219
- vlan_tag : int | None ,
220
- modify_native_vlan : bool | None = True ,
222
+ interface_uuid : str ,
223
+ native_vlan_id : int | None ,
224
+ allowed_vlans_ids : set [ int ] ,
225
+ vlan_group_name : str ,
221
226
) -> dict :
222
- """Runs a Nautobot Job to update a switch interface for tenant mode.
223
-
224
- The nautobot job will assign vlans as required and set the interface
225
- into the correct mode for "normal" tenant operation.
227
+ """Set the tagged and untagged vlan(s) on an interface."""
228
+ url = f"/api/dcim/interfaces/{ interface_uuid } /"
226
229
227
- The dictionary with vlan group ID and vlan tag is returned.
228
- """
229
- url = "/api/plugins/undercloud-vni/prep_switch_interface"
230
- payload = {
231
- "ucvni_id" : str (ucvni_uuid ),
232
- "connected_interface_id" : str (connected_interface_id ),
233
- "modify_native_vlan" : modify_native_vlan ,
234
- "vlan_tag" : vlan_tag ,
230
+ payload : dict = {
231
+ "tagged_vlans" : [
232
+ _vlan_payload (vlan_group_name , vlan_id ) for vlan_id in allowed_vlans_ids
233
+ ],
235
234
}
236
- return self .make_api_request ("POST" , url , payload )
237
235
238
- def detach_port ( self , connected_interface_id : str , ucvni_uuid : str ) -> str :
239
- """Runs a Nautobot Job to cleanup a switch interface.
236
+ if native_vlan_id is not None :
237
+ payload [ "untagged_vlan" ] = _vlan_payload ( vlan_group_name , native_vlan_id )
240
238
241
- The nautobot job will find a VLAN that is bound to the UCVNI, remove it
242
- from the Interface and if the VLAN is unused it will delete it.
239
+ return self .make_api_request ("PATCH" , url , payload )
240
+
241
+ def add_port_vlan_associations (
242
+ self ,
243
+ interface_uuid : str ,
244
+ allowed_vlans_ids : set [int ],
245
+ vlan_group_name : str ,
246
+ ) -> dict :
247
+ """Adds the specified vlan(s) to interface untagged/tagged vlans."""
248
+ url = f"/api/dcim/interfaces/{ interface_uuid } /"
249
+
250
+ current_state = self .make_api_request ("GET" , f"{ url } ?depth=1" )
251
+
252
+ current_tagged_vlans = {
253
+ tagged_vlan ["vid" ] for tagged_vlan in current_state .get ("tagged_vlans" , [])
254
+ }
255
+
256
+ tagged_vlans = current_tagged_vlans .union (allowed_vlans_ids )
243
257
244
- The vlan group ID is returned.
245
- """
246
- url = "/api/plugins/undercloud-vni/detach_port"
247
258
payload = {
248
- "ucvni_uuid" : str (ucvni_uuid ),
249
- "connected_interface_id" : str (connected_interface_id ),
259
+ "tagged_vlans" : [
260
+ _vlan_payload (vlan_group_name , vlan_id ) for vlan_id in tagged_vlans
261
+ ],
250
262
}
251
- resp_data = self .make_api_request ("POST " , url , payload )
263
+ return self .make_api_request ("PATCH " , url , payload )
252
264
253
- return resp_data ["vlan_group_id" ]
265
+ def remove_port_network_associations (
266
+ self , interface_uuid : str , network_ids_to_remove : set [str ]
267
+ ):
268
+ query = """
269
+ query($interface_id: ID!){
270
+ interface(id: $interface_id){
271
+ name
272
+ untagged_vlan {id network: rel_ucvni_vlans { id }}
273
+ tagged_vlans {id network: rel_ucvni_vlans { id }}
274
+ }
275
+ }
276
+ """
277
+ variables = {"interface_id" : interface_uuid }
278
+ current = self .api .graphql .query (query , variables ).json ["data" ]["interface" ]
279
+ LOG .debug ("Nautobot %s query result: %s" , variables , current )
254
280
255
- def configure_port_status (self , interface_uuid : str , status : str ) -> dict :
256
281
url = f"/api/dcim/interfaces/{ interface_uuid } /"
257
- payload = {"status" : {"name" : status }}
282
+ payload = {}
283
+
284
+ if (
285
+ current ["untagged_vlan" ]
286
+ and current ["untagged_vlan" ]["id" ] in network_ids_to_remove
287
+ ):
288
+ payload ["untagged_vlan" ] = None
289
+
290
+ payload ["tagged_vlans" ] = [
291
+ tagged_vlan ["id" ]
292
+ for tagged_vlan in current ["tagged_vlans" ]
293
+ if tagged_vlan ["id" ] not in network_ids_to_remove
294
+ ]
295
+
258
296
return self .make_api_request ("PATCH" , url , payload )
259
297
260
298
def fetch_vlan_group_uuid (self , device_uuid : str ) -> str :
@@ -303,3 +341,10 @@ def create_vlan_and_associate_vlan_to_ucvni(self, vlan: VlanPayload):
303
341
) from error
304
342
else :
305
343
return result
344
+
345
+
346
+ def _vlan_payload (vlan_group_name : str , vlan_id : int ) -> dict :
347
+ return {
348
+ "vlan_group" : {"name" : vlan_group_name },
349
+ "vid" : vlan_id ,
350
+ }
0 commit comments