Esempio n. 1
0
    def main(self, stdscr, server, eventHandler):
    #-------------------------------------------------------------------------#
        height, width = stdscr.getmaxyx()

        # for now split it like that:
        # MAIN_y + THREAD_y = 2/3 screen at the top
        # MAIN_x = 2/3 left, THREAD_y = 1/3 right
        # CLI_y = 1/3 of screen at the bottom
        # CLI_x = full

        main_left = 0
        main_top = 0
        main_height = ( height / 3 * 2 )
        main_width = ( width / 3 ) * 2
        clo_left = main_left
        clo_top = main_top + main_height
        clo_height = height - main_height - main_top - 1
        clo_width = width
        cli_left = main_left
        cli_top = clo_top + clo_height
        cli_height = 1
        cli_width = width
        thread_left = main_left + main_width
        thread_top = main_top
        thread_height = main_height
        thread_width = width - main_width

        #tw = self.TitleWindow( 0, 0, width, main_top )
        mw = self.MainWindow( main_left, main_top, main_width, main_height )
        taw = self.ThreadActivityWindow( thread_left, thread_top, thread_width, thread_height )
        clo = self.ShellOutputWindow( clo_left, clo_top, clo_width, clo_height )
        cli = self.ShellInputWindow( cli_left, cli_top, cli_width, cli_height )
        cli.setText( 0, 0, "BB>" )

        mw.setStatus("Idle")

        helper = uihelper.BBUIHelper()
        shutdown = 0
   
        try:
            cmdline = server.runCommand(["getCmdLineAction"])
            if not cmdline:
                return
            ret = server.runCommand(cmdline)
            if ret != True:
                print "Couldn't get default commandlind! %s" % ret
                return
        except xmlrpclib.Fault, x:
            print "XMLRPC Fault getting commandline:\n %s" % x
            return
Esempio n. 2
0
def init(server, eventHandler):

    # Get values of variables which control our output
    includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"])
    loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])

    helper = uihelper.BBUIHelper()

    try:
        cmdline = server.runCommand(["getCmdLineAction"])
        #print cmdline
        if not cmdline:
            return 1
        ret = server.runCommand(cmdline)
        if ret != True:
            print "Couldn't get default commandline! %s" % ret
            return 1
    except xmlrpclib.Fault, x:
        print "XMLRPC Fault getting commandline:\n %s" % x
        return 1
