Stop implicit validation_resources provisioning
The provisioning of validation resources is unreadable and hard to use. Tests have to call an helper before super's resource_setup is invoked and they will find resources in a dictionary in a class attribute. Changing to a model where the test.py base class provides helpers that takes care of common tasks: - pulling the right parameters from configuration - scheduling cleanup There are two helpers available, one to be used when validation resources are provisioned for a server created at class setup time; the second one shall be used with servers provisioned durint tests or test setup. The new helper returns the provisioned resources to the test. Other helpers are affected by this change since they cannot pull validation resource from class anymore safely, and they have been updated to accept validation resources as input. Change-Id: I1106e40c6d7483f66d645f3bb560c6d74a612d0f
This commit is contained in:
parent
3be574898c
commit
9f416dd25a
@ -17,8 +17,10 @@ import testtools
|
||||
|
||||
from tempest.api.compute import base
|
||||
from tempest.common.utils.linux import remote_client
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils import test_utils
|
||||
from tempest.lib import decorators
|
||||
|
||||
CONF = config.CONF
|
||||
@ -35,12 +37,6 @@ class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
|
||||
super(ServersWithSpecificFlavorTestJSON, cls).setup_clients()
|
||||
cls.client = cls.servers_client
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
|
||||
super(ServersWithSpecificFlavorTestJSON, cls).resource_setup()
|
||||
|
||||
@decorators.idempotent_id('b3c7bcfc-bb5b-4e22-b517-c7f686b802ca')
|
||||
@testtools.skipUnless(CONF.validation.run_validation,
|
||||
'Instance validation tests are disabled.')
|
||||
@ -67,20 +63,30 @@ class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
|
||||
|
||||
admin_pass = self.image_ssh_password
|
||||
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
server_no_eph_disk = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE',
|
||||
adminPass=admin_pass,
|
||||
flavor=flavor_no_eph_disk_id)
|
||||
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, server_no_eph_disk['id'])
|
||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.servers_client.delete_server,
|
||||
server_no_eph_disk['id'])
|
||||
|
||||
# Get partition number of server without ephemeral disk.
|
||||
server_no_eph_disk = self.client.show_server(
|
||||
server_no_eph_disk['id'])['server']
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server_no_eph_disk),
|
||||
self.get_server_ip(server_no_eph_disk,
|
||||
validation_resources),
|
||||
self.ssh_user,
|
||||
admin_pass,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server_no_eph_disk,
|
||||
servers_client=self.client)
|
||||
disks_num = len(linux_client.get_disks().split('\n'))
|
||||
@ -90,17 +96,25 @@ class ServersWithSpecificFlavorTestJSON(base.BaseV2ComputeAdminTest):
|
||||
|
||||
server_with_eph_disk = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE',
|
||||
adminPass=admin_pass,
|
||||
flavor=flavor_with_eph_disk_id)
|
||||
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, server_with_eph_disk['id'])
|
||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.servers_client.delete_server,
|
||||
server_with_eph_disk['id'])
|
||||
|
||||
server_with_eph_disk = self.client.show_server(
|
||||
server_with_eph_disk['id'])['server']
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server_with_eph_disk),
|
||||
self.get_server_ip(server_with_eph_disk,
|
||||
validation_resources),
|
||||
self.ssh_user,
|
||||
admin_pass,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server_with_eph_disk,
|
||||
servers_client=self.client)
|
||||
disks_num_eph = len(linux_client.get_disks().split('\n'))
|
||||
|
@ -190,7 +190,7 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
||||
|
||||
@classmethod
|
||||
def create_test_server(cls, validatable=False, volume_backed=False,
|
||||
**kwargs):
|
||||
validation_resources=None, **kwargs):
|
||||
"""Wrapper utility that returns a test server.
|
||||
|
||||
This wrapper utility calls the common create test server and
|
||||
@ -200,6 +200,10 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
||||
|
||||
:param validatable: Whether the server will be pingable or sshable.
|
||||
:param volume_backed: Whether the instance is volume backed or not.
|
||||
:param validation_resources: Dictionary of validation resources as
|
||||
returned by `get_class_validation_resources`.
|
||||
:param kwargs: Extra arguments are passed down to the
|
||||
`compute.create_test_server` call.
|
||||
"""
|
||||
if 'name' not in kwargs:
|
||||
kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server")
|
||||
@ -216,7 +220,7 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
||||
body, servers = compute.create_test_server(
|
||||
cls.os_primary,
|
||||
validatable,
|
||||
validation_resources=cls.validation_resources,
|
||||
validation_resources=validation_resources,
|
||||
tenant_network=tenant_network,
|
||||
volume_backed=volume_backed,
|
||||
**kwargs)
|
||||
@ -326,13 +330,33 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
||||
|
||||
@classmethod
|
||||
def rebuild_server(cls, server_id, validatable=False, **kwargs):
|
||||
# Destroy an existing server and creates a new one
|
||||
"""Destroy an existing class level server and creates a new one
|
||||
|
||||
Some test classes use a test server that can be used by multiple
|
||||
tests. This is done to optimise runtime and test load.
|
||||
If something goes wrong with the test server, it can be rebuilt
|
||||
using this helper.
|
||||
|
||||
This helper can also be used for the initial provisioning if no
|
||||
server_id is specified.
|
||||
|
||||
:param server_id: UUID of the server to be rebuilt. If None is
|
||||
specified, a new server is provisioned.
|
||||
:param validatable: whether to the server needs to be
|
||||
validatable. When True, validation resources are acquired via
|
||||
the `get_class_validation_resources` helper.
|
||||
:param kwargs: extra paramaters are passed through to the
|
||||
`create_test_server` call.
|
||||
:return: the UUID of the created server.
|
||||
"""
|
||||
if server_id:
|
||||
cls.delete_server(server_id)
|
||||
|
||||
cls.password = data_utils.rand_password()
|
||||
server = cls.create_test_server(
|
||||
validatable,
|
||||
validation_resources=cls.get_class_validation_resources(
|
||||
cls.os_primary),
|
||||
wait_until='ACTIVE',
|
||||
adminPass=cls.password,
|
||||
**kwargs)
|
||||
@ -363,14 +387,23 @@ class BaseV2ComputeTest(api_version_utils.BaseMicroversionTest,
|
||||
cls._delete_volume(cls.volumes_client, volume_id)
|
||||
|
||||
@classmethod
|
||||
def get_server_ip(cls, server):
|
||||
def get_server_ip(cls, server, validation_resources=None):
|
||||
"""Get the server fixed or floating IP.
|
||||
|
||||
Based on the configuration we're in, return a correct ip
|
||||
address for validating that a guest is up.
|
||||
|
||||
:param server: The server dict as returned by the API
|
||||
:param validation_resources: The dict of validation resources
|
||||
provisioned for the server.
|
||||
"""
|
||||
if CONF.validation.connect_method == 'floating':
|
||||
return cls.validation_resources['floating_ip']['ip']
|
||||
if validation_resources:
|
||||
return validation_resources['floating_ip']['ip']
|
||||
else:
|
||||
msg = ('When validation.connect_method equals floating, '
|
||||
'validation_resources cannot be None')
|
||||
raise exceptions.InvalidParam(invalid_param=msg)
|
||||
elif CONF.validation.connect_method == 'fixed':
|
||||
addresses = server['addresses'][CONF.validation.network_for_ssh]
|
||||
for address in addresses:
|
||||
|
@ -42,8 +42,9 @@ class ServersTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
super(ServersTestJSON, cls).resource_setup()
|
||||
validation_resources = cls.get_class_validation_resources(
|
||||
cls.os_primary)
|
||||
cls.meta = {'hello': 'world'}
|
||||
cls.accessIPv4 = '1.1.1.1'
|
||||
cls.accessIPv6 = '0000:0000:0000:0000:0000:babe:220.12.22.2'
|
||||
@ -52,6 +53,7 @@ class ServersTestJSON(base.BaseV2ComputeTest):
|
||||
disk_config = cls.disk_config
|
||||
server_initial = cls.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE',
|
||||
name=cls.name,
|
||||
metadata=cls.meta,
|
||||
@ -105,11 +107,13 @@ class ServersTestJSON(base.BaseV2ComputeTest):
|
||||
# Verify that the number of vcpus reported by the instance matches
|
||||
# the amount stated by the flavor
|
||||
flavor = self.flavors_client.show_flavor(self.flavor_ref)['flavor']
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(self.server),
|
||||
self.get_server_ip(self.server, validation_resources),
|
||||
self.ssh_user,
|
||||
self.password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=self.server,
|
||||
servers_client=self.client)
|
||||
output = linux_client.exec_command('grep -c ^processor /proc/cpuinfo')
|
||||
@ -120,11 +124,13 @@ class ServersTestJSON(base.BaseV2ComputeTest):
|
||||
'Instance validation tests are disabled.')
|
||||
def test_host_name_is_same_as_server_name(self):
|
||||
# Verify the instance host name is the same as the server name
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(self.server),
|
||||
self.get_server_ip(self.server, validation_resources),
|
||||
self.ssh_user,
|
||||
self.password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=self.server,
|
||||
servers_client=self.client)
|
||||
hostname = linux_client.exec_command("hostname").rstrip()
|
||||
|
@ -66,11 +66,6 @@ class DeviceTaggingTest(base.BaseV2ComputeTest):
|
||||
dhcp=True)
|
||||
super(DeviceTaggingTest, cls).setup_credentials()
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
super(DeviceTaggingTest, cls).resource_setup()
|
||||
|
||||
def verify_device_metadata(self, md_json):
|
||||
md_dict = json.loads(md_json)
|
||||
for d in md_dict['devices']:
|
||||
@ -139,9 +134,12 @@ class DeviceTaggingTest(base.BaseV2ComputeTest):
|
||||
# Create server
|
||||
admin_pass = data_utils.rand_password()
|
||||
config_drive_enabled = CONF.compute_feature_enabled.config_drive
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
|
||||
server = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
config_drive=config_drive_enabled,
|
||||
adminPass=admin_pass,
|
||||
name=data_utils.rand_name('device-tagging-server'),
|
||||
@ -208,10 +206,10 @@ class DeviceTaggingTest(base.BaseV2ComputeTest):
|
||||
self.addCleanup(self.delete_server, server['id'])
|
||||
|
||||
self.ssh_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
CONF.validation.image_ssh_user,
|
||||
admin_pass,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.servers_client)
|
||||
|
||||
|
@ -44,8 +44,13 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
self.server_id, 'ACTIVE')
|
||||
except lib_exc.NotFound:
|
||||
# The server was deleted by previous test, create a new one
|
||||
# Use class level validation resources to avoid them being
|
||||
# deleted once a test is over
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
server = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE')
|
||||
self.__class__.server_id = server['id']
|
||||
except Exception:
|
||||
@ -69,8 +74,6 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
|
||||
super(ServerActionsTestJSON, cls).resource_setup()
|
||||
cls.server_id = cls.rebuild_server(None, validatable=True)
|
||||
|
||||
@ -80,8 +83,11 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
def test_change_server_password(self):
|
||||
# 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(
|
||||
self.os_primary)
|
||||
newserver = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE')
|
||||
# The server's password should be set to the provided password
|
||||
new_password = 'Newpass1234'
|
||||
@ -92,7 +98,7 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
# Verify that the user can authenticate with the new password
|
||||
server = self.client.show_server(newserver['id'])['server']
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.ssh_user,
|
||||
new_password,
|
||||
server=server,
|
||||
@ -101,13 +107,15 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
def _test_reboot_server(self, reboot_type):
|
||||
if CONF.validation.run_validation:
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
# Get the time the server was last rebooted,
|
||||
server = self.client.show_server(self.server_id)['server']
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.ssh_user,
|
||||
self.password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.client)
|
||||
boot_time = linux_client.get_boot_time()
|
||||
@ -122,10 +130,10 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
if CONF.validation.run_validation:
|
||||
# Log in and verify the boot time has changed
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.ssh_user,
|
||||
self.password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.client)
|
||||
new_boot_time = linux_client.get_boot_time()
|
||||
@ -201,6 +209,8 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
self.assertEqual(original_addresses, server['addresses'])
|
||||
|
||||
if CONF.validation.run_validation:
|
||||
validation_resources = self.get_class_validation_resources(
|
||||
self.os_primary)
|
||||
# Authentication is attempted in the following order of priority:
|
||||
# 1.The key passed in, if one was passed in.
|
||||
# 2.Any key we can find through an SSH agent (if allowed).
|
||||
@ -208,10 +218,10 @@ class ServerActionsTestJSON(base.BaseV2ComputeTest):
|
||||
# ~/.ssh/ (if allowed).
|
||||
# 4.Plain username/password auth, if a password was given.
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(rebuilt_server),
|
||||
self.get_server_ip(rebuilt_server, validation_resources),
|
||||
self.ssh_user,
|
||||
password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=rebuilt_server,
|
||||
servers_client=self.client)
|
||||
linux_client.validate_authentication()
|
||||
|
@ -20,6 +20,7 @@ from tempest.common.utils.linux import remote_client
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import data_utils
|
||||
from tempest.lib.common.utils import test_utils
|
||||
from tempest.lib import decorators
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
|
||||
@ -33,11 +34,6 @@ class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
|
||||
cls.prepare_instance_network()
|
||||
super(ServerPersonalityTestJSON, cls).setup_credentials()
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
super(ServerPersonalityTestJSON, cls).resource_setup()
|
||||
|
||||
@classmethod
|
||||
def skip_checks(cls):
|
||||
super(ServerPersonalityTestJSON, cls).skip_checks()
|
||||
@ -57,16 +53,23 @@ class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
|
||||
personality = [{'path': file_path,
|
||||
'contents': base64.encode_as_text(file_contents)}]
|
||||
password = data_utils.rand_password()
|
||||
created_server = self.create_test_server(personality=personality,
|
||||
adminPass=password,
|
||||
wait_until='ACTIVE',
|
||||
validatable=True)
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
created_server = self.create_test_server(
|
||||
personality=personality, adminPass=password, wait_until='ACTIVE',
|
||||
validatable=True,
|
||||
validation_resources=validation_resources)
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, created_server['id'])
|
||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.servers_client.delete_server,
|
||||
created_server['id'])
|
||||
server = self.client.show_server(created_server['id'])['server']
|
||||
if CONF.validation.run_validation:
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.ssh_user, password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.client)
|
||||
self.assertEqual(file_contents,
|
||||
@ -75,8 +78,16 @@ class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
@decorators.idempotent_id('128966d8-71fc-443c-8cab-08e24114ecc9')
|
||||
def test_rebuild_server_with_personality(self):
|
||||
server = self.create_test_server(wait_until='ACTIVE', validatable=True)
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
server = self.create_test_server(
|
||||
wait_until='ACTIVE', validatable=True,
|
||||
validation_resources=validation_resources)
|
||||
server_id = server['id']
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, server_id)
|
||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.servers_client.delete_server, server_id)
|
||||
file_contents = 'Test server rebuild.'
|
||||
personality = [{'path': 'rebuild.txt',
|
||||
'contents': base64.encode_as_text(file_contents)}]
|
||||
@ -126,16 +137,22 @@ class ServerPersonalityTestJSON(base.BaseV2ComputeTest):
|
||||
'contents': base64.encode_as_text(file_contents + str(i)),
|
||||
})
|
||||
password = data_utils.rand_password()
|
||||
created_server = self.create_test_server(personality=person,
|
||||
adminPass=password,
|
||||
wait_until='ACTIVE',
|
||||
validatable=True)
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
created_server = self.create_test_server(
|
||||
personality=person, adminPass=password, wait_until='ACTIVE',
|
||||
validatable=True, validation_resources=validation_resources)
|
||||
self.addCleanup(waiters.wait_for_server_termination,
|
||||
self.servers_client, created_server['id'])
|
||||
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
|
||||
self.servers_client.delete_server,
|
||||
created_server['id'])
|
||||
server = self.client.show_server(created_server['id'])['server']
|
||||
if CONF.validation.run_validation:
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.ssh_user, password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.client)
|
||||
for i in person:
|
||||
|
@ -40,35 +40,37 @@ class AttachVolumeTestJSON(base.BaseV2ComputeTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
cls.set_validation_resources()
|
||||
super(AttachVolumeTestJSON, cls).resource_setup()
|
||||
cls.device = CONF.compute.volume_device_name
|
||||
|
||||
def _create_server(self):
|
||||
# Start a server and wait for it to become ready
|
||||
validation_resources = self.get_test_validation_resources(
|
||||
self.os_primary)
|
||||
server = self.create_test_server(
|
||||
validatable=True,
|
||||
validation_resources=validation_resources,
|
||||
wait_until='ACTIVE',
|
||||
adminPass=self.image_ssh_password)
|
||||
self.addCleanup(self.delete_server, server['id'])
|
||||
# Record addresses so that we can ssh later
|
||||
server['addresses'] = self.servers_client.list_addresses(
|
||||
server['id'])['addresses']
|
||||
return server
|
||||
return server, validation_resources
|
||||
|
||||
@decorators.idempotent_id('52e9045a-e90d-4c0d-9087-79d657faffff')
|
||||
def test_attach_detach_volume(self):
|
||||
# Stop and Start a server with an attached volume, ensuring that
|
||||
# the volume remains attached.
|
||||
server = self._create_server()
|
||||
server, validation_resources = self._create_server()
|
||||
|
||||
# NOTE(andreaf) Create one remote client used throughout the test.
|
||||
if CONF.validation.run_validation:
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.image_ssh_user,
|
||||
self.image_ssh_password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.servers_client)
|
||||
# NOTE(andreaf) We need to ensure the ssh key has been
|
||||
@ -111,7 +113,7 @@ class AttachVolumeTestJSON(base.BaseV2ComputeTest):
|
||||
@decorators.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
|
||||
def test_list_get_volume_attachments(self):
|
||||
# List volume attachment of the server
|
||||
server = self._create_server()
|
||||
server, _ = self._create_server()
|
||||
volume_1st = self.create_volume()
|
||||
attachment_1st = self.attach_volume(server, volume_1st,
|
||||
device=('/dev/%s' % self.device))
|
||||
@ -163,15 +165,15 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
if not CONF.compute_feature_enabled.shelve:
|
||||
raise cls.skipException('Shelve is not available.')
|
||||
|
||||
def _count_volumes(self, server):
|
||||
def _count_volumes(self, server, validation_resources):
|
||||
# Count number of volumes on an instance
|
||||
volumes = 0
|
||||
if CONF.validation.run_validation:
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.image_ssh_user,
|
||||
self.image_ssh_password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.servers_client)
|
||||
|
||||
@ -179,7 +181,7 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
volumes = int(linux_client.exec_command(command).strip())
|
||||
return volumes
|
||||
|
||||
def _shelve_server(self, server):
|
||||
def _shelve_server(self, server, validation_resources):
|
||||
# NOTE(andreaf) If we are going to shelve a server, we should
|
||||
# check first whether the server is ssh-able. Otherwise we
|
||||
# won't be able to distinguish failures introduced by shelve
|
||||
@ -188,10 +190,10 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
# avoid breaking the VM
|
||||
if CONF.validation.run_validation:
|
||||
linux_client = remote_client.RemoteClient(
|
||||
self.get_server_ip(server),
|
||||
self.get_server_ip(server, validation_resources),
|
||||
self.image_ssh_user,
|
||||
self.image_ssh_password,
|
||||
self.validation_resources['keypair']['private_key'],
|
||||
validation_resources['keypair']['private_key'],
|
||||
server=server,
|
||||
servers_client=self.servers_client)
|
||||
linux_client.validate_authentication()
|
||||
@ -199,30 +201,34 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
# If validation went ok, or it was skipped, shelve the server
|
||||
compute.shelve_server(self.servers_client, server['id'])
|
||||
|
||||
def _unshelve_server_and_check_volumes(self, server, number_of_volumes):
|
||||
def _unshelve_server_and_check_volumes(self, server,
|
||||
validation_resources,
|
||||
number_of_volumes):
|
||||
# Unshelve the instance and check that there are expected volumes
|
||||
self.servers_client.unshelve_server(server['id'])
|
||||
waiters.wait_for_server_status(self.servers_client,
|
||||
server['id'],
|
||||
'ACTIVE')
|
||||
if CONF.validation.run_validation:
|
||||
counted_volumes = self._count_volumes(server)
|
||||
counted_volumes = self._count_volumes(
|
||||
server, validation_resources)
|
||||
self.assertEqual(number_of_volumes, counted_volumes)
|
||||
|
||||
@decorators.idempotent_id('13a940b6-3474-4c3c-b03f-29b89112bfee')
|
||||
def test_attach_volume_shelved_or_offload_server(self):
|
||||
# Create server, count number of volumes on it, shelve
|
||||
# server and attach pre-created volume to shelved server
|
||||
server = self._create_server()
|
||||
server, validation_resources = self._create_server()
|
||||
volume = self.create_volume()
|
||||
num_vol = self._count_volumes(server)
|
||||
self._shelve_server(server)
|
||||
num_vol = self._count_volumes(server, validation_resources)
|
||||
self._shelve_server(server, validation_resources)
|
||||
attachment = self.attach_volume(server, volume,
|
||||
device=('/dev/%s' % self.device),
|
||||
check_reserved=True)
|
||||
|
||||
# Unshelve the instance and check that attached volume exists
|
||||
self._unshelve_server_and_check_volumes(server, num_vol + 1)
|
||||
self._unshelve_server_and_check_volumes(
|
||||
server, validation_resources, num_vol + 1)
|
||||
|
||||
# Get volume attachment of the server
|
||||
volume_attachment = self.servers_client.show_volume_attachment(
|
||||
@ -238,10 +244,10 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
def test_detach_volume_shelved_or_offload_server(self):
|
||||
# Count number of volumes on instance, shelve
|
||||
# server and attach pre-created volume to shelved server
|
||||
server = self._create_server()
|
||||
server, validation_resources = self._create_server()
|
||||
volume = self.create_volume()
|
||||
num_vol = self._count_volumes(server)
|
||||
self._shelve_server(server)
|
||||
num_vol = self._count_volumes(server, validation_resources)
|
||||
self._shelve_server(server, validation_resources)
|
||||
|
||||
# Attach and then detach the volume
|
||||
self.attach_volume(server, volume, device=('/dev/%s' % self.device),
|
||||
@ -252,4 +258,5 @@ class AttachVolumeShelveTestJSON(AttachVolumeTestJSON):
|
||||
|
||||
# Unshelve the instance and check that we have the expected number of
|
||||
# volume(s)
|
||||
self._unshelve_server_and_check_volumes(server, num_vol)
|
||||
self._unshelve_server_and_check_volumes(
|
||||
server, validation_resources, num_vol)
|
||||
|
@ -128,6 +128,8 @@ def create_test_server(clients, validatable=False, validation_resources=None,
|
||||
"this stage.")
|
||||
raise ValueError(msg)
|
||||
|
||||
LOG.debug("Provisioning test server with validation resources %s",
|
||||
validation_resources)
|
||||
if 'security_groups' in kwargs:
|
||||
kwargs['security_groups'].append(
|
||||
{'name': validation_resources['security_group']['name']})
|
||||
|
@ -181,6 +181,9 @@ def create_validation_resources(clients, keypair=False, floating_ip=False,
|
||||
floating_ip = resources['floating_ip']['ip']
|
||||
"""
|
||||
# Create and Return the validation resources required to validate a VM
|
||||
msg = ('Requested validation resources keypair %s, floating IP %s, '
|
||||
'security group %s')
|
||||
LOG.debug(msg, keypair, floating_ip, security_group)
|
||||
validation_data = {}
|
||||
try:
|
||||
if keypair:
|
||||
@ -429,6 +432,9 @@ class ValidationResourcesFixture(fixtures.Fixture):
|
||||
self._validation_resources = None
|
||||
|
||||
def _setUp(self):
|
||||
msg = ('Requested setup of ValidationResources keypair %s, floating '
|
||||
'IP %s, security group %s')
|
||||
LOG.debug(msg, self._keypair, self._floating_ip, self._security_group)
|
||||
self._validation_resources = create_validation_resources(
|
||||
self._clients, keypair=self._keypair,
|
||||
floating_ip=self._floating_ip,
|
||||
@ -441,9 +447,9 @@ class ValidationResourcesFixture(fixtures.Fixture):
|
||||
# cleanup here, so we don't need a try-finally around provisioning
|
||||
vr = self._validation_resources
|
||||
self.addCleanup(clear_validation_resources, self._clients,
|
||||
keypair=vr['keypair'],
|
||||
floating_ip=vr['floating_ip'],
|
||||
security_group=vr['security_group'],
|
||||
keypair=vr.get('keypair', None),
|
||||
floating_ip=vr.get('floating_ip', None),
|
||||
security_group=vr.get('security_group', None),
|
||||
use_neutron=self._use_neutron)
|
||||
|
||||
@property
|
||||
|
131
tempest/test.py
131
tempest/test.py
@ -26,7 +26,7 @@ import testtools
|
||||
from tempest import clients
|
||||
from tempest.common import credentials_factory as credentials
|
||||
from tempest.common import utils
|
||||
import tempest.common.validation_resources as vresources
|
||||
import tempest.common.validation_resources as vr
|
||||
from tempest import config
|
||||
from tempest.lib.common import cred_client
|
||||
from tempest.lib.common import fixed_network
|
||||
@ -105,13 +105,14 @@ class BaseTestCase(testtools.testcase.WithAttributes,
|
||||
# a list of roles - the first element of the list being a label, and the
|
||||
# rest the actual roles
|
||||
credentials = []
|
||||
# Resources required to validate a server using ssh
|
||||
validation_resources = {}
|
||||
network_resources = {}
|
||||
|
||||
# Stack of resource cleanups
|
||||
_class_cleanups = []
|
||||
|
||||
# Resources required to validate a server using ssh
|
||||
_validation_resources = {}
|
||||
|
||||
# NOTE(sdague): log_format is defined inline here instead of using the oslo
|
||||
# default because going through the config path recouples config to the
|
||||
# stress tests too early, and depending on testr order will fail unit tests
|
||||
@ -379,29 +380,13 @@ class BaseTestCase(testtools.testcase.WithAttributes,
|
||||
servers.delete_server,
|
||||
cls.shared_server2['id'])
|
||||
"""
|
||||
if (CONF.validation.ip_version_for_ssh not in (4, 6) and
|
||||
CONF.service_available.neutron):
|
||||
msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
|
||||
raise lib_exc.InvalidConfiguration(
|
||||
msg % CONF.validation.ip_version_for_ssh)
|
||||
if hasattr(cls, "os_primary"):
|
||||
vr = cls.validation_resources
|
||||
cls.validation_resources = vresources.create_validation_resources(
|
||||
cls.os_primary,
|
||||
use_neutron=CONF.service_available.neutron,
|
||||
ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
|
||||
floating_network_id=CONF.network.public_network_id,
|
||||
floating_network_name=CONF.network.floating_network_name,
|
||||
**vr)
|
||||
else:
|
||||
LOG.warning("Client manager not found, validation resources not"
|
||||
" created")
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def resource_cleanup(cls):
|
||||
"""Class level resource cleanup for test cases.
|
||||
|
||||
Resource cleanup processes the stack or cleanups produced by
|
||||
Resource cleanup processes the stack of cleanups produced by
|
||||
`addClassResourceCleanup` and then cleans up validation resources
|
||||
if any were provisioned.
|
||||
|
||||
@ -440,16 +425,6 @@ class BaseTestCase(testtools.testcase.WithAttributes,
|
||||
fn(*args, **kwargs)
|
||||
except Exception:
|
||||
cleanup_errors.append(sys.exc_info())
|
||||
if cls.validation_resources:
|
||||
if hasattr(cls, "os_primary"):
|
||||
vr = cls.validation_resources
|
||||
vresources.clear_validation_resources(
|
||||
cls.os_primary,
|
||||
use_neutron=CONF.service_available.neutron, **vr)
|
||||
cls.validation_resources = {}
|
||||
else:
|
||||
LOG.warning("Client manager not found, validation resources "
|
||||
"not deleted")
|
||||
if cleanup_errors:
|
||||
raise testtools.MultipleExceptions(*cleanup_errors)
|
||||
|
||||
@ -610,45 +585,83 @@ class BaseTestCase(testtools.testcase.WithAttributes,
|
||||
if hasattr(cls, '_creds_provider'):
|
||||
cls._creds_provider.clear_creds()
|
||||
|
||||
@staticmethod
|
||||
def _validation_resources_params_from_conf():
|
||||
return dict(
|
||||
keypair=(CONF.validation.auth_method.lower() == "keypair"),
|
||||
floating_ip=(CONF.validation.connect_method.lower() == "floating"),
|
||||
security_group=CONF.validation.security_group,
|
||||
security_group_rules=CONF.validation.security_group_rules,
|
||||
use_neutron=CONF.service_available.neutron,
|
||||
ethertype='IPv' + str(CONF.validation.ip_version_for_ssh),
|
||||
floating_network_id=CONF.network.public_network_id,
|
||||
floating_network_name=CONF.network.floating_network_name)
|
||||
|
||||
@classmethod
|
||||
def set_validation_resources(cls, keypair=None, floating_ip=None,
|
||||
security_group=None,
|
||||
security_group_rules=None):
|
||||
"""Specify which ssh server validation resources should be created.
|
||||
def get_class_validation_resources(cls, os_clients):
|
||||
"""Provision validation resources according to configuration
|
||||
|
||||
Each of the argument must be set to either None, True or False, with
|
||||
None - use default from config (security groups and security group
|
||||
rules get created when set to None)
|
||||
False - Do not create the validation resource
|
||||
True - create the validation resource
|
||||
This is a wrapper around `create_validation_resources` from
|
||||
`tempest.common.validation_resources` that passes parameters from
|
||||
Tempest configuration. Only one instance of class level
|
||||
validation resources is managed by the helper, so If resources
|
||||
were already provisioned before, existing ones will be returned.
|
||||
|
||||
@param keypair
|
||||
@param security_group
|
||||
@param security_group_rules
|
||||
@param floating_ip
|
||||
Resources are returned as a dictionary. They are also scheduled for
|
||||
automatic cleanup during class teardown using
|
||||
`addClassResourcesCleanup`.
|
||||
|
||||
If `CONF.validation.run_validation` is False no resource will be
|
||||
provisioned at all.
|
||||
|
||||
@param os_clients: Clients to be used to provision the resources.
|
||||
"""
|
||||
if not CONF.validation.run_validation:
|
||||
return
|
||||
|
||||
if keypair is None:
|
||||
keypair = (CONF.validation.auth_method.lower() == "keypair")
|
||||
if os_clients in cls._validation_resources:
|
||||
return cls._validation_resources[os_clients]
|
||||
|
||||
if floating_ip is None:
|
||||
floating_ip = (CONF.validation.connect_method.lower() ==
|
||||
"floating")
|
||||
if (CONF.validation.ip_version_for_ssh not in (4, 6) and
|
||||
CONF.service_available.neutron):
|
||||
msg = "Invalid IP version %s in ip_version_for_ssh. Use 4 or 6"
|
||||
raise lib_exc.InvalidConfiguration(
|
||||
msg % CONF.validation.ip_version_for_ssh)
|
||||
|
||||
if security_group is None:
|
||||
security_group = CONF.validation.security_group
|
||||
resources = vr.create_validation_resources(
|
||||
os_clients,
|
||||
**cls._validation_resources_params_from_conf())
|
||||
|
||||
if security_group_rules is None:
|
||||
security_group_rules = CONF.validation.security_group_rules
|
||||
cls.addClassResourceCleanup(
|
||||
vr.clear_validation_resources, os_clients,
|
||||
use_neutron=CONF.service_available.neutron,
|
||||
**resources)
|
||||
cls._validation_resources[os_clients] = resources
|
||||
return resources
|
||||
|
||||
if not cls.validation_resources:
|
||||
cls.validation_resources = {
|
||||
'keypair': keypair,
|
||||
'security_group': security_group,
|
||||
'security_group_rules': security_group_rules,
|
||||
'floating_ip': floating_ip}
|
||||
def get_test_validation_resources(self, os_clients):
|
||||
"""Returns a dict of validation resources according to configuration
|
||||
|
||||
Initialise a validation resources fixture based on configuration.
|
||||
Start the fixture and returns the validation resources.
|
||||
|
||||
If `CONF.validation.run_validation` is False no resource will be
|
||||
provisioned at all.
|
||||
|
||||
@param os_clients: Clients to be used to provision the resources.
|
||||
"""
|
||||
|
||||
params = {}
|
||||
# Test will try to use the fixture, so for this to be useful
|
||||
# we must return a fixture. If validation is disabled though
|
||||
# we don't need to provision anything, which is the default
|
||||
# behavior for the fixture.
|
||||
if CONF.validation.run_validation:
|
||||
params = self._validation_resources_params_from_conf()
|
||||
|
||||
validation = self.useFixture(
|
||||
vr.ValidationResourcesFixture(os_clients, **params))
|
||||
return validation.resources
|
||||
|
||||
@classmethod
|
||||
def set_network_resources(cls, network=False, router=False, subnet=False,
|
||||
|
@ -19,10 +19,15 @@ import mock
|
||||
from oslo_config import cfg
|
||||
import testtools
|
||||
|
||||
from tempest import clients
|
||||
from tempest.common import validation_resources as vr
|
||||
from tempest import config
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from tempest import test
|
||||
from tempest.tests import base
|
||||
from tempest.tests import fake_config
|
||||
from tempest.tests.lib import fake_credentials
|
||||
from tempest.tests.lib.services import registry_fixture
|
||||
|
||||
|
||||
if sys.version_info >= (2, 7):
|
||||
@ -41,6 +46,121 @@ class LoggingTestResult(testtools.TestResult):
|
||||
self.log.append((test, err, details))
|
||||
|
||||
|
||||
class TestValidationResources(base.TestCase):
|
||||
|
||||
validation_resources_module = 'tempest.common.validation_resources'
|
||||
|
||||
def setUp(self):
|
||||
super(TestValidationResources, self).setUp()
|
||||
self.useFixture(fake_config.ConfigFixture())
|
||||
self.useFixture(registry_fixture.RegistryFixture())
|
||||
self.patchobject(config, 'TempestConfigPrivate',
|
||||
fake_config.FakePrivate)
|
||||
|
||||
class TestTestClass(test.BaseTestCase):
|
||||
pass
|
||||
|
||||
self.test_test_class = TestTestClass
|
||||
|
||||
def test_validation_resources_no_validation(self):
|
||||
cfg.CONF.set_default('run_validation', False, 'validation')
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
vr = self.test_test_class.get_class_validation_resources(osclients)
|
||||
self.assertIsNone(vr)
|
||||
|
||||
def test_validation_resources_exists(self):
|
||||
cfg.CONF.set_default('run_validation', True, 'validation')
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
expected_vr = 'expected_validation_resources'
|
||||
self.test_test_class._validation_resources[osclients] = expected_vr
|
||||
obtained_vr = self.test_test_class.get_class_validation_resources(
|
||||
osclients)
|
||||
self.assertEqual(expected_vr, obtained_vr)
|
||||
|
||||
@mock.patch(validation_resources_module + '.create_validation_resources',
|
||||
autospec=True)
|
||||
def test_validation_resources_new(self, mock_create_vr):
|
||||
cfg.CONF.set_default('run_validation', True, 'validation')
|
||||
cfg.CONF.set_default('neutron', True, 'service_available')
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
expected_vr = {'expected_validation_resources': None}
|
||||
mock_create_vr.return_value = expected_vr
|
||||
with mock.patch.object(
|
||||
self.test_test_class,
|
||||
'addClassResourceCleanup') as mock_add_class_cleanup:
|
||||
obtained_vr = self.test_test_class.get_class_validation_resources(
|
||||
osclients)
|
||||
self.assertEqual(1, mock_add_class_cleanup.call_count)
|
||||
self.assertEqual(mock.call(vr.clear_validation_resources,
|
||||
osclients,
|
||||
use_neutron=True,
|
||||
**expected_vr),
|
||||
mock_add_class_cleanup.call_args)
|
||||
self.assertEqual(mock_create_vr.call_count, 1)
|
||||
self.assertIn(osclients, mock_create_vr.call_args_list[0][0])
|
||||
self.assertEqual(expected_vr, obtained_vr)
|
||||
self.assertIn(osclients, self.test_test_class._validation_resources)
|
||||
self.assertEqual(expected_vr,
|
||||
self.test_test_class._validation_resources[osclients])
|
||||
|
||||
def test_validation_resources_invalid_config(self):
|
||||
invalid_version = 999
|
||||
cfg.CONF.set_default('run_validation', True, 'validation')
|
||||
cfg.CONF.set_default('ip_version_for_ssh', invalid_version,
|
||||
'validation')
|
||||
cfg.CONF.set_default('neutron', True, 'service_available')
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
with testtools.ExpectedException(
|
||||
lib_exc.InvalidConfiguration,
|
||||
value_re='^.*\n.*' + str(invalid_version)):
|
||||
self.test_test_class.get_class_validation_resources(osclients)
|
||||
|
||||
@mock.patch(validation_resources_module + '.create_validation_resources',
|
||||
autospec=True)
|
||||
def test_validation_resources_invalid_config_nova_net(self,
|
||||
mock_create_vr):
|
||||
invalid_version = 999
|
||||
cfg.CONF.set_default('run_validation', True, 'validation')
|
||||
cfg.CONF.set_default('ip_version_for_ssh', invalid_version,
|
||||
'validation')
|
||||
cfg.CONF.set_default('neutron', False, 'service_available')
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
expected_vr = {'expected_validation_resources': None}
|
||||
mock_create_vr.return_value = expected_vr
|
||||
obtained_vr = self.test_test_class.get_class_validation_resources(
|
||||
osclients)
|
||||
self.assertEqual(mock_create_vr.call_count, 1)
|
||||
self.assertIn(osclients, mock_create_vr.call_args_list[0][0])
|
||||
self.assertEqual(expected_vr, obtained_vr)
|
||||
self.assertIn(osclients, self.test_test_class._validation_resources)
|
||||
self.assertEqual(expected_vr,
|
||||
self.test_test_class._validation_resources[osclients])
|
||||
|
||||
@mock.patch(validation_resources_module + '.create_validation_resources',
|
||||
autospec=True)
|
||||
@mock.patch(validation_resources_module + '.clear_validation_resources',
|
||||
autospec=True)
|
||||
def test_validation_resources_fixture(self, mock_clean_vr, mock_create_vr):
|
||||
|
||||
class TestWithRun(self.test_test_class):
|
||||
|
||||
def runTest(self):
|
||||
pass
|
||||
|
||||
cfg.CONF.set_default('run_validation', True, 'validation')
|
||||
test_case = TestWithRun()
|
||||
creds = fake_credentials.FakeKeystoneV3Credentials()
|
||||
osclients = clients.Manager(creds)
|
||||
test_case.get_test_validation_resources(osclients)
|
||||
self.assertEqual(1, mock_create_vr.call_count)
|
||||
self.assertEqual(0, mock_clean_vr.call_count)
|
||||
|
||||
|
||||
class TestTempestBaseTestClass(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -56,26 +176,16 @@ class TestTempestBaseTestClass(base.TestCase):
|
||||
|
||||
self.parent_test = ParentTest
|
||||
|
||||
@mock.patch(
|
||||
'tempest.common.validation_resources.clear_validation_resources',
|
||||
autospec=True)
|
||||
def test_resource_cleanup(self, mock_vr):
|
||||
def test_resource_cleanup(self):
|
||||
cfg.CONF.set_default('neutron', False, 'service_available')
|
||||
exp_args = (1, 2,)
|
||||
exp_kwargs = {'a': 1, 'b': 2}
|
||||
exp_vr = {'keypair': 'kp1', 'floating_ip': 'fip2'}
|
||||
mock1 = mock.Mock()
|
||||
mock2 = mock.Mock()
|
||||
exp_functions = [mock1, mock2]
|
||||
|
||||
class TestWithCleanups(self.parent_test):
|
||||
|
||||
# set fake validation resources
|
||||
validation_resources = exp_vr
|
||||
|
||||
# set fake clients
|
||||
os_primary = 'os_primary'
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
for fn in exp_functions:
|
||||
@ -92,34 +202,22 @@ class TestTempestBaseTestClass(base.TestCase):
|
||||
# All stacked resource cleanups invoked
|
||||
mock1.assert_called_once_with(*exp_args, **exp_kwargs)
|
||||
mock2.assert_called_once_with(*exp_args, **exp_kwargs)
|
||||
self.assertEqual(1, mock_vr.call_count)
|
||||
# Cleanup stack is empty
|
||||
self.assertEqual(0, len(test_cleanups._class_cleanups))
|
||||
# Assert vrs are cleaned up
|
||||
self.assertIn(mock.call(TestWithCleanups.os_primary, use_neutron=False,
|
||||
**exp_vr), mock_vr.call_args_list)
|
||||
|
||||
@mock.patch(
|
||||
'tempest.common.validation_resources.clear_validation_resources',
|
||||
autospec=True)
|
||||
def test_resource_cleanup_failures(self, mock_vr):
|
||||
def test_resource_cleanup_failures(self):
|
||||
cfg.CONF.set_default('neutron', False, 'service_available')
|
||||
exp_args = (1, 2,)
|
||||
exp_kwargs = {'a': 1, 'b': 2}
|
||||
exp_vr = {'keypair': 'kp1', 'floating_ip': 'fip2'}
|
||||
mock1 = mock.Mock()
|
||||
mock1.side_effect = Exception('mock1 resource cleanup failure')
|
||||
mock2 = mock.Mock()
|
||||
exp_functions = [mock1, mock2]
|
||||
mock3 = mock.Mock()
|
||||
mock3.side_effect = Exception('mock3 resource cleanup failure')
|
||||
exp_functions = [mock1, mock2, mock3]
|
||||
|
||||
class TestWithFailingCleanups(self.parent_test):
|
||||
|
||||
# set fake validation resources
|
||||
validation_resources = exp_vr
|
||||
|
||||
# set fake clients
|
||||
os_primary = 'os_primary'
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
for fn in exp_functions:
|
||||
@ -137,19 +235,15 @@ class TestTempestBaseTestClass(base.TestCase):
|
||||
# Type, Exception, traceback [1] -> MultipleException
|
||||
found_exc = log[0][1][1]
|
||||
self.assertTrue(isinstance(found_exc, testtools.MultipleExceptions))
|
||||
self.assertEqual(1, len(found_exc.args))
|
||||
self.assertEqual(2, len(found_exc.args))
|
||||
# Each arg is exc_info - match messages and order
|
||||
self.assertIn('mock1 resource', str(found_exc.args[0][1]))
|
||||
self.assertIn('mock3 resource', str(found_exc.args[0][1]))
|
||||
self.assertIn('mock1 resource', str(found_exc.args[1][1]))
|
||||
# All stacked resource cleanups invoked
|
||||
mock1.assert_called_once_with(*exp_args, **exp_kwargs)
|
||||
mock2.assert_called_once_with(*exp_args, **exp_kwargs)
|
||||
self.assertEqual(1, mock_vr.call_count)
|
||||
# Cleanup stack is empty
|
||||
self.assertEqual(0, len(test_cleanups._class_cleanups))
|
||||
# Assert fake vr are cleaned up
|
||||
self.assertIn(mock.call(TestWithFailingCleanups.os_primary,
|
||||
use_neutron=False, **exp_vr),
|
||||
mock_vr.call_args_list)
|
||||
|
||||
def test_super_resource_cleanup_not_invoked(self):
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user