#
# 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)
}

