baremetal: raise more specific ResourceFailure in wait_for_* methods
Raising a generic SDKException makes it harder to distinguish them from other failures. Also add missing docstrings. Change-Id: I576469b0bdb664512ce9d34d5217329f3fa62b64
This commit is contained in:
parent
f7860861a1
commit
f4fa6fabba
@ -344,6 +344,9 @@ class Proxy(proxy.Proxy):
|
|||||||
|
|
||||||
:return: The list of :class:`~openstack.baremetal.v1.node.Node`
|
:return: The list of :class:`~openstack.baremetal.v1.node.Node`
|
||||||
instances that reached the requested state.
|
instances that reached the requested state.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if a node
|
||||||
|
reaches an error state and ``abort_on_failed_state`` is ``True``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
log_nodes = ', '.join(n.id if isinstance(n, _node.Node) else n
|
log_nodes = ', '.join(n.id if isinstance(n, _node.Node) else n
|
||||||
for n in nodes)
|
for n in nodes)
|
||||||
@ -895,6 +898,9 @@ class Proxy(proxy.Proxy):
|
|||||||
|
|
||||||
:returns: The instance of the allocation.
|
:returns: The instance of the allocation.
|
||||||
:rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`.
|
:rtype: :class:`~openstack.baremetal.v1.allocation.Allocation`.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if allocation
|
||||||
|
fails and ``ignore_error`` is ``False``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
res = self._get_resource(_allocation.Allocation, allocation)
|
res = self._get_resource(_allocation.Allocation, allocation)
|
||||||
return res.wait(self, timeout=timeout, ignore_error=ignore_error)
|
return res.wait(self, timeout=timeout, ignore_error=ignore_error)
|
||||||
|
@ -76,6 +76,9 @@ class Allocation(_common.ListMixin, resource.Resource):
|
|||||||
state is considered successful and the call returns.
|
state is considered successful and the call returns.
|
||||||
|
|
||||||
:return: This :class:`Allocation` instance.
|
:return: This :class:`Allocation` instance.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if allocation
|
||||||
|
fails and ``ignore_error`` is ``False``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
if self.state == 'active':
|
if self.state == 'active':
|
||||||
return self
|
return self
|
||||||
@ -86,7 +89,7 @@ class Allocation(_common.ListMixin, resource.Resource):
|
|||||||
self.fetch(session)
|
self.fetch(session)
|
||||||
|
|
||||||
if self.state == 'error' and not ignore_error:
|
if self.state == 'error' and not ignore_error:
|
||||||
raise exceptions.SDKException(
|
raise exceptions.ResourceFailure(
|
||||||
"Allocation %(allocation)s failed: %(error)s" %
|
"Allocation %(allocation)s failed: %(error)s" %
|
||||||
{'allocation': self.id, 'error': self.last_error})
|
{'allocation': self.id, 'error': self.last_error})
|
||||||
elif self.state != 'allocating':
|
elif self.state != 'allocating':
|
||||||
|
@ -323,6 +323,10 @@ class Node(_common.ListMixin, resource.Resource):
|
|||||||
:return: This :class:`Node` instance.
|
:return: This :class:`Node` instance.
|
||||||
:raises: ValueError if ``config_drive``, ``clean_steps`` or
|
:raises: ValueError if ``config_drive``, ``clean_steps`` or
|
||||||
``rescue_password`` are provided with an invalid ``target``.
|
``rescue_password`` are provided with an invalid ``target``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if the node
|
||||||
|
reaches an error state while waiting for the state.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` if timeout
|
||||||
|
is reached while waiting for the state.
|
||||||
"""
|
"""
|
||||||
session = self._get_session(session)
|
session = self._get_session(session)
|
||||||
|
|
||||||
@ -400,6 +404,9 @@ class Node(_common.ListMixin, resource.Resource):
|
|||||||
``manageable`` transition is ``enroll`` again.
|
``manageable`` transition is ``enroll`` again.
|
||||||
|
|
||||||
:return: This :class:`Node` instance.
|
:return: This :class:`Node` instance.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if the node
|
||||||
|
reaches an error state and ``abort_on_failed_state`` is ``True``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
for count in utils.iterate_timeout(
|
for count in utils.iterate_timeout(
|
||||||
timeout,
|
timeout,
|
||||||
@ -469,8 +476,8 @@ class Node(_common.ListMixin, resource.Resource):
|
|||||||
``manageable`` transition is ``enroll`` again.
|
``manageable`` transition is ``enroll`` again.
|
||||||
|
|
||||||
:return: ``True`` if the target state is reached
|
:return: ``True`` if the target state is reached
|
||||||
:raises: SDKException if ``abort_on_failed_state`` is ``True`` and
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if the node
|
||||||
a failure state is reached.
|
reaches an error state and ``abort_on_failed_state`` is ``True``.
|
||||||
"""
|
"""
|
||||||
# NOTE(dtantsur): microversion 1.2 changed None to available
|
# NOTE(dtantsur): microversion 1.2 changed None to available
|
||||||
if (self.provision_state == expected_state
|
if (self.provision_state == expected_state
|
||||||
@ -481,7 +488,7 @@ class Node(_common.ListMixin, resource.Resource):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if self.provision_state.endswith(' failed'):
|
if self.provision_state.endswith(' failed'):
|
||||||
raise exceptions.SDKException(
|
raise exceptions.ResourceFailure(
|
||||||
"Node %(node)s reached failure state \"%(state)s\"; "
|
"Node %(node)s reached failure state \"%(state)s\"; "
|
||||||
"the last error is %(error)s" %
|
"the last error is %(error)s" %
|
||||||
{'node': self.id, 'state': self.provision_state,
|
{'node': self.id, 'state': self.provision_state,
|
||||||
@ -490,7 +497,7 @@ class Node(_common.ListMixin, resource.Resource):
|
|||||||
# "enroll"
|
# "enroll"
|
||||||
elif (expected_state == 'manageable'
|
elif (expected_state == 'manageable'
|
||||||
and self.provision_state == 'enroll' and self.last_error):
|
and self.provision_state == 'enroll' and self.last_error):
|
||||||
raise exceptions.SDKException(
|
raise exceptions.ResourceFailure(
|
||||||
"Node %(node)s could not reach state manageable: "
|
"Node %(node)s could not reach state manageable: "
|
||||||
"failed to verify management credentials; "
|
"failed to verify management credentials; "
|
||||||
"the last error is %(error)s" %
|
"the last error is %(error)s" %
|
||||||
|
@ -125,6 +125,9 @@ class Proxy(proxy.Proxy):
|
|||||||
if the introspection reaches the ``error`` state. Otherwise the
|
if the introspection reaches the ``error`` state. Otherwise the
|
||||||
error state is considered successful and the call returns.
|
error state is considered successful and the call returns.
|
||||||
:returns: :class:`~.introspection.Introspection` instance.
|
:returns: :class:`~.introspection.Introspection` instance.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if
|
||||||
|
introspection fails and ``ignore_error`` is ``False``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
res = self._get_resource(_introspect.Introspection, introspection)
|
res = self._get_resource(_introspect.Introspection, introspection)
|
||||||
return res.wait(self, timeout=timeout, ignore_error=ignore_error)
|
return res.wait(self, timeout=timeout, ignore_error=ignore_error)
|
||||||
|
@ -107,6 +107,9 @@ class Introspection(resource.Resource):
|
|||||||
if the introspection reaches the ``error`` state. Otherwise the
|
if the introspection reaches the ``error`` state. Otherwise the
|
||||||
error state is considered successful and the call returns.
|
error state is considered successful and the call returns.
|
||||||
:return: This :class:`Introspection` instance.
|
:return: This :class:`Introspection` instance.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if
|
||||||
|
introspection fails and ``ignore_error`` is ``False``.
|
||||||
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
||||||
"""
|
"""
|
||||||
if self._check_state(ignore_error):
|
if self._check_state(ignore_error):
|
||||||
return self
|
return self
|
||||||
@ -124,7 +127,7 @@ class Introspection(resource.Resource):
|
|||||||
|
|
||||||
def _check_state(self, ignore_error):
|
def _check_state(self, ignore_error):
|
||||||
if self.state == 'error' and not ignore_error:
|
if self.state == 'error' and not ignore_error:
|
||||||
raise exceptions.SDKException(
|
raise exceptions.ResourceFailure(
|
||||||
"Introspection of node %(node)s failed: %(error)s" %
|
"Introspection of node %(node)s failed: %(error)s" %
|
||||||
{'node': self.id, 'error': self.error})
|
{'node': self.id, 'error': self.error})
|
||||||
else:
|
else:
|
||||||
|
@ -104,6 +104,36 @@ class TestWaitForAllocation(base.TestCase):
|
|||||||
self.assertIs(allocation, self.allocation)
|
self.assertIs(allocation, self.allocation)
|
||||||
self.assertEqual(2, mock_fetch.call_count)
|
self.assertEqual(2, mock_fetch.call_count)
|
||||||
|
|
||||||
|
def test_failure(self, mock_fetch):
|
||||||
|
marker = [False] # mutable object to modify in the closure
|
||||||
|
|
||||||
|
def _side_effect(allocation, session):
|
||||||
|
if marker[0]:
|
||||||
|
self.allocation.state = 'error'
|
||||||
|
self.allocation.last_error = 'boom!'
|
||||||
|
else:
|
||||||
|
marker[0] = True
|
||||||
|
|
||||||
|
mock_fetch.side_effect = _side_effect
|
||||||
|
self.assertRaises(exceptions.ResourceFailure,
|
||||||
|
self.allocation.wait, self.session)
|
||||||
|
self.assertEqual(2, mock_fetch.call_count)
|
||||||
|
|
||||||
|
def test_failure_ignored(self, mock_fetch):
|
||||||
|
marker = [False] # mutable object to modify in the closure
|
||||||
|
|
||||||
|
def _side_effect(allocation, session):
|
||||||
|
if marker[0]:
|
||||||
|
self.allocation.state = 'error'
|
||||||
|
self.allocation.last_error = 'boom!'
|
||||||
|
else:
|
||||||
|
marker[0] = True
|
||||||
|
|
||||||
|
mock_fetch.side_effect = _side_effect
|
||||||
|
allocation = self.allocation.wait(self.session, ignore_error=True)
|
||||||
|
self.assertIs(allocation, self.allocation)
|
||||||
|
self.assertEqual(2, mock_fetch.call_count)
|
||||||
|
|
||||||
def test_timeout(self, mock_fetch):
|
def test_timeout(self, mock_fetch):
|
||||||
self.assertRaises(exceptions.ResourceTimeout,
|
self.assertRaises(exceptions.ResourceTimeout,
|
||||||
self.allocation.wait, self.session, timeout=0.001)
|
self.allocation.wait, self.session, timeout=0.001)
|
||||||
|
@ -178,7 +178,7 @@ class TestNodeWaitForProvisionState(base.TestCase):
|
|||||||
|
|
||||||
mock_fetch.side_effect = _get_side_effect
|
mock_fetch.side_effect = _get_side_effect
|
||||||
|
|
||||||
self.assertRaisesRegex(exceptions.SDKException,
|
self.assertRaisesRegex(exceptions.ResourceFailure,
|
||||||
'failure state "deploy failed"',
|
'failure state "deploy failed"',
|
||||||
self.node.wait_for_provision_state,
|
self.node.wait_for_provision_state,
|
||||||
self.session, 'manageable')
|
self.session, 'manageable')
|
||||||
@ -191,7 +191,7 @@ class TestNodeWaitForProvisionState(base.TestCase):
|
|||||||
|
|
||||||
mock_fetch.side_effect = _get_side_effect
|
mock_fetch.side_effect = _get_side_effect
|
||||||
|
|
||||||
self.assertRaisesRegex(exceptions.SDKException,
|
self.assertRaisesRegex(exceptions.ResourceFailure,
|
||||||
'failed to verify management credentials',
|
'failed to verify management credentials',
|
||||||
self.node.wait_for_provision_state,
|
self.node.wait_for_provision_state,
|
||||||
self.session, 'manageable')
|
self.session, 'manageable')
|
||||||
|
@ -86,7 +86,7 @@ class TestWaitForIntrospection(base.TestCase):
|
|||||||
self.introspection.error = 'boom'
|
self.introspection.error = 'boom'
|
||||||
|
|
||||||
mock_fetch.side_effect = _side_effect
|
mock_fetch.side_effect = _side_effect
|
||||||
self.assertRaisesRegex(exceptions.SDKException, 'boom',
|
self.assertRaisesRegex(exceptions.ResourceFailure, 'boom',
|
||||||
self.proxy.wait_for_introspection,
|
self.proxy.wait_for_introspection,
|
||||||
self.introspection)
|
self.introspection)
|
||||||
mock_fetch.assert_called_once_with(self.introspection, self.proxy)
|
mock_fetch.assert_called_once_with(self.introspection, self.proxy)
|
||||||
|
7
releasenotes/notes/baremetal-wait-e4571cdb150b188a.yaml
Normal file
7
releasenotes/notes/baremetal-wait-e4571cdb150b188a.yaml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
The baremetal calls ``wait_for_nodes_provision_state``,
|
||||||
|
``wait_for_allocation`` and the baremetal introspection call
|
||||||
|
``wait_for_introspection`` now raise ``ResourceFailure`` on reaching
|
||||||
|
an error state instead of a generic ``SDKException``.
|
Loading…
x
Reference in New Issue
Block a user