2121from oslo_utils import versionutils
2222from oslo_versionedobjects import fields as obj_fields
2323from sqlalchemy import func
24+ from sqlalchemy import or_
2425from sqlalchemy import sql
2526
2627from neutron .db .models import dvr as dvr_models
3031from neutron .db import models_v2
3132from neutron .objects import base
3233from neutron .objects .qos import binding as qos_binding
34+ from neutron .plugins .ml2 import models as ml2_models
3335
3436
3537@base .NeutronObjectRegistry .register
@@ -390,7 +392,7 @@ def obj_make_compatible(self, primitive, target_version):
390392
391393 @classmethod
392394 @db_api .CONTEXT_READER
393- def get_scoped_floating_ips (cls , context , router_ids ):
395+ def get_scoped_floating_ips (cls , context , router_ids , host = None ):
394396 query = context .session .query (l3 .FloatingIP ,
395397 models_v2 .SubnetPool .address_scope_id )
396398 query = query .join (
@@ -405,11 +407,28 @@ def get_scoped_floating_ips(cls, context, router_ids):
405407 models_v2 .SubnetPool ,
406408 models_v2 .Subnet .subnetpool_id == models_v2 .SubnetPool .id )
407409
410+ # If a host value is provided, filter output to a specific host
411+ if host is not None :
412+ query = query .outerjoin (
413+ ml2_models .PortBinding ,
414+ models_v2 .Port .id == ml2_models .PortBinding .port_id )
415+ # Also filter for ports with migrating_to as they may be relevant
416+ # to this host but might not yet have the 'host' column updated
417+ # if the migration is in a pre-live migration state
418+ query = query .filter (or_ (
419+ ml2_models .PortBinding .host == host ,
420+ ml2_models .PortBinding .profile .like ('%migrating_to%' ),
421+ ))
422+
408423 # Filter out on router_ids
409424 query = query .filter (l3 .FloatingIP .router_id .in_ (router_ids ))
410425
411- # Remove duplicate rows based on FIP IDs
412- query = query .group_by (l3 .FloatingIP .id )
426+ # Remove duplicate rows based on FIP IDs and the subnet pool address
427+ # scope. Only one subnet pool (per IP version, 4 in this case) can
428+ # be assigned to a subnet. The subnet pool address scope for a FIP is
429+ # unique.
430+ query = query .group_by (l3 .FloatingIP .id ,
431+ models_v2 .SubnetPool .address_scope_id )
413432
414433 for row in query :
415434 yield (cls ._load_object (context , row [0 ]), row [1 ])
0 commit comments