Esempio n. 3
0
def main(server, eventHandler, params, tf = TerminalFilter):

    try:
        if not params.observe_only:
            params.updateToServer(server, os.environ.copy())

        includelogs, loglines, consolelogfile, logconfigfile = _log_settings_from_server(server, params.observe_only)

        loglevel, _ = bb.msg.constructLogOptions()
    except bb.BBHandledException:
        drain_events_errorhandling(eventHandler)
        return 1

    if params.options.quiet == 0:
        console_loglevel = loglevel
    elif params.options.quiet > 2:
        console_loglevel = bb.msg.BBLogFormatter.ERROR
    else:
        console_loglevel = bb.msg.BBLogFormatter.WARNING

    logconfig = {
        "version": 1,
        "handlers": {
            "BitBake.console": {
                "class": "logging.StreamHandler",
                "formatter": "BitBake.consoleFormatter",
                "level": console_loglevel,
                "stream": "ext://sys.stdout",
                "filters": ["BitBake.stdoutFilter"],
                ".": {
                    "is_console": True,
                },
            },
            "BitBake.errconsole": {
                "class": "logging.StreamHandler",
                "formatter": "BitBake.consoleFormatter",
                "level": loglevel,
                "stream": "ext://sys.stderr",
                "filters": ["BitBake.stderrFilter"],
                ".": {
                    "is_console": True,
                },
            },
            # This handler can be used if specific loggers should print on
            # the console at a lower severity than the default. It will
            # display any messages sent to it that are lower than then
            # BitBake.console logging level (so as to prevent duplication of
            # messages). Nothing is attached to this handler by default
            "BitBake.verbconsole": {
                "class": "logging.StreamHandler",
                "formatter": "BitBake.consoleFormatter",
                "level": 1,
                "stream": "ext://sys.stdout",
                "filters": ["BitBake.verbconsoleFilter"],
                ".": {
                    "is_console": True,
                },
            },
        },
        "formatters": {
            # This format instance will get color output enabled by the
            # terminal
            "BitBake.consoleFormatter" : {
                "()": "bb.msg.BBLogFormatter",
                "format": "%(levelname)s: %(message)s"
            },
            # The file log requires a separate instance so that it doesn't get
            # color enabled
            "BitBake.logfileFormatter": {
                "()": "bb.msg.BBLogFormatter",
                "format": "%(levelname)s: %(message)s"
            }
        },
        "filters": {
            "BitBake.stdoutFilter": {
                "()": "bb.msg.LogFilterLTLevel",
                "level": "ERROR"
            },
            "BitBake.stderrFilter": {
                "()": "bb.msg.LogFilterGEQLevel",
                "level": "ERROR"
            },
            "BitBake.verbconsoleFilter": {
                "()": "bb.msg.LogFilterLTLevel",
                "level": console_loglevel
            },
        },
        "loggers": {
            "BitBake": {
                "level": loglevel,
                "handlers": ["BitBake.console", "BitBake.errconsole"],
            }
        },
        "disable_existing_loggers": False
    }

    # Enable the console log file if enabled
    if consolelogfile and not params.options.show_environment and not params.options.show_versions:
        logconfig = bb.msg.mergeLoggingConfig(logconfig, {
                "version": 1,
                "handlers" : {
                    "BitBake.consolelog": {
                        "class": "logging.FileHandler",
                        "formatter": "BitBake.logfileFormatter",
                        "level": loglevel,
                        "filename": consolelogfile,
                    },
                    # Just like verbconsole, anything sent here will go to the
                    # log file, unless it would go to BitBake.consolelog
                    "BitBake.verbconsolelog" : {
                        "class": "logging.FileHandler",
                        "formatter": "BitBake.logfileFormatter",
                        "level": 1,
                        "filename": consolelogfile,
                        "filters": ["BitBake.verbconsolelogFilter"],
                    },
                },
                "filters": {
                    "BitBake.verbconsolelogFilter": {
                        "()": "bb.msg.LogFilterLTLevel",
                        "level": loglevel,
                    },
                },
                "loggers": {
                    "BitBake": {
                        "handlers": ["BitBake.consolelog"],
                    },

                    # Other interesting things that we want to keep an eye on
                    # in the log files in case someone has an issue, but not
                    # necessarily show to the user on the console
                    "BitBake.SigGen.HashEquiv": {
                        "level": "VERBOSE",
                        "handlers": ["BitBake.verbconsolelog"],
                    },
                    "BitBake.RunQueue.HashEquiv": {
                        "level": "VERBOSE",
                        "handlers": ["BitBake.verbconsolelog"],
                    }
                }
            })

        bb.utils.mkdirhier(os.path.dirname(consolelogfile))
        loglink = os.path.join(os.path.dirname(consolelogfile), 'console-latest.log')
        bb.utils.remove(loglink)
        try:
           os.symlink(os.path.basename(consolelogfile), loglink)
        except OSError:
           pass

    conf = bb.msg.setLoggingConfig(logconfig, logconfigfile)

    if sys.stdin.isatty() and sys.stdout.isatty():
        log_exec_tty = True
    else:
        log_exec_tty = False

    helper = uihelper.BBUIHelper()

    # Look for the specially designated handlers which need to be passed to the
    # terminal handler
    console_handlers = [h for h in conf.config['handlers'].values() if getattr(h, 'is_console', False)]

    bb.utils.set_process_name("KnottyUI")

    if params.options.remote_server and params.options.kill_server:
        server.terminateServer()
        return

    llevel, debug_domains = bb.msg.constructLogOptions()
    server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])

    # The logging_tree module is *extremely* helpful in debugging logging
    # domains. Uncomment here to dump the logging tree when bitbake starts
    #import logging_tree
    #logging_tree.printout()

    universe = False
    if not params.observe_only:
        params.updateFromServer(server)
        cmdline = params.parseActions()
        if not cmdline:
            print("Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
            return 1
        if 'msg' in cmdline and cmdline['msg']:
            logger.error(cmdline['msg'])
            return 1
        if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]:
            universe = True

        ret, error = server.runCommand(cmdline['action'])
        if error:
            logger.error("Command '%s' failed: %s" % (cmdline, error))
            return 1
        elif not ret:
            logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
            return 1


    parseprogress = None
    cacheprogress = None
    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []

    printinterval = 5000
    lastprint = time.time()

    termfilter = tf(main, helper, console_handlers, params.options.quiet)
    atexit.register(termfilter.finish)

    while True:
        try:
            if (lastprint + printinterval) <= time.time():
                termfilter.keepAlive(printinterval)
                printinterval += 5000
            event = eventHandler.waitEvent(0)
            if event is None:
                if main.shutdown > 1:
                    break
                if not parseprogress:
                    termfilter.updateFooter()
                event = eventHandler.waitEvent(0.25)
                if event is None:
                    continue
            helper.eventHandler(event)
            if isinstance(event, bb.runqueue.runQueueExitWait):
                if not main.shutdown:
                    main.shutdown = 1
                continue
            if isinstance(event, bb.event.LogExecTTY):
                if log_exec_tty:
                    tries = event.retries
                    while tries:
                        print("Trying to run: %s" % event.prog)
                        if os.system(event.prog) == 0:
                            break
                        time.sleep(event.sleep_delay)
                        tries -= 1
                    if tries:
                        continue
                logger.warning(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                lastprint = time.time()
                printinterval = 5000
                if event.levelno >= bb.msg.BBLogFormatter.ERROR:
                    errors = errors + 1
                    return_value = 1
                elif event.levelno == bb.msg.BBLogFormatter.WARNING:
                    warnings = warnings + 1

                if event.taskpid != 0:
                    # For "normal" logging conditions, don't show note logs from tasks
                    # but do show them if the user has changed the default log level to
                    # include verbose/debug messages
                    if event.levelno <= bb.msg.BBLogFormatter.NOTE and (event.levelno < llevel or (event.levelno == bb.msg.BBLogFormatter.NOTE and llevel != bb.msg.BBLogFormatter.VERBOSE)):
                        continue

                    # Prefix task messages with recipe/task
                    if event.taskpid in helper.pidmap and event.levelno != bb.msg.BBLogFormatter.PLAIN:
                        taskinfo = helper.running_tasks[helper.pidmap[event.taskpid]]
                        event.msg = taskinfo['title'] + ': ' + event.msg
                if hasattr(event, 'fn'):
                    event.msg = event.fn + ': ' + event.msg
                logging.getLogger(event.name).handle(event)
                continue

            if isinstance(event, bb.build.TaskFailedSilent):
                logger.warning("Logfile for failed setscene task is %s" % event.logfile)
                continue
            if isinstance(event, bb.build.TaskFailed):
                return_value = 1
                print_event_log(event, includelogs, loglines, termfilter)
            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
                continue
            if isinstance(event, bb.event.ParseStarted):
                if params.options.quiet > 1:
                    continue
                if event.total == 0:
                    continue
                termfilter.clearFooter()
                parseprogress = new_progress("Parsing recipes", event.total).start()
                continue
            if isinstance(event, bb.event.ParseProgress):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.update(event.current)
                else:
                    bb.warn("Got ParseProgress event for parsing that never started?")
                continue
            if isinstance(event, bb.event.ParseCompleted):
                if params.options.quiet > 1:
                    continue
                if not parseprogress:
                    continue
                parseprogress.finish()
                parseprogress = None
                if params.options.quiet == 0:
                    print(("Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                        % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
                continue

            if isinstance(event, bb.event.CacheLoadStarted):
                if params.options.quiet > 1:
                    continue
                cacheprogress = new_progress("Loading cache", event.total).start()
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                if params.options.quiet > 1:
                    continue
                cacheprogress.update(event.current)
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                if params.options.quiet > 1:
                    continue
                cacheprogress.finish()
                if params.options.quiet == 0:
                    print("Loaded %d entries from dependency cache." % event.num_entries)
                continue

            if isinstance(event, bb.command.CommandFailed):
                return_value = event.exitcode
                if event.error:
                    errors = errors + 1
                    logger.error(str(event))
                main.shutdown = 2
                continue
            if isinstance(event, bb.command.CommandExit):
                if not return_value:
                    return_value = event.exitcode
                main.shutdown = 2
                continue
            if isinstance(event, (bb.command.CommandCompleted, bb.cooker.CookerExit)):
                main.shutdown = 2
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info(str(event))
                continue
            if isinstance(event, bb.event.NoProvider):
                # For universe builds, only show these as warnings, not errors
                if not universe:
                    return_value = 1
                    errors = errors + 1
                    logger.error(str(event))
                else:
                    logger.warning(str(event))
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
                logger.info("Running setscene task %d of %d (%s)" % (event.stats.completed + event.stats.active + event.stats.failed + 1, event.stats.total, event.taskstring))
                continue

            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if event.noexec:
                    tasktype = 'noexec task'
                else:
                    tasktype = 'task'
                logger.info("Running %s %d of %d (%s)",
                            tasktype,
                            event.stats.completed + event.stats.active +
                                event.stats.failed + 1,
                            event.stats.total, event.taskstring)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                return_value = 1
                taskfailures.append(event.taskstring)
                logger.error(str(event))
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
                logger.warning(str(event))
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                continue

            if isinstance(event, bb.event.ProcessStarted):
                if params.options.quiet > 1:
                    continue
                termfilter.clearFooter()
                parseprogress = new_progress(event.processname, event.total)
                parseprogress.start(False)
                continue
            if isinstance(event, bb.event.ProcessProgress):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.update(event.progress)
                else:
                    bb.warn("Got ProcessProgress event for someting that never started?")
                continue
            if isinstance(event, bb.event.ProcessFinished):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.finish()
                parseprogress = None
                continue

            # ignore
            if isinstance(event, (bb.event.BuildBase,
                                  bb.event.MetadataEvent,
                                  bb.event.ConfigParsed,
                                  bb.event.MultiConfigParsed,
                                  bb.event.RecipeParsed,
                                  bb.event.RecipePreFinalise,
                                  bb.runqueue.runQueueEvent,
                                  bb.event.OperationStarted,
                                  bb.event.OperationCompleted,
                                  bb.event.OperationProgress,
                                  bb.event.DiskFull,
                                  bb.event.HeartbeatEvent,
                                  bb.build.TaskProgress)):
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            termfilter.clearFooter()
            # ignore interrupted io
            if ioerror.args[0] == 4:
                continue
            sys.stderr.write(str(ioerror))
            if not params.observe_only:
                _, error = server.runCommand(["stateForceShutdown"])
            main.shutdown = 2
        except KeyboardInterrupt:
            termfilter.clearFooter()
            if params.observe_only:
                print("\nKeyboard Interrupt, exiting observer...")
                main.shutdown = 2

            def state_force_shutdown():
                print("\nSecond Keyboard Interrupt, stopping...\n")
                _, error = server.runCommand(["stateForceShutdown"])
                if error:
                    logger.error("Unable to cleanly stop: %s" % error)

            if not params.observe_only and main.shutdown == 1:
                state_force_shutdown()

            if not params.observe_only and main.shutdown == 0:
                print("\nKeyboard Interrupt, closing down...\n")
                interrupted = True
                # Capture the second KeyboardInterrupt during stateShutdown is running
                try:
                    _, error = server.runCommand(["stateShutdown"])
                    if error:
                        logger.error("Unable to cleanly shutdown: %s" % error)
                except KeyboardInterrupt:
                    state_force_shutdown()

            main.shutdown = main.shutdown + 1
            pass
        except Exception as e:
            import traceback
            sys.stderr.write(traceback.format_exc())
            if not params.observe_only:
                _, error = server.runCommand(["stateForceShutdown"])
            main.shutdown = 2
            return_value = 1
    try:
        termfilter.clearFooter()
        summary = ""
        if taskfailures:
            summary += pluralise("\nSummary: %s task failed:",
                                 "\nSummary: %s tasks failed:", len(taskfailures))
            for failure in taskfailures:
                summary += "\n  %s" % failure
        if warnings:
            summary += pluralise("\nSummary: There was %s WARNING message shown.",
                                 "\nSummary: There were %s WARNING messages shown.", warnings)
        if return_value and errors:
            summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
                                 "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
        if summary and params.options.quiet == 0:
            print(summary)

        if interrupted:
            print("Execution was interrupted, returning a non-zero exit code.")
            if return_value == 0:
                return_value = 1
    except IOError as e:
        import errno
        if e.errno == errno.EPIPE:
            pass

    logging.shutdown()

    return return_value
Esempio n. 4
0
def main(server, eventHandler, params):
    params.updateToServer(server, os.environ.copy())

    includelogs, loglines = _log_settings_from_server(server)

    ui = TeamCityUI()

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    errconsole = logging.StreamHandler(sys.stderr)
    format = TeamcityLogFormatter()
    if params.options.quiet == 0:
        forcelevel = None
    elif params.options.quiet > 2:
        forcelevel = bb.msg.BBLogFormatter.ERROR
    else:
        forcelevel = bb.msg.BBLogFormatter.WARNING
    bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut, forcelevel)
    bb.msg.addDefaultlogFilter(errconsole, bb.msg.BBLogFilterStdErr)
    console.setFormatter(format)
    errconsole.setFormatter(format)
    if not bb.msg.has_console_handler(logger):
        logger.addHandler(console)
        logger.addHandler(errconsole)

    if params.options.remote_server and params.options.kill_server:
        server.terminateServer()
        return

    if params.observe_only:
        logger.error("Observe-only mode not supported in this UI")
        return 1

    llevel, debug_domains = bb.msg.constructLogOptions()
    server.runCommand([
        "setEventMask",
        server.getEventHandle(), llevel, debug_domains, _evt_list
    ])

    try:
        params.updateFromServer(server)
        cmdline = params.parseActions()
        if not cmdline:
            logger.error("No task given")
            return 1
        if 'msg' in cmdline and cmdline['msg']:
            logger.error(cmdline['msg'])
            return 1
        cmdline = cmdline['action']
        ret, error = server.runCommand(cmdline)
        if error:
            logger.error("{0}: {1}".format(cmdline, error))
            return 1
        elif not ret:
            logger.error("Couldn't get default commandline: {0}".format(re))
            return 1
    except xmlrpc.client.Fault as x:
        logger.error("XMLRPC Fault getting commandline: {0}".format(x))
        return 1

    active_process_total = None
    is_tasks_running = False

    while True:
        try:
            event = eventHandler.waitEvent(0.25)
            if not event:
                continue

            helper.eventHandler(event)

            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
            if isinstance(event, logging.LogRecord):
                # Don't report sstate failures as errors, since Yocto will just run the tasks for real
                if event.msg == "No suitable staging package found" or (
                        event.msg.startswith(
                            "Fetcher failure: Unable to find file")
                        and "downloadfilename" in event.msg
                        and "sstate" in event.msg):
                    event.levelno = bb.msg.BBLogFormatter.WARNING
                if event.taskpid != 0:
                    # For "normal" logging conditions, don't show note logs from tasks
                    # but do show them if the user has changed the default log level to
                    # include verbose/debug messages
                    if event.levelno <= bb.msg.BBLogFormatter.NOTE and (
                            event.levelno < llevel or
                        (event.levelno == bb.msg.BBLogFormatter.NOTE
                         and llevel != bb.msg.BBLogFormatter.VERBOSE)):
                        continue

                    # Prefix task messages with recipe/task
                    if event.taskpid in helper.running_tasks and event.levelno != bb.msg.BBLogFormatter.PLAIN:
                        taskinfo = helper.running_tasks[event.taskpid]
                        event.msg = taskinfo['title'] + ': ' + event.msg
                if hasattr(event, 'fn'):
                    event.msg = event.fn + ': ' + event.msg
                logger.handle(event)
            if isinstance(event, bb.build.TaskFailedSilent):
                logger.warning("Logfile for failed setscene task is %s" %
                               event.logfile)
                continue
            if isinstance(event, bb.build.TaskFailed):
                rt = "{0}-{1}:{2}".format(event.pn,
                                          event.pv.replace("AUTOINC", "0"),
                                          event.task)

                logfile = event.logfile
                if not logfile or not os.path.exists(logfile):
                    TeamCityUI.emit_service_message(
                        "buildProblem",
                        description=
                        "{0}\nUnknown failure (no log file available)".format(
                            rt))
                    if not event.task.endswith("_setscene"):
                        server.runCommand(["stateForceShutdown"])
                    continue

                details = deque(maxlen=loglines)
                error_lines = []
                if includelogs and not event.errprinted:
                    with open(logfile, "r") as f:
                        while True:
                            line = f.readline()
                            if not line:
                                break
                            line = line.rstrip()
                            details.append(' | %s' % line)
                            # TODO: a less stupid check for errors
                            if (event.task == "do_compile") and ("error:"
                                                                 in line):
                                error_lines.append(line)

                if error_lines:
                    TeamCityUI.emit_service_message("compilationStarted",
                                                    compiler=rt)
                    for line in error_lines:
                        TeamCityUI.emit_service_message("message",
                                                        text=line,
                                                        status="ERROR")
                    TeamCityUI.emit_service_message("compilationFinished",
                                                    compiler=rt)
                else:
                    TeamCityUI.emit_service_message("buildProblem",
                                                    description=rt)

                err = "Logfile of failure stored in: %s" % logfile
                if details:
                    ui.block_start("{0} task log".format(rt))
                    # TeamCity seems to choke on service messages longer than about 63800 characters, so if error
                    # details is longer than, say, 60000, batch it up into several messages.
                    first_message = True
                    while details:
                        detail_len = 0
                        batch = deque()
                        while details and detail_len < 60000:
                            # TODO: This code doesn't bother to handle lines that themselves are extremely long.
                            line = details.popleft()
                            batch.append(line)
                            detail_len += len(line)

                        if first_message:
                            batch.appendleft("Log data follows:")
                            first_message = False
                            TeamCityUI.emit_service_message(
                                "message",
                                text=err,
                                status="ERROR",
                                errorDetails="\n".join(batch))
                        else:
                            TeamCityUI.emit_service_message(
                                "message",
                                text="[continued]",
                                status="ERROR",
                                errorDetails="\n".join(batch))
                    ui.block_end()
                else:
                    TeamCityUI.emit_service_message("message",
                                                    text=err,
                                                    status="ERROR",
                                                    errorDetails="")

                if not event.task.endswith("_setscene"):
                    server.runCommand(["stateForceShutdown"])

            if isinstance(event, bb.event.ProcessStarted):
                if event.processname in [
                        "Initialising tasks",
                        "Checking sstate mirror object availability"
                ]:
                    active_process_total = event.total
                    ui.block_start(event.processname)
            if isinstance(event, bb.event.ProcessFinished):
                if event.processname in [
                        "Initialising tasks",
                        "Checking sstate mirror object availability"
                ]:
                    ui.progress(event.processname, 100)
                    ui.block_end()
            if isinstance(event, bb.event.ProcessProgress):
                if event.processname in [
                        "Initialising tasks",
                        "Checking sstate mirror object availability"
                ] and active_process_total != 0:
                    ui.progress(event.processname,
                                event.progress * 100 / active_process_total)
            if isinstance(event, bb.event.CacheLoadStarted):
                ui.block_start("Loading cache")
            if isinstance(event, bb.event.CacheLoadProgress):
                if event.total != 0:
                    ui.progress("Loading cache",
                                math.floor(event.current * 100 / event.total))
            if isinstance(event, bb.event.CacheLoadCompleted):
                ui.progress("Loading cache", 100)
                ui.block_end()
            if isinstance(event, bb.event.ParseStarted):
                ui.block_start(
                    "Parsing recipes and checking upstream revisions")
            if isinstance(event, bb.event.ParseProgress):
                if event.total != 0:
                    ui.progress("Parsing recipes",
                                math.floor(event.current * 100 / event.total))
            if isinstance(event, bb.event.ParseCompleted):
                ui.progress("Parsing recipes", 100)
                ui.block_end()
            if isinstance(event, bb.command.CommandCompleted):
                return
            if isinstance(event, bb.command.CommandFailed):
                logger.error(str(event))
                return 1
            if isinstance(event, bb.event.MultipleProviders):
                logger.warning(str(event))
                continue
            if isinstance(event, bb.event.NoProvider):
                logger.error(str(event))
                continue
            if isinstance(event, bb.command.CommandExit):
                return
            if isinstance(event, bb.cooker.CookerExit):
                return
            if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
                if not is_tasks_running:
                    is_tasks_running = True
                    ui.block_start("Running tasks")
                if event.stats.total != 0:
                    ui.progress("Running setscene tasks",
                                (event.stats.completed + event.stats.active +
                                 event.stats.failed + 1) * 100 /
                                event.stats.total)
            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if not is_tasks_running:
                    is_tasks_running = True
                    ui.block_start("Running tasks")
                if event.stats.total != 0:
                    pseudo_total = event.stats.total - event.stats.skipped
                    pseudo_complete = event.stats.completed + event.stats.active - event.stats.skipped + event.stats.failed + 1
                    # TODO: sometimes this gives over 100%
                    ui.progress(
                        "Running runqueue tasks",
                        (pseudo_complete) * 100 / pseudo_total,
                        " ({0}/{1})".format(pseudo_complete, pseudo_total))
            if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
                logger.warning(str(event))
                continue
            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                logger.error(str(event))
                return 1
            if isinstance(event, bb.event.LogExecTTY):
                pass
        except EnvironmentError as ioerror:
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except Exception as ex:
            logger.error(str(ex))
Esempio n. 5
0
def main(server, eventHandler, params, tf = TerminalFilter):

    if not params.observe_only:
        params.updateToServer(server, os.environ.copy())

    includelogs, loglines, consolelogfile = _log_settings_from_server(server, params.observe_only)

    if sys.stdin.isatty() and sys.stdout.isatty():
        log_exec_tty = True
    else:
        log_exec_tty = False

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    errconsole = logging.StreamHandler(sys.stderr)
    format_str = "%(levelname)s: %(message)s"
    format = bb.msg.BBLogFormatter(format_str)
    if params.options.quiet == 0:
        forcelevel = None
    elif params.options.quiet > 2:
        forcelevel = bb.msg.BBLogFormatter.ERROR
    else:
        forcelevel = bb.msg.BBLogFormatter.WARNING
    bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut, forcelevel)
    bb.msg.addDefaultlogFilter(errconsole, bb.msg.BBLogFilterStdErr)
    console.setFormatter(format)
    errconsole.setFormatter(format)
    if not bb.msg.has_console_handler(logger):
        logger.addHandler(console)
        logger.addHandler(errconsole)

    bb.utils.set_process_name("KnottyUI")

    if params.options.remote_server and params.options.kill_server:
        server.terminateServer()
        return

    consolelog = None
    if consolelogfile and not params.options.show_environment and not params.options.show_versions:
        bb.utils.mkdirhier(os.path.dirname(consolelogfile))
        conlogformat = bb.msg.BBLogFormatter(format_str)
        consolelog = logging.FileHandler(consolelogfile)
        bb.msg.addDefaultlogFilter(consolelog)
        consolelog.setFormatter(conlogformat)
        logger.addHandler(consolelog)
        loglink = os.path.join(os.path.dirname(consolelogfile), 'console-latest.log')
        bb.utils.remove(loglink)
        try:
           os.symlink(os.path.basename(consolelogfile), loglink)
        except OSError:
           pass

    llevel, debug_domains = bb.msg.constructLogOptions()
    server.runCommand(["setEventMask", server.getEventHandle(), llevel, debug_domains, _evt_list])

    universe = False
    if not params.observe_only:
        params.updateFromServer(server)
        cmdline = params.parseActions()
        if not cmdline:
            print("Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information.")
            return 1
        if 'msg' in cmdline and cmdline['msg']:
            logger.error(cmdline['msg'])
            return 1
        if cmdline['action'][0] == "buildTargets" and "universe" in cmdline['action'][1]:
            universe = True

        ret, error = server.runCommand(cmdline['action'])
        if error:
            logger.error("Command '%s' failed: %s" % (cmdline, error))
            return 1
        elif ret != True:
            logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
            return 1


    parseprogress = None
    cacheprogress = None
    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []

    printinterval = 5000
    lastprint = time.time()

    termfilter = tf(main, helper, console, errconsole, format, params.options.quiet)
    atexit.register(termfilter.finish)

    while True:
        try:
            if (lastprint + printinterval) <= time.time():
                termfilter.keepAlive(printinterval)
                printinterval += 5000
            event = eventHandler.waitEvent(0)
            if event is None:
                if main.shutdown > 1:
                    break
                termfilter.updateFooter()
                event = eventHandler.waitEvent(0.25)
                if event is None:
                    continue
            helper.eventHandler(event)
            if isinstance(event, bb.runqueue.runQueueExitWait):
                if not main.shutdown:
                    main.shutdown = 1
                continue
            if isinstance(event, bb.event.LogExecTTY):
                if log_exec_tty:
                    tries = event.retries
                    while tries:
                        print("Trying to run: %s" % event.prog)
                        if os.system(event.prog) == 0:
                            break
                        time.sleep(event.sleep_delay)
                        tries -= 1
                    if tries:
                        continue
                logger.warning(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                lastprint = time.time()
                printinterval = 5000
                if event.levelno >= format.ERROR:
                    errors = errors + 1
                    return_value = 1
                elif event.levelno == format.WARNING:
                    warnings = warnings + 1

                if event.taskpid != 0:
                    # For "normal" logging conditions, don't show note logs from tasks
                    # but do show them if the user has changed the default log level to
                    # include verbose/debug messages
                    if event.levelno <= format.NOTE and (event.levelno < llevel or (event.levelno == format.NOTE and llevel != format.VERBOSE)):
                        continue

                    # Prefix task messages with recipe/task
                    if event.taskpid in helper.running_tasks and event.levelno != format.PLAIN:
                        taskinfo = helper.running_tasks[event.taskpid]
                        event.msg = taskinfo['title'] + ': ' + event.msg
                if hasattr(event, 'fn'):
                    event.msg = event.fn + ': ' + event.msg
                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailedSilent):
                logger.warning("Logfile for failed setscene task is %s" % event.logfile)
                continue
            if isinstance(event, bb.build.TaskFailed):
                return_value = 1
                print_event_log(event, includelogs, loglines, termfilter)
            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
                continue
            if isinstance(event, bb.event.ParseStarted):
                if params.options.quiet > 1:
                    continue
                if event.total == 0:
                    continue
                parseprogress = new_progress("Parsing recipes", event.total).start()
                continue
            if isinstance(event, bb.event.ParseProgress):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.update(event.current)
                else:
                    bb.warn("Got ParseProgress event for parsing that never started?")
                continue
            if isinstance(event, bb.event.ParseCompleted):
                if params.options.quiet > 1:
                    continue
                if not parseprogress:
                    continue
                parseprogress.finish()
                pasreprogress = None
                if params.options.quiet == 0:
                    print(("Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                        % ( event.total, event.cached, event.parsed, event.virtuals, event.skipped, event.masked, event.errors)))
                continue

            if isinstance(event, bb.event.CacheLoadStarted):
                if params.options.quiet > 1:
                    continue
                cacheprogress = new_progress("Loading cache", event.total).start()
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                if params.options.quiet > 1:
                    continue
                cacheprogress.update(event.current)
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                if params.options.quiet > 1:
                    continue
                cacheprogress.finish()
                if params.options.quiet == 0:
                    print("Loaded %d entries from dependency cache." % event.num_entries)
                continue

            if isinstance(event, bb.command.CommandFailed):
                return_value = event.exitcode
                if event.error:
                    errors = errors + 1
                    logger.error(str(event))
                main.shutdown = 2
                continue
            if isinstance(event, bb.command.CommandExit):
                if not return_value:
                    return_value = event.exitcode
                continue
            if isinstance(event, (bb.command.CommandCompleted, bb.cooker.CookerExit)):
                main.shutdown = 2
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info(str(event))
                continue
            if isinstance(event, bb.event.NoProvider):
                # For universe builds, only show these as warnings, not errors
                if not universe:
                    return_value = 1
                    errors = errors + 1
                    logger.error(str(event))
                else:
                    logger.warning(str(event))
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
                logger.info("Running setscene task %d of %d (%s)" % (event.stats.completed + event.stats.active + event.stats.failed + 1, event.stats.total, event.taskstring))
                continue

            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if event.noexec:
                    tasktype = 'noexec task'
                else:
                    tasktype = 'task'
                logger.info("Running %s %d of %d (%s)",
                            tasktype,
                            event.stats.completed + event.stats.active +
                                event.stats.failed + 1,
                            event.stats.total, event.taskstring)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                return_value = 1
                taskfailures.append(event.taskstring)
                logger.error(str(event))
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
                logger.warning(str(event))
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                continue

            if isinstance(event, bb.event.ProcessStarted):
                if params.options.quiet > 1:
                    continue
                parseprogress = new_progress(event.processname, event.total)
                parseprogress.start(False)
                continue
            if isinstance(event, bb.event.ProcessProgress):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.update(event.progress)
                else:
                    bb.warn("Got ProcessProgress event for someting that never started?")
                continue
            if isinstance(event, bb.event.ProcessFinished):
                if params.options.quiet > 1:
                    continue
                if parseprogress:
                    parseprogress.finish()
                parseprogress = None
                continue

            # ignore
            if isinstance(event, (bb.event.BuildBase,
                                  bb.event.MetadataEvent,
                                  bb.event.StampUpdate,
                                  bb.event.ConfigParsed,
                                  bb.event.MultiConfigParsed,
                                  bb.event.RecipeParsed,
                                  bb.event.RecipePreFinalise,
                                  bb.runqueue.runQueueEvent,
                                  bb.event.OperationStarted,
                                  bb.event.OperationCompleted,
                                  bb.event.OperationProgress,
                                  bb.event.DiskFull,
                                  bb.event.HeartbeatEvent,
                                  bb.build.TaskProgress)):
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            termfilter.clearFooter()
            # ignore interrupted io
            if ioerror.args[0] == 4:
                continue
            sys.stderr.write(str(ioerror))
            if not params.observe_only:
                _, error = server.runCommand(["stateForceShutdown"])
            main.shutdown = 2
        except KeyboardInterrupt:
            termfilter.clearFooter()
            if params.observe_only:
                print("\nKeyboard Interrupt, exiting observer...")
                main.shutdown = 2
            if not params.observe_only and main.shutdown == 1:
                print("\nSecond Keyboard Interrupt, stopping...\n")
                _, error = server.runCommand(["stateForceShutdown"])
                if error:
                    logger.error("Unable to cleanly stop: %s" % error)
            if not params.observe_only and main.shutdown == 0:
                print("\nKeyboard Interrupt, closing down...\n")
                interrupted = True
                _, error = server.runCommand(["stateShutdown"])
                if error:
                    logger.error("Unable to cleanly shutdown: %s" % error)
            main.shutdown = main.shutdown + 1
            pass
        except Exception as e:
            import traceback
            sys.stderr.write(traceback.format_exc())
            if not params.observe_only:
                _, error = server.runCommand(["stateForceShutdown"])
            main.shutdown = 2
            return_value = 1
    try:
        termfilter.clearFooter()
        summary = ""
        if taskfailures:
            summary += pluralise("\nSummary: %s task failed:",
                                 "\nSummary: %s tasks failed:", len(taskfailures))
            for failure in taskfailures:
                summary += "\n  %s" % failure
        if warnings:
            summary += pluralise("\nSummary: There was %s WARNING message shown.",
                                 "\nSummary: There were %s WARNING messages shown.", warnings)
        if return_value and errors:
            summary += pluralise("\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
                                 "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.", errors)
        if summary and params.options.quiet == 0:
            print(summary)

        if interrupted:
            print("Execution was interrupted, returning a non-zero exit code.")
            if return_value == 0:
                return_value = 1
    except IOError as e:
        import errno
        if e.errno == errno.EPIPE:
            pass

    if consolelog:
        logger.removeHandler(consolelog)
        consolelog.close()

    return return_value
Esempio n. 6
0
def main(server, eventHandler, tf=TerminalFilter):

    # Get values of variables which control our output
    includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"])
    loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
    consolelogfile = server.runCommand(["getVariable", "BB_CONSOLELOG"])
    if sys.stdin.isatty() and sys.stdout.isatty():
        log_exec_tty = True
    else:
        log_exec_tty = False

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(format)
    logger.addHandler(console)
    if consolelogfile:
        bb.utils.mkdirhier(os.path.dirname(consolelogfile))
        consolelog = logging.FileHandler(consolelogfile)
        bb.msg.addDefaultlogFilter(consolelog)
        consolelog.setFormatter(format)
        logger.addHandler(consolelog)

    try:
        cmdline = server.runCommand(["getCmdLineAction"])
        if not cmdline:
            print(
                "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
            )
            return 1
        elif not cmdline['action']:
            print(cmdline['msg'])
            return 1
        ret = server.runCommand(cmdline['action'])
        if ret != True:
            print("Couldn't get default commandline! %s" % ret)
            return 1
    except xmlrpclib.Fault as x:
        print("XMLRPC Fault getting commandline:\n %s" % x)
        return 1

    parseprogress = None
    cacheprogress = None
    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []

    termfilter = tf(main, helper, console, format)

    while True:
        try:
            termfilter.updateFooter()
            event = eventHandler.waitEvent(0.25)
            if event is None:
                if main.shutdown > 1:
                    break
                continue
            helper.eventHandler(event)
            if isinstance(event, bb.runqueue.runQueueExitWait):
                if not main.shutdown:
                    main.shutdown = 1

            if isinstance(event, bb.event.LogExecTTY):
                if log_exec_tty:
                    tries = event.retries
                    while tries:
                        print "Trying to run: %s" % event.prog
                        if os.system(event.prog) == 0:
                            break
                        time.sleep(event.sleep_delay)
                        tries -= 1
                    if tries:
                        continue
                logger.warn(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                if event.levelno >= format.ERROR:
                    errors = errors + 1
                    return_value = 1
                elif event.levelno == format.WARNING:
                    warnings = warnings + 1
                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= format.NOTE:
                    continue
                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                return_value = 1
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    termfilter.clearFooter()
                    print("ERROR: Logfile of failure stored in: %s" % logfile)
                    if includelogs and not event.errprinted:
                        print("Log data follows:")
                        f = open(logfile, "r")
                        lines = []
                        while True:
                            l = f.readline()
                            if l == '':
                                break
                            l = l.rstrip()
                            if loglines:
                                lines.append(' | %s' % l)
                                if len(lines) > int(loglines):
                                    lines.pop(0)
                            else:
                                print('| %s' % l)
                        f.close()
                        if lines:
                            for line in lines:
                                print(line)
            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
                continue
            if isinstance(event, bb.event.ParseStarted):
                if event.total == 0:
                    continue
                parseprogress = new_progress("Parsing recipes",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.ParseProgress):
                parseprogress.update(event.current)
                continue
            if isinstance(event, bb.event.ParseCompleted):
                if not parseprogress:
                    continue

                parseprogress.finish()
                print((
                    "Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                    % (event.total, event.cached, event.parsed, event.virtuals,
                       event.skipped, event.masked, event.errors)))
                continue

            if isinstance(event, bb.event.CacheLoadStarted):
                cacheprogress = new_progress("Loading cache",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                cacheprogress.update(event.current)
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                cacheprogress.finish()
                print("Loaded %d entries from dependency cache." %
                      event.num_entries)
                continue

            if isinstance(event, bb.command.CommandFailed):
                return_value = event.exitcode
                errors = errors + 1
                logger.error("Command execution failed: %s", event.error)
                main.shutdown = 2
                continue
            if isinstance(event, bb.command.CommandExit):
                if not return_value:
                    return_value = event.exitcode
                continue
            if isinstance(event,
                          (bb.command.CommandCompleted, bb.cooker.CookerExit)):
                main.shutdown = 2
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue
            if isinstance(event, bb.event.NoProvider):
                return_value = 1
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    logger.error(
                        "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)",
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    logger.error("Nothing %sPROVIDES '%s'", r, event._item)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
                logger.info("Running setscene task %d of %d (%s)" %
                            (event.stats.completed + event.stats.active +
                             event.stats.failed + 1, event.stats.total,
                             event.taskstring))
                continue

            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if event.noexec:
                    tasktype = 'noexec task'
                else:
                    tasktype = 'task'
                logger.info(
                    "Running %s %s of %s (ID: %s, %s)", tasktype,
                    event.stats.completed + event.stats.active +
                    event.stats.failed + 1, event.stats.total, event.taskid,
                    event.taskstring)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                taskfailures.append(event.taskstring)
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
                logger.warn(
                    "Setscene task %s (%s) failed with exit code '%s' - real task will be run instead",
                    event.taskid, event.taskstring, event.exitcode)
                continue

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.StampUpdate,
                 bb.event.ConfigParsed, bb.event.RecipeParsed,
                 bb.event.RecipePreFinalise, bb.runqueue.runQueueEvent,
                 bb.runqueue.runQueueExitWait, bb.event.OperationStarted,
                 bb.event.OperationCompleted, bb.event.OperationProgress)):
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            termfilter.clearFooter()
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            termfilter.clearFooter()
            if main.shutdown == 1:
                print("\nSecond Keyboard Interrupt, stopping...\n")
                server.runCommand(["stateStop"])
            if main.shutdown == 0:
                interrupted = True
                print("\nKeyboard Interrupt, closing down...\n")
                server.runCommand(["stateShutdown"])
            main.shutdown = main.shutdown + 1
            pass

    summary = ""
    if taskfailures:
        summary += pluralise("\nSummary: %s task failed:",
                             "\nSummary: %s tasks failed:", len(taskfailures))
        for failure in taskfailures:
            summary += "\n  %s" % failure
    if warnings:
        summary += pluralise(
            "\nSummary: There was %s WARNING message shown.",
            "\nSummary: There were %s WARNING messages shown.", warnings)
    if return_value:
        summary += pluralise(
            "\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
            "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.",
            errors)
    if summary:
        print(summary)

    if interrupted:
        print("Execution was interrupted, returning a non-zero exit code.")
        if return_value == 0:
            return_value = 1

    termfilter.finish()

    return return_value
Esempio n. 7
0
def main(server, eventHandler, params):
    # set to a logging.FileHandler instance when a build starts;
    # see _open_build_log()
    build_log = None

    # set to the log path when a build starts
    build_log_file_path = None

    helper = uihelper.BBUIHelper()

    # TODO don't use log output to determine when bitbake has started
    #
    # WARNING: this log handler cannot be removed, as localhostbecontroller
    # relies on output in the toaster_ui.log file to determine whether
    # the bitbake server has started, which only happens if
    # this logger is setup here (see the TODO in the loop below)
    console = logging.StreamHandler(sys.stdout)
    format_str = "%(levelname)s: %(message)s"
    formatter = bb.msg.BBLogFormatter(format_str)
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(formatter)
    logger.addHandler(console)
    logger.setLevel(logging.INFO)
    llevel, debug_domains = bb.msg.constructLogOptions()
    server.runCommand([
        "setEventMask",
        server.getEventHandle(), llevel, debug_domains, _evt_list
    ])

    # verify and warn
    build_history_enabled = True
    inheritlist, _ = server.runCommand(["getVariable", "INHERIT"])

    if not "buildhistory" in inheritlist.split(" "):
        logger.warn(
            "buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details."
        )
        build_history_enabled = False

    if not params.observe_only:
        logger.error("ToasterUI can only work in observer mode")
        return 1

    # set to 1 when toasterui needs to shut down
    main.shutdown = 0

    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []
    first = True

    buildinfohelper = BuildInfoHelper(server, build_history_enabled)

    # write our own log files into bitbake's log directory;
    # we're only interested in the path to the parent directory of
    # this file, as we're writing our own logs into the same directory
    consolelogfile = _log_settings_from_server(server)
    log_dir = os.path.dirname(consolelogfile)
    bb.utils.mkdirhier(log_dir)

    while True:
        try:
            event = eventHandler.waitEvent(0.25)
            if first:
                first = False

                # TODO don't use log output to determine when bitbake has started
                #
                # this is the line localhostbecontroller needs to
                # see in toaster_ui.log which it uses to decide whether
                # the bitbake server has started...
                logger.info("ToasterUI waiting for events")

            if event is None:
                if main.shutdown > 0:
                    # if shutting down, close any open build log first
                    _close_build_log(build_log)

                    break
                continue

            helper.eventHandler(event)

            # pylint: disable=protected-access
            # the code will look into the protected variables of the event; no easy way around this

            # we treat ParseStarted as the first event of toaster-triggered
            # builds; that way we get the Build Configuration included in the log
            # and any errors that occur before BuildStarted is fired
            if isinstance(event, bb.event.ParseStarted):
                if not (build_log and build_log_file_path):
                    build_log, build_log_file_path = _open_build_log(log_dir)
                continue

            if isinstance(event, bb.event.BuildStarted):
                if not (build_log and build_log_file_path):
                    build_log, build_log_file_path = _open_build_log(log_dir)

                buildinfohelper.store_started_build(event, build_log_file_path)

            if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded,
                                  bb.build.TaskFailedSilent)):
                buildinfohelper.update_and_store_task(event)
                logger.info("Logfile for task %s", event.logfile)
                continue

            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)

            if isinstance(event, bb.event.LogExecTTY):
                logger.info(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                if event.levelno == -1:
                    event.levelno = formatter.ERROR

                buildinfohelper.store_log_event(event)

                if event.levelno >= formatter.ERROR:
                    errors = errors + 1
                elif event.levelno == formatter.WARNING:
                    warnings = warnings + 1

                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= formatter.NOTE:
                    continue

                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                buildinfohelper.update_and_store_task(event)
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    bb.error("Logfile of failure stored in: %s" % logfile)
                continue

            # these events are unprocessed now, but may be used in the future to log
            # timing and error informations from the parsing phase in Toaster
            if isinstance(event,
                          (bb.event.SanityCheckPassed, bb.event.SanityCheck)):
                continue
            if isinstance(event, bb.event.ParseProgress):
                continue
            if isinstance(event, bb.event.ParseCompleted):
                continue
            if isinstance(event, bb.event.CacheLoadStarted):
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue

            if isinstance(event, bb.event.NoProvider):
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    text = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    text = "Nothing %sPROVIDES '%s'" % (r, event._item)

                logger.error(text)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                        text += reason
                buildinfohelper.store_log_error(text)
                continue

            if isinstance(event, bb.event.ConfigParsed):
                continue
            if isinstance(event, bb.event.RecipeParsed):
                continue

            # end of saved events

            if isinstance(event, (bb.runqueue.sceneQueueTaskStarted,
                                  bb.runqueue.runQueueTaskStarted,
                                  bb.runqueue.runQueueTaskSkipped)):
                buildinfohelper.store_started_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskCompleted):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                buildinfohelper.update_and_store_task(event)
                taskfailures.append(event.taskstring)
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted,
                                  bb.runqueue.sceneQueueTaskFailed)):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, (bb.event.TreeDataPreparationStarted,
                                  bb.event.TreeDataPreparationCompleted)):
                continue

            if isinstance(event,
                          (bb.event.BuildCompleted, bb.command.CommandFailed)):

                errorcode = 0
                if isinstance(event, bb.command.CommandFailed):
                    errors += 1
                    errorcode = 1
                    logger.error("Command execution failed: %s", event.error)

                # turn off logging to the current build log
                _close_build_log(build_log)

                # reset ready for next BuildStarted
                build_log = None

                # update the build info helper on BuildCompleted, not on CommandXXX
                buildinfohelper.update_build_information(
                    event, errors, warnings, taskfailures)
                buildinfohelper.close(errorcode)
                # mark the log output; controllers may kill the toasterUI after seeing this log
                logger.info("ToasterUI build done 1, brbe: %s",
                            buildinfohelper.brbe)

                # we start a new build info
                logger.debug("ToasterUI prepared for new build")
                errors = 0
                warnings = 0
                taskfailures = []
                buildinfohelper = BuildInfoHelper(server,
                                                  build_history_enabled)

                logger.info("ToasterUI build done 2")
                continue

            if isinstance(event,
                          (bb.command.CommandCompleted,
                           bb.command.CommandFailed, bb.command.CommandExit)):
                errorcode = 0

                continue

            if isinstance(event, bb.event.MetadataEvent):
                if event.type == "SinglePackageInfo":
                    buildinfohelper.store_build_package_information(event)
                elif event.type == "LayerInfo":
                    buildinfohelper.store_layer_info(event)
                elif event.type == "BuildStatsList":
                    buildinfohelper.store_tasks_stats(event)
                elif event.type == "ImagePkgList":
                    buildinfohelper.store_target_package_data(event)
                elif event.type == "MissedSstate":
                    buildinfohelper.store_missed_state_tasks(event)
                elif event.type == "ImageFileSize":
                    buildinfohelper.update_target_image_file(event)
                elif event.type == "ArtifactFileSize":
                    buildinfohelper.update_artifact_image_file(event)
                elif event.type == "LicenseManifestPath":
                    buildinfohelper.store_license_manifest_path(event)
                elif event.type == "SetBRBE":
                    buildinfohelper.brbe = buildinfohelper._get_data_from_event(
                        event)
                elif event.type == "OSErrorException":
                    logger.error(event)
                else:
                    logger.error("Unprocessed MetadataEvent %s ", str(event))
                continue

            if isinstance(event, bb.cooker.CookerExit):
                # shutdown when bitbake server shuts down
                main.shutdown = 1
                continue

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.StampUpdate,
                 bb.event.RecipePreFinalise, bb.runqueue.runQueueEvent,
                 bb.runqueue.runQueueExitWait, bb.event.OperationProgress,
                 bb.command.CommandFailed, bb.command.CommandExit,
                 bb.command.CommandCompleted, bb.event.ReachableStamps)):
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                buildinfohelper.store_dependency_information(event)
                continue

            logger.warn("Unknown event: %s", event)
            return_value += 1

        except EnvironmentError as ioerror:
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            main.shutdown = 1
        except Exception as e:
            # print errors to log
            import traceback
            from pprint import pformat
            exception_data = traceback.format_exc()
            logger.error("%s\n%s", e, exception_data)

            _, _, tb = sys.exc_info()
            if tb is not None:
                curr = tb
                while curr is not None:
                    logger.error("Error data dump %s\n%s\n",
                                 traceback.format_tb(curr, 1),
                                 pformat(curr.tb_frame.f_locals))
                    curr = curr.tb_next

            # save them to database, if possible; if it fails, we already logged to console.
            try:
                buildinfohelper.store_log_exception("%s\n%s" %
                                                    (str(e), exception_data))
            except Exception as ce:
                logger.error(
                    "CRITICAL - Failed to to save toaster exception to the database: %s",
                    str(ce))

            # make sure we return with an error
            return_value += 1

    if interrupted and return_value == 0:
        return_value += 1

    logger.warn("Return value is %d", return_value)
    return return_value
