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