bitbake: toaster: fill in build data from buildrequest

This patch adds logic to complete changing the interface
from showing BuildRequests to showing Build data.

The BuildRequest data is now transformed in Build data with
proper Toaster exceptions being recorded instead of listing
problems during startup as build errors.

(Bitbake rev: 51a41172d0b390370f9a38696b1ac65666ada4d2)

Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Alexandru DAMIAN 2015-06-11 18:27:53 +01:00 committed by Richard Purdie
parent 160563532f
commit d7c8d9558c
5 changed files with 84 additions and 11 deletions

View File

@ -133,7 +133,21 @@ class ORMWrapper(object):
logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj)
build = Build.objects.create(
if buildrequest is not None:
build = buildrequest.build
build.machine=build_info['machine'],
build.distro=build_info['distro'],
build.distro_version=build_info['distro_version'],
build.completed_on=build_info['started_on'],
build.cooker_log_path=build_info['cooker_log_path'],
build.build_name=build_info['build_name'],
build.bitbake_version=build_info['bitbake_version']
build.save()
build.target_set.delete()
else:
build = Build.objects.create(
project = prj,
machine=build_info['machine'],
distro=build_info['distro'],

View File

@ -1,6 +1,6 @@
from django.core.management.base import NoArgsCommand, CommandError
from django.db import transaction
from orm.models import Build, ToasterSetting
from orm.models import Build, ToasterSetting, LogMessage, Target
from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException
from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable
import os
@ -109,6 +109,36 @@ class Command(NoArgsCommand):
from datetime import timedelta
# DISABLED environments locked for more than 30 seconds - they should be unlocked
#BuildEnvironment.objects.filter(lock=BuildEnvironment.LOCK_LOCK).filter(updated__lt = timezone.now() - timedelta(seconds = 30)).update(lock = BuildEnvironment.LOCK_FREE)
# update all Builds that failed to start
for br in BuildRequest.objects.filter(state = BuildRequest.REQ_FAILED):
br.build.outcome = Build.FAILED
# transpose the launch errors in ToasterExceptions
for brerror in br.brerror_set.all():
LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
br.build.save()
# update all BuildRequests without a build created
for br in BuildRequest.objects.filter(build = None):
br.build = Build.objects.create(project = br.project, completed_on = br.updated, started_on = br.created)
br.build.outcome = Build.REQ_FAILED
try:
br.build.machine = br.brvariable_set.get(name='MACHINE').value
except BRVariable.DoesNotExist:
pass
br.save()
# transpose target information
for brtarget in br.brtarget_set.all():
Target.objects.create(build = br.build, target= brtarget.target)
# transpose the launch errors in ToasterExceptions
for brerror in br.brerror_set.all():
LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
br.build.save()
pass

View File

@ -201,16 +201,32 @@ class Project(models.Model):
commit = l.layercommit.get_vcs_reference()
print("ii Building layer ", l.layercommit.layer.name, " at vcs point ", commit)
BRLayer.objects.create(req = br, name = l.layercommit.layer.name, giturl = l.layercommit.layer.vcs_url, commit = commit, dirpath = l.layercommit.dirpath)
br.state = BuildRequest.REQ_QUEUED
now = timezone.now()
br.build = Build.objects.create(project = self,
completed_on=now,
started_on=now,
)
for t in self.projecttarget_set.all():
BRTarget.objects.create(req = br, target = t.target, task = t.task)
Target.objects.create(build = br.build, target = t.target)
for v in self.projectvariable_set.all():
BRVariable.objects.create(req = br, name = v.name, value = v.value)
br.state = BuildRequest.REQ_QUEUED
try:
br.build.machine = self.projectvariable_set.get(name = 'MACHINE').value
br.build.save()
except ProjectVariable.DoesNotExist:
pass
br.save()
except Exception as e:
br.delete()
raise e
import sys
et, ei, tb = sys.exc_info()
raise type(e), e, tb
return br
class Build(models.Model):
@ -250,7 +266,6 @@ class Build(models.Model):
return completeper
def eta(self):
from django.utils import timezone
eta = timezone.now()
completeper = self.completeper()
if self.completeper() > 0:
@ -266,6 +281,12 @@ class Build(models.Model):
def toaster_exceptions(self):
return self.logmessage_set.filter(level=LogMessage.EXCEPTION)
def get_current_status(self):
if self.outcome == Build.IN_PROGRESS and self.build_name == "":
return "Queued"
return self.get_outcome_display()
def __str__(self):
return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()]))
@ -299,6 +320,7 @@ class Target(models.Model):
search_allowed_fields = ['target', 'file_name']
build = models.ForeignKey(Build)
target = models.CharField(max_length=100)
task = models.CharField(max_length=100, null=True)
is_image = models.BooleanField(default = False)
image_size = models.IntegerField(default=0)
license_manifest_path = models.CharField(max_length=500, null=True)

