Example #1
0
    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)
Example #2
0
    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'])
Example #3
0
    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'])
Example #4
0
    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'])
Example #5
0
    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'])
Example #6
0
    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'])
Example #7
0
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'])
Example #8
0
    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'])