blob: d8dad694df56e10c60bba6c9ae169828e73fd5ef [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
Doug Hellmann583ce2c2015-03-11 14:55:46 +000016from oslo_log import log as logging
Matthew Treinish01472ff2015-02-20 17:26:52 -050017
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -070018from tempest.common import image as common_image
Attila Fazekas0abbc952013-07-01 19:19:42 +020019from tempest import config
20from tempest import exceptions
Andrea Frittoli (andreaf)db9672e2016-02-23 14:07:24 -050021from tempest.lib.common.utils import misc as misc_utils
22from tempest.lib import exceptions as lib_exc
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +030023from tempest.services.image.v1.json import images_client as images_v1_client
Attila Fazekas0abbc952013-07-01 19:19:42 +020024
Sean Dague86bd8422013-12-20 09:56:44 -050025CONF = config.CONF
Attila Fazekas0abbc952013-07-01 19:19:42 +020026LOG = logging.getLogger(__name__)
27
28
29# NOTE(afazekas): This function needs to know a token and a subject.
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090030def wait_for_server_status(client, server_id, status, ready_wait=True,
Zhi Kun Liue5401762013-09-11 20:45:48 +080031 extra_timeout=0, raise_on_error=True):
Attila Fazekas0abbc952013-07-01 19:19:42 +020032 """Waits for a server to reach a given status."""
33
34 def _get_task_state(body):
Ken'ichi Ohmichia58c1562014-12-15 00:39:55 +000035 return body.get('OS-EXT-STS:task_state', None)
Attila Fazekas0abbc952013-07-01 19:19:42 +020036
37 # NOTE(afazekas): UNKNOWN status possible on ERROR
38 # or in a very early stage.
ghanshyam0f825252015-08-25 16:02:50 +090039 body = client.show_server(server_id)['server']
Attila Fazekas0abbc952013-07-01 19:19:42 +020040 old_status = server_status = body['status']
41 old_task_state = task_state = _get_task_state(body)
42 start_time = int(time.time())
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090043 timeout = client.build_timeout + extra_timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020044 while True:
45 # NOTE(afazekas): Now the BUILD status only reached
Shane Wang111f86c2014-02-20 16:40:22 +080046 # between the UNKNOWN->ACTIVE transition.
Attila Fazekas0abbc952013-07-01 19:19:42 +020047 # TODO(afazekas): enumerate and validate the stable status set
48 if status == 'BUILD' and server_status != 'UNKNOWN':
49 return
50 if server_status == status:
51 if ready_wait:
52 if status == 'BUILD':
53 return
54 # NOTE(afazekas): The instance is in "ready for action state"
55 # when no task in progress
nayna-patelfdc87a52015-08-03 10:46:33 +000056 # NOTE(afazekas): Converted to string because of the XML
Attila Fazekas0abbc952013-07-01 19:19:42 +020057 # responses
58 if str(task_state) == "None":
59 # without state api extension 3 sec usually enough
Sean Dague86bd8422013-12-20 09:56:44 -050060 time.sleep(CONF.compute.ready_wait)
Attila Fazekas0abbc952013-07-01 19:19:42 +020061 return
62 else:
63 return
64
65 time.sleep(client.build_interval)
ghanshyam0f825252015-08-25 16:02:50 +090066 body = client.show_server(server_id)['server']
Attila Fazekas0abbc952013-07-01 19:19:42 +020067 server_status = body['status']
68 task_state = _get_task_state(body)
69 if (server_status != old_status) or (task_state != old_task_state):
70 LOG.info('State transition "%s" ==> "%s" after %d second wait',
71 '/'.join((old_status, str(old_task_state))),
72 '/'.join((server_status, str(task_state))),
73 time.time() - start_time)
Zhi Kun Liue5401762013-09-11 20:45:48 +080074 if (server_status == 'ERROR') and raise_on_error:
Attila Fazekas0462a7f2014-06-20 07:38:06 +020075 if 'fault' in body:
76 raise exceptions.BuildErrorException(body['fault'],
Matthew Treinish1d14c542014-06-17 20:25:40 -040077 server_id=server_id)
Attila Fazekas0462a7f2014-06-20 07:38:06 +020078 else:
79 raise exceptions.BuildErrorException(server_id=server_id)
Attila Fazekas0abbc952013-07-01 19:19:42 +020080
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090081 timed_out = int(time.time()) - start_time >= timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020082
83 if timed_out:
Matt Riedemann629fa7c2013-12-11 18:20:56 -080084 expected_task_state = 'None' if ready_wait else 'n/a'
85 message = ('Server %(server_id)s failed to reach %(status)s '
86 'status and task state "%(expected_task_state)s" '
87 'within the required time (%(timeout)s s).' %
88 {'server_id': server_id,
89 'status': status,
90 'expected_task_state': expected_task_state,
91 'timeout': timeout})
Attila Fazekas0abbc952013-07-01 19:19:42 +020092 message += ' Current status: %s.' % server_status
Matt Riedemann629fa7c2013-12-11 18:20:56 -080093 message += ' Current task state: %s.' % task_state
Matt Riedemann128c23e2014-05-02 13:46:39 -070094 caller = misc_utils.find_test_caller()
95 if caller:
96 message = '(%s) %s' % (caller, message)
Attila Fazekas0abbc952013-07-01 19:19:42 +020097 raise exceptions.TimeoutException(message)
98 old_status = server_status
99 old_task_state = task_state
Matt Riedemannc00f3262013-12-14 12:03:55 -0800100
101
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000102def wait_for_server_termination(client, server_id, ignore_error=False):
103 """Waits for server to reach termination."""
104 start_time = int(time.time())
105 while True:
106 try:
ghanshyam0f825252015-08-25 16:02:50 +0900107 body = client.show_server(server_id)['server']
Ken'ichi Ohmichie91a0c62015-08-13 02:09:16 +0000108 except lib_exc.NotFound:
109 return
110
111 server_status = body['status']
112 if server_status == 'ERROR' and not ignore_error:
113 raise exceptions.BuildErrorException(server_id=server_id)
114
115 if int(time.time()) - start_time >= client.build_timeout:
116 raise exceptions.TimeoutException
117
118 time.sleep(client.build_interval)
119
120
Matt Riedemannc00f3262013-12-14 12:03:55 -0800121def wait_for_image_status(client, image_id, status):
122 """Waits for an image to reach a given status.
123
Ken'ichi Ohmichi5d410762015-05-22 01:10:03 +0000124 The client should have a show_image(image_id) method to get the image.
Matt Riedemannc00f3262013-12-14 12:03:55 -0800125 The client should also have build_interval and build_timeout attributes.
126 """
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300127 if isinstance(client, images_v1_client.ImagesClient):
128 # The 'check_image' method is used here because the show_image method
129 # returns image details plus the image itself which is very expensive.
130 # The 'check_image' method returns just image details.
Ken'ichi Ohmichi01151e82016-06-10 11:19:52 -0700131 def _show_image_v1(image_id):
132 resp = client.check_image(image_id)
133 return common_image.get_image_meta_from_headers(resp)
134
135 show_image = _show_image_v1
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300136 else:
137 show_image = client.show_image
Matt Riedemannc00f3262013-12-14 12:03:55 -0800138
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300139 current_status = 'An unknown status'
140 start = int(time.time())
141 while int(time.time()) - start < client.build_timeout:
142 image = show_image(image_id)
143 # Compute image client returns response wrapped in 'image' element
144 # which is not case with Glance image client.
ghanshyam1756e0b2015-08-18 19:19:05 +0900145 if 'image' in image:
146 image = image['image']
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300147
148 current_status = image['status']
149 if current_status == status:
150 return
151 if current_status.lower() == 'killed':
152 raise exceptions.ImageKilledException(image_id=image_id,
153 status=status)
154 if current_status.lower() == 'error':
Matt Riedemannc00f3262013-12-14 12:03:55 -0800155 raise exceptions.AddImageException(image_id=image_id)
156
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300157 time.sleep(client.build_interval)
Matt Riedemannc00f3262013-12-14 12:03:55 -0800158
Yaroslav Lobankov2fea4052016-04-19 15:05:57 +0300159 message = ('Image %(image_id)s failed to reach %(status)s state '
160 '(current state %(current_status)s) within the required '
161 'time (%(timeout)s s).' % {'image_id': image_id,
162 'status': status,
163 'current_status': current_status,
164 'timeout': client.build_timeout})
165 caller = misc_utils.find_test_caller()
166 if caller:
167 message = '(%s) %s' % (caller, message)
168 raise exceptions.TimeoutException(message)
Adam Gandelman00682612014-09-02 17:10:36 -0700169
170
Ken'ichi Ohmichib942be62015-07-08 08:16:12 +0000171def wait_for_volume_status(client, volume_id, status):
172 """Waits for a Volume to reach a given status."""
ghanshyamcb131762015-08-24 18:21:08 +0900173 body = client.show_volume(volume_id)['volume']
Ken'ichi Ohmichib942be62015-07-08 08:16:12 +0000174 volume_status = body['status']
175 start = int(time.time())
176
177 while volume_status != status:
178 time.sleep(client.build_interval)
ghanshyamcb131762015-08-24 18:21:08 +0900179 body = client.show_volume(volume_id)['volume']
Ken'ichi Ohmichib942be62015-07-08 08:16:12 +0000180 volume_status = body['status']
181 if volume_status == 'error':
182 raise exceptions.VolumeBuildErrorException(volume_id=volume_id)
Matt Riedemannf77e7dc2015-08-10 16:39:39 -0700183 if volume_status == 'error_restoring':
184 raise exceptions.VolumeRestoreErrorException(volume_id=volume_id)
Ken'ichi Ohmichib942be62015-07-08 08:16:12 +0000185
186 if int(time.time()) - start >= client.build_timeout:
187 message = ('Volume %s failed to reach %s status (current %s) '
188 'within the required time (%s s).' %
189 (volume_id, status, volume_status,
190 client.build_timeout))
191 raise exceptions.TimeoutException(message)
192
193
Gaozexub9c9d6e2015-09-10 17:08:04 +0800194def wait_for_snapshot_status(client, snapshot_id, status):
195 """Waits for a Snapshot to reach a given status."""
196 body = client.show_snapshot(snapshot_id)['snapshot']
197 snapshot_status = body['status']
198 start = int(time.time())
199
200 while snapshot_status != status:
201 time.sleep(client.build_interval)
202 body = client.show_snapshot(snapshot_id)['snapshot']
203 snapshot_status = body['status']
204 if snapshot_status == 'error':
205 raise exceptions.SnapshotBuildErrorException(
206 snapshot_id=snapshot_id)
207 if int(time.time()) - start >= client.build_timeout:
208 message = ('Snapshot %s failed to reach %s status (current %s) '
209 'within the required time (%s s).' %
210 (snapshot_id, status, snapshot_status,
211 client.build_timeout))
212 raise exceptions.TimeoutException(message)
213
214
Adam Gandelman00682612014-09-02 17:10:36 -0700215def wait_for_bm_node_status(client, node_id, attr, status):
216 """Waits for a baremetal node attribute to reach given status.
217
218 The client should have a show_node(node_uuid) method to get the node.
219 """
220 _, node = client.show_node(node_id)
221 start = int(time.time())
222
223 while node[attr] != status:
224 time.sleep(client.build_interval)
225 _, node = client.show_node(node_id)
Martin Pavlasek1102c3a2014-10-20 17:17:55 +0200226 status_curr = node[attr]
227 if status_curr == status:
Adam Gandelman00682612014-09-02 17:10:36 -0700228 return
229
230 if int(time.time()) - start >= client.build_timeout:
231 message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
232 'within the required time (%(timeout)s s).' %
233 {'node_id': node_id,
234 'attr': attr,
235 'status': status,
236 'timeout': client.build_timeout})
Martin Pavlasek1102c3a2014-10-20 17:17:55 +0200237 message += ' Current state of %s: %s.' % (attr, status_curr)
Adam Gandelman00682612014-09-02 17:10:36 -0700238 caller = misc_utils.find_test_caller()
239 if caller:
240 message = '(%s) %s' % (caller, message)
241 raise exceptions.TimeoutException(message)