'status': floatingip['status']}
return self._fields(res, fields)
- def _get_interface_ports_for_network(self, context, network_id):
- router_intf_qry = context.session.query(RouterPort)
- router_intf_qry = router_intf_qry.join(models_v2.Port)
- return router_intf_qry.filter(
- models_v2.Port.network_id == network_id,
- RouterPort.port_type == DEVICE_OWNER_ROUTER_INTF
- )
-
def _get_router_for_floatingip(self, context, internal_port,
internal_subnet_id,
external_network_id):
'which has no gateway_ip') % internal_subnet_id)
raise n_exc.BadRequest(resource='floatingip', msg=msg)
- router_intf_ports = self._get_interface_ports_for_network(
- context, internal_port['network_id'])
-
- # This joins on port_id so is not a cross-join
- routerport_qry = router_intf_ports.join(models_v2.IPAllocation)
- routerport_qry = routerport_qry.filter(
+ # Find routers(with router_id and interface address) that
+ # connect given internal subnet and the external network.
+ # Among them, if the router's interface address matches
+ # with subnet's gateway-ip, return that router.
+ # Otherwise return the first router.
+ gw_port = orm.aliased(models_v2.Port, name="gw_port")
+ routerport_qry = context.session.query(
+ RouterPort.router_id, models_v2.IPAllocation.ip_address).join(
+ models_v2.Port, models_v2.IPAllocation).filter(
+ models_v2.Port.network_id == internal_port['network_id'],
+ RouterPort.port_type.in_(l3_constants.ROUTER_INTERFACE_OWNERS),
models_v2.IPAllocation.subnet_id == internal_subnet_id
- )
+ ).join(gw_port, gw_port.device_id == RouterPort.router_id).filter(
+ gw_port.network_id == external_network_id).distinct()
- for router_port in routerport_qry:
- router_id = router_port.router.id
- router_gw_qry = context.session.query(models_v2.Port)
- has_gw_port = router_gw_qry.filter_by(
- network_id=external_network_id,
- device_id=router_id,
- device_owner=DEVICE_OWNER_ROUTER_GW).count()
- if has_gw_port:
+ first_router_id = None
+ for router_id, interface_ip in routerport_qry:
+ if interface_ip == subnet['gateway_ip']:
return router_id
+ if not first_router_id:
+ first_router_id = router_id
+ if first_router_id:
+ return first_router_id
raise l3.ExternalGatewayForFloatingIPNotFound(
subnet_id=internal_subnet_id,
from neutron.db import l3_attrs_db
from neutron.db import l3_db
from neutron.db import l3_dvrscheduler_db as l3_dvrsched_db
-from neutron.db import models_v2
from neutron.extensions import l3
from neutron.extensions import portbindings
from neutron import manager
return super(L3_NAT_with_dvr_db_mixin,
self)._get_device_owner(context, router)
- def _get_interface_ports_for_network(self, context, network_id):
- router_intf_qry = context.session.query(l3_db.RouterPort)
- router_intf_qry = router_intf_qry.join(models_v2.Port)
-
- return router_intf_qry.filter(
- models_v2.Port.network_id == network_id,
- l3_db.RouterPort.port_type.in_(l3_const.ROUTER_INTERFACE_OWNERS)
- )
-
def _update_fip_assoc(self, context, fip, floatingip_db, external_port):
"""Override to create floating agent gw port for DVR.
self.assertEqual(fp2['floatingip']['router_id'],
r2['router']['id'])
+ def test_floatingip_same_external_and_internal(self):
+ # Select router with subnet's gateway_ip for floatingip when
+ # routers connected to same subnet and external network.
+ with self.subnet(cidr="10.0.0.0/24") as exs,\
+ self.subnet(cidr="12.0.0.0/24", gateway_ip="12.0.0.50") as ins:
+ network_ex_id = exs['subnet']['network_id']
+ self._set_net_external(network_ex_id)
+
+ r2i_fixed_ips = [{'ip_address': '12.0.0.2'}]
+ with self.router() as r1,\
+ self.router() as r2,\
+ self.port(subnet=ins,
+ fixed_ips=r2i_fixed_ips) as r2i_port:
+ self._add_external_gateway_to_router(
+ r1['router']['id'],
+ network_ex_id)
+ self._router_interface_action('add', r2['router']['id'],
+ None,
+ r2i_port['port']['id'])
+ self._router_interface_action('add', r1['router']['id'],
+ ins['subnet']['id'],
+ None)
+ self._add_external_gateway_to_router(
+ r2['router']['id'],
+ network_ex_id)
+
+ with self.port(subnet=ins,
+ fixed_ips=[{'ip_address': '12.0.0.8'}]
+ ) as private_port:
+
+ fp = self._make_floatingip(self.fmt, network_ex_id,
+ private_port['port']['id'],
+ floating_ip='10.0.0.8')
+ self.assertEqual(r1['router']['id'],
+ fp['floatingip']['router_id'])
+
def test_floatingip_delete_router_intf_with_subnet_id_returns_409(self):
found = False
with self.floatingip_with_assoc():