Blame src/plugins/abrt-action-ureport

Packit 8ea169
#!/usr/bin/python3 -u
Packit 8ea169
# WARNING: python -u means unbuffered I/O. Without it the messages are
Packit 8ea169
# passed to the parent asynchronously which looks bad in clients.
Packit 8ea169
#
Packit 8ea169
# This script wraps reporter-ureport client and keeps number of sent
Packit 8ea169
# uReports to a server consistent with number of problem ocurrences.
Packit 8ea169
Packit 8ea169
import sys
Packit 8ea169
import os
Packit 8ea169
import getopt
Packit 8ea169
import augeas
Packit 8ea169
Packit 8ea169
from report import dd_opendir, DD_FAIL_QUIETLY_ENOENT, run_event_on_problem_dir
Packit 8ea169
from reportclient import set_verbosity, error_msg_and_die, error_msg, log1, log_warning
Packit 8ea169
Packit 8ea169
GETTEXT_PROGNAME = "abrt"
Packit 8ea169
import locale
Packit 8ea169
import gettext
Packit 8ea169
Packit 8ea169
_ = lambda x: gettext.gettext(x)
Packit 8ea169
Packit 8ea169
def init_gettext():
Packit 8ea169
    try:
Packit 8ea169
        locale.setlocale(locale.LC_ALL, "")
Packit 8ea169
    except locale.Error:
Packit 8ea169
        os.environ['LC_ALL'] = 'C'
Packit 8ea169
        locale.setlocale(locale.LC_ALL, "")
Packit 8ea169
    # Defeat "AttributeError: 'module' object has no attribute 'nl_langinfo'"
Packit 8ea169
    try:
Packit 8ea169
        gettext.bind_textdomain_codeset(GETTEXT_PROGNAME, locale.nl_langinfo(locale.CODESET))
Packit 8ea169
    except AttributeError:
Packit 8ea169
        pass
Packit 8ea169
    gettext.bindtextdomain(GETTEXT_PROGNAME, '/usr/share/locale')
Packit 8ea169
    gettext.textdomain(GETTEXT_PROGNAME)
Packit 8ea169
Packit 8ea169
Packit 8ea169
def get_augeas(module, file_path):
Packit 8ea169
    """
Packit 8ea169
    A function for efficient configuration of Augeas.
Packit 8ea169
    Augeas modules are placed in /usr/share/augeas/lenses/dist
Packit 8ea169
    """
Packit 8ea169
Packit 8ea169
    aug_obj = augeas.Augeas(flags=augeas.Augeas.NO_MODL_AUTOLOAD)
Packit 8ea169
    aug_obj.set("/augeas/load/{0}/lens".format(module), "{0}.lns".format(module))
Packit 8ea169
    aug_obj.set("/augeas/load/{0}/incl".format(module), file_path)
Packit 8ea169
    aug_obj.load()
Packit 8ea169
    return aug_obj
Packit 8ea169
Packit 8ea169
Packit 8ea169
def spawn_and_wait(prog, args=None):
Packit 8ea169
    if args is None:
Packit 8ea169
        args = [prog]
Packit 8ea169
    else:
Packit 8ea169
        args.insert(0, prog)
Packit 8ea169
Packit 8ea169
    try:
Packit 8ea169
        return os.spawnvpe(os.P_WAIT, prog, args, os.environ)
Packit 8ea169
    except OSError as err:
Packit 8ea169
        error_msg(_("Unable to start '%s', error message was: '%s'"),
Packit 8ea169
                    " ".join(args), err)
Packit 8ea169
        return -1
Packit 8ea169
Packit 8ea169
def try_parse_number(dd, filename):
Packit 8ea169
    try:
Packit 8ea169
        n = dd.load_text(filename, DD_FAIL_QUIETLY_ENOENT)
Packit 8ea169
        if n == "":
Packit 8ea169
            return 0
Packit 8ea169
        return int(n)
Packit 8ea169
    except:
Packit 8ea169
        error_msg(_("Not a number in file '%s'"), filename)
Packit 8ea169
        return 0
Packit 8ea169
Packit 8ea169
def get_bugzilla_reports(reported_to):
Packit 8ea169
    bugs = set()
