Refactor waiters in our tempest plugin
Deduplicates some of the code between common.waiters module and BaremetalScenarioTest functions. Change-Id: Ia87646cccdefba22caf121f4e347e8f2edf736e0
This commit is contained in:
parent
f6bad6fb9e
commit
733ff3fff7
33
ironic_tempest_plugin/common/utils.py
Normal file
33
ironic_tempest_plugin/common/utils.py
Normal file
@ -0,0 +1,33 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
def get_node(client, node_id=None, instance_uuid=None):
|
||||
"""Get a node by its identifier or instance UUID.
|
||||
|
||||
If both node_id and instance_uuid specified, node_id will be used.
|
||||
|
||||
:param client: an instance of tempest plugin BaremetalClient.
|
||||
:param node_id: identifier (UUID or name) of the node.
|
||||
:param instance_uuid: UUID of the instance.
|
||||
:returns: the requested node.
|
||||
:raises: AssertionError, if neither node_id nor instance_uuid was provided
|
||||
"""
|
||||
assert node_id or instance_uuid, ('Either node or instance identifier '
|
||||
'has to be provided.')
|
||||
if node_id:
|
||||
_, body = client.show_node(node_id)
|
||||
return body
|
||||
elif instance_uuid:
|
||||
_, body = client.show_node_by_instance_uuid(instance_uuid)
|
||||
if body['nodes']:
|
||||
return body['nodes'][0]
|
@ -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 @@ def wait_for_bm_node_status(client, node_id, attr, status, timeout=None,
|
||||
: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 @@ def wait_for_bm_node_status(client, node_id, attr, status, timeout=None,
|
||||
|
||||
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)
|
||||
|
@ -16,11 +16,11 @@
|
||||
|
||||
from tempest.common import waiters
|
||||
from tempest import config
|
||||
from tempest.lib.common.utils import test_utils
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from tempest.scenario import manager # noqa
|
||||
|
||||
from ironic_tempest_plugin import clients
|
||||
from ironic_tempest_plugin.common import utils
|
||||
from ironic_tempest_plugin.common import waiters as ironic_waiters
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
@ -73,58 +73,23 @@ class BaremetalScenarioTest(manager.ScenarioTest):
|
||||
# allow any issues obtaining the node list to raise early
|
||||
cls.baremetal_client.list_nodes()
|
||||
|
||||
def _node_state_timeout(self, node_id, state_attr,
|
||||
target_states, timeout=10, interval=1):
|
||||
if not isinstance(target_states, list):
|
||||
target_states = [target_states]
|
||||
|
||||
def check_state():
|
||||
node = self.get_node(node_id=node_id)
|
||||
if node.get(state_attr) in target_states:
|
||||
return True
|
||||
return False
|
||||
|
||||
if not test_utils.call_until_true(check_state, timeout, interval):
|
||||
msg = ("Timed out waiting for node %s to reach %s state(s) %s" %
|
||||
(node_id, state_attr, target_states))
|
||||
raise lib_exc.TimeoutException(msg)
|
||||
|
||||
def wait_provisioning_state(self, node_id, state, timeout, interval=1):
|
||||
self._node_state_timeout(
|
||||
node_id=node_id, state_attr='provision_state',
|
||||
target_states=state, timeout=timeout, interval=interval)
|
||||
def wait_provisioning_state(self, node_id, state, timeout=10, interval=1):
|
||||
ironic_waiters.wait_for_bm_node_status(
|
||||
self.baremetal_client, node_id=node_id, attr='provision_state',
|
||||
status=state, timeout=timeout, interval=interval)
|
||||
|
||||
def wait_power_state(self, node_id, state):
|
||||
self._node_state_timeout(
|
||||
node_id=node_id, state_attr='power_state',
|
||||
target_states=state, timeout=CONF.baremetal.power_timeout)
|
||||
ironic_waiters.wait_for_bm_node_status(
|
||||
self.baremetal_client, node_id=node_id, attr='power_state',
|
||||
status=state, timeout=CONF.baremetal.power_timeout)
|
||||
|
||||
def wait_node(self, instance_id):
|
||||
"""Waits for a node to be associated with instance_id."""
|
||||
|
||||
def _get_node():
|
||||
node = None
|
||||
try:
|
||||
node = self.get_node(instance_id=instance_id)
|
||||
except lib_exc.NotFound:
|
||||
pass
|
||||
return node is not None
|
||||
|
||||
if (not test_utils.call_until_true(
|
||||
_get_node, CONF.baremetal.association_timeout, 1)):
|
||||
msg = ('Timed out waiting to get Ironic node by instance id %s'
|
||||
% instance_id)
|
||||
raise lib_exc.TimeoutException(msg)
|
||||
ironic_waiters.wait_node_instance_association(self.baremetal_client,
|
||||
instance_id)
|
||||
|
||||
def get_node(self, node_id=None, instance_id=None):
|
||||
if node_id:
|
||||
_, body = self.baremetal_client.show_node(node_id)
|
||||
return body
|
||||
elif instance_id:
|
||||
_, body = self.baremetal_client.show_node_by_instance_uuid(
|
||||
instance_id)
|
||||
if body['nodes']:
|
||||
return body['nodes'][0]
|
||||
return utils.get_node(self.baremetal_client, node_id, instance_id)
|
||||
|
||||
def get_ports(self, node_uuid):
|
||||
ports = []
|
||||
|
Loading…
Reference in New Issue
Block a user