Support reservation_id parameter in List and Get Allocation API

The List and Get Allocation API allows cloud admin to query with
reservation_id in their request. When the parameter is specified in API
requests, the API returns allocations related to the reservation.

Partially Implements: blueprint resource-allocation-api
Change-Id: I87ed410c23f04a17f6c1deeb9ad1e4ab0756a549
This commit is contained in:
Masahito Muroi 2018-07-25 17:12:08 +09:00 committed by Pierre Riteau
parent 7a491b8a79
commit a3aff12f3e
7 changed files with 105 additions and 7 deletions

View File

@ -268,6 +268,7 @@ Request
.. rest_parameters:: parameters.yaml .. rest_parameters:: parameters.yaml
- lease_id: allocation_lease_id_query - lease_id: allocation_lease_id_query
- reservation_id: allocation_reservation_id_query
Response Response
-------- --------
@ -306,6 +307,7 @@ Request
- host_id: host_id_path - host_id: host_id_path
- lease_id: allocation_lease_id_query - lease_id: allocation_lease_id_query
- reservation_id: allocation_reservation_id_query
Response Response
-------- --------

View File

@ -20,6 +20,12 @@ allocation_lease_id_query:
in: query in: query
required: false required: false
type: string type: string
allocation_reservation_id_query:
description: |
Filter allocations results by reservation id
in: query
required: false
type: string
# variables in body # variables in body

View File

@ -89,7 +89,8 @@ def get_reservations_by_host_ids(host_ids, start_date, end_date):
def get_reservation_allocations_by_host_ids(host_ids, start_date, end_date, def get_reservation_allocations_by_host_ids(host_ids, start_date, end_date,
lease_id=None): lease_id=None,
reservation_id=None):
session = get_session() session = get_session()
border0 = models.Lease.end_date < start_date border0 = models.Lease.end_date < start_date
border1 = models.Lease.start_date > end_date border1 = models.Lease.start_date > end_date
@ -100,6 +101,8 @@ def get_reservation_allocations_by_host_ids(host_ids, start_date, end_date,
.filter(~sa.or_(border0, border1))) .filter(~sa.or_(border0, border1)))
if lease_id: if lease_id:
query = query.filter(models.Reservation.lease_id == lease_id) query = query.filter(models.Reservation.lease_id == lease_id)
if reservation_id:
query = query.filter(models.Reservation.id == reservation_id)
return query.all() return query.all()

View File

@ -112,9 +112,12 @@ def get_reservations_by_host_ids(host_ids, start_date, end_date):
def get_reservation_allocations_by_host_ids(host_ids, start_date, end_date, def get_reservation_allocations_by_host_ids(host_ids, start_date, end_date,
lease_id=None): lease_id=None,
return IMPL.get_reservation_allocations_by_host_ids(host_ids, start_date, reservation_id=None):
end_date, lease_id) return IMPL.get_reservation_allocations_by_host_ids(host_ids,
start_date, end_date,
lease_id,
reservation_id)
def get_plugin_reservation(resource_type, resource_id): def get_plugin_reservation(resource_type, resource_id):

View File

@ -83,7 +83,7 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
freepool_name = CONF.nova.aggregate_freepool_name freepool_name = CONF.nova.aggregate_freepool_name
pool = None pool = None
query_options = { query_options = {
QUERY_TYPE_ALLOCATION: ['lease_id'] QUERY_TYPE_ALLOCATION: ['lease_id', 'reservation_id']
} }
def __init__(self): def __init__(self):
@ -521,7 +521,8 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
allocs = host_allocations[host_id] allocs = host_allocations[host_id]
return {"resource_id": host_id, "reservations": allocs} return {"resource_id": host_id, "reservations": allocs}
def query_host_allocations(self, hosts, lease_id=None): def query_host_allocations(self, hosts, lease_id=None,
reservation_id=None):
"""Return dict of host and its allocations. """Return dict of host and its allocations.
The list element forms The list element forms
@ -540,7 +541,7 @@ class PhysicalHostPlugin(base.BasePlugin, nova.NovaClientWrapper):
# To reduce overhead, this method only executes one query # To reduce overhead, this method only executes one query
# to get the allocation information # to get the allocation information
allocs = db_utils.get_reservation_allocations_by_host_ids( allocs = db_utils.get_reservation_allocations_by_host_ids(
hosts, start, end, lease_id) hosts, start, end, lease_id, reservation_id)
hosts_allocs = {} hosts_allocs = {}
for reservation, alloc in allocs: for reservation, alloc in allocs:

