From 27f410a2d62d40d2f4945b3c3708ec67a52a5a63 Mon Sep 17 00:00:00 2001 From: zhufl Date: Thu, 13 Aug 2020 15:27:59 +0800 Subject: [PATCH] Adding description for testcases - compute part11 When Tempest is used in customer site, often we are required to provide a testcase list including testcase names and descriptions. Now no this kind of doc is available, so we can add descriptions with the format of doc string for every testcase, so later we can generata such a testcase description list. There are hundreds of testcases missing descriptions, so we can add them gradually, and limit the modified files in one patch for the convenience of reviewing. Change-Id: I5bf95ca579b731ca4baefb590edb8e265126ce4f partially-implements: blueprint testcase-description --- .../admin/test_instance_usage_audit_log.py | 5 +- .../test_instance_usage_audit_log_negative.py | 10 +- .../api/compute/admin/test_security_groups.py | 18 +++- .../compute/admin/test_server_diagnostics.py | 6 ++ tempest/api/compute/admin/test_volume_swap.py | 51 +++++++--- .../compute/admin/test_volumes_negative.py | 19 ++++ .../servers/test_create_server_multi_nic.py | 14 ++- .../compute/servers/test_server_actions.py | 97 ++++++++++++++++--- 8 files changed, 184 insertions(+), 36 deletions(-) diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log.py b/tempest/api/compute/admin/test_instance_usage_audit_log.py index 1b62249b08..4dcbb3b082 100644 --- a/tempest/api/compute/admin/test_instance_usage_audit_log.py +++ b/tempest/api/compute/admin/test_instance_usage_audit_log.py @@ -22,6 +22,7 @@ from tempest.lib import decorators class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest): + """Test instance usage audit logs API""" @classmethod def setup_clients(cls): @@ -30,12 +31,12 @@ class InstanceUsageAuditLogTestJSON(base.BaseV2ComputeAdminTest): @decorators.idempotent_id('25319919-33d9-424f-9f99-2c203ee48b9d') def test_list_instance_usage_audit_logs(self): - # list instance usage audit logs + """Test listing instance usage audit logs""" self.adm_client.list_instance_usage_audit_logs() @decorators.idempotent_id('6e40459d-7c5f-400b-9e83-449fbc8e7feb') def test_get_instance_usage_audit_log(self): - # Get instance usage audit log before specified time + """Test getting instance usage audit log before specified time""" now = datetime.datetime.now() self.adm_client.show_instance_usage_audit_log( urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S"))) diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py index de8e221a5a..84d18c47bf 100644 --- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py +++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py @@ -23,6 +23,7 @@ from tempest.lib import exceptions as lib_exc class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest): + """Negative tests of instance usage audit logs""" @classmethod def setup_clients(cls): @@ -32,7 +33,10 @@ class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest): @decorators.attr(type=['negative']) @decorators.idempotent_id('a9d33178-d2c9-4131-ad3b-f4ca8d0308a2') def test_instance_usage_audit_logs_with_nonadmin_user(self): - # the instance_usage_audit_logs API just can be accessed by admin user + """Test list/show instance usage audit logs by non-admin should fail + + The instance_usage_audit_logs API just can be accessed by admin user. + """ self.assertRaises(lib_exc.Forbidden, self.instance_usages_audit_log_client. list_instance_usage_audit_logs) @@ -45,6 +49,10 @@ class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest): @decorators.attr(type=['negative']) @decorators.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8') def test_get_instance_usage_audit_logs_with_invalid_time(self): + """Test showing instance usage audit logs with invalid time + + Showing instance usage audit logs with invalid time should fail. + """ self.assertRaises(lib_exc.BadRequest, self.adm_client.show_instance_usage_audit_log, "invalid_time") diff --git a/tempest/api/compute/admin/test_security_groups.py b/tempest/api/compute/admin/test_security_groups.py index dfa801b855..f0a6a84e1d 100644 --- a/tempest/api/compute/admin/test_security_groups.py +++ b/tempest/api/compute/admin/test_security_groups.py @@ -20,6 +20,12 @@ from tempest.lib import decorators class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest): + """Test security groups API that requires admin privilege + + Test security groups API that requires admin privilege with compute + microversion less than 2.36 + """ + max_microversion = '2.35' @classmethod @@ -37,7 +43,17 @@ class SecurityGroupsTestAdminJSON(base.BaseV2ComputeAdminTest): @decorators.idempotent_id('49667619-5af9-4c63-ab5d-2cfdd1c8f7f1') @utils.services('network') def test_list_security_groups_list_all_tenants_filter(self): - # Admin can list security groups of all tenants + """Test listing security groups with all_tenants filter + + 1. Create two security groups for non-admin user + 2. Create two security groups for admin user + 3. Fetch all security groups based on 'all_tenants' search filter by + admin, check that all four created security groups are present in + fetched list + 4. Fetch all security groups based on 'all_tenants' search filter by + non-admin, check only two security groups created by the provided + non-admin user are present in fetched list + """ # List of all security groups created security_group_list = [] # Create two security groups for a non-admin tenant diff --git a/tempest/api/compute/admin/test_server_diagnostics.py b/tempest/api/compute/admin/test_server_diagnostics.py index 005efddb80..d855a62805 100644 --- a/tempest/api/compute/admin/test_server_diagnostics.py +++ b/tempest/api/compute/admin/test_server_diagnostics.py @@ -19,6 +19,8 @@ from tempest.lib import decorators class ServerDiagnosticsTest(base.BaseV2ComputeAdminTest): + """Test server diagnostics with compute microversion less than 2.48""" + min_microversion = None max_microversion = '2.47' @@ -29,6 +31,7 @@ class ServerDiagnosticsTest(base.BaseV2ComputeAdminTest): @decorators.idempotent_id('31ff3486-b8a0-4f56-a6c0-aab460531db3') def test_get_server_diagnostics(self): + """Test getting server diagnostics""" server_id = self.create_test_server(wait_until='ACTIVE')['id'] diagnostics = self.client.show_server_diagnostics(server_id) @@ -41,6 +44,8 @@ class ServerDiagnosticsTest(base.BaseV2ComputeAdminTest): class ServerDiagnosticsV248Test(base.BaseV2ComputeAdminTest): + """Test server diagnostics with compute microversion greater than 2.47""" + min_microversion = '2.48' max_microversion = 'latest' @@ -51,6 +56,7 @@ class ServerDiagnosticsV248Test(base.BaseV2ComputeAdminTest): @decorators.idempotent_id('64d0d48c-dff1-11e6-bf01-fe55135034f3') def test_get_server_diagnostics(self): + """Test getting server diagnostics""" server_id = self.create_test_server(wait_until='ACTIVE')['id'] # Response status and filed types will be checked by json schema self.client.show_server_diagnostics(server_id) diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py index edcb1a7440..c1236a7b30 100644 --- a/tempest/api/compute/admin/test_volume_swap.py +++ b/tempest/api/compute/admin/test_volume_swap.py @@ -68,21 +68,7 @@ class TestVolumeSwapBase(base.BaseV2ComputeAdminTest): class TestVolumeSwap(TestVolumeSwapBase): - """The test suite for swapping of volume with admin user. - - The following is the scenario outline: - - 1. Create a volume "volume1" with non-admin. - 2. Create a volume "volume2" with non-admin. - 3. Boot an instance "instance1" with non-admin. - 4. Attach "volume1" to "instance1" with non-admin. - 5. Swap volume from "volume1" to "volume2" as admin. - 6. Check the swap volume is successful and "volume2" - is attached to "instance1" and "volume1" is in available state. - 7. Swap volume from "volume2" to "volume1" as admin. - 8. Check the swap volume is successful and "volume1" - is attached to "instance1" and "volume2" is in available state. - """ + """The test suite for swapping of volume with admin user""" # NOTE(mriedem): This is an uncommon scenario to call the compute API # to swap volumes directly; swap volume is primarily only for volume @@ -92,6 +78,21 @@ class TestVolumeSwap(TestVolumeSwapBase): @decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813') @utils.services('volume') def test_volume_swap(self): + """Test swapping of volume attached to server with admin user + + The following is the scenario outline: + + 1. Create a volume "volume1" with non-admin. + 2. Create a volume "volume2" with non-admin. + 3. Boot an instance "instance1" with non-admin. + 4. Attach "volume1" to "instance1" with non-admin. + 5. Swap volume from "volume1" to "volume2" as admin. + 6. Check the swap volume is successful and "volume2" + is attached to "instance1" and "volume1" is in available state. + 7. Swap volume from "volume2" to "volume1" as admin. + 8. Check the swap volume is successful and "volume1" + is attached to "instance1" and "volume2" is in available state. + """ # Create two volumes. # NOTE(gmann): Volumes are created before server creation so that # volumes cleanup can happen successfully irrespective of which volume @@ -134,6 +135,12 @@ class TestVolumeSwap(TestVolumeSwapBase): class TestMultiAttachVolumeSwap(TestVolumeSwapBase): + """Test swapping volume attached to multiple servers + + Test swapping volume attached to multiple servers with microversion + greater than 2.59 + """ + min_microversion = '2.60' max_microversion = 'latest' @@ -164,6 +171,20 @@ class TestMultiAttachVolumeSwap(TestVolumeSwapBase): condition=CONF.compute.min_compute_nodes > 1) @utils.services('volume') def test_volume_swap_with_multiattach(self): + """Test swapping volume attached to multiple servers + + The following is the scenario outline: + + 1. Create a volume "volume1" with non-admin. + 2. Create a volume "volume2" with non-admin. + 3. Boot 2 instances "server1" and "server2" with non-admin. + 4. Attach "volume1" to "server1" with non-admin. + 5. Attach "volume1" to "server2" with non-admin. + 6. Swap "volume1" to "volume2" on "server1" + 7. Check "volume1" is attached to "server2" and not attached to + "server1" + 8. Check "volume2" is attached to "server1". + """ # Create two volumes. # NOTE(gmann): Volumes are created before server creation so that # volumes cleanup can happen successfully irrespective of which volume diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py index 7b0f48b8a7..10d522bba5 100644 --- a/tempest/api/compute/admin/test_volumes_negative.py +++ b/tempest/api/compute/admin/test_volumes_negative.py @@ -23,6 +23,8 @@ CONF = config.CONF class VolumesAdminNegativeTest(base.BaseV2ComputeAdminTest): + """Negative tests of volume swapping""" + create_default_network = True @classmethod @@ -40,6 +42,7 @@ class VolumesAdminNegativeTest(base.BaseV2ComputeAdminTest): @decorators.attr(type=['negative']) @decorators.idempotent_id('309b5ecd-0585-4a7e-a36f-d2b2bf55259d') def test_update_attached_volume_with_nonexistent_volume_in_uri(self): + """Test swapping non existent volume should fail""" volume = self.create_volume() nonexistent_volume = data_utils.rand_uuid() self.assertRaises(lib_exc.NotFound, @@ -51,6 +54,7 @@ class VolumesAdminNegativeTest(base.BaseV2ComputeAdminTest): @decorators.attr(type=['negative']) @decorators.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a') def test_update_attached_volume_with_nonexistent_volume_in_body(self): + """Test swapping volume to a non existence volume should fail""" volume = self.create_volume() self.attach_volume(self.server, volume) @@ -62,6 +66,12 @@ class VolumesAdminNegativeTest(base.BaseV2ComputeAdminTest): class UpdateMultiattachVolumeNegativeTest(base.BaseV2ComputeAdminTest): + """Negative tests of swapping volume attached to multiple servers + + Negative tests of swapping volume attached to multiple servers with + compute microversion greater than 2.59 and volume microversion greater + than 3.26 + """ min_microversion = '2.60' volume_min_microversion = '3.27' @@ -76,7 +86,16 @@ class UpdateMultiattachVolumeNegativeTest(base.BaseV2ComputeAdminTest): @decorators.idempotent_id('7576d497-b7c6-44bd-9cc5-c5b4e50fec71') @utils.services('volume') def test_multiattach_rw_volume_update_failure(self): + """Test swapping volume attached to multi-servers with read-write mode + 1. Create two volumes "vol1" and "vol2" + 2. Create two instances "server1" and "server2" + 3. Attach "vol1" to both of these instances + 4. By default both of these attachments should have an attach_mode of + read-write, so trying to swap "vol1" to "vol2" should fail + 5. Check "vol1" is still attached to both servers + 6. Check "vol2" is not attached to any server + """ # Create two multiattach capable volumes. vol1 = self.create_volume(multiattach=True) vol2 = self.create_volume(multiattach=True) diff --git a/tempest/api/compute/servers/test_create_server_multi_nic.py b/tempest/api/compute/servers/test_create_server_multi_nic.py index d0f53fe31a..bd3f58d03b 100644 --- a/tempest/api/compute/servers/test_create_server_multi_nic.py +++ b/tempest/api/compute/servers/test_create_server_multi_nic.py @@ -24,6 +24,7 @@ CONF = config.CONF class ServersTestMultiNic(base.BaseV2ComputeTest): + """Test multiple networks in servers""" @classmethod def skip_checks(cls): @@ -59,8 +60,11 @@ class ServersTestMultiNic(base.BaseV2ComputeTest): @decorators.idempotent_id('0578d144-ed74-43f8-8e57-ab10dbf9b3c2') def test_verify_multiple_nics_order(self): - # Verify that the networks order given at the server creation is - # preserved within the server. + """Test verifying multiple networks order in server + + The networks order given at the server creation is preserved within + the server. + """ net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24') net2 = self._create_net_subnet_ret_net_from_cidr('19.86.0.0/24') @@ -95,6 +99,12 @@ class ServersTestMultiNic(base.BaseV2ComputeTest): @decorators.idempotent_id('1678d144-ed74-43f8-8e57-ab10dbf9b3c2') def test_verify_duplicate_network_nics(self): + """Test multiple duplicate networks can be used to create server + + Creating server with networks [net1, net2, net1], the server can + be created successfully and all three networks are in the server + addresses. + """ # Verify that server creation does not fail when more than one nic # is created on the same network. net1 = self._create_net_subnet_ret_net_from_cidr('19.80.0.0/24') diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py index d477be0eb4..4db6987da3 100644 --- a/tempest/api/compute/servers/test_server_actions.py +++ b/tempest/api/compute/servers/test_server_actions.py @@ -34,6 +34,8 @@ LOG = logging.getLogger(__name__) class ServerActionsTestJSON(base.BaseV2ComputeTest): + """Test server actions""" + def setUp(self): # NOTE(afazekas): Normally we use the same server with all test cases, # but if it has an issue, we build a new one @@ -84,6 +86,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.change_password, 'Change password not available.') def test_change_server_password(self): + """Test changing server's password + + The server's password should be set to the provided password and + the user can authenticate with the new password. + """ # Since this test messes with the password and makes the # server unreachable, it should create its own server validation_resources = self.get_test_validation_resources( @@ -147,17 +154,24 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @decorators.attr(type='smoke') @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32') def test_reboot_server_hard(self): - # The server should be power cycled + """Test hard rebooting server + + The server should be power cycled. + """ self._test_reboot_server('HARD') @decorators.skip_because(bug="1014647") @decorators.idempotent_id('4640e3ef-a5df-482e-95a1-ceeeb0faa84d') def test_reboot_server_soft(self): - # The server should be signaled to reboot gracefully + """Test soft rebooting server + + The server should be signaled to reboot gracefully. + """ self._test_reboot_server('SOFT') @decorators.idempotent_id('1d1c9104-1b0a-11e7-a3d4-fa163e65f5ce') def test_remove_server_all_security_groups(self): + """Test removing all security groups from server""" server = self.create_test_server(wait_until='ACTIVE') # Remove all Security group @@ -232,12 +246,19 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @decorators.idempotent_id('aaa6cdf3-55a7-461a-add9-1c8596b9a07c') def test_rebuild_server(self): + """Test rebuilding server + + The server should be rebuilt using the provided image and data. + """ self._test_rebuild_server() @decorators.idempotent_id('30449a88-5aff-4f9b-9866-6ee9b17f906d') def test_rebuild_server_in_stop_state(self): - # The server in stop state should be rebuilt using the provided - # image and remain in SHUTOFF state + """Test rebuilding server in stop state + + The server in stop state should be rebuilt using the provided + image and remain in SHUTOFF state. + """ server = self.client.show_server(self.server_id)['server'] old_image = server['image']['id'] new_image = (self.image_ref_alt @@ -274,6 +295,10 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @decorators.idempotent_id('b68bd8d6-855d-4212-b59b-2e704044dace') @utils.services('volume') def test_rebuild_server_with_volume_attached(self): + """Test rebuilding server with volume attached + + The volume should be attached to the instance after rebuild. + """ # create a new volume and attach it to the server volume = self.create_volume() @@ -333,6 +358,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.resize, 'Resize not available.') def test_resize_server_confirm(self): + """Test resizing server and then confirming""" self._test_resize_server_confirm(self.server_id, stop=False) @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b') @@ -341,6 +367,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): 'Resize not available.') @utils.services('volume') def test_resize_volume_backed_server_confirm(self): + """Test resizing a volume backed server and then confirming""" # We have to create a new server that is volume-backed since the one # from setUp is not volume-backed. kwargs = {'volume_backed': True, @@ -377,14 +404,18 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.resize, 'Resize not available.') def test_resize_server_confirm_from_stopped(self): + """Test resizing a stopped server and then confirming""" self._test_resize_server_confirm(self.server_id, stop=True) @decorators.idempotent_id('c03aab19-adb1-44f5-917d-c419577e9e68') @testtools.skipUnless(CONF.compute_feature_enabled.resize, 'Resize not available.') def test_resize_server_revert(self): - # The server's RAM and disk space should return to its original - # values after a resize is reverted + """Test resizing server and then reverting + + The server's RAM and disk space should return to its original + values after a resize is reverted. + """ self.client.resize_server(self.server_id, self.flavor_ref_alt) # NOTE(zhufl): Explicitly delete the server to get a new one for later @@ -405,10 +436,13 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): 'Resize not available.') @utils.services('volume') def test_resize_server_revert_with_volume_attached(self): - # Tests attaching a volume to a server instance and then resizing - # the instance. Once the instance is resized, revert the resize which - # should move the instance and volume attachment back to the original - # compute host. + """Test resizing a volume attached server and then reverting + + Tests attaching a volume to a server instance and then resizing + the instance. Once the instance is resized, revert the resize which + should move the instance and volume attachment back to the original + compute host. + """ # Create a blank volume and attach it to the server created in setUp. volume = self.create_volume() @@ -437,7 +471,14 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): 'Snapshotting not available, backup not possible.') @utils.services('image') def test_create_backup(self): - # Positive test:create backup successfully and rotate backups correctly + """Test creating server backup + + 1. create server backup1 with rotation=2, there are 1 backup. + 2. create server backup2 with rotation=2, there are 2 backups. + 3. create server backup3, due to the rotation is 2, the first one + (backup1) will be deleted, so now there are still 2 backups. + """ + # create the first and the second backup # Check if glance v1 is available to determine which client to use. We @@ -563,8 +604,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.console_output, 'Console output not supported.') def test_get_console_output(self): - # Positive test:Should be able to GET the console output - # for a given server_id and number of lines + """Test getting console output for a server + + Should be able to GET the console output for a given server_id and + number of lines. + """ # This reboot is necessary for outputting some console log after # creating an instance backup. If an instance backup, the console @@ -579,6 +623,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.console_output, 'Console output not supported.') def test_get_console_output_with_unlimited_size(self): + """Test getting server's console output with unlimited size + + The console output lines length should be bigger than the one + of test_get_console_output. + """ server = self.create_test_server(wait_until='ACTIVE') def _check_full_length_console_log(): @@ -597,8 +646,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.console_output, 'Console output not supported.') def test_get_console_output_server_id_in_shutoff_status(self): - # Positive test:Should be able to GET the console output - # for a given server_id in SHUTOFF status + """Test getting console output for a server in SHUTOFF status + + Should be able to GET the console output for a given server_id + in SHUTOFF status. + """ # NOTE: SHUTOFF is irregular status. To avoid test instability, # one server is created only for this test without using @@ -614,6 +666,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.pause, 'Pause is not available.') def test_pause_unpause_server(self): + """Test pausing and unpausing server""" self.client.pause_server(self.server_id) waiters.wait_for_server_status(self.client, self.server_id, 'PAUSED') self.client.unpause_server(self.server_id) @@ -623,6 +676,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.suspend, 'Suspend is not available.') def test_suspend_resume_server(self): + """Test suspending and resuming server""" self.client.suspend_server(self.server_id) waiters.wait_for_server_status(self.client, self.server_id, 'SUSPENDED') @@ -634,6 +688,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): 'Shelve is not available.') @utils.services('image') def test_shelve_unshelve_server(self): + """Test shelving and unshelving server""" if CONF.image_feature_enabled.api_v2: glance_client = self.os_primary.image_client_v2 elif CONF.image_feature_enabled.api_v1: @@ -673,6 +728,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.pause, 'Pause is not available.') def test_shelve_paused_server(self): + """Test shelving a paused server""" server = self.create_test_server(wait_until='ACTIVE') self.client.pause_server(server['id']) waiters.wait_for_server_status(self.client, server['id'], 'PAUSED') @@ -682,6 +738,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @decorators.idempotent_id('af8eafd4-38a7-4a4b-bdbc-75145a580560') def test_stop_start_server(self): + """Test stopping and starting server""" self.client.stop_server(self.server_id) waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF') self.client.start_server(self.server_id) @@ -689,6 +746,12 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @decorators.idempotent_id('80a8094c-211e-440a-ab88-9e59d556c7ee') def test_lock_unlock_server(self): + """Test locking and unlocking server + + Lock the server, and trying to stop it will fail because locked + server is not allowed to be stopped by non-admin user. + Then unlock the server, now the server can be stopped and started. + """ # Lock the server,try server stop(exceptions throw),unlock it and retry self.client.lock_server(self.server_id) self.addCleanup(self.client.unlock_server, self.server_id) @@ -714,6 +777,10 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest): @testtools.skipUnless(CONF.compute_feature_enabled.vnc_console, 'VNC Console feature is disabled.') def test_get_vnc_console(self): + """Test getting vnc console from a server + + The returned vnc console url should be in valid format. + """ if self.is_requested_microversion_compatible('2.5'): body = self.client.get_vnc_console( self.server_id, type='novnc')['console']