Esempio n. 8
0
def main(server, eventHandler, params, tf=TerminalFilter):

    includelogs, loglines, consolelogfile = _log_settings_from_server(server)

    if sys.stdin.isatty() and sys.stdout.isatty():
        log_exec_tty = True
    else:
        log_exec_tty = False

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    errconsole = logging.StreamHandler(sys.stderr)
    format_str = "%(levelname)s: %(message)s"
    format = bb.msg.BBLogFormatter(format_str)
    bb.msg.addDefaultlogFilter(console, bb.msg.BBLogFilterStdOut)
    bb.msg.addDefaultlogFilter(errconsole, bb.msg.BBLogFilterStdErr)
    console.setFormatter(format)
    errconsole.setFormatter(format)
    logger.addHandler(console)
    logger.addHandler(errconsole)

    if params.options.remote_server and params.options.kill_server:
        server.terminateServer()
        return

    if consolelogfile and not params.options.show_environment:
        bb.utils.mkdirhier(os.path.dirname(consolelogfile))
        conlogformat = bb.msg.BBLogFormatter(format_str)
        consolelog = logging.FileHandler(consolelogfile)
        bb.msg.addDefaultlogFilter(consolelog)
        consolelog.setFormatter(conlogformat)
        logger.addHandler(consolelog)

    llevel, debug_domains = bb.msg.constructLogOptions()
    server.runCommand([
        "setEventMask",
        server.getEventHandle(), llevel, debug_domains, _evt_list
    ])

    if not params.observe_only:
        params.updateFromServer(server)
        cmdline = params.parseActions()
        if not cmdline:
            print(
                "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
            )
            return 1
        if 'msg' in cmdline and cmdline['msg']:
            logger.error(cmdline['msg'])
            return 1

        ret, error = server.runCommand(cmdline['action'])
        if error:
            logger.error("Command '%s' failed: %s" % (cmdline, error))
            return 1
        elif ret != True:
            logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
            return 1

    parseprogress = None
    cacheprogress = None
    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []

    termfilter = tf(main, helper, console, errconsole, format)
    atexit.register(termfilter.finish)

    while True:
        try:
            event = eventHandler.waitEvent(0)
            if event is None:
                if main.shutdown > 1:
                    break
                termfilter.updateFooter()
                event = eventHandler.waitEvent(0.25)
                if event is None:
                    continue
            helper.eventHandler(event)
            if isinstance(event, bb.runqueue.runQueueExitWait):
                if not main.shutdown:
                    main.shutdown = 1
                continue
            if isinstance(event, bb.event.LogExecTTY):
                if log_exec_tty:
                    tries = event.retries
                    while tries:
                        print("Trying to run: %s" % event.prog)
                        if os.system(event.prog) == 0:
                            break
                        time.sleep(event.sleep_delay)
                        tries -= 1
                    if tries:
                        continue
                logger.warn(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                if event.levelno >= format.ERROR:
                    errors = errors + 1
                    return_value = 1
                elif event.levelno == format.WARNING:
                    warnings = warnings + 1
                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= format.NOTE and (
                        event.levelno < llevel or
                    (event.levelno == format.NOTE
                     and llevel != format.VERBOSE)):
                    continue
                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailedSilent):
                logger.warn("Logfile for failed setscene task is %s" %
                            event.logfile)
                continue
            if isinstance(event, bb.build.TaskFailed):
                return_value = 1
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    termfilter.clearFooter()
                    bb.error("Logfile of failure stored in: %s" % logfile)
                    if includelogs and not event.errprinted:
                        print("Log data follows:")
                        f = open(logfile, "r")
                        lines = []
                        while True:
                            l = f.readline()
                            if l == '':
                                break
                            l = l.rstrip()
                            if loglines:
                                lines.append(' | %s' % l)
                                if len(lines) > int(loglines):
                                    lines.pop(0)
                            else:
                                print('| %s' % l)
                        f.close()
                        if lines:
                            for line in lines:
                                print(line)
            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
                continue
            if isinstance(event, bb.event.ParseStarted):
                if event.total == 0:
                    continue
                parseprogress = new_progress("Parsing recipes",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.ParseProgress):
                parseprogress.update(event.current)
                continue
            if isinstance(event, bb.event.ParseCompleted):
                if not parseprogress:
                    continue

                parseprogress.finish()
                print((
                    "Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                    % (event.total, event.cached, event.parsed, event.virtuals,
                       event.skipped, event.masked, event.errors)))
                continue

            if isinstance(event, bb.event.CacheLoadStarted):
                cacheprogress = new_progress("Loading cache",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                cacheprogress.update(event.current)
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                cacheprogress.finish()
                print("Loaded %d entries from dependency cache." %
                      event.num_entries)
                continue

            if isinstance(event, bb.command.CommandFailed):
                return_value = event.exitcode
                if event.error:
                    errors = errors + 1
                    logger.error("Command execution failed: %s", event.error)
                main.shutdown = 2
                continue
            if isinstance(event, bb.command.CommandExit):
                if not return_value:
                    return_value = event.exitcode
                continue
            if isinstance(event,
                          (bb.command.CommandCompleted, bb.cooker.CookerExit)):
                main.shutdown = 2
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue
            if isinstance(event, bb.event.NoProvider):
                return_value = 1
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                extra = ''
                if not event._reasons:
                    if event._close_matches:
                        extra = ". Close matches:\n  %s" % '\n  '.join(
                            event._close_matches)

                if event._dependees:
                    logger.error(
                        "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)%s",
                        r, event._item, ", ".join(event._dependees), r, extra)
                else:
                    logger.error("Nothing %sPROVIDES '%s'%s", r, event._item,
                                 extra)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskStarted):
                logger.info("Running setscene task %d of %d (%s)" %
                            (event.stats.completed + event.stats.active +
                             event.stats.failed + 1, event.stats.total,
                             event.taskstring))
                continue

            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if event.noexec:
                    tasktype = 'noexec task'
                else:
                    tasktype = 'task'
                logger.info(
                    "Running %s %s of %s (ID: %s, %s)", tasktype,
                    event.stats.completed + event.stats.active +
                    event.stats.failed + 1, event.stats.total, event.taskid,
                    event.taskstring)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                taskfailures.append(event.taskstring)
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, bb.runqueue.sceneQueueTaskFailed):
                logger.warn(
                    "Setscene task %s (%s) failed with exit code '%s' - real task will be run instead",
                    event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                continue

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.MetadataEvent,
                 bb.event.StampUpdate, bb.event.ConfigParsed,
                 bb.event.RecipeParsed, bb.event.RecipePreFinalise,
                 bb.runqueue.runQueueEvent, bb.event.OperationStarted,
                 bb.event.OperationCompleted, bb.event.OperationProgress,
                 bb.event.DiskFull)):
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            termfilter.clearFooter()
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            termfilter.clearFooter()
            if params.observe_only:
                print("\nKeyboard Interrupt, exiting observer...")
                main.shutdown = 2
            if not params.observe_only and main.shutdown == 1:
                print("\nSecond Keyboard Interrupt, stopping...\n")
                _, error = server.runCommand(["stateForceShutdown"])
                if error:
                    logger.error("Unable to cleanly stop: %s" % error)
            if not params.observe_only and main.shutdown == 0:
                print("\nKeyboard Interrupt, closing down...\n")
                interrupted = True
                _, error = server.runCommand(["stateShutdown"])
                if error:
                    logger.error("Unable to cleanly shutdown: %s" % error)
            main.shutdown = main.shutdown + 1
            pass

    summary = ""
    if taskfailures:
        summary += pluralise("\nSummary: %s task failed:",
                             "\nSummary: %s tasks failed:", len(taskfailures))
        for failure in taskfailures:
            summary += "\n  %s" % failure
    if warnings:
        summary += pluralise(
            "\nSummary: There was %s WARNING message shown.",
            "\nSummary: There were %s WARNING messages shown.", warnings)
    if return_value and errors:
        summary += pluralise(
            "\nSummary: There was %s ERROR message shown, returning a non-zero exit code.",
            "\nSummary: There were %s ERROR messages shown, returning a non-zero exit code.",
            errors)
    if summary:
        print(summary)

    if interrupted:
        print("Execution was interrupted, returning a non-zero exit code.")
        if return_value == 0:
            return_value = 1

    return return_value
