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