|  | # | 
|  | # Small event handler to automatically open URLs and file | 
|  | # bug reports at a bugzilla of your choiche | 
|  | # it uses XML-RPC interface, so you must have it enabled | 
|  | # | 
|  | # Before using you must define BUGZILLA_USER, BUGZILLA_PASS credentials, | 
|  | # BUGZILLA_XMLRPC - uri of xmlrpc.cgi, | 
|  | # BUGZILLA_PRODUCT, BUGZILLA_COMPONENT - a place in BTS for build bugs | 
|  | # BUGZILLA_VERSION - version against which to report new bugs | 
|  | # | 
|  |  | 
|  | def bugzilla_find_bug_report(debug_file, server, args, bugname): | 
|  | args['summary'] = bugname | 
|  | bugs = server.Bug.search(args) | 
|  | if len(bugs['bugs']) == 0: | 
|  | print >> debug_file, "Bugs not found" | 
|  | return (False,None) | 
|  | else: # silently pick the first result | 
|  | print >> debug_file, "Result of bug search is " | 
|  | print >> debug_file, bugs | 
|  | status = bugs['bugs'][0]['status'] | 
|  | id = bugs['bugs'][0]['id'] | 
|  | return (not status in ["CLOSED", "RESOLVED", "VERIFIED"],id) | 
|  |  | 
|  | def bugzilla_file_bug(debug_file, server, args, name, text, version): | 
|  | args['summary'] = name | 
|  | args['comment'] = text | 
|  | args['version'] = version | 
|  | args['op_sys'] = 'Linux' | 
|  | args['platform'] = 'Other' | 
|  | args['severity'] = 'normal' | 
|  | args['priority'] = 'Normal' | 
|  | try: | 
|  | return server.Bug.create(args)['id'] | 
|  | except Exception, e: | 
|  | print >> debug_file, repr(e) | 
|  | return None | 
|  |  | 
|  | def bugzilla_reopen_bug(debug_file, server, args, bug_number): | 
|  | args['ids'] = [bug_number] | 
|  | args['status'] = "CONFIRMED" | 
|  | try: | 
|  | server.Bug.update(args) | 
|  | return True | 
|  | except Exception, e: | 
|  | print >> debug_file, repr(e) | 
|  | return False | 
|  |  | 
|  | def bugzilla_create_attachment(debug_file, server, args, bug_number, text, file_name, log, logdescription): | 
|  | args['ids'] = [bug_number] | 
|  | args['file_name'] = file_name | 
|  | args['summary'] = logdescription | 
|  | args['content_type'] = "text/plain" | 
|  | args['data'] = log | 
|  | args['comment'] = text | 
|  | try: | 
|  | server.Bug.add_attachment(args) | 
|  | return True | 
|  | except Exception, e: | 
|  | print >> debug_file, repr(e) | 
|  | return False | 
|  |  | 
|  | def bugzilla_add_comment(debug_file, server, args, bug_number, text): | 
|  | args['id'] = bug_number | 
|  | args['comment'] = text | 
|  | try: | 
|  | server.Bug.add_comment(args) | 
|  | return True | 
|  | except Exception, e: | 
|  | print >> debug_file, repr(e) | 
|  | return False | 
|  |  | 
|  | addhandler bugzilla_eventhandler | 
|  | bugzilla_eventhandler[eventmask] = "bb.event.MsgNote bb.build.TaskFailed" | 
|  | python bugzilla_eventhandler() { | 
|  | import glob | 
|  | import xmlrpclib, httplib | 
|  |  | 
|  | class ProxiedTransport(xmlrpclib.Transport): | 
|  | def __init__(self, proxy, use_datetime = 0): | 
|  | xmlrpclib.Transport.__init__(self, use_datetime) | 
|  | self.proxy = proxy | 
|  | self.user = None | 
|  | self.password = None | 
|  |  | 
|  | def set_user(self, user): | 
|  | self.user = user | 
|  |  | 
|  | def set_password(self, password): | 
|  | self.password = password | 
|  |  | 
|  | def make_connection(self, host): | 
|  | self.realhost = host | 
|  | return httplib.HTTP(self.proxy) | 
|  |  | 
|  | def send_request(self, connection, handler, request_body): | 
|  | connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler)) | 
|  | if self.user != None: | 
|  | if self.password != None: | 
|  | auth = "%s:%s" % (self.user, self.password) | 
|  | else: | 
|  | auth = self.user | 
|  | connection.putheader("Proxy-authorization", "Basic " + base64.encodestring(auth)) | 
|  |  | 
|  | event = e | 
|  | data = e.data | 
|  | name = bb.event.getName(event) | 
|  | if name == "MsgNote": | 
|  | # avoid recursion | 
|  | return | 
|  |  | 
|  | if name == "TaskFailed": | 
|  | xmlrpc  = data.getVar("BUGZILLA_XMLRPC", True) | 
|  | user    = data.getVar("BUGZILLA_USER", True) | 
|  | passw   = data.getVar("BUGZILLA_PASS", True) | 
|  | product = data.getVar("BUGZILLA_PRODUCT", True) | 
|  | compon  = data.getVar("BUGZILLA_COMPONENT", True) | 
|  | version = data.getVar("BUGZILLA_VERSION", True) | 
|  |  | 
|  | proxy   = data.getVar('http_proxy', True ) | 
|  | if (proxy): | 
|  | import urllib2 | 
|  | s, u, p, hostport = urllib2._parse_proxy(proxy) | 
|  | transport = ProxiedTransport(hostport) | 
|  | else: | 
|  | transport = None | 
|  |  | 
|  | server = xmlrpclib.ServerProxy(xmlrpc, transport=transport, verbose=0) | 
|  | args = { | 
|  | 'Bugzilla_login': user, | 
|  | 'Bugzilla_password': passw, | 
|  | 'product': product, | 
|  | 'component': compon} | 
|  |  | 
|  | # evil hack to figure out what is going on | 
|  | debug_file = open(os.path.join(data.getVar("TMPDIR", True),"..","bugzilla-log"),"a") | 
|  |  | 
|  | file = None | 
|  | bugname = "%(package)s-%(pv)s-autobuild" % { "package" : data.getVar("PN", True), | 
|  | "pv"      : data.getVar("PV", True), | 
|  | } | 
|  | log_file = glob.glob("%s/log.%s.*" % (event.data.getVar('T', True), event.task)) | 
|  | text     = "The %s step in %s failed at %s for machine %s" % (e.task, data.getVar("PN", True), data.getVar('DATETIME', True), data.getVar( 'MACHINE', True ) ) | 
|  | if len(log_file) != 0: | 
|  | print >> debug_file, "Adding log file %s" % log_file[0] | 
|  | file = open(log_file[0], 'r') | 
|  | log = file.read() | 
|  | file.close(); | 
|  | else: | 
|  | print >> debug_file, "No log file found for the glob" | 
|  | log = None | 
|  |  | 
|  | (bug_open, bug_number) = bugzilla_find_bug_report(debug_file, server, args.copy(), bugname) | 
|  | print >> debug_file, "Bug is open: %s and bug number: %s" % (bug_open, bug_number) | 
|  |  | 
|  | # The bug is present and still open, attach an error log | 
|  | if not bug_number: | 
|  | bug_number = bugzilla_file_bug(debug_file, server, args.copy(), bugname, text, version) | 
|  | if not bug_number: | 
|  | print >> debug_file, "Couldn't acquire a new bug_numer, filing a bugreport failed" | 
|  | else: | 
|  | print >> debug_file, "The new bug_number: '%s'" % bug_number | 
|  | elif not bug_open: | 
|  | if not bugzilla_reopen_bug(debug_file, server, args.copy(), bug_number): | 
|  | print >> debug_file, "Failed to reopen the bug #%s" % bug_number | 
|  | else: | 
|  | print >> debug_file, "Reopened the bug #%s" % bug_number | 
|  |  | 
|  | if bug_number and log: | 
|  | print >> debug_file, "The bug is known as '%s'" % bug_number | 
|  | desc = "Build log for machine %s" % (data.getVar('MACHINE', True)) | 
|  | if not bugzilla_create_attachment(debug_file, server, args.copy(), bug_number, text, log_file[0], log, desc): | 
|  | print >> debug_file, "Failed to attach the build log for bug #%s" % bug_number | 
|  | else: | 
|  | print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number) | 
|  | else: | 
|  | print >> debug_file, "Not trying to create an attachment for bug #%s" % bug_number | 
|  | if not bugzilla_add_comment(debug_file, server, args.copy(), bug_number, text, ): | 
|  | print >> debug_file, "Failed to create a comment the build log for bug #%s" % bug_number | 
|  | else: | 
|  | print >> debug_file, "Created an attachment for '%s' '%s' '%s'" % (product, compon, bug_number) | 
|  |  | 
|  | # store bug number for oestats-client | 
|  | if bug_number: | 
|  | data.setVar('OESTATS_BUG_NUMBER', bug_number) | 
|  | } | 
|  |  |