tinderclient.bbclass 10 KB

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