83f805eb72
Apply my comments from the original patch [1] and add unit tests. [1] https://review.opendev.org/c/openstack/blazar/+/781917 Change-Id: I116aad6677423aedb5dda48f06b36afc32819ba8
161 lines
5.2 KiB
ReStructuredText
161 lines
5.2 KiB
ReStructuredText
=================
|
|
Usage Enforcement
|
|
=================
|
|
|
|
Synopsis
|
|
========
|
|
|
|
Usage enforcement and lease constraints can be implemented by operators via
|
|
custom usage enforcement filters or an external service.
|
|
|
|
Description
|
|
===========
|
|
|
|
Usage enforcement filters are called on ``lease_create``, ``lease_update`` and
|
|
``on_end`` operations. The filters check whether or not lease values or
|
|
allocation criteria pass admin defined thresholds. There are currently two
|
|
filters provided out-of-the-box. ``MaxLeaseDurationFilter`` restricts the
|
|
duration of leases. ``ExternalServiceFilter`` calls a third-party service for
|
|
implementing policies using a URL configured in ``blazar.conf``.
|
|
|
|
Options
|
|
=======
|
|
|
|
All filters are a subclass of the BaseFilter class located in
|
|
``blazar/enforcement/filter/base_filter.py``. Custom filters must implement
|
|
methods for ``check_create``, ``check_update``, and ``on_end``. The
|
|
``MaxLeaseDurationFilter`` is a good example to follow. Filters are enabled in
|
|
``blazar.conf`` under the ``[enforcement]`` group. For example, enabling the
|
|
``MaxLeaseDurationFilter`` to limit lease durations to only one day would work
|
|
as follows:
|
|
|
|
.. sourcecode:: console
|
|
|
|
[enforcement]
|
|
enabled_filters = MaxLeaseDurationFilter
|
|
max_lease_duration = 86400
|
|
|
|
..
|
|
|
|
Do note that filter config options follow filter names - the prefix is always
|
|
the snake case of the filter name (``MaxLeaseDurationFilter`` becomes
|
|
``max_lease_duration``; in this case it is special that there is nothing
|
|
beyond the prefix but there is also ``max_lease_duration_exempt_project_ids``).
|
|
|
|
MaxLeaseDurationFilter
|
|
----------------------
|
|
|
|
This filter simply examines the lease ``start_date`` and ``end_date``
|
|
attributes and rejects the lease if its duration exceeds a threshold. It
|
|
supports two configuration options:
|
|
|
|
* ``max_lease_duration``
|
|
* ``max_lease_duration_exempt_project_ids``
|
|
|
|
See the :doc:`../configuration/blazar-conf` page for a description of these
|
|
options.
|
|
|
|
|
|
ExternalServiceFilter
|
|
---------------------
|
|
|
|
This filter delegates the decision for each API to an external HTTP service.
|
|
The service must use token-based authentication, accepting (or ignoring)
|
|
the static token sent by Blazar in the ``X-Auth-Token`` header.
|
|
The following endpoints should be implemented:
|
|
|
|
* ``POST /check-create``
|
|
* ``POST /check-update``
|
|
* ``POST /on-end``
|
|
|
|
The exact URLs can be overridden and not all have to be used (although
|
|
we imagine a proper implementation requires at least both checks unless
|
|
lease updates are disabled in the first place).
|
|
|
|
The external service should return ``204 No Content`` if the parameters meet
|
|
defined criteria and ``403 Forbidden`` if not. The service may send a JSON
|
|
body response with the ``403 Forbidden`` reply, including the rejection
|
|
reasoning in the field named ``message`` as in:
|
|
|
|
.. sourcecode:: json
|
|
|
|
{
|
|
"message": "You shall not pass!"
|
|
}
|
|
|
|
An example of data the external service will receive in a request body (do note
|
|
all dates and times are encoded as strings following the ISO8601 standard that
|
|
is expected in JSON to represent dates and times):
|
|
|
|
* Request example:
|
|
|
|
.. sourcecode:: json
|
|
|
|
{
|
|
"context": {
|
|
"user_id": "c631173e-dec0-4bb7-a0c3-f7711153c06c",
|
|
"project_id": "a0b86a98-b0d3-43cb-948e-00689182efd4",
|
|
"auth_url": "https://api.example.com:5000/v3",
|
|
"region_name": "RegionOne"
|
|
},
|
|
"current_lease": {
|
|
"start_date": "2020-05-13T00:00:00.012345+02:00",
|
|
"end_time": "2020-05-14T23:59:00.012345+02:00",
|
|
"reservations": [
|
|
{
|
|
"resource_type": "physical:host",
|
|
"min": 1,
|
|
"max": 2,
|
|
"hypervisor_properties": "[]",
|
|
"resource_properties": "[\"==\", \"$availability_zone\", \"az1\"]",
|
|
"allocations": [
|
|
{
|
|
"id": "1",
|
|
"hypervisor_hostname": "32af5a7a-e7a3-4883-a643-828e3f63bf54",
|
|
"extra": {
|
|
"availability_zone": "az1"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"lease": {
|
|
"start_date": "2020-05-13T00:00:00.012345+02:00",
|
|
"end_time": "2020-05-14T23:59:00.012345+02:00",
|
|
"reservations": [
|
|
{
|
|
"resource_type": "physical:host",
|
|
"min": 2,
|
|
"max": 3,
|
|
"hypervisor_properties": "[]",
|
|
"resource_properties": "[\"==\", \"$availability_zone\", \"az1\"]",
|
|
"allocations": [
|
|
{
|
|
"id": "1",
|
|
"hypervisor_hostname": "32af5a7a-e7a3-4883-a643-828e3f63bf54",
|
|
"extra": {
|
|
"availability_zone": "az1"
|
|
}
|
|
},
|
|
{
|
|
"id": "2",
|
|
"hypervisor_hostname": "af69aabd-8386-4053-a6dd-1a983787bd7f",
|
|
"extra": {
|
|
"availability_zone": "az1"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
|
|
The ``current_lease`` field is present only in ``check-update`` requests and
|
|
describes the existing lease. In both checks the ``lease`` field describes
|
|
the new lease. In ``on-end``, the ``lease`` field describes the lease that
|
|
has just ended.
|
|
|
|
There is no guarantee on the delivery of the ``on-end`` event and it should be
|
|
considered an optimisation rather than a reliable mechanism.
|