Merge "Add functional recreate test for regression bug 1825537" into stable/rocky
This commit is contained in:
commit
29861a3611
|
@ -0,0 +1,82 @@
|
|||
# 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.tests.functional import integrated_helpers
|
||||
|
||||
|
||||
class FinishResizeErrorAllocationCleanupTestCase(
|
||||
integrated_helpers.ProviderUsageBaseTestCase):
|
||||
"""Test for bug 1825537 introduced in Rocky and backported down to Pike.
|
||||
|
||||
Tests a scenario where finish_resize fails on the dest compute during a
|
||||
resize and ensures resource provider allocations are properly cleaned up
|
||||
in placement.
|
||||
"""
|
||||
|
||||
compute_driver = 'fake.FakeFinishMigrationFailDriver'
|
||||
|
||||
def setUp(self):
|
||||
super(FinishResizeErrorAllocationCleanupTestCase, self).setUp()
|
||||
# Get the flavors we're going to use.
|
||||
flavors = self.api.get_flavors()
|
||||
self.flavor1 = flavors[0]
|
||||
self.flavor2 = flavors[1]
|
||||
|
||||
def _resize_and_assert_error(self, server, dest_host):
|
||||
# Now resize the server and wait for it to go to ERROR status because
|
||||
# the finish_migration virt driver method in host2 should fail.
|
||||
req = {'resize': {'flavorRef': self.flavor2['id']}}
|
||||
self.api.post_server_action(server['id'], req)
|
||||
# The instance is set to ERROR status before the fault is recorded so
|
||||
# to avoid a race we need to wait for the task_state to change
|
||||
# to None which happens after the fault is recorded.
|
||||
server = self._wait_for_server_parameter(
|
||||
self.admin_api, server,
|
||||
{'status': 'ERROR', 'OS-EXT-STS:task_state': None})
|
||||
# The server should be pointing at $dest_host because resize_instance
|
||||
# will have updated the host/node value on the instance before casting
|
||||
# to the finish_resize method on the dest compute.
|
||||
self.assertEqual(dest_host, server['OS-EXT-SRV-ATTR:host'])
|
||||
# In this case the FakeFinishMigrationFailDriver.finish_migration
|
||||
# method raises VirtualInterfaceCreateException.
|
||||
self.assertIn('Virtual Interface creation failed',
|
||||
server['fault']['message'])
|
||||
|
||||
def test_finish_resize_fails_allocation_cleanup(self):
|
||||
# Start two computes so we can resize across hosts.
|
||||
self._start_compute('host1')
|
||||
self._start_compute('host2')
|
||||
|
||||
# Create a server on host1.
|
||||
server = self._boot_and_check_allocations(self.flavor1, 'host1')
|
||||
|
||||
# Resize to host2 which should fail.
|
||||
self._resize_and_assert_error(server, 'host2')
|
||||
|
||||
# Check the resource provider allocations. Since the server is pointed
|
||||
# at the dest host in the DB now, the dest node resource provider
|
||||
# allocations should still exist with the new flavor.
|
||||
source_rp_uuid = self._get_provider_uuid_by_host('host1')
|
||||
dest_rp_uuid = self._get_provider_uuid_by_host('host2')
|
||||
# FIXME(mriedem): This is bug 1825537 where the allocations are
|
||||
# reverted when finish_resize fails so the dest node resource provider
|
||||
# does not have any allocations and the instance allocations are for
|
||||
# the old flavor on the source node resource provider even though the
|
||||
# instance is not running on the source host nor pointed at the source
|
||||
# host in the DB.
|
||||
# self.assertFlavorMatchesAllocation(
|
||||
# self.flavor2, server['id'], dest_rp_uuid)
|
||||
dest_rp_usages = self._get_provider_usages(dest_rp_uuid)
|
||||
no_usage = {'VCPU': 0, 'MEMORY_MB': 0, 'DISK_GB': 0}
|
||||
self.assertEqual(no_usage, dest_rp_usages)
|
||||
source_usages = self._get_provider_usages(source_rp_uuid)
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, source_usages)
|
|
@ -3088,6 +3088,7 @@ class ServerMovingTests(integrated_helpers.ProviderUsageBaseTestCase):
|
|||
# Ensure the allocation records still exist on the host.
|
||||
source_rp_uuid = self._get_provider_uuid_by_host(hostname)
|
||||
source_usages = self._get_provider_usages(source_rp_uuid)
|
||||
# FIXME(mriedem): This is wrong for the _finish_resize case.
|
||||
# The new_flavor should have been subtracted from the doubled
|
||||
# allocation which just leaves us with the original flavor.
|
||||
self.assertFlavorMatchesAllocation(self.flavor1, source_usages)
|
||||
|
|
|
@ -674,6 +674,13 @@ class MediumFakeDriver(FakeDriver):
|
|||
local_gb = 1028
|
||||
|
||||
|
||||
class FakeFinishMigrationFailDriver(FakeDriver):
|
||||
"""FakeDriver variant that will raise an exception from finish_migration"""
|
||||
|
||||
def finish_migration(self, *args, **kwargs):
|
||||
raise exception.VirtualInterfaceCreateException()
|
||||
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue