From 5e452f8eb743c226af4f4998835ece8dd142a011 Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Mon, 10 Feb 2020 15:23:02 +0100 Subject: [PATCH] Reproduce bug 1862633 If port update fails during unshelve of an offloaded server then placement allocation on the target host is leaked. Changes in nova test_bug_1862633.py due to Idaed39629095f86d24a54334c699a26c218c6593 is missing from stable/rocky Change-Id: I7be32e4fc2e69f805535e0a437931516f491e5cb Related-Bug: #1862633 (cherry picked from commit c33ebdafbd633578a0a4b6f1b118c756510acea6) (cherry picked from commit bd1bfc13d7e2c418afc409871ab56da454a1334d) (cherry picked from commit f960d1751d752d559ea18604bfd1fcaf1a3283cd) --- .../regressions/test_bug_1862633.py | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 nova/tests/functional/regressions/test_bug_1862633.py diff --git a/nova/tests/functional/regressions/test_bug_1862633.py b/nova/tests/functional/regressions/test_bug_1862633.py new file mode 100644 index 000000000000..03ef62041d2c --- /dev/null +++ b/nova/tests/functional/regressions/test_bug_1862633.py @@ -0,0 +1,97 @@ +# 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. +import mock +from neutronclient.common import exceptions as neutron_exception + +from nova import test +from nova.tests import fixtures as nova_fixtures +from nova.tests.functional import integrated_helpers +from nova.tests.unit import fake_notifier +from nova.tests.unit.image import fake as fake_image + + +class UnshelveNeutronErrorTest( + test.TestCase, integrated_helpers.InstanceHelperMixin): + def setUp(self): + super(UnshelveNeutronErrorTest, self).setUp() + # Start standard fixtures. + placement = nova_fixtures.PlacementFixture() + self.useFixture(placement) + self.placement_api = placement.api + self.neutron = nova_fixtures.NeutronFixture(self) + self.useFixture(self.neutron) + fake_image.stub_out_image_service(self) + self.addCleanup(fake_image.FakeImageService_reset) + # Start nova services. + self.api = self.useFixture(nova_fixtures.OSAPIFixture( + api_version='v2.1')).admin_api + self.api.microversion = 'latest' + fake_notifier.stub_notifier(self) + self.addCleanup(fake_notifier.reset) + + self.start_service('conductor') + self.start_service('scheduler') + self.start_service('compute', host='host1') + self.start_service('compute', host='host2') + + def test_unshelve_offloaded_fails_due_to_neutron(self): + server_req = self._build_minimal_create_server_request( + self.api, name='unshelve-error-vm', + image_uuid='155d900f-4e14-4e4c-a73d-069cbf4541e6', + networks=[{'port': self.neutron.port_1['id']}], az='nova:host1') + created_server = self.api.post_server({'server': server_req}) + server = self._wait_for_state_change( + self.api, created_server, 'ACTIVE') + + # with default config shelve means immediate offload as well + req = { + 'shelve': {} + } + self.api.post_server_action(server['id'], req) + self._wait_for_server_parameter( + self.api, server, {'status': 'SHELVED_OFFLOADED'}) + allocations = self.placement_api.get( + '/allocations/%s' % server['id']).body['allocations'] + self.assertEqual(0, len(allocations)) + + # disable the original host of the instance to force a port update + # during unshelve + source_service_id = self.api.get_services( + host='host1', binary='nova-compute')[0]['id'] + self.api.put_service(source_service_id, {"status": "disabled"}) + + # Simulate that port update fails during unshelve due to neutron is + # unavailable + with mock.patch( + 'nova.tests.fixtures.NeutronFixture.' + 'update_port') as mock_update_port: + mock_update_port.side_effect = neutron_exception.ConnectionFailed( + reason='test') + req = {'unshelve': None} + self.api.post_server_action(server['id'], req) + fake_notifier.wait_for_versioned_notifications( + 'instance.unshelve.start') + self._wait_for_server_parameter( + self.api, + server, + {'status': 'SHELVED_OFFLOADED', + 'OS-EXT-STS:task_state': None}) + + # As the instance went back to offloaded state we expect no allocation + # allocations = self.placement_api.get( + # '/allocations/%s' % server['id']).body['allocations'] + # self.assertEqual(0, len(allocations)) + # + # but the allocation is leaked this is bug 1862633 + allocations = self.placement_api.get( + '/allocations/%s' % server['id']).body['allocations'] + self.assertEqual(1, len(allocations))