Merge "[Trivial]Do not use cls in instance method"
diff --git a/.zuul.yaml b/.zuul.yaml
index 23fc72d..c20f204 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -671,6 +671,9 @@
- tempest-full-py3-ipv6:
voting: false
irrelevant-files: *tempest-irrelevant-files
+ - glance-multistore-cinder-import:
+ voting: false
+ irrelevant-files: *tempest-irrelevant-files
- tempest-full-victoria-py3:
irrelevant-files: *tempest-irrelevant-files
- tempest-full-ussuri-py3:
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index 5445113..c222893 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -16,6 +16,7 @@
import testtools
from tempest.api.compute import base
+from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -189,6 +190,7 @@
self._test_stable_device_rescue(server_id, rescue_image_id)
@decorators.idempotent_id('a3772b42-00bf-4310-a90b-1cc6fd3e7eab')
+ @utils.services('volume')
def test_stable_device_rescue_disk_virtio_with_volume_attached(self):
"""Test rescuing server with volume attached
@@ -214,6 +216,13 @@
min_microversion = '2.87'
+ @classmethod
+ def skip_checks(cls):
+ super(ServerBootFromVolumeStableRescueTest, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
@decorators.attr(type='slow')
@decorators.idempotent_id('48f123cb-922a-4065-8db6-b9a9074a556b')
def test_stable_device_rescue_bfv_blank_volume(self):
diff --git a/tempest/common/compute.py b/tempest/common/compute.py
index edb9d16..da3a4a9 100644
--- a/tempest/common/compute.py
+++ b/tempest/common/compute.py
@@ -64,7 +64,7 @@
def create_test_server(clients, validatable=False, validation_resources=None,
tenant_network=None, wait_until=None,
volume_backed=False, name=None, flavor=None,
- image_id=None, **kwargs):
+ image_id=None, wait_for_sshable=True, **kwargs):
"""Common wrapper utility returning a test server.
This method is a common wrapper returning a test server that can be
@@ -100,6 +100,8 @@
CONF.compute.flavor_ref will be used instead.
:param image_id: ID of the image to be used to provision the server. If not
defined, CONF.compute.image_ref will be used instead.
+ :param wait_for_sshable: Check server's console log and wait until it will
+ be ready to login.
:returns: a tuple
"""
@@ -270,6 +272,10 @@
LOG.exception('Server %s failed to delete in time',
server['id'])
+ if (validatable and CONF.compute_feature_enabled.console_output and
+ wait_for_sshable):
+ waiters.wait_for_guest_os_boot(clients.servers_client, server['id'])
+
return body, servers
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 789daaf..17796df 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -437,3 +437,20 @@
'the required time (%s s)' % (port_id, server_id,
client.build_timeout))
raise lib_exc.TimeoutException(message)
+
+
+def wait_for_guest_os_boot(client, server_id):
+ start_time = int(time.time())
+ while True:
+ console_output = client.get_console_output(server_id)['output']
+ for line in console_output.split('\n'):
+ if 'login:' in line.lower():
+ return
+ if int(time.time()) - start_time >= client.build_timeout:
+ LOG.info("Guest OS on server %s probably isn't ready or its "
+ "console log can't be parsed properly. If guest OS "
+ "isn't ready, that may cause problems with SSH to "
+ "the server.",
+ server_id)
+ return
+ time.sleep(client.build_interval)
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 73924bd..f03c7cc 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -131,6 +131,36 @@
mock.call('server_id')])
sleep.assert_called_once_with(client.build_interval)
+ def test_wait_for_guest_os_boot(self):
+ get_console_output = mock.Mock(
+ side_effect=[
+ {'output': 'os not ready yet\n'},
+ {'output': 'login:\n'}
+ ])
+ client = self.mock_client(get_console_output=get_console_output)
+ self.patch('time.time', return_value=0.)
+ sleep = self.patch('time.sleep')
+
+ with mock.patch.object(waiters.LOG, "info") as log_info:
+ waiters.wait_for_guest_os_boot(client, 'server_id')
+
+ get_console_output.assert_has_calls([
+ mock.call('server_id'), mock.call('server_id')])
+ sleep.assert_called_once_with(client.build_interval)
+ log_info.assert_not_called()
+
+ def test_wait_for_guest_os_boot_timeout(self):
+ get_console_output = mock.Mock(
+ return_value={'output': 'os not ready yet\n'})
+ client = self.mock_client(get_console_output=get_console_output)
+ self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
+ self.patch('time.sleep')
+
+ with mock.patch.object(waiters.LOG, "info") as log_info:
+ waiters.wait_for_guest_os_boot(client, 'server_id')
+
+ log_info.assert_called_once()
+
class TestVolumeWaiters(base.TestCase):
vol_migrating_src_host = {