diff options
author | Alexandru DAMIAN <alexandru.damian@intel.com> | 2015-06-11 18:27:53 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-06-26 09:27:32 +0100 |
commit | d7c8d9558c8b600be1507212c78dde833b2bb57e (patch) | |
tree | 941c11d7e4aeca7f0c1106a39d1b8006264fbd16 | |
parent | 160563532f87bd901e1cc6972fe238be87a8b63c (diff) | |
download | poky-d7c8d9558c8b600be1507212c78dde833b2bb57e.tar.gz |
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>
-rw-r--r-- | bitbake/lib/bb/ui/buildinfohelper.py | 16 | ||||
-rw-r--r-- | bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py | 32 | ||||
-rw-r--r-- | bitbake/lib/toaster/orm/models.py | 28 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/project.html | 15 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 4 |
5 files changed, 84 insertions, 11 deletions
diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py index 3ea842cd4b..8b63f70a07 100644 --- a/bitbake/lib/bb/ui/buildinfohelper.py +++ b/bitbake/lib/bb/ui/buildinfohelper.py | |||
@@ -133,7 +133,21 @@ class ORMWrapper(object): | |||
133 | logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj) | 133 | logger.debug(1, "buildinfohelper: project is not specified, defaulting to %s" % prj) |
134 | 134 | ||
135 | 135 | ||
136 | build = Build.objects.create( | 136 | if buildrequest is not None: |
137 | build = buildrequest.build | ||
138 | build.machine=build_info['machine'], | ||
139 | build.distro=build_info['distro'], | ||
140 | build.distro_version=build_info['distro_version'], | ||
141 | build.completed_on=build_info['started_on'], | ||
142 | build.cooker_log_path=build_info['cooker_log_path'], | ||
143 | build.build_name=build_info['build_name'], | ||
144 | build.bitbake_version=build_info['bitbake_version'] | ||
145 | build.save() | ||
146 | |||
147 | build.target_set.delete() | ||
148 | |||
149 | else: | ||
150 | build = Build.objects.create( | ||
137 | project = prj, | 151 | project = prj, |
138 | machine=build_info['machine'], | 152 | machine=build_info['machine'], |
139 | distro=build_info['distro'], | 153 | distro=build_info['distro'], |
diff --git a/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py b/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py index 920d9efcd0..da7d4af07e 100644 --- a/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py +++ b/bitbake/lib/toaster/bldcontrol/management/commands/runbuilds.py | |||
@@ -1,6 +1,6 @@ | |||
1 | from django.core.management.base import NoArgsCommand, CommandError | 1 | from django.core.management.base import NoArgsCommand, CommandError |
2 | from django.db import transaction | 2 | from django.db import transaction |
3 | from orm.models import Build, ToasterSetting | 3 | from orm.models import Build, ToasterSetting, LogMessage, Target |
4 | from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException | 4 | from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException |
5 | from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable | 5 | from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable |
6 | import os | 6 | import os |
@@ -109,6 +109,36 @@ class Command(NoArgsCommand): | |||
109 | from datetime import timedelta | 109 | from datetime import timedelta |
110 | # DISABLED environments locked for more than 30 seconds - they should be unlocked | 110 | # DISABLED environments locked for more than 30 seconds - they should be unlocked |
111 | #BuildEnvironment.objects.filter(lock=BuildEnvironment.LOCK_LOCK).filter(updated__lt = timezone.now() - timedelta(seconds = 30)).update(lock = BuildEnvironment.LOCK_FREE) | 111 | #BuildEnvironment.objects.filter(lock=BuildEnvironment.LOCK_LOCK).filter(updated__lt = timezone.now() - timedelta(seconds = 30)).update(lock = BuildEnvironment.LOCK_FREE) |
112 | |||
113 | |||
114 | # update all Builds that failed to start | ||
115 | |||
116 | for br in BuildRequest.objects.filter(state = BuildRequest.REQ_FAILED): | ||
117 | br.build.outcome = Build.FAILED | ||
118 | # transpose the launch errors in ToasterExceptions | ||
119 | for brerror in br.brerror_set.all(): | ||
120 | LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg) | ||
121 | br.build.save() | ||
122 | |||
123 | |||
124 | |||
125 | # update all BuildRequests without a build created | ||
126 | for br in BuildRequest.objects.filter(build = None): | ||
127 | br.build = Build.objects.create(project = br.project, completed_on = br.updated, started_on = br.created) | ||
128 | br.build.outcome = Build.REQ_FAILED | ||
129 | try: | ||
130 | br.build.machine = br.brvariable_set.get(name='MACHINE').value | ||
131 | except BRVariable.DoesNotExist: | ||
132 | pass | ||
133 | br.save() | ||
134 | # transpose target information | ||
135 | for brtarget in br.brtarget_set.all(): | ||
136 | Target.objects.create(build = br.build, target= brtarget.target) | ||
137 | # transpose the launch errors in ToasterExceptions | ||
138 | for brerror in br.brerror_set.all(): | ||
139 | LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg) | ||
140 | |||
141 | br.build.save() | ||
112 | pass | 142 | pass |
113 | 143 | ||
114 | 144 | ||
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py index 422f2bfd93..d97eadb592 100644 --- a/bitbake/lib/toaster/orm/models.py +++ b/bitbake/lib/toaster/orm/models.py | |||
@@ -201,16 +201,32 @@ class Project(models.Model): | |||
201 | commit = l.layercommit.get_vcs_reference() | 201 | commit = l.layercommit.get_vcs_reference() |
202 | print("ii Building layer ", l.layercommit.layer.name, " at vcs point ", commit) | 202 | print("ii Building layer ", l.layercommit.layer.name, " at vcs point ", commit) |
203 | BRLayer.objects.create(req = br, name = l.layercommit.layer.name, giturl = l.layercommit.layer.vcs_url, commit = commit, dirpath = l.layercommit.dirpath) | 203 | BRLayer.objects.create(req = br, name = l.layercommit.layer.name, giturl = l.layercommit.layer.vcs_url, commit = commit, dirpath = l.layercommit.dirpath) |
204 | |||
205 | br.state = BuildRequest.REQ_QUEUED | ||
206 | now = timezone.now() | ||
207 | br.build = Build.objects.create(project = self, | ||
208 | completed_on=now, | ||
209 | started_on=now, | ||
210 | ) | ||
204 | for t in self.projecttarget_set.all(): | 211 | for t in self.projecttarget_set.all(): |
205 | BRTarget.objects.create(req = br, target = t.target, task = t.task) | 212 | BRTarget.objects.create(req = br, target = t.target, task = t.task) |
213 | Target.objects.create(build = br.build, target = t.target) | ||
214 | |||
206 | for v in self.projectvariable_set.all(): | 215 | for v in self.projectvariable_set.all(): |
207 | BRVariable.objects.create(req = br, name = v.name, value = v.value) | 216 | BRVariable.objects.create(req = br, name = v.name, value = v.value) |
208 | 217 | ||
209 | br.state = BuildRequest.REQ_QUEUED | 218 | |
219 | try: | ||
220 | br.build.machine = self.projectvariable_set.get(name = 'MACHINE').value | ||
221 | br.build.save() | ||
222 | except ProjectVariable.DoesNotExist: | ||
223 | pass | ||
210 | br.save() | 224 | br.save() |
211 | except Exception as e: | 225 | except Exception as e: |
212 | br.delete() | 226 | br.delete() |
213 | raise e | 227 | import sys |
228 | et, ei, tb = sys.exc_info() | ||
229 | raise type(e), e, tb | ||
214 | return br | 230 | return br |
215 | 231 | ||
216 | class Build(models.Model): | 232 | class Build(models.Model): |
@@ -250,7 +266,6 @@ class Build(models.Model): | |||
250 | return completeper | 266 | return completeper |
251 | 267 | ||
252 | def eta(self): | 268 | def eta(self): |
253 | from django.utils import timezone | ||
254 | eta = timezone.now() | 269 | eta = timezone.now() |
255 | completeper = self.completeper() | 270 | completeper = self.completeper() |
256 | if self.completeper() > 0: | 271 | if self.completeper() > 0: |
@@ -266,6 +281,12 @@ class Build(models.Model): | |||
266 | def toaster_exceptions(self): | 281 | def toaster_exceptions(self): |
267 | return self.logmessage_set.filter(level=LogMessage.EXCEPTION) | 282 | return self.logmessage_set.filter(level=LogMessage.EXCEPTION) |
268 | 283 | ||
284 | |||
285 | def get_current_status(self): | ||
286 | if self.outcome == Build.IN_PROGRESS and self.build_name == "": | ||
287 | return "Queued" | ||
288 | return self.get_outcome_display() | ||
289 | |||
269 | def __str__(self): | 290 | def __str__(self): |
270 | return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) | 291 | return "%d %s %s" % (self.id, self.project, ",".join([t.target for t in self.target_set.all()])) |
271 | 292 | ||
@@ -299,6 +320,7 @@ class Target(models.Model): | |||
299 | search_allowed_fields = ['target', 'file_name'] | 320 | search_allowed_fields = ['target', 'file_name'] |
300 | build = models.ForeignKey(Build) | 321 | build = models.ForeignKey(Build) |
301 | target = models.CharField(max_length=100) | 322 | target = models.CharField(max_length=100) |
323 | task = models.CharField(max_length=100, null=True) | ||
302 | is_image = models.BooleanField(default = False) | 324 | is_image = models.BooleanField(default = False) |
303 | image_size = models.IntegerField(default=0) | 325 | image_size = models.IntegerField(default=0) |
304 | license_manifest_path = models.CharField(max_length=500, null=True) | 326 | license_manifest_path = models.CharField(max_length=500, null=True) |
diff --git a/bitbake/lib/toaster/toastergui/templates/project.html b/bitbake/lib/toaster/toastergui/templates/project.html index 0f6a77b63c..1a8991fda4 100644 --- a/bitbake/lib/toaster/toastergui/templates/project.html +++ b/bitbake/lib/toaster/toastergui/templates/project.html | |||
@@ -114,7 +114,7 @@ vim: expandtab tabstop=2 | |||
114 | 114 | ||
115 | <script type="text/ng-template" id="target_display"> | 115 | <script type="text/ng-template" id="target_display"> |
116 | <div data-ng-switch on="t.task.length"> | 116 | <div data-ng-switch on="t.task.length"> |
117 | <div data-ng-switch-when="0">{[t.target]}</div> | 117 | <div data-ng-switch-when="undefined">{[t.target]}</div> |
118 | <div data-ng-switch-default>{[t.target]}:{[t.task]}</div> | 118 | <div data-ng-switch-default>{[t.target]}:{[t.task]}</div> |
119 | </div> | 119 | </div> |
120 | </script> | 120 | </script> |
@@ -145,13 +145,13 @@ vim: expandtab tabstop=2 | |||
145 | 145 | ||
146 | <a id="buildslist"></a> | 146 | <a id="buildslist"></a> |
147 | <h2 class="air" data-ng-if="builds.length">Latest builds</h2> | 147 | <h2 class="air" data-ng-if="builds.length">Latest builds</h2> |
148 | <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]"> | 148 | <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]"> |
149 | <div class="row-fluid"> | 149 | <div class="row-fluid"> |
150 | <switch data-ng-switch="b.status"> | 150 | <switch data-ng-switch="b.status"> |
151 | 151 | ||
152 | <case data-ng-switch-when="Failed"> | 152 | <case data-ng-switch-when="Failed"> |
153 | <div class="lead span3"> | 153 | <div class="lead span3"> |
154 | <a data-ng-class="{'succeeded': 'success', 'failed': 'error'}[b.status]" href="{[b.br_page_url]}"> | 154 | <a data-ng-class="{'Succeeded': 'success', 'Failed': 'error'}[b.status]" href="{[b.br_page_url]}"> |
155 | <span data-ng-repeat="t in b.targets" data-ng-include src="'target_display'"></span> | 155 | <span data-ng-repeat="t in b.targets" data-ng-include src="'target_display'"></span> |
156 | </a> | 156 | </a> |
157 | </div> | 157 | </div> |
@@ -176,12 +176,19 @@ vim: expandtab tabstop=2 | |||
176 | <!-- we don't have warnings in this case --> | 176 | <!-- we don't have warnings in this case --> |
177 | </div> | 177 | </div> |
178 | <div> <span class="lead">Build time: {[b.command_time|timediff]}</span> | 178 | <div> <span class="lead">Build time: {[b.command_time|timediff]}</span> |
179 | <button class="btn pull-right" data-ng-class="{'succeeded': 'btn-success', 'failed': 'btn-danger'}[b.status]" | 179 | <button class="btn pull-right" data-ng-class="{'Succeeded': 'btn-success', 'Failed': 'btn-danger'}[b.status]" |
180 | data-ng-click="buildExistingTarget(b.targets)">Run again</button> | 180 | data-ng-click="buildExistingTarget(b.targets)">Run again</button> |
181 | 181 | ||
182 | </div> | 182 | </div> |
183 | </case> | 183 | </case> |
184 | 184 | ||
185 | <case data-ng-switch-when="Queued"> | ||
186 | <div class="lead span5"> <span data-ng-repeat="t in b.targets" data-ng-include src="'target_display'"></span> </div> | ||
187 | <div class="span4 lead" >Build queued | ||
188 | <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> | ||
189 | </div> | ||
190 | <button class="btn pull-right btn-info" data-ng-click="buildCancel(b)">Cancel</button> | ||
191 | </case> | ||
185 | 192 | ||
186 | <case data-ng-switch-when="In Progress"> | 193 | <case data-ng-switch-when="In Progress"> |
187 | <switch data-ng-switch="b.build.length"> | 194 | <switch data-ng-switch="b.build.length"> |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 0324d17065..2336ae3bec 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -74,8 +74,8 @@ def _project_recent_build_list(prj): | |||
74 | for x in _get_latest_builds(prj): | 74 | for x in _get_latest_builds(prj): |
75 | d = { | 75 | d = { |
76 | "id": x.pk, | 76 | "id": x.pk, |
77 | "targets" : map(lambda y: {"target": y.target, "task": None }, x.target_set.all()), # TODO: create the task entry in the Target table | 77 | "targets" : map(lambda y: {"target": y.target, "task": y.task }, x.target_set.all()), # TODO: create the task entry in the Target table |
78 | "status": x.get_outcome_display(), | 78 | "status": x.get_current_status(), |
79 | "errors": map(lambda y: {"type": y.lineno, "msg": y.message, "tb": y.pathname}, x.logmessage_set.filter(level__gte=LogMessage.WARNING)), | 79 | "errors": map(lambda y: {"type": y.lineno, "msg": y.message, "tb": y.pathname}, x.logmessage_set.filter(level__gte=LogMessage.WARNING)), |
80 | "updated": x.completed_on.strftime('%s')+"000", | 80 | "updated": x.completed_on.strftime('%s')+"000", |
81 | "command_time": (x.completed_on - x.started_on).total_seconds(), | 81 | "command_time": (x.completed_on - x.started_on).total_seconds(), |