'Reboot an instance on this host.'

@wrap_exception()
@reverts_task_state
@wrap_instance_event(prefix='compute')
@wrap_instance_fault
def reboot_instance(self, context, instance, block_device_info, reboot_type):

    if (reboot_type == 'SOFT'):
        instance.task_state = task_states.REBOOT_PENDING
        expected_states = (task_states.REBOOTING, task_states.REBOOT_PENDING, task_states.REBOOT_STARTED)
    else:
        instance.task_state = task_states.REBOOT_PENDING_HARD
        expected_states = (task_states.REBOOTING_HARD, task_states.REBOOT_PENDING_HARD, task_states.REBOOT_STARTED_HARD)
    context = context.elevated()
    LOG.info('Rebooting    instance', instance=instance)
    block_device_info = self._get_instance_block_device_info(context, instance)
    network_info = self.network_api.get_instance_nw_info(context, instance)
    self._notify_about_instance_usage(context, instance, 'reboot.start')
    compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.REBOOT, phase=fields.NotificationPhase.START)
    instance.power_state = self._get_power_state(context, instance)
    instance.save(expected_task_state=expected_states)
    if (instance.power_state != power_state.RUNNING):
        state = instance.power_state
        running = power_state.RUNNING
        LOG.warning('trying    to    reboot    a    non-running    instance:    (state:    %(state)s    expected:    %(running)s)', {'state': state, 'running': running}, instance=instance)
    def bad_volumes_callback(bad_devices):
        self._handle_bad_volumes_detached(context, instance, bad_devices, block_device_info)
    try:
        if (instance.vm_state == vm_states.RESCUED):
            new_vm_state = vm_states.RESCUED
        else:
            new_vm_state = vm_states.ACTIVE
        new_power_state = None
        if (reboot_type == 'SOFT'):
            instance.task_state = task_states.REBOOT_STARTED
            expected_state = task_states.REBOOT_PENDING
        else:
            instance.task_state = task_states.REBOOT_STARTED_HARD
            expected_state = task_states.REBOOT_PENDING_HARD
        instance.save(expected_task_state=expected_state)
        self.driver.reboot(context, instance, network_info, reboot_type, block_device_info=block_device_info, bad_volumes_callback=bad_volumes_callback)
    except Exception as error:
        with excutils.save_and_reraise_exception() as ctxt:
            exc_info = sys.exc_info()
            new_power_state = self._get_power_state(context, instance)
            if (new_power_state == power_state.RUNNING):
                LOG.warning('Reboot    failed    but    instance    is    running', instance=instance)
                compute_utils.add_instance_fault_from_exc(context, instance, error, exc_info)
                self._notify_about_instance_usage(context, instance, 'reboot.error', fault=error)
                compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.REBOOT, phase=fields.NotificationPhase.ERROR, exception=error)
                ctxt.reraise = False
            else:
                LOG.error('Cannot    reboot    instance:    %s', error, instance=instance)
                self._set_instance_obj_error_state(context, instance)
    if (not new_power_state):
        new_power_state = self._get_power_state(context, instance)
    try:
        instance.power_state = new_power_state
        instance.vm_state = new_vm_state
        instance.task_state = None
        instance.save()
    except exception.InstanceNotFound:
        LOG.warning('Instance    disappeared    during    reboot', instance=instance)
    self._notify_about_instance_usage(context, instance, 'reboot.end')
    compute_utils.notify_about_instance_action(context, instance, self.host, action=fields.NotificationAction.REBOOT, phase=fields.NotificationPhase.END)
