summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/bldcontrol/localhostbecontroller.py')
-rw-r--r--bitbake/lib/toaster/bldcontrol/localhostbecontroller.py172
1 files changed, 139 insertions, 33 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
index 16c7c80441..6bdd743b8b 100644
--- a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
+++ b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
@@ -27,8 +27,9 @@ import shutil
27import time 27import time
28from django.db import transaction 28from django.db import transaction
29from django.db.models import Q 29from django.db.models import Q
30from bldcontrol.models import BuildEnvironment, BRLayer, BRVariable, BRTarget, BRBitbake 30from bldcontrol.models import BuildEnvironment, BuildRequest, BRLayer, BRVariable, BRTarget, BRBitbake, Build
31from orm.models import CustomImageRecipe, Layer, Layer_Version, ProjectLayer, ToasterSetting 31from orm.models import CustomImageRecipe, Layer, Layer_Version, Project, ProjectLayer, ToasterSetting
32from orm.models import signal_runbuilds
32import subprocess 33import subprocess
33 34
34from toastermain import settings 35from toastermain import settings
@@ -38,6 +39,8 @@ from bldcontrol.bbcontroller import BuildEnvironmentController, ShellCmdExceptio
38import logging 39import logging
39logger = logging.getLogger("toaster") 40logger = logging.getLogger("toaster")
40 41
42install_dir = os.environ.get('TOASTER_DIR')
43
41from pprint import pprint, pformat 44from pprint import pprint, pformat
42 45
43class LocalhostBEController(BuildEnvironmentController): 46class LocalhostBEController(BuildEnvironmentController):
@@ -87,10 +90,10 @@ class LocalhostBEController(BuildEnvironmentController):
87 #logger.debug("localhostbecontroller: using HEAD checkout in %s" % local_checkout_path) 90 #logger.debug("localhostbecontroller: using HEAD checkout in %s" % local_checkout_path)
88 return local_checkout_path 91 return local_checkout_path
89 92
90 93 def setCloneStatus(self,bitbake,status,total,current,repo_name):
91 def setCloneStatus(self,bitbake,status,total,current):
92 bitbake.req.build.repos_cloned=current 94 bitbake.req.build.repos_cloned=current
93 bitbake.req.build.repos_to_clone=total 95 bitbake.req.build.repos_to_clone=total
96 bitbake.req.build.progress_item=repo_name
94 bitbake.req.build.save() 97 bitbake.req.build.save()
95 98
96 def setLayers(self, bitbake, layers, targets): 99 def setLayers(self, bitbake, layers, targets):
@@ -100,6 +103,7 @@ class LocalhostBEController(BuildEnvironmentController):
100 103
101 layerlist = [] 104 layerlist = []
102 nongitlayerlist = [] 105 nongitlayerlist = []
106 layer_index = 0
103 git_env = os.environ.copy() 107 git_env = os.environ.copy()
104 # (note: add custom environment settings here) 108 # (note: add custom environment settings here)
105 109
@@ -113,7 +117,7 @@ class LocalhostBEController(BuildEnvironmentController):
113 if bitbake.giturl and bitbake.commit: 117 if bitbake.giturl and bitbake.commit:
114 gitrepos[(bitbake.giturl, bitbake.commit)] = [] 118 gitrepos[(bitbake.giturl, bitbake.commit)] = []
115 gitrepos[(bitbake.giturl, bitbake.commit)].append( 119 gitrepos[(bitbake.giturl, bitbake.commit)].append(
116 ("bitbake", bitbake.dirpath)) 120 ("bitbake", bitbake.dirpath, 0))
117 121
118 for layer in layers: 122 for layer in layers:
119 # We don't need to git clone the layer for the CustomImageRecipe 123 # We don't need to git clone the layer for the CustomImageRecipe
@@ -124,12 +128,13 @@ class LocalhostBEController(BuildEnvironmentController):
124 # If we have local layers then we don't need clone them 128 # If we have local layers then we don't need clone them
125 # For local layers giturl will be empty 129 # For local layers giturl will be empty
126 if not layer.giturl: 130 if not layer.giturl:
127 nongitlayerlist.append(layer.layer_version.layer.local_source_dir) 131 nongitlayerlist.append( "%03d:%s" % (layer_index,layer.local_source_dir) )
128 continue 132 continue
129 133
130 if not (layer.giturl, layer.commit) in gitrepos: 134 if not (layer.giturl, layer.commit) in gitrepos:
131 gitrepos[(layer.giturl, layer.commit)] = [] 135 gitrepos[(layer.giturl, layer.commit)] = []
132 gitrepos[(layer.giturl, layer.commit)].append( (layer.name, layer.dirpath) ) 136 gitrepos[(layer.giturl, layer.commit)].append( (layer.name,layer.dirpath,layer_index) )
137 layer_index += 1
133 138
134 139
135 logger.debug("localhostbecontroller, our git repos are %s" % pformat(gitrepos)) 140 logger.debug("localhostbecontroller, our git repos are %s" % pformat(gitrepos))
@@ -159,9 +164,9 @@ class LocalhostBEController(BuildEnvironmentController):
159 # 3. checkout the repositories 164 # 3. checkout the repositories
160 clone_count=0 165 clone_count=0
161 clone_total=len(gitrepos.keys()) 166 clone_total=len(gitrepos.keys())
162 self.setCloneStatus(bitbake,'Started',clone_total,clone_count) 167 self.setCloneStatus(bitbake,'Started',clone_total,clone_count,'')
163 for giturl, commit in gitrepos.keys(): 168 for giturl, commit in gitrepos.keys():
164 self.setCloneStatus(bitbake,'progress',clone_total,clone_count) 169 self.setCloneStatus(bitbake,'progress',clone_total,clone_count,gitrepos[(giturl, commit)][0][0])
165 clone_count += 1 170 clone_count += 1
166 171
167 localdirname = os.path.join(self.be.sourcedir, self.getGitCloneDirectory(giturl, commit)) 172 localdirname = os.path.join(self.be.sourcedir, self.getGitCloneDirectory(giturl, commit))
@@ -205,16 +210,16 @@ class LocalhostBEController(BuildEnvironmentController):
205 self._shellcmd("git clone -b \"%s\" \"%s\" \"%s\" " % (bitbake.commit, bitbake.giturl, os.path.join(self.pokydirname, 'bitbake')),env=git_env) 210 self._shellcmd("git clone -b \"%s\" \"%s\" \"%s\" " % (bitbake.commit, bitbake.giturl, os.path.join(self.pokydirname, 'bitbake')),env=git_env)
206 211
207 # verify our repositories 212 # verify our repositories
208 for name, dirpath in gitrepos[(giturl, commit)]: 213 for name, dirpath, index in gitrepos[(giturl, commit)]:
209 localdirpath = os.path.join(localdirname, dirpath) 214 localdirpath = os.path.join(localdirname, dirpath)
210 logger.debug("localhostbecontroller: localdirpath expected '%s'" % localdirpath) 215 logger.debug("localhostbecontroller: localdirpath expects '%s'" % localdirpath)
211 if not os.path.exists(localdirpath): 216 if not os.path.exists(localdirpath):
212 raise BuildSetupException("Cannot find layer git path '%s' in checked out repository '%s:%s'. Aborting." % (localdirpath, giturl, commit)) 217 raise BuildSetupException("Cannot find layer git path '%s' in checked out repository '%s:%s'. Aborting." % (localdirpath, giturl, commit))
213 218
214 if name != "bitbake": 219 if name != "bitbake":
215 layerlist.append(localdirpath.rstrip("/")) 220 layerlist.append("%03d:%s" % (index,localdirpath.rstrip("/")))
216 221
217 self.setCloneStatus(bitbake,'complete',clone_total,clone_count) 222 self.setCloneStatus(bitbake,'complete',clone_total,clone_count,'')
218 logger.debug("localhostbecontroller: current layer list %s " % pformat(layerlist)) 223 logger.debug("localhostbecontroller: current layer list %s " % pformat(layerlist))
219 224
220 if self.pokydirname is None and os.path.exists(os.path.join(self.be.sourcedir, "oe-init-build-env")): 225 if self.pokydirname is None and os.path.exists(os.path.join(self.be.sourcedir, "oe-init-build-env")):
@@ -232,7 +237,7 @@ class LocalhostBEController(BuildEnvironmentController):
232 customrecipe, layers) 237 customrecipe, layers)
233 238
234 if os.path.isdir(custom_layer_path): 239 if os.path.isdir(custom_layer_path):
235 layerlist.append(custom_layer_path) 240 layerlist.append("%03d:%s" % (layer_index,custom_layer_path))
236 241
237 except CustomImageRecipe.DoesNotExist: 242 except CustomImageRecipe.DoesNotExist:
238 continue # not a custom recipe, skip 243 continue # not a custom recipe, skip
@@ -240,7 +245,11 @@ class LocalhostBEController(BuildEnvironmentController):
240 layerlist.extend(nongitlayerlist) 245 layerlist.extend(nongitlayerlist)
241 logger.debug("\n\nset layers gives this list %s" % pformat(layerlist)) 246 logger.debug("\n\nset layers gives this list %s" % pformat(layerlist))
242 self.islayerset = True 247 self.islayerset = True
243 return layerlist 248
249 # restore the order of layer list for bblayers.conf
250 layerlist.sort()
251 sorted_layerlist = [l[4:] for l in layerlist]
252 return sorted_layerlist
244 253
245 def setup_custom_image_recipe(self, customrecipe, layers): 254 def setup_custom_image_recipe(self, customrecipe, layers):
246 """ Set up toaster-custom-images layer and recipe files """ 255 """ Set up toaster-custom-images layer and recipe files """
@@ -310,31 +319,115 @@ class LocalhostBEController(BuildEnvironmentController):
310 319
311 def triggerBuild(self, bitbake, layers, variables, targets, brbe): 320 def triggerBuild(self, bitbake, layers, variables, targets, brbe):
312 layers = self.setLayers(bitbake, layers, targets) 321 layers = self.setLayers(bitbake, layers, targets)
322 is_merged_attr = bitbake.req.project.merged_attr
323
324 git_env = os.environ.copy()
325 # (note: add custom environment settings here)
326 try:
327 # insure that the project init/build uses the selected bitbake, and not Toaster's
328 del git_env['TEMPLATECONF']
329 del git_env['BBBASEDIR']
330 del git_env['BUILDDIR']
331 except KeyError:
332 pass
313 333
314 # init build environment from the clone 334 # init build environment from the clone
315 builddir = '%s-toaster-%d' % (self.be.builddir, bitbake.req.project.id) 335 if bitbake.req.project.builddir:
336 builddir = bitbake.req.project.builddir
337 else:
338 builddir = '%s-toaster-%d' % (self.be.builddir, bitbake.req.project.id)
316 oe_init = os.path.join(self.pokydirname, 'oe-init-build-env') 339 oe_init = os.path.join(self.pokydirname, 'oe-init-build-env')
317 # init build environment 340 # init build environment
318 try: 341 try:
319 custom_script = ToasterSetting.objects.get(name="CUSTOM_BUILD_INIT_SCRIPT").value 342 custom_script = ToasterSetting.objects.get(name="CUSTOM_BUILD_INIT_SCRIPT").value
320 custom_script = custom_script.replace("%BUILDDIR%" ,builddir) 343 custom_script = custom_script.replace("%BUILDDIR%" ,builddir)
321 self._shellcmd("bash -c 'source %s'" % (custom_script)) 344 self._shellcmd("bash -c 'source %s'" % (custom_script),env=git_env)
322 except ToasterSetting.DoesNotExist: 345 except ToasterSetting.DoesNotExist:
323 self._shellcmd("bash -c 'source %s %s'" % (oe_init, builddir), 346 self._shellcmd("bash -c 'source %s %s'" % (oe_init, builddir),
324 self.be.sourcedir) 347 self.be.sourcedir,env=git_env)
325 348
326 # update bblayers.conf 349 # update bblayers.conf
327 bblconfpath = os.path.join(builddir, "conf/toaster-bblayers.conf") 350 if not is_merged_attr:
328 with open(bblconfpath, 'w') as bblayers: 351 bblconfpath = os.path.join(builddir, "conf/toaster-bblayers.conf")
329 bblayers.write('# line added by toaster build control\n' 352 with open(bblconfpath, 'w') as bblayers:
330 'BBLAYERS = "%s"' % ' '.join(layers)) 353 bblayers.write('# line added by toaster build control\n'
331 354 'BBLAYERS = "%s"' % ' '.join(layers))
332 # write configuration file 355
333 confpath = os.path.join(builddir, 'conf/toaster.conf') 356 # write configuration file
334 with open(confpath, 'w') as conf: 357 confpath = os.path.join(builddir, 'conf/toaster.conf')
335 for var in variables: 358 with open(confpath, 'w') as conf:
336 conf.write('%s="%s"\n' % (var.name, var.value)) 359 for var in variables:
337 conf.write('INHERIT+="toaster buildhistory"') 360 conf.write('%s="%s"\n' % (var.name, var.value))
361 conf.write('INHERIT+="toaster buildhistory"')
362 else:
363 # Append the Toaster-specific values directly to the bblayers.conf
364 bblconfpath = os.path.join(bitbake.req.project.builddir, "conf/bblayers.conf")
365 bblconfpath_save = os.path.join(bitbake.req.project.builddir, "conf/bblayers.conf.save")
366 shutil.copyfile(bblconfpath, bblconfpath_save)
367 with open(bblconfpath) as bblayers:
368 content = bblayers.readlines()
369 do_write = True
370 was_toaster = False
371 with open(bblconfpath,'w') as bblayers:
372 for line in content:
373 #line = line.strip('\n')
374 if 'TOASTER_CONFIG_PROLOG' in line:
375 do_write = False
376 was_toaster = True
377 elif 'TOASTER_CONFIG_EPILOG' in line:
378 do_write = True
379 elif do_write:
380 bblayers.write(line)
381 if not was_toaster:
382 bblayers.write('\n')
383 bblayers.write('#=== TOASTER_CONFIG_PROLOG ===\n')
384 bblayers.write('BBLAYERS = "\\\n')
385 for layer in layers:
386 bblayers.write(' %s \\\n' % layer)
387 bblayers.write(' "\n')
388 bblayers.write('#=== TOASTER_CONFIG_EPILOG ===\n')
389 # Append the Toaster-specific values directly to the local.conf
390 bbconfpath = os.path.join(bitbake.req.project.builddir, "conf/local.conf")
391 bbconfpath_save = os.path.join(bitbake.req.project.builddir, "conf/local.conf.save")
392 shutil.copyfile(bbconfpath, bbconfpath_save)
393 with open(bbconfpath) as f:
394 content = f.readlines()
395 do_write = True
396 was_toaster = False
397 with open(bbconfpath,'w') as conf:
398 for line in content:
399 #line = line.strip('\n')
400 if 'TOASTER_CONFIG_PROLOG' in line:
401 do_write = False
402 was_toaster = True
403 elif 'TOASTER_CONFIG_EPILOG' in line:
404 do_write = True
405 elif do_write:
406 conf.write(line)
407 if not was_toaster:
408 conf.write('\n')
409 conf.write('#=== TOASTER_CONFIG_PROLOG ===\n')
410 for var in variables:
411 if (not var.name.startswith("INTERNAL_")) and (not var.name == "BBLAYERS"):
412 conf.write('%s="%s"\n' % (var.name, var.value))
413 conf.write('#=== TOASTER_CONFIG_EPILOG ===\n')
414
415 # If 'target' is just the project preparation target, then we are done
416 for target in targets:
417 if "_PROJECT_PREPARE_" == target.target:
418 logger.debug('localhostbecontroller: Project has been prepared. Done.')
419 # Update the Build Request and release the build environment
420 bitbake.req.state = BuildRequest.REQ_COMPLETED
421 bitbake.req.save()
422 self.be.lock = BuildEnvironment.LOCK_FREE
423 self.be.save()
424 # Close the project build and progress bar
425 bitbake.req.build.outcome = Build.SUCCEEDED
426 bitbake.req.build.save()
427 # Update the project status
428 bitbake.req.project.set_variable(Project.PROJECT_SPECIFIC_STATUS,Project.PROJECT_SPECIFIC_CLONING_SUCCESS)
429 signal_runbuilds()
430 return
338 431
339 # clean the Toaster to build environment 432 # clean the Toaster to build environment
340 env_clean = 'unset BBPATH;' # clean BBPATH for <= YP-2.4.0 433 env_clean = 'unset BBPATH;' # clean BBPATH for <= YP-2.4.0
@@ -342,9 +435,14 @@ class LocalhostBEController(BuildEnvironmentController):
342 # run bitbake server from the clone 435 # run bitbake server from the clone
343 bitbake = os.path.join(self.pokydirname, 'bitbake', 'bin', 'bitbake') 436 bitbake = os.path.join(self.pokydirname, 'bitbake', 'bin', 'bitbake')
344 toasterlayers = os.path.join(builddir,"conf/toaster-bblayers.conf") 437 toasterlayers = os.path.join(builddir,"conf/toaster-bblayers.conf")
345 self._shellcmd('%s bash -c \"source %s %s; BITBAKE_UI="knotty" %s --read %s --read %s ' 438 if not is_merged_attr:
346 '--server-only -B 0.0.0.0:0\"' % (env_clean, oe_init, 439 self._shellcmd('%s bash -c \"source %s %s; BITBAKE_UI="knotty" %s --read %s --read %s '
347 builddir, bitbake, confpath, toasterlayers), self.be.sourcedir) 440 '--server-only -B 0.0.0.0:0\"' % (env_clean, oe_init,
441 builddir, bitbake, confpath, toasterlayers), self.be.sourcedir)
442 else:
443 self._shellcmd('%s bash -c \"source %s %s; BITBAKE_UI="knotty" %s '
444 '--server-only -B 0.0.0.0:0\"' % (env_clean, oe_init,
445 builddir, bitbake), self.be.sourcedir)
348 446
349 # read port number from bitbake.lock 447 # read port number from bitbake.lock
350 self.be.bbport = -1 448 self.be.bbport = -1
@@ -390,12 +488,20 @@ class LocalhostBEController(BuildEnvironmentController):
390 log = os.path.join(builddir, 'toaster_ui.log') 488 log = os.path.join(builddir, 'toaster_ui.log')
391 local_bitbake = os.path.join(os.path.dirname(os.getenv('BBBASEDIR')), 489 local_bitbake = os.path.join(os.path.dirname(os.getenv('BBBASEDIR')),
392 'bitbake') 490 'bitbake')
393 self._shellcmd(['%s bash -c \"(TOASTER_BRBE="%s" BBSERVER="0.0.0.0:%s" ' 491 if not is_merged_attr:
492 self._shellcmd(['%s bash -c \"(TOASTER_BRBE="%s" BBSERVER="0.0.0.0:%s" '
394 '%s %s -u toasterui --read %s --read %s --token="" >>%s 2>&1;' 493 '%s %s -u toasterui --read %s --read %s --token="" >>%s 2>&1;'
395 'BITBAKE_UI="knotty" BBSERVER=0.0.0.0:%s %s -m)&\"' \ 494 'BITBAKE_UI="knotty" BBSERVER=0.0.0.0:%s %s -m)&\"' \
396 % (env_clean, brbe, self.be.bbport, local_bitbake, bbtargets, confpath, toasterlayers, log, 495 % (env_clean, brbe, self.be.bbport, local_bitbake, bbtargets, confpath, toasterlayers, log,
397 self.be.bbport, bitbake,)], 496 self.be.bbport, bitbake,)],
398 builddir, nowait=True) 497 builddir, nowait=True)
498 else:
499 self._shellcmd(['%s bash -c \"(TOASTER_BRBE="%s" BBSERVER="0.0.0.0:%s" '
500 '%s %s -u toasterui --token="" >>%s 2>&1;'
501 'BITBAKE_UI="knotty" BBSERVER=0.0.0.0:%s %s -m)&\"' \
502 % (env_clean, brbe, self.be.bbport, local_bitbake, bbtargets, log,
503 self.be.bbport, bitbake,)],
504 builddir, nowait=True)
399 505
400 logger.debug('localhostbecontroller: Build launched, exiting. ' 506 logger.debug('localhostbecontroller: Build launched, exiting. '
401 'Follow build logs at %s' % log) 507 'Follow build logs at %s' % log)