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