2929from networking_generic_switch .devices import utils as device_utils
3030from networking_generic_switch import exceptions as exc
3131from networking_generic_switch import locking as ngs_lock
32+ from networking_generic_switch import utils as ngs_utils
3233
3334LOG = logging .getLogger (__name__ )
3435CONF = cfg .CONF
@@ -90,6 +91,22 @@ class NetmikoSwitch(devices.GenericSwitchDevice):
9091
9192 SAVE_CONFIGURATION = None
9293
94+ SET_NATIVE_VLAN = None
95+
96+ DELETE_NATIVE_VLAN = None
97+
98+ SET_NATIVE_VLAN_BOND = None
99+
100+ DELETE_NATIVE_VLAN_BOND = None
101+
102+ ADD_NETWORK_TO_TRUNK = None
103+
104+ REMOVE_NETWORK_FROM_TRUNK = None
105+
106+ ADD_NETWORK_TO_BOND_TRUNK = None
107+
108+ DELETE_NETWORK_ON_BOND_TRUNK = None
109+
93110 ERROR_MSG_PATTERNS = ()
94111 """Sequence of error message patterns.
95112
@@ -145,6 +162,14 @@ def __init__(self, device_cfg, *args, **kwargs):
145162 self .locker .start ()
146163 atexit .register (self .locker .stop )
147164
165+ @property
166+ def support_trunk_on_ports (self ):
167+ return bool (self .ADD_NETWORK_TO_TRUNK )
168+
169+ @property
170+ def support_trunk_on_bond_ports (self ):
171+ return bool (self .ADD_NETWORK_TO_BOND_TRUNK )
172+
148173 def _format_commands (self , commands , ** kwargs ):
149174 if not commands :
150175 return []
@@ -277,7 +302,7 @@ def del_network(self, segmentation_id, network_id):
277302 return self .send_commands_to_device (cmds )
278303
279304 @check_output ('plug port' )
280- def plug_port_to_network (self , port , segmentation_id ):
305+ def plug_port_to_network (self , port , segmentation_id , trunk_details = None ):
281306 cmds = []
282307 if self ._disable_inactive_ports () and self .ENABLE_PORT :
283308 cmds += self ._format_commands (self .ENABLE_PORT , port = port )
@@ -287,18 +312,38 @@ def plug_port_to_network(self, port, segmentation_id):
287312 self .DELETE_PORT ,
288313 port = port ,
289314 segmentation_id = ngs_port_default_vlan )
290- cmds += self ._format_commands (
291- self .PLUG_PORT_TO_NETWORK ,
292- port = port ,
293- segmentation_id = segmentation_id )
315+
316+ if trunk_details :
317+ cmds += self ._format_commands (self .SET_NATIVE_VLAN ,
318+ port = port ,
319+ segmentation_id = segmentation_id )
320+ for sub_port in trunk_details .get ('sub_ports' , []):
321+ cmds += self ._format_commands (
322+ self .ADD_NETWORK_TO_TRUNK , port = port ,
323+ segmentation_id = sub_port ['segmentation_id' ])
324+ else :
325+ cmds += self ._format_commands (
326+ self .PLUG_PORT_TO_NETWORK ,
327+ port = port ,
328+ segmentation_id = segmentation_id )
329+
294330 return self .send_commands_to_device (cmds )
295331
296332 @check_output ('unplug port' )
297- def delete_port (self , port , segmentation_id ):
333+ def delete_port (self , port , segmentation_id , trunk_details = None ):
298334 cmds = self ._format_commands (self .DELETE_PORT ,
299335 port = port ,
300336 segmentation_id = segmentation_id )
301337 ngs_port_default_vlan = self ._get_port_default_vlan ()
338+ if trunk_details :
339+ cmds += self ._format_commands (self .DELETE_NATIVE_VLAN ,
340+ port = port ,
341+ segmentation_id = segmentation_id )
342+ for sub_port in trunk_details .get ('sub_ports' , []):
343+ cmds += self ._format_commands (
344+ self .REMOVE_NETWORK_FROM_TRUNK , port = port ,
345+ segmentation_id = sub_port ['segmentation_id' ])
346+
302347 if ngs_port_default_vlan :
303348 # NOTE(mgoddard): Pass network_id and segmentation_id for drivers
304349 # not yet using network_name.
@@ -315,14 +360,16 @@ def delete_port(self, port, segmentation_id):
315360 segmentation_id = ngs_port_default_vlan )
316361 if self ._disable_inactive_ports () and self .DISABLE_PORT :
317362 cmds += self ._format_commands (self .DISABLE_PORT , port = port )
363+
318364 return self .send_commands_to_device (cmds )
319365
320366 @check_output ('plug bond' )
321- def plug_bond_to_network (self , bond , segmentation_id ):
367+ def plug_bond_to_network (self , bond , segmentation_id , trunk_details = None ):
322368 # Fallback to regular plug port if no specialist PLUG_BOND_TO_NETWORK
323369 # commands set
324370 if not self .PLUG_BOND_TO_NETWORK :
325- return self .plug_port_to_network (bond , segmentation_id )
371+ return self .plug_port_to_network (bond , segmentation_id ,
372+ trunk_details = trunk_details )
326373 cmds = []
327374 if self ._disable_inactive_ports () and self .ENABLE_BOND :
328375 cmds += self ._format_commands (self .ENABLE_BOND , bond = bond )
@@ -332,22 +379,44 @@ def plug_bond_to_network(self, bond, segmentation_id):
332379 self .UNPLUG_BOND_FROM_NETWORK ,
333380 bond = bond ,
334381 segmentation_id = ngs_port_default_vlan )
335- cmds += self ._format_commands (
336- self .PLUG_BOND_TO_NETWORK ,
337- bond = bond ,
338- segmentation_id = segmentation_id )
382+
383+ if trunk_details :
384+ cmds += self ._format_commands (self .SET_NATIVE_VLAN_BOND ,
385+ bond = bond ,
386+ segmentation_id = segmentation_id )
387+ for sub_port in trunk_details .get ('sub_ports' , []):
388+ cmds += self ._format_commands (
389+ self .ADD_NETWORK_TO_BOND_TRUNK , bond = bond ,
390+ segmentation_id = sub_port ['segmentation_id' ])
391+ else :
392+ cmds += self ._format_commands (
393+ self .PLUG_BOND_TO_NETWORK ,
394+ bond = bond ,
395+ segmentation_id = segmentation_id )
396+
339397 return self .send_commands_to_device (cmds )
340398
341399 @check_output ('unplug bond' )
342- def unplug_bond_from_network (self , bond , segmentation_id ):
400+ def unplug_bond_from_network (self , bond , segmentation_id ,
401+ trunk_details = None ):
343402 # Fallback to regular port delete if no specialist
344403 # UNPLUG_BOND_FROM_NETWORK commands set
345404 if not self .UNPLUG_BOND_FROM_NETWORK :
346- return self .delete_port (bond , segmentation_id )
405+ return self .delete_port (bond , segmentation_id ,
406+ trunk_details = trunk_details )
347407 cmds = self ._format_commands (self .UNPLUG_BOND_FROM_NETWORK ,
348408 bond = bond ,
349409 segmentation_id = segmentation_id )
350410 ngs_port_default_vlan = self ._get_port_default_vlan ()
411+ if trunk_details :
412+ cmds += self ._format_commands (self .DELETE_NATIVE_VLAN_BOND ,
413+ bond = bond ,
414+ segmentation_id = segmentation_id )
415+ for sub_port in trunk_details .get ('sub_ports' , []):
416+ cmds += self ._format_commands (
417+ self .ADD_NETWORK_TO_BOND_TRUNK , bond = bond ,
418+ segmentation_id = sub_port ['segmentation_id' ])
419+
351420 if ngs_port_default_vlan :
352421 # NOTE(mgoddard): Pass network_id and segmentation_id for drivers
353422 # not yet using network_name.
@@ -364,6 +433,7 @@ def unplug_bond_from_network(self, bond, segmentation_id):
364433 segmentation_id = ngs_port_default_vlan )
365434 if self ._disable_inactive_ports () and self .DISABLE_BOND :
366435 cmds += self ._format_commands (self .DISABLE_BOND , bond = bond )
436+
367437 return self .send_commands_to_device (cmds )
368438
369439 def send_config_set (self , net_connect , cmd_set ):
@@ -417,3 +487,48 @@ def check_output(self, output, operation):
417487 raise exc .GenericSwitchNetmikoConfigError (
418488 config = device_utils .sanitise_config (self .config ),
419489 error = msg )
490+
491+ def add_subports_on_trunk (self , binding_profile , port_id , subports ):
492+ """Allow subports on trunk
493+
494+ :param binding_profile: Binding profile of parent port
495+ :param port_id: The name of the switch port from
496+ Local Link Information
497+ :param subports: List with subports objects.
498+ """
499+ cmds = []
500+ is_802_3ad = ngs_utils .is_802_3ad (binding_profile )
501+
502+ for sub_port in subports :
503+ if is_802_3ad :
504+ cmds += self ._format_commands (
505+ self .ADD_NETWORK_TO_BOND_TRUNK , bond = port_id ,
506+ segmentation_id = sub_port ['segmentation_id' ])
507+ else :
508+ cmds += self ._format_commands (
509+ self .ADD_NETWORK_TO_TRUNK , port = port_id ,
510+ segmentation_id = sub_port ['segmentation_id' ])
511+ return self .send_commands_to_device (cmds )
512+
513+ def del_subports_on_trunk (self , binding_profile , port_id , subports ):
514+ """Allow subports on trunk
515+
516+ :param binding_profile: Binding profile of parent port
517+ :param port_id: The name of the switch port from
518+ Local Link Information
519+ :param subports: List with subports objects.
520+ """
521+
522+ cmds = []
523+ is_802_3ad = ngs_utils .is_802_3ad (binding_profile )
524+
525+ for sub_port in subports :
526+ if is_802_3ad :
527+ cmds += self ._format_commands (
528+ self .DELETE_NETWORK_ON_BOND_TRUNK , bond = port_id ,
529+ segmentation_id = sub_port ['segmentation_id' ])
530+ else :
531+ cmds += self ._format_commands (
532+ self .REMOVE_NETWORK_FROM_TRUNK , port = port_id ,
533+ segmentation_id = sub_port ['segmentation_id' ])
534+ return self .send_commands_to_device (cmds )
0 commit comments