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: a dictionary containing the following keys: For partition image: * 'root uuid': UUID of root partition * 'efi system partition uuid': UUID of the uefi system partition (if boot mode is uefi). .. note:: If key exists but value is None, it means partition doesn't exist. For whole disk image: * 'disk identifier': ID of the disk to which image was deployed. """ node = task.node params = get_deploy_info(node, **kwargs) def _fail_deploy(task, msg, raise_exception=True): """Fail the deploy after logging and setting error states.""" if isinstance(msg, Exception): msg = (_('Deploy failed for instance %(instance)s. ' 'Error: %(error)s') % {'instance': node.instance_uuid, 'error': msg}) deploy_utils.set_failed_state(task, msg) deploy_utils.destroy_images(task.node.uuid) if raise_exception: raise exception.InstanceDeployFailure(msg) # NOTE(lucasagomes): Let's make sure we don't log the full content # of the config drive here because it can be up to 64MB in size, # so instead let's log "***" in case config drive is enabled. if LOG.isEnabledFor(logging.logging.DEBUG): log_params = { k: params[k] if k != 'configdrive' else '***' for k in params } LOG.debug('Continuing deployment for node %(node)s, params %(params)s', {'node': node.uuid, 'params': log_params}) uuid_dict_returned = {} try: if node.driver_internal_info['is_whole_disk_image']: uuid_dict_returned = deploy_utils.deploy_disk_image(**params) else: uuid_dict_returned = deploy_utils.deploy_partition_image(**params) except exception.IronicException as e: with excutils.save_and_reraise_exception(): LOG.error('Deploy of instance %(instance)s on node %(node)s ' 'failed: %(error)s', {'instance': node.instance_uuid, 'node': node.uuid, 'error': e}) _fail_deploy(task, e, raise_exception=False) except Exception as e: LOG.exception('Deploy of instance %(instance)s on node %(node)s ' 'failed with exception', {'instance': node.instance_uuid, 'node': node.uuid}) _fail_deploy(task, e) root_uuid_or_disk_id = uuid_dict_returned.get( 'root uuid', uuid_dict_returned.get('disk identifier')) if not root_uuid_or_disk_id: msg = (_("Couldn't determine the UUID of the root " "partition or the disk identifier after deploying " "node %s") % node.uuid) LOG.error(msg) _fail_deploy(task, msg) if params.get('preserve_ephemeral', False): # Save disk layout information, to check that they are unchanged # for any future rebuilds _save_disk_layout(node, deploy_utils.parse_instance_info(node)) deploy_utils.destroy_images(node.uuid) return uuid_dict_returned
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: a dictionary containing the following keys: For partition image: 'root uuid': UUID of root partition 'efi system partition uuid': UUID of the uefi system partition (if boot mode is uefi). NOTE: If key exists but value is None, it means partition doesn't exist. For whole disk image: 'disk identifier': ID of the disk to which image was deployed. """ node = task.node params = get_deploy_info(node, **kwargs) ramdisk_error = kwargs.get("error") def _fail_deploy(task, msg): """Fail the deploy after logging and setting error states.""" LOG.error(msg) deploy_utils.set_failed_state(task, msg) destroy_images(task.node.uuid) raise exception.InstanceDeployFailure(msg) if ramdisk_error: msg = _("Error returned from deploy ramdisk: %s") % ramdisk_error _fail_deploy(task, msg) # NOTE(lucasagomes): Let's make sure we don't log the full content # of the config drive here because it can be up to 64MB in size, # so instead let's log "***" in case config drive is enabled. if LOG.isEnabledFor(logging.logging.DEBUG): log_params = {k: params[k] if k != "configdrive" else "***" for k in params.keys()} LOG.debug( "Continuing deployment for node %(node)s, params %(params)s", {"node": node.uuid, "params": log_params} ) uuid_dict_returned = {} try: if node.driver_internal_info["is_whole_disk_image"]: uuid_dict_returned = deploy_utils.deploy_disk_image(**params) else: uuid_dict_returned = deploy_utils.deploy_partition_image(**params) except Exception as e: msg = _("Deploy failed for instance %(instance)s. " "Error: %(error)s") % { "instance": node.instance_uuid, "error": e, } _fail_deploy(task, msg) root_uuid_or_disk_id = uuid_dict_returned.get("root uuid", uuid_dict_returned.get("disk identifier")) if not root_uuid_or_disk_id: msg = ( _("Couldn't determine the UUID of the root " "partition or the disk identifier after deploying " "node %s") % node.uuid ) _fail_deploy(task, msg) if params.get("preserve_ephemeral", False): # Save disk layout information, to check that they are unchanged # for any future rebuilds _save_disk_layout(node, parse_instance_info(node)) destroy_images(node.uuid) return uuid_dict_returned
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: a dictionary containing the following keys: For partition image: 'root uuid': UUID of root partition 'efi system partition uuid': UUID of the uefi system partition (if boot mode is uefi). NOTE: If key exists but value is None, it means partition doesn't exist. For whole disk image: 'disk identifier': ID of the disk to which image was deployed. """ node = task.node params = get_deploy_info(node, **kwargs) def _fail_deploy(task, msg, raise_exception=True): """Fail the deploy after logging and setting error states.""" if isinstance(msg, Exception): msg = (_('Deploy failed for instance %(instance)s. ' 'Error: %(error)s') % {'instance': node.instance_uuid, 'error': msg}) deploy_utils.set_failed_state(task, msg) destroy_images(task.node.uuid) if raise_exception: raise exception.InstanceDeployFailure(msg) # NOTE(lucasagomes): Let's make sure we don't log the full content # of the config drive here because it can be up to 64MB in size, # so instead let's log "***" in case config drive is enabled. if LOG.isEnabledFor(logging.logging.DEBUG): log_params = { k: params[k] if k != 'configdrive' else '***' for k in params } LOG.debug('Continuing deployment for node %(node)s, params %(params)s', {'node': node.uuid, 'params': log_params}) uuid_dict_returned = {} try: if node.driver_internal_info['is_whole_disk_image']: uuid_dict_returned = deploy_utils.deploy_disk_image(**params) else: uuid_dict_returned = deploy_utils.deploy_partition_image(**params) except exception.IronicException as e: with excutils.save_and_reraise_exception(): LOG.error(_LE('Deploy of instance %(instance)s on node %(node)s ' 'failed: %(error)s'), {'instance': node.instance_uuid, 'node': node.uuid, 'error': e}) _fail_deploy(task, e, raise_exception=False) except Exception as e: LOG.exception(_LE('Deploy of instance %(instance)s on node %(node)s ' 'failed with exception'), {'instance': node.instance_uuid, 'node': node.uuid}) _fail_deploy(task, e) root_uuid_or_disk_id = uuid_dict_returned.get( 'root uuid', uuid_dict_returned.get('disk identifier')) if not root_uuid_or_disk_id: msg = (_("Couldn't determine the UUID of the root " "partition or the disk identifier after deploying " "node %s") % node.uuid) LOG.error(msg) _fail_deploy(task, msg) if params.get('preserve_ephemeral', False): # Save disk layout information, to check that they are unchanged # for any future rebuilds _save_disk_layout(node, deploy_utils.parse_instance_info(node)) destroy_images(node.uuid) return uuid_dict_returned