View File

@ -114,7 +114,7 @@ vim: expandtab tabstop=2
<script type="text/ng-template" id="target_display">
<div data-ng-switch on="t.task.length">
<div data-ng-switch-when="0">{[t.target]}</div>
<div data-ng-switch-when="undefined">{[t.target]}</div>
<div data-ng-switch-default>{[t.target]}:{[t.task]}</div>
</div>
</script>
@ -145,13 +145,13 @@ vim: expandtab tabstop=2
<a id="buildslist"></a>
<h2 class="air" data-ng-if="builds.length">Latest builds</h2>
<div class="animate-repeat alert" data-ng-repeat="b in builds track by b.id" data-ng-class="{'In Progress':'alert-info', 'Succeeded':'alert-success', 'Failed':'alert-error'}[b.status]">
<div class="animate-repeat alert" data-ng-repeat="b in builds track by b.id" data-ng-class="{'Queued':'alert-info', 'In Progress':'alert-info', 'Succeeded':'alert-success', 'Failed':'alert-error'}[b.status]">
<div class="row-fluid">
<switch data-ng-switch="b.status">
<case data-ng-switch-when="Failed">
<div class="lead span3">
<a data-ng-class="{'succeeded': 'success', 'failed': 'error'}[b.status]" href="{[b.br_page_url]}">
<a data-ng-class="{'Succeeded': 'success', 'Failed': 'error'}[b.status]" href="{[b.br_page_url]}">
<span data-ng-repeat="t in b.targets" data-ng-include src="'target_display'"></span>
</a>
</div>
@ -176,12 +176,19 @@ vim: expandtab tabstop=2
<!-- we don't have warnings in this case -->
</div>
<div> <span class="lead">Build time: {[b.command_time|timediff]}</span>
<button class="btn pull-right" data-ng-class="{'succeeded': 'btn-success', 'failed': 'btn-danger'}[b.status]"
<button class="btn pull-right" data-ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.status]"
data-ng-click="buildExistingTarget(b.targets)">Run again</button>
</div>
</case>
<case data-ng-switch-when="Queued">
<div class="lead span5"> <span data-ng-repeat="t in b.targets" data-ng-include src="'target_display'"></span> </div>
<div class="span4 lead" >Build queued
<i title="This build will start as soon as a build server is available" class="icon-question-sign get-help get-help-blue heading-help" data-toggle="tooltip"></i>
</div>
<button class="btn pull-right btn-info" data-ng-click="buildCancel(b)">Cancel</button>
</case>
<case data-ng-switch-when="In Progress">
<switch data-ng-switch="b.build.length">

View File

@ -74,8 +74,8 @@ def _project_recent_build_list(prj):
for x in _get_latest_builds(prj):
d = {
"id": x.pk,
"targets" : map(lambda y: {"target": y.target, "task": None }, x.target_set.all()), # TODO: create the task entry in the Target table
"status": x.get_outcome_display(),
"targets" : map(lambda y: {"target": y.target, "task": y.task }, x.target_set.all()), # TODO: create the task entry in the Target table
"status": x.get_current_status(),
"errors": map(lambda y: {"type": y.lineno, "msg": y.message, "tb": y.pathname}, x.logmessage_set.filter(level__gte=LogMessage.WARNING)),
"updated": x.completed_on.strftime('%s')+"000",
"command_time": (x.completed_on - x.started_on).total_seconds(),