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