Merge "Fix for volume manage test" into mcp/epoxy
diff --git a/tempest/api/compute/admin/test_create_server.py b/tempest/api/compute/admin/test_create_server.py
index 5bc9206..3cc2928 100644
--- a/tempest/api/compute/admin/test_create_server.py
+++ b/tempest/api/compute/admin/test_create_server.py
@@ -151,6 +151,9 @@
super(ServersTestUEFI, cls).setup_clients()
cls.client = cls.servers_client
+ @testtools.skipIf(
+ CONF.compute_feature_enabled.barbican_integration_enabled,
+ "Not supported when barbican integration enabled.")
@decorators.idempotent_id('94feb6c3-d07e-b3b9-def8-64fd082d9b21')
def test_created_server_uefi(self):
# create custom image with uefi type
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 24b3ee4..22cb732 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -36,6 +36,10 @@
raise cls.skipException("Cinder is not available")
if not CONF.compute_feature_enabled.swap_volume:
raise cls.skipException("Swapping volumes is not supported.")
+ if CONF.compute_feature_enabled.attach_encrypted_volume:
+ raise cls.skipException(
+ 'Volume swap is not available for OS configurations '
+ 'with crypted volumes.')
def wait_for_server_volume_swap(self, server_id, old_volume_id,
new_volume_id):
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index d6c0324..9404ebd 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -74,6 +74,7 @@
class ServerRescueTestJSONUnderV235(ServerRescueTestBase):
"""Test server rescue with compute microversion less than 2.36"""
+ min_microversion = '2.1'
max_microversion = '2.35'
# TODO(zhufl): After 2.35 we should switch to neutron client to create
@@ -123,6 +124,9 @@
if not CONF.compute_feature_enabled.stable_rescue:
msg = "Stable rescue not available."
raise cls.skipException(msg)
+ if CONF.compute_feature_enabled.barbican_integration_enabled:
+ msg = "Rescue not supported with barbican integration."
+ raise cls.skipException(msg)
@classmethod
def setup_credentials(cls):
diff --git a/tempest/api/image/v2/admin/test_images.py b/tempest/api/image/v2/admin/test_images.py
index 2c2e9a8..b380f11 100644
--- a/tempest/api/image/v2/admin/test_images.py
+++ b/tempest/api/image/v2/admin/test_images.py
@@ -105,7 +105,7 @@
# NOTE(gmann): Skip if copy-image import method and multistore
# are not available.
if ('copy-image' not in available_import_methods or
- not available_stores):
+ len(available_stores) < 2):
raise self.skipException('Either copy-image import method or '
'multistore is not available')
uuid = data_utils.rand_uuid()
diff --git a/tempest/config.py b/tempest/config.py
index 9196a27..2e51eb3 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -303,6 +303,15 @@
help="Valid secondary image reference to be used in tests. "
"This is a required option, but if only one image is "
"available duplicate the value of image_ref above"),
+ cfg.StrOpt('image_full_ref',
+ help="This is image with full OS like ubuntu/centos used"
+ "in some tests. When not set related tests will be "
+ "skipped"),
+ cfg.StrOpt('image_full_username',
+ default="ubuntu",
+ help="Username for image_full_ref authentication."),
+ cfg.StrOpt('image_full_flavor_ref',
+ help="Flavor to boot image_full_ref."),
cfg.StrOpt('certified_image_ref',
help="Valid image reference to be used in image certificate "
"validation tests when enabled. This image must also "
diff --git a/tempest/lib/api_schema/response/compute/v2_19/servers.py b/tempest/lib/api_schema/response/compute/v2_19/servers.py
index ba3d787..5d1f315 100644
--- a/tempest/lib/api_schema/response/compute/v2_19/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_19/servers.py
@@ -14,9 +14,12 @@
import copy
+from tempest.lib.api_schema.response.compute.v2_1 import servers \
+ as servers
from tempest.lib.api_schema.response.compute.v2_16 import servers \
as serversv216
+
# Compute microversion 2.19:
# 1. New attributes in 'server' dict.
# 'description'
@@ -63,3 +66,4 @@
list_volume_attachments = copy.deepcopy(serversv216.list_volume_attachments)
show_instance_action = copy.deepcopy(serversv216.show_instance_action)
create_backup = copy.deepcopy(serversv216.create_backup)
+list_instance_actions = copy.deepcopy(servers.list_instance_actions)
diff --git a/tempest/lib/api_schema/response/compute/v2_58/servers.py b/tempest/lib/api_schema/response/compute/v2_58/servers.py
index 637b765..5c22c79 100644
--- a/tempest/lib/api_schema/response/compute/v2_58/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_58/servers.py
@@ -12,8 +12,10 @@
import copy
from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
+from tempest.lib.api_schema.response.compute.v2_1 import servers as servers
from tempest.lib.api_schema.response.compute.v2_57 import servers as servers257
+
# microversion 2.58 added updated_at to the response
show_instance_action = copy.deepcopy(servers257.show_instance_action)
show_instance_action['response_body']['properties']['instanceAction'][
@@ -21,6 +23,14 @@
show_instance_action['response_body']['properties']['instanceAction'][
'required'].append('updated_at')
+# microversion 2.58 added updated_at to the response
+list_instance_actions = copy.deepcopy(servers.list_instance_actions)
+list_instance_actions['response_body']['properties']['instanceActions'][
+ 'items']['properties'].update({'updated_at': parameter_types.date_time})
+list_instance_actions['response_body']['properties']['instanceActions'][
+ 'items']['required'].append('updated_at')
+
+
# Below are the unchanged schema in this microversion. We need
# to keep this schema in this file to have the generic way to select the
# right schema based on self.schema_versions_info mapping in service client.
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index f73045f..4c91599 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -746,6 +746,8 @@
resp, body = self.get("servers/%s/os-instance-actions" %
server_id)
body = json.loads(body)
+ # select proper schema depending on microverion
+ schema = self.get_schema(self.schema_versions_info)
self.validate_response(schema.list_instance_actions, resp, body)
return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index afd63a2..feb2cf1 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -802,7 +802,20 @@
linux_client = remote_client.RemoteClient(
ip_address, username, pkey=private_key, password=password,
server=server, servers_client=self.servers_client)
- linux_client.validate_authentication()
+ try:
+ linux_client.validate_authentication()
+ except Exception as e:
+ message = ('Initializing SSH connection to %(ip)s failed. '
+ 'Error: %(error)s' % {'ip': ip_address,
+ 'error': e})
+ caller = test_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ LOG.exception(message)
+ servers = (server,) if server else None
+ self.log_console_output(servers=servers)
+ raise
+
return linux_client
def image_create(self, name='scenario-img', **kwargs):
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index fb68e46..23e5ae6 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -239,6 +239,26 @@
network=self.new_net,
gateway_ip=None)
+ def _assign_nic_ip_address_by_port(self, ssh_client, port, device):
+ ip_output = ssh_client.exec_command('ip a')
+ ip_address = port['fixed_ips'][0]['ip_address']
+ ip_mask = CONF.network.project_network_mask_bits
+ # check if the address is not already in use, if not, set it
+ if ' ' + ip_address + '/' + str(ip_mask) not in ip_output:
+ try:
+ ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
+ ip_address, ip_mask, device))
+ ssh_client.exec_command("sudo ip link set %s up" % device)
+ except exceptions.SSHExecCommandFailed as exc:
+ if 'RTNETLINK answers: File exists' in str(exc):
+ LOG.debug(
+ 'IP address %(ip_address)s is already set in device '
+ '%(device)s\nPrevious "ip a" output: %(ip_output)s',
+ {'ip_address': ip_address, 'device': device,
+ 'ip_output': ip_output})
+ else:
+ raise exc
+
def _hotplug_server(self):
old_floating_ip, server = self.floating_ip_tuple
ip_address = old_floating_ip['floating_ip_address']
@@ -292,24 +312,7 @@
% CONF.network.build_timeout)
_, new_nic = self.diff_list[0]
- ip_output = ssh_client.exec_command('ip a')
- ip_address = new_port['fixed_ips'][0]['ip_address']
- ip_mask = CONF.network.project_network_mask_bits
- # check if the address is not already in use, if not, set it
- if ' ' + ip_address + '/' + str(ip_mask) not in ip_output:
- try:
- ssh_client.exec_command("sudo ip addr add %s/%s dev %s" % (
- ip_address, ip_mask, new_nic))
- ssh_client.exec_command("sudo ip link set %s up" % new_nic)
- except exceptions.SSHExecCommandFailed as exc:
- if 'RTNETLINK answers: File exists' in str(exc):
- LOG.debug(
- 'IP address %(ip_address)s is already set in device '
- '%(device)s\nPrevious "ip a" output: %(ip_output)s',
- {'ip_address': ip_address, 'device': new_nic,
- 'ip_output': ip_output})
- else:
- raise exc
+ self._assign_nic_ip_address_by_port(ssh_client, new_port, new_nic)
def _get_server_nics(self, ssh_client):
reg = re.compile(r'(?P<num>\d+): (?P<nic_name>\w+)[@]?.*:')
@@ -911,6 +914,7 @@
).format(ip_address=ip_address, nic=spoof_nic)
ssh_client.exec_command(cmd)
+ self._assign_nic_ip_address_by_port(ssh_client, spoof_port, spoof_nic)
new_mac = ssh_client.get_mac_address(nic=spoof_nic)
self.assertEqual(spoof_mac, new_mac)
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index d04cb9a..db8f533 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -41,6 +41,11 @@
super(TestSnapshotPattern, cls).skip_checks()
if not CONF.compute_feature_enabled.snapshot:
raise cls.skipException("Snapshotting is not available.")
+ if not all([CONF.compute.image_full_ref,
+ CONF.compute.image_full_username,
+ CONF.compute.image_full_flavor_ref]):
+ raise cls.skipException(
+ "Test requires image_full_* options to be set.")
@decorators.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
@decorators.attr(type='slow')
@@ -51,16 +56,20 @@
# prepare for booting an instance
keypair = self.create_keypair()
security_group = self.create_security_group()
+ username = CONF.compute.image_full_username
# boot an instance and create a timestamp file in it
server = self.create_server(
key_name=keypair['name'],
- security_groups=[{'name': security_group['name']}])
+ security_groups=[{'name': security_group['name']}],
+ flavor=CONF.compute.image_full_flavor_ref,
+ image_id=CONF.compute.image_full_ref)
instance_ip = self.get_server_ip(server)
timestamp = self.create_timestamp(instance_ip,
private_key=keypair['private_key'],
- server=server)
+ server=server,
+ username=username)
# snapshot the instance
snapshot_image = self.create_server_snapshot(server=server)
@@ -74,13 +83,15 @@
server_from_snapshot = self.create_server(
image_id=snapshot_image['id'],
key_name=keypair['name'],
- security_groups=[{'name': security_group['name']}])
+ security_groups=[{'name': security_group['name']}],
+ flavor=CONF.compute.image_full_flavor_ref)
# check the existence of the timestamp file in the second instance
server_from_snapshot_ip = self.get_server_ip(server_from_snapshot)
timestamp2 = self.get_timestamp(server_from_snapshot_ip,
private_key=keypair['private_key'],
- server=server_from_snapshot)
+ server=server_from_snapshot,
+ username=username)
self.assertEqual(timestamp, timestamp2)
# snapshot the instance again