Adds subnormal path for placement client (1)
We start to support placement api from Stein, so there are cases where the child resource provider of a host doesn't exist if the host has been created in blazar before Rocky release. This patch changes the placement client code to be aware of the cases. Namely, in cases the resource provider is not found, - Change get_resource_provider() to return None - Change delete_reservation_provider() to skip the operation - Change update_reservation_inventory() to create the resource provider - Change delete_reservation_inventory() to raise an error Change-Id: I82abbc73f69f4036f60b7c549c1cbd0c0b91a130 Blueprint: placement-api
This commit is contained in:
parent
99924bd79b
commit
5e114768a3
|
@ -130,6 +130,28 @@ class TestPlacementClient(tests.TestCase):
|
|||
'parent_provider_uuid': parent_uuid}
|
||||
self.assertEqual(expected, result)
|
||||
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_get_resource_provider_no_rp(self, kss_req):
|
||||
rp_name = 'blazar'
|
||||
|
||||
mock_json_data = {
|
||||
'resource_providers': []
|
||||
}
|
||||
|
||||
kss_req.return_value = fake_requests.FakeResponse(
|
||||
200, content=json.dumps(mock_json_data))
|
||||
|
||||
result = self.client.get_resource_provider(rp_name)
|
||||
|
||||
expected_url = '/resource_providers?name=blazar'
|
||||
kss_req.assert_called_once_with(
|
||||
expected_url, 'GET',
|
||||
endpoint_filter={'service_type': 'placement',
|
||||
'interface': 'public'},
|
||||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
self.assertEqual(None, result)
|
||||
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_get_resource_provider_fail(self, kss_req):
|
||||
rp_name = 'blazar'
|
||||
|
@ -286,6 +308,31 @@ class TestPlacementClient(tests.TestCase):
|
|||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_delete_reservation_provider_no_rp(self, kss_req):
|
||||
host_name = "compute-1"
|
||||
rp_name = "blazar_compute-1"
|
||||
get_json_mock = {
|
||||
'resource_providers': []
|
||||
}
|
||||
mock_call1 = fake_requests.FakeResponse(
|
||||
200, content=json.dumps(get_json_mock))
|
||||
mock_call2 = fake_requests.FakeResponse(200)
|
||||
kss_req.side_effect = [mock_call1, mock_call2]
|
||||
|
||||
self.client.delete_reservation_provider(host_name)
|
||||
|
||||
expected_url_get = "/resource_providers?name=%s" % rp_name
|
||||
kss_req.assert_any_call(
|
||||
expected_url_get, 'GET',
|
||||
endpoint_filter={'service_type': 'placement',
|
||||
'interface': 'public'},
|
||||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
|
||||
# Ensure that mock_call2 for delete is not called
|
||||
self.assertEqual(kss_req.call_count, 1)
|
||||
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_create_reservation_class(self, kss_req):
|
||||
rc_name = 'abc-def'
|
||||
|
@ -429,6 +476,84 @@ class TestPlacementClient(tests.TestCase):
|
|||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
self.assertEqual(mock_put_json, result)
|
||||
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get_resource_provider')
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.create_reservation_provider')
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get')
|
||||
@mock.patch('keystoneauth1.session.Session.request')
|
||||
def test_update_reservation_inventory_no_rp(
|
||||
self, kss_req, client_get, create_rp, get_rp):
|
||||
host_uuid = uuidutils.generate_uuid()
|
||||
host_name = "compute-1"
|
||||
rp_uuid = uuidutils.generate_uuid()
|
||||
rp_name = "blazar_compute-1"
|
||||
|
||||
# Build the mock that there is no existing reservation provider
|
||||
get_rp.return_value = None
|
||||
|
||||
# Build the mock of created resource provider
|
||||
mock_post_rp_json = {'uuid': rp_uuid,
|
||||
'name': rp_name,
|
||||
'generation': 0,
|
||||
'parent_provider_uuid': host_uuid}
|
||||
create_rp.return_value = mock_post_rp_json
|
||||
|
||||
# Build the mock of "current" inventory for get_inventory()
|
||||
curr_gen = 0
|
||||
mock_get_inv_json = {
|
||||
'inventories': {},
|
||||
"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 = 1
|
||||
mock_put_json = {
|
||||
'inventories': {
|
||||
'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)
|
||||
|
||||
# Ensure that the create_reservation_provider() is called.
|
||||
create_rp.assert_called_once_with(host_name)
|
||||
|
||||
expected_data = {
|
||||
'inventories': {
|
||||
'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')
|
||||
|
@ -458,3 +583,14 @@ class TestPlacementClient(tests.TestCase):
|
|||
'interface': 'public'},
|
||||
headers={'accept': 'application/json'},
|
||||
microversion=PLACEMENT_MICROVERSION, raise_exc=False)
|
||||
|
||||
@mock.patch('blazar.utils.openstack.placement.'
|
||||
'BlazarPlacementClient.get_resource_provider')
|
||||
def test_delete_reservation_inventory_no_rp(self, get_rp):
|
||||
host_name = "compute-1"
|
||||
# Build the mock that there is no existing reservation provider
|
||||
get_rp.return_value = None
|
||||
|
||||
self.assertRaises(
|
||||
exceptions.ResourceProviderNotFound,
|
||||
self.client.delete_reservation_inventory, host_name, "curr1")
|
||||
|
|
|
@ -98,14 +98,18 @@ class BlazarPlacementClient(object):
|
|||
"""Calls the placement API for a resource provider record.
|
||||
|
||||
:param rp_name: Name of the resource provider
|
||||
:return: A dict of resource provider information.
|
||||
:return: A dict of resource provider information
|
||||
or None if the resource provider doesn't exist.
|
||||
:raise: ResourceProviderRetrievalFailed on error.
|
||||
"""
|
||||
url = "/resource_providers?name=%s" % rp_name
|
||||
resp = self.get(url)
|
||||
if resp:
|
||||
json_resp = resp.json()
|
||||
return json_resp['resource_providers'][0]
|
||||
if json_resp['resource_providers']:
|
||||
return json_resp['resource_providers'][0]
|
||||
else:
|
||||
return None
|
||||
|
||||
msg = ("Failed to get resource provider %(name)s. "
|
||||
"Got %(status_code)d: %(err_text)s.")
|
||||
|
@ -192,6 +196,10 @@ class BlazarPlacementClient(object):
|
|||
"""Delete the reservation provider, the child of the given host"""
|
||||
rp_name = "blazar_" + host_name
|
||||
rp = self.get_resource_provider(rp_name)
|
||||
if rp is None:
|
||||
# If the reservation provider doesn't exist,
|
||||
# no operation will be performed.
|
||||
return
|
||||
rp_uuid = rp['uuid']
|
||||
self.delete_resource_provider(rp_uuid)
|
||||
|
||||
|
@ -319,6 +327,10 @@ class BlazarPlacementClient(object):
|
|||
# Get reservation provider uuid
|
||||
rp_name = "blazar_" + host_name
|
||||
rp = self.get_resource_provider(rp_name)
|
||||
if rp is None:
|
||||
# If the reservation provider is not created yet,
|
||||
# this function creates it.
|
||||
rp = self.create_reservation_provider(host_name)
|
||||
rp_uuid = rp['uuid']
|
||||
|
||||
# Build inventory data
|
||||
|
@ -341,10 +353,15 @@ class BlazarPlacementClient(object):
|
|||
|
||||
:param host_name: The name of the target host
|
||||
:param reserv_uuid: The reservation uuid
|
||||
:raises: ResourceProviderNotFound if the reservation
|
||||
provider is not found
|
||||
"""
|
||||
# Get reservation provider uuid
|
||||
rp_name = "blazar_" + host_name
|
||||
rp = self.get_resource_provider(rp_name)
|
||||
if rp is None:
|
||||
raise exceptions.ResourceProviderNotFound(
|
||||
resource_provider=rp_name)
|
||||
rp_uuid = rp['uuid']
|
||||
|
||||
# Convert reservation uuid to resource class name
|
||||
|
|
Loading…
Reference in New Issue