Exemplo n.º 1
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_exc.ExternalGatewayForFloatingIPNotFound(
            subnet_id=internal_subnet['id'],
            external_network_id=external_network_id,
            port_id=internal_port['id'])
Exemplo n.º 2
0
    def test_negative_find_a_router_for_fip_port_forwarding(
            self, mock_get_subnet, mock_get_port, mock_get_router,
            mock_get_ip_subnet):
        fip_obj = mock.Mock()
        pf_dict = {
            'internal_port_id': 'internal_neutron_port',
            'internal_ip_address': '10.0.0.1'
        }
        port_dict = {
            'id':
            'ID',
            'fixed_ips': [{
                "subnet_id": "test-subnet-id",
                "ip_address": "10.0.0.1"
            }]
        }
        mock_get_port.return_value = port_dict
        mock_get_ip_subnet.return_value = None
        self.assertRaises(
            lib_exc.BadRequest,
            self.pf_plugin._find_a_router_for_fip_port_forwarding, self.ctxt,
            pf_dict, fip_obj)
        self.assertTrue(not mock_get_subnet.called)

        mock_get_ip_subnet.return_value = 'internal_subnet_id'

        mock_get_router.side_effect = (
            lib_l3_exc.ExternalGatewayForFloatingIPNotFound(
                external_network_id=mock.Mock(),
                subnet_id=mock.Mock(),
                port_id=mock.Mock()))
        self.assertRaises(
            lib_exc.BadRequest,
            self.pf_plugin._find_a_router_for_fip_port_forwarding, self.ctxt,
            pf_dict, fip_obj)
        self.assertTrue(mock_get_subnet.called)

        ipv6_port_dict = {
            'id': 'ID',
            'fixed_ips': [{
                "subnet_id": "test-subnet-id",
                "ip_address": "1::1"
            }]
        }
        mock_get_port.return_value = ipv6_port_dict
        self.assertRaises(
            lib_exc.BadRequest,
            self.pf_plugin._find_a_router_for_fip_port_forwarding, self.ctxt,
            pf_dict, fip_obj)
Exemplo n.º 3
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.
        """
        # REVISIT(yamamoto): The above docstring can be removed once
        # https://review.openstack.org/#/c/577029/ is released.
        # 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_models.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_models.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_models.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_exc.ExternalGatewayForFloatingIPNotFound(
            subnet_id=internal_subnet['id'],
            external_network_id=external_network_id,
            port_id=internal_port['id'])
Exemplo n.º 4
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'])