Packit 8ea169
    for line in reported_to.split("\n"):
Packit 8ea169
        if line.startswith("Bugzilla:"):
Packit 8ea169
            bugs.add(line)
Packit 8ea169
    return bugs
Packit 8ea169
Packit 8ea169
def run_event(event_name, dump_dir_name):
Packit 8ea169
    state, ret = run_event_on_problem_dir(dump_dir_name, event_name)
Packit 8ea169
    if ret == 0 and state.children_count == 0:
Packit 8ea169
        log1("Didn't find definition of event '%s'", event_name)
Packit 8ea169
Packit 8ea169
if __name__ == "__main__":
Packit 8ea169
    # localization
Packit 8ea169
    init_gettext()
Packit 8ea169
Packit 8ea169
    verbose = 0
Packit 8ea169
    ABRT_VERBOSE = os.getenv("ABRT_VERBOSE")
Packit 8ea169
    if ABRT_VERBOSE:
Packit 8ea169
        try:
Packit 8ea169
            verbose = int(ABRT_VERBOSE)
Packit 8ea169
        except:
Packit 8ea169
            pass
Packit 8ea169
Packit 8ea169
    progname = os.path.basename(sys.argv[0])
Packit 8ea169
    help_text = _("Usage: %s [-v]") % progname
Packit 8ea169
    try:
Packit 8ea169
        opts, args = getopt.getopt(sys.argv[1:], "vh", ["help"])
Packit 8ea169
    except getopt.GetoptError as err:
Packit 8ea169
        error_msg(err)  # prints something like "option -a not recognized"
Packit 8ea169
        error_msg_and_die(help_text)
Packit 8ea169
Packit 8ea169
    for opt, arg in opts:
Packit 8ea169
        if opt in ("-h", "--help"):
Packit 8ea169
            print(help_text)
Packit 8ea169
            sys.exit(0)
Packit 8ea169
        if opt == "-v":
Packit 8ea169
            verbose += 1
Packit 8ea169
Packit 8ea169
    set_verbosity(verbose)
Packit 8ea169
    os.environ["ABRT_VERBOSE"] = str(verbose)
Packit 8ea169
Packit 8ea169
    # getcwd might fail if cwd was deleted
Packit 8ea169
    try:
Packit 8ea169
        dirname = os.getcwd()
Packit 8ea169
    except OSError as err:
Packit 8ea169
        error_msg_and_die(_("Unable to get current working directory as"
Packit 8ea169
                            " it was probably deleted"))
Packit 8ea169
Packit 8ea169
    dd = dd_opendir(dirname, 0)
Packit 8ea169
    if not dd:
Packit 8ea169
        sys.exit(1)
Packit 8ea169
Packit 8ea169
    report_type = dd.load_text("type", DD_FAIL_QUIETLY_ENOENT)
Packit 8ea169
Packit 8ea169
    # because of backward compatibility
Packit 8ea169
    if not report_type:
Packit 8ea169
        report_type = dd.load_text("analyzer", 0)
Packit 8ea169
Packit 8ea169
    core_backtrace_exists = dd.exist("core_backtrace")
Packit 8ea169
    packaged = dd.exist("package")
Packit 8ea169
    reported_to = dd.load_text("reported_to", DD_FAIL_QUIETLY_ENOENT)
Packit 8ea169
    ureports_counter = try_parse_number(dd, "ureports_counter")
Packit 8ea169
    count = try_parse_number(dd, "count")
Packit 8ea169
    dd.close()
Packit 8ea169
Packit 8ea169
    # Send only if the problem is not yet reported
Packit 8ea169
    #           if the count file is corrupted or
Packit 8ea169
    #           if the number of ureports is lower then the number of occurrences
Packit 8ea169
    if ureports_counter != 0 and count != 0 and ureports_counter >= count:
Packit 8ea169
        log1("uReport has been already sent: '%s'", dirname)
Packit 8ea169
Packit 8ea169
        if reported_to and reported_to != "":
Packit 8ea169
            bugs = get_bugzilla_reports(reported_to)
Packit 8ea169
            if bugs:
