From 167e593ed54a670e485a4e8c1d62e08fbd065911 Mon Sep 17 00:00:00 2001 From: Balazs Gibizer Date: Tue, 24 Sep 2019 17:45:23 +0200 Subject: [PATCH] Functional reproduction for bug 1845291 Nova does not try to re-schedule a migration if the original boot was done with --availability-zone or . Related-Bug #1845291 Change-Id: Id78627c5c08090de6220249a5f44d26bf32724af --- .../regressions/test_bug_1845291.py | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 nova/tests/functional/regressions/test_bug_1845291.py diff --git a/nova/tests/functional/regressions/test_bug_1845291.py b/nova/tests/functional/regressions/test_bug_1845291.py new file mode 100644 index 000000000000..8a2a30e795b7 --- /dev/null +++ b/nova/tests/functional/regressions/test_bug_1845291.py @@ -0,0 +1,87 @@ +# 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 + +import nova +from nova import exception +from nova.tests.functional import integrated_helpers + + +class ForcedHostMissingReScheduleTestCase( + integrated_helpers.ProviderUsageBaseTestCase): + + compute_driver = 'fake.SmallFakeDriver' + + def setUp(self): + super(ForcedHostMissingReScheduleTestCase, self).setUp() + self._start_compute(host="host1") + self._start_compute(host="host2") + self._start_compute(host="host3") + + flavors = self.api.get_flavors() + self.flavor1 = flavors[0] + + def test_boot_with_az_and_host_then_migrate_re_schedules(self): + """Ensure that re-schedule is possible on migration even if the server + is originally booted with forced host. + + The _boot_and_check_allocations() will start a server forced to host1. + Then a migration is triggered. Both host2 and host3 are valid targets. + But the test mocks resize_claim to make the first dest host fail and + expects that nova will try the alternative host. + """ + + server = self._boot_and_check_allocations( + self.flavor1, 'host1') + + orig_claim = nova.compute.resource_tracker.ResourceTracker.resize_claim + claim_calls = [] + + def fake_orig_claim( + _self, context, instance, instance_type, nodename, + *args, **kwargs): + if not claim_calls: + claim_calls.append(nodename) + raise exception.ComputeResourcesUnavailable( + reason='Simulated claim failure') + else: + claim_calls.append(nodename) + return orig_claim( + _self, context, instance, instance_type, nodename, *args, + **kwargs) + + with mock.patch( + 'nova.compute.resource_tracker.ResourceTracker.resize_claim', + new=fake_orig_claim): + # Now migrate the server which is going to fail on the first + # destination but then will expect to be rescheduled. + self.api.post_server_action(server['id'], {'migrate': None}) + + # We expect that the instance re-scheduled but successfully ended + # up on the second destination host. + # FIXME(gibi): this is bug 1845291 as nova does not try to + # re-schedule. The forced host was not cleared from the + # RequestSpec before the MigrationTask populated the retry + # information for the re-scheduling. + # self._wait_for_server_parameter( + # self.api, server, + # { + # 'OS-EXT-STS:task_state': None, + # 'status': 'VERIFY_RESIZE'}) + # Instead the server goes to ERROR state + self._wait_for_server_parameter( + self.api, server, {'status': 'ERROR'}) + + # we ensure that there was a failed and then a successful claim call + # FIXME(gibi): this is bug 1845291 as there was no second claim call + # self.assertEqual(2, len(claim_calls)) + self.assertEqual(1, len(claim_calls))