From a7bd9688d533aaa622d6049a99d9339d1fbfa88f Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Fri, 5 Apr 2019 15:16:41 -0400 Subject: [PATCH] Add functional recreate test for bug 1823370 When evacuating a server in a multi-cell environment we should be restricting the scheduling request during evacuate to the cell in which the instance already exists since we don't support cross-cell evacuate. This adds a functional test to recreate the bug to show that the scheduler is not restricted to the instance's current cell when evacuating. Change-Id: I56e20c84f25cc4961dc8d637c222b6f213c4d5f9 Related-Bug: #1823370 --- .../regressions/test_bug_1823370.py | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 nova/tests/functional/regressions/test_bug_1823370.py diff --git a/nova/tests/functional/regressions/test_bug_1823370.py b/nova/tests/functional/regressions/test_bug_1823370.py new file mode 100644 index 0000000000..08c8b0513a --- /dev/null +++ b/nova/tests/functional/regressions/test_bug_1823370.py @@ -0,0 +1,90 @@ +# 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.scheduler import weights +from nova.tests.functional import integrated_helpers + +# Prefer host1 over host2 over host3 +WEIGHT_MAP = {'host1': 100, 'host2': 50, 'host3': 25} + + +class HostNameWeigher(weights.BaseHostWeigher): + def _weigh_object(self, host_state, weight_properties): + return WEIGHT_MAP.get(host_state.host, 0) + + +class MultiCellEvacuateTestCase(integrated_helpers._IntegratedTestBase, + integrated_helpers.InstanceHelperMixin): + """Recreate test for bug 1823370 which was introduced in Pike. + + When evacuating a server, the request to the scheduler should be restricted + to the cell in which the instance is already running since cross-cell + evacuate is not supported, at least not yet. This test creates two cells + with two compute hosts in one cell and another compute host in the other + cell. A server is created in the cell with two hosts and then evacuated + which should land it on the other host in that cell, not the other cell + with only one host. The scheduling behavior is controlled via the custom + HostNameWeigher. + """ + # Set variables used in the parent class. + NUMBER_OF_CELLS = 2 + REQUIRES_LOCKING = False + ADMIN_API = True + USE_NEUTRON = True + _image_ref_parameter = 'imageRef' + _flavor_ref_parameter = 'flavorRef' + api_major_version = 'v2.1' + microversion = '2.11' # Need at least 2.11 for the force-down API + + def setUp(self): + # Register our custom weigher for predictable scheduling results. + self.flags(weight_classes=[__name__ + '.HostNameWeigher'], + group='filter_scheduler') + super(MultiCellEvacuateTestCase, self).setUp() + + def _setup_compute_service(self): + """Start three compute services, two in cell1 and one in cell2. + + host1: cell1 (highest weight) + host2: cell2 (medium weight) + host3: cell1 (lowest weight) + """ + host_to_cell = {'host1': 'cell1', 'host2': 'cell2', 'host3': 'cell1'} + for host, cell in host_to_cell.items(): + svc = self.start_service('compute', host=host, cell=cell) + # Set an attribute so we can access this service later. + setattr(self, host, svc) + + def test_evacuate_multi_cell(self): + # Create a server which should land on host1 since it has the highest + # weight. + server = self._build_server(self.api.get_flavors()[0]['id']) + server = self.api.post_server({'server': server}) + server = self._wait_for_state_change(self.api, server, 'ACTIVE') + self.assertEqual('host1', server['OS-EXT-SRV-ATTR:host']) + + # Disable the host on which the server is now running. + self.host1.stop() + self.api.force_down_service('host1', 'nova-compute', forced_down=True) + + # Now evacuate the server which should send it to host3 since it is + # in the same cell as host1, even though host2 in cell2 is weighed + # higher than host3. + req = {'evacuate': {'onSharedStorage': False}} + self.api.post_server_action(server['id'], req) + self._wait_for_migration_status(server, ['done']) + server = self._wait_for_state_change(self.api, server, 'ACTIVE') + # FIXME(mriedem): This is bug 1823370 where conductor does not restrict + # the RequestSpec to the origin cell before calling the scheduler to + # pick a new host so the host (host2) in the other cell (cell2) is + # incorrectly picked. + self.assertEqual('host2', server['OS-EXT-SRV-ATTR:host'])