Packit 8ea169
                log_warning(_("A bug was already filed about this problem:"))
Packit 8ea169
                bugs = sorted(bugs)
Packit 8ea169
                for bug in bugs:
Packit 8ea169
                    print(bug)
Packit 8ea169
                sys.exit(70)  # EXIT_STOP_EVENT_RUN
Packit 8ea169
            log1("Bug for '%s' not yet filed. Continuing.", dirname)
Packit 8ea169
            sys.exit(0)
Packit 8ea169
        else:
Packit 8ea169
            log1("'%s/reported_to' doesn't exist", dirname)
Packit 8ea169
Packit 8ea169
        log_warning(_("uReport was already sent, not sending it again"))
Packit 8ea169
        sys.exit(0)
Packit 8ea169
Packit 8ea169
    if report_type == "CCpp" and not core_backtrace_exists:
Packit 8ea169
        exitcode = spawn_and_wait("abrt-action-generate-core-backtrace")
Packit 8ea169
        if exitcode != 0:
Packit 8ea169
            log1("uReport can't be sent without core_backtrace. Exiting.")
Packit 8ea169
            sys.exit(1)
Packit 8ea169
Packit 8ea169
    if not packaged:
Packit 8ea169
        log1("Problem comes from unpackaged executable.")
Packit 8ea169
Packit 8ea169
        process_unpackaged_str = os.getenv("uReport_ProcessUnpackaged")
Packit 8ea169
        if not process_unpackaged_str:
Packit 8ea169
            augeas_conf = get_augeas("libreport", "/etc/libreport/plugins/ureport.conf")
Packit 8ea169
            process_unpackaged_str = augeas_conf.get("/files/etc/libreport/plugins/ureport.conf/ProcessUnpackaged")
Packit 8ea169
        process_unpackaged = False
Packit 8ea169
        if process_unpackaged_str:
Packit 8ea169
            process_unpackaged = process_unpackaged_str.lower() in ['yes', '1', 'on']
Packit 8ea169
Packit 8ea169
        if not process_unpackaged:
Packit 8ea169
            log_warning(_("Problem comes from unpackaged executable. Unable to create uReport."))
Packit 8ea169
            sys.exit(1)
Packit 8ea169
Packit 8ea169
    exitcode = spawn_and_wait("reporter-ureport")
Packit 8ea169
    if exitcode == 0 or exitcode == 70:
Packit 8ea169
        dd = dd_opendir(dirname, 0)
Packit 8ea169
        if not dd:
Packit 8ea169
            sys.exit(1)
Packit 8ea169
        dd.save_text("ureports_counter", str(ureports_counter + 1))
Packit 8ea169
        reported_to = dd.load_text("reported_to", DD_FAIL_QUIETLY_ENOENT)
Packit 8ea169
        dd.close()
Packit 8ea169
Packit 8ea169
        watch = os.getenv("uReport_WatchReportedBugs") or ""
Packit 8ea169
        if exitcode == 70 and watch.lower() in ["yes", "on", "1"]:
Packit 8ea169
            if reported_to and reported_to != "" and get_bugzilla_reports(reported_to):
Packit 8ea169
                log_warning(_("Adding you to CC List of the existing bugzilla bug"))
Packit 8ea169
                run_event("watch_Bugzilla", dirname)
Packit 8ea169
Packit 8ea169
        email = os.getenv("uReport_ContactEmail")
Packit 8ea169
        if not email:
Packit 8ea169
            augeas_conf = get_augeas("libreport", "/etc/libreport/plugins/ureport.conf")
Packit 8ea169
            email = augeas_conf.get("/files/etc/libreport/plugins/ureport.conf/ContactEmail")
Packit 8ea169
Packit 8ea169
        if email:
Packit 8ea169
            log1("Attaching ContactEmail: " + email)
Packit 8ea169
            spawn_and_wait("reporter-ureport", ["-A", "-E"])
Packit 8ea169
Packit 8ea169
        sys.exit(exitcode)
Packit 8ea169
    else:
Packit 8ea169
        log1(_("reporter-ureport failed with exit code %d" % exitcode))
Packit 8ea169
        sys.exit(exitcode)