OpenStack Compute (Nova)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

request_filter.py 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  2. # not use this file except in compliance with the License. You may obtain
  3. # a copy of the License at
  4. #
  5. # http://www.apache.org/licenses/LICENSE-2.0
  6. #
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. # License for the specific language governing permissions and limitations
  11. # under the License.
  12. from oslo_log import log as logging
  13. import nova.conf
  14. from nova import exception
  15. from nova.i18n import _
  16. from nova import objects
  17. CONF = nova.conf.CONF
  18. LOG = logging.getLogger(__name__)
  19. TENANT_METADATA_KEY = 'filter_tenant_id'
  20. def require_tenant_aggregate(ctxt, request_spec):
  21. """Require hosts in an aggregate based on tenant id.
  22. This will modify request_spec to request hosts in an aggregate
  23. defined specifically for the tenant making the request. We do that
  24. by looking for a nova host aggregate with metadata indicating which
  25. tenant it is for, and passing that aggregate uuid to placement to
  26. limit results accordingly.
  27. """
  28. enabled = CONF.scheduler.limit_tenants_to_placement_aggregate
  29. agg_required = CONF.scheduler.placement_aggregate_required_for_tenants
  30. if not enabled:
  31. return
  32. aggregates = objects.AggregateList.get_by_metadata(
  33. ctxt, value=request_spec.project_id)
  34. aggregate_uuids_for_tenant = set([])
  35. for agg in aggregates:
  36. for key, value in agg.metadata.items():
  37. if key.startswith(TENANT_METADATA_KEY):
  38. aggregate_uuids_for_tenant.add(agg.uuid)
  39. break
  40. if aggregate_uuids_for_tenant:
  41. if ('requested_destination' not in request_spec or
  42. request_spec.requested_destination is None):
  43. request_spec.requested_destination = objects.Destination()
  44. destination = request_spec.requested_destination
  45. destination.require_aggregates(aggregate_uuids_for_tenant)
  46. elif agg_required:
  47. LOG.warning('Tenant %(tenant)s has no available aggregates',
  48. {'tenant': request_spec.project_id})
  49. raise exception.RequestFilterFailed(
  50. reason=_('No hosts available for tenant'))
  51. def map_az_to_placement_aggregate(ctxt, request_spec):
  52. """Map requested nova availability zones to placement aggregates.
  53. This will modify request_spec to request hosts in an aggregate that
  54. matches the desired AZ of the user's request.
  55. """
  56. if not CONF.scheduler.query_placement_for_availability_zone:
  57. return
  58. az_hint = request_spec.availability_zone
  59. if not az_hint:
  60. return
  61. aggregates = objects.AggregateList.get_by_metadata(ctxt,
  62. key='availability_zone',
  63. value=az_hint)
  64. if aggregates:
  65. if ('requested_destination' not in request_spec or
  66. request_spec.requested_destination is None):
  67. request_spec.requested_destination = objects.Destination()
  68. request_spec.requested_destination.require_aggregates(
  69. [agg.uuid for agg in aggregates])
  70. ALL_REQUEST_FILTERS = [
  71. require_tenant_aggregate,
  72. map_az_to_placement_aggregate,
  73. ]
  74. def process_reqspec(ctxt, request_spec):
  75. """Process an objects.ReqestSpec before calling placement.
  76. :param ctxt: A RequestContext
  77. :param request_spec: An objects.RequestSpec to be inspected/modified
  78. """
  79. for filter in ALL_REQUEST_FILTERS:
  80. filter(ctxt, request_spec)