Add update/delete resource inventory
This patch adds two methods to add and to delete resource inventory in placement client. Change-Id: Iee05962c3726411cca015c6155e59161aa023d3e Blueprint: placement-api
This commit is contained in:
parent
44bc4383ab
commit
99924bd79b
|
@ -334,3 +334,127 @@ class TestPlacementClient(tests.TestCase):
|
|||
self.assertRaises(
|
||||
exceptions.ResourceClassDeletionFailed,
|
||||
self.client.delete_reservation_class, rc_name)
|
||||
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get_resource_provider')
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get')
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_update_reservation_inventory(self, kss_req, client_get, get_rp):
|
||||
host_uuid = uuidutils.generate_uuid()
|
||||
host_name = "compute-1"
|
||||
rp_uuid = uuidutils.generate_uuid()
|
||||
rp_name = "blazar_compute-1"
|
||||
|
||||
# Build the mock of current resource provider
|
||||
mock_get_rp_json = {'uuid': rp_uuid,
|
||||
'name': rp_name,
|
||||
'generation': 0,
|
||||
'parent_provider_uuid': host_uuid}
|
||||
get_rp.return_value = mock_get_rp_json
|
||||
|
||||
# Build the mock of "current" inventory for get_inventory()
|
||||
curr_gen = 11
|
||||
mock_get_inv_json = {
|
||||
'inventories': {
|
||||
'CUSTOM_RESERVATION_CURR': {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": 1
|
||||
},
|
||||
},
|
||||
"resource_provider_generation": curr_gen
|
||||
}
|
||||
client_get.return_value = fake_requests.FakeResponse(
|
||||
200, content=json.dumps(mock_get_inv_json))
|
||||
|
||||
# Build the mock of "updated" inventory for update_inventory()
|
||||
update_gen = 12
|
||||
mock_put_json = {
|
||||
'inventories': {
|
||||
'CUSTOM_RESERVATION_CURR': {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": 1
|
||||
},
|
||||
'CUSTOM_RESERVATION_ADD': {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": 3
|
||||
},
|
||||
},
|
||||
"resource_provider_generation": update_gen
|
||||
}
|
||||
kss_req.return_value = fake_requests.FakeResponse(
|
||||
200, content=json.dumps(mock_put_json))
|
||||
|
||||
result = self.client.update_reservation_inventory(host_name, 'add', 3)
|
||||
|
||||
expected_data = {
|
||||
'inventories': {
|
||||
'CUSTOM_RESERVATION_CURR': {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": 1
|
||||
},
|
||||
'CUSTOM_RESERVATION_ADD': {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": 3
|
||||
},
|
||||
},
|
||||
"resource_provider_generation": curr_gen
|
||||
}
|
||||
expected_url = '/resource_providers/%s/inventories' % rp_uuid
|
||||
kss_req.assert_called_once_with(
|
||||
expected_url, 'PUT', json=expected_data,
|
||||
endpoint_filter={'service_type': 'placement',
|
||||
'interface': 'public'},
|
||||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
self.assertEqual(mock_put_json, result)
|
||||
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get_resource_provider')
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_delete_reservation_inventory(self, kss_req, get_rp):
|
||||
host_uuid = uuidutils.generate_uuid()
|
||||
host_name = "compute-1"
|
||||
rp_uuid = uuidutils.generate_uuid()
|
||||
rp_name = "blazar_compute-1"
|
||||
|
||||
# Build the mock of current resource provider
|
||||
mock_get_rp_json = {'uuid': rp_uuid,
|
||||
'name': rp_name,
|
||||
'generation': 0,
|
||||
'parent_provider_uuid': host_uuid}
|
||||
get_rp.return_value = mock_get_rp_json
|
||||
|
||||
kss_req.return_value = fake_requests.FakeResponse(200)
|
||||
|
||||
self.client.delete_reservation_inventory(host_name, "curr1")
|
||||
|
||||
expected_url = ('/resource_providers/%s/inventories'
|
||||
'/CUSTOM_RESERVATION_CURR1' % rp_uuid)
|
||||
|
||||
kss_req.assert_called_once_with(
|
||||
expected_url, 'DELETE',
|
||||
endpoint_filter={'service_type': 'placement',
|
||||
'interface': 'public'},
|
||||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
|
|
|
@ -33,3 +33,12 @@ class ResourceClassCreationFailed(exceptions.BlazarException):
|
|||
|
||||
class ResourceClassDeletionFailed(exceptions.BlazarException):
|
||||
msg_fmt = _("Failed to delete resource class '%(resource_class)s'")
|
||||
|
||||
|
||||
class ResourceProviderNotFound(exceptions.BlazarException):
|
||||
msg_fmt = _("No such resource provider %(resource_provider)s")
|
||||
|
||||
|
||||
class InventoryUpdateFailed(exceptions.BlazarException):
|
||||
msg_fmt = _("Failed to update the inventory of resource provider "
|
||||
"%(resource_provider)s")
|
||||
|
|
|
@ -255,3 +255,99 @@ class BlazarPlacementClient(object):
|
|||
reservation_uuid = reservation_uuid.upper().replace("-", "_")
|
||||
rc_name = 'CUSTOM_RESERVATION_' + reservation_uuid
|
||||
self.delete_resource_class(rc_name)
|
||||
|
||||
def get_inventory(self, rp_uuid):
|
||||
"""Calls the placement API to get resource inventory information.
|
||||
|
||||
:param rp_uuid: UUID of the resource provider to get
|
||||
"""
|
||||
url = '/resource_providers/%s/inventories' % rp_uuid
|
||||
resp = self.get(url)
|
||||
if resp:
|
||||
return resp.json()
|
||||
raise exceptions.ResourceProviderNotFound(resource_provider=rp_uuid)
|
||||
|
||||
def update_inventory(self, rp_uuid, inv_data):
|
||||
"""Update the inventory for the resource provider.
|
||||
|
||||
:param rp_uuid: The resource provider UUID for the operation
|
||||
:param inv_data: The new inventory for the resource provider
|
||||
:raises: ResourceProviderNotFound or InventoryUpdateFailed error.
|
||||
"""
|
||||
curr = self.get_inventory(rp_uuid)
|
||||
inventories = curr['inventories']
|
||||
generation = curr['resource_provider_generation']
|
||||
|
||||
inventories.update(inv_data)
|
||||
|
||||
payload = {
|
||||
'inventories': inventories,
|
||||
'resource_provider_generation': generation,
|
||||
}
|
||||
url = '/resource_providers/%s/inventories' % rp_uuid
|
||||
|
||||
resp = self.put(url, payload)
|
||||
if resp:
|
||||
return resp.json()
|
||||
|
||||
# TODO(tetsuro): Try again on 409 conflict errors
|
||||
raise exceptions.InventoryUpdateFailed(resource_provider=rp_uuid)
|
||||
|
||||
def delete_inventory(self, rp_uuid, rc_name):
|
||||
"""Delete the inventory for the resource provider.
|
||||
|
||||
:param rp_uuid: The resource provider UUID for the operation
|
||||
:param rc_name: The resource class name to delete from inventory
|
||||
:raises: InventoryUpdateFailed error
|
||||
"""
|
||||
url = '/resource_providers/%s/inventories/%s' % (rp_uuid, rc_name)
|
||||
|
||||
resp = self.delete(url)
|
||||
if resp:
|
||||
return
|
||||
|
||||
raise exceptions.InventoryUpdateFailed(resource_provider=rp_uuid)
|
||||
|
||||
def update_reservation_inventory(self, host_name, reserv_uuid, num):
|
||||
"""Update the reservation inventory for the reservation provider.
|
||||
|
||||
:param host_name: The name of the target host
|
||||
:param reserv_uuid: The reservation uuid
|
||||
:param num: The number of the instances to reserve on the host
|
||||
:return: The updated inventory record
|
||||
"""
|
||||
# Get reservation provider uuid
|
||||
rp_name = "blazar_" + host_name
|
||||
rp = self.get_resource_provider(rp_name)
|
||||
rp_uuid = rp['uuid']
|
||||
|
||||
# Build inventory data
|
||||
reserv_uuid = reserv_uuid.upper().replace("-", "_")
|
||||
rc_name = 'CUSTOM_RESERVATION_' + reserv_uuid
|
||||
inv_data = {
|
||||
rc_name: {
|
||||
"allocation_ratio": 1.0,
|
||||
"max_unit": 1,
|
||||
"min_unit": 1,
|
||||
"reserved": 0,
|
||||
"step_size": 1,
|
||||
"total": num
|
||||
},
|
||||
}
|
||||
return self.update_inventory(rp_uuid, inv_data)
|
||||
|
||||
def delete_reservation_inventory(self, host_name, reserv_uuid):
|
||||
"""Delete the reservation inventory for the reservation provider.
|
||||
|
||||
:param host_name: The name of the target host
|
||||
:param reserv_uuid: The reservation uuid
|
||||
"""
|
||||
# Get reservation provider uuid
|
||||
rp_name = "blazar_" + host_name
|
||||
rp = self.get_resource_provider(rp_name)
|
||||
rp_uuid = rp['uuid']
|
||||
|
||||
# Convert reservation uuid to resource class name
|
||||
reserv_uuid = reserv_uuid.upper().replace("-", "_")
|
||||
rc_name = 'CUSTOM_RESERVATION_' + reserv_uuid
|
||||
self.delete_inventory(rp_uuid, rc_name)
|
||||
|
|
Loading…
Reference in New Issue