Esempio n. 9
0
    def main(self, stdscr, server, eventHandler, params):
        #-------------------------------------------------------------------------#
        height, width = stdscr.getmaxyx()

        # for now split it like that:
        # MAIN_y + THREAD_y = 2/3 screen at the top
        # MAIN_x = 2/3 left, THREAD_y = 1/3 right
        # CLI_y = 1/3 of screen at the bottom
        # CLI_x = full

        main_left = 0
        main_top = 0
        main_height = (height // 3 * 2)
        main_width = (width // 3) * 2
        clo_left = main_left
        clo_top = main_top + main_height
        clo_height = height - main_height - main_top - 1
        clo_width = width
        cli_left = main_left
        cli_top = clo_top + clo_height
        cli_height = 1
        cli_width = width
        thread_left = main_left + main_width
        thread_top = main_top
        thread_height = main_height
        thread_width = width - main_width

        #tw = self.TitleWindow( 0, 0, width, main_top )
        mw = self.MainWindow(main_left, main_top, main_width, main_height)
        taw = self.ThreadActivityWindow(thread_left, thread_top, thread_width,
                                        thread_height)
        clo = self.ShellOutputWindow(clo_left, clo_top, clo_width, clo_height)
        cli = self.ShellInputWindow(cli_left, cli_top, cli_width, cli_height)
        cli.setText(0, 0, "BB>")

        mw.setStatus("Idle")

        helper = uihelper.BBUIHelper()
        shutdown = 0

        try:
            params.updateFromServer(server)
            cmdline = params.parseActions()
            if not cmdline:
                print(
                    "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
                )
                return 1
            if 'msg' in cmdline and cmdline['msg']:
                logger.error(cmdline['msg'])
                return 1
            cmdline = cmdline['action']
            ret, error = server.runCommand(cmdline)
            if error:
                print("Error running command '%s': %s" % (cmdline, error))
                return
            elif not ret:
                print("Couldn't get default commandlind! %s" % ret)
                return
        except xmlrpc.client.Fault as x:
            print("XMLRPC Fault getting commandline:\n %s" % x)
            return

        exitflag = False
        while not exitflag:
            try:
                event = eventHandler.waitEvent(0.25)
                if not event:
                    continue

                helper.eventHandler(event)
                if isinstance(event, bb.build.TaskBase):
                    mw.appendText("NOTE: %s\n" % event._message)
                if isinstance(event, logging.LogRecord):
                    mw.appendText(
                        logging.getLevelName(event.levelno) + ': ' +
                        event.getMessage() + '\n')

                if isinstance(event, bb.event.CacheLoadStarted):
                    self.parse_total = event.total
                if isinstance(event, bb.event.CacheLoadProgress):
                    x = event.current
                    y = self.parse_total
                    mw.setStatus("Loading Cache:   %s [%2d %%]" %
                                 (next(parsespin), x * 100 / y))
                if isinstance(event, bb.event.CacheLoadCompleted):
                    mw.setStatus("Idle")
                    mw.appendText(
                        "Loaded %d entries from dependency cache.\n" %
                        (event.num_entries))

                if isinstance(event, bb.event.ParseStarted):
                    self.parse_total = event.total
                if isinstance(event, bb.event.ParseProgress):
                    x = event.current
                    y = self.parse_total
                    mw.setStatus("Parsing Recipes: %s [%2d %%]" %
                                 (next(parsespin), x * 100 / y))
                if isinstance(event, bb.event.ParseCompleted):
                    mw.setStatus("Idle")
                    mw.appendText(
                        "Parsing finished. %d cached, %d parsed, %d skipped, %d masked.\n"
                        % (event.cached, event.parsed, event.skipped,
                           event.masked))


#                if isinstance(event, bb.build.TaskFailed):
#                    if event.logfile:
#                        if data.getVar("BBINCLUDELOGS", d):
#                            bb.error("log data follows (%s)" % logfile)
#                            number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d)
#                            if number_of_lines:
#                                subprocess.check_call('tail -n%s %s' % (number_of_lines, logfile), shell=True)
#                            else:
#                                f = open(logfile, "r")
#                                while True:
#                                    l = f.readline()
#                                    if l == '':
#                                        break
#                                    l = l.rstrip()
#                                    print '| %s' % l
#                                f.close()
#                        else:
#                            bb.error("see log in %s" % logfile)

                if isinstance(event, bb.command.CommandCompleted):
                    # stop so the user can see the result of the build, but
                    # also allow them to now exit with a single ^C
                    shutdown = 2
                if isinstance(event, bb.command.CommandFailed):
                    mw.appendText(str(event))
                    time.sleep(2)
                    exitflag = True
                if isinstance(event, bb.command.CommandExit):
                    exitflag = True
                if isinstance(event, bb.cooker.CookerExit):
                    exitflag = True

                if isinstance(event, bb.event.LogExecTTY):
                    mw.appendText('WARN: ' + event.msg + '\n')
                if helper.needUpdate:
                    activetasks, failedtasks = helper.getTasks()
                    taw.erase()
                    taw.setText(0, 0, "")
                    if activetasks:
                        taw.appendText("Active Tasks:\n")
                        for task in activetasks.values():
                            taw.appendText(task["title"] + '\n')
                    if failedtasks:
                        taw.appendText("Failed Tasks:\n")
                        for task in failedtasks:
                            taw.appendText(task["title"] + '\n')

                curses.doupdate()
            except EnvironmentError as ioerror:
                # ignore interrupted io
                if ioerror.args[0] == 4:
                    pass

            except KeyboardInterrupt:
                if shutdown == 2:
                    mw.appendText("Third Keyboard Interrupt, exit.\n")
                    exitflag = True
                if shutdown == 1:
                    mw.appendText("Second Keyboard Interrupt, stopping...\n")
                    _, error = server.runCommand(["stateForceShutdown"])
                    if error:
                        print("Unable to cleanly stop: %s" % error)
                if shutdown == 0:
                    mw.appendText("Keyboard Interrupt, closing down...\n")
                    _, error = server.runCommand(["stateShutdown"])
                    if error:
                        print("Unable to cleanly shutdown: %s" % error)
                shutdown = shutdown + 1
                pass
Esempio n. 10
0
def main(server, eventHandler, params):
    # set to a logging.FileHandler instance when a build starts;
    # see _open_build_log()
    build_log = None

    # set to the log path when a build starts
    build_log_file_path = None

    helper = uihelper.BBUIHelper()

    # TODO don't use log output to determine when bitbake has started
    #
    # WARNING: this log handler cannot be removed, as localhostbecontroller
    # relies on output in the toaster_ui.log file to determine whether
    # the bitbake server has started, which only happens if
    # this logger is setup here (see the TODO in the loop below)
    console = logging.StreamHandler(sys.stdout)
    format_str = "%(levelname)s: %(message)s"
    formatter = bb.msg.BBLogFormatter(format_str)
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(formatter)
    logger.addHandler(console)
    logger.setLevel(logging.INFO)
    llevel, debug_domains = bb.msg.constructLogOptions()
    result, error = server.runCommand([
        "setEventMask",
        server.getEventHandle(), llevel, debug_domains, _evt_list
    ])
    if not result or error:
        logger.error("can't set event mask: %s", error)
        return 1

    # verify and warn
    build_history_enabled = True
    inheritlist, _ = server.runCommand(["getVariable", "INHERIT"])

    if not "buildhistory" in inheritlist.split(" "):
        logger.warning(
            "buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details."
        )
        build_history_enabled = False

    if not params.observe_only:
        params.updateFromServer(server)
        params.updateToServer(server, os.environ.copy())
        cmdline = params.parseActions()
        if not cmdline:
            print(
                "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
            )
            return 1
        if 'msg' in cmdline and cmdline['msg']:
            logger.error(cmdline['msg'])
            return 1

        ret, error = server.runCommand(cmdline['action'])
        if error:
            logger.error("Command '%s' failed: %s" % (cmdline, error))
            return 1
        elif ret != True:
            logger.error("Command '%s' failed: returned %s" % (cmdline, ret))
            return 1

    # set to 1 when toasterui needs to shut down
    main.shutdown = 0

    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []
    first = True

    buildinfohelper = BuildInfoHelper(server, build_history_enabled,
                                      os.getenv('TOASTER_BRBE'))

    # write our own log files into bitbake's log directory;
    # we're only interested in the path to the parent directory of
    # this file, as we're writing our own logs into the same directory
    consolelogfile = _log_settings_from_server(server)
    log_dir = os.path.dirname(consolelogfile)
    bb.utils.mkdirhier(log_dir)

    while True:
        try:
            event = eventHandler.waitEvent(0.25)
            if first:
                first = False

                # TODO don't use log output to determine when bitbake has started
                #
                # this is the line localhostbecontroller needs to
                # see in toaster_ui.log which it uses to decide whether
                # the bitbake server has started...
                logger.info("ToasterUI waiting for events")

            if event is None:
                if main.shutdown > 0:
                    # if shutting down, close any open build log first
                    _close_build_log(build_log)

                    break
                continue

            helper.eventHandler(event)

            # pylint: disable=protected-access
            # the code will look into the protected variables of the event; no easy way around this

            if isinstance(event, bb.event.ParseStarted):
                if not (build_log and build_log_file_path):
                    build_log, build_log_file_path = _open_build_log(log_dir)

                buildinfohelper.store_started_build()
                buildinfohelper.save_build_log_file_path(build_log_file_path)
                buildinfohelper.set_recipes_to_parse(event.total)
                continue

            # create a build object in buildinfohelper from either BuildInit
            # (if available) or BuildStarted (for jethro and previous versions)
            if isinstance(event, (bb.event.BuildStarted, bb.event.BuildInit)):
                if not (build_log and build_log_file_path):
                    build_log, build_log_file_path = _open_build_log(log_dir)

                buildinfohelper.save_build_targets(event)
                buildinfohelper.save_build_log_file_path(build_log_file_path)

                # get additional data from BuildStarted
                if isinstance(event, bb.event.BuildStarted):
                    buildinfohelper.save_build_layers_and_variables()
                continue

            if isinstance(event, bb.event.ParseProgress):
                buildinfohelper.set_recipes_parsed(event.current)
                continue

            if isinstance(event, bb.event.ParseCompleted):
                buildinfohelper.set_recipes_parsed(event.total)
                continue

            if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded,
                                  bb.build.TaskFailedSilent)):
                buildinfohelper.update_and_store_task(event)
                logger.info("Logfile for task %s", event.logfile)
                continue

            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)

            if isinstance(event, bb.event.LogExecTTY):
                logger.info(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                if event.levelno == -1:
                    event.levelno = formatter.ERROR

                buildinfohelper.store_log_event(event)

                if event.levelno >= formatter.ERROR:
                    errors = errors + 1
                elif event.levelno == formatter.WARNING:
                    warnings = warnings + 1

                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= formatter.NOTE:
                    continue

                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                buildinfohelper.update_and_store_task(event)
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    bb.error("Logfile of failure stored in: %s" % logfile)
                continue

            # these events are unprocessed now, but may be used in the future to log
            # timing and error informations from the parsing phase in Toaster
            if isinstance(event,
                          (bb.event.SanityCheckPassed, bb.event.SanityCheck)):
                continue
            if isinstance(event, bb.event.CacheLoadStarted):
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue

            if isinstance(event, bb.event.NoProvider):
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    text = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    text = "Nothing %sPROVIDES '%s'" % (r, event._item)

                logger.error(text)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                        text += reason
                buildinfohelper.store_log_error(text)
                continue

            if isinstance(event, bb.event.ConfigParsed):
                continue
            if isinstance(event, bb.event.RecipeParsed):
                continue

            # end of saved events

            if isinstance(event, (bb.runqueue.sceneQueueTaskStarted,
                                  bb.runqueue.runQueueTaskStarted,
                                  bb.runqueue.runQueueTaskSkipped)):
                buildinfohelper.store_started_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskCompleted):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                buildinfohelper.update_and_store_task(event)
                taskfailures.append(event.taskstring)
                logger.error("Task (%s) failed with exit code '%s'",
                             event.taskstring, event.exitcode)
                continue

            if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted,
                                  bb.runqueue.sceneQueueTaskFailed)):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, (bb.event.TreeDataPreparationStarted,
                                  bb.event.TreeDataPreparationCompleted)):
                continue

            if isinstance(event,
                          (bb.event.BuildCompleted, bb.command.CommandFailed)):

                errorcode = 0
                if isinstance(event, bb.command.CommandFailed):
                    errors += 1
                    errorcode = 1
                    logger.error("Command execution failed: %s", event.error)
                elif isinstance(event, bb.event.BuildCompleted):
                    buildinfohelper.scan_image_artifacts()
                    buildinfohelper.clone_required_sdk_artifacts()

                # turn off logging to the current build log
                _close_build_log(build_log)

                # reset ready for next BuildStarted
                build_log = None

                # update the build info helper on BuildCompleted, not on CommandXXX
                buildinfohelper.update_build_information(
                    event, errors, warnings, taskfailures)

                brbe = buildinfohelper.brbe
                buildinfohelper.close(errorcode)

                # we start a new build info
                if params.observe_only:
                    logger.debug("ToasterUI prepared for new build")
                    errors = 0
                    warnings = 0
                    taskfailures = []
                    buildinfohelper = BuildInfoHelper(server,
                                                      build_history_enabled)
                else:
                    main.shutdown = 1

                logger.info("ToasterUI build done, brbe: %s", brbe)
                continue

            if isinstance(event,
                          (bb.command.CommandCompleted,
                           bb.command.CommandFailed, bb.command.CommandExit)):
                if params.observe_only:
                    errorcode = 0
                else:
                    main.shutdown = 1

                continue

            if isinstance(event, bb.event.MetadataEvent):
                if event.type == "SinglePackageInfo":
                    buildinfohelper.store_build_package_information(event)
                elif event.type == "LayerInfo":
                    buildinfohelper.store_layer_info(event)
                elif event.type == "BuildStatsList":
                    buildinfohelper.store_tasks_stats(event)
                elif event.type == "ImagePkgList":
                    buildinfohelper.store_target_package_data(event)
                elif event.type == "MissedSstate":
                    buildinfohelper.store_missed_state_tasks(event)
                elif event.type == "SDKArtifactInfo":
                    buildinfohelper.scan_sdk_artifacts(event)
                elif event.type == "SetBRBE":
                    buildinfohelper.brbe = buildinfohelper._get_data_from_event(
                        event)
                elif event.type == "TaskArtifacts":
                    # not implemented yet
                    # see https://bugzilla.yoctoproject.org/show_bug.cgi?id=10283 for details
                    pass
                elif event.type == "OSErrorException":
                    logger.error(event)
                else:
                    logger.error("Unprocessed MetadataEvent %s", event.type)
                continue

            if isinstance(event, bb.cooker.CookerExit):
                # shutdown when bitbake server shuts down
                main.shutdown = 1
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                buildinfohelper.store_dependency_information(event)
                continue

            logger.warning("Unknown event: %s", event)
            return_value += 1

        except EnvironmentError as ioerror:
            logger.warning("EnvironmentError: %s" % ioerror)
            # ignore interrupted io system calls
            if ioerror.args[0] == 4:  # errno 4 is EINTR
                logger.warning("Skipped EINTR: %s" % ioerror)
            else:
                raise
        except KeyboardInterrupt:
            if params.observe_only:
                print("\nKeyboard Interrupt, exiting observer...")
                main.shutdown = 2
            if not params.observe_only and main.shutdown == 1:
                print("\nSecond Keyboard Interrupt, stopping...\n")
                _, error = server.runCommand(["stateForceShutdown"])
                if error:
                    logger.error("Unable to cleanly stop: %s" % error)
            if not params.observe_only and main.shutdown == 0:
                print("\nKeyboard Interrupt, closing down...\n")
                interrupted = True
                _, error = server.runCommand(["stateShutdown"])
                if error:
                    logger.error("Unable to cleanly shutdown: %s" % error)
            buildinfohelper.cancel_cli_build()
            main.shutdown = main.shutdown + 1
        except Exception as e:
            # print errors to log
            import traceback
            from pprint import pformat
            exception_data = traceback.format_exc()
            logger.error("%s\n%s", e, exception_data)

            # save them to database, if possible; if it fails, we already logged to console.
            try:
                buildinfohelper.store_log_exception("%s\n%s" %
                                                    (str(e), exception_data))
            except Exception as ce:
                logger.error(
                    "CRITICAL - Failed to to save toaster exception to the database: %s",
                    str(ce))

            # make sure we return with an error
            return_value += 1

    if interrupted and return_value == 0:
        return_value += 1

    logger.warning("Return value is %d", return_value)
    return return_value
