def save_attachment(db, attachment): atype = attachment["type"].lower() if not attachment_type_allowed(atype): raise FafError( "Attachment type '{}' not allowed on this server".format(atype)) report = get_report(db, attachment["bthash"]) if not report: raise FafError("Report for given bthash not found") if atype in ["rhbz", "fedora-bugzilla", "rhel-bugzilla"]: bug_id = int(attachment["data"]) reportbug = (db.session.query( ReportBz).filter((ReportBz.report_id == report.id) & (ReportBz.bzbug_id == bug_id)).first()) if reportbug: log.debug("Skipping existing attachment") return bug = get_bz_bug(db, bug_id) if not bug: if atype in bugtrackers: # download from bugtracker identified by atype tracker = bugtrackers[atype] if not tracker.installed(db): raise FafError("Bugtracker used in this attachment" " is not installed") bug = tracker.download_bug_to_storage(db, bug_id) elif atype == "rhbz": # legacy value # - we need to guess the bugtracker: # either fedora-bugzilla or rhel-bugzilla, # former is more probable for possible_tracker in ["fedora-bugzilla", "rhel-bugzilla"]: if possible_tracker not in bugtrackers: continue tracker = bugtrackers[possible_tracker] if not tracker.installed(db): continue bug = tracker.download_bug_to_storage(db, bug_id) if bug: break if bug: new = ReportBz() new.report = report new.bzbug = bug db.session.add(new) db.session.flush() else: log.error("Failed to fetch bug #{0} from '{1}'".format( bug_id, atype)) elif atype == "centos-mantisbt": bug_id = int(attachment["data"]) reportbug = (db.session.query(ReportMantis).filter( (ReportMantis.report_id == report.id) & (ReportMantis.mantisbug_id == bug_id)).first()) if reportbug: log.debug("Skipping existing attachment") return bug = get_mantis_bug(db, bug_id) if not bug: if atype in bugtrackers: # download from bugtracker identified by atype tracker = bugtrackers[atype] if not tracker.installed(db): raise FafError("Bugtracker used in this attachment" " is not installed") bug = tracker.download_bug_to_storage(db, bug_id) if bug: new = ReportMantis() new.report = report new.mantisbug = bug db.session.add(new) db.session.flush() else: log.error("Failed to fetch bug #{0} from '{1}'".format( bug_id, atype)) elif atype == "comment": comment = ReportComment() comment.report = report comment.text = attachment["data"] comment.saved = datetime.datetime.utcnow() db.session.add(comment) db.session.flush() elif atype == "email": db_contact_email = get_contact_email(db, attachment["data"]) if db_contact_email is None: db_contact_email = ContactEmail() db_contact_email.email_address = attachment["data"] db.session.add(db_contact_email) db_report_contact_email = ReportContactEmail() db_report_contact_email.contact_email = db_contact_email db_report_contact_email.report = report db.session.add(db_report_contact_email) else: db_report_contact_email = \ get_report_contact_email(db, db_contact_email.id, report.id) if db_report_contact_email is None: db_report_contact_email = ReportContactEmail() db_report_contact_email.contact_email = db_contact_email db_report_contact_email.report = report db.session.add(db_report_contact_email) try: db.session.flush() except IntegrityError: raise FafError("Email address already assigned to the report") elif atype == "url": url = attachment["data"] # 0ne URL can be attached to many Reports, but every reports must # have unique url's db_url = (db.session.query(ReportURL).filter( ReportURL.url == url).filter( ReportURL.report_id == report.id).first()) if db_url: log.debug("Skipping existing URL") return db_url = ReportURL() db_url.report = report db_url.url = url db_url.saved = datetime.datetime.utcnow() try: db.session.flush() except IntegrityError: raise FafError("Unable to save URL") else: log.warning("Unknown attachment type")
def _save_bug(self, db, bug): """ Save bug represented by `bug_dict` to the database. If bug is marked as duplicate, the duplicate bug is downloaded as well. """ bug_dict = self._preprocess_bug(bug) if not bug_dict: self.log_error("Bug pre-processing failed") raise FafError("Bug pre-processing failed") self.log_debug("Saving bug #{0}: {1}".format(bug_dict["bug_id"], bug_dict["summary"])) bug_id = bug_dict["bug_id"] # check if we already have this bug up-to-date old_bug = ( db.session.query(BzBug) .filter(BzBug.id == bug_id) .filter(BzBug.last_change_time == bug_dict["last_change_time"]) .first()) if old_bug: self.log_info("Bug already up-to-date") return old_bug tracker = queries.get_bugtracker_by_name(db, self.name) if not tracker: self.log_error("Tracker with name '{0}' is not installed" .format(self.name)) raise FafError("Tracker with name '{0}' is not installed" .format(self.name)) opsysrelease = queries.get_osrelease(db, bug_dict["product"], bug_dict["version"]) if not opsysrelease: self.log_error("Unable to save this bug due to unknown " "release '{0} {1}'".format(bug_dict["product"], bug_dict["version"])) raise FafError("Unable to save this bug due to unknown " "release '{0} {1}'".format(bug_dict["product"], bug_dict["version"])) relcomponent = queries.get_component_by_name_release( db, opsysrelease, bug_dict["component"]) if not relcomponent: self.log_error("Unable to save this bug due to unknown " "component '{0}'".format(bug_dict["component"])) raise FafError("Unable to save this bug due to unknown " "component '{0}'".format(bug_dict["component"])) component = relcomponent.component reporter = queries.get_bz_user(db, bug_dict["reporter"]) if not reporter: self.log_debug("Creator {0} not found".format( bug_dict["reporter"])) downloaded = self._download_user(bug_dict["reporter"]) if not downloaded: self.log_error("Unable to download user, skipping.") raise FafError("Unable to download user, skipping.") reporter = self._save_user(db, downloaded) new_bug = BzBug() new_bug.id = bug_dict["bug_id"] new_bug.summary = bug_dict["summary"] new_bug.status = bug_dict["status"] new_bug.creation_time = bug_dict["creation_time"] new_bug.last_change_time = bug_dict["last_change_time"] new_bug.private = True if bug_dict["groups"] else False if bug_dict["status"] == "CLOSED": new_bug.resolution = bug_dict["resolution"] if bug_dict["resolution"] == "DUPLICATE": if not queries.get_bz_bug(db, bug_dict["dupe_id"]): self.log_debug("Duplicate #{0} not found".format( bug_dict["dupe_id"])) dup = self.download_bug_to_storage(db, bug_dict["dupe_id"]) if dup: new_bug.duplicate = dup.id new_bug.tracker_id = tracker.id new_bug.component_id = component.id new_bug.opsysrelease_id = opsysrelease.id new_bug.creator_id = reporter.id new_bug.whiteboard = bug_dict["status_whiteboard"] # the bug itself might be downloaded during duplicate processing # exit in this case - it would cause duplicate database entry if queries.get_bz_bug(db, bug_dict["bug_id"]): self.log_debug("Bug #{0} already exists in storage," " updating".format(bug_dict["bug_id"])) bugdict = {} for col in new_bug.__table__._columns: bugdict[col.name] = getattr(new_bug, col.name) (db.session.query(BzBug) .filter(BzBug.id == bug_id).update(bugdict)) new_bug = queries.get_bz_bug(db, bug_dict["bug_id"]) else: db.session.add(new_bug) db.session.flush() self._save_ccs(db, bug_dict["cc"], new_bug.id) self._save_history(db, bug_dict["history"], new_bug.id) if self.save_attachments: self._save_attachments(db, bug_dict["attachments"], new_bug.id) if self.save_comments: self._save_comments(db, bug_dict["comments"], new_bug.id) return new_bug
def associate_bug(report_id): result = (db.session.query(Report, OpSysComponent).join(OpSysComponent).filter( Report.id == report_id).first()) if result is None: abort(404) report, component = result is_maintainer = app.config["EVERYONE_IS_MAINTAINER"] if not is_maintainer and g.user is not None: if user_is_maintainer(db, g.user.username, component.id): is_maintainer = True if not is_maintainer: flash("You are not the maintainer of this component.", "danger") return redirect(url_for("reports.item", report_id=report_id)) form = AssociateBzForm(request.form) if request.method == "POST" and form.validate(): bug_id = form.bug_id.data reportbug = (db.session.query( ReportBz).filter((ReportBz.report_id == report.id) & (ReportBz.bzbug_id == bug_id)).first()) if reportbug: flash("Bug already associated.", "danger") else: bug = get_bz_bug(db, bug_id) if not bug: tracker = bugtrackers[form.bugtracker.data] try: bug = tracker.download_bug_to_storage_no_retry(db, bug_id) except Exception as e: flash("Failed to fetch bug. {0}".format(str(e)), "danger") raise if bug: new = ReportBz() new.report = report new.bzbug = bug db.session.add(new) db.session.flush() db.session.commit() flash("Bug successfully associated.", "success") return redirect(url_for("reports.item", report_id=report_id)) else: flash("Failed to fetch bug.", "danger") bthash_url = url_for("reports.bthash_forward", bthash=report.hashes[0].hash, _external=True) new_bug_params = { "component": component.name, "short_desc": "[abrt] [faf] {0}: {1}(): {2} killed by {3}".format( component.name, report.crash_function, ",".join(exe.path for exe in report.executables), report.errname), "comment": "This bug has been created based on an anonymous crash " "report requested by the package maintainer.\n\n" "Report URL: {0}".format(bthash_url), "bug_file_loc": bthash_url } new_bug_urls = [] for rosr in report.opsysreleases: osr = rosr.opsysrelease for bugtracker in bugtrackers.keys(): try: params = new_bug_params.copy() if osr.opsys.name.startswith("Red Hat"): params.update(product="{0} {1}".format( osr.opsys.name, osr.version[0]), version=osr.version) else: params.update(product=osr.opsys.name, version=osr.version) print(params) new_bug_urls.append( ("{0} {1} in {2}".format(osr.opsys.name, osr.version, bugtracker), "{0}?{1}".format(bugtrackers[bugtracker].new_bug_url, urllib.urlencode(params)))) except: pass return render_template("reports/associate_bug.html", form=form, report=report, new_bug_urls=new_bug_urls)
def save_attachment(db, attachment): atype = attachment["type"].lower() if not attachment_type_allowed(atype): raise FafError("Attachment type '{}' not allowed on this server" .format(atype)) report = get_report(db, attachment["bthash"]) if not report: raise FafError("Report for given bthash not found") if atype in ["rhbz", "fedora-bugzilla", "rhel-bugzilla"]: bug_id = int(attachment["data"]) reportbug = (db.session.query(ReportBz) .filter( (ReportBz.report_id == report.id) & (ReportBz.bzbug_id == bug_id) ) .first()) if reportbug: log.debug("Skipping existing attachment") return bug = get_bz_bug(db, bug_id) if not bug: if atype in bugtrackers: # download from bugtracker identified by atype tracker = bugtrackers[atype] if not tracker.installed(db): raise FafError("Bugtracker used in this attachment" " is not installed") bug = tracker.download_bug_to_storage(db, bug_id) elif atype == "rhbz": # legacy value # - we need to guess the bugtracker: # either fedora-bugzilla or rhel-bugzilla, # former is more probable for possible_tracker in ["fedora-bugzilla", "rhel-bugzilla"]: if possible_tracker not in bugtrackers: continue tracker = bugtrackers[possible_tracker] if not tracker.installed(db): continue bug = tracker.download_bug_to_storage(db, bug_id) if bug: break if bug: new = ReportBz() new.report = report new.bzbug = bug db.session.add(new) db.session.flush() else: log.error("Failed to fetch bug #{0} from '{1}'" .format(bug_id, atype)) elif atype == "centos-mantisbt": bug_id = int(attachment["data"]) reportbug = (db.session.query(ReportMantis) .filter( (ReportMantis.report_id == report.id) & (ReportMantis.mantisbug_id == bug_id)) .first()) if reportbug: log.debug("Skipping existing attachment") return bug = get_mantis_bug(db, bug_id) if not bug: if atype in bugtrackers: # download from bugtracker identified by atype tracker = bugtrackers[atype] if not tracker.installed(db): raise FafError("Bugtracker used in this attachment" " is not installed") bug = tracker.download_bug_to_storage(db, bug_id) if bug: new = ReportMantis() new.report = report new.mantisbug = bug db.session.add(new) db.session.flush() else: log.error("Failed to fetch bug #{0} from '{1}'" .format(bug_id, atype)) elif atype == "comment": comment = ReportComment() comment.report = report comment.text = attachment["data"] comment.saved = datetime.datetime.utcnow() db.session.add(comment) db.session.flush() elif atype == "email": db_contact_email = get_contact_email(db, attachment["data"]) if db_contact_email is None: db_contact_email = ContactEmail() db_contact_email.email_address = attachment["data"] db.session.add(db_contact_email) db_report_contact_email = ReportContactEmail() db_report_contact_email.contact_email = db_contact_email db_report_contact_email.report = report db.session.add(db_report_contact_email) else: db_report_contact_email = \ get_report_contact_email(db, db_contact_email.id, report.id) if db_report_contact_email is None: db_report_contact_email = ReportContactEmail() db_report_contact_email.contact_email = db_contact_email db_report_contact_email.report = report db.session.add(db_report_contact_email) try: db.session.flush() except IntegrityError: raise FafError("Email address already assigned to the report") elif atype == "url": url = attachment["data"] # 0ne URL can be attached to many Reports, but every reports must # have unique url's db_url = (db.session.query(ReportURL) .filter(ReportURL.url == url) .filter(ReportURL.report_id == report.id) .first()) if db_url: log.debug("Skipping existing URL") return db_url = ReportURL() db_url.report = report db_url.url = url db_url.saved = datetime.datetime.utcnow() try: db.session.flush() except IntegrityError: raise FafError("Unable to save URL") else: log.warning("Unknown attachment type")
def _save_bug(self, db, bug): """ Save bug represented by `bug_dict` to the database. If bug is marked as duplicate, the duplicate bug is downloaded as well. """ bug_dict = self.preprocess_bug(bug) if not bug_dict: self.log_error("Bug pre-processing failed") raise FafError("Bug pre-processing failed") self.log_debug("Saving bug #{0}: {1}".format(bug_dict["bug_id"], bug_dict["summary"])) bug_id = bug_dict["bug_id"] # check if we already have this bug up-to-date old_bug = ( db.session.query(BzBug) .filter(BzBug.id == bug_id) .filter(BzBug.last_change_time == bug_dict["last_change_time"]) .first()) if old_bug: self.log_info("Bug already up-to-date") return old_bug tracker = queries.get_bugtracker_by_name(db, self.name) if not tracker: self.log_error("Tracker with name '{0}' is not installed" .format(self.name)) raise FafError("Tracker with name '{0}' is not installed" .format(self.name)) opsysrelease = queries.get_osrelease(db, bug_dict["product"], bug_dict["version"]) if not opsysrelease: self.log_error("Unable to save this bug due to unknown " "release '{0} {1}'".format(bug_dict["product"], bug_dict["version"])) raise FafError("Unable to save this bug due to unknown " "release '{0} {1}'".format(bug_dict["product"], bug_dict["version"])) relcomponent = queries.get_component_by_name_release( db, opsysrelease, bug_dict["component"]) if not relcomponent: self.log_error("Unable to save this bug due to unknown " "component '{0}'".format(bug_dict["component"])) raise FafError("Unable to save this bug due to unknown " "component '{0}'".format(bug_dict["component"])) component = relcomponent.component reporter = queries.get_bz_user(db, bug_dict["reporter"]) if not reporter: self.log_debug("Creator {0} not found".format( bug_dict["reporter"])) downloaded = self._download_user(bug_dict["reporter"]) if not downloaded: self.log_error("Unable to download user, skipping.") raise FafError("Unable to download user, skipping.") reporter = self._save_user(db, downloaded) new_bug = BzBug() new_bug.id = bug_dict["bug_id"] new_bug.summary = bug_dict["summary"] new_bug.status = bug_dict["status"] new_bug.creation_time = bug_dict["creation_time"] new_bug.last_change_time = bug_dict["last_change_time"] new_bug.private = bool(bug_dict["groups"]) if bug_dict["status"] == "CLOSED": new_bug.resolution = bug_dict["resolution"] if bug_dict["resolution"] == "DUPLICATE": if not queries.get_bz_bug(db, bug_dict["dupe_id"]): self.log_debug("Duplicate #{0} not found".format( bug_dict["dupe_id"])) dup = self.download_bug_to_storage(db, bug_dict["dupe_id"]) if dup: new_bug.duplicate = dup.id new_bug.tracker_id = tracker.id new_bug.component_id = component.id new_bug.opsysrelease_id = opsysrelease.id new_bug.creator_id = reporter.id new_bug.whiteboard = bug_dict["status_whiteboard"] # the bug itself might be downloaded during duplicate processing # exit in this case - it would cause duplicate database entry if queries.get_bz_bug(db, bug_dict["bug_id"]): self.log_debug("Bug #{0} already exists in storage," " updating".format(bug_dict["bug_id"])) bugdict = {} for col in new_bug.__table__._columns: #pylint: disable=protected-access bugdict[col.name] = getattr(new_bug, col.name) (db.session.query(BzBug) .filter(BzBug.id == bug_id).update(bugdict)) new_bug = queries.get_bz_bug(db, bug_dict["bug_id"]) else: db.session.add(new_bug) db.session.flush() self._save_ccs(db, bug_dict["cc"], new_bug.id) self._save_history(db, bug_dict["history"], new_bug.id) if self.save_attachments: self._save_attachments(db, bug_dict["attachments"], new_bug.id) if self.save_comments: self._save_comments(db, bug_dict["comments"], new_bug.id) return new_bug
def associate_bug(report_id) -> Union[WzResponse, str]: result = (db.session.query(Report, OpSysComponent).join(OpSysComponent).filter( Report.id == report_id).first()) if result is None: abort(404) report, component = result is_maintainer = is_component_maintainer(db, g.user, component) if not is_maintainer: flash("You are not the maintainer of this component.", "danger") return redirect(url_for("reports.item", report_id=report_id)) form = AssociateBzForm(request.form) if request.method == "POST" and form.validate(): bug_id = form.bug_id.data tracker = bugtrackers[form.bugtracker.data] db_report = inspect(Report).relationships[tracker.report_backref_name] db_report_class = inspect(db_report.entity).class_ reportbug = get_bugtracker_report(db, bug_id, report.id, db_report_class) if reportbug: flash("Bug already associated.", "danger") else: bug = get_bz_bug(db, bug_id) if not bug: tracker = bugtrackers[form.bugtracker.data] try: bug = tracker.download_bug_to_storage(db, bug_id) except Exception as e: #pylint: disable=broad-except flash("Failed to fetch bug. {0}".format(str(e)), "danger") return redirect( url_for("reports.associate_bug", report_id=report_id)) if bug: new_report = db_report_class() new_report.report = report new_report.bug = bug db.session.add(new_report) db.session.flush() db.session.commit() flash("Bug successfully associated.", "success") return redirect(url_for("reports.item", report_id=report_id)) bthash_url = url_for("reports.bthash_forward", bthash=report.hashes[0].hash, _external=True) new_bug_params = { "component": component.name, "short_desc": "[abrt] [faf] {0}: {1}(): {2} killed by {3}".format( component.name, report.crash_function, ",".join(exe.path for exe in report.executables), report.errname), "comment": "This bug has been created based on an anonymous crash " "report requested by the package maintainer.\n\n" "Report URL: {0}".format(bthash_url), "bug_file_loc": bthash_url } new_bug_urls = [] for rosr in report.opsysreleases: osr = rosr.opsysrelease for bugtracker in bugtrackers: try: params = new_bug_params.copy() if osr.opsys.name.startswith("Red Hat"): params.update(product="{0} {1}".format( osr.opsys.name, osr.version[0]), version=osr.version) else: params.update(product=osr.opsys.name, version=osr.version) new_bug_urls.append( ("{0} in {1}".format(str(osr), bugtracker), "{0}?{1}".format(bugtrackers[bugtracker].new_bug_url, urllib.parse.urlencode(params)))) except: # pylint: disable=bare-except pass return render_template("reports/associate_bug.html", form=form, report=report, new_bug_urls=new_bug_urls)
def associate_bug(report_id): result = (db.session.query(Report, OpSysComponent) .join(OpSysComponent) .filter(Report.id == report_id) .first()) if result is None: abort(404) report, component = result is_maintainer = is_component_maintainer(db, g.user, component) if not is_maintainer: flash("You are not the maintainer of this component.", "danger") return redirect(url_for("reports.item", report_id=report_id)) form = AssociateBzForm(request.form) if request.method == "POST" and form.validate(): bug_id = form.bug_id.data reportbug = (db.session.query(ReportBz) .filter( (ReportBz.report_id == report.id) & (ReportBz.bzbug_id == bug_id)) .first()) if reportbug: flash("Bug already associated.", "danger") else: bug = get_bz_bug(db, bug_id) if not bug: tracker = bugtrackers[form.bugtracker.data] try: bug = tracker.download_bug_to_storage_no_retry(db, bug_id) except Exception as e: #pylint: disable=broad-except flash("Failed to fetch bug. {0}".format(str(e)), "danger") return redirect(url_for("reports.associate_bug", report_id=report_id)) if bug: newReportBz = ReportBz() newReportBz.report = report newReportBz.bzbug = bug db.session.add(newReportBz) db.session.flush() db.session.commit() flash("Bug successfully associated.", "success") return redirect(url_for("reports.item", report_id=report_id)) bthash_url = url_for("reports.bthash_forward", bthash=report.hashes[0].hash, _external=True) new_bug_params = { "component": component.name, "short_desc": "[abrt] [faf] {0}: {1}(): {2} killed by {3}" .format(component.name, report.crash_function, ",".join(exe.path for exe in report.executables), report.errname ), "comment": "This bug has been created based on an anonymous crash " "report requested by the package maintainer.\n\n" "Report URL: {0}" .format(bthash_url), "bug_file_loc": bthash_url } new_bug_urls = [] for rosr in report.opsysreleases: osr = rosr.opsysrelease for bugtracker in bugtrackers: try: params = new_bug_params.copy() if osr.opsys.name.startswith("Red Hat"): params.update(product="{0} {1}".format(osr.opsys.name, osr.version[0]), version=osr.version) else: params.update(product=osr.opsys.name, version=osr.version) new_bug_urls.append( ("{0} {1} in {2}".format(osr.opsys.name, osr.version, bugtracker), "{0}?{1}".format( bugtrackers[bugtracker].new_bug_url, urllib.parse.urlencode(params)) ) ) except: # pylint: disable=bare-except pass return render_template("reports/associate_bug.html", form=form, report=report, new_bug_urls=new_bug_urls)