blob: d242c14285fe3f4b7e75f5017a20119a3a31250a [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
25# NOTE(afazekas): This function needs to know a token and a subject.
Ken'ichi Ohmichi39437e22013-10-06 00:21:38 +090026def wait_for_server_status(client, server_id, status, ready_wait=True,
Zhi Kun Liue5401762013-09-11 20:45:48 +080027 extra_timeout=0, raise_on_error=True):
Attila Fazekas0abbc952013-07-01 19:19:42 +020028 """Waits for a server to reach a given status."""
29
30 def _get_task_state(body):
ivan-zhu2ca89b32013-08-07 22:37:32 +080031 if client.service == CONF.compute.catalog_v3_type:
32 task_state = body.get("os-extended-status:task_state", None)
33 else:
34 task_state = body.get('OS-EXT-STS:task_state', None)
Attila Fazekas0abbc952013-07-01 19:19:42 +020035 return task_state
36
37 # NOTE(afazekas): UNKNOWN status possible on ERROR
38 # or in a very early stage.
39 resp, body = client.get_server(server_id)
40 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
56 # NOTE(afazekas): Converted to string bacuse of the XML
57 # 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)
66 resp, body = client.get_server(server_id)
67 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'],
77 server_id=server_id)
78 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
102def wait_for_image_status(client, image_id, status):
103 """Waits for an image to reach a given status.
104
105 The client should have a get_image(image_id) method to get the image.
106 The client should also have build_interval and build_timeout attributes.
107 """
108 resp, image = client.get_image(image_id)
109 start = int(time.time())
110
111 while image['status'] != status:
112 time.sleep(client.build_interval)
113 resp, image = client.get_image(image_id)
114 if image['status'] == 'ERROR':
115 raise exceptions.AddImageException(image_id=image_id)
116
117 # check the status again to avoid a false negative where we hit
118 # the timeout at the same time that the image reached the expected
119 # status
120 if image['status'] == status:
121 return
122
123 if int(time.time()) - start >= client.build_timeout:
124 message = ('Image %(image_id)s failed to reach %(status)s '
125 'status within the required time (%(timeout)s s).' %
126 {'image_id': image_id,
127 'status': status,
128 'timeout': client.build_timeout})
129 message += ' Current status: %s.' % image['status']
Matt Riedemann128c23e2014-05-02 13:46:39 -0700130 caller = misc_utils.find_test_caller()
131 if caller:
132 message = '(%s) %s' % (caller, message)
Matt Riedemannc00f3262013-12-14 12:03:55 -0800133 raise exceptions.TimeoutException(message)