blob: 554e5f877d425f460a6ce8f8c6dd3347530a656b [file] [log] [blame]
Yuiko Takadab6527002015-12-07 11:49:12 +09001# All Rights Reserved.
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
Vladyslav Drok0cad0442016-12-14 12:48:20 +020015import six
16from tempest import config
wangxiyuandbd33dc2017-02-10 09:40:50 +080017from tempest.lib.common.utils import test_utils
Lenny Verkhovsky88625042016-03-08 17:44:00 +020018from tempest.lib import exceptions as lib_exc
Yuiko Takadab6527002015-12-07 11:49:12 +090019
Vladyslav Drok0cad0442016-12-14 12:48:20 +020020from ironic_tempest_plugin.common import utils
21
22CONF = config.CONF
23
24
25def _determine_and_check_timeout_interval(timeout, default_timeout,
26 interval, default_interval):
27 if timeout is None:
28 timeout = default_timeout
29 if interval is None:
30 interval = default_interval
31 if (not isinstance(timeout, six.integer_types) or
32 not isinstance(interval, six.integer_types) or
33 timeout < 0 or interval < 0):
34 raise AssertionError(
35 'timeout and interval should be >= 0 or None, current values are: '
36 '%(timeout)s, %(interval)s respectively. If timeout and/or '
37 'interval are None, the default_timeout and default_interval are '
38 'used, and they should be integers >= 0, current values are: '
39 '%(default_timeout)s, %(default_interval)s respectively.' % dict(
40 timeout=timeout, interval=interval,
41 default_timeout=default_timeout,
42 default_interval=default_interval)
43 )
44 return timeout, interval
45
Yuiko Takadab6527002015-12-07 11:49:12 +090046
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020047def wait_for_bm_node_status(client, node_id, attr, status, timeout=None,
Dmitry Tantsur4e2116d2019-08-27 17:01:58 +020048 interval=None, abort_on_error_state=False):
Yuiko Takadab6527002015-12-07 11:49:12 +090049 """Waits for a baremetal node attribute to reach given status.
50
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020051 :param client: an instance of tempest plugin BaremetalClient.
52 :param node_id: identifier of the node.
53 :param attr: node's API-visible attribute to check status of.
Vladyslav Drok0cad0442016-12-14 12:48:20 +020054 :param status: desired status. Can be a list of statuses.
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020055 :param timeout: the timeout after which the check is considered as failed.
56 Defaults to client.build_timeout.
57 :param interval: an interval between show_node calls for status check.
58 Defaults to client.build_interval.
Dmitry Tantsur4e2116d2019-08-27 17:01:58 +020059 :param abort_on_error_state: whether to abort waiting if the node reaches
60 an error state.
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020061
62 The client should have a show_node(node_id) method to get the node.
Yuiko Takadab6527002015-12-07 11:49:12 +090063 """
Vladyslav Drok0cad0442016-12-14 12:48:20 +020064 timeout, interval = _determine_and_check_timeout_interval(
65 timeout, client.build_timeout, interval, client.build_interval)
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020066
Vladyslav Drok0cad0442016-12-14 12:48:20 +020067 if not isinstance(status, list):
68 status = [status]
Yuiko Takadab6527002015-12-07 11:49:12 +090069
Vladyslav Drok0cad0442016-12-14 12:48:20 +020070 def is_attr_in_status():
71 node = utils.get_node(client, node_id=node_id)
72 if node[attr] in status:
73 return True
Dmitry Tantsur4e2116d2019-08-27 17:01:58 +020074 elif (abort_on_error_state
75 and node['provision_state'].endswith(' failed')):
76 raise lib_exc.TempestException(
77 'Node %(node)s reached failure state %(state)s while waiting '
78 'for %(attr)s=%(expected)s. Error: %(error)s' %
79 {'node': node_id, 'state': node['provision_state'],
80 'attr': attr, 'expected': status,
81 'error': node.get('last_error')})
Vladyslav Drok0cad0442016-12-14 12:48:20 +020082 return False
Yuiko Takadab6527002015-12-07 11:49:12 +090083
Vladyslav Drok0cad0442016-12-14 12:48:20 +020084 if not test_utils.call_until_true(is_attr_in_status, timeout,
85 interval):
86 message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
87 'within the required time (%(timeout)s s).' %
88 {'node_id': node_id,
89 'attr': attr,
90 'status': status,
91 'timeout': timeout})
92 caller = test_utils.find_test_caller()
93 if caller:
94 message = '(%s) %s' % (caller, message)
95 raise lib_exc.TimeoutException(message)
Vladyslav Drok0ac08c82016-12-13 19:51:20 +020096
Vladyslav Drok0cad0442016-12-14 12:48:20 +020097
98def wait_node_instance_association(client, instance_uuid, timeout=None,
99 interval=None):
100 """Waits for a node to be associated with instance_id.
101
102 :param client: an instance of tempest plugin BaremetalClient.
103 :param instance_uuid: UUID of the instance.
104 :param timeout: the timeout after which the check is considered as failed.
105 Defaults to CONF.baremetal.association_timeout.
106 :param interval: an interval between show_node calls for status check.
107 Defaults to client.build_interval.
108 """
109 timeout, interval = _determine_and_check_timeout_interval(
110 timeout, CONF.baremetal.association_timeout,
111 interval, client.build_interval)
112
113 def is_some_node_associated():
114 node = utils.get_node(client, instance_uuid=instance_uuid)
115 return node is not None
116
117 if not test_utils.call_until_true(is_some_node_associated, timeout,
118 interval):
Vladyslav Drok401fd462017-03-13 16:33:52 +0000119 msg = ('Timed out waiting to get Ironic node by instance UUID '
120 '%(instance_uuid)s within the required time (%(timeout)s s).'
121 % {'instance_uuid': instance_uuid, 'timeout': timeout})
Vladyslav Drok0cad0442016-12-14 12:48:20 +0200122 raise lib_exc.TimeoutException(msg)
Dmitry Tantsur47ff4892019-02-08 17:24:46 +0100123
124
125def wait_for_allocation(client, allocation_ident, timeout=15, interval=1,
126 expect_error=False):
127 """Wait for the allocation to become active.
128
129 :param client: an instance of tempest plugin BaremetalClient.
130 :param allocation_ident: UUID or name of the allocation.
131 :param timeout: the timeout after which the allocation is considered as
132 failed. Defaults to 15 seconds.
133 :param interval: an interval between show_allocation calls.
134 Defaults to 1 second.
135 :param expect_error: if True, return successfully even in case of an error.
136 """
137 result = [None] # a mutable object to modify in the closure
138
139 def check():
140 result[0] = client.show_allocation(allocation_ident)
141 allocation = result[0][1]
142
143 if allocation['state'] == 'error' and not expect_error:
144 raise lib_exc.TempestException(
145 "Allocation %(ident)s failed: %(error)s" %
146 {'ident': allocation_ident,
147 'error': allocation.get('last_error')})
148 else:
149 return allocation['state'] != 'allocating'
150
151 if not test_utils.call_until_true(check, timeout, interval):
152 msg = ('Timed out waiting for the allocation %s to become active' %
153 allocation_ident)
154 raise lib_exc.TimeoutException(msg)
155
156 return result[0]