Exemple #1
0
def item(problem_id, component_names=None):
    components_form = ProblemComponents()

    problem = db.session.query(Problem).filter(
        Problem.id == problem_id).first()

    if problem is None:
        raise abort(404)

    if component_names:
        try:
            (db.session.query(ProblemComponent).filter_by(
                problem_id=problem_id).delete())

            for index, comp_name in enumerate(component_names.split(',')):
                component = (db.session.query(OpSysComponent).filter_by(
                    name=comp_name).first())
                if not component:
                    raise ValueError(
                        "Component {} not found.".format(comp_name))

                db.session.add(
                    ProblemComponent(problem_id=problem.id,
                                     component_id=component.id,
                                     order=index + 1))

            reassign = (db.session.query(ProblemReassign).filter_by(
                problem_id=problem_id).first())
            if reassign is None:
                reassign = ProblemReassign(problem_id=problem_id)

            reassign.date = datetime.date.today()
            reassign.username = g.user.username

            db.session.add(reassign)
            db.session.commit()
        except SQLAlchemyError:
            db.session.rollback()
            flash("Database transaction error.", 'error')
        except ValueError as e:
            db.session.rollback()
            flash(str(e), 'error')

    report_ids = [report.id for report in problem.reports]

    solutions = []
    equal_solution = lambda s: [x for x in solutions if s.cause == x.cause]
    for report in problem.reports:
        if report.max_certainty is not None:
            osr = get_report_opsysrelease(db=db, report_id=report.id)
            solution = find_solution(report, db=db, osr=osr)
            if solution and not equal_solution(solution):
                solutions.append(solution)

    sub = (db.session.query(
        ReportOpSysRelease.opsysrelease_id,
        func.sum(ReportOpSysRelease.count).label("cnt")).join(Report).filter(
            Report.id.in_(report_ids)).group_by(
                ReportOpSysRelease.opsysrelease_id).subquery())

    osreleases = (db.session.query(OpSysRelease, sub.c.cnt).join(sub).order_by(
        desc("cnt")).all())

    sub = (db.session.query(
        ReportArch.arch_id,
        func.sum(ReportArch.count).label("cnt")).join(Report).filter(
            Report.id.in_(report_ids)).group_by(ReportArch.arch_id).subquery())

    arches = (db.session.query(Arch, sub.c.cnt).join(sub).order_by(
        desc("cnt")).all())

    exes = (db.session.query(
        ReportExecutable.path,
        func.sum(ReportExecutable.count).label("cnt")).join(Report).filter(
            Report.id.in_(report_ids)).group_by(
                ReportExecutable.path).order_by(desc("cnt")).all())

    sub = (db.session.query(
        ReportPackage.installed_package_id,
        func.sum(ReportPackage.count).label("cnt")).join(Report).filter(
            Report.id.in_(report_ids)).group_by(
                ReportPackage.installed_package_id).subquery())
    packages_known = db.session.query(Package, sub.c.cnt).join(sub).all()

    packages_unknown = (db.session.query(
        ReportUnknownPackage, ReportUnknownPackage.count).join(Report).filter(
            Report.id.in_(report_ids))).all()

    packages = packages_known + packages_unknown

    # creates a package_counts list with this structure:
    # [(package name, count, [(package version, count in the version)])]
    names = defaultdict(lambda: {"count": 0, "versions": defaultdict(int)})
    for (pkg, cnt) in packages:
        names[pkg.name]["name"] = pkg.name
        names[pkg.name]["count"] += cnt
        names[pkg.name]["versions"][pkg.evr()] += cnt

    package_counts = []
    for pkg in sorted(names.values(), key=itemgetter("count"), reverse=True):
        package_counts.append((pkg["name"], pkg["count"],
                               sorted(pkg["versions"].items(),
                                      key=itemgetter(1),
                                      reverse=True)))

    for report in problem.reports:
        for backtrace in report.backtraces:
            fid = 0
            for frame in backtrace.frames:
                fid += 1
                frame.nice_order = fid

    bt_hashes = (db.session.query(
        ReportHash.hash).join(Report).join(Problem).filter(
            Problem.id == problem_id).distinct(ReportHash.hash).all())

    forward = {
        "problem": problem,
        "osreleases": metric(osreleases),
        "arches": metric(arches),
        "exes": metric(exes),
        "package_counts": package_counts,
        "solutions": solutions,
        "components_form": components_form
    }

    if not bt_hashes:
        logger.warning("No backtrace hashes found for problem #%d", problem_id)
    else:
        # Generate a permalink for this problem. We do this by uniformly picking
        # (at most) 10 hashes from the list. This ensures the selected hashes are
        # more or less representative of the problem.
        k = min(len(bt_hashes), 10)
        # A hint of determinism in this uncertain world.
        r = random.Random(problem_id)
        hashes_sampled = r.sample(bt_hashes, k)
        permalink_query = "&".join("bth={}".format(bth)
                                   for (bth, ) in hashes_sampled)
        forward["permalink_query"] = permalink_query

    if request_wants_json():
        return jsonify(forward)

    is_maintainer = is_problem_maintainer(db, g.user, problem)
    forward["is_maintainer"] = is_maintainer

    forward["extfafs"] = get_external_faf_instances(db)

    if report_ids:
        bt_diff_form = BacktraceDiffForm()
        bt_diff_form.lhs.choices = [(id, id) for id in report_ids]
        bt_diff_form.rhs.choices = bt_diff_form.lhs.choices
        forward['bt_diff_form'] = bt_diff_form

    return render_template("problems/item.html", **forward)
