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