From 4ba7baf451512d72b14f51cefe762642fabeda3e Mon Sep 17 00:00:00 2001 From: melanie witt Date: Fri, 2 Jun 2017 23:09:30 +0000 Subject: [PATCH] Add functional test for local delete allocations This adds a test that shows we clean up allocations for an instance that was local deleted while the compute host was down, when the compute host comes back up. There might still be a problem if the compute host is never brought back up, as allocations will still exist for the instance and show up as usage during usage queries to placement. Related-Bug: #1679750 Change-Id: Ia68a5a69783963b063264edde84006973bb77ceb --- .../regressions/test_bug_1679750.py | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 nova/tests/functional/regressions/test_bug_1679750.py diff --git a/nova/tests/functional/regressions/test_bug_1679750.py b/nova/tests/functional/regressions/test_bug_1679750.py new file mode 100644 index 000000000000..6cbaf9934f94 --- /dev/null +++ b/nova/tests/functional/regressions/test_bug_1679750.py @@ -0,0 +1,102 @@ +# 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 nova import test +from nova.tests import fixtures as nova_fixtures +from nova.tests.functional import integrated_helpers +from nova.tests.unit import cast_as_call +import nova.tests.unit.image.fake +from nova.tests.unit import policy_fixture + + +class TestLocalDeleteAllocations(test.TestCase, + integrated_helpers.InstanceHelperMixin): + def setUp(self): + super(TestLocalDeleteAllocations, self).setUp() + self.useFixture(policy_fixture.RealPolicyFixture()) + # The NeutronFixture is needed to show security groups for a server. + self.useFixture(nova_fixtures.NeutronFixture(self)) + # We need the computes reporting into placement for the filter + # scheduler to pick a host. + placement = self.useFixture(nova_fixtures.PlacementFixture()) + self.placement_api = placement.api + api_fixture = self.useFixture(nova_fixtures.OSAPIFixture( + api_version='v2.1')) + self.api = api_fixture.api + self.admin_api = api_fixture.admin_api + # We need the latest microversion to force-down the compute service + self.admin_api.microversion = 'latest' + # the image fake backend needed for image discovery + nova.tests.unit.image.fake.stub_out_image_service(self) + + self.start_service('conductor') + self.start_service('consoleauth') + + self.flags(group='scheduler', driver='chance_scheduler') + self.start_service('scheduler') + + self.compute = self.start_service('compute') + + self.useFixture(cast_as_call.CastAsCall(self)) + + self.image_id = self.api.get_images()[0]['id'] + self.flavor_id = self.api.get_flavors()[0]['id'] + + def _get_usages(self, rp_uuid): + fmt = '/resource_providers/%(uuid)s/usages' + resp = self.placement_api.get(fmt % {'uuid': rp_uuid}) + return resp.body['usages'] + + def test_local_delete_removes_allocations(self): + """Tests that allocations are removed after a local delete. + + This tests the scenario where a server is local deleted (because the + compute host is down) and we want to make sure that its allocations + have been cleaned up. + """ + # Get allocations, make sure they are 0. + resp = self.placement_api.get('/resource_providers') + rp_uuid = resp.body['resource_providers'][0]['uuid'] + usages_before = self._get_usages(rp_uuid) + for usage in usages_before.values(): + self.assertEqual(0, usage) + + # Create a server. + server = self._build_minimal_create_server_request(self.api, + 'local-delete-test', self.image_id, self.flavor_id, 'none') + server = self.admin_api.post_server({'server': server}) + server = self._wait_for_state_change(self.api, server, 'ACTIVE') + + # Assert usages are non zero now. + usages_during = self._get_usages(rp_uuid) + for usage in usages_during.values(): + self.assertNotEqual(0, usage) + + # Force-down compute to trigger local delete. + self.compute.stop() + compute_service_id = self.admin_api.get_services( + host=self.compute.host, binary='nova-compute')[0]['id'] + self.admin_api.put_service(compute_service_id, {'forced_down': True}) + + # Delete the server (will be a local delete because compute is down). + self.api.delete_server(server['id']) + + # Start the compute service again. Before it comes up, it will call the + # update_available_resource code in the ResourceTracker which is what + # "heals" the allocations for the deleted instance. + self.compute.start() + + # Get the allocations again to check against the original. + usages_after = self._get_usages(rp_uuid) + + # They should match. + self.assertEqual(usages_before, usages_after)