summaryrefslogtreecommitdiffstats
path: root/bitbake
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2013-12-13 17:14:34 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-01-10 15:20:26 +0000
commit5482409a370552809de75150350defef04ac7144 (patch)
treee0af09995517b66cc01be62508fef763907e051d /bitbake
parent2251426ae420640c082ec0d0109b9be435075411 (diff)
downloadpoky-5482409a370552809de75150350defef04ac7144.tar.gz
bitbake: toaster: Build dashboard implementation
This patch adds the build dashboard page implementation, which is the landing page for the Toaster GUI. Also adds correct links from the main build page to the various parts of the dashboard. [YOCTO #4258] (Bitbake rev: bf7fbf5c0ee39564d813f82e194242f9d4f73c47) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake')
-rw-r--r--bitbake/lib/toaster/toastergui/templates/basebuildpage.html7
-rw-r--r--bitbake/lib/toaster/toastergui/templates/basetable_bottom.html4
-rw-r--r--bitbake/lib/toaster/toastergui/templates/build.html17
-rw-r--r--bitbake/lib/toaster/toastergui/templates/builddashboard.html66
-rw-r--r--bitbake/lib/toaster/toastergui/templatetags/projecttags.py18
-rw-r--r--bitbake/lib/toaster/toastergui/views.py36
6 files changed, 125 insertions, 23 deletions
diff --git a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
index 1b037f9539..7d2a1f388e 100644
--- a/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
+++ b/bitbake/lib/toaster/toastergui/templates/basebuildpage.html
@@ -3,7 +3,7 @@
3{% block pagecontent %} 3{% block pagecontent %}
4 4
5 5
6 <div class="span12"> 6 <div class="">
7<!-- Breadcrumbs --> 7<!-- Breadcrumbs -->
8 <div class="section"> 8 <div class="section">
9 <ul class="breadcrumb" id="breadcrumb"> 9 <ul class="breadcrumb" id="breadcrumb">
@@ -40,12 +40,11 @@
40 <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li> 40 <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
41 </ul> 41 </ul>
42 </div> 42 </div>
43
44 <!-- end left sidebar container --> 43 <!-- end left sidebar container -->
44
45 <!-- Begin right container --> 45 <!-- Begin right container -->
46 <div class="row span10">
47 {% block buildinfomain %}{% endblock %} 46 {% block buildinfomain %}{% endblock %}
48 </div> 47 <!-- End right container -->
49 48
50 49
51 </div> 50 </div>
diff --git a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
index 2a6f084929..00703fe4c1 100644
--- a/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
+++ b/bitbake/lib/toaster/toastergui/templates/basetable_bottom.html
@@ -53,8 +53,8 @@
53 $('.progress, .lead span').tooltip({container:'table', placement:'top'}); 53 $('.progress, .lead span').tooltip({container:'table', placement:'top'});
54 54
55 $(".pagesize").change(function () { 55 $(".pagesize").change(function () {
56 $(".pagesize option:selected").each(function () 56 console.log("page size change");
57 {reload_params({"count":$(this).text()}); }); 57 reload_params({"count":$(this).val()}); ;
58 }); 58 });
59}); 59});
60</script> 60</script>
diff --git a/bitbake/lib/toaster/toastergui/templates/build.html b/bitbake/lib/toaster/toastergui/templates/build.html
index 27ce1ccbc5..43b491d558 100644
--- a/bitbake/lib/toaster/toastergui/templates/build.html
+++ b/bitbake/lib/toaster/toastergui/templates/build.html
@@ -12,7 +12,6 @@
12 Recent Builds 12 Recent Builds
13 </h1> 13 </h1>
14</div> 14</div>
15{{build_mru}}
16{% for build in mru %} 15{% for build in mru %}
17<div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-error{%else%}alert-info{%endif%}"> 16<div class="alert {%if build.outcome == build.SUCCEEDED%}alert-success{%elif build.outcome == build.FAILED%}alert-error{%else%}alert-info{%endif%}">
18 <div class="row-fluid"> 17 <div class="row-fluid">
@@ -74,17 +73,17 @@
74 </tr> 73 </tr>
75 {% for build in objects %} 74 {% for build in objects %}
76 <tr class="data"> 75 <tr class="data">
77 <td class="outcome"><a href="{% url "configuration" build.id %}">{%if build.outcome == build.SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif build.outcome == build.FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a></td> 76 <td class="outcome"><a href="{% url "builddashboard" build.id %}">{%if build.outcome == build.SUCCEEDED%}<i class="icon-ok-sign success"></i>{%elif build.outcome == build.FAILED%}<i class="icon-minus-sign error"></i>{%else%}{%endif%}</a></td>
78 <td class="target">{% for t in build.target_set.all %}{%if t.is_image %}<a href="{% url "target" build.id t.id %}">{% endif %}{{t.target}}{% if t.is_image %}</a>{% endif %}<br/>{% endfor %}</td> 77 <td class="target">{% for t in build.target_set.all %}{%if t.is_image %}<a href="{% url "target" build.id t.id %}">{% endif %}{{t.target}}{% if t.is_image %}</a>{% endif %}<br/>{% endfor %}</td>
79 <td class="machine">{{build.machine}}</td> 78 <td class="machine"><a href="{% url "builddashboard" build.id %}">{{build.machine}}</a></td>
80 <td class="started_on">{{build.started_on}}</td> 79 <td class="started_on"><a href="{% url "builddashboard" build.id %}">{{build.started_on}}</a></td>
81 <td class="completed_on">{{build.completed_on}}</td> 80 <td class="completed_on"><a href="{% url "builddashboard" build.id %}">{{build.completed_on}}</a></td>
82 <td class="failed_tasks"></td> 81 <td class="failed_tasks"></td>
83 <td class="errors">{% if build.errors_no %}<a class="error" href="#">{{build.errors_no}} error{{build.errors_no|pluralize}}</a>{%endif%}</td> 82 <td class="errors">{% if build.errors_no %}<a class="error" href="{% url "builddashboard" build.id %}#errors">{{build.errors_no}} error{{build.errors_no|pluralize}}</a>{%endif%}</td>
84 <td class="warnings">{% if build.warnings_no %}<a class="warning" href="#">{{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a>{%endif%}</td> 83 <td class="warnings">{% if build.warnings_no %}<a class="warning" href="{% url "builddashboard" build.id %}#warnings">{{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a>{%endif%}</td>
85 <td class="time">{{build|timespent}}</td> 84 <td class="time"><a href="{% url "buildtime" build.id %}">{{build|timespent}}</a></td>
86 <td class="log">{{build.log}}</td> 85 <td class="log">{{build.log}}</td>
87 <td class="output">{% if build.outcome == 0 %}{% for t in build.target_set.all %}{% if t.is_image %}{{build.image_fstypes}}{% endif %}{% endfor %}{% endif %}</td> 86 <td class="output">{% if build.outcome == 0 %}{% for t in build.target_set.all %}{% if t.is_image %}<a href="{%url "builddashboard" build.id%}#images">{{build.image_fstypes}}</a>{% endif %}{% endfor %}{% endif %}</td>
88 </tr> 87 </tr>
89 88
90 {% endfor %} 89 {% endfor %}
diff --git a/bitbake/lib/toaster/toastergui/templates/builddashboard.html b/bitbake/lib/toaster/toastergui/templates/builddashboard.html
index 7c58cc0b25..3b184372bf 100644
--- a/bitbake/lib/toaster/toastergui/templates/builddashboard.html
+++ b/bitbake/lib/toaster/toastergui/templates/builddashboard.html
@@ -1,8 +1,74 @@
1{% extends "basebuildpage.html" %} 1{% extends "basebuildpage.html" %}
2{% load humanize %}
3{% load projecttags %}
2{% block localbreadcrumb %} 4{% block localbreadcrumb %}
3<li>Dashboard</li> 5<li>Dashboard</li>
4{% endblock %} 6{% endblock %}
5 7
6{% block buildinfomain %} 8{% block buildinfomain %}
9<!-- page title -->
10<div class="row-fluid span10">
11 <div class="page-header">
12 <h1>{{build.target_set.all|join:" "}} {{build.machine}}</h1>
13 </div>
14</div>
15
16<!-- build result bar -->
17<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%}">
19 <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|naturaltime}} with </span>{%if build.outcome == build.SUCCEEDED or build.outcome == build.FAILED %}{% if build.errors_no %}
21 <span class="span2"><i class="icon-minus-sign red"></i><strong><a href="{%url 'builddashboard' build.pk%}" class="error"> {{build.errors_no}} error{{build.errors_no|pluralize}}</a></strong></span>
22{% endif %}
23{% if build.warnings_no %}
24 <span class="span2"><i class="icon-warning-sign yellow"></i><strong><a href="{%url 'builddashboard' build.pk%}" class="warning"> {{build.warnings_no}} warning{{build.warnings_no|pluralize}}</a></strong></span>
25{% endif %}
26 <span class="pull-right">Build time: <a href="build-time.html">{{ build|timespent }}</a></span>
27{%endif%}
28 </div>
29 </div>
30</div>
31
32{%if build.outcome == build.SUCCEEDED%}
33<!-- built images -->
34<div class="row-fluid span10 pull-right">
35 <h2>Images</h2>
36
37<div class="well" style="background-color:transparent;">
38</div>
39</div>
40
41{%else%}
42<!-- error dump -->
43{%endif%}
44
45<!-- build summary -->
46<div class="row-fluid span10 pull-right">
47<h2>Build summary</h2>
48 <div class="well span4" style="margin-left:0px; background-color:transparent;">
49 <h4><a href="{%url 'configuration' build.pk%}">Configuration</a></h4>
50 <dl>
51 <dt>Machine</dt><dd>{{build.machine}}</dd>
52 <dt>Distro</dt><dd></dd>
53 <dt>Layers</dt>{% for i in build.layer_version_build.all %}<dd>{{i.layer.name}}</dd>{%endfor%}
54 </dl>
55 </div>
56 <div class="well span4" style="background-color:transparent;">
57 <h4><a href="{%url 'tasks' build.pk%}">Tasks</a></h4>
58 <dl>
59 <dt>Total number of tasks</dt><dd>{{build.task_build.all.count}}</dd>
60 <dt>Tasks executed</dt><dd>{% query build.task_build task_executed=1 order__gt=0 as exectask%}{{exectask.count}}</dd>
61 <dt>Tasks prebuilt</dt><dd>{% query build.task_build task_executed=0 order__gt=0 as noexectask%}{{noexectask.count}}</dd>
62 <dt>Reuse</dt><dd>{% query build.task_build order__gt=0 as texec %}{{noexectask.count|multiply:100|divide:texec.count}}%</dd>
63 </dl>
64 </div>
65 <div class="well span4" style="background-color:transparent;">
66 <h4><a href="{% url 'recipes' build.pk %}">Recipes</a> & <a href="{% url 'packages' build.pk %}">Packages</a></h4>
67 <dl>
68 <dt>Recipes used</dt><dd>{{recipecount}}</dd>
69 <dt>Packages built</dt><dd>{{build.package_set.all.count}}</dd>
70 </dl>
71 </div>
72</div>
7 73
8{% endblock %} 74{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
index 5f60379932..1455026754 100644
--- a/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
+++ b/bitbake/lib/toaster/toastergui/templatetags/projecttags.py
@@ -29,3 +29,21 @@ def time_difference(start_time, end_time):
29def timespent(build_object): 29def timespent(build_object):
30 tdsec = (build_object.completed_on - build_object.started_on).total_seconds() 30 tdsec = (build_object.completed_on - build_object.started_on).total_seconds()
31 return "%02d:%02d:%02d" % (int(tdsec/3600), int((tdsec - tdsec/ 3600)/ 60), int(tdsec) % 60) 31 return "%02d:%02d:%02d" % (int(tdsec/3600), int((tdsec - tdsec/ 3600)/ 60), int(tdsec) % 60)
32
33@register.assignment_tag
34def query(qs, **kwargs):
35 """ template tag which allows queryset filtering. Usage:
36 {% query books author=author as mybooks %}
37 {% for book in mybooks %}
38 ...
39 {% endfor %}
40 """
41 return qs.filter(**kwargs)
42
43@register.filter
44def divide(value, arg):
45 return int(value) / int(arg)
46
47@register.filter
48def multiply(value, arg):
49 return int(value) * int(arg)
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 663e03dfd2..7d4d710f83 100644
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -59,10 +59,10 @@ def _verify_parameters(g, mandatory_parameters):
59 return miss 59 return miss
60 return None 60 return None
61 61
62def _redirect_parameters(view, g, mandatory_parameters): 62def _redirect_parameters(view, g, mandatory_parameters, *args, **kwargs):
63 import urllib 63 import urllib
64 from django.core.urlresolvers import reverse 64 from django.core.urlresolvers import reverse
65 url = reverse(view) 65 url = reverse(view, kwargs=kwargs)
66 params = {} 66 params = {}
67 for i in g: 67 for i in g:
68 params[i] = g[i] 68 params[i] = g[i]
@@ -70,7 +70,7 @@ def _redirect_parameters(view, g, mandatory_parameters):
70 if not i in params: 70 if not i in params:
71 params[i] = mandatory_parameters[i] 71 params[i] = mandatory_parameters[i]
72 72
73 return redirect(url + "?%s" % urllib.urlencode(params)) 73 return redirect(url + "?%s" % urllib.urlencode(params), *args, **kwargs)
74 74
75 75
76# shows the "all builds" page 76# shows the "all builds" page
@@ -82,7 +82,7 @@ def builds(request):
82 mandatory_parameters = { 'count': 10, 'page' : 1}; 82 mandatory_parameters = { 'count': 10, 'page' : 1};
83 retval = _verify_parameters( request.GET, mandatory_parameters ) 83 retval = _verify_parameters( request.GET, mandatory_parameters )
84 if retval: 84 if retval:
85 return _redirect_parameters( builds, request.GET, mandatory_parameters) 85 return _redirect_parameters( 'all-builds', request.GET, mandatory_parameters)
86 86
87 # retrieve the objects that will be displayed in the table 87 # retrieve the objects that will be displayed in the table
88 build_info = _build_page_range(Paginator(Build.objects.exclude(outcome = Build.IN_PROGRESS).order_by("-id"), request.GET.get('count', 10)),request.GET.get('page', 1)) 88 build_info = _build_page_range(Paginator(Build.objects.exclude(outcome = Build.IN_PROGRESS).order_by("-id"), request.GET.get('count', 10)),request.GET.get('page', 1))
@@ -125,6 +125,7 @@ def builddashboard(request, build_id):
125 return redirect(builds) 125 return redirect(builds)
126 context = { 126 context = {
127 'build' : Build.objects.filter(pk=build_id)[0], 127 'build' : Build.objects.filter(pk=build_id)[0],
128 'recipecount' : Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)).count()
128 } 129 }
129 return render(request, template, context) 130 return render(request, template, context)
130 131
@@ -186,8 +187,12 @@ def _find_task_provider(task):
186 187
187def tasks(request, build_id): 188def tasks(request, build_id):
188 template = 'task.html' 189 template = 'task.html'
190 mandatory_parameters = { 'count': 100, 'page' : 1};
191 retval = _verify_parameters( request.GET, mandatory_parameters )
192 if retval:
193 return _redirect_parameters( 'tasks', request.GET, mandatory_parameters, build_id = build_id)
189 194
190 tasks = _build_page_range(Paginator(Task.objects.filter(build=build_id), 100),request.GET.get('page', 1)) 195 tasks = _build_page_range(Paginator(Task.objects.filter(build=build_id, order__gt=0), request.GET.get('count', 100)),request.GET.get('page', 1))
191 196
192 for t in tasks: 197 for t in tasks:
193 if t.outcome == Task.OUTCOME_COVERED: 198 if t.outcome == Task.OUTCOME_COVERED:
@@ -199,16 +204,25 @@ def tasks(request, build_id):
199 204
200def recipes(request, build_id): 205def recipes(request, build_id):
201 template = 'recipe.html' 206 template = 'recipe.html'
207 mandatory_parameters = { 'count': 100, 'page' : 1};
208 retval = _verify_parameters( request.GET, mandatory_parameters )
209 if retval:
210 return _redirect_parameters( 'recipes', request.GET, mandatory_parameters, build_id = build_id)
202 211
203 recipes = _build_page_range(Paginator(Recipe.objects.filter(build_recipe=build_id), 100),request.GET.get('page', 1)) 212 recipes = _build_page_range(Paginator(Recipe.objects.filter(layer_version__id__in=Layer_Version.objects.filter(build=build_id)), request.GET.get('count', 100)),request.GET.get('page', 1))
204 213
205 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects': recipes} 214 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects': recipes, }
206 215
207 return render(request, template, context) 216 return render(request, template, context)
208 217
209 218
210def configuration(request, build_id): 219def configuration(request, build_id):
211 template = 'configuration.html' 220 template = 'configuration.html'
221 mandatory_parameters = { 'count': 100, 'page' : 1};
222 retval = _verify_parameters( request.GET, mandatory_parameters )
223 if retval:
224 return _redirect_parameters( 'configuration', request.GET, mandatory_parameters, build_id = build_id)
225
212 variables = _build_page_range(Paginator(Variable.objects.filter(build=build_id), 50), request.GET.get('page', 1)) 226 variables = _build_page_range(Paginator(Variable.objects.filter(build=build_id), 50), request.GET.get('page', 1))
213 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : variables} 227 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : variables}
214 return render(request, template, context) 228 return render(request, template, context)
@@ -245,7 +259,13 @@ def diskio(request, build_id):
245 259
246def bpackage(request, build_id): 260def bpackage(request, build_id):
247 template = 'bpackage.html' 261 template = 'bpackage.html'
248 packages = Package.objects.filter(build = build_id) 262 mandatory_parameters = { 'count': 100, 'page' : 1};
263 retval = _verify_parameters( request.GET, mandatory_parameters )
264 if retval:
265 return _redirect_parameters( 'packages', request.GET, mandatory_parameters, build_id = build_id)
266
267 packages = _build_page_range(Paginator(Package.objects.filter(build = build_id), request.GET.get('count', 100)),request.GET.get('page', 1))
268
249 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : packages} 269 context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : packages}
250 return render(request, template, context) 270 return render(request, template, context)
251 271