blob: d2b40c9ab48876ab769e626dff811f0774196211 [file] [log] [blame]
Attila Fazekas0abbc952013-07-01 19:19:42 +02001# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15
16import time
17
18from tempest import config
19from tempest import exceptions
20from tempest.openstack.common import log as logging
21
22CONFIG = config.TempestConfig()
23LOG = logging.getLogger(__name__)
24
25
26# NOTE(afazekas): This function needs to know a token and a subject.
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090027def wait_for_server_status(client, server_id, status, ready_wait=True,
Zhi Kun Liue5401762013-09-11 20:45:48 +080028 extra_timeout=0, raise_on_error=True):
Attila Fazekas0abbc952013-07-01 19:19:42 +020029 """Waits for a server to reach a given status."""
30
31 def _get_task_state(body):
32 task_state = body.get('OS-EXT-STS:task_state', None)
33 return task_state
34
35 # NOTE(afazekas): UNKNOWN status possible on ERROR
36 # or in a very early stage.
37 resp, body = client.get_server(server_id)
38 old_status = server_status = body['status']
39 old_task_state = task_state = _get_task_state(body)
40 start_time = int(time.time())
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090041 timeout = client.build_timeout + extra_timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020042 while True:
43 # NOTE(afazekas): Now the BUILD status only reached
44 # between the UNKOWN->ACTIVE transition.
45 # TODO(afazekas): enumerate and validate the stable status set
46 if status == 'BUILD' and server_status != 'UNKNOWN':
47 return
48 if server_status == status:
49 if ready_wait:
50 if status == 'BUILD':
51 return
52 # NOTE(afazekas): The instance is in "ready for action state"
53 # when no task in progress
54 # NOTE(afazekas): Converted to string bacuse of the XML
55 # responses
56 if str(task_state) == "None":
57 # without state api extension 3 sec usually enough
58 time.sleep(CONFIG.compute.ready_wait)
59 return
60 else:
61 return
62
63 time.sleep(client.build_interval)
64 resp, body = client.get_server(server_id)
65 server_status = body['status']
66 task_state = _get_task_state(body)
67 if (server_status != old_status) or (task_state != old_task_state):
68 LOG.info('State transition "%s" ==> "%s" after %d second wait',
69 '/'.join((old_status, str(old_task_state))),
70 '/'.join((server_status, str(task_state))),
71 time.time() - start_time)
Zhi Kun Liue5401762013-09-11 20:45:48 +080072 if (server_status == 'ERROR') and raise_on_error:
Attila Fazekas0abbc952013-07-01 19:19:42 +020073 raise exceptions.BuildErrorException(server_id=server_id)
74
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090075 timed_out = int(time.time()) - start_time >= timeout
Attila Fazekas0abbc952013-07-01 19:19:42 +020076
77 if timed_out:
Matt Riedemann629fa7c2013-12-11 18:20:56 -080078 expected_task_state = 'None' if ready_wait else 'n/a'
79 message = ('Server %(server_id)s failed to reach %(status)s '
80 'status and task state "%(expected_task_state)s" '
81 'within the required time (%(timeout)s s).' %
82 {'server_id': server_id,
83 'status': status,
84 'expected_task_state': expected_task_state,
85 'timeout': timeout})
Attila Fazekas0abbc952013-07-01 19:19:42 +020086 message += ' Current status: %s.' % server_status
Matt Riedemann629fa7c2013-12-11 18:20:56 -080087 message += ' Current task state: %s.' % task_state
Attila Fazekas0abbc952013-07-01 19:19:42 +020088 raise exceptions.TimeoutException(message)
89 old_status = server_status
90 old_task_state = task_state
Matt Riedemannc00f3262013-12-14 12:03:55 -080091
92
93def wait_for_image_status(client, image_id, status):
94 """Waits for an image to reach a given status.
95
96 The client should have a get_image(image_id) method to get the image.
97 The client should also have build_interval and build_timeout attributes.
98 """
99 resp, image = client.get_image(image_id)
100 start = int(time.time())
101
102 while image['status'] != status:
103 time.sleep(client.build_interval)
104 resp, image = client.get_image(image_id)
105 if image['status'] == 'ERROR':
106 raise exceptions.AddImageException(image_id=image_id)
107
108 # check the status again to avoid a false negative where we hit
109 # the timeout at the same time that the image reached the expected
110 # status
111 if image['status'] == status:
112 return
113
114 if int(time.time()) - start >= client.build_timeout:
115 message = ('Image %(image_id)s failed to reach %(status)s '
116 'status within the required time (%(timeout)s s).' %
117 {'image_id': image_id,
118 'status': status,
119 'timeout': client.build_timeout})
120 message += ' Current status: %s.' % image['status']
121 raise exceptions.TimeoutException(message)