def _continue_deploy(self, task, node, **kwargs): params = self._get_deploy_info(node, **kwargs) ctx = context.get_admin_context() node_id = node['uuid'] err_msg = kwargs.get('error') if err_msg: LOG.error(_('Node %(node_id)s deploy error message: %(error)s') % {'node_id': node_id, 'error': err_msg}) LOG.info(_('start deployment for node %(node_id)s, ' 'params %(params)s') % {'node_id': node_id, 'params': params}) try: node['provision_state'] = states.DEPLOYING node.save(ctx) deploy_utils.deploy(**params) except Exception as e: LOG.error(_('deployment to node %s failed') % node_id) node['provision_state'] = states.DEPLOYFAIL node.save(ctx) raise exception.InstanceDeployFailure(_( 'Deploy error: "%(error)s" for node %(node_id)s') % {'error': e.message, 'node_id': node_id}) else: LOG.info(_('deployment to node %s done') % node_id) node['provision_state'] = states.DEPLOYDONE node.save(ctx)
def test_deploy_preserve_ephemeral(self): """Check if all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 128 swap_mb = 64 ephemeral_mb = 256 ephemeral_format = 'exttest' dev = '/dev/fake' ephemeral_part = '/dev/fake-part1' swap_part = '/dev/fake-part2' root_part = '/dev/fake-part3' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' mock_mkfs_eph = mock.patch.object(utils, 'mkfs_ephemeral').start() self.addCleanup(mock_mkfs_eph.stop) name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'dd', 'mkswap', 'block_uuid', 'switch_pxe_config', 'notify'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'swap': swap_part, 'ephemeral': ephemeral_part, 'root': root_part} parent_mock.block_uuid.return_value = root_uuid calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.is_block_device(ephemeral_part), mock.call.dd(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn), mock.call.switch_pxe_config(pxe_config_path, root_uuid), mock.call.notify(address, 10000)] utils.deploy(address, port, iqn, lun, image_path, pxe_config_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, preserve_ephemeral=True) self.assertEqual(calls_expected, parent_mock.mock_calls) # mkfs_ephemeral should not be called self.assertFalse(mock_mkfs_eph.called)
def _continue_deploy(self, task, **kwargs): """Resume a deployment upon getting POST data from deploy ramdisk. This method raises no exceptions because it is intended to be invoked asynchronously as a callback from the deploy ramdisk. """ node = task.node def _set_failed_state(msg): node.provision_state = states.DEPLOYFAIL node.target_provision_state = states.NOSTATE node.save(task.context) try: manager_utils.node_power_action(task, node, 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(task.context) if node.provision_state != states.DEPLOYWAIT: LOG.error(_('Node %s is not waiting to be deployed.') % node.uuid) return node.provision_state = states.DEPLOYING node.save(task.context) # remove cached keystone token immediately _destroy_token_file(node) params = self._get_deploy_info(node, **kwargs) ramdisk_error = kwargs.get('error') if ramdisk_error: LOG.error(_('Error returned from PXE deploy ramdisk: %s') % ramdisk_error) _set_failed_state(_('Failure in PXE deploy ramdisk.')) return LOG.info(_('Continuing deployment for node %(node)s, params ' '%(params)s') % {'node': node.uuid, 'params': params}) try: deploy_utils.deploy(**params) except Exception as e: LOG.error(_('PXE deploy failed for instance %(instance)s. ' 'Error: %(error)s') % {'instance': node.instance_uuid, 'error': e}) _set_failed_state(_('PXE driver failed to continue deployment.')) else: LOG.info(_('Deployment to node %s done') % node.uuid) node.provision_state = states.ACTIVE node.target_provision_state = states.NOSTATE node.save(task.context)
def test_deploy(self): """Check loosely all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 128 swap_mb = 64 ephemeral_mb = 0 ephemeral_format = None node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' swap_part = '/dev/fake-part1' root_part = '/dev/fake-part2' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'dd', 'mkswap', 'block_uuid', 'switch_pxe_config', 'notify', 'destroy_disk_metadata', 'has_partition_table'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'root': root_part, 'swap': swap_part} parent_mock.has_partition_table.return_value = False calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.has_partition_table(image_path), mock.call.is_block_device(dev), mock.call.destroy_disk_metadata(dev, node_uuid), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb, commit=True), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.dd(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn), mock.call.switch_pxe_config(pxe_config_path, root_uuid), mock.call.notify(address, 10000)] utils.deploy(address, port, iqn, lun, image_path, pxe_config_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid) self.assertEqual(calls_expected, parent_mock.mock_calls)
def test_deploy_preserve_ephemeral(self): """Check if all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 128 swap_mb = 64 ephemeral_mb = 256 ephemeral_format = 'exttest' dev = '/dev/fake' ephemeral_part = '/dev/fake-part1' swap_part = '/dev/fake-part2' root_part = '/dev/fake-part3' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' mock_mkfs_eph = mock.patch.object(utils, 'mkfs_ephemeral').start() self.addCleanup(mock_mkfs_eph.stop) name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'dd', 'mkswap', 'block_uuid', 'switch_pxe_config', 'notify'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.is_block_device(ephemeral_part), mock.call.dd(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn), mock.call.switch_pxe_config(pxe_config_path, root_uuid), mock.call.notify(address, 10000)] utils.deploy(address, port, iqn, lun, image_path, pxe_config_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, preserve_ephemeral=True) self.assertEqual(calls_expected, parent_mock.mock_calls) # mkfs_ephemeral should not be called self.assertFalse(mock_mkfs_eph.called)
def test_deploy(self): """Check loosely all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 128 swap_mb = 64 dev = '/dev/fake' root_part = '/dev/fake-part1' swap_part = '/dev/fake-part2' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'make_partitions', 'is_block_device', 'dd', 'mkswap', 'block_uuid', 'switch_pxe_config', 'notify'] patch_list = [mock.patch.object(utils, name) for name in name_list] mock_list = [patcher.start() for patcher in patch_list] parent_mock = mock.MagicMock() for mocker, name in zip(mock_list, name_list): parent_mock.attach_mock(mocker, name) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.make_partitions(dev, root_mb, swap_mb), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.dd(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.switch_pxe_config(pxe_config_path, root_uuid), mock.call.notify(address, 10000)] utils.deploy(address, port, iqn, lun, image_path, pxe_config_path, root_mb, swap_mb) self.assertEqual(calls_expected, parent_mock.mock_calls) for patcher in patch_list: patcher.stop()
def test_deploy_preserve_ephemeral(self): """Check if all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' root_mb = 128 swap_mb = 64 ephemeral_mb = 256 ephemeral_format = 'exttest' configdrive_mb = 0 node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' ephemeral_part = '/dev/fake-part1' swap_part = '/dev/fake-part2' root_part = '/dev/fake-part3' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'populate_image', 'mkswap', 'block_uuid', 'notify', 'mkfs_ephemeral', 'get_dev_block_size'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'swap': swap_part, 'ephemeral': ephemeral_part, 'root': root_part} parent_mock.block_uuid.return_value = root_uuid calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, commit=False), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.is_block_device(ephemeral_part), mock.call.populate_image(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn)] returned_root_uuid = utils.deploy(address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid, preserve_ephemeral=True) self.assertEqual(calls_expected, parent_mock.mock_calls) self.assertFalse(parent_mock.mkfs_ephemeral.called) self.assertFalse(parent_mock.get_dev_block_size.called) self.assertEqual(root_uuid, returned_root_uuid)
def test_deploy_preserve_ephemeral(self): """Check if all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' root_mb = 128 swap_mb = 64 ephemeral_mb = 256 ephemeral_format = 'exttest' configdrive_mb = 0 node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' ephemeral_part = '/dev/fake-part1' swap_part = '/dev/fake-part2' root_part = '/dev/fake-part3' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'populate_image', 'mkswap', 'block_uuid', 'notify', 'mkfs_ephemeral', 'get_dev_block_size'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'swap': swap_part, 'ephemeral': ephemeral_part, 'root': root_part} parent_mock.block_uuid.return_value = root_uuid calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, commit=False), mock.call.is_block_device(root_part), mock.call.is_block_device(swap_part), mock.call.is_block_device(ephemeral_part), mock.call.populate_image(image_path, root_part), mock.call.mkswap(swap_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn)] returned_root_uuid = utils.deploy(address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid, preserve_ephemeral=True) self.assertEqual(calls_expected, parent_mock.mock_calls) self.assertFalse(parent_mock.mkfs_ephemeral.called) self.assertFalse(parent_mock.get_dev_block_size.called) self.assertEqual(root_uuid, returned_root_uuid)
def test_deploy_without_swap(self): """Check loosely all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' root_mb = 128 swap_mb = 0 ephemeral_mb = 0 ephemeral_format = None configdrive_mb = 0 node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' root_part = '/dev/fake-part1' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = [ 'get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'populate_image', 'block_uuid', 'notify', 'destroy_disk_metadata' ] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'root': root_part} calls_expected = [ mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.destroy_disk_metadata(dev, node_uuid), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, commit=True), mock.call.is_block_device(root_part), mock.call.populate_image(image_path, root_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn) ] returned_root_uuid = utils.deploy(address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid) self.assertEqual(calls_expected, parent_mock.mock_calls) self.assertEqual(root_uuid, returned_root_uuid)
def test_deploy_disk_image(self): """Check loosely all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' pxe_config_path = '/tmp/abc/pxeconfig' root_mb = 0 swap_mb = 0 ephemeral_mb = 0 ephemeral_format = 'exttest' node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi','delete_iscsi', 'is_block_device', 'dd', 'notify', 'has_partition_table', 'block_uuid', 'switch_pxe_config'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.has_partition_table.return_value = True calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.has_partition_table(image_path), mock.call.is_block_device(dev), mock.call.dd(image_path, dev), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn), mock.call.switch_pxe_config(pxe_config_path, None), mock.call.notify(address, 10000)] utils.deploy(address, port, iqn, lun, image_path, pxe_config_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid) self.assertEqual(calls_expected, parent_mock.mock_calls)
def test_deploy_without_swap(self): """Check loosely all functions are called with right args.""" address = '127.0.0.1' port = 3306 iqn = 'iqn.xyz' lun = 1 image_path = '/tmp/xyz/image' root_mb = 128 swap_mb = 0 ephemeral_mb = 0 ephemeral_format = None configdrive_mb = 0 node_uuid = "12345678-1234-1234-1234-1234567890abcxyz" dev = '/dev/fake' root_part = '/dev/fake-part1' root_uuid = '12345678-1234-1234-12345678-12345678abcdef' name_list = ['get_dev', 'get_image_mb', 'discovery', 'login_iscsi', 'logout_iscsi', 'delete_iscsi', 'make_partitions', 'is_block_device', 'populate_image', 'block_uuid', 'notify', 'destroy_disk_metadata'] parent_mock = self._mock_calls(name_list) parent_mock.get_dev.return_value = dev parent_mock.get_image_mb.return_value = 1 parent_mock.is_block_device.return_value = True parent_mock.block_uuid.return_value = root_uuid parent_mock.make_partitions.return_value = {'root': root_part} calls_expected = [mock.call.get_dev(address, port, iqn, lun), mock.call.get_image_mb(image_path), mock.call.discovery(address, port), mock.call.login_iscsi(address, port, iqn), mock.call.is_block_device(dev), mock.call.destroy_disk_metadata(dev, node_uuid), mock.call.make_partitions(dev, root_mb, swap_mb, ephemeral_mb, configdrive_mb, commit=True), mock.call.is_block_device(root_part), mock.call.populate_image(image_path, root_part), mock.call.block_uuid(root_part), mock.call.logout_iscsi(address, port, iqn), mock.call.delete_iscsi(address, port, iqn)] returned_root_uuid = utils.deploy(address, port, iqn, lun, image_path, root_mb, swap_mb, ephemeral_mb, ephemeral_format, node_uuid) self.assertEqual(calls_expected, parent_mock.mock_calls) self.assertEqual(root_uuid, returned_root_uuid)
def continue_deploy(task, **kwargs): """Resume a deployment upon getting POST data from deploy ramdisk. This method raises no exceptions because it is intended to be invoked asynchronously as a callback from the deploy ramdisk. :param task: a TaskManager instance containing the node to act on. :param kwargs: the kwargs to be passed to deploy. :raises: InvalidState if the event is not allowed by the associated state machine. :returns: UUID of the root partition or None on error. """ node = task.node params = get_deploy_info(node, **kwargs) ramdisk_error = kwargs.get('error') if ramdisk_error: LOG.error(_LE('Error returned from deploy ramdisk: %s'), ramdisk_error) deploy_utils.set_failed_state(task, _('Failure in deploy ramdisk.')) destroy_images(node.uuid) return LOG.info(_LI('Continuing deployment for node %(node)s, params %(params)s'), { 'node': node.uuid, 'params': params }) root_uuid = None try: root_uuid = deploy_utils.deploy(**params) except Exception as e: LOG.error( _LE('Deploy failed for instance %(instance)s. ' 'Error: %(error)s'), { 'instance': node.instance_uuid, 'error': e }) deploy_utils.set_failed_state( task, _('Failed to continue ' 'iSCSI deployment.')) destroy_images(node.uuid) return root_uuid
def continue_deploy(task, **kwargs): """Resume a deployment upon getting POST data from deploy ramdisk. This method raises no exceptions because it is intended to be invoked asynchronously as a callback from the deploy ramdisk. :param task: a TaskManager instance containing the node to act on. :param kwargs: the kwargs to be passed to deploy. :returns: UUID of the root partition or None on error. """ node = task.node node.provision_state = states.DEPLOYING node.save() params = get_deploy_info(node, **kwargs) ramdisk_error = kwargs.get('error') if ramdisk_error: LOG.error(_LE('Error returned from deploy ramdisk: %s'), ramdisk_error) deploy_utils.set_failed_state(task, _('Failure in deploy ramdisk.')) destroy_images(node.uuid) return LOG.info(_LI('Continuing deployment for node %(node)s, params %(params)s'), {'node': node.uuid, 'params': params}) root_uuid = None try: root_uuid = deploy_utils.deploy(**params) except Exception as e: LOG.error(_LE('Deploy failed for instance %(instance)s. ' 'Error: %(error)s'), {'instance': node.instance_uuid, 'error': e}) deploy_utils.set_failed_state(task, _('Failed to continue ' 'iSCSI deployment.')) destroy_images(node.uuid) return root_uuid
def _continue_deploy(self, task, **kwargs): """Resume a deployment upon getting POST data from deploy ramdisk. This method raises no exceptions because it is intended to be invoked asynchronously as a callback from the deploy ramdisk. """ node = task.node driver_info = _parse_driver_info(node) def _set_failed_state(msg): node.provision_state = states.DEPLOYFAIL node.target_provision_state = states.NOSTATE node.save(task.context) 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(task.context) if node.provision_state != states.DEPLOYWAIT: LOG.error(_('Node %s is not waiting to be deployed.') % node.uuid) return node.provision_state = states.DEPLOYING node.save(task.context) # remove cached keystone token immediately _destroy_token_file(node) params = self._get_deploy_info(node, **kwargs) ramdisk_error = kwargs.get('error') if ramdisk_error: LOG.error( _('Error returned from PXE deploy ramdisk: %s') % ramdisk_error) _set_failed_state(_('Failure in PXE deploy ramdisk.')) _destroy_images(driver_info, node.uuid) return LOG.info( _('Continuing deployment for node %(node)s, params ' '%(params)s') % { 'node': node.uuid, 'params': params }) try: deploy_utils.deploy(**params) except Exception as e: LOG.error( _('PXE deploy failed for instance %(instance)s. ' 'Error: %(error)s') % { 'instance': node.instance_uuid, 'error': e }) _set_failed_state(_('PXE driver failed to continue deployment.')) else: LOG.info(_('Deployment to node %s done') % node.uuid) node.provision_state = states.ACTIVE node.target_provision_state = states.NOSTATE node.save(task.context) boot_from_pxe = (node.instance_info.get('kernel') and node.instance_info.get('ramdisk')) if not boot_from_pxe: # Remove PXE boot configuration in order to boot from disk. pxe_utils.clean_up_pxe_config(task) neutron.update_neutron(task, None) _destroy_images(driver_info, node.uuid)