def get_calcjob_report(calcjob):
    """
    Return a multi line string representation of the log messages and output of a given calcjob

    :param calcjob: the calcjob node
    :return: a string representation of the log messages and scheduler output
    """
    from aiida import orm
    from aiida.common.datastructures import CalcJobState
    log_messages = orm.Log.objects.get_logs_for(calcjob)
    scheduler_out = calcjob.get_scheduler_stdout()
    scheduler_err = calcjob.get_scheduler_stderr()
    calcjob_state = calcjob.get_state()
    scheduler_state = calcjob.get_scheduler_state()
    report = []
    if calcjob_state == CalcJobState.WITHSCHEDULER:
        state_string = '{}, scheduler state: {}'.format(calcjob_state, 
            scheduler_state if scheduler_state else '(unknown)')
    else:
        state_string = '{}'.format(calcjob_state)
    label_string = ' [{}]'.format(calcjob.label) if calcjob.label else ''
    report.append('*** {}{}: {}'.format(calcjob.pk, label_string, state_string)
        )
    if scheduler_out is None:
        report.append('*** Scheduler output: N/A')
    elif scheduler_out:
        report.append('*** Scheduler output:\n{}'.format(scheduler_out))
    else:
        report.append('*** (empty scheduler output file)')
    if scheduler_err is None:
        report.append('*** Scheduler errors: N/A')
    elif scheduler_err:
        report.append('*** Scheduler errors:\n{}'.format(scheduler_err))
    else:
        report.append('*** (empty scheduler errors file)')
    if log_messages:
        report.append('*** {} LOG MESSAGES:'.format(len(log_messages)))
    else:
        report.append('*** 0 LOG MESSAGES')
    for log in log_messages:
        report.append('+-> {} at {}'.format(log.levelname, log.time))
        for message in log.message.splitlines():
            report.append(' | {}'.format(message))
    return '\n'.join(report)