Esempio n. 11
0
def main(server, eventHandler, params):

    includelogs, loglines = _log_settings_from_server(server)

    # verify and warn
    build_history_enabled = True
    inheritlist, error = server.runCommand(["getVariable", "INHERIT"])
    if not "buildhistory" in inheritlist.split(" "):
        logger.warn(
            "buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details."
        )
        build_history_enabled = False

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    format_str = "%(levelname)s: %(message)s"
    format = bb.msg.BBLogFormatter(format_str)
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(format)
    logger.addHandler(console)

    if not params.observe_only:
        logger.error("ToasterUI can only work in observer mode")
        return

    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []

    buildinfohelper = BuildInfoHelper(server, build_history_enabled)

    while True:
        try:
            event = eventHandler.waitEvent(0.25)

            if event is None:
                if main.shutdown > 0:
                    break
                continue

            helper.eventHandler(event)

            if isinstance(event, bb.event.BuildStarted):
                buildinfohelper.store_started_build(event)

            if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded,
                                  bb.build.TaskFailedSilent)):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, bb.event.LogExecTTY):
                logger.warn(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                buildinfohelper.store_log_event(event)
                if event.levelno >= format.ERROR:
                    errors = errors + 1
                    return_value = 1
                elif event.levelno == format.WARNING:
                    warnings = warnings + 1
                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= format.NOTE:
                    continue

                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                buildinfohelper.update_and_store_task(event)
                return_value = 1
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    bb.error("Logfile of failure stored in: %s" % logfile)
                continue

            # these events are unprocessed now, but may be used in the future to log
            # timing and error informations from the parsing phase in Toaster
            if isinstance(event,
                          (bb.event.SanityCheckPassed, bb.event.SanityCheck)):
                continue
            if isinstance(event, bb.event.ParseStarted):
                continue
            if isinstance(event, bb.event.ParseProgress):
                continue
            if isinstance(event, bb.event.ParseCompleted):
                continue
            if isinstance(event, bb.event.CacheLoadStarted):
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                continue
            if isinstance(event, bb.event.MultipleProviders):
                continue
            if isinstance(event, bb.event.NoProvider):
                return_value = 1
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    text = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    text = "Nothing %sPROVIDES '%s'" % (r, event._item)

                logger.error(text)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                        text += reason
                buildinfohelper.store_log_error(text)
                continue

            if isinstance(event, bb.event.ConfigParsed):
                continue
            if isinstance(event, bb.event.RecipeParsed):
                continue

            # end of saved events

            if isinstance(event, (bb.runqueue.sceneQueueTaskStarted,
                                  bb.runqueue.runQueueTaskStarted,
                                  bb.runqueue.runQueueTaskSkipped)):
                buildinfohelper.store_started_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskCompleted):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                buildinfohelper.update_and_store_task(event)
                taskfailures.append(event.taskstring)
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted,
                                  bb.runqueue.sceneQueueTaskFailed)):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, (bb.event.TreeDataPreparationStarted,
                                  bb.event.TreeDataPreparationCompleted)):
                continue

            if isinstance(event, (bb.event.BuildCompleted)):
                continue

            if isinstance(event,
                          (bb.command.CommandCompleted,
                           bb.command.CommandFailed, bb.command.CommandExit)):
                if (isinstance(event, bb.command.CommandFailed)):
                    event.levelno = format.ERROR
                    event.msg = event.error
                    event.pathname = ""
                    event.lineno = 0
                    buildinfohelper.store_log_event(event)
                    errors += 1

                buildinfohelper.update_build_information(
                    event, errors, warnings, taskfailures)

                brbe = server.runCommand(["getVariable", "TOASTER_BRBE"])[0]
                # we start a new build info
                if brbe is not None:
                    print "we are under BuildEnvironment management - after the build, we exit"
                    server.terminateServer()
                else:
                    print "prepared for new build"
                    errors = 0
                    warnings = 0
                    taskfailures = []
                    buildinfohelper = BuildInfoHelper(server,
                                                      build_history_enabled)

                continue

            if isinstance(event, bb.event.MetadataEvent):
                if event.type == "SinglePackageInfo":
                    buildinfohelper.store_build_package_information(event)
                elif event.type == "LayerInfo":
                    buildinfohelper.store_layer_info(event)
                elif event.type == "BuildStatsList":
                    buildinfohelper.store_tasks_stats(event)
                elif event.type == "ImagePkgList":
                    buildinfohelper.store_target_package_data(event)
                elif event.type == "MissedSstate":
                    buildinfohelper.store_missed_state_tasks(event)
                elif event.type == "ImageFileSize":
                    buildinfohelper.update_target_image_file(event)
                elif event.type == "LicenseManifestPath":
                    buildinfohelper.store_license_manifest_path(event)
                continue

            if isinstance(event, bb.cooker.CookerExit):
                # exit when the server exits
                break

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.StampUpdate,
                 bb.event.RecipePreFinalise, bb.runqueue.runQueueEvent,
                 bb.runqueue.runQueueExitWait, bb.event.OperationProgress,
                 bb.command.CommandFailed, bb.command.CommandExit,
                 bb.command.CommandCompleted)):
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                buildinfohelper.store_dependency_information(event)
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            main.shutdown = 1
            pass
        except Exception as e:
            logger.error(e)
            import traceback
            traceback.print_exc()
            pass

    if interrupted:
        if return_value == 0:
            return_value = 1

    return return_value
