Refactor waiters in our tempest plugin
Deduplicates some of the code between common.waiters module and
BaremetalScenarioTest functions.
Change-Id: Ia87646cccdefba22caf121f4e347e8f2edf736e0
diff --git a/ironic_tempest_plugin/common/waiters.py b/ironic_tempest_plugin/common/waiters.py
index 83aeeab..7cfc12e 100644
--- a/ironic_tempest_plugin/common/waiters.py
+++ b/ironic_tempest_plugin/common/waiters.py
@@ -12,12 +12,37 @@
# License for the specific language governing permissions and limitations
# under the License.
-
-import time
-
+import six
+from tempest import config
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
+from ironic_tempest_plugin.common import utils
+
+CONF = config.CONF
+
+
+def _determine_and_check_timeout_interval(timeout, default_timeout,
+ interval, default_interval):
+ if timeout is None:
+ timeout = default_timeout
+ if interval is None:
+ interval = default_interval
+ if (not isinstance(timeout, six.integer_types) or
+ not isinstance(interval, six.integer_types) or
+ timeout < 0 or interval < 0):
+ raise AssertionError(
+ 'timeout and interval should be >= 0 or None, current values are: '
+ '%(timeout)s, %(interval)s respectively. If timeout and/or '
+ 'interval are None, the default_timeout and default_interval are '
+ 'used, and they should be integers >= 0, current values are: '
+ '%(default_timeout)s, %(default_interval)s respectively.' % dict(
+ timeout=timeout, interval=interval,
+ default_timeout=default_timeout,
+ default_interval=default_interval)
+ )
+ return timeout, interval
+
def wait_for_bm_node_status(client, node_id, attr, status, timeout=None,
interval=None):
@@ -26,7 +51,7 @@
:param client: an instance of tempest plugin BaremetalClient.
:param node_id: identifier of the node.
:param attr: node's API-visible attribute to check status of.
- :param status: desired status.
+ :param status: desired status. Can be a list of statuses.
:param timeout: the timeout after which the check is considered as failed.
Defaults to client.build_timeout.
:param interval: an interval between show_node calls for status check.
@@ -34,37 +59,54 @@
The client should have a show_node(node_id) method to get the node.
"""
- if timeout is None:
- timeout = client.build_timeout
- if interval is None:
- interval = client.build_interval
- if timeout < 0 or interval < 0:
- raise lib_exc.InvalidConfiguration(
- 'timeout and interval should be >= 0 or None, current values are: '
- '%(timeout)s, %(interval)s respectively.' % dict(timeout=timeout,
- interval=interval)
- )
+ timeout, interval = _determine_and_check_timeout_interval(
+ timeout, client.build_timeout, interval, client.build_interval)
- start = int(time.time())
- _, node = client.show_node(node_id)
+ if not isinstance(status, list):
+ status = [status]
- while node[attr] != status:
- status_curr = node[attr]
- if status_curr == status:
- return
+ def is_attr_in_status():
+ node = utils.get_node(client, node_id=node_id)
+ if node[attr] in status:
+ return True
+ return False
- if int(time.time()) - start >= timeout:
- message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
- 'within the required time (%(timeout)s s).' %
- {'node_id': node_id,
- 'attr': attr,
- 'status': status,
- 'timeout': client.build_timeout})
- message += ' Current state of %s: %s.' % (attr, status_curr)
- caller = test_utils.find_test_caller()
- if caller:
- message = '(%s) %s' % (caller, message)
- raise lib_exc.TimeoutException(message)
+ if not test_utils.call_until_true(is_attr_in_status, timeout,
+ interval):
+ message = ('Node %(node_id)s failed to reach %(attr)s=%(status)s '
+ 'within the required time (%(timeout)s s).' %
+ {'node_id': node_id,
+ 'attr': attr,
+ 'status': status,
+ 'timeout': timeout})
+ caller = test_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ raise lib_exc.TimeoutException(message)
- time.sleep(interval)
- _, node = client.show_node(node_id)
+
+def wait_node_instance_association(client, instance_uuid, timeout=None,
+ interval=None):
+ """Waits for a node to be associated with instance_id.
+
+ :param client: an instance of tempest plugin BaremetalClient.
+ :param instance_uuid: UUID of the instance.
+ :param timeout: the timeout after which the check is considered as failed.
+ Defaults to CONF.baremetal.association_timeout.
+ :param interval: an interval between show_node calls for status check.
+ Defaults to client.build_interval.
+ """
+ timeout, interval = _determine_and_check_timeout_interval(
+ timeout, CONF.baremetal.association_timeout,
+ interval, client.build_interval)
+
+ def is_some_node_associated():
+ node = utils.get_node(client, instance_uuid=instance_uuid)
+ return node is not None
+
+ if not test_utils.call_until_true(is_some_node_associated, timeout,
+ interval):
+ msg = ('Timed out waiting to get Ironic node by instance ID '
+ '%(instance_id)s within the required time (%(timeout)s s).'
+ % {'instance_id': instance_uuid, 'timeout': timeout})
+ raise lib_exc.TimeoutException(msg)