Exemple #2
0
def item(problem_id, component_names=None):
    components_form = ProblemComponents()

    problem = db.session.query(Problem).filter(
        Problem.id == problem_id).first()

    if problem is None:
        raise abort(404)

    if component_names:
        try:
            (db.session.query(ProblemComponent)
             .filter_by(problem_id=problem_id)
             .delete())

            for index, comp_name in enumerate(component_names.split(',')):
                component = (db.session.query(OpSysComponent)
                             .filter_by(name=comp_name)
                             .first())
                if not component:
                    raise ValueError("Component {} not found.".format(
                        comp_name))

                db.session.add(ProblemComponent(problem_id=problem.id,
                                                component_id=component.id,
                                                order=index + 1))

            reassign = (db.session.query(ProblemReassign)
                        .filter_by(problem_id=problem_id)
                        .first())
            if reassign is None:
                reassign = ProblemReassign(problem_id=problem_id)

            reassign.date = datetime.date.today()
            reassign.username = g.user.username

            db.session.add(reassign)
            db.session.commit()
        except SQLAlchemyError:
            db.session.rollback()
            flash("Database transaction error.", 'error')
        except ValueError as e:
            db.session.rollback()
            flash(str(e), 'error')

    report_ids = [report.id for report in problem.reports]

    solutions = []
    equal_solution = lambda s: [x for x in solutions if s.cause == x.cause]
    for report in problem.reports:
        if report.max_certainty is not None:
            osr = get_report_opsysrelease(db=db, report_id=report.id)
            solution = find_solution(report, db=db, osr=osr)
            if solution and not equal_solution(solution):
                solutions.append(solution)

    sub = (db.session.query(ReportOpSysRelease.opsysrelease_id,
                            func.sum(ReportOpSysRelease.count).label("cnt"))
           .join(Report)
           .filter(Report.id.in_(report_ids))
           .group_by(ReportOpSysRelease.opsysrelease_id)
           .subquery())

    osreleases = (db.session.query(OpSysRelease, sub.c.cnt)
                  .join(sub)
                  .order_by(desc("cnt"))
                  .all())

    sub = (db.session.query(ReportArch.arch_id,
                            func.sum(ReportArch.count).label("cnt"))
           .join(Report)
           .filter(Report.id.in_(report_ids))
           .group_by(ReportArch.arch_id)
           .subquery())

    arches = (db.session.query(Arch, sub.c.cnt).join(sub)
              .order_by(desc("cnt"))
              .all())

    exes = (db.session.query(ReportExecutable.path,
                             func.sum(ReportExecutable.count).label("cnt"))
            .join(Report)
            .filter(Report.id.in_(report_ids))
            .group_by(ReportExecutable.path)
            .order_by(desc("cnt"))
            .all())

    sub = (db.session.query(ReportPackage.installed_package_id,
                            func.sum(ReportPackage.count).label("cnt"))
           .join(Report)
           .filter(Report.id.in_(report_ids))
           .group_by(ReportPackage.installed_package_id)
           .subquery())
    packages_known = db.session.query(Package, sub.c.cnt).join(sub).all()

    packages_unknown = (db.session.query(ReportUnknownPackage,
                                         ReportUnknownPackage.count)
                        .join(Report)
                        .filter(Report.id.in_(report_ids))).all()

    packages = packages_known + packages_unknown

    # creates a package_counts list with this structure:
    # [(package name, count, [(package version, count in the version)])]
    names = defaultdict(lambda: {"count": 0, "versions": defaultdict(int)})
    for (pkg, cnt) in packages:
        names[pkg.name]["name"] = pkg.name
        names[pkg.name]["count"] += cnt
        names[pkg.name]["versions"][pkg.evr()] += cnt

    package_counts = []
    for pkg in sorted(names.values(), key=itemgetter("count"), reverse=True):
        package_counts.append((
            pkg["name"],
            pkg["count"],
            sorted(pkg["versions"].items(), key=itemgetter(1), reverse=True)))

    for report in problem.reports:
        for backtrace in report.backtraces:
            fid = 0
            for frame in backtrace.frames:
                fid += 1
                frame.nice_order = fid

    bt_hashes = (db.session.query(ReportHash.hash)
                 .join(Report)
                 .join(Problem)
                 .filter(Problem.id == problem_id)
                 .distinct(ReportHash.hash).all())
    # Limit to 10 bt_hashes (otherwise the URL can get too long)
    # Select the 10 hashes uniformly from the entire list to make sure it is a
    # good representation. (Slicing the 10 first could mean the 10 oldest
    # are selected which is not a good representation.)
    k = min(len(bt_hashes), 10)
    a = 0
    d = len(bt_hashes)/float(k)
    bt_hashes_limited = []
    for _ in range(k):
        bt_hashes_limited.append("bth=" + bt_hashes[int(a)][0])
        a += d
    bt_hash_qs = "&".join(bt_hashes_limited)

    forward = {"problem": problem,
               "osreleases": metric(osreleases),
               "arches": metric(arches),
               "exes": metric(exes),
               "package_counts": package_counts,
               "bt_hash_qs": bt_hash_qs,
               "solutions": solutions,
               "components_form": components_form
              }

    if request_wants_json():
        return jsonify(forward)

    is_maintainer = is_problem_maintainer(db, g.user, problem)
    forward["is_maintainer"] = is_maintainer

    forward["extfafs"] = get_external_faf_instances(db)

    if report_ids:
        bt_diff_form = BacktraceDiffForm()
        bt_diff_form.lhs.choices = [(id, id) for id in report_ids]
        bt_diff_form.rhs.choices = bt_diff_form.lhs.choices
        forward['bt_diff_form'] = bt_diff_form

    return render_template("problems/item.html", **forward)