merge of 79fa588c44f87f6ad9821f7fb8136225ef69860e
[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
165     # there is a bug with tipple quoted strings
166     # i will work around but will fix the original
167     # bug as well
168     output = []
169     output.append("== Tinderbox Info" )
170     output.append("Time: %(time)s" )
171     output.append("OS: %(ops)s" )
172     output.append("%(version)s" )
173     output.append("Compiler: gcc" )
174     output.append("Tinderbox Client: 0.1" )
175     output.append("Tinderbox Client Last Modified: yesterday" )
176     output.append("Tinderbox Protocol: 0.1" )
177     output.append("URL: %(url)s" )
178     output.append("Tree: %(tree)s" )
179     output.append("Config:" )
180     output.append("branch = '%(branch)s'" )
181     output.append("TARGET_ARCH = '%(tarch)s'" )
182     output.append("TARGET_FPU = '%(fpu)s'" )
183     output.append("SRCDATE = '%(srcdate)s'" )
184     output.append("MACHINE = '%(machine)s'" )
185     output.append("DISTRO = '%(distro)s'" )
186     output.append("BBFILES = '%(bbfiles)s'" )
187     output.append("== End Tinderbox Client Info" )
188
189     # now create the real output
190     return "\n".join(output) % vars()
191
192
193 def tinder_print_env():
194     """
195     Print the environment variables of this build
196     """
197     from bb import data
198     import os
199
200     time_start = tinder_time_string()
201     time_end   = tinder_time_string()
202
203     # build the environment
204     env = ""
205     for var in os.environ:
206         env += "%s=%s\n" % (var, os.environ[var])
207
208     output = []
209     output.append( "---> TINDERBOX RUNNING env %(time_start)s" )
210     output.append( env )
211     output.append( "<--- TINDERBOX FINISHED (SUCCESS) %(time_end)s" )
212
213     return "\n".join(output) % vars()
214
215 def tinder_tinder_start(d):
216     """
217     PRINT the configuration of this build
218     """
219
220     time_start = tinder_time_string()
221     config = tinder_print_info(d)
222     env    = tinder_print_env()
223     time_end   = tinder_time_string()
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     return "\n".join(output) % vars()
231
232 def tinder_do_tinder_report(event):
233     """
234     Report to the tinderbox:
235         On the BuildStart we will inform the box directly
236         On the other events we will write to the TINDER_LOG and
237         when the Task is finished we will send the report.
238
239     The above is not yet fully implemented. Currently we send
240     information immediately. The caching/queuing needs to be
241     implemented. Also sending more or less information is not
242     implemented yet.
243     """
244     from bb.event import getName
245     from bb import data, mkdirhier
246     import os, glob
247
248     # variables
249     name = getName(event)
250     log  = ""
251     status = 1
252
253     # Check what we need to do Build* shows we start or are done
254     if name == "BuildStarted":
255         tinder_build_start(event.data)
256         log = tinder_tinder_start(event.data)
257
258         try:
259             # truncate the tinder log file
260             f = file(data.getVar('TINDER_LOG', event.data, True), 'rw+')
261             f.truncate(0)
262             f.close()
263         except IOError:
264             pass
265
266     # Append the Task-Log (compile,configure...) to the log file
267     # we will send to the server
268     if name == "TaskSucceeded" or name == "TaskFailed":
269         log_file = glob.glob("%s/log.%s.*" % (data.getVar('T', event.data, True), event.task))
270
271         if len(log_file) != 0:
272             to_file  = data.getVar('TINDER_LOG', event.data, True)
273             log      = open(log_file[0], 'r').readlines()
274
275     # set the right 'HEADER'/Summary for the TinderBox
276     if name == "TaskStarted":
277         log += "--> TINDERBOX Task %s started" % event.task
278     elif name == "TaskSucceeded":
279         log += "<-- TINDERBOX Task %s done (SUCCESS)" % event.task
280     elif name == "TaskFailed":
281         log += "<-- TINDERBOX Task %s failed (FAILURE)" % event.task
282     elif name == "PkgStarted":
283         log += "--> TINDERBOX Package %s started" % data.getVar('P', event.data, True)
284     elif name == "PkgSucceeded":
285         log += "<-- TINDERBOX Package %s done (SUCCESS)" % data.getVar('P', event.data, True)
286     elif name == "PkgFailed":
287         log += "<-- TINDERBOX Package %s failed (FAILURE)" % data.getVar('P', event.data, True)
288         status = 200
289     elif name == "BuildCompleted":
290         status = 100
291
292     # now post the log
293     if len(log) == 0:
294         return
295
296     # for now we will use the http post method as it is the only one
297     log_post_method = tinder_send_http
298     log_post_method(event.data, status, log)
299
300
301 # we want to be an event handler
302 addhandler tinderclient_eventhandler
303 python tinderclient_eventhandler() {
304     from bb import note, error, data
305     from bb.event import NotHandled
306
307     do_tinder_report = data.getVar('TINDER_REPORT', e.data, True)
308     if do_tinder_report and do_tinder_report == "1":
309         tinder_do_tinder_report(e)
310
311     return NotHandled
312 }