@@ -342,7 +342,7 @@ def update_port_postcommit(self, context):
342342 state changes that it does not know or care about.
343343 """
344344 port = context .current
345- network = context .network . current
345+ segment = context .top_bound_segment
346346 if self ._is_port_bound (port ):
347347 binding_profile = port ['binding:profile' ]
348348 local_link_information = binding_profile .get (
@@ -359,7 +359,7 @@ def update_port_postcommit(self, context):
359359 return
360360 # If binding has already succeeded, we should have valid links
361361 # at this point, but check just in case.
362- if not self ._is_link_valid (port , network ):
362+ if not self ._is_link_valid (port , segment ):
363363 return
364364 is_802_3ad = self ._is_802_3ad (port )
365365 for link in local_link_information :
@@ -371,7 +371,7 @@ def update_port_postcommit(self, context):
371371 ngs_mac_address = switch_id )
372372
373373 # If segmentation ID is None, set vlan 1
374- segmentation_id = network .get ('provider:segmentation_id' ) or 1
374+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
375375 trunk_details = port .get ('trunk_details' , {})
376376 LOG .debug ("Putting switch port %(switch_port)s on "
377377 "%(switch_info)s in vlan %(segmentation_id)s" ,
@@ -411,10 +411,10 @@ def update_port_postcommit(self, context):
411411 GENERIC_SWITCH_ENTITY )
412412 elif self ._is_port_bound (context .original ):
413413 # The port has been unbound. This will cause the local link
414- # information to be lost, so remove the port from the network on
414+ # information to be lost, so remove the port from the segment on
415415 # the switch now while we have the required information.
416- self ._unplug_port_from_network (context .original ,
417- context .network . current )
416+ self ._unplug_port_from_segment (context .original ,
417+ context .original_top_bound_segment )
418418
419419 def delete_port_precommit (self , context ):
420420 """Delete resources of a port.
@@ -443,7 +443,7 @@ def delete_port_postcommit(self, context):
443443
444444 port = context .current
445445 if self ._is_port_bound (port ):
446- self ._unplug_port_from_network (port , context .network . current )
446+ self ._unplug_port_from_segment (port , context .top_bound_segment )
447447
448448 def _is_vlan_translation_required (self , trunk_details ):
449449 """Check if vlan translation is required to configure specific trunk.
@@ -500,34 +500,50 @@ def bind_port(self, context):
500500 # For more info please read docstring.
501501
502502 port = context .current
503- network = context .network .current
504503 binding_profile = port ['binding:profile' ]
505504 local_link_information = binding_profile .get ('local_link_information' )
506505
507506 if self ._is_port_supported (port ) and local_link_information :
507+ # Filter segments where port is already assigned to subnet(s)
508+ subnets = []
509+ for fixed_ip in port .get ('fixed_ips' , []):
510+ subnet_id = fixed_ip .get ('subnet_id' )
511+ if subnet_id :
512+ subnets .append (context ._plugin .get_subnet (
513+ context .plugin_context ,
514+ subnet_id ))
515+ segments = []
516+ if len (subnets ) > 0 :
517+ for segment in context .segments_to_bind :
518+ for subnet in subnets :
519+ segment_id = subnet .get ('segment_id' )
520+ if segment_id is None or segment_id == segment [api .ID ]:
521+ segments .append (segment )
522+ else :
523+ segments = context .segments_to_bind
524+
508525 # NOTE(jamesdenton): If any link of the port is invalid, none
509526 # of the links should be processed.
510- if not self ._is_link_valid (port , network ):
527+ if not self ._is_link_valid (port , segments [ 0 ] ):
511528 return
512529
513- segments = context .segments_to_bind
514530 context .set_binding (segments [0 ][api .ID ],
515531 portbindings .VIF_TYPE_OTHER , {})
516532
517533 provisioning_blocks .add_provisioning_component (
518534 context ._plugin_context , port ['id' ], resources .PORT ,
519535 GENERIC_SWITCH_ENTITY )
520536
521- def _is_link_valid (self , port , network ):
522- """Return whether a link references valid switch and physnet .
537+ def _is_link_valid (self , port , segment ):
538+ """Return whether a link references valid switch and segment .
523539
524540 If the local link information refers to a switch that is not
525541 known to NGS or the switch is not associated with the respective
526542 physnet, the port will not be processed and no exception will
527543 be raised.
528544
529545 :param port: The port to check
530- :param network: the network mapped to physnet
546+ :param segment: The segment to check against
531547 :returns: Whether the link refers to a configured switch and/or switch
532548 is associated with physnet
533549 """
@@ -550,9 +566,9 @@ def _is_link_valid(self, port, network):
550566 'device' : switch_info })
551567 return False
552568
553- physnet = network [ 'provider:physical_network' ]
569+ physnet = segment . get ( api . PHYSICAL_NETWORK )
554570 switch_physnets = switch ._get_physical_networks ()
555- segmentation_id = network .get ('provider:segmentation_id' ) or 1
571+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
556572
557573 if switch_physnets and physnet not in switch_physnets :
558574 LOG .error ("Cannot bind port %(port)s as device %(device)s "
@@ -616,15 +632,15 @@ def _is_802_3ad(port):
616632 return False
617633 return local_group_information .get ('bond_mode' ) in ['4' , '802.3ad' ]
618634
619- def _unplug_port_from_network (self , port , network ):
620- """Unplug a port from a network .
635+ def _unplug_port_from_segment (self , port , segment ):
636+ """Unplug a port from a segment .
621637
622638 If the configuration required to unplug the port is not present
623639 (e.g. local link information), the port will not be unplugged and no
624640 exception will be raised.
625641
626642 :param port: The port to unplug
627- :param network : The network from which to unplug the port
643+ :param segment : The segment from which to unplug the port
628644 """
629645 binding_profile = port ['binding:profile' ]
630646 local_link_information = binding_profile .get ('local_link_information' )
@@ -642,7 +658,7 @@ def _unplug_port_from_network(self, port, network):
642658 continue
643659 port_id = link .get ('port_id' )
644660 # If segmentation ID is None, set vlan 1
645- segmentation_id = network .get ('provider:segmentation_id' ) or 1
661+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
646662 LOG .debug ("Unplugging port %(port)s on %(switch_info)s from vlan: "
647663 "%(segmentation_id)s" ,
648664 {'port' : port_id , 'switch_info' : switch_info ,
@@ -656,12 +672,13 @@ def _unplug_port_from_network(self, port, network):
656672 LOG .error ("Failed to unplug port %(port_id)s "
657673 "on device: %(switch)s from network %(net_id)s "
658674 "reason: %(exc)s" ,
659- {'port_id' : port ['id' ], 'net_id' : network ['id' ],
675+ {'port_id' : port ['id' ],
676+ 'net_id' : segment ['network_id' ],
660677 'switch' : switch_info , 'exc' : e })
661678 raise e
662679 LOG .info ('Port %(port_id)s has been unplugged from network '
663680 '%(net_id)s on device %(device)s' ,
664- {'port_id' : port ['id' ], 'net_id' : network [ 'id ' ],
681+ {'port_id' : port ['id' ], 'net_id' : segment [ 'network_id ' ],
665682 'device' : switch_info })
666683
667684 def _get_devices_by_physnet (self , physnet ):
0 commit comments