diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index 8f522a4e1d7a..414ef7cb68a2 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -1780,6 +1780,48 @@ class ServerMovingTests(ProviderUsageBaseTestCase): self.compute2.manager.update_available_resource(ctx) LOG.info('Finished with periodics') + def _migrate_and_check_allocations(self, server, flavor, source_rp_uuid, + dest_rp_uuid): + request = { + 'migrate': None + } + self._move_and_check_allocations( + server, request=request, old_flavor=flavor, new_flavor=flavor, + source_rp_uuid=source_rp_uuid, dest_rp_uuid=dest_rp_uuid) + + def _move_and_check_allocations(self, server, request, old_flavor, + new_flavor, source_rp_uuid, dest_rp_uuid): + self.api.post_server_action(server['id'], request) + self._wait_for_state_change(self.api, server, 'VERIFY_RESIZE') + + def _check_allocation(): + source_usages = self._get_provider_usages(source_rp_uuid) + self.assertFlavorMatchesAllocation(old_flavor, source_usages) + dest_usages = self._get_provider_usages(dest_rp_uuid) + self.assertFlavorMatchesAllocation(new_flavor, dest_usages) + + # The instance should own the new_flavor allocation against the + # destination host created by the scheduler + allocations = self._get_allocations_by_server_uuid(server['id']) + self.assertEqual(1, len(allocations)) + dest_alloc = allocations[dest_rp_uuid]['resources'] + self.assertFlavorMatchesAllocation(new_flavor, dest_alloc) + + # The migration should own the old_flavor allocation against the + # source host created by conductor + migration_uuid = self.get_migration_uuid_for_instance(server['id']) + allocations = self._get_allocations_by_server_uuid(migration_uuid) + source_alloc = allocations[source_rp_uuid]['resources'] + self.assertFlavorMatchesAllocation(old_flavor, source_alloc) + + # OK, so the move operation has run, but we have not yet confirmed or + # reverted the move operation. Before we run periodics, make sure + # that we have allocations/usages on BOTH the source and the + # destination hosts. + _check_allocation() + self._run_periodics() + _check_allocation() + def test_resize_revert(self): self._test_resize_revert(dest_hostname='host1') @@ -1794,63 +1836,16 @@ class ServerMovingTests(ProviderUsageBaseTestCase): def _resize_and_check_allocations(self, server, old_flavor, new_flavor, source_rp_uuid, dest_rp_uuid): - # Resize the server and check usages in VERIFY_RESIZE state self.flags(allow_resize_to_same_host=False) resize_req = { 'resize': { 'flavorRef': new_flavor['id'] } } - self.api.post_server_action(server['id'], resize_req) - self._wait_for_state_change(self.api, server, 'VERIFY_RESIZE') - - # OK, so the resize operation has run, but we have not yet confirmed or - # reverted the resize operation. Before we run periodics, make sure - # that we have allocations/usages on BOTH the source and the - # destination hosts. - source_usages = self._get_provider_usages(source_rp_uuid) - self.assertFlavorMatchesAllocation(old_flavor, source_usages) - dest_usages = self._get_provider_usages(dest_rp_uuid) - self.assertFlavorMatchesAllocation(new_flavor, dest_usages) - - # The instance should own the new_flavor allocation against the - # destination host created by the scheduler - allocations = self._get_allocations_by_server_uuid(server['id']) - self.assertEqual(1, len(allocations)) - dest_alloc = allocations[dest_rp_uuid]['resources'] - self.assertFlavorMatchesAllocation(new_flavor, dest_alloc) - - # The migration should own the old_flavor allocation against the - # source host created by conductor - migration_uuid = self.get_migration_uuid_for_instance(server['id']) - allocations = self._get_allocations_by_server_uuid(migration_uuid) - source_alloc = allocations[source_rp_uuid]['resources'] - self.assertFlavorMatchesAllocation(old_flavor, source_alloc) - - self._run_periodics() - - # the original host expected to have the old resource usage - source_usages = self._get_provider_usages(source_rp_uuid) - self.assertFlavorMatchesAllocation(old_flavor, source_usages) - - # the dest host expected to have resource allocation based on - # the new flavor the server is resized to - dest_usages = self._get_provider_usages(dest_rp_uuid) - self.assertFlavorMatchesAllocation(new_flavor, dest_usages) - - # The instance should own the new_flavor allocation against the - # destination host - allocations = self._get_allocations_by_server_uuid(server['id']) - self.assertEqual(1, len(allocations)) - dest_allocation = allocations[dest_rp_uuid]['resources'] - self.assertFlavorMatchesAllocation(new_flavor, dest_allocation) - - # The migration should own the old_flavor allocation against the - # source host - migration_uuid = self.get_migration_uuid_for_instance(server['id']) - allocations = self._get_allocations_by_server_uuid(migration_uuid) - source_alloc = allocations[source_rp_uuid]['resources'] - self.assertFlavorMatchesAllocation(old_flavor, source_alloc) + self._move_and_check_allocations( + server, request=resize_req, old_flavor=old_flavor, + new_flavor=new_flavor, source_rp_uuid=source_rp_uuid, + dest_rp_uuid=dest_rp_uuid) def _test_resize_revert(self, dest_hostname): source_hostname = self._other_hostname(dest_hostname) @@ -2990,6 +2985,100 @@ class ServerMovingTests(ProviderUsageBaseTestCase): def test_resize_reschedule_uses_host_lists_not_enough_alts(self): self._test_resize_reschedule_uses_host_lists(fails=3, num_alts=1) + def test_migrate_confirm(self): + source_hostname = self.compute1.host + dest_hostname = self.compute2.host + source_rp_uuid = self._get_provider_uuid_by_host(source_hostname) + dest_rp_uuid = self._get_provider_uuid_by_host(dest_hostname) + + server = self._boot_and_check_allocations( + self.flavor1, source_hostname) + + self._migrate_and_check_allocations( + server, self.flavor1, source_rp_uuid, dest_rp_uuid) + + # Confirm the move and check the usages + post = {'confirmResize': None} + self.api.post_server_action( + server['id'], post, check_response_status=[204]) + self._wait_for_state_change(self.api, server, 'ACTIVE') + + def _check_allocation(): + allocations = self._get_allocations_by_server_uuid(server['id']) + + # and the server allocates only from the target host + self.assertEqual(1, len(allocations)) + + source_usages = self._get_provider_usages(source_rp_uuid) + dest_usages = self._get_provider_usages(dest_rp_uuid) + + # and the target host allocation should be according to the flavor + self.assertFlavorMatchesAllocation(self.flavor1, dest_usages) + self.assertEqual({'VCPU': 0, + 'MEMORY_MB': 0, + 'DISK_GB': 0}, source_usages, + 'The source host %s still has usages after the ' + 'resize has been confirmed' % source_hostname) + + # and the target host allocation should be according to the flavor + self.assertFlavorMatchesAllocation(self.flavor1, dest_usages) + + dest_allocation = allocations[dest_rp_uuid]['resources'] + self.assertFlavorMatchesAllocation(self.flavor1, dest_allocation) + + # After confirming, we should have an allocation only on the + # destination host + _check_allocation() + self._run_periodics() + + # Check we're still accurate after running the periodics + _check_allocation() + + self._delete_and_check_allocations(server) + + def test_migrate_revert(self): + source_hostname = self.compute1.host + dest_hostname = self.compute2.host + source_rp_uuid = self._get_provider_uuid_by_host(source_hostname) + dest_rp_uuid = self._get_provider_uuid_by_host(dest_hostname) + + server = self._boot_and_check_allocations( + self.flavor1, source_hostname) + + self._migrate_and_check_allocations( + server, self.flavor1, source_rp_uuid, dest_rp_uuid) + + # Revert the move and check the usages + post = {'revertResize': None} + self.api.post_server_action(server['id'], post) + self._wait_for_state_change(self.api, server, 'ACTIVE') + + def _check_allocation(): + source_usages = self._get_provider_usages(source_rp_uuid) + allocations = self._get_allocations_by_server_uuid(server['id']) + self.assertFlavorMatchesAllocation(self.flavor1, source_usages) + + dest_usages = self._get_provider_usages(dest_rp_uuid) + self.assertEqual({'VCPU': 0, + 'MEMORY_MB': 0, + 'DISK_GB': 0}, dest_usages, + 'Target host %s still has usage after the ' + 'resize has been reverted' % dest_hostname) + + # Check that the server only allocates resource from the original + # host + self.assertEqual(1, len(allocations)) + + source_allocation = allocations[source_rp_uuid]['resources'] + self.assertFlavorMatchesAllocation(self.flavor1, source_allocation) + + # the original host expected to have the old resource allocation + _check_allocation() + self._run_periodics() + _check_allocation() + + self._delete_and_check_allocations(server) + class ServerLiveMigrateForceAndAbort(ProviderUsageBaseTestCase): """Test Server live migrations, which delete the migration or