コード例 #1
0
ファイル: request_filter.py プロジェクト: varun131185/nova
def require_tenant_aggregate(ctxt, request_spec):
    """Require hosts in an aggregate based on tenant id.

    This will modify request_spec to request hosts in an aggregate
    defined specifically for the tenant making the request. We do that
    by looking for a nova host aggregate with metadata indicating which
    tenant it is for, and passing that aggregate uuid to placement to
    limit results accordingly.
    """

    enabled = CONF.scheduler.limit_tenants_to_placement_aggregate
    agg_required = CONF.scheduler.placement_aggregate_required_for_tenants
    if not enabled:
        return

    aggregates = objects.AggregateList.get_by_metadata(
        ctxt, value=request_spec.project_id)
    aggregate_uuids_for_tenant = set([])
    for agg in aggregates:
        for key, value in agg.metadata.items():
            if key.startswith(TENANT_METADATA_KEY):
                aggregate_uuids_for_tenant.add(agg.uuid)
                break

    if aggregate_uuids_for_tenant:
        if ('requested_destination' not in request_spec or
                request_spec.requested_destination is None):
            request_spec.requested_destination = objects.Destination()
        destination = request_spec.requested_destination
        destination.require_aggregates(aggregate_uuids_for_tenant)
    elif agg_required:
        LOG.warning('Tenant %(tenant)s has no available aggregates',
                    {'tenant': request_spec.project_id})
        raise exception.RequestFilterFailed(
            reason=_('No hosts available for tenant'))
コード例 #2
0
ファイル: request_filter.py プロジェクト: vwangyanweida/nova
def routed_networks_filter(
    ctxt: nova_context.RequestContext,
    request_spec: 'objects.RequestSpec'
) -> bool:
    """Adds requested placement aggregates that match requested networks.

    This will modify request_spec to request hosts in aggregates that
    matches segment IDs related to requested networks.

    :param ctxt: The usual suspect for a context object.
    :param request_spec: a classic RequestSpec object containing the request.
    :returns: True if the filter was used or False if not.
    :raises: exception.InvalidRoutedNetworkConfiguration if something went
             wrong when trying to get the related segment aggregates.
    """
    if not CONF.scheduler.query_placement_for_routed_network_aggregates:
        return False

    # NOTE(sbauza): On a create operation with no specific network request, we
    # allocate the network only after scheduling when the nova-compute service
    # calls Neutron. In this case, here we just want to accept any destination
    # as fine.
    # NOTE(sbauza): This could be also going from an old compute reschedule.
    if 'requested_networks' not in request_spec:
        return True

    # This object field is not nullable
    requested_networks = request_spec.requested_networks

    # NOTE(sbauza): This field could be not created yet.
    if (
        'requested_destination' not in request_spec or
        request_spec.requested_destination is None
    ):
        request_spec.requested_destination = objects.Destination()

    # Get the clients we need
    network_api = neutron.API()
    report_api = report.SchedulerReportClient()

    for requested_network in requested_networks:
        network_id = None
        # Check for a specifically requested network ID.
        if "port_id" in requested_network and requested_network.port_id:
            # We have to lookup the port to see which segment(s) to support.
            port = network_api.show_port(ctxt, requested_network.port_id)[
                "port"
            ]
            if port['fixed_ips']:
                # The instance already exists with a related subnet. We need to
                # stick on this subnet.
                # NOTE(sbauza): In case of multiple IPs, we could have more
                # subnets than only one but given they would be for the same
                # port, just looking at the first subnet is needed.
                subnet_id = port['fixed_ips'][0]['subnet_id']
                try:
                    aggregates = utils.get_aggregates_for_routed_subnet(
                        ctxt, network_api, report_api, subnet_id)
                except exception.InvalidRoutedNetworkConfiguration as e:
                    raise exception.RequestFilterFailed(
                        reason=_('Aggregates not found for the subnet %s'
                        ) % subnet_id) from e
            else:
                # The port was just created without a subnet.
                network_id = port["network_id"]
        elif (
            "network_id" in requested_network and requested_network.network_id
        ):
            network_id = requested_network.network_id

        if network_id:
            # As the user only requested a network or a port unbound to a
            # segment, we are free to choose any segment from the network.
            try:
                aggregates = utils.get_aggregates_for_routed_network(
                    ctxt, network_api, report_api, network_id)
            except exception.InvalidRoutedNetworkConfiguration as e:
                raise exception.RequestFilterFailed(
                    reason=_('Aggregates not found for the network %s'
                    ) % network_id) from e

        if aggregates:
            LOG.debug(
                'routed_networks_filter request filter added the following '
                'aggregates for network ID %s: %s',
                network_id, ', '.join(aggregates))
            # NOTE(sbauza): All of the aggregates from this request will be
            # accepted, but they will have an AND relationship with any other
            # requested aggregate, like for another NIC request in this loop.
            request_spec.requested_destination.require_aggregates(aggregates)

    return True