126 lines
4.8 KiB
Python
126 lines
4.8 KiB
Python
# Copyright (c) 2013 Bull.
|
|
#
|
|
# All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
# not use this file except in compliance with the License. You may obtain
|
|
# a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
# License for the specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
import six
|
|
|
|
from blazarnova.i18n import _ # noqa
|
|
|
|
from nova.scheduler import filters
|
|
from oslo_config import cfg
|
|
from oslo_log import log as logging
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
opts = [
|
|
cfg.StrOpt('aggregate_freepool_name',
|
|
default='freepool',
|
|
help='Name of the special aggregate where all hosts '
|
|
'are candidate for physical host reservation'),
|
|
cfg.StrOpt('project_id_key',
|
|
default='blazar:tenant',
|
|
help='Aggregate metadata value for key matching project_id'),
|
|
cfg.StrOpt('blazar_owner',
|
|
default='blazar:owner',
|
|
help='Aggregate metadata key for knowing owner project_id'),
|
|
cfg.StrOpt('blazar_az_prefix',
|
|
default='blazar:',
|
|
help='Prefix for Availability Zones created by Blazar')
|
|
]
|
|
|
|
cfg.CONF.register_opts(opts, 'blazar:physical:host')
|
|
|
|
|
|
class BlazarFilter(filters.BaseHostFilter):
|
|
"""Blazar Filter for nova-scheduler."""
|
|
|
|
run_filter_once_per_request = True
|
|
|
|
def host_passes(self, host_state, spec_obj):
|
|
"""Check if a host in a pool can be used for a request
|
|
|
|
A host is in a pool if it is a member of an aggregate that has
|
|
a metadata item with a key value of "blazar:owner"
|
|
|
|
If the user does not pass "reservation=<id>" as a hint then only
|
|
hosts which are not in a pool (including freepool) pass.
|
|
|
|
If the user does pass "reservation=<id>" as a hint then the host only
|
|
passes if it is a member of the specified pool and that pool
|
|
has a metadata key of either :
|
|
- "blazar:owner=tenant_id (which grants automatically all the
|
|
users from the tenant from which the request came from)
|
|
- or, "tenant_id=blazar:tenant" (which grants extra tenants for
|
|
the reservation)
|
|
"""
|
|
|
|
# Find which Pools the user wants to use (if any)
|
|
requested_pools = spec_obj.get_scheduler_hint('reservation')
|
|
if isinstance(requested_pools, six.text_type):
|
|
requested_pools = [requested_pools]
|
|
|
|
# Get any reservation pools this host is part of
|
|
# Note this include possibly the freepool
|
|
aggregates = host_state.aggregates
|
|
pools = []
|
|
for agg in aggregates:
|
|
if str(agg.availability_zone).startswith(
|
|
cfg.CONF['blazar:physical:host'].blazar_az_prefix):
|
|
pools.append(agg)
|
|
if agg.name == (
|
|
cfg.CONF['blazar:physical:host'].aggregate_freepool_name):
|
|
pools.append(agg)
|
|
|
|
if pools:
|
|
if not requested_pools:
|
|
# Host is in a Pool and none requested
|
|
LOG.info(_("In a user pool or in the freepool"))
|
|
return False
|
|
|
|
# Find aggregate which matches Pool
|
|
for pool in pools:
|
|
if pool.name in requested_pools:
|
|
|
|
# Check tenant is allowed to use this Pool
|
|
|
|
# NOTE(sbauza): Currently, the key is only the project_id,
|
|
# but later will possibly be blazar:tenant:{project_id}
|
|
key = spec_obj.project_id
|
|
access = pool.metadata.get(key)
|
|
if access:
|
|
return True
|
|
# NOTE(sbauza): We also need to check the blazar:owner key
|
|
# until we modify the reservation pool for including the
|
|
# project_id key as for any other extra project
|
|
owner = cfg.CONF['blazar:physical:host'].blazar_owner
|
|
owner_project_id = pool.metadata.get(owner)
|
|
if owner_project_id == spec_obj.project_id:
|
|
return True
|
|
LOG.info(_("Unauthorized request to use Pool "
|
|
"%(pool_id)s by tenant %(tenant_id)s"),
|
|
{'pool_id': pool.name,
|
|
'tenant_id': spec_obj.project_id})
|
|
return False
|
|
|
|
# Host not in requested Pools
|
|
return False
|
|
|
|
else:
|
|
|
|
if requested_pools:
|
|
# Host is not in a Pool and Pool requested
|
|
return False
|
|
return True
|