def get_assoc_data(self, context, fip, floating_network_id): """Determine/extract data associated with the internal port. When a floating IP is associated with an internal port, we need to extract/determine some data associated with the internal port, including the internal_ip_address, and router_id. We also need to confirm that this internal port is owned by the tenant who owns the floating IP. """ (internal_port, internal_subnet_id, internal_ip_address) = self._internal_fip_assoc_data(context, fip) router_id = self._get_router_for_floatingip(context, internal_port, internal_subnet_id, floating_network_id) # confirm that this router has a floating # ip enabled gateway with support for this floating IP network try: port_qry = context.elevated().session.query(models_v2.Port) port_qry.filter_by(network_id=floating_network_id, device_id=router_id, device_owner=DEVICE_OWNER_ROUTER_GW).one() except exc.NoResultFound: raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, port_id=internal_port['id']) return (fip['port_id'], internal_ip_address, router_id)
def get_router_for_floatingip(self, context, internal_port, internal_subnet, external_network_id): """Find a router to handle the floating-ip association. :param internal_port: The port for the fixed-ip. :param internal_subnet: The subnet for the fixed-ip. :param external_network_id: The external network for floating-ip. :raises: ExternalGatewayForFloatingIPNotFound if no suitable router is found. """ router_port = l3_models.RouterPort gw_port = orm.aliased(models_v2.Port, name="gw_port") router_port_qry = context.session.query(router_port.router_id).join( gw_port, gw_port.device_id == router_port.router_id).filter( gw_port.network_id == external_network_id, gw_port.device_owner == constants.DEVICE_OWNER_ROUTER_GW).distinct() first_router_id = None for router in router_port_qry: if not first_router_id: first_router_id = router.router_id if first_router_id: return first_router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet['id'], external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): subnet_db = self._core_plugin._get_subnet(context, internal_subnet_id) if not subnet_db['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise q_exc.BadRequest(resource='floatingip', msg=msg) # find router interface ports on this network router_intf_qry = context.session.query(models_v2.Port) router_intf_ports = router_intf_qry.filter_by( network_id=internal_port['network_id'], device_owner=DEVICE_OWNER_ROUTER_INTF) for intf_p in router_intf_ports: if intf_p['fixed_ips'][0]['subnet_id'] == internal_subnet_id: router_id = intf_p['device_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: return router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])
def get_router_for_floatingip(self, context, internal_port, internal_subnet, external_network_id): # REVISIT(yamamoto): These direct manipulation of core-plugin db # resources is not ideal. gw_port = orm.aliased(models_v2.Port, name="gw_port") routerport_qry = context.session.query( l3_db.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'], l3_db.RouterPort.port_type.in_( n_const.ROUTER_INTERFACE_OWNERS ), models_v2.IPAllocation.subnet_id == internal_subnet['id'] ).join( gw_port, gw_port.device_id == l3_db.RouterPort.router_id ).filter( gw_port.network_id == external_network_id, ).distinct() first_router_id = None for router_id, interface_ip in routerport_qry: if interface_ip == internal_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'], external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """We need to over-load this function so that we only return the user visible router and never its redundancy routers (as they never have floatingips associated with them). """ subnet = self._core_plugin._get_subnet(context, internal_subnet_id) if not subnet['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise n_exc.BadRequest(resource='floatingip', msg=msg) gw_port = orm.aliased(models_v2.Port, name="gw_port") routerport_qry = context.session.query( l3_db.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'], l3_db.RouterPort.port_type.in_( l3_constants.ROUTER_INTERFACE_OWNERS), models_v2.IPAllocation.subnet_id == internal_subnet_id ).join(gw_port, gw_port.device_id == l3_db.RouterPort.router_id).filter( gw_port.network_id == external_network_id).distinct() # Ensure that redundancy routers (in a ha group) are not returned, # since only the user visible router should have floatingips. # This can be done by checking that the id of routers does not # appear in the 'redundancy_router_id' column in the # 'cisco_router_redundancy_bindings' table. routerport_qry = routerport_qry.outerjoin( RouterRedundancyBinding, RouterRedundancyBinding.redundancy_router_id == l3_db.RouterPort.router_id) routerport_qry = routerport_qry.filter( RouterRedundancyBinding.redundancy_router_id == expr.null()) 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, external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """We need to over-load this function so that we only return the user visible router and never its redundancy routers (as they never have floatingips associated with them). """ subnet_db = self._core_plugin._get_subnet(context, internal_subnet_id) if not subnet_db['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' '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( models_v2.IPAllocation.subnet_id == internal_subnet_id ) # Ensure that redundancy routers (in a ha group) are not returned, # since only the user visible router should have floatingips. # This can be done by checking that the id of routers does not # appear in the 'redundancy_router_id' column in the # 'cisco_router_redundancy_bindings' table. routerport_qry = routerport_qry.outerjoin( RouterRedundancyBinding, RouterRedundancyBinding.redundancy_router_id == l3_db.RouterPort.router_id) routerport_qry = routerport_qry.filter( RouterRedundancyBinding.redundancy_router_id == expr.null()) 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: return router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): subnet = self._core_plugin.get_subnet(context, internal_subnet_id) if not subnet['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise n_exc.BadRequest(resource='floatingip', msg=msg) # 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_(nlib_const.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() 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 router_ids = self._find_routers_via_routes_for_floatingip( context, internal_port, internal_subnet_id, external_network_id) if router_ids: return router_ids[0] raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])
def _get_router_for_floatingip(self, context, internal_port, internal_subnet_id, external_network_id): """Get a router for a requested floating IP. OpenFlow vrouter does not support NAT, so we need to exclude them from candidate routers for floating IP association. This method is called in l3_db.get_assoc_data(). """ subnet_db = self._get_subnet(context, internal_subnet_id) if not subnet_db['gateway_ip']: msg = (_('Cannot add floating IP to port on subnet %s ' 'which has no gateway_ip') % internal_subnet_id) raise q_exc.BadRequest(resource='floatingip', msg=msg) # find router interface ports on this network router_intf_qry = context.session.query(models_v2.Port) router_intf_ports = router_intf_qry.filter_by( network_id=internal_port['network_id'], device_owner=l3_db.DEVICE_OWNER_ROUTER_INTF) for intf_p in router_intf_ports: if intf_p['fixed_ips'][0]['subnet_id'] == internal_subnet_id: router_id = intf_p['device_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=l3_db.DEVICE_OWNER_ROUTER_GW).count() driver = self._get_router_driver_by_id(context, router_id) if (has_gw_port and driver.floating_ip_support()): return router_id raise l3.ExternalGatewayForFloatingIPNotFound( subnet_id=internal_subnet_id, external_network_id=external_network_id, port_id=internal_port['id'])