From 2202d7726bb41a2d3228297545327d5b41f35f7e Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Tue, 2 Oct 2018 16:19:06 +0200 Subject: [PATCH] Run ServerMovingTests with nested resources This patch duplicates the functional test from ServerMovingTest twice. First to run them against compute nodes that have nested RP tree. Second to actually request resources from those nested RPs. Change-Id: Iefff121640e04abdbb6a4ae546c447f168dc8af9 Blueprint: use-nested-allocation-candidates --- nova/tests/functional/test_servers.py | 96 +++++++++++++++++++++++++++ nova/virt/fake.py | 32 +++++++++ 2 files changed, 128 insertions(+) diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index 6e3a54297a56..4a66aefc4e12 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -13,8 +13,10 @@ # License for the specific language governing permissions and limitations # under the License. +import collections import datetime import time +import unittest import zlib from keystoneauth1 import adapter @@ -4839,3 +4841,97 @@ class ConsumerGenerationConflictTest( # retry the delete to make sure that allocations are removed this time self._delete_and_check_allocations(server) + + +class ServerMovingTestsWithNestedComputes(ServerMovingTests): + """Runs all the server moving tests while the computes have nested trees. + The servers still do not request resources from any child provider though. + """ + compute_driver = 'fake.MediumFakeDriverWithNestedCustomResources' + + +class ServerMovingTestsWithNestedResourceRequests( + ServerMovingTestsWithNestedComputes): + """Runs all the server moving tests while the computes have nested trees. + The servers also request resources from child providers. + """ + + def setUp(self): + super(ServerMovingTestsWithNestedResourceRequests, self).setUp() + # modify the flavors used in the ServerMoving test base class to + # require one piece of CUSTOM_MAGIC resource as well. + + for flavor in [self.flavor1, self.flavor2, self.flavor3]: + self.api.post_extra_spec( + flavor['id'], {'extra_specs': {'resources:CUSTOM_MAGIC': 1}}) + # save the extra_specs in the flavor stored in the test case as + # well + flavor['extra_specs'] = {'resources:CUSTOM_MAGIC': 1} + + def _check_allocation_during_evacuate( + self, flavor, server_uuid, source_root_rp_uuid, dest_root_rp_uuid): + # NOTE(gibi): evacuate is the only case when the same consumer has + # allocation from two different RP trees so we need a special check + # here. + allocations = self._get_allocations_by_server_uuid(server_uuid) + source_rps = self._get_all_rp_uuids_in_a_tree(source_root_rp_uuid) + dest_rps = self._get_all_rp_uuids_in_a_tree(dest_root_rp_uuid) + + self.assertEqual(set(source_rps + dest_rps), set(allocations)) + + total_source_allocation = collections.defaultdict(int) + total_dest_allocation = collections.defaultdict(int) + for rp, alloc in allocations.items(): + for rc, value in alloc['resources'].items(): + if rp in source_rps: + total_source_allocation[rc] += value + else: + total_dest_allocation[rc] += value + + self.assertEqual( + self._resources_from_flavor(flavor), total_source_allocation) + self.assertEqual( + self._resources_from_flavor(flavor), total_dest_allocation) + + @unittest.expectedFailure + def test_live_migrate_force(self): + # This test shows a bug. The replace_allocation_with_migration() call + # only returns the allocation on the compute RP and therefore the + # LiveMigrationTask._held_migration only stores and reapplies that + # during the move. Therefore the allocation on the child RP is lost + # during the force live migration + super(ServerMovingTestsWithNestedResourceRequests, + self).test_live_migrate_force() + + @unittest.expectedFailure + def test_evacuate(self): + # This test shows a bug. It seems that when the source allocation is + # dropped after the failed evacuate nova only drops the allocation from + # the root RP but not from the child RP. + super(ServerMovingTestsWithNestedResourceRequests, + self).test_evacuate() + + @unittest.expectedFailure + def test_evacuate_rebuild_on_dest_fails(self): + # This test shows a bug. It seems that when the rebuild fails on the + # destination host only the root RP allocation is deleted on the dest + # host. + super(ServerMovingTestsWithNestedResourceRequests, + self).test_evacuate_rebuild_on_dest_fails() + + @unittest.expectedFailure + def test_evacuate_claim_on_dest_fails(self): + # This test shows a bug. It seems that when the evacuation fails on the + # destination host only the root RP allocation is deleted on the dest + # host. + super(ServerMovingTestsWithNestedResourceRequests, + self).test_evacuate_claim_on_dest_fails() + + @unittest.expectedFailure + def test_evacuate_forced_host(self): + # This test shows a bug. When the conductor tries to claim the same + # resources on the dest host that was on the source host it only + # considers the root RP allocations therefore the child RP allocation + # isn't replicated on the dest host. + super(ServerMovingTestsWithNestedResourceRequests, + self).test_evacuate_forced_host() diff --git a/nova/virt/fake.py b/nova/virt/fake.py index e95bc4239972..3b32cf7d824a 100644 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -666,6 +666,38 @@ class MediumFakeDriver(FakeDriver): local_gb = 1028 +class MediumFakeDriverWithNestedCustomResources(MediumFakeDriver): + # A MediumFakeDriver variant that also reports CUSTOM_MAGIC resources on + # a nested resource provider + vcpus = 10 + memory_mb = 8192 + local_gb = 1028 + child_resources = { + 'CUSTOM_MAGIC': { + 'total': 10, + 'reserved': 0, + 'min_unit': 1, + 'max_unit': 10, + 'step_size': 1, + 'allocation_ratio': 1, + } + } + + def update_provider_tree(self, provider_tree, nodename, allocations=None): + super( + MediumFakeDriverWithNestedCustomResources, + self).update_provider_tree( + provider_tree, nodename, + allocations=allocations) + + if not provider_tree.exists(nodename + '-child'): + provider_tree.new_child(name=nodename + '-child', + parent=nodename) + + provider_tree.update_inventory(nodename + '-child', + self.child_resources) + + class FakeRescheduleDriver(FakeDriver): """FakeDriver derivative that triggers a reschedule on the first spawn attempt. This is expected to only be used in tests that have more than