View File

@ -455,6 +455,26 @@ class SQLAlchemyDBUtilsTestCase(tests.DBTestCase):
self.assertListEqual(expected, [(r['id'], a['id']) for r, a in ret]) self.assertListEqual(expected, [(r['id'], a['id']) for r, a in ret])
def test_get_reservation_allocations_by_host_ids_with_reservation_id(self):
def create_allocation_tuple(lease_id):
reservation = db_api.reservation_get_all_by_lease_id(lease_id)[0]
allocation = db_api.host_allocation_get_all_by_values(
reservation_id=reservation['id'])[0]
return (reservation['id'], allocation['id'])
self._setup_leases()
reservation1 = db_api.reservation_get_all_by_lease_id('lease1')[0]
# query allocations of lease1
expected = [
create_allocation_tuple('lease1'),
]
ret = db_utils.get_reservation_allocations_by_host_ids(
['r1', 'r2'], '2030-01-01 08:00', '2030-01-01 15:00',
reservation_id=reservation1['id'])
self.assertListEqual(expected, [(r['id'], a['id']) for r, a in ret])
def test_get_plugin_reservation_with_host(self): def test_get_plugin_reservation_with_host(self):
patch_host_reservation_get = self.patch(db_api, 'host_reservation_get') patch_host_reservation_get = self.patch(db_api, 'host_reservation_get')
patch_host_reservation_get.return_value = { patch_host_reservation_get.return_value = {

View File

@ -521,6 +521,43 @@ class PhysicalHostPluginTestCase(tests.TestCase):
self.assertListEqual(expected, ret) self.assertListEqual(expected, ret)
def test_list_allocations_with_reservation_id(self):
def reservation_allocation_tuple(r_id, l_id, h_id):
return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id})
self.db_get_reserv_allocs = self.patch(
self.db_utils, 'get_reservation_allocations_by_host_ids')
# Expecting a list of (Reservation, Allocation)
self.db_get_reserv_allocs.return_value = [
reservation_allocation_tuple('reservation-1', 'lease-1', 'host-1'),
reservation_allocation_tuple('reservation-1', 'lease-1', 'host-2'),
]
expected = [
{
'resource_id': 'host-1',
'reservations': [
{'id': 'reservation-1', 'lease_id': 'lease-1'},
]
},
{
'resource_id': 'host-2',
'reservations': [
{'id': 'reservation-1', 'lease_id': 'lease-1'},
]
},
]
ret = self.fake_phys_plugin.list_allocations(
{'reservation_id': 'reservation-1'})
# Sort returned value to use assertListEqual
for r in ret:
r['reservations'].sort(key=lambda x: x['id'])
ret.sort(key=lambda x: x['resource_id'])
self.assertListEqual(expected, ret)
def test_get_allocations(self): def test_get_allocations(self):
def reservation_allocation_tuple(r_id, l_id, h_id): def reservation_allocation_tuple(r_id, l_id, h_id):
return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id}) return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id})
@ -577,6 +614,32 @@ class PhysicalHostPluginTestCase(tests.TestCase):
self.assertDictEqual(expected, ret) self.assertDictEqual(expected, ret)
def test_get_allocations_with_reservation_id(self):
def reservation_allocation_tuple(r_id, l_id, h_id):
return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id})
self.db_get_reserv_allocs = self.patch(
self.db_utils, 'get_reservation_allocations_by_host_ids')
# Expecting a list of (Reservation, Allocation)
self.db_get_reserv_allocs.return_value = [
reservation_allocation_tuple('reservation-1', 'lease-1', 'host-1'),
]
expected = {
'resource_id': 'host-1',
'reservations': [
{'id': 'reservation-1', 'lease_id': 'lease-1'},
]
}
ret = self.fake_phys_plugin.get_allocations(
'host-1', {'reservation_id': 'reservation-1'})
# sort returned value to use assertListEqual
ret['reservations'].sort(key=lambda x: x['id'])
self.assertDictEqual(expected, ret)
def test_get_allocations_with_invalid_host(self): def test_get_allocations_with_invalid_host(self):
def reservation_allocation_tuple(r_id, l_id, h_id): def reservation_allocation_tuple(r_id, l_id, h_id):
return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id}) return ({'id': r_id, 'lease_id': l_id}, {'compute_host_id': h_id})