# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. from unittest import mock from keystoneauth1 import exceptions as ks_exc from keystoneauth1 import loading as keystone from oslo_serialization import jsonutils from oslo_utils import uuidutils from neutron_lib._i18n import _ from neutron_lib.exceptions import placement as n_exc from neutron_lib import fixture from neutron_lib.placement import client as place_client from neutron_lib.tests import _base as base RESOURCE_PROVIDER_UUID = uuidutils.generate_uuid() SECOND_RESOURCE_PROVIDER_UUID = uuidutils.generate_uuid() CONSUMER_UUID = uuidutils.generate_uuid() RESOURCE_PROVIDER_NAME = 'resource_provider_name' RESOURCE_PROVIDER = { 'uuid': RESOURCE_PROVIDER_UUID, 'name': RESOURCE_PROVIDER_NAME, } RESOURCE_PROVIDER_GENERATION = 1 RESOURCE_CLASS_NAME = 'resource_class_name' TRAIT_NAME = 'trait_name' INVENTORY = { RESOURCE_CLASS_NAME: { 'total': 42 } } class TestNoAuthClient(base.BaseTestCase): def setUp(self): super(TestNoAuthClient, self).setUp() self.noauth_client = place_client.NoAuthClient('placement/') self.body_json = jsonutils.dumps({'name': 'foo'}) self.uuid = '42' @mock.patch.object(place_client.NoAuthClient, 'request') def test_get(self, mock_request): self.noauth_client.get('resource_providers', '') mock_request.assert_called_with('placement/resource_providers', 'GET') @mock.patch.object(place_client.NoAuthClient, 'request') def test_post(self, mock_request): self.noauth_client.post('resource_providers', self.body_json, '') mock_request.assert_called_with('placement/resource_providers', 'POST', body=self.body_json) @mock.patch.object(place_client.NoAuthClient, 'request') def test_put(self, mock_request): self.noauth_client.put('resource_providers/%s' % self.uuid, self.body_json, '') mock_request.assert_called_with( 'placement/resource_providers/%s' % self.uuid, 'PUT', body=self.body_json) @mock.patch.object(place_client.NoAuthClient, 'request') def test_delete(self, mock_request): self.noauth_client.delete('resource_providers/%s' % self.uuid, '') mock_request.assert_called_with( 'placement/resource_providers/%s' % self.uuid, 'DELETE') class TestPlacementAPIClientNoAuth(base.BaseTestCase): def setUp(self): super(TestPlacementAPIClientNoAuth, self).setUp() self.config = mock.Mock() @mock.patch('neutron_lib.placement.client.NoAuthClient', autospec=True) def test__create_client_noauth(self, mock_auth_client): self.config.placement.auth_type = 'noauth' self.config.placement.auth_section = 'placement/' self.placement_api_client = place_client.PlacementAPIClient( self.config) self.placement_api_client._create_client() mock_auth_client.assert_called_once_with('placement/') @mock.patch.object(keystone, 'load_auth_from_conf_options') @mock.patch.object(keystone, 'load_session_from_conf_options') def test__create_client(self, mock_session_from_conf, mock_auth_from_conf): self.config.placement.auth_type = 'password' self.placement_api_client = place_client.PlacementAPIClient( self.config) self.placement_api_client._create_client() mock_auth_from_conf.assert_called_once_with(self.config, 'placement') mock_session_from_conf.assert_called_once() class TestPlacementAPIClient(base.BaseTestCase): def setUp(self): super(TestPlacementAPIClient, self).setUp() config = mock.Mock() config.region_name = 'region_name' self.openstack_api_version = ( place_client.PLACEMENT_API_LATEST_SUPPORTED) self.placement_api_client = place_client.PlacementAPIClient( config, self.openstack_api_version) self.placement_fixture = self.useFixture( fixture.PlacementAPIClientFixture(self.placement_api_client)) def test_create_resource_provider(self): self.placement_api_client.create_resource_provider( RESOURCE_PROVIDER) self.placement_fixture.mock_post.assert_called_once_with( '/resource_providers', RESOURCE_PROVIDER ) def test_update_resource_provider(self): self.placement_api_client.update_resource_provider( RESOURCE_PROVIDER) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%s' % RESOURCE_PROVIDER_UUID, {'name': RESOURCE_PROVIDER_NAME} ) def test_ensure_update_resource_provider(self): self.placement_api_client.ensure_resource_provider( RESOURCE_PROVIDER) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%s' % RESOURCE_PROVIDER_UUID, {'name': RESOURCE_PROVIDER_NAME} ) self.placement_fixture.mock_post.assert_not_called() def test_ensure_create_resource_provider(self): self.placement_fixture.mock_put.side_effect = \ n_exc.PlacementResourceProviderNotFound( resource_provider=RESOURCE_PROVIDER_UUID) self.placement_api_client.ensure_resource_provider( RESOURCE_PROVIDER) self.placement_fixture.mock_post.assert_called_once_with( '/resource_providers', RESOURCE_PROVIDER ) def test_delete_resource_provider(self): self.placement_api_client.delete_resource_provider( RESOURCE_PROVIDER_UUID) self.placement_fixture.mock_delete.assert_called_once_with( '/resource_providers/%s' % RESOURCE_PROVIDER_UUID) def test_get_resource_provider(self): self.placement_api_client.get_resource_provider(RESOURCE_PROVIDER_UUID) self.placement_fixture.mock_get.assert_called_once_with( '/resource_providers/%s' % RESOURCE_PROVIDER_UUID) def test_get_resource_provider_no_resource_provider(self): self.placement_fixture.mock_get.side_effect = ks_exc.NotFound() self.assertRaises(n_exc.PlacementResourceProviderNotFound, self.placement_api_client.get_resource_provider, RESOURCE_PROVIDER_UUID) def test_list_resource_providers(self): filter_1 = {'name': 'name1', 'in_tree': 'tree1_uuid'} self.placement_api_client.list_resource_providers(**filter_1) args = str(self.placement_fixture.mock_get.call_args) self.placement_fixture.mock_get.assert_called_once() self.assertIn('name=name1', args) self.assertIn('in_tree=tree1_uuid', args) filter_2 = {'member_of': ['aggregate_uuid'], 'uuid': 'uuid_1', 'resources': {'r_class1': 'value1'}} self.placement_fixture.mock_get.reset_mock() self.placement_api_client.list_resource_providers(**filter_2) args = str(self.placement_fixture.mock_get.call_args) self.placement_fixture.mock_get.assert_called_once() self.assertIn('member_of', args) self.assertIn('uuid', args) self.assertIn('resources', args) filter_1.update(filter_2) self.placement_fixture.mock_get.reset_mock() self.placement_api_client.list_resource_providers(**filter_1) args = str(self.placement_fixture.mock_get.call_args) self.placement_fixture.mock_get.assert_called_once() for key in filter_1: self.assertIn(key, args) def test_list_resource_providers_placement_api_version_too_low(self): self.placement_api_client._target_version = (1, 1) self.assertRaises( n_exc.PlacementAPIVersionIncorrect, self.placement_api_client.list_resource_providers, member_of=['aggregate_uuid']) self.assertRaises( n_exc.PlacementAPIVersionIncorrect, self.placement_api_client.list_resource_providers, in_tree='tree1_uuid') def test_update_resource_provider_inventories_generation(self): expected_body = { 'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, 'inventories': INVENTORY } self.placement_api_client.update_resource_provider_inventories( RESOURCE_PROVIDER_UUID, INVENTORY, RESOURCE_PROVIDER_GENERATION) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%s/inventories' % RESOURCE_PROVIDER_UUID, expected_body) def test_update_resource_provider_inventories_no_generation(self): expected_body = { 'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, 'inventories': INVENTORY } with mock.patch.object( self.placement_api_client, 'get_resource_provider', return_value={'generation': RESOURCE_PROVIDER_GENERATION}): self.placement_api_client.update_resource_provider_inventories( RESOURCE_PROVIDER_UUID, INVENTORY) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%s/inventories' % RESOURCE_PROVIDER_UUID, expected_body) def test_update_resource_provider_inventories_no_rp(self): self.placement_fixture.mock_put.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceProviderNotFound, self.placement_api_client.update_resource_provider_inventories, RESOURCE_PROVIDER_UUID, INVENTORY, RESOURCE_PROVIDER_GENERATION) def test_delete_resource_provider_inventory(self): self.placement_api_client.delete_resource_provider_inventory( RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME ) self.placement_fixture.mock_delete.assert_called_once_with( '/resource_providers/%(rp_uuid)s/inventories/%(rc_name)s' % {'rp_uuid': RESOURCE_PROVIDER_UUID, 'rc_name': RESOURCE_CLASS_NAME} ) def test_delete_resource_provider_inventory_no_rp(self): self.placement_fixture.mock_delete.side_effect = ks_exc.NotFound( details='No resource provider with uuid' ) self.assertRaises( n_exc.PlacementResourceProviderNotFound, self.placement_api_client.delete_resource_provider_inventory, RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME ) def test_get_inventory(self): self.placement_api_client.get_inventory(RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME) self.placement_fixture.mock_get.assert_called_once_with( '/resource_providers/%(rp_uuid)s/inventories/%(rc_name)s' % {'rp_uuid': RESOURCE_PROVIDER_UUID, 'rc_name': RESOURCE_CLASS_NAME}) def test_get_inventory_no_resource_provider(self): _exception = ks_exc.NotFound() _exception.details = "No resource provider with uuid" self.placement_fixture.mock_get.side_effect = _exception self.assertRaises(n_exc.PlacementResourceProviderNotFound, self.placement_api_client.get_inventory, RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME) def test_get_inventory_no_inventory(self): _exception = ks_exc.NotFound() _exception.details = _("No inventory of class") self.placement_fixture.mock_get.side_effect = _exception self.assertRaises(n_exc.PlacementInventoryNotFound, self.placement_api_client.get_inventory, RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME) def test_get_inventory_not_found(self): _exception = ks_exc.NotFound() _exception.details = "Any other exception explanation" _exception.response = mock.Mock(text="Some error response body") self.placement_fixture.mock_get.side_effect = _exception self.assertRaises(n_exc.PlacementClientError, self.placement_api_client.get_inventory, RESOURCE_PROVIDER_UUID, RESOURCE_CLASS_NAME) def test_update_resource_provider_inventory_generation(self): expected_body = { 'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, } expected_body.update(INVENTORY) self.placement_api_client.update_resource_provider_inventory( RESOURCE_PROVIDER_UUID, INVENTORY, RESOURCE_CLASS_NAME, resource_provider_generation=1) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%(rp_uuid)s/inventories/%(rc_name)s' % {'rp_uuid': RESOURCE_PROVIDER_UUID, 'rc_name': RESOURCE_CLASS_NAME}, expected_body) def test_update_resource_provider_inventory_no_generation(self): expected_body = { 'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, } expected_body.update(INVENTORY) with mock.patch.object( self.placement_api_client, 'get_resource_provider', return_value={'generation': RESOURCE_PROVIDER_GENERATION}): self.placement_api_client.update_resource_provider_inventory( RESOURCE_PROVIDER_UUID, INVENTORY, RESOURCE_CLASS_NAME) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%(rp_uuid)s/inventories/%(rc_name)s' % {'rp_uuid': RESOURCE_PROVIDER_UUID, 'rc_name': RESOURCE_CLASS_NAME}, expected_body) def test_update_resource_provider_inventory_not_found(self): # Test the resource provider not found case self.placement_fixture.mock_put.side_effect = ks_exc.NotFound( details="No resource provider with uuid") self.assertRaises( n_exc.PlacementResourceNotFound, self.placement_api_client.update_resource_provider_inventory, RESOURCE_PROVIDER_UUID, INVENTORY, RESOURCE_CLASS_NAME, RESOURCE_PROVIDER_GENERATION) def test_associate_aggregates(self): self.placement_api_client.associate_aggregates(RESOURCE_PROVIDER_UUID, mock.ANY) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%s/aggregates' % RESOURCE_PROVIDER_UUID, mock.ANY) def test_list_aggregates(self): self.placement_api_client.list_aggregates(RESOURCE_PROVIDER_UUID) self.placement_fixture.mock_get.assert_called_once_with( '/resource_providers/%s/aggregates' % RESOURCE_PROVIDER_UUID) def test_list_aggregates_no_resource_provider(self): self.placement_fixture.mock_get.side_effect = ks_exc.NotFound() self.assertRaises(n_exc.PlacementAggregateNotFound, self.placement_api_client.list_aggregates, RESOURCE_PROVIDER_UUID) def test_list_traits(self): self.placement_api_client.list_traits() self.placement_fixture.mock_get.assert_called_once_with( '/traits') def test_get_trait(self): self.placement_api_client.get_trait(TRAIT_NAME) self.placement_fixture.mock_get.assert_called_once_with( '/traits/%s' % TRAIT_NAME) def test_get_trait_no_trait(self): self.placement_fixture.mock_get.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementTraitNotFound, self.placement_api_client.get_trait, TRAIT_NAME) def test_create_trait(self): self.placement_api_client.update_trait(TRAIT_NAME) self.placement_fixture.mock_put.assert_called_once_with( '/traits/%s' % TRAIT_NAME, None) def test_update_resource_provider_traits_generation(self): traits = [TRAIT_NAME] self.placement_api_client.update_resource_provider_traits( RESOURCE_PROVIDER_UUID, traits, resource_provider_generation=RESOURCE_PROVIDER_GENERATION) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%(rp_uuid)s/traits' % {'rp_uuid': RESOURCE_PROVIDER_UUID}, {'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, 'traits': traits}) def test_update_resource_provider_traits_no_generation(self): traits = [TRAIT_NAME] with mock.patch.object( self.placement_api_client, 'get_resource_provider', return_value={'generation': RESOURCE_PROVIDER_GENERATION}): self.placement_api_client.update_resource_provider_traits( RESOURCE_PROVIDER_UUID, traits) self.placement_fixture.mock_put.assert_called_once_with( '/resource_providers/%(rp_uuid)s/traits' % {'rp_uuid': RESOURCE_PROVIDER_UUID}, {'resource_provider_generation': RESOURCE_PROVIDER_GENERATION, 'traits': traits}) def test_update_resource_provider_traits_no_rp(self): traits = [TRAIT_NAME] self.placement_fixture.mock_put.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceProviderNotFound, self.placement_api_client.update_resource_provider_traits, RESOURCE_PROVIDER_UUID, traits, resource_provider_generation=0) def test_update_resource_provider_traits_trait_not_found(self): traits = [TRAIT_NAME] self.placement_fixture.mock_put.side_effect = ks_exc.BadRequest() self.assertRaises( n_exc.PlacementTraitNotFound, self.placement_api_client.update_resource_provider_traits, RESOURCE_PROVIDER_UUID, traits, resource_provider_generation=0) def test_list_resource_provider_traits(self): self.placement_api_client.list_resource_provider_traits( RESOURCE_PROVIDER_UUID) self.placement_fixture.mock_get.assert_called_once_with( '/resource_providers/%s/traits' % RESOURCE_PROVIDER_UUID) def test_list_resource_provider_traits_no_rp(self): self.placement_fixture.mock_get.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceProviderNotFound, self.placement_api_client.list_resource_provider_traits, RESOURCE_PROVIDER_UUID) def test_delete_trait(self): self.placement_api_client.delete_trait(TRAIT_NAME) self.placement_fixture.mock_delete.assert_called_once_with( '/traits/%s' % TRAIT_NAME) def test_delete_trait_no_trait(self): self.placement_fixture.mock_delete.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementTraitNotFound, self.placement_api_client.delete_trait, TRAIT_NAME) def test_delete_resource_provider_traits(self): self.placement_api_client.delete_resource_provider_traits( RESOURCE_PROVIDER_UUID) self.placement_fixture.mock_delete.assert_called_once_with( '/resource_providers/%s/traits' % RESOURCE_PROVIDER_UUID) def test_delete_resource_provider_traits_no_rp(self): self.placement_fixture.mock_delete.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceProviderNotFound, self.placement_api_client.delete_resource_provider_traits, RESOURCE_PROVIDER_UUID) def test_list_resource_classes(self): self.placement_api_client.list_resource_classes() self.placement_fixture.mock_get.assert_called_once_with( '/resource_classes' ) def test_get_resource_class(self): self.placement_api_client.get_resource_class(RESOURCE_CLASS_NAME) self.placement_fixture.mock_get.assert_called_once_with( '/resource_classes/%s' % RESOURCE_CLASS_NAME ) def test_get_resource_class_no_resource_class(self): self.placement_fixture.mock_get.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceClassNotFound, self.placement_api_client.get_resource_class, RESOURCE_CLASS_NAME ) def test_create_resource_class(self): self.placement_api_client.create_resource_class(RESOURCE_CLASS_NAME) self.placement_fixture.mock_post.assert_called_once_with( '/resource_classes', {'name': RESOURCE_CLASS_NAME}, ) def test_update_resource_class(self): self.placement_api_client.update_resource_class(RESOURCE_CLASS_NAME) self.placement_fixture.mock_put.assert_called_once_with( '/resource_classes/%s' % RESOURCE_CLASS_NAME, None) def test_delete_resource_class(self): self.placement_api_client.delete_resource_class(RESOURCE_CLASS_NAME) self.placement_fixture.mock_delete.assert_called_once_with( '/resource_classes/%s' % RESOURCE_CLASS_NAME ) def test_delete_resource_class_no_resource_class(self): self.placement_fixture.mock_delete.side_effect = ks_exc.NotFound() self.assertRaises( n_exc.PlacementResourceClassNotFound, self.placement_api_client.delete_resource_class, RESOURCE_CLASS_NAME ) def test_update_rp_traits_caller_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = ks_exc.Conflict( response=mock_resp) self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_traits, resource_provider_uuid='resource provider uuid', traits=['trait a', 'trait b'], resource_provider_generation=3, ) self.placement_fixture.mock_put.assert_called_once() def test_update_rp_traits_callee_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.placement_api_client.update_resource_provider_traits( resource_provider_uuid='resource provider uuid', traits=['trait a', 'trait b'], resource_provider_generation=None, ) self.assertEqual(2, self.placement_fixture.mock_put.call_count) def test_update_rp_traits_reached_max_tries(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = 10 * [ ks_exc.Conflict(response=mock_resp), ] self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_traits, resource_provider_uuid='resource provider uuid', traits=['trait a', 'trait b'], resource_provider_generation=None, ) self.assertEqual(10, self.placement_fixture.mock_put.call_count) def test_update_rp_traits_raise_other_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'some_other_code'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.assertRaises( n_exc.PlacementClientError, self.placement_api_client.update_resource_provider_traits, resource_provider_uuid='resource provider uuid', traits=[], resource_provider_generation=None, ) self.assertEqual(1, self.placement_fixture.mock_put.call_count) def test_update_rp_inventory_caller_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = ks_exc.Conflict( response=mock_resp) self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_inventory, resource_provider_uuid='resource provider uuid', inventory={}, resource_class='a resource class', resource_provider_generation=3, ) self.placement_fixture.mock_put.assert_called_once() def test_update_rp_inventory_callee_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.placement_api_client.update_resource_provider_inventory( resource_provider_uuid='resource provider uuid', inventory={}, resource_class='a resource class', resource_provider_generation=None, ) self.assertEqual(2, self.placement_fixture.mock_put.call_count) def test_update_rp_inventory_reached_max_tries(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = 10 * [ ks_exc.Conflict(response=mock_resp), ] self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_inventory, resource_provider_uuid='resource provider uuid', inventory={}, resource_class='a resource class', resource_provider_generation=None, ) self.assertEqual(10, self.placement_fixture.mock_put.call_count) def test_update_rp_inventory_raise_other_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'some_other_code'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.assertRaises( n_exc.PlacementClientError, self.placement_api_client.update_resource_provider_inventory, resource_provider_uuid='resource provider uuid', inventory={}, resource_class='a resource class', resource_provider_generation=None, ) self.assertEqual(1, self.placement_fixture.mock_put.call_count) def test_update_rp_inventories_caller_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = ks_exc.Conflict( response=mock_resp) self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_inventories, resource_provider_uuid='resource provider uuid', inventories={}, resource_provider_generation=3, ) self.placement_fixture.mock_put.assert_called_once() def test_update_rp_inventories_callee_handles_generation_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.placement_api_client.update_resource_provider_inventories( resource_provider_uuid='resource provider uuid', inventories={}, resource_provider_generation=None, ) self.assertEqual(2, self.placement_fixture.mock_put.call_count) def test_update_rp_inventories_reached_max_tries(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = 10 * [ ks_exc.Conflict(response=mock_resp), ] self.assertRaises( n_exc.PlacementResourceProviderGenerationConflict, self.placement_api_client.update_resource_provider_inventories, resource_provider_uuid='resource provider uuid', inventories={}, resource_provider_generation=None, ) self.assertEqual(10, self.placement_fixture.mock_put.call_count) def test_update_rp_inventories_raise_other_conflict(self): mock_resp = mock.Mock() mock_resp.text = '' mock_resp.json = lambda: { 'errors': [{'code': 'some_other_code'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_resp), mock.Mock(), ] self.assertRaises( n_exc.PlacementClientError, self.placement_api_client.update_resource_provider_inventories, resource_provider_uuid='resource provider uuid', inventories={}, resource_provider_generation=None, ) self.assertEqual(1, self.placement_fixture.mock_put.call_count) def test_list_allocations(self): self.placement_api_client.list_allocations(CONSUMER_UUID) self.placement_fixture.mock_get.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID) def test_update_allocation(self): mock_rsp = mock.Mock() mock_rsp.json = lambda: { 'allocations': { RESOURCE_PROVIDER_UUID: {'resources': {'a': 10}} } } self.placement_fixture.mock_get.side_effect = [mock_rsp] self.placement_api_client.update_allocation( CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'a': 20}} }}) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'a': 20}} }} ) def _get_allocation_response(self, allocation): mock_rsp_get = mock.Mock() mock_rsp_get.json = lambda: { 'allocations': allocation } return mock_rsp_get def test_update_qos_allocation(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'resources': {'a': 3, 'b': 2}}}) self.placement_fixture.mock_get.side_effect = [mock_rsp_get] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': 2, 'b': 2}}, ) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'a': 5, 'b': 4}} }} ) def test_update_qos_allocation_removed(self): mock_rsp = mock.Mock() mock_rsp.json = lambda: {'allocations': {}} self.placement_fixture.mock_get.side_effect = [mock_rsp] self.assertRaises( n_exc.PlacementAllocationRemoved, self.placement_api_client.update_qos_allocation, consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': 1, 'b': 1}}, ) def test_update_qos_allocation_rp_not_exists(self): mock_rsp = mock.Mock() mock_rsp.json = lambda: {'allocations': {'other:rp:uuid': {'c': 3}}} self.placement_fixture.mock_get.side_effect = [mock_rsp] self.assertRaises( n_exc.PlacementAllocationRpNotExists, self.placement_api_client.update_qos_allocation, consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': 1, 'b': 1}}, ) def test_update_qos_allocation_max_retries(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'c': 3}}) self.placement_fixture.mock_get.side_effect = 10 * [mock_rsp_get] mock_rsp_put = mock.Mock() mock_rsp_put.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = ks_exc.Conflict( response=mock_rsp_put) self.assertRaises( n_exc.PlacementAllocationGenerationConflict, self.placement_api_client.update_qos_allocation, consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {}}, ) self.assertEqual(10, self.placement_fixture.mock_put.call_count) def test_update_qos_minbwallocation_generation_conflict_solved(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'c': 3}}) self.placement_fixture.mock_get.side_effect = 2 * [mock_rsp_get] mock_rsp_put = mock.Mock() mock_rsp_put.json = lambda: { 'errors': [{'code': 'placement.concurrent_update'}]} self.placement_fixture.mock_put.side_effect = [ ks_exc.Conflict(response=mock_rsp_put), mock.Mock() ] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {}}, ) self.assertEqual(2, self.placement_fixture.mock_put.call_count) def test_update_qos_allocation_other_conflict(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'c': 3}}) self.placement_fixture.mock_get.side_effect = 10 * [mock_rsp_get] mock_rsp_put = mock.Mock() mock_rsp_put.text = '' mock_rsp_put.json = lambda: { 'errors': [{'code': 'some other error code'}]} self.placement_fixture.mock_put.side_effect = ks_exc.Conflict( response=mock_rsp_put) self.assertRaises( ks_exc.Conflict, self.placement_api_client.update_qos_allocation, consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {}}, ) self.placement_fixture.mock_put.assert_called_once() def test_update_qos_allocation_to_zero(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'resources': {'a': 3, 'b': 2}}}) self.placement_fixture.mock_get.side_effect = [mock_rsp_get] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': -3, 'b': -2}}, ) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': {}}) def test_update_qos_allocation_one_class_to_zero(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'resources': {'a': 3, 'b': 2}}}) self.placement_fixture.mock_get.side_effect = [mock_rsp_get] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': -3, 'b': 1}}, ) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'b': 3}} }}) def test_update_qos_allocation_one_class_to_zero_and_new_class(self): mock_rsp_get = self._get_allocation_response( {RESOURCE_PROVIDER_UUID: {'resources': {'a': 3}}}) self.placement_fixture.mock_get.side_effect = [mock_rsp_get] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={RESOURCE_PROVIDER_UUID: {'a': -3, 'b': 1}}, ) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'b': 1}} }}) def test_update_qos_allocation_multiple_rps(self): mock_rsp_get = self._get_allocation_response({ RESOURCE_PROVIDER_UUID: {'resources': {'a': 3, 'b': 2}}, SECOND_RESOURCE_PROVIDER_UUID: {'resources': {'c': 1, 'd': 5}}, }) self.placement_fixture.mock_get.side_effect = [mock_rsp_get] self.placement_api_client.update_qos_allocation( consumer_uuid=CONSUMER_UUID, alloc_diff={ RESOURCE_PROVIDER_UUID: {'a': -3, 'b': 2}, SECOND_RESOURCE_PROVIDER_UUID: {'e': 3, 'd': -5}, }, ) self.placement_fixture.mock_put.assert_called_once_with( '/allocations/%s' % CONSUMER_UUID, {'allocations': { RESOURCE_PROVIDER_UUID: { 'resources': {'b': 4}}, SECOND_RESOURCE_PROVIDER_UUID: { 'resources': {'c': 1, 'e': 3}}, }} )