blob: d8474a020779cf153adc295e0e4cef2a6d20b8b7 [file] [log] [blame]
Attila Fazekas0abbc952013-07-01 19:19:42 +02001# Licensed under the Apache License, Version 2.0 (the "License"); you may
2# not use this file except in compliance with the License. You may obtain
3# a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10# License for the specific language governing permissions and limitations
11# under the License.
12
13
14import time
15
Matt Riedemann128c23e2014-05-02 13:46:39 -070016from tempest.common.utils import misc as misc_utils
Attila Fazekas0abbc952013-07-01 19:19:42 +020017from tempest import config
18from tempest import exceptions
19from tempest.openstack.common import log as logging
20
Sean Dague86bd8422013-12-20 09:56:44 -050021CONF = config.CONF
Attila Fazekas0abbc952013-07-01 19:19:42 +020022LOG = logging.getLogger(__name__)
23
24
Sean Daguec1a3bbe2014-06-04 10:49:09 -040025def _console_dump(client, server_id):
26 try:
27 resp, output = client.get_console_output(server_id, None)
28 LOG.debug("Console Output for Server %s:\n%s" % (
29 server_id, output))
30 except exceptions.NotFound:
31 LOG.debug("Server %s: doesn't have a console" % server_id)
32 pass
33
34
Attila Fazekas0abbc952013-07-01 19:19:42 +020035# NOTE(afazekas): This function needs to know a token and a subject.
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090036def wait_for_server_status(client, server_id, status, ready_wait=True,
Zhi Kun Liue5401762013-09-11 20:45:48 +080037 extra_timeout=0, raise_on_error=True):
Attila Fazekas0abbc952013-07-01 19:19:42 +020038 """Waits for a server to reach a given status."""
39
40 def _get_task_state(body):
ivan-zhu2ca89b32013-08-07 22:37:32 +080041 if client.service == CONF.compute.catalog_v3_type:
42 task_state = body.get("os-extended-status:task_state", None)
43 else:
44 task_state = body.get('OS-EXT-STS:task_state', None)
Attila Fazekas0abbc952013-07-01 19:19:42 +020045 return task_state
46
47 # NOTE(afazekas): UNKNOWN status possible on ERROR
48 # or in a very early stage.
49 resp, body = client.get_server(server_id)
50 old_status = server_status = body['status']
51 old_task_state = task_state = _get_task_state(body)
52 start_time = int(time.time())
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090053 timeout = client.build_timeout + extra_timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020054 while True:
55 # NOTE(afazekas): Now the BUILD status only reached
Shane Wang111f86c2014-02-20 16:40:22 +080056 # between the UNKNOWN->ACTIVE transition.
Attila Fazekas0abbc952013-07-01 19:19:42 +020057 # TODO(afazekas): enumerate and validate the stable status set
58 if status == 'BUILD' and server_status != 'UNKNOWN':
59 return
60 if server_status == status:
61 if ready_wait:
62 if status == 'BUILD':
63 return
64 # NOTE(afazekas): The instance is in "ready for action state"
65 # when no task in progress
66 # NOTE(afazekas): Converted to string bacuse of the XML
67 # responses
68 if str(task_state) == "None":
69 # without state api extension 3 sec usually enough
Sean Dague86bd8422013-12-20 09:56:44 -050070 time.sleep(CONF.compute.ready_wait)
Attila Fazekas0abbc952013-07-01 19:19:42 +020071 return
72 else:
73 return
74
75 time.sleep(client.build_interval)
76 resp, body = client.get_server(server_id)
77 server_status = body['status']
78 task_state = _get_task_state(body)
79 if (server_status != old_status) or (task_state != old_task_state):
80 LOG.info('State transition "%s" ==> "%s" after %d second wait',
81 '/'.join((old_status, str(old_task_state))),
82 '/'.join((server_status, str(task_state))),
83 time.time() - start_time)
Sean Daguec1a3bbe2014-06-04 10:49:09 -040084
Zhi Kun Liue5401762013-09-11 20:45:48 +080085 if (server_status == 'ERROR') and raise_on_error:
Sean Daguec1a3bbe2014-06-04 10:49:09 -040086 _console_dump(client, server_id)
Attila Fazekas0abbc952013-07-01 19:19:42 +020087 raise exceptions.BuildErrorException(server_id=server_id)
88
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090089 timed_out = int(time.time()) - start_time >= timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020090
91 if timed_out:
Matt Riedemann629fa7c2013-12-11 18:20:56 -080092 expected_task_state = 'None' if ready_wait else 'n/a'
93 message = ('Server %(server_id)s failed to reach %(status)s '
94 'status and task state "%(expected_task_state)s" '
95 'within the required time (%(timeout)s s).' %
96 {'server_id': server_id,
97 'status': status,
98 'expected_task_state': expected_task_state,
99 'timeout': timeout})
Attila Fazekas0abbc952013-07-01 19:19:42 +0200100 message += ' Current status: %s.' % server_status
Matt Riedemann629fa7c2013-12-11 18:20:56 -0800101 message += ' Current task state: %s.' % task_state
Sean Daguec1a3bbe2014-06-04 10:49:09 -0400102
Matt Riedemann128c23e2014-05-02 13:46:39 -0700103 caller = misc_utils.find_test_caller()
104 if caller:
105 message = '(%s) %s' % (caller, message)
Sean Daguec1a3bbe2014-06-04 10:49:09 -0400106 _console_dump(client, server_id)
Attila Fazekas0abbc952013-07-01 19:19:42 +0200107 raise exceptions.TimeoutException(message)
108 old_status = server_status
109 old_task_state = task_state
Matt Riedemannc00f3262013-12-14 12:03:55 -0800110
111
112def wait_for_image_status(client, image_id, status):
113 """Waits for an image to reach a given status.
114
115 The client should have a get_image(image_id) method to get the image.
116 The client should also have build_interval and build_timeout attributes.
117 """
118 resp, image = client.get_image(image_id)
119 start = int(time.time())
120
121 while image['status'] != status:
122 time.sleep(client.build_interval)
123 resp, image = client.get_image(image_id)
124 if image['status'] == 'ERROR':
125 raise exceptions.AddImageException(image_id=image_id)
126
127 # check the status again to avoid a false negative where we hit
128 # the timeout at the same time that the image reached the expected
129 # status
130 if image['status'] == status:
131 return
132
133 if int(time.time()) - start >= client.build_timeout:
134 message = ('Image %(image_id)s failed to reach %(status)s '
135 'status within the required time (%(timeout)s s).' %
136 {'image_id': image_id,
137 'status': status,
138 'timeout': client.build_timeout})
139 message += ' Current status: %s.' % image['status']
Matt Riedemann128c23e2014-05-02 13:46:39 -0700140 caller = misc_utils.find_test_caller()
141 if caller:
142 message = '(%s) %s' % (caller, message)
Matt Riedemannc00f3262013-12-14 12:03:55 -0800143 raise exceptions.TimeoutException(message)