'Rebuild/redeploy an instance.
This version of rebuild() allows for supporting the option to
preserve the ephemeral partition. We cannot call spawn() from
here because it will attempt to set the instance_uuid value
again, which is not allowed by the Ironic API. It also requires
the instance to not have an \'active\' provision state, but we
cannot safely change that. Given that, we implement only the
portions of spawn() we need within rebuild().
:param context: The security context.
:param instance: The instance object.
:param image_meta: Image object returned by nova.image.glance
that defines the image from which to boot this instance. Ignored
by this driver.
:param injected_files: User files to inject into instance. Ignored
by this driver.
:param admin_password: Administrator password to set in
instance. Ignored by this driver.
:param bdms: block-device-mappings to use for rebuild. Ignored
by this driver.
:param detach_block_devices: function to detach block devices. See
nova.compute.manager.ComputeManager:_rebuild_default_impl for
usage. Ignored by this driver.
:param attach_block_devices: function to attach block devices. See
nova.compute.manager.ComputeManager:_rebuild_default_impl for
usage. Ignored by this driver.
:param network_info: Instance network information. Ignored by
this driver.
:param recreate: Boolean value; if True the instance is
recreated on a new hypervisor - all the cleanup of old state is
skipped. Ignored by this driver.
:param block_device_info: Instance block device
information. Ignored by this driver.
:param preserve_ephemeral: Boolean value; if True the ephemeral
must be preserved on rebuild.'

def rebuild(self, context, instance, image_meta, injected_files, admin_password, bdms, detach_block_devices, attach_block_devices, network_info=None, recreate=False, block_device_info=None, preserve_ephemeral=False):

    LOG.debug('Rebuild    called    for    instance', instance=instance)
    instance.task_state = task_states.REBUILD_SPAWNING
    instance.save(expected_task_state=[task_states.REBUILDING])
    node_uuid = instance.node
    node = self._get_node(node_uuid)
    self._add_instance_info_to_node(node, instance, image_meta, instance.flavor, preserve_ephemeral)
    try:
        self.ironicclient.call('node.set_provision_state', node_uuid, ironic_states.REBUILD)
    except (exception.NovaException, ironic.exc.InternalServerError, ironic.exc.BadRequest) as e:
        msg = (_('Failed    to    request    Ironic    to    rebuild    instance    %(inst)s:    %(reason)s') % {'inst': instance.uuid, 'reason': six.text_type(e)})
        raise exception.InstanceDeployFailure(msg)
    timer = loopingcall.FixedIntervalLoopingCall(self._wait_for_active, instance)
    timer.start(interval=CONF.ironic.api_retry_interval).wait()
    LOG.info('Instance    was    successfully    rebuilt', instance=instance)
