summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitbake/lib/toaster/orm/models.py5
-rw-r--r--bitbake/lib/toaster/toastergui/templates/basebuildpage.html7
-rw-r--r--bitbake/lib/toaster/toastergui/templates/builddashboard.html87
-rw-r--r--bitbake/lib/toaster/toastergui/views.py49
4 files changed, 122 insertions, 26 deletions
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 30599088e5..4975433acd 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -50,6 +50,11 @@ class Build(models.Model):
50 build_name = models.CharField(max_length=100) 50 build_name = models.CharField(max_length=100)
51 bitbake_version = models.CharField(max_length=50) 51 bitbake_version = models.CharField(max_length=50)
52 52
53 def get_sorted_target_list(self):
54 tgts = Target.objects.filter(build_id = self.id).order_by( 'target' );
55 return( tgts );
56
57
53@python_2_unicode_compatible 58@python_2_unicode_compatible
54class Target(models.Model): 59class Target(models.Model):
55 search_allowed_fields = ['target', 'file_name'] 60 search_allowed_fields = ['target', 'file_name']
diff --git a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
index 636fca28dd..0ce5dbd27f 100644
--- a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
+++ b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
@@ -1,4 +1,5 @@
1{% extends "base.html" %} 1{% extends "base.html" %}
2{% load projecttags %}
2{% load humanize %} 3{% load humanize %}
3{% block pagecontent %} 4{% block pagecontent %}
4 5
@@ -8,7 +9,7 @@
8 <div class="section"> 9 <div class="section">
9 <ul class="breadcrumb" id="breadcrumb"> 10 <ul class="breadcrumb" id="breadcrumb">
10<li><a href="{% url 'all-builds' %}">All builds</a></li> 11<li><a href="{% url 'all-builds' %}">All builds</a></li>
11<li><a href="{%url 'builddashboard' build.pk%}">{{build.target_set.all.0.target}} {%if build.target_set.all.count > 1%}(+{{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})</a></li> 12<li><a href="{%url 'builddashboard' build.pk%}">{{build.get_sorted_target_list.0.target}} {%if build.target_set.all.count > 1%}(+ {{build.target_set.all.count|add:"-1"}}){%endif%} {{build.machine}} ({{build.completed_on|date:"d/m/y H:i"}})</a></li>
12 {% block localbreadcrumb %}{% endblock %} 13 {% block localbreadcrumb %}{% endblock %}
13 </ul> 14 </ul>
14 <script> 15 <script>
@@ -25,10 +26,12 @@
25 <!-- begin left sidebar container --> 26 <!-- begin left sidebar container -->
26 <div id="nav" class="span2"> 27 <div id="nav" class="span2">
27 <ul class="nav nav-list well"> 28 <ul class="nav nav-list well">
29 {% if build.target_set.all.0.is_image %}
28 <li class="nav-header">Images</li> 30 <li class="nav-header">Images</li>
29 {% for t in build.target_set.all|dictsort:"target" %} 31 {% for t in build.get_sorted_target_list %}
30 <li><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li> 32 <li><a href="{% url 'target' build.pk t.pk %}">{{t.target}}</a><li>
31 {% endfor %} 33 {% endfor %}
34 {% endif %}
32 <li class="nav-header">Build</li> 35 <li class="nav-header">Build</li>
33 <li><a href="{% url 'configuration' build.pk %}">Configuration</a></li> 36 <li><a href="{% url 'configuration' build.pk %}">Configuration</a></li>
34 <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li> 37 <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li>
diff --git a/bitbake/lib/toaster/toastergui/templates/builddashboard.html b/bitbake/lib/toaster/toastergui/templates/builddashboard.html
index 763a28d1bf..9d91f4031f 100644
--- a/bitbake/lib/toaster/toastergui/templates/builddashboard.html
+++ b/bitbake/lib/toaster/toastergui/templates/builddashboard.html
@@ -1,15 +1,12 @@
1{% extends "basebuildpage.html" %} 1{% extends "basebuildpage.html" %}
2{% load humanize %} 2{% load humanize %}
3{% load projecttags %} 3{% load projecttags %}
4{% block localbreadcrumb %}
5<li>Dashboard</li>
6{% endblock %}
7 4
8{% block buildinfomain %} 5{% block buildinfomain %}
9<!-- page title --> 6<!-- page title -->
10<div class="row-fluid span10"> 7<div class="row-fluid span10">
11 <div class="page-header"> 8 <div class="page-header">
12 <h1>{{build.target_set.all|join:" "}} {{build.machine}}</h1> 9 <h1>{{build.target_set.all|join:", "}} {{build.machine}}</h1>
13 </div> 10 </div>
14</div> 11</div>
15 12
@@ -17,13 +14,25 @@
17<div class="row-fluid span10 pull-right"> 14<div class="row-fluid span10 pull-right">
18 <div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-error{%else%}alert-info{%endif%}"> 15 <div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-error{%else%}alert-info{%endif%}">
19 <div class="row-fluid lead"> 16 <div class="row-fluid lead">
20 <span class="pull-left"><strong>{%if build.outcome == build.SUCCEEDED%}Completed{%elif build.outcome == build.FAILED%}Failed{%else%}{%endif%}</strong> {{build.completed_on|date:"d/m/y H:i"}} with </span>{%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %}{% if build.errors_no %} 17 <span class="pull-left"><strong>
21 <span class="span2"><i class="icon-minus-sign red"></i><strong><a href="#errors" class="error"> {{build.errors_no}} error{{build.errors_no|pluralize}}</a></strong></span> 18 {%if build.outcome == build.SUCCEEDED%}Completed{%elif build.outcome == build.FAILED%}Failed{%else%}{%endif%}
19 </strong>
20 {{build.completed_on|date:"d/m/y H:i"}}
21</span>
22{% if build.warnings_no or build.errors_no %}
23&nbsp;with
24{% endif %}
25{%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %}
26{% if build.errors_no %}
27 <span > <i class="icon-minus-sign red"></i><strong><a href="#errors" class="error"> {{build.errors_no}} error{{build.errors_no|pluralize}}</a></strong></span>
22{% endif %} 28{% endif %}
23{% if build.warnings_no %} 29{% if build.warnings_no %}
24 <span class="span2"><i class="icon-warning-sign yellow"></i><strong><a href="#warnings" class="warning"> {{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a></strong></span> 30{% if build.errors_no %}
31&nbsp;and
32{% endif %}
33 <span > <i class="icon-warning-sign yellow"></i><strong><a href="#warnings" class="warning"> {{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a></strong></span>
25{% endif %} 34{% endif %}
26 <span class="pull-right">Build time: <a href="build-time.html">{{ build.timespent|sectohms }}</a></span> 35 <span class="pull-right">Build time: <a href="{% url 'buildtime' build.pk %}">{{ build.timespent|sectohms }}</a></span>
27{%endif%} 36{%endif%}
28 </div> 37 </div>
29 </div> 38 </div>
@@ -58,10 +67,40 @@
58{%if build.outcome == build.SUCCEEDED%} 67{%if build.outcome == build.SUCCEEDED%}
59<!-- built images --> 68<!-- built images -->
60<div class="row-fluid span10 pull-right"> 69<div class="row-fluid span10 pull-right">
61 <h2>Images</h2> 70 {% if hasImages %}
62 71 <h2>Images</h2>
63<div class="well" style="background-color:transparent;"> 72 {% for target in targets %}
64</div> 73 {% if target.target.is_image %}
74 <div class="well" style="background-color:transparent;">
75 <h3><a href="{% url 'target' build.pk target.target.pk %}">{{target.target}}</a>
76 </h3>
77 <dl class="dl-horizontal">
78 <dt>Packages included</dt>
79 <dd><a href="{% url 'packages' build.pk %}">{{target.npkg}}</a></dd>
80 <dt>Total package size</dt>
81 <dd>{{target.pkgsz|filtered_filesizeformat}}</dd>
82 <dt>
83 <i class="icon-question-sign get-help" title="The location in disk of the license manifest, a document listing all packages installed in your image and their licenses"></i>
84 License manifest
85 </dt>
86 <dd><a href="{% url 'targetpackages' build.pk target.target.pk %}"><code>{{target.target.license_manifest_path}}</code></a></dd>
87 <dt>
88 <i class="icon-question-sign get-help" title="Image files are stored in <code style='background-color:transparent;color:#FFFFFF;font-weight:normal;border:none;'>/build/tmp/deploy/images/</code>"></i>
89 Image files
90 </dt>
91 <dd>
92 <ul>
93 {% for i in target.imageFiles %}
94 <li><strong>{{i.path}}</strong>
95 ({{i.size|filtered_filesizeformat}})</li>
96 {% endfor %}
97 </ul>
98 </dd>
99 </dl>
100 </div>
101 {% endif %}
102 {% endfor %}
103 {% endif %}
65</div> 104</div>
66 105
67{%else%} 106{%else%}
@@ -75,24 +114,32 @@
75 <h4><a href="{%url 'configuration' build.pk%}">Configuration</a></h4> 114 <h4><a href="{%url 'configuration' build.pk%}">Configuration</a></h4>
76 <dl> 115 <dl>
77 <dt>Machine</dt><dd>{{build.machine}}</dd> 116 <dt>Machine</dt><dd>{{build.machine}}</dd>
78 <dt>Distro</dt><dd></dd> 117 <dt>Distro</dt><dd>{{build.distro}}</dd>
79 <dt>Layers</dt>{% for i in build.layer_version_build.all %}<dd>{{i.layer.name}}</dd>{%endfor%} 118 <dt>Layers</dt>{% for i in build.layer_version_build.all|dictsort:"layer.name" %}<dd>{{i.layer.name}}</dd>{%endfor%}
80 </dl> 119 </dl>
81 </div> 120 </div>
82 <div class="well span4" style="background-color:transparent;"> 121 <div class="well span4" style="background-color:transparent;">
83 <h4><a href="{%url 'tasks' build.pk%}">Tasks</a></h4> 122 <h4><a href="{%url 'tasks' build.pk%}">Tasks</a></h4>
84 <dl> 123 <dl>
85 <dt>Total number of tasks</dt><dd>{{build.task_build.all.count}}</dd> 124 <dt>Total number of tasks</dt><dd><a href="{% url 'tasks' build.pk %}">{{build.task_build.all.count}}</a></dd>
86 <dt>Tasks executed</dt><dd>{% query build.task_build task_executed=1 order__gt=0 as exectask%}{{exectask.count}}</dd> 125 <dt>Tasks executed</dt><dd><a href="{% url 'tasks' build.pk %}?filter=task_executed%3A1&amp;count=25&amp;search=&amp;page=1&amp;orderby=order%3A%2B">{% query build.task_build task_executed=1 order__gt=0 as exectask%}{{exectask.count}}</a></dd>
87 <dt>Tasks prebuilt</dt><dd>{% query build.task_build task_executed=0 order__gt=0 as noexectask%}{{noexectask.count}}</dd> 126 <dt>Tasks not executed</dt><dd><a href="{% url 'tasks' build.pk %}?filter=task_executed%3A0&amp;count=25&amp;search=&amp;page=1&amp;orderby=order%3A%2B">{% query build.task_build task_executed=0 order__gt=0 as noexectask%}{{noexectask.count}}</a></dd>
88 <dt>Reuse</dt><dd>{% query build.task_build order__gt=0 as texec %}{{noexectask.count|multiply:100|divide:texec.count}}%</dd> 127 <dt>Reuse</dt><dd>
128{% query build.task_build order__gt=0 as texec %}
129{% if noexectask.count|multiply:100|divide:texec.count < 0 %}
1300
131{% else %}
132{{noexectask.count|multiply:100|divide:texec.count}}
133{% endif %}
134%
135 </dd>
89 </dl> 136 </dl>
90 </div> 137 </div>
91 <div class="well span4" style="background-color:transparent;"> 138 <div class="well span4" style="background-color:transparent;">
92 <h4><a href="{% url 'recipes' build.pk %}">Recipes</a> & <a href="{% url 'packages' build.pk %}">Packages</a></h4> 139 <h4><a href="{% url 'recipes' build.pk %}">Recipes</a> & <a href="{% url 'packages' build.pk %}">Packages</a></h4>
93 <dl> 140 <dl>
94 <dt>Recipes used</dt><dd>{{recipecount}}</dd> 141 <dt>Recipes built</dt><dd><a href="{% url 'recipes' build.pk %}">{{recipecount}}</a></dd>
95 <dt>Packages built</dt><dd>{{build.package_set.all.count}}</dd> 142 <dt>Packages built</dt><dd><a href="{% url 'packages' build.pk %}">{{build.package_set.all.count}}</a></dd>
96 </dl> 143 </dl>
97 </div> 144 </div>
98</div> 145</div>
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index d1234fe804..4f31ddb4bf 100644
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -25,7 +25,7 @@ from django.db.models import Q, Sum
25from django.shortcuts import render, redirect 25from django.shortcuts import render, redirect
26from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable 26from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
27from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency 27from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
28from orm.models import Target_Installed_Package, Target_File 28from orm.models import Target_Installed_Package, Target_Image_File
29from django.views.decorators.cache import cache_control 29from django.views.decorators.cache import cache_control
30from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger 30from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
31from django.http import HttpResponseBadRequest 31from django.http import HttpResponseBadRequest
@@ -350,18 +350,59 @@ def builds(request):
350 return render(request, template, context) 350 return render(request, template, context)
351 351
352 352
353##
353# build dashboard for a single build, coming in as argument 354# build dashboard for a single build, coming in as argument
355# Each build may contain multiple targets and each target
356# may generate multiple image files. display them all.
357#
354def builddashboard(request, build_id): 358def builddashboard(request, build_id):
355 template = "builddashboard.html" 359 template = "builddashboard.html"
356 if Build.objects.filter(pk=build_id).count() == 0 : 360 if Build.objects.filter(pk=build_id).count() == 0 :
357 return redirect(builds) 361 return redirect(builds)
362 build = Build.objects.filter(pk = build_id)[0];
363 layerVersionId = Layer_Version.objects.filter( build = build_id );
364 recipeCount = Recipe.objects.filter( layer_version__id__in = layerVersionId ).count( );
365 tgts = Target.objects.filter( build_id = build_id ).order_by( 'target' );
366
367 # set up custom target list with computed package and image data
368 targets = [ ];
369 ntargets = 0;
370 hasImages = False;
371 for t in tgts:
372 elem = { };
373 elem[ 'target' ] = t;
374 if ( t.is_image ):
375 hasImages = True;
376 npkg = 0;
377 pkgsz = 0;
378 pid= 0;
379 tp = Target_Installed_Package.objects.filter( target_id = t.id );
380 package = None;
381 for p in tp:
382 pid = p.package_id;
383 package = Package.objects.get( pk = p.package_id )
384 pkgsz = pkgsz + package.size;
385 npkg = npkg + 1;
386 elem[ 'npkg' ] = npkg;
387 elem[ 'pkgsz' ] = pkgsz;
388 ti = Target_Image_File.objects.filter( target_id = t.id );
389 imageFiles = [ ];
390 for i in ti:
391 imageFiles.append({ 'path': i.file_name, 'size' : i.file_size });
392 elem[ 'imageFiles' ] = imageFiles;
393 targets.append( elem );
394
358 context = { 395 context = {
359 'build' : Build.objects.filter(pk=build_id)[0], 396 'build' : build,
360 'recipecount' : Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)).count(), 397 'hasImages' : hasImages,
361 'logmessages' : LogMessage.objects.filter(build=build_id), 398 'ntargets' : ntargets,
399 'targets' : targets,
400 'recipecount' : recipeCount,
401 'logmessages' : LogMessage.objects.filter(build=build_id),
362 } 402 }
363 return render(request, template, context) 403 return render(request, template, context)
364 404
405
365def task(request, build_id, task_id): 406def task(request, build_id, task_id):
366 template = "task.html" 407 template = "task.html"
367 if Task.objects.filter(pk=task_id).count() == 0 : 408 if Task.objects.filter(pk=task_id).count() == 0 :