Merge branch 'org.openembedded.dev' of git://git.openembedded.net/openembedded into...
[vuplus_openembedded] / classes / oestats-client.bbclass
1 # Integration with the oestats build statistics server, see:
2 #
3 # http://opensource.bolloretelecom.eu/projects/oestats
4 #
5 # To make use of this class, add to your local.conf:
6 #
7 # INHERIT += "oestats-client"
8 # OESTATS_SERVER = "some.server.org"
9 # OESTATS_BUILDER = "some_nickname"
10
11 def oestats_setid(d, val):
12         import bb
13         f = file(bb.data.getVar('TMPDIR', d, True) + '/oestats.id', 'w')
14         f.write(val)
15
16 def oestats_getid(d):
17         import bb
18         f = file(bb.data.getVar('TMPDIR', d, True) + '/oestats.id', 'r')
19         return f.read()
20         
21 def oestats_send(d, server, action, vars = {}, files = {}):
22         import httplib
23         import bb
24
25         # build body
26         output = []
27         bound = '----------ThIs_Is_tHe_bouNdaRY_$'
28         for key in vars:
29                 assert vars[key]
30                 output.append('--' + bound)
31                 output.append('Content-Disposition: form-data; name="%s"' % key)
32                 output.append('')
33                 output.append(vars[key])
34         for key in files:
35                 assert files[key]
36                 output.append('--' + bound)
37                 output.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, files[key]['filename']))
38                 output.append('Content-Type: %s' % files[key]['content-type'])
39                 
40                 output.append('')
41                 output.append(files[key]['content'])
42         output.append('--' + bound + '--')
43         output.append('')
44         body = "\r\n".join(output)
45
46         # build headers
47         headers = {
48                 "User-agent": "oestats-client/0.5",
49                 "Content-type": "multipart/form-data; boundary=%s" % bound,
50                 "Content-length": str(len(body))}
51
52         # send request
53         proxy = bb.data.getVar('HTTP_PROXY', d, True )
54         if (proxy):
55                 if (proxy.endswith('/')):
56                         proxy = proxy[:-1]
57                 if (proxy.startswith('http://')):
58                         proxy = proxy[7:]
59                 conn = httplib.HTTPConnection(proxy)
60                 action = "http://%s%s" %(server, action)
61         else:
62                 conn = httplib.HTTPConnection(server)
63         conn.request("POST", action, body, headers)
64         response = conn.getresponse()
65         data = response.read()
66         conn.close()
67         return data
68
69 def oestats_start(server, builder, d):
70         import bb
71         import os.path
72         import re
73
74         # send report
75         id = ""
76         try:
77                 data = oestats_send(d, server, "/builds/", {
78                         'builder': builder,
79                         'build_arch': bb.data.getVar('BUILD_ARCH', d, True),
80                         'metadata_branch': bb.data.getVar('METADATA_BRANCH', d, True),
81                         'metadata_revision': bb.data.getVar('METADATA_REVISION', d, True),
82                         'machine': bb.data.getVar('MACHINE', d, True),
83                         'distro': bb.data.getVar('DISTRO', d, True),
84                 })
85                 if re.match("^\d+$", data): id=data
86         except:
87                 pass
88
89         # save the build id
90         if id:
91                 bb.note("oestats: build %s" % id)
92         else:
93                 bb.note("oestats: error starting build, disabling stats")
94         oestats_setid(d, id)
95
96 def oestats_stop(server, d, failures):
97         import bb
98
99         # retrieve build id
100         id = oestats_getid(d)
101         if not id: return
102
103         # send report
104         if failures > 0:
105                 status = "Failed"
106         else:
107                 status = "Succeeded"                  
108
109         try:
110                 response = oestats_send(d, server, "/builds/%s/" % id, {
111                         'status': status,
112                 })
113                 if status == 'Failed':
114                         bb.note("oestats: build failed, see http://%s%s" % (server,response))
115         except:
116                 bb.note("oestats: error stopping build")
117
118 def oestats_task(server, d, task, status):
119         import bb
120         import glob
121         import os.path
122         import time
123
124         # retrieve build id
125         id = oestats_getid(d)
126         if not id: return
127
128         # calculate build time
129         try:
130                 elapsed = time.time() - float(bb.data.getVar('OESTATS_STAMP', d, True))
131         except:
132                 elapsed = 0
133         
134         # prepare files
135         files = {}
136         if status == 'Failed':
137                 logs = glob.glob("%s/log.%s.*" % (bb.data.getVar('T', d, True), task))
138                 if len(logs) > 0:
139                         log = logs[0]
140                         files['log'] = {
141                                 'filename': 'log.txt',
142                                 'content': file(log).read(),
143                                 'content-type': 'text/plain'}
144         if task == 'do_package':
145                 qalog = "%s/log.qa_package" % bb.data.getVar('T', d, True)
146                 if os.path.exists(qalog):
147                         files['qalog'] = {
148                                 'filename': 'qalog.txt',
149                                 'content': file(qalog).read(),
150                                 'content-type': 'text/plain'}
151         
152         # prepare report
153         vars = {
154                 'build': id,
155                 'package': bb.data.getVar('PN', d, True),
156                 'version': bb.data.getVar('PV', d, True),
157                 'revision': bb.data.getVar('PR', d, True),
158                 'depends': bb.data.getVar('DEPENDS', d, True),
159                 'task': task,
160                 'status': status,
161                 'time': str(elapsed)}
162         bug_number = bb.data.getVar('OESTATS_BUG_NUMBER', d, True)
163         bug_tracker = bb.data.getVar('OESTATS_BUG_TRACKER', d, True)
164         if bug_number and bug_tracker:
165                 vars['bug_number'] = bug_number
166                 vars['bug_tracker'] = bug_tracker
167
168         # send report
169         try:
170                 response = oestats_send(d, server, "/tasks/", vars, files)
171                 if status == 'Failed':
172                         bb.note("oestats: task failed, see http://%s%s" % (server, response))
173         except:
174                 bb.note("oestats: error sending task, disabling stats")
175                 oestats_setid(d, "")
176
177 addhandler oestats_eventhandler
178 python oestats_eventhandler () {
179         from bb.event import getName
180         import bb
181         import time
182
183         if e.data is None or getName(e) == "MsgNote":
184                 return NotHandled
185
186         server = bb.data.getVar('OESTATS_SERVER', e.data, True)
187         builder = bb.data.getVar('OESTATS_BUILDER', e.data, True)
188         if not server or not builder:
189                 return NotHandled
190
191         if getName(e) == 'BuildStarted':
192                 oestats_start(server, builder, e.data)
193         elif getName(e) == 'BuildCompleted':
194                 oestats_stop(server, e.data, e.getFailures())
195         elif getName(e) == 'TaskStarted':
196                 bb.data.setVar('OESTATS_STAMP', repr(time.time()), e.data)
197         elif getName(e) == 'TaskSucceeded':
198                 oestats_task(server, e.data, e.task, 'Succeeded')
199         elif getName(e) == 'TaskFailed':
200                 oestats_task(server, e.data, e.task, 'Failed')
201
202         return NotHandled
203 }