Merge "Revert "Skip tests for transfering volumes when volumes are encrypted by LUKS"" into mcp/antelope
diff --git a/requirements.txt b/requirements.txt
index abe25b5..83410e2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -3,7 +3,6 @@
# process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
cliff!=2.9.0,>=2.8.0 # Apache-2.0
-ddt>=1.6.0 # MIT
jsonschema>=3.2.0 # MIT
testtools>=2.2.0 # MIT
paramiko>=2.7.0 # LGPLv2.1+
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index cae9c06..369b4b1 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -15,8 +15,6 @@
import time
-import ddt
-
from oslo_log import log as logging
import testtools
@@ -51,6 +49,11 @@
"Less than 2 compute nodes, skipping migration test.")
@classmethod
+ def setup_credentials(cls):
+ cls.prepare_instance_network()
+ super(LiveMigrationTestBase, cls).setup_credentials()
+
+ @classmethod
def setup_clients(cls):
super(LiveMigrationTestBase, cls).setup_clients()
cls.admin_migration_client = cls.os_admin.migrations_client
@@ -96,17 +99,6 @@
self.assertEqual(target_host, self.get_host_for_server(server_id),
msg)
-
-@ddt.ddt
-class LiveMigrationTest(LiveMigrationTestBase):
- max_microversion = '2.24'
- block_migration = None
-
- @classmethod
- def setup_credentials(cls):
- cls.prepare_instance_network()
- super(LiveMigrationTest, cls).setup_credentials()
-
def _test_live_migration(
self, state='ACTIVE', volume_backed=False, image_id=None):
"""Tests live migration between two hosts.
@@ -145,16 +137,19 @@
LOG.info("Live migrate back to source %s", source_host)
self._live_migrate(server_id, source_host, state, volume_backed)
+
+class LiveMigrationTest(LiveMigrationTestBase):
+ max_microversion = '2.24'
+ block_migration = None
+
@decorators.attr(type='multinode')
@decorators.idempotent_id('1dce86b8-eb04-4c03-a9d8-9c1dc3ee0c7b')
@testtools.skipUnless(CONF.compute_feature_enabled.
block_migration_for_live_migration,
'Block Live migration not available')
- @ddt.data('image_ref', 'image_raw_ref')
- def test_live_block_migration(self, image):
+ def test_live_block_migration(self):
"""Test live migrating an active server"""
- image_id = getattr(CONF.compute, image)
- self._test_live_migration(image_id=image_id)
+ self._test_live_migration()
@decorators.attr(type='multinode')
@decorators.idempotent_id('1e107f21-61b2-4988-8f22-b196e938ab88')
@@ -385,3 +380,53 @@
if CONF.compute_feature_enabled.volume_multiattach:
min_microversion = '2.60'
+
+
+class LiveMigrationTestRaw(LiveMigrationTestBase):
+ max_microversion = '2.24'
+ block_migration = None
+ image_id = CONF.compute.image_raw_ref
+
+ @classmethod
+ def skip_checks(cls):
+ super(LiveMigrationTestRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.attr(type='multinode')
+ @decorators.idempotent_id('6916bb20-fbf1-42df-958d-fa19acbbc09d')
+ @testtools.skipUnless(CONF.compute_feature_enabled.
+ block_migration_for_live_migration,
+ 'Block Live migration not available')
+ def test_live_block_migration(self):
+ """Test live migrating an active server"""
+ self._test_live_migration(image_id=self.image_id)
+
+
+class LiveAutoBlockMigrationV225TestRaw(LiveMigrationTestBase):
+ min_microversion = '2.25'
+ max_microversion = 'latest'
+ block_migration = 'auto'
+ image_id = CONF.compute.image_raw_ref
+
+ if CONF.compute_feature_enabled.volume_multiattach:
+ min_microversion = '2.60'
+
+ @classmethod
+ def skip_checks(cls):
+ super(LiveAutoBlockMigrationV225TestRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.attr(type='multinode')
+ @decorators.idempotent_id('f7aeae41-83af-4574-87d1-bdd11d2f994e')
+ @testtools.skipUnless(CONF.compute_feature_enabled.
+ block_migration_for_live_migration,
+ 'Block Live migration not available')
+ def test_live_block_migration(self):
+ """Test live migrating an active server"""
+ self._test_live_migration(image_id=self.image_id)
diff --git a/tempest/api/compute/admin/test_migrations.py b/tempest/api/compute/admin/test_migrations.py
index 551ea9d..0e9ea5a 100644
--- a/tempest/api/compute/admin/test_migrations.py
+++ b/tempest/api/compute/admin/test_migrations.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
import testtools
from tempest.api.compute import base
@@ -25,15 +24,43 @@
CONF = config.CONF
-@ddt.ddt
-class MigrationsAdminTest(base.BaseV2ComputeAdminTest):
+class MigrationsAdminTestBase(base.BaseV2ComputeAdminTest):
"""Test migration operations supported by admin user"""
@classmethod
def setup_clients(cls):
- super(MigrationsAdminTest, cls).setup_clients()
+ super(MigrationsAdminTestBase, cls).setup_clients()
cls.client = cls.os_admin.migrations_client
+ def _test_cold_migrate_server(self, revert=False, image_id=None):
+ if CONF.compute.min_compute_nodes < 2:
+ msg = "Less than 2 compute nodes, skipping multinode tests."
+ raise self.skipException(msg)
+
+ server = self.create_test_server(image_id=image_id,
+ wait_until="ACTIVE")
+ src_host = self.get_host_for_server(server['id'])
+
+ self.admin_servers_client.migrate_server(server['id'])
+
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'VERIFY_RESIZE')
+
+ if revert:
+ self.servers_client.revert_resize_server(server['id'])
+ assert_func = self.assertEqual
+ else:
+ self.servers_client.confirm_resize_server(server['id'])
+ assert_func = self.assertNotEqual
+
+ waiters.wait_for_server_status(self.servers_client,
+ server['id'], 'ACTIVE')
+ dst_host = self.get_host_for_server(server['id'])
+ assert_func(src_host, dst_host)
+
+
+class MigrationsAdminTest(MigrationsAdminTestBase):
+
@decorators.idempotent_id('75c0b83d-72a0-4cf8-a153-631e83e7d53f')
def test_list_migrations(self):
"""Test admin user can get the migrations list"""
@@ -137,48 +164,47 @@
'flavor!' % key)
self.assertEqual(pre_flavor[key], server['flavor'][key], msg)
- def _test_cold_migrate_server(self, revert=False, image_id=None):
- if CONF.compute.min_compute_nodes < 2:
- msg = "Less than 2 compute nodes, skipping multinode tests."
- raise self.skipException(msg)
-
- server = self.create_test_server(image_id=image_id,
- wait_until="ACTIVE")
- src_host = self.get_host_for_server(server['id'])
-
- self.admin_servers_client.migrate_server(server['id'])
-
- waiters.wait_for_server_status(self.servers_client,
- server['id'], 'VERIFY_RESIZE')
-
- if revert:
- self.servers_client.revert_resize_server(server['id'])
- assert_func = self.assertEqual
- else:
- self.servers_client.confirm_resize_server(server['id'])
- assert_func = self.assertNotEqual
-
- waiters.wait_for_server_status(self.servers_client,
- server['id'], 'ACTIVE')
- dst_host = self.get_host_for_server(server['id'])
- assert_func(src_host, dst_host)
-
@decorators.attr(type='multinode')
@decorators.idempotent_id('4bf0be52-3b6f-4746-9a27-3143636fe30d')
@testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
'Cold migration not available.')
- @ddt.data('image_ref', 'image_raw_ref')
- def test_cold_migration(self, image):
+ def test_cold_migration(self):
"""Test cold migrating server and then confirm the migration"""
- image_id = getattr(CONF.compute, image)
- self._test_cold_migrate_server(revert=False, image_id=image_id)
+ self._test_cold_migrate_server(revert=False)
@decorators.attr(type='multinode')
@decorators.idempotent_id('caa1aa8b-f4ef-4374-be0d-95f001c2ac2d')
@testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
'Cold migration not available.')
- @ddt.data('image_ref', 'image_raw_ref')
- def test_revert_cold_migration(self, image):
+ def test_revert_cold_migration(self):
"""Test cold migrating server and then revert the migration"""
- image_id = getattr(CONF.compute, image)
- self._test_cold_migrate_server(revert=True, image_id=image_id)
+ self._test_cold_migrate_server(revert=True)
+
+
+class MigrationsAdminTestRaw(MigrationsAdminTestBase):
+
+ image_id = CONF.compute.image_raw_ref
+
+ @classmethod
+ def skip_checks(cls):
+ super(MigrationsAdminTestRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.attr(type='multinode')
+ @decorators.idempotent_id('17f41ec8-734d-41cf-b18c-6c2fe3eb65c3')
+ @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+ 'Cold migration not available.')
+ def test_cold_migration(self):
+ """Test cold migrating server and then confirm the migration"""
+ self._test_cold_migrate_server(revert=False, image_id=self.image_id)
+
+ @decorators.attr(type='multinode')
+ @decorators.idempotent_id('c9d5dc79-d7fc-4f81-9a8d-e6e104ec4f98')
+ @testtools.skipUnless(CONF.compute_feature_enabled.cold_migration,
+ 'Cold migration not available.')
+ def test_revert_cold_migration(self):
+ """Test cold migrating server and then revert the migration"""
+ self._test_cold_migrate_server(revert=True, image_id=self.image_id)
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index f87e353..f8b621b 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -34,14 +34,14 @@
LOG = logging.getLogger(__name__)
-class ServerActionsBaseTestJSON(base.BaseV2ComputeTest):
+class ServerActionsTestJSONBase(base.BaseV2ComputeTest):
image_id = None
if CONF.compute_feature_enabled.volume_multiattach:
min_microversion = '2.60'
def setUp(self):
- super(ServerActionsBaseTestJSON, self).setUp()
+ super(ServerActionsTestJSONBase, self).setUp()
# Instead of reusing an instance which had been created before a new
# instance is created in favour of increasing stability of tests.
self.validation_resources = self.get_test_validation_resources(
@@ -57,11 +57,11 @@
@classmethod
def setup_credentials(cls):
cls.prepare_instance_network()
- super(ServerActionsBaseTestJSON, cls).setup_credentials()
+ super(ServerActionsTestJSONBase, cls).setup_credentials()
@classmethod
def setup_clients(cls):
- super(ServerActionsBaseTestJSON, cls).setup_clients()
+ super(ServerActionsTestJSONBase, cls).setup_clients()
cls.client = cls.servers_client
def _test_reboot_server(self, reboot_type):
@@ -218,7 +218,7 @@
self.assertIn(parsed_url.scheme, valid_scheme)
-class ServerActionsTestJSON(ServerActionsBaseTestJSON):
+class ServerActionsTestJSON(ServerActionsTestJSONBase):
"""Test server actions"""
@decorators.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
@@ -714,9 +714,6 @@
self.assertNotEqual('', body['url'])
self._validate_url(body['url'])
-
-class ServerActionsBaseImageTestJSON(ServerActionsBaseTestJSON):
-
@decorators.attr(type='smoke')
@decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
def test_reboot_server_hard(self):
@@ -773,10 +770,73 @@
waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
-class ServerActionsRawImageTestJSON(ServerActionsBaseImageTestJSON):
+class ServerActionsTestJSONRaw(ServerActionsTestJSONBase):
"""Test server actions with raw image type"""
image_id = CONF.compute.image_raw_ref
+ @classmethod
+ def skip_checks(cls):
+ super(ServerActionsTestJSONRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.attr(type='smoke')
+ @decorators.idempotent_id('b6a39851-a0d9-413f-bb2a-d260557201c2')
+ def test_reboot_server_hard(self):
+ """Test hard rebooting server
+
+ The server should be power cycled.
+ """
+ self._test_reboot_server('HARD')
+
+ @decorators.idempotent_id('38aa6f34-7160-44ad-bb95-c46d7760a838')
+ @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
+ '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:
+ glance_client = self.os_primary.image_client
+ else:
+ raise lib_exc.InvalidConfiguration(
+ 'Either api_v1 or api_v2 must be True in '
+ '[image-feature-enabled].')
+ compute.shelve_server(self.client, self.server_id,
+ force_shelve_offload=True)
+
+ def _unshelve_server():
+ server_info = self.client.show_server(self.server_id)['server']
+ if 'SHELVED' in server_info['status']:
+ self.client.unshelve_server(self.server_id)
+ self.addCleanup(_unshelve_server)
+
+ server = self.client.show_server(self.server_id)['server']
+ image_name = server['name'] + '-shelved'
+ params = {'name': image_name}
+ if CONF.image_feature_enabled.api_v2:
+ images = glance_client.list_images(params)['images']
+ elif CONF.image_feature_enabled.api_v1:
+ images = glance_client.list_images(
+ detail=True, **params)['images']
+ self.assertEqual(1, len(images))
+ self.assertEqual(image_name, images[0]['name'])
+
+ self.client.unshelve_server(self.server_id)
+ waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
+ glance_client.wait_for_resource_deletion(images[0]['id'])
+
+ @decorators.idempotent_id('441a3ae1-7f1e-4c99-9a3b-288c538ca192')
+ 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)
+ waiters.wait_for_server_status(self.client, self.server_id, 'ACTIVE')
+
class ServersAaction247Test(base.BaseV2ComputeTest):
"""Test compute server with microversion greater than 2.47
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 32dbd3c..cfb3a59 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
-
from oslo_serialization import jsonutils as json
from tempest.common import utils
@@ -29,8 +27,7 @@
CONF = config.CONF
-@ddt.ddt
-class TestServerBasicOps(manager.ScenarioTestWithNetwork):
+class TestServerBasicOpsBase(manager.ScenarioTestWithNetwork):
"""The test suite for server basic operations
@@ -46,7 +43,7 @@
"""
def setUp(self):
- super(TestServerBasicOps, self).setUp()
+ super(TestServerBasicOpsBase, self).setUp()
self.run_ssh = CONF.validation.run_validation
self.ssh_user = CONF.validation.image_ssh_user
@@ -128,17 +125,51 @@
# TODO(clarkb) construct network_data from known network
# instance info and do direct comparison.
+
+class TestServerBasicOps(TestServerBasicOpsBase):
+
@decorators.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
@decorators.attr(type='smoke')
- @ddt.data('image_ref', 'image_raw_ref')
@utils.services('compute', 'network')
- def test_server_basic_ops(self, image):
+ def test_server_basic_ops(self):
keypair = self.create_keypair()
security_group = self.create_security_group()
self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
- image_id = getattr(CONF.compute, image)
self.instance = self.create_server(
- image_id=image_id,
+ key_name=keypair['name'],
+ security_groups=[{'name': security_group['name']}],
+ config_drive=CONF.compute_feature_enabled.config_drive,
+ metadata=self.md)
+ self.verify_ssh(keypair)
+ self.verify_metadata()
+ self.verify_metadata_on_config_drive()
+ self.verify_networkdata_on_config_drive()
+ self.servers_client.delete_server(self.instance['id'])
+ waiters.wait_for_server_termination(
+ self.servers_client, self.instance['id'], ignore_error=False)
+
+
+class TestServerBasicOpsRaw(TestServerBasicOpsBase):
+
+ image_id = CONF.compute.image_raw_ref
+
+ @classmethod
+ def skip_checks(cls):
+ super(TestServerBasicOpsRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.idempotent_id('2d203d40-c3d4-4e2f-b22f-380c1a165f79')
+ @decorators.attr(type='smoke')
+ @utils.services('compute', 'network')
+ def test_server_basic_ops(self):
+ keypair = self.create_keypair()
+ security_group = self.create_security_group()
+ self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
+ self.instance = self.create_server(
+ image_id=self.image_id,
key_name=keypair['name'],
security_groups=[{'name': security_group['name']}],
config_drive=CONF.compute_feature_enabled.config_drive,
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 4273a3a..3ba301a 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
import testtools
from tempest.common import compute
@@ -26,8 +25,7 @@
CONF = config.CONF
-@ddt.ddt
-class TestShelveInstance(manager.ScenarioTest):
+class TestShelveInstanceBase(manager.ScenarioTest):
"""This test shelves then unshelves a Nova instance
The following is the scenario outline:
@@ -44,12 +42,12 @@
@classmethod
def setup_clients(cls):
- super(TestShelveInstance, cls).setup_clients()
+ super(TestShelveInstanceBase, cls).setup_clients()
cls.admin_servers_client = cls.os_admin.servers_client
@classmethod
def skip_checks(cls):
- super(TestShelveInstance, cls).skip_checks()
+ super(TestShelveInstanceBase, cls).skip_checks()
if not CONF.compute_feature_enabled.shelve:
raise cls.skipException("Shelve is not available.")
@@ -106,15 +104,16 @@
server=server)
self.assertEqual(timestamp, timestamp2)
+
+class TestShelveInstance(TestShelveInstanceBase):
+
@decorators.attr(type='slow')
@decorators.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
@testtools.skipUnless(CONF.network.public_network_id,
'The public_network_id option must be specified.')
- @ddt.data('image_ref', 'image_raw_ref')
@utils.services('compute', 'network', 'image')
- def test_shelve_instance(self, image):
- image_id = getattr(CONF.compute, image)
- self._create_server_then_shelve_and_unshelve(image_id=image_id)
+ def test_shelve_instance(self):
+ self._create_server_then_shelve_and_unshelve()
@decorators.attr(type='slow')
@decorators.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
@@ -138,3 +137,24 @@
@utils.services('compute', 'network', 'image')
def test_cold_migrate_unshelved_instance(self):
self._create_server_then_shelve_and_unshelve(cold_migrate=True)
+
+
+class TestShelveInstanceRaw(TestShelveInstanceBase):
+
+ image_id = CONF.compute.image_raw_ref
+
+ @classmethod
+ def skip_checks(cls):
+ super(TestShelveInstanceRaw, cls).skip_checks()
+
+ if not cls.image_id:
+ skip_msg = ("Environment doesn't have raw type image")
+ raise cls.skipException(skip_msg)
+
+ @decorators.attr(type='slow')
+ @decorators.idempotent_id('ee0b7d90-54e3-4f50-abd0-cef03c793914')
+ @testtools.skipUnless(CONF.network.public_network_id,
+ 'The public_network_id option must be specified.')
+ @utils.services('compute', 'network', 'image')
+ def test_shelve_instance(self):
+ self._create_server_then_shelve_and_unshelve(image_id=self.image_id)