~fgiff/linaro-android-bot-review/878894

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import xmlrpclib
import urllib2
import json
import datetime
import re
import logging


xmlrpc_log = logging.getLogger("xmlrpclib")

class LoggingTransport(xmlrpclib.Transport):
    def send_request(self, connection, handler, request_body):
        xmlrpc_log.debug("%s", (connection, handler, request_body))
        return xmlrpclib.Transport.send_request(self, connection, handler, request_body)


class LavaConnection:
    def __init__(self, lava_server, lava_stream):
        """LAVA server e.g. http://validation.linaro.org/lava-server."""
        self.lava_server = lava_server
        """LAVA stream to query e.g. /anonymous/android-daily/."""
        self.lava_stream = lava_stream
        "Cached results"
        self.lava_results = None
        self.log = logging.getLogger(self.__class__.__name__)


    def get_server(self):
        if not hasattr(self, "server"):
            self.server = xmlrpclib.ServerProxy("%s/RPC2/" % (self.lava_server), transport=LoggingTransport())
        return self.server

    def request(self, url, data=None):
        if "://" not in url:
            url = self.lava_server + "/" + url
        self.log.debug("LAVA request: %s", url)
        req = urllib2.Request(url, data)
        resp = urllib2.urlopen(req)
        return resp.read()

    def json_request(self, url, data=None):
        res = self.request(url, data)
        return json.loads(res)

    def get_job_status(self, job):
        url = "scheduler/job/%s/json" % job
        return self.json_request(url)

    def get_job_url(self, job):
        url = "%s/scheduler/job/%s" % (self.lava_server, job)
        return url

    def get_bundle(self, bundle_id):
        url = "dashboard/permalink/bundle/%s/json" % bundle_id
        return self.json_request(url)

    def parse_bundle_url(self, bundle_url):
        # http://validation.linaro.org/lava-server/dashboard/permalink/bundle/f19c4669fc37b6907901e067f5e910cd4655e76a/
        m = re.search(r"bundle/([0-9A-Fa-f]+)", bundle_url)
        if not m:
            return None
        return m.group(1)


    def get_lava_results(self):
        """ Get lava results from all tests run in the last 2 days."""
        self.get_server()
        bundles = []
        try:
            bundles = self.server.dashboard.bundles("%s" % (self.lava_stream))
        except xmlrpclib.Fault:
            # Problem with LAVA xmlrpc call.
            self.log.error("Error: Couldn't get test results from LAVA.")
        except xmlrpclib.ProtocolError:
            # Problem connecting to LAVA.
            self.log.error("Error: Couldn't connect to LAVA.")
        lava_results = []
        # Since we're operating on fresh builds, we know the bundle will 
        # have been uploaded in the last 48 hrs, so prune out older ones.
        for bundle in bundles:
            if (datetime.datetime.strptime("%s" % (bundle["uploaded_on"]),
                                          "%Y%m%dT%H:%M:%S") >
                (datetime.datetime.now() - datetime.timedelta(2))):

                try:
                    s = json.loads(
                        self.server.dashboard.get(bundle["content_sha1"])["content"])

                    if (s.has_key("test_runs") and
                        s["test_runs"][0].has_key("attributes")):

                        lava_results.append([s["test_runs"][0]["attributes"],
                                            s["test_runs"][0]["test_results"],
                                            bundle["content_sha1"]])
                except xmlrpclib.Fault:
                    # Not a user-friendly identifier, but we'd need to download
                    # the bundle to work out which build it corresponds to
                    # and this error occurs when we can't do that.
                    self.log.error("Error: Couldn't fetch test results for %s" % (
                        bundle["content_sha1"]))
                    continue
                except xmlrpclib.ProtocolError:
                    # Problem connecting to LAVA.
                    self.log.error("Error: Couldn't connect to LAVA.")
                    continue
        return lava_results


    def find_lava_result(self, build_url):
        """ Check for LAVA result. """
        if self.lava_results is None:
            self.lava_results = self.get_lava_results()
        overall_result = "not tested"
        result_hash = ""
        for lava_result in self.lava_results:
            if lava_result[0]["android.url"] == build_url:
                result_hash = lava_result[2]
                overall_result = "pass"
                for result in lava_result[1]:
                    if result["result"] != "pass":
                        overall_result = result["result"]
                break

        return overall_result, result_hash