From b7e72674adac175e27029175370c0cf37fc63ded Mon Sep 17 00:00:00 2001 From: Tetsuro Nakamura Date: Mon, 24 Dec 2018 11:27:19 +0000 Subject: [PATCH] Consider the number of instances for reservation inventory When an instance reservation starts, Blazar calls placement to update reservation resource providers to have the number of reserved instances in each reservation inventory. However, it has been fixed to one because we have supported only anti-affinity policy. This patch changes it to count the number of allocations and register the appropriate number in each reservation inventory. Change-Id: Icc15efaeb029d330ef0b77aeed4a7a12cb18315e Blueprint: no-affinity-instance-reservation --- blazar/plugins/instances/instance_plugin.py | 24 +++++++++++++++---- .../plugins/instances/test_instance_plugin.py | 22 ++++++++++++----- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/blazar/plugins/instances/instance_plugin.py b/blazar/plugins/instances/instance_plugin.py index 93e730b2..746404f8 100644 --- a/blazar/plugins/instances/instance_plugin.py +++ b/blazar/plugins/instances/instance_plugin.py @@ -354,9 +354,17 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper): if reservation['status'] == 'active': pool = nova.ReservationPool() + + # Dict of number of instances to reserve on a host keyed by the + # host id + allocation_map = collections.defaultdict(lambda: 0) for allocation in db_api.host_allocation_get_all_by_values( reservation_id=reservation['id']): - host = db_api.host_get(allocation['compute_host_id']) + host_id = allocation['compute_host_id'] + allocation_map[host_id] += 1 + + for host_id, num in allocation_map.items(): + host = db_api.host_get(host_id) try: pool.add_computehost( reservation['aggregate_id'], @@ -368,7 +376,7 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper): % (host, reservation['aggregate_id'])) raise mgr_exceptions.NovaClientError(err_msg) self.placement_client.update_reservation_inventory( - host['hypervisor_hostname'], reservation['id'], 1) + host['hypervisor_hostname'], reservation['id'], num) else: try: self.nova.nova.flavors.delete(reservation['id']) @@ -529,13 +537,21 @@ class VirtualInstancePlugin(base.BasePlugin, nova.NovaClientWrapper): raise mgr_exceptions.EventError() pool = nova.ReservationPool() + + # Dict of number of instances to reserve on a host keyed by the + # host id + allocation_map = collections.defaultdict(lambda: 0) for allocation in db_api.host_allocation_get_all_by_values( reservation_id=reservation_id): - host = db_api.host_get(allocation['compute_host_id']) + host_id = allocation['compute_host_id'] + allocation_map[host_id] += 1 + + for host_id, num in allocation_map.items(): + host = db_api.host_get(host_id) pool.add_computehost(instance_reservation['aggregate_id'], host['service_name'], stay_in=True) self.placement_client.update_reservation_inventory( - host['hypervisor_hostname'], reservation_id, 1) + host['hypervisor_hostname'], reservation_id, num) def on_end(self, resource_id): instance_reservation = db_api.instance_reservation_get(resource_id) diff --git a/blazar/tests/plugins/instances/test_instance_plugin.py b/blazar/tests/plugins/instances/test_instance_plugin.py index 8352ce90..9be7409f 100644 --- a/blazar/tests/plugins/instances/test_instance_plugin.py +++ b/blazar/tests/plugins/instances/test_instance_plugin.py @@ -893,7 +893,7 @@ class TestVirtualInstancePlugin(tests.TestCase): 'host_allocation_get_all_by_values') mock_alloc_get.return_value = [ {'compute_host_id': 'host-id1'}, {'compute_host_id': 'host-id2'}, - {'compute_host_id': 'host-id3'}] + {'compute_host_id': 'host-id3'}, {'compute_host_id': 'host-id3'}] mock_host_get = self.patch(db_api, 'host_get') mock_host_get.side_effect = fake_host_get @@ -904,8 +904,13 @@ class TestVirtualInstancePlugin(tests.TestCase): for i in range(3): fake_pool.add_computehost.assert_any_call( 'aggregate-1', 'host' + str(i + 1), stay_in=True) - mock_update_reservation_inventory.assert_any_call( - 'host' + str(i + 1), 'reservation-id1', 1) + + mock_update_reservation_inventory.assert_any_call( + 'host1', 'reservation-id1', 1) + mock_update_reservation_inventory.assert_any_call( + 'host2', 'reservation-id1', 1) + mock_update_reservation_inventory.assert_any_call( + 'host3', 'reservation-id1', 2) def test_update_reservation(self): plugin = instance_plugin.VirtualInstancePlugin() @@ -1073,7 +1078,7 @@ class TestVirtualInstancePlugin(tests.TestCase): 'host_allocation_get_all_by_values') mock_alloc_get.return_value = [ {'compute_host_id': 'host-id1'}, {'compute_host_id': 'host-id2'}, - {'compute_host_id': 'host-id3'}] + {'compute_host_id': 'host-id3'}, {'compute_host_id': 'host-id3'}] mock_host_get = self.patch(db_api, 'host_get') mock_host_get.side_effect = fake_host_get @@ -1085,8 +1090,13 @@ class TestVirtualInstancePlugin(tests.TestCase): for i in range(3): fake_pool.add_computehost.assert_any_call( 'aggregate-id1', 'host' + str(i + 1), stay_in=True) - mock_update_reservation_inventory.assert_any_call( - 'host' + str(i + 1), 'reservation-id1', 1) + + mock_update_reservation_inventory.assert_any_call( + 'host1', 'reservation-id1', 1) + mock_update_reservation_inventory.assert_any_call( + 'host2', 'reservation-id1', 1) + mock_update_reservation_inventory.assert_any_call( + 'host3', 'reservation-id1', 2) def test_on_end(self): self.set_context(context.BlazarContext(project_id='fake-project-id'))