blob: b54ef7337030fdf8e62a71a7dcb9c08ee986d454 [file] [log] [blame]
Maru Newbyb096d9f2015-03-09 18:54:54 +00001# 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
16from neutron.tests.tempest.common.utils import misc as misc_utils
17from neutron.tests.tempest import config
18from neutron.tests.tempest import exceptions
19from neutron.openstack.common import log as logging
20
21CONF = config.CONF
22LOG = logging.getLogger(__name__)
23
24
25# NOTE(afazekas): This function needs to know a token and a subject.
26def wait_for_server_status(client, server_id, status, ready_wait=True,
27 extra_timeout=0, raise_on_error=True):
28 """Waits for a server to reach a given status."""
29
30 def _get_task_state(body):
31 return body.get('OS-EXT-STS:task_state', None)
32
33 # NOTE(afazekas): UNKNOWN status possible on ERROR
34 # or in a very early stage.
35 body = client.get_server(server_id)
36 old_status = server_status = body['status']
37 old_task_state = task_state = _get_task_state(body)
38 start_time = int(time.time())
39 timeout = client.build_timeout + extra_timeout
40 while True:
41 # NOTE(afazekas): Now the BUILD status only reached
42 # between the UNKNOWN->ACTIVE transition.
43 # TODO(afazekas): enumerate and validate the stable status set
44 if status == 'BUILD' and server_status != 'UNKNOWN':
45 return
46 if server_status == status:
47 if ready_wait:
48 if status == 'BUILD':
49 return
50 # NOTE(afazekas): The instance is in "ready for action state"
51 # when no task in progress
52 # NOTE(afazekas): Converted to string bacuse of the XML
53 # responses
54 if str(task_state) == "None":
55 # without state api extension 3 sec usually enough
56 time.sleep(CONF.compute.ready_wait)
57 return
58 else:
59 return
60
61 time.sleep(client.build_interval)
62 body = client.get_server(server_id)
63 server_status = body['status']
64 task_state = _get_task_state(body)
65 if (server_status != old_status) or (task_state != old_task_state):
66 LOG.info('State transition "%s" ==> "%s" after %d second wait',
67 '/'.join((old_status, str(old_task_state))),
68 '/'.join((server_status, str(task_state))),
69 time.time() - start_time)
70 if (server_status == 'ERROR') and raise_on_error:
71 if 'fault' in body:
72 raise exceptions.BuildErrorException(body['fault'],
73 server_id=server_id)
74 else:
75 raise exceptions.BuildErrorException(server_id=server_id)
76
77 timed_out = int(time.time()) - start_time >= timeout
78
79 if timed_out:
80 expected_task_state = 'None' if ready_wait else 'n/a'
81 message = ('Server %(server_id)s failed to reach %(status)s '
82 'status and task state "%(expected_task_state)s" '
83 'within the required time (%(timeout)s s).' %
84 {'server_id': server_id,
85 'status': status,
86 'expected_task_state': expected_task_state,
87 'timeout': timeout})
88 message += ' Current status: %s.' % server_status
89 message += ' Current task state: %s.' % task_state
90 caller = misc_utils.find_test_caller()
91 if caller:
92 message = '(%s) %s' % (caller, message)
93 raise exceptions.TimeoutException(message)
94 old_status = server_status
95 old_task_state = task_state
96
97
98def wait_for_image_status(client, image_id, status):
99 """Waits for an image to reach a given status.
100
101 The client should have a get_image(image_id) method to get the image.
102 The client should also have build_interval and build_timeout attributes.
103 """
104 image = client.get_image(image_id)
105 start = int(time.time())
106
107 while image['status'] != status:
108 time.sleep(client.build_interval)
109 image = client.get_image(image_id)
110 status_curr = image['status']
111 if status_curr == 'ERROR':
112 raise exceptions.AddImageException(image_id=image_id)
113
114 # check the status again to avoid a false negative where we hit
115 # the timeout at the same time that the image reached the expected
116 # status
117 if status_curr == status:
118 return
119
120 if int(time.time()) - start >= client.build_timeout:
121 message = ('Image %(image_id)s failed to reach %(status)s state'
122 '(current state %(status_curr)s) '
123 'within the required time (%(timeout)s s).' %
124 {'image_id': image_id,
125 'status': status,
126 'status_curr': status_curr,
127 'timeout': client.build_timeout})
128 caller = misc_utils.find_test_caller()
129 if caller:
130 message = '(%s) %s' % (caller, message)
131 raise exceptions.TimeoutException(message)
132
133
134def wait_for_bm_node_status(client, node_id, attr, status):
135 """Waits for a baremetal node attribute to reach given status.
136
137 The client should have a show_node(node_uuid) method to get the node.
138 """
139 _, node = client.show_node(node_id)
140 start = int(time.time())
141
142 while node[attr] != status:
143 time.sleep(client.build_interval)
144 _, node = client.show_node(node_id)
145 status_curr = node[attr]
146 if status_curr == status:
147 return
148
149 if int(time.time()) - start >= client.build_timeout:
150 message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
151 'within the required time (%(timeout)s s).' %
152 {'node_id': node_id,
153 'attr': attr,
154 'status': status,
155 'timeout': client.build_timeout})
156 message += ' Current state of %s: %s.' % (attr, status_curr)
157 caller = misc_utils.find_test_caller()
158 if caller:
159 message = '(%s) %s' % (caller, message)
160 raise exceptions.TimeoutException(message)