Get rid of set_failed_state duplication
drivers.modules.agent and drivers.modules.iscsi_deploy contain _set_failed_state and set_failed_state functions respectively, which are almost identical. This change moves this functionality to drivers.modules.deploy_utils. Change-Id: I2987898e656b2451d3eacd0d5e9bc7fa35723ad5
This commit is contained in:
@@ -114,34 +114,6 @@ def _get_tftp_image_info(node):
|
||||
return pxe_utils.get_deploy_kr_info(node.uuid, node.driver_info)
|
||||
|
||||
|
||||
def _set_failed_state(task, msg):
|
||||
"""Set a node's error state and provision state to signal Nova.
|
||||
|
||||
When deploy steps aren't called by explicitly the conductor, but are
|
||||
the result of callbacks, we need to set the node's state explicitly.
|
||||
This tells Nova to change the instance's status so the user can see
|
||||
their deploy/tear down had an issue and makes debugging/deleting Nova
|
||||
instances easier.
|
||||
"""
|
||||
node = task.node
|
||||
node.provision_state = states.DEPLOYFAIL
|
||||
node.target_provision_state = states.NOSTATE
|
||||
node.save()
|
||||
try:
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
except Exception:
|
||||
msg = (_('Node %s failed to power off while handling deploy '
|
||||
'failure. This may be a serious condition. Node '
|
||||
'should be removed from Ironic or put in maintenance '
|
||||
'mode until the problem is resolved.') % node.uuid)
|
||||
LOG.error(msg)
|
||||
finally:
|
||||
# NOTE(deva): node_power_action() erases node.last_error
|
||||
# so we need to set it again here.
|
||||
node.last_error = msg
|
||||
node.save()
|
||||
|
||||
|
||||
@image_cache.cleanup(priority=25)
|
||||
class AgentTFTPImageCache(image_cache.ImageCache):
|
||||
def __init__(self, image_service=None):
|
||||
@@ -388,7 +360,7 @@ class AgentVendorInterface(base.VendorInterface):
|
||||
LOG.exception(_LE('Async exception for %(node)s: %(msg)s'),
|
||||
{'node': node,
|
||||
'msg': msg})
|
||||
_set_failed_state(task, msg)
|
||||
deploy_utils.set_failed_state(task, msg)
|
||||
|
||||
def _deploy_is_done(self, node):
|
||||
return self._client.deploy_is_done(node)
|
||||
@@ -438,7 +410,7 @@ class AgentVendorInterface(base.VendorInterface):
|
||||
msg = _('node %(node)s command status errored: %(error)s') % (
|
||||
{'node': node.uuid, 'error': error})
|
||||
LOG.error(msg)
|
||||
_set_failed_state(task, msg)
|
||||
deploy_utils.set_failed_state(task, msg)
|
||||
return
|
||||
|
||||
LOG.debug('Rebooting node %s to disk', node.uuid)
|
||||
|
||||
@@ -29,7 +29,9 @@ from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common.i18n import _LE
|
||||
from ironic.common import images
|
||||
from ironic.common import states
|
||||
from ironic.common import utils
|
||||
from ironic.conductor import utils as manager_utils
|
||||
from ironic.drivers.modules import image_cache
|
||||
from ironic.openstack.common import log as logging
|
||||
|
||||
@@ -441,3 +443,32 @@ def fetch_images(ctx, cache, images_info, force_raw=True):
|
||||
# (probably unrelated) processes
|
||||
for href, path in images_info:
|
||||
cache.fetch_image(href, path, ctx=ctx, force_raw=force_raw)
|
||||
|
||||
|
||||
def set_failed_state(task, msg):
|
||||
"""Sets the deploy status as failed with relevant messages.
|
||||
|
||||
This method sets the deployment as fail with the given message.
|
||||
It sets node's provision_state to DEPLOYFAIL and updates last_error
|
||||
with the given error message. It also powers off the baremetal node.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:param msg: the message to set in last_error of the node.
|
||||
"""
|
||||
node = task.node
|
||||
node.provision_state = states.DEPLOYFAIL
|
||||
node.target_provision_state = states.NOSTATE
|
||||
node.save()
|
||||
try:
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
except Exception:
|
||||
msg2 = (_LE('Node %s failed to power off while handling deploy '
|
||||
'failure. This may be a serious condition. Node '
|
||||
'should be removed from Ironic or put in maintenance '
|
||||
'mode until the problem is resolved.') % node.uuid)
|
||||
LOG.exception(msg2)
|
||||
finally:
|
||||
# NOTE(deva): node_power_action() erases node.last_error
|
||||
# so we need to set it again here.
|
||||
node.last_error = msg
|
||||
node.save()
|
||||
|
||||
@@ -550,4 +550,4 @@ class VendorPassthru(base.VendorInterface):
|
||||
'Error: %(error)s'),
|
||||
{'instance': node.instance_uuid, 'error': e})
|
||||
msg = _('Failed to continue iSCSI deployment.')
|
||||
iscsi_deploy.set_failed_state(task, msg)
|
||||
deploy_utils.set_failed_state(task, msg)
|
||||
|
||||
@@ -26,7 +26,6 @@ from ironic.common import image_service as service
|
||||
from ironic.common import keystone
|
||||
from ironic.common import states
|
||||
from ironic.common import utils
|
||||
from ironic.conductor import utils as manager_utils
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
from ironic.drivers.modules import image_cache
|
||||
from ironic.drivers import utils as driver_utils
|
||||
@@ -243,35 +242,6 @@ def get_deploy_info(node, **kwargs):
|
||||
return params
|
||||
|
||||
|
||||
def set_failed_state(task, msg):
|
||||
"""Sets the deploy status as failed with relevant messages.
|
||||
|
||||
This method sets the deployment as fail with the given message.
|
||||
It sets node's provision_state to DEPLOYFAIL and updates last_error
|
||||
with the given error message. It also powers off the baremetal node.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:param msg: the message to set in last_error of the node.
|
||||
"""
|
||||
node = task.node
|
||||
node.provision_state = states.DEPLOYFAIL
|
||||
node.target_provision_state = states.NOSTATE
|
||||
node.save()
|
||||
try:
|
||||
manager_utils.node_power_action(task, states.POWER_OFF)
|
||||
except Exception:
|
||||
msg2 = (_('Node %s failed to power off while handling deploy '
|
||||
'failure. This may be a serious condition. Node '
|
||||
'should be removed from Ironic or put in maintenance '
|
||||
'mode until the problem is resolved.') % node.uuid)
|
||||
LOG.exception(msg2)
|
||||
finally:
|
||||
# NOTE(deva): node_power_action() erases node.last_error
|
||||
# so we need to set it again here.
|
||||
node.last_error = msg
|
||||
node.save()
|
||||
|
||||
|
||||
def continue_deploy(task, **kwargs):
|
||||
"""Resume a deployment upon getting POST data from deploy ramdisk.
|
||||
|
||||
@@ -293,7 +263,7 @@ def continue_deploy(task, **kwargs):
|
||||
if ramdisk_error:
|
||||
LOG.error(_LE('Error returned from deploy ramdisk: %s'),
|
||||
ramdisk_error)
|
||||
set_failed_state(task, _('Failure in deploy ramdisk.'))
|
||||
deploy_utils.set_failed_state(task, _('Failure in deploy ramdisk.'))
|
||||
destroy_images(node.uuid)
|
||||
return
|
||||
|
||||
@@ -307,7 +277,8 @@ def continue_deploy(task, **kwargs):
|
||||
LOG.error(_LE('Deploy failed for instance %(instance)s. '
|
||||
'Error: %(error)s'),
|
||||
{'instance': node.instance_uuid, 'error': e})
|
||||
set_failed_state(task, _('Failed to continue iSCSI deployment.'))
|
||||
deploy_utils.set_failed_state(task, _('Failed to continue '
|
||||
'iSCSI deployment.'))
|
||||
|
||||
destroy_images(node.uuid)
|
||||
return root_uuid
|
||||
|
||||
@@ -487,4 +487,4 @@ class VendorPassthru(base.VendorInterface):
|
||||
'Error: %(error)s'),
|
||||
{'instance': node.instance_uuid, 'error': e})
|
||||
msg = _('Failed to continue iSCSI deployment.')
|
||||
iscsi_deploy.set_failed_state(task, msg)
|
||||
deploy_utils.set_failed_state(task, msg)
|
||||
|
||||
@@ -22,6 +22,7 @@ from ironic.common import pxe_utils
|
||||
from ironic.common import states
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.drivers.modules import agent
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
from ironic import objects
|
||||
from ironic.tests.conductor import utils as mgr_utils
|
||||
from ironic.tests.db import base as db_base
|
||||
@@ -388,7 +389,7 @@ class TestAgentVendor(db_base.DbTestCase):
|
||||
self.assertRaises(exception.MissingParameterValue,
|
||||
self.passthru.heartbeat, task, **kwargs)
|
||||
|
||||
@mock.patch.object(agent, '_set_failed_state')
|
||||
@mock.patch.object(deploy_utils, 'set_failed_state')
|
||||
@mock.patch.object(agent.AgentVendorInterface, '_deploy_is_done')
|
||||
def test_heartbeat_deploy_done_fails(self, done_mock, failed_mock):
|
||||
kwargs = {
|
||||
|
||||
Reference in New Issue
Block a user