@@ -341,7 +341,7 @@ def update_port_postcommit(self, context):
341341 state changes that it does not know or care about.
342342 """
343343 port = context .current
344- network = context .network . current
344+ segment = context .top_bound_segment
345345 if self ._is_port_bound (port ):
346346 binding_profile = port ['binding:profile' ]
347347 local_link_information = binding_profile .get (
@@ -358,7 +358,7 @@ def update_port_postcommit(self, context):
358358 return
359359 # If binding has already succeeded, we should have valid links
360360 # at this point, but check just in case.
361- if not self ._is_link_valid (port , network ):
361+ if not self ._is_link_valid (port , segment ):
362362 return
363363 is_802_3ad = self ._is_802_3ad (port )
364364 for link in local_link_information :
@@ -370,7 +370,7 @@ def update_port_postcommit(self, context):
370370 ngs_mac_address = switch_id )
371371
372372 # If segmentation ID is None, set vlan 1
373- segmentation_id = network .get ('provider:segmentation_id' ) or 1
373+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
374374 LOG .debug ("Putting switch port %(switch_port)s on "
375375 "%(switch_info)s in vlan %(segmentation_id)s" ,
376376 {'switch_port' : port_id , 'switch_info' : switch_info ,
@@ -390,10 +390,10 @@ def update_port_postcommit(self, context):
390390 GENERIC_SWITCH_ENTITY )
391391 elif self ._is_port_bound (context .original ):
392392 # The port has been unbound. This will cause the local link
393- # information to be lost, so remove the port from the network on
393+ # information to be lost, so remove the port from the segment on
394394 # the switch now while we have the required information.
395- self ._unplug_port_from_network (context .original ,
396- context .network . current )
395+ self ._unplug_port_from_segment (context .original ,
396+ context .original_top_bound_segment )
397397
398398 def delete_port_precommit (self , context ):
399399 """Delete resources of a port.
@@ -422,7 +422,7 @@ def delete_port_postcommit(self, context):
422422
423423 port = context .current
424424 if self ._is_port_bound (port ):
425- self ._unplug_port_from_network (port , context .network . current )
425+ self ._unplug_port_from_segment (port , context .top_bound_segment )
426426
427427 def bind_port (self , context ):
428428 """Attempt to bind a port.
@@ -471,34 +471,50 @@ def bind_port(self, context):
471471 # For more info please read docstring.
472472
473473 port = context .current
474- network = context .network .current
475474 binding_profile = port ['binding:profile' ]
476475 local_link_information = binding_profile .get ('local_link_information' )
477476
478477 if self ._is_port_supported (port ) and local_link_information :
478+ # Filter segments where port is already assigned to subnet(s)
479+ subnets = []
480+ for fixed_ip in port .get ('fixed_ips' , []):
481+ subnet_id = fixed_ip .get ('subnet_id' )
482+ if subnet_id :
483+ subnets .append (context ._plugin .get_subnet (
484+ context .plugin_context ,
485+ subnet_id ))
486+ segments = []
487+ if len (subnets ) > 0 :
488+ for segment in context .segments_to_bind :
489+ for subnet in subnets :
490+ segment_id = subnet .get ('segment_id' )
491+ if segment_id is None or segment_id == segment [api .ID ]:
492+ segments .append (segment )
493+ else :
494+ segments = context .segments_to_bind
495+
479496 # NOTE(jamesdenton): If any link of the port is invalid, none
480497 # of the links should be processed.
481- if not self ._is_link_valid (port , network ):
498+ if not self ._is_link_valid (port , segments [ 0 ] ):
482499 return
483500
484- segments = context .segments_to_bind
485501 context .set_binding (segments [0 ][api .ID ],
486502 portbindings .VIF_TYPE_OTHER , {})
487503
488504 provisioning_blocks .add_provisioning_component (
489505 context ._plugin_context , port ['id' ], resources .PORT ,
490506 GENERIC_SWITCH_ENTITY )
491507
492- def _is_link_valid (self , port , network ):
493- """Return whether a link references valid switch and physnet .
508+ def _is_link_valid (self , port , segment ):
509+ """Return whether a link references valid switch and segment .
494510
495511 If the local link information refers to a switch that is not
496512 known to NGS or the switch is not associated with the respective
497513 physnet, the port will not be processed and no exception will
498514 be raised.
499515
500516 :param port: The port to check
501- :param network: the network mapped to physnet
517+ :param segment: The segment to check against
502518 :returns: Whether the link refers to a configured switch and/or switch
503519 is associated with physnet
504520 """
@@ -521,9 +537,9 @@ def _is_link_valid(self, port, network):
521537 'device' : switch_info })
522538 return False
523539
524- physnet = network [ 'provider:physical_network' ]
540+ physnet = segment . get ( api . PHYSICAL_NETWORK )
525541 switch_physnets = switch ._get_physical_networks ()
526- segmentation_id = network .get ('provider:segmentation_id' ) or 1
542+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
527543
528544 if switch_physnets and physnet not in switch_physnets :
529545 LOG .error ("Cannot bind port %(port)s as device %(device)s "
@@ -587,15 +603,15 @@ def _is_802_3ad(port):
587603 return False
588604 return local_group_information .get ('bond_mode' ) in ['4' , '802.3ad' ]
589605
590- def _unplug_port_from_network (self , port , network ):
591- """Unplug a port from a network .
606+ def _unplug_port_from_segment (self , port , segment ):
607+ """Unplug a port from a segment .
592608
593609 If the configuration required to unplug the port is not present
594610 (e.g. local link information), the port will not be unplugged and no
595611 exception will be raised.
596612
597613 :param port: The port to unplug
598- :param network : The network from which to unplug the port
614+ :param segment : The segment from which to unplug the port
599615 """
600616 binding_profile = port ['binding:profile' ]
601617 local_link_information = binding_profile .get ('local_link_information' )
@@ -613,7 +629,7 @@ def _unplug_port_from_network(self, port, network):
613629 continue
614630 port_id = link .get ('port_id' )
615631 # If segmentation ID is None, set vlan 1
616- segmentation_id = network .get ('provider:segmentation_id' ) or 1
632+ segmentation_id = segment .get (api . SEGMENTATION_ID ) or 1
617633 LOG .debug ("Unplugging port %(port)s on %(switch_info)s from vlan: "
618634 "%(segmentation_id)s" ,
619635 {'port' : port_id , 'switch_info' : switch_info ,
@@ -627,12 +643,13 @@ def _unplug_port_from_network(self, port, network):
627643 LOG .error ("Failed to unplug port %(port_id)s "
628644 "on device: %(switch)s from network %(net_id)s "
629645 "reason: %(exc)s" ,
630- {'port_id' : port ['id' ], 'net_id' : network ['id' ],
646+ {'port_id' : port ['id' ],
647+ 'net_id' : segment ['network_id' ],
631648 'switch' : switch_info , 'exc' : e })
632649 raise e
633650 LOG .info ('Port %(port_id)s has been unplugged from network '
634651 '%(net_id)s on device %(device)s' ,
635- {'port_id' : port ['id' ], 'net_id' : network [ 'id ' ],
652+ {'port_id' : port ['id' ], 'net_id' : segment [ 'network_id ' ],
636653 'device' : switch_info })
637654
638655 def _get_devices_by_physnet (self , physnet ):
0 commit comments