21
21
from oslo_utils import versionutils
22
22
from oslo_versionedobjects import fields as obj_fields
23
23
from sqlalchemy import func
24
+ from sqlalchemy import or_
24
25
from sqlalchemy import sql
25
26
26
27
from neutron .db .models import dvr as dvr_models
30
31
from neutron .db import models_v2
31
32
from neutron .objects import base
32
33
from neutron .objects .qos import binding as qos_binding
34
+ from neutron .plugins .ml2 import models as ml2_models
33
35
34
36
35
37
@base .NeutronObjectRegistry .register
@@ -390,7 +392,7 @@ def obj_make_compatible(self, primitive, target_version):
390
392
391
393
@classmethod
392
394
@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 ):
394
396
query = context .session .query (l3 .FloatingIP ,
395
397
models_v2 .SubnetPool .address_scope_id )
396
398
query = query .join (
@@ -405,11 +407,28 @@ def get_scoped_floating_ips(cls, context, router_ids):
405
407
models_v2 .SubnetPool ,
406
408
models_v2 .Subnet .subnetpool_id == models_v2 .SubnetPool .id )
407
409
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
+
408
423
# Filter out on router_ids
409
424
query = query .filter (l3 .FloatingIP .router_id .in_ (router_ids ))
410
425
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 )
413
432
414
433
for row in query :
415
434
yield (cls ._load_object (context , row [0 ]), row [1 ])
0 commit comments