Esempio n. 12
0
def main(server, eventHandler):

    # Get values of variables which control our output
    includelogs = server.runCommand(["getVariable", "BBINCLUDELOGS"])
    loglines = server.runCommand(["getVariable", "BBINCLUDELOGS_LINES"])
    consolelogfile = server.runCommand(["getVariable", "BB_CONSOLELOG"])

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    format = bb.msg.BBLogFormatter("%(levelname)s: %(message)s")
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(format)
    logger.addHandler(console)
    if consolelogfile:
        consolelog = logging.FileHandler(consolelogfile)
        bb.msg.addDefaultlogFilter(consolelog)
        consolelog.setFormatter(format)
        logger.addHandler(consolelog)

    try:
        cmdline = server.runCommand(["getCmdLineAction"])
        if not cmdline:
            print(
                "Nothing to do.  Use 'bitbake world' to build everything, or run 'bitbake --help' for usage information."
            )
            return 1
        elif not cmdline['action']:
            print(cmdline['msg'])
            return 1
        ret = server.runCommand(cmdline['action'])
        if ret != True:
            print("Couldn't get default commandline! %s" % ret)
            return 1
    except xmlrpclib.Fault as x:
        print("XMLRPC Fault getting commandline:\n %s" % x)
        return 1

    parseprogress = None
    cacheprogress = None
    shutdown = 0
    return_value = 0
    while True:
        try:
            event = eventHandler.waitEvent(0.25)
            if event is None:
                continue
            helper.eventHandler(event)
            if isinstance(event, bb.runqueue.runQueueExitWait):
                if not shutdown:
                    shutdown = 1
            if shutdown and helper.needUpdate:
                activetasks, failedtasks = helper.getTasks()
                if activetasks:
                    print("Waiting for %s active tasks to finish:" %
                          len(activetasks))
                    for tasknum, task in enumerate(activetasks):
                        print("%s: %s (pid %s)" %
                              (tasknum, activetasks[task]["title"], task))

            if isinstance(event, logging.LogRecord):
                if event.levelno >= format.ERROR:
                    return_value = 1
                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                #if logger.getEffectiveLevel() > format.VERBOSE:
                if event.taskpid != 0 and event.levelno <= format.NOTE:
                    continue
                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                return_value = 1
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    print("ERROR: Logfile of failure stored in: %s" % logfile)
                    if 1 or includelogs:
                        print("Log data follows:")
                        f = open(logfile, "r")
                        lines = []
                        while True:
                            l = f.readline()
                            if l == '':
                                break
                            l = l.rstrip()
                            if loglines:
                                lines.append(' | %s' % l)
                                if len(lines) > int(loglines):
                                    lines.pop(0)
                            else:
                                print('| %s' % l)
                        f.close()
                        if lines:
                            for line in lines:
                                print(line)
            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)
                continue
            if isinstance(event, bb.event.ParseStarted):
                if event.total == 0:
                    continue
                parseprogress = new_progress("Parsing recipes",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.ParseProgress):
                parseprogress.update(event.current)
                continue
            if isinstance(event, bb.event.ParseCompleted):
                if not parseprogress:
                    continue

                parseprogress.finish()
                print((
                    "Parsing of %d .bb files complete (%d cached, %d parsed). %d targets, %d skipped, %d masked, %d errors."
                    % (event.total, event.cached, event.parsed, event.virtuals,
                       event.skipped, event.masked, event.errors)))
                continue

            if isinstance(event, bb.event.CacheLoadStarted):
                cacheprogress = new_progress("Loading cache",
                                             event.total).start()
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                cacheprogress.update(event.current)
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                cacheprogress.finish()
                print("Loaded %d entries from dependency cache." %
                      event.num_entries)
                continue

            if isinstance(event, bb.command.CommandCompleted):
                break
            if isinstance(event, bb.command.CommandFailed):
                return_value = event.exitcode
                logger.error("Command execution failed: %s", event.error)
                break
            if isinstance(event, bb.command.CommandExit):
                if not return_value:
                    return_value = event.exitcode
                continue
            if isinstance(event, bb.cooker.CookerExit):
                break
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue
            if isinstance(event, bb.event.NoProvider):
                return_value = 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    logger.error(
                        "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)",
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    logger.error("Nothing %sPROVIDES '%s'", r, event._item)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskStarted):
                if event.noexec:
                    tasktype = 'noexec task'
                else:
                    tasktype = 'task'
                logger.info(
                    "Running %s %s of %s (ID: %s, %s)", tasktype,
                    event.stats.completed + event.stats.active +
                    event.stats.failed + 1, event.stats.total, event.taskid,
                    event.taskstring)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.StampUpdate,
                 bb.event.ConfigParsed, bb.event.RecipeParsed,
                 bb.event.RecipePreFinalise, bb.runqueue.runQueueEvent,
                 bb.runqueue.runQueueExitWait)):
                continue

            logger.error("Unknown event: %s", event)

        except EnvironmentError as ioerror:
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            if shutdown == 2:
                print("\nThird Keyboard Interrupt, exit.\n")
                break
            if shutdown == 1:
                print("\nSecond Keyboard Interrupt, stopping...\n")
                server.runCommand(["stateStop"])
            if shutdown == 0:
                print("\nKeyboard Interrupt, closing down...\n")
                server.runCommand(["stateShutdown"])
            shutdown = shutdown + 1
            pass
    return return_value
