From 0f613248935a71a2057d37e759c3708a8efec121 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 15 Jul 2020 14:52:11 +0100 Subject: [PATCH] tests: Add helpers for suspend, resume and reboot of server We will use this in a later test, but some tests that could have benefited from these are reworked now to validate the approach. Change-Id: I03bcd6753ed776d2ee216dcdca48514e5da8c43e Signed-off-by: Stephen Finucane --- nova/tests/functional/integrated_helpers.py | 52 ++++++++++++------- .../regressions/test_bug_1835822.py | 14 ++--- .../functional/test_cross_cell_migrate.py | 12 ++--- nova/tests/functional/test_servers.py | 18 ++----- nova/tests/functional/wsgi/test_interfaces.py | 25 ++++----- 5 files changed, 54 insertions(+), 67 deletions(-) diff --git a/nova/tests/functional/integrated_helpers.py b/nova/tests/functional/integrated_helpers.py index 3c2618a7497a..93ee84921bf2 100644 --- a/nova/tests/functional/integrated_helpers.py +++ b/nova/tests/functional/integrated_helpers.py @@ -393,6 +393,20 @@ class InstanceHelperMixin: self.api.delete_server(server['id']) self._wait_until_deleted(server) + def _reboot_server(self, server, hard=False, expected_state='ACTIVE'): + """Reboot a server.""" + self.api.post_server_action( + server['id'], {'reboot': {'type': 'HARD' if hard else 'SOFT'}}, + ) + fake_notifier.wait_for_versioned_notifications('instance.reboot.end') + return self._wait_for_state_change(server, expected_state) + + def _resize_server(self, server, flavor_id): + self.api.post_server_action( + server['id'], {'resize': {'flavorRef': flavor_id}}) + fake_notifier.wait_for_versioned_notifications('instance.resize.end') + return self._wait_for_state_change(server, 'VERIFY_RESIZE') + def _confirm_resize(self, server): self.api.post_server_action(server['id'], {'confirmResize': None}) server = self._wait_for_state_change(server, 'ACTIVE') @@ -415,30 +429,26 @@ class InstanceHelperMixin: 'instance.resize_revert.end') return server - def _migrate_or_resize(self, server, request): - if 'resize' not in request and 'migrate' not in request: - raise Exception('_migrate_or_resize only supports resize or ' - 'migrate requests.') - self.api.post_server_action(server['id'], request) - self._wait_for_state_change(server, 'VERIFY_RESIZE') - - def _resize_server(self, server, new_flavor): - resize_req = { - 'resize': { - 'flavorRef': new_flavor - } - } - self._migrate_or_resize(server, resize_req) - def _live_migrate(self, server, migration_expected_state, server_expected_state='ACTIVE'): self.api.post_server_action( server['id'], - {'os-migrateLive': {'host': None, - 'block_migration': 'auto'}}) + {'os-migrateLive': {'host': None, 'block_migration': 'auto'}}) self._wait_for_state_change(server, server_expected_state) self._wait_for_migration_status(server, [migration_expected_state]) + def _suspend_server(self, server, expected_state='SUSPENDED'): + """Suspend a server.""" + self.api.post_server_action(server['id'], {'suspend': {}}) + fake_notifier.wait_for_versioned_notifications('instance.suspend.end') + return self._wait_for_state_change(server, expected_state) + + def _resume_server(self, server, expected_state='ACTIVE'): + """Resume a server.""" + self.api.post_server_action(server['id'], {'resume': {}}) + fake_notifier.wait_for_versioned_notifications('instance.resume.end') + return self._wait_for_state_change(server, expected_state) + class PlacementHelperMixin: """A helper mixin for interacting with placement.""" @@ -827,7 +837,13 @@ class PlacementInstanceHelperMixin(InstanceHelperMixin, PlacementHelperMixin): self, server, request, old_flavor, new_flavor, source_rp_uuid, dest_rp_uuid, ): - self._migrate_or_resize(server, request) + if 'resize' not in request and 'migrate' not in request: + raise Exception( + '_move_and_check_allocations only supports resize or migrate ' + 'requests.') + + self.api.post_server_action(server['id'], request) + self._wait_for_state_change(server, 'VERIFY_RESIZE') def _check_allocation(): self.assertFlavorMatchesUsage(source_rp_uuid, old_flavor) diff --git a/nova/tests/functional/regressions/test_bug_1835822.py b/nova/tests/functional/regressions/test_bug_1835822.py index d627cd8fa788..91d95679cf32 100644 --- a/nova/tests/functional/regressions/test_bug_1835822.py +++ b/nova/tests/functional/regressions/test_bug_1835822.py @@ -59,13 +59,6 @@ class RegressionTest1835822( server = self.api.post_server({'server': basic_server}) return self._wait_for_state_change(server, 'ACTIVE') - def _hard_reboot_server(self, active_server): - args = {"reboot": {"type": "HARD"}} - self.api.api_post('servers/%s/action' % - active_server['id'], args) - fake_notifier.wait_for_versioned_notifications('instance.reboot.end') - return self._wait_for_state_change(active_server, 'ACTIVE') - def _rebuild_server(self, active_server): args = {"rebuild": {"imageRef": self.image_ref_1}} self.api.api_post('servers/%s/action' % @@ -112,7 +105,7 @@ class RegressionTest1835822( self.flags(force_config_drive=True) active_server = self._create_active_server() self.assertTrue(active_server['config_drive']) - active_server = self._hard_reboot_server(active_server) + active_server = self._reboot_server(active_server, hard=True) self.assertTrue(active_server['config_drive']) def test_create_server_config_drive_reboot_after_conf_change(self): @@ -132,13 +125,14 @@ class RegressionTest1835822( # this server was created with force_config_drive=true # so assert now that force_config_drive is false it does # not override the value it was booted with. - with_config_drive = self._hard_reboot_server(with_config_drive) + with_config_drive = self._reboot_server(with_config_drive, hard=True) self.assertTrue(with_config_drive['config_drive']) # this server was booted with force_config_drive=False so # assert that it's config drive setting is not overridden self.flags(force_config_drive=True) - without_config_drive = self._hard_reboot_server(without_config_drive) + without_config_drive = self._reboot_server( + without_config_drive, hard=True) self.assertEqual('', without_config_drive['config_drive']) def test_create_server_config_drive_rebuild_after_conf_change(self): diff --git a/nova/tests/functional/test_cross_cell_migrate.py b/nova/tests/functional/test_cross_cell_migrate.py index 26233f0761b1..5fd01faf3ff5 100644 --- a/nova/tests/functional/test_cross_cell_migrate.py +++ b/nova/tests/functional/test_cross_cell_migrate.py @@ -1116,13 +1116,11 @@ class TestMultiCellMigrate(integrated_helpers.ProviderUsageBaseTestCase): # Now hard reboot the server in the source cell and it should go back # to ACTIVE. - self.api.post_server_action(server['id'], {'reboot': {'type': 'HARD'}}) - self._wait_for_state_change(server, 'ACTIVE') + self._reboot_server(server, hard=True) # Now retry the resize without the fault in the target host to make # sure things are OK (no duplicate entry errors in the target DB). - self.api.post_server_action(server['id'], body) - self._wait_for_state_change(server, 'VERIFY_RESIZE') + self._resize_server(server, flavor2) def _assert_instance_not_in_cell(self, cell_name, server_id): cell = self.cell_mappings[cell_name] @@ -1189,10 +1187,8 @@ class TestMultiCellMigrate(integrated_helpers.ProviderUsageBaseTestCase): # Now hard reboot the server in the source cell and it should go back # to ACTIVE. - self.api.post_server_action(server['id'], {'reboot': {'type': 'HARD'}}) - self._wait_for_state_change(server, 'ACTIVE') + self._reboot_server(server, hard=True) # Now retry the resize without the fault in the target host to make # sure things are OK (no duplicate entry errors in the target DB). - self.api.post_server_action(server['id'], body) - self._wait_for_state_change(server, 'VERIFY_RESIZE') + self._resize_server(server, flavor2) diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index d85e148ee751..77d77ec368f0 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -344,14 +344,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): 'SOFT_DELETED') # Create a second server - server = self._build_server() - - created_server2 = self.api.post_server({'server': server}) - LOG.debug("created_server: %s", created_server2) - self.assertTrue(created_server2['id']) - - # Wait for it to finish being created - self._wait_for_state_change(created_server2, 'ACTIVE') + self._create_server() # Try to restore the first server, it should fail ex = self.assertRaises(client.OpenStackApiException, @@ -8098,16 +8091,11 @@ class AcceleratorServerOpsTest(AcceleratorServerBase): networks='none', expected_state='ACTIVE') def test_soft_reboot_ok(self): - params = {'reboot': {'type': 'SOFT'}} - self.api.post_server_action(self.server['id'], params) - self._wait_for_state_change(self.server, 'ACTIVE') + self._reboot_server(self.server) self._check_allocations_usage(self.server) def test_hard_reboot_ok(self): - params = {'reboot': {'type': 'HARD'}} - self.api.post_server_action(self.server['id'], params) - self._wait_for_state_change(self.server, 'HARD_REBOOT') - self._wait_for_state_change(self.server, 'ACTIVE') + self._reboot_server(self.server, hard=True) self._check_allocations_usage(self.server) def test_pause_unpause_ok(self): diff --git a/nova/tests/functional/wsgi/test_interfaces.py b/nova/tests/functional/wsgi/test_interfaces.py index ad7189cc7481..b50ad94efd17 100644 --- a/nova/tests/functional/wsgi/test_interfaces.py +++ b/nova/tests/functional/wsgi/test_interfaces.py @@ -29,32 +29,25 @@ class InterfaceFullstack(integrated_helpers._IntegratedTestBase): def test_detach_interface_negative_invalid_state(self): # Create server with network - created_server = self._create_server( + server = self._create_server( networks=[{'uuid': '3cb9bc59-5699-4588-a4b1-b87f96708bc6'}]) - created_server_id = created_server['id'] - found_server = self._wait_for_state_change(created_server, 'ACTIVE') + self.addCleanup(self._delete_server, server) post = { 'interfaceAttachment': { 'net_id': "3cb9bc59-5699-4588-a4b1-b87f96708bc6" } } - self.api.attach_interface(created_server_id, post) + self.api.attach_interface(server['id'], post) - response = self.api.get_port_interfaces(created_server_id)[0] - port_id = response['port_id'] + ports = self.api.get_port_interfaces(server['id']) # Change status from ACTIVE to SUSPENDED for negative test - post = {'suspend': {}} - self.api.post_server_action(created_server_id, post) - found_server = self._wait_for_state_change(found_server, 'SUSPENDED') + server = self._suspend_server(server) # Detach port interface in SUSPENDED (not ACTIVE, etc.) - ex = self.assertRaises(client.OpenStackApiException, - self.api.detach_interface, - created_server_id, port_id) + ex = self.assertRaises( + client.OpenStackApiException, + self.api.detach_interface, + server['id'], ports[0]['port_id']) self.assertEqual(409, ex.response.status_code) - self.assertEqual('SUSPENDED', found_server['status']) - - # Cleanup - self._delete_server(found_server)