explicit_merge of '601faaded8a6427e29dc8dc43433fe9be662c96c'
[vuplus_openembedded] / classes / tinderclient.bbclass
1 def tinder_form_data(bound, dict, log):
2     """
3     Create the boundary for the HTTP Post
4     """
5     output = []
6
7     # for each key in the dictionary
8     for name in dict:
9         output.append( "--" + bound )
10         output.append( 'Content-Disposition: form-data; name="%s"' % name )
11         output.append( "" )
12         output.append( dict[name] )
13     if log:
14         output.append( "--" + bound )
15         output.append( 'Content-Disposition: form-data; name="log"; filename="log.txt"' )
16         output.append( '' )
17         output.append( log )
18     output.append( '--' + bound + '--' )
19     output.append( '' )
20
21     return "\r\n".join(output)
22
23 def tinder_time_string():
24     """
25     Return the time as GMT
26     """
27     return ""
28
29 def tinder_format_http_post(d,status,log):
30     """
31     Format the Tinderbox HTTP post with the data needed
32     for the tinderbox to be happy.
33     """
34
35     from bb import data
36     import os,random
37
38     # the variables we will need to send on this form post
39     variables =  {
40         "tree"         : data.getVar('TINDER_TREE',    d, True),
41         "machine_name" : data.getVar('TINDER_MACHINE', d, True),
42         "os"           : os.uname()[0],
43         "os_version"   : os.uname()[2],
44         "compiler"     : "gcc",
45         "clobber"      : data.getVar('TINDER_CLOBBER', d, True)
46     }
47
48     # optionally add the status
49     if status:
50         variables["status"] = str(status)
51
52     # try to load the machine id
53     # we only need on build_status.pl but sending it
54     # always does not hurt
55     try:
56         f = file(data.getVar('TMPDIR',d,True)+'/tinder-machine.id', 'r')
57         id = f.read()
58         variables['machine_id'] = id
59     except:
60         pass
61
62     # the boundary we will need
63     boundary = "----------------------------------%d" % int(random.random()*1000000000000)
64
65     # now format the body
66     body = tinder_form_data( boundary, variables, log )
67
68     return ("multipart/form-data; boundary=%s" % boundary),body
69
70
71 def tinder_build_start(d):
72     """
73     Inform the tinderbox that a build is starting. We do this
74     by posting our name and tree to the build_start.pl script
75     on the server.
76     """
77     from bb import data
78     import httplib
79
80     # get the body and type
81     content_type, body = tinder_format_http_post(d,None,None)
82     server = data.getVar('TINDER_HOST', d, True )
83     url    = data.getVar('TINDER_URL',  d, True )
84
85     selector = url + "/xml/build_start.pl"
86
87     #print "selector %s and url %s" % (selector, url)
88
89     # now post it
90     h = httplib.HTTP(server)
91     h.putrequest('POST', selector)
92     h.putheader('content-type', content_type)
93     h.putheader('content-length', str(len(body)))
94     h.endheaders()
95     h.send(body)
96     errcode, errmsg, headers = h.getreply()
97     #print errcode, errmsg, headers
98     report = h.file.read()
99
100     # now let us find the machine id that was assigned to us
101     search = "<machine id='"
102     report = report[report.find(search)+len(search):]
103     report = report[0:report.find("'")]
104
105     import bb
106     bb.note("Machine ID assigned by tinderbox: %s" % report )
107
108     # now we will need to save the machine number
109     # we will override any previous numbers
110     f = file(data.getVar('TMPDIR', d, True)+"/tinder-machine.id", 'w')
111     f.write(report)
112
113
114 def tinder_send_http(d, status, log):
115     """
116     Send this log as build status
117     """
118     from bb import data
119     import httplib
120
121
122     # get the body and type
123     content_type, body = tinder_format_http_post(d,status,log)
124     server = data.getVar('TINDER_HOST', d, True )
125     url    = data.getVar('TINDER_URL',  d, True )
126
127     selector = url + "/xml/build_status.pl"
128
129     # now post it
130     h = httplib.HTTP(server)
131     h.putrequest('POST', selector)
132     h.putheader('content-type', content_type)
133     h.putheader('content-length', str(len(body)))
134     h.endheaders()
135     h.send(body)
136     errcode, errmsg, headers = h.getreply()
137     #print errcode, errmsg, headers
138     #print h.file.read()
139
140
141 def tinder_print_info(d):
142     """
143     Print the TinderBox Info
144         Including informations of the BaseSystem and the Tree
145         we use.
146     """
147
148     from   bb import data
149     import os
150     # get the local vars
151
152     time    = tinder_time_string()
153     ops     = os.uname()[0]
154     version = os.uname()[2]
155     url     = data.getVar( 'TINDER_URL' , d, True )
156     tree    = data.getVar( 'TINDER_TREE', d, True )
157     branch  = data.getVar( 'TINDER_BRANCH', d, True )
158     srcdate = data.getVar( 'SRCDATE', d, True )
159     machine = data.getVar( 'MACHINE', d, True )
160     distro  = data.getVar( 'DISTRO',  d, True )
161     bbfiles = data.getVar( 'BBFILES', d, True )
162     tarch   = data.getVar( 'TARGET_ARCH', d, True )
163     fpu     = data.getVar( 'TARGET_FPU', d, True )
164     oerev   = data.getVar( 'OE_REVISION', d, True ) or "unknown"
165
166     # there is a bug with tipple quoted strings
167     # i will work around but will fix the original
168     # bug as well
169     output = []
170     output.append("== Tinderbox Info" )
171     output.append("Time: %(time)s" )
172     output.append("OS: %(ops)s" )
173     output.append("%(version)s" )
174     output.append("Compiler: gcc" )
175     output.append("Tinderbox Client: 0.1" )
176     output.append("Tinderbox Client Last Modified: yesterday" )
177     output.append("Tinderbox Protocol: 0.1" )
178     output.append("URL: %(url)s" )
179     output.append("Tree: %(tree)s" )
180     output.append("Config:" )
181     output.append("branch = '%(branch)s'" )
182     output.append("TARGET_ARCH = '%(tarch)s'" )
183     output.append("TARGET_FPU = '%(fpu)s'" )
184     output.append("SRCDATE = '%(srcdate)s'" )
185     output.append("MACHINE = '%(machine)s'" )
186     output.append("DISTRO = '%(distro)s'" )
187     output.append("BBFILES = '%(bbfiles)s'" )
188     output.append("OEREV = '%(oerev)s'" )
189     output.append("== End Tinderbox Client Info" )
190
191     # now create the real output
192     return "\n".join(output) % vars()
193
194
195 def tinder_print_env():
196     """
197     Print the environment variables of this build
198     """
199     from bb import data
200     import os
201
202     time_start = tinder_time_string()
203     time_end   = tinder_time_string()
204
205     # build the environment
206     env = ""
207     for var in os.environ:
208         env += "%s=%s\n" % (var, os.environ[var])
209
210     output = []
211     output.append( "---> TINDERBOX RUNNING env %(time_start)s" )
212     output.append( env )
213     output.append( "<--- TINDERBOX FINISHED (SUCCESS) %(time_end)s" )
214
215     return "\n".join(output) % vars()
216
217 def tinder_tinder_start(d):
218     """
219     PRINT the configuration of this build
220     """
221
222     time_start = tinder_time_string()
223     config = tinder_print_info(d)
224     #env    = tinder_print_env()
225     time_end   = tinder_time_string()
226
227     output = []
228     output.append( "---> TINDERBOX PRINTING CONFIGURATION %(time_start)s" )
229     output.append( config )
230     #output.append( env    )
231     output.append( "<--- TINDERBOX FINISHED PRINTING CONFIGURATION %(time_end)s" )
232     output.append( "" )
233     return "\n".join(output) % vars()
234
235 def tinder_do_tinder_report(event):
236     """
237     Report to the tinderbox:
238         On the BuildStart we will inform the box directly
239         On the other events we will write to the TINDER_LOG and
240         when the Task is finished we will send the report.
241
242     The above is not yet fully implemented. Currently we send
243     information immediately. The caching/queuing needs to be
244     implemented. Also sending more or less information is not
245     implemented yet.
246     """
247     from bb.event import getName
248     from bb import data, mkdirhier
249     import os, glob
250
251     # variables
252     name = getName(event)
253     log  = ""
254     status = 1
255
256     # Check what we need to do Build* shows we start or are done
257     if name == "BuildStarted":
258         tinder_build_start(event.data)
259         log = tinder_tinder_start(event.data)
260
261         try:
262             # truncate the tinder log file
263             f = file(data.getVar('TINDER_LOG', event.data, True), 'rw+')
264             f.truncate(0)
265             f.close()
266         except IOError:
267             pass
268
269     # Append the Task-Log (compile,configure...) to the log file
270     # we will send to the server
271     if name == "TaskSucceeded" or name == "TaskFailed":
272         log_file = glob.glob("%s/log.%s.*" % (data.getVar('T', event.data, True), event.task))
273
274         if len(log_file) != 0:
275             to_file  = data.getVar('TINDER_LOG', event.data, True)
276             log     += "".join(open(log_file[0], 'r').readlines())
277
278     # set the right 'HEADER'/Summary for the TinderBox
279     if name == "TaskStarted":
280         log += "---> TINDERBOX Task %s started\n" % event.task
281     elif name == "TaskSucceeded":
282         log += "<--- TINDERBOX Task %s done (SUCCESS)\n" % event.task
283     elif name == "TaskFailed":
284         log += "<--- TINDERBOX Task %s failed (FAILURE)\n" % event.task
285     elif name == "PkgStarted":
286         log += "---> TINDERBOX Package %s started\n" % data.getVar('P', event.data, True)
287     elif name == "PkgSucceeded":
288         log += "<--- TINDERBOX Package %s done (SUCCESS)\n" % data.getVar('P', event.data, True)
289     elif name == "PkgFailed":
290         log += "<--- TINDERBOX Package %s failed (FAILURE)\n" % data.getVar('P', event.data, True)
291         status = 200
292     elif name == "BuildCompleted":
293         log += "Build Completed\n"
294         status = 100
295
296     # now post the log
297     if len(log) == 0:
298         return
299
300     # for now we will use the http post method as it is the only one
301     log_post_method = tinder_send_http
302     log_post_method(event.data, status, log)
303
304
305 # we want to be an event handler
306 addhandler tinderclient_eventhandler
307 python tinderclient_eventhandler() {
308     from bb import note, error, data
309     from bb.event import NotHandled
310
311     do_tinder_report = data.getVar('TINDER_REPORT', e.data, True)
312     if do_tinder_report and do_tinder_report == "1":
313         tinder_do_tinder_report(e)
314
315     return NotHandled
316 }