Esempio n. 13
0
def main(server, eventHandler, params):

    helper = uihelper.BBUIHelper()

    console = logging.StreamHandler(sys.stdout)
    format_str = "%(levelname)s: %(message)s"
    format = bb.msg.BBLogFormatter(format_str)
    bb.msg.addDefaultlogFilter(console)
    console.setFormatter(format)
    logger.addHandler(console)

    includelogs, loglines, consolelogfile = _log_settings_from_server(server)

    # verify and warn
    build_history_enabled = True
    inheritlist, error = server.runCommand(["getVariable", "INHERIT"])

    if not "buildhistory" in inheritlist.split(" "):
        logger.warn(
            "buildhistory is not enabled. Please enable INHERIT += \"buildhistory\" to see image details."
        )
        build_history_enabled = False

    if not params.observe_only:
        logger.error("ToasterUI can only work in observer mode")
        return 1

    main.shutdown = 0
    interrupted = False
    return_value = 0
    errors = 0
    warnings = 0
    taskfailures = []
    first = True

    buildinfohelper = BuildInfoHelper(server, build_history_enabled)

    if buildinfohelper.brbe is not None and consolelogfile:
        # if we are under managed mode we have no other UI and we need to write our own file
        bb.utils.mkdirhier(os.path.dirname(consolelogfile))
        conlogformat = bb.msg.BBLogFormatter(format_str)
        consolelog = logging.FileHandler(consolelogfile)
        bb.msg.addDefaultlogFilter(consolelog)
        consolelog.setFormatter(conlogformat)
        logger.addHandler(consolelog)

    while True:
        try:
            event = eventHandler.waitEvent(0.25)
            if first:
                first = False
                logger.info("ToasterUI waiting for events")

            if event is None:
                if main.shutdown > 0:
                    break
                continue

            helper.eventHandler(event)

            if isinstance(event, bb.event.BuildStarted):
                buildinfohelper.store_started_build(event)

            if isinstance(event, (bb.build.TaskStarted, bb.build.TaskSucceeded,
                                  bb.build.TaskFailedSilent)):
                buildinfohelper.update_and_store_task(event)
                logger.warn("Logfile for task %s" % event.logfile)
                continue

            if isinstance(event, bb.build.TaskBase):
                logger.info(event._message)

            if isinstance(event, bb.event.LogExecTTY):
                logger.warn(event.msg)
                continue

            if isinstance(event, logging.LogRecord):
                buildinfohelper.store_log_event(event)
                if event.levelno >= format.ERROR:
                    errors = errors + 1
                elif event.levelno == format.WARNING:
                    warnings = warnings + 1
                # For "normal" logging conditions, don't show note logs from tasks
                # but do show them if the user has changed the default log level to
                # include verbose/debug messages
                if event.taskpid != 0 and event.levelno <= format.NOTE:
                    continue

                logger.handle(event)
                continue

            if isinstance(event, bb.build.TaskFailed):
                buildinfohelper.update_and_store_task(event)
                logfile = event.logfile
                if logfile and os.path.exists(logfile):
                    bb.error("Logfile of failure stored in: %s" % logfile)
                continue

            # these events are unprocessed now, but may be used in the future to log
            # timing and error informations from the parsing phase in Toaster
            if isinstance(event,
                          (bb.event.SanityCheckPassed, bb.event.SanityCheck)):
                continue
            if isinstance(event, bb.event.ParseStarted):
                continue
            if isinstance(event, bb.event.ParseProgress):
                continue
            if isinstance(event, bb.event.ParseCompleted):
                continue
            if isinstance(event, bb.event.CacheLoadStarted):
                continue
            if isinstance(event, bb.event.CacheLoadProgress):
                continue
            if isinstance(event, bb.event.CacheLoadCompleted):
                continue
            if isinstance(event, bb.event.MultipleProviders):
                logger.info("multiple providers are available for %s%s (%s)",
                            event._is_runtime and "runtime " or "",
                            event._item, ", ".join(event._candidates))
                logger.info(
                    "consider defining a PREFERRED_PROVIDER entry to match %s",
                    event._item)
                continue

            if isinstance(event, bb.event.NoProvider):
                errors = errors + 1
                if event._runtime:
                    r = "R"
                else:
                    r = ""

                if event._dependees:
                    text = "Nothing %sPROVIDES '%s' (but %s %sDEPENDS on or otherwise requires it)" % (
                        r, event._item, ", ".join(event._dependees), r)
                else:
                    text = "Nothing %sPROVIDES '%s'" % (r, event._item)

                logger.error(text)
                if event._reasons:
                    for reason in event._reasons:
                        logger.error("%s", reason)
                        text += reason
                buildinfohelper.store_log_error(text)
                continue

            if isinstance(event, bb.event.ConfigParsed):
                continue
            if isinstance(event, bb.event.RecipeParsed):
                continue

            # end of saved events

            if isinstance(event, (bb.runqueue.sceneQueueTaskStarted,
                                  bb.runqueue.runQueueTaskStarted,
                                  bb.runqueue.runQueueTaskSkipped)):
                buildinfohelper.store_started_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskCompleted):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, bb.runqueue.runQueueTaskFailed):
                buildinfohelper.update_and_store_task(event)
                taskfailures.append(event.taskstring)
                logger.error("Task %s (%s) failed with exit code '%s'",
                             event.taskid, event.taskstring, event.exitcode)
                continue

            if isinstance(event, (bb.runqueue.sceneQueueTaskCompleted,
                                  bb.runqueue.sceneQueueTaskFailed)):
                buildinfohelper.update_and_store_task(event)
                continue

            if isinstance(event, (bb.event.TreeDataPreparationStarted,
                                  bb.event.TreeDataPreparationCompleted)):
                continue

            if isinstance(event, (bb.event.BuildCompleted)):
                # update the build info helper on BuildCompleted, not on CommandXXX
                buildinfohelper.update_build_information(
                    event, errors, warnings, taskfailures)
                buildinfohelper.close(errorcode)
                # mark the log output; controllers may kill the toasterUI after seeing this log
                logger.info("ToasterUI build done")

                # we start a new build info
                if buildinfohelper.brbe is not None:

                    logger.debug(
                        1,
                        "ToasterUI under BuildEnvironment management - exiting after the build"
                    )
                    server.terminateServer()
                else:
                    logger.debug(1, "ToasterUI prepared for new build")
                    errors = 0
                    warnings = 0
                    taskfailures = []
                    buildinfohelper = BuildInfoHelper(server,
                                                      build_history_enabled)

                continue

            if isinstance(event,
                          (bb.command.CommandCompleted,
                           bb.command.CommandFailed, bb.command.CommandExit)):
                errorcode = 0
                if (isinstance(event, bb.command.CommandFailed)):
                    event.levelno = format.ERROR
                    event.msg = "Command Failed " + event.error
                    event.pathname = ""
                    event.lineno = 0
                    buildinfohelper.store_log_event(event)
                    errors += 1
                    errorcode = 1
                    logger.error("Command execution failed: %s", event.error)

                continue

            if isinstance(event, bb.event.MetadataEvent):
                if event.type == "SinglePackageInfo":
                    buildinfohelper.store_build_package_information(event)
                elif event.type == "LayerInfo":
                    buildinfohelper.store_layer_info(event)
                elif event.type == "BuildStatsList":
                    buildinfohelper.store_tasks_stats(event)
                elif event.type == "ImagePkgList":
                    buildinfohelper.store_target_package_data(event)
                elif event.type == "MissedSstate":
                    buildinfohelper.store_missed_state_tasks(event)
                elif event.type == "ImageFileSize":
                    buildinfohelper.update_target_image_file(event)
                elif event.type == "ArtifactFileSize":
                    buildinfohelper.update_artifact_image_file(event)
                elif event.type == "LicenseManifestPath":
                    buildinfohelper.store_license_manifest_path(event)
                else:
                    logger.error("Unprocessed MetadataEvent %s " % str(event))
                continue

            if isinstance(event, bb.cooker.CookerExit):
                # exit when the server exits
                break

            # ignore
            if isinstance(
                    event,
                (bb.event.BuildBase, bb.event.StampUpdate,
                 bb.event.RecipePreFinalise, bb.runqueue.runQueueEvent,
                 bb.runqueue.runQueueExitWait, bb.event.OperationProgress,
                 bb.command.CommandFailed, bb.command.CommandExit,
                 bb.command.CommandCompleted)):
                continue

            if isinstance(event, bb.event.DepTreeGenerated):
                buildinfohelper.store_dependency_information(event)
                continue

            logger.error("Unknown event: %s", event)
            return_value += 1

        except EnvironmentError as ioerror:
            # ignore interrupted io
            if ioerror.args[0] == 4:
                pass
        except KeyboardInterrupt:
            main.shutdown = 1
            pass
        except Exception as e:
            # print errors to log
            import traceback
            from pprint import pformat
            exception_data = traceback.format_exc()
            logger.error("%s\n%s" % (e, exception_data))

            exc_type, exc_value, tb = sys.exc_info()
            if tb is not None:
                curr = tb
                while curr is not None:
                    logger.warn(
                        "Error data dump %s\n%s\n" % (traceback.format_tb(
                            curr, 1), pformat(curr.tb_frame.f_locals)))
                    curr = curr.tb_next

            # save them to database, if possible; if it fails, we already logged to console.
            try:
                buildinfohelper.store_log_exception("%s\n%s" %
                                                    (str(e), exception_data))
            except Exception as ce:
                logger.error(
                    "CRITICAL - Failed to to save toaster exception to the database: %s"
                    % str(ce))

            # make sure we return with an error
            return_value += 1
            pass

    if interrupted:
        if return_value == 0:
            return_value += 1

    logger.warn("Return value is %d", return_value)
    return return_value