summaryrefslogtreecommitdiffstats
path: root/bitbake/lib
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2016-05-26 16:12:22 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-06-15 08:35:04 +0100
commitb2a68f55110b39aaf0b0d47bf533251a59a40a41 (patch)
tree7791ed85141e07f01c228619047740b235ee02dc /bitbake/lib
parent32d1e2dd25f288790450db48766cf115854712ba (diff)
downloadpoky-b2a68f55110b39aaf0b0d47bf533251a59a40a41.tar.gz
bitbake: toaster: port Task tables to ToasterTables widget
Port the Task based tables to ToasterTable. This is the Task, Time, CPU usage and Disk I/O tables. (Bitbake rev: bebcef7a4bf08b10e472475435ddc7a524364adb) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib')
-rw-r--r--bitbake/lib/toaster/toastergui/buildtables.py227
-rw-r--r--bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html4
-rw-r--r--bitbake/lib/toaster/toastergui/templates/buildtime.html4
-rw-r--r--bitbake/lib/toaster/toastergui/templates/task.html2
-rw-r--r--bitbake/lib/toaster/toastergui/templates/tasks.html141
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py23
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py280
7 files changed, 248 insertions, 433 deletions
diff --git a/bitbake/lib/toaster/toastergui/buildtables.py b/bitbake/lib/toaster/toastergui/buildtables.py
index dc742b9fe5..51c136f988 100644
--- a/bitbake/lib/toaster/toastergui/buildtables.py
+++ b/bitbake/lib/toaster/toastergui/buildtables.py
@@ -19,10 +19,13 @@
19# with this program; if not, write to the Free Software Foundation, Inc., 19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 21
22from orm.models import Build 22from orm.models import Build, Task
23import toastergui.tables as tables 23from django.db.models import Q
24 24
25import toastergui.tables as tables
25from toastergui.widgets import ToasterTable 26from toastergui.widgets import ToasterTable
27from toastergui.tablefilter import TableFilter
28from toastergui.tablefilter import TableFilterActionToggle
26 29
27 30
28class BuildTablesMixin(ToasterTable): 31class BuildTablesMixin(ToasterTable):
@@ -279,3 +282,223 @@ class BuiltRecipesTable(BuildTablesMixin):
279 self.add_column(title="Layer commit", 282 self.add_column(title="Layer commit",
280 static_data_name="commit", 283 static_data_name="commit",
281 static_data_template=git_rev_template) 284 static_data_template=git_rev_template)
285
286
287class BuildTasksTable(BuildTablesMixin):
288 """ Table to show the tasks that run in this build """
289
290 def __init__(self, *args, **kwargs):
291 super(BuildTasksTable, self).__init__(*args, **kwargs)
292 self.title = "Tasks"
293 self.default_orderby = "order"
294
295 # Toggle these columns on off for Time/CPU usage/Disk I/O tables
296 self.toggle_columns = {}
297
298 def setup_queryset(self, *args, **kwargs):
299 build = Build.objects.get(pk=kwargs['build_id'])
300 self.static_context_extra['build'] = build
301 self.queryset = build.task_build.filter(~Q(order=None))
302 self.queryset = self.queryset.order_by(self.default_orderby)
303
304 def setup_filters(self, *args, **kwargs):
305 # Execution outcome types filter
306 executed_outcome = TableFilter(name="execution_outcome",
307 title="Filter Tasks by 'Executed")
308
309 exec_outcome_action_exec = TableFilterActionToggle(
310 "executed",
311 "Executed Tasks",
312 Q(task_executed=True))
313
314 exec_outcome_action_not_exec = TableFilterActionToggle(
315 "not_executed",
316 "Not Executed Tasks",
317 Q(task_executed=False))
318
319 executed_outcome.add_action(exec_outcome_action_exec)
320 executed_outcome.add_action(exec_outcome_action_not_exec)
321
322 # Task outcome types filter
323 task_outcome = TableFilter(name="task_outcome",
324 title="Filter Task by 'Outcome'")
325
326 for outcome_enum, title in Task.TASK_OUTCOME:
327 action = TableFilterActionToggle(
328 title.replace(" ", "_").lower(),
329 "%s Tasks" % title,
330 Q(outcome=outcome_enum))
331
332 task_outcome.add_action(action)
333
334 # SSTATE outcome types filter
335 sstate_outcome = TableFilter(name="sstate_outcome",
336 title="Filter Task by 'Cache attempt'")
337
338 for sstate_result_enum, title in Task.SSTATE_RESULT:
339 action = TableFilterActionToggle(
340 title.replace(" ", "_").lower(),
341 "Tasks with '%s' attempts" % title,
342 Q(sstate_result=sstate_result_enum))
343
344 sstate_outcome.add_action(action)
345
346 self.add_filter(sstate_outcome)
347 self.add_filter(executed_outcome)
348 self.add_filter(task_outcome)
349
350 def setup_columns(self, *args, **kwargs):
351 self.toggle_columns['order'] = len(self.columns)
352
353 recipe_name_tmpl =\
354 '<a href="{% url "recipe" extra.build.pk data.recipe.pk %}">'\
355 '{{data.recipe.name}}'\
356 '</a>'
357
358 recipe_version_tmpl =\
359 '<a href="{% url "recipe" extra.build.pk data.recipe.pk %}">'\
360 '{{data.recipe.version}}'\
361 '</a>'
362
363 def task_link_tmpl(val):
364 return ('<a name="task-{{data.order}}"'
365 'href="{%% url "task" extra.build.pk data.pk %%}">'
366 '%s'
367 '</a>') % str(val)
368
369 self.add_column(title="Order",
370 static_data_name="order",
371 static_data_template=task_link_tmpl('{{data.order}}'),
372 orderable=True)
373
374 self.add_column(title="Recipe",
375 static_data_name='recipe__name',
376 static_data_template=recipe_name_tmpl,
377 orderable=True)
378
379 self.add_column(title="Recipe version",
380 static_data_name='recipe__version',
381 static_data_template=recipe_version_tmpl)
382
383 self.add_column(title="Task",
384 static_data_name="task_name",
385 static_data_template=task_link_tmpl(
386 "{{data.task_name}}"),
387 orderable=True)
388
389 self.add_column(title="Executed",
390 static_data_name="task_executed",
391 static_data_template=task_link_tmpl(
392 "{{data.get_executed_display}}"),
393 filter_name='execution_outcome',
394 orderable=True)
395
396 self.static_context_extra['OUTCOME_FAILED'] = Task.OUTCOME_FAILED
397 outcome_tmpl = task_link_tmpl("{{data.outcome_text}}")
398 outcome_tmpl = ('%s '
399 '{%% if data.outcome = extra.OUTCOME_FAILED %%}'
400 '<a href="{%% url "build_artifact" extra.build.pk '
401 ' "tasklogfile" data.pk %%}">'
402 ' <i class="icon-download-alt" '
403 ' title="Download task log file"></i>'
404 '</a> {%% endif %%}'
405 '<i class="icon-question-sign get-help '
406 'hover-help" style="visibility: hidden;" '
407 'title="{{data.get_outcome_help}}"></i>'
408 ) % outcome_tmpl
409
410 self.add_column(title="Outcome",
411 static_data_name="outcome",
412 static_data_template=outcome_tmpl,
413 filter_name="task_outcome",
414 orderable=True)
415
416 self.add_column(title="Cache attempt",
417 static_data_name="sstate_result",
418 static_data_template=task_link_tmpl(
419 "{{data.sstate_text}}"),
420 filter_name="sstate_outcome",
421 orderable=True)
422
423 self.toggle_columns['elapsed_time'] = len(self.columns)
424
425 self.add_column(
426 title="Time (secs)",
427 static_data_name="elapsed_time",
428 static_data_template='{% load projecttags %}{% load humanize %}'
429 '{{data.elapsed_time|format_none_and_zero|floatformat:2}}',
430 orderable=True,
431 hidden=True)
432
433 self.toggle_columns['cpu_time_sys'] = len(self.columns)
434
435 self.add_column(
436 title="System CPU time (secs)",
437 static_data_name="cpu_time_system",
438 static_data_template='{% load projecttags %}{% load humanize %}'
439 '{{data.cpu_time_system|format_none_and_zero|floatformat:2}}',
440 hidden=True,
441 orderable=True)
442
443 self.toggle_columns['cpu_time_user'] = len(self.columns)
444
445 self.add_column(
446 title="User CPU time (secs)",
447 static_data_name="cpu_time_user",
448 static_data_template='{% load projecttags %}{% load humanize %}'
449 '{{data.cpu_time_user|format_none_and_zero|floatformat:2}}',
450 hidden=True,
451 orderable=True)
452
453 self.toggle_columns['disk_io'] = len(self.columns)
454
455 self.add_column(
456 title="Disk I/O (ms)",
457 static_data_name="disk_io",
458 static_data_template='{% load projecttags %}{% load humanize %}'
459 '{{data.disk_io|format_none_and_zero|filtered_filesizeformat}}',
460 hidden=True,
461 orderable=True)
462
463
464class BuildTimeTable(BuildTasksTable):
465 """ Same as tasks table but the Time column is default displayed"""
466
467 def __init__(self, *args, **kwargs):
468 super(BuildTimeTable, self).__init__(*args, **kwargs)
469 self.default_orderby = "-elapsed_time"
470
471 def setup_columns(self, *args, **kwargs):
472 super(BuildTimeTable, self).setup_columns(**kwargs)
473
474 self.columns[self.toggle_columns['order']]['hidden'] = True
475 self.columns[self.toggle_columns['elapsed_time']]['hidden'] = False
476
477
478class BuildCPUTimeTable(BuildTasksTable):
479 """ Same as tasks table but the CPU usage columns are default displayed"""
480
481 def __init__(self, *args, **kwargs):
482 super(BuildCPUTimeTable, self).__init__(*args, **kwargs)
483 self.default_orderby = "-cpu_time_system"
484
485 def setup_columns(self, *args, **kwargs):
486 super(BuildCPUTimeTable, self).setup_columns(**kwargs)
487
488 self.columns[self.toggle_columns['order']]['hidden'] = True
489 self.columns[self.toggle_columns['cpu_time_sys']]['hidden'] = False
490 self.columns[self.toggle_columns['cpu_time_user']]['hidden'] = False
491
492
493class BuildIOTable(BuildTasksTable):
494 """ Same as tasks table but the Disk IO column is default displayed"""
495
496 def __init__(self, *args, **kwargs):
497 super(BuildIOTable, self).__init__(*args, **kwargs)
498 self.default_orderby = "-disk_io"
499
500 def setup_columns(self, *args, **kwargs):
501 super(BuildIOTable, self).setup_columns(**kwargs)
502
503 self.columns[self.toggle_columns['order']]['hidden'] = True
504 self.columns[self.toggle_columns['disk_io']]['hidden'] = False
diff --git a/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html
index 4ce5c4a8a5..52cc0569f7 100644
--- a/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html
+++ b/bitbake/lib/toaster/toastergui/templates/buildinfo-toastertable.html
@@ -12,12 +12,14 @@
12 12
13{% block buildinfomain %} 13{% block buildinfomain %}
14<div class="span10"> 14<div class="span10">
15{% url 'builtpackagestable' build.id as xhr_table_url %} 15{# xhr_table_url is just the current url so leave it blank #}
16{% with xhr_table_url='' %}
16 <div class="page-header"> 17 <div class="page-header">
17 <h1> 18 <h1>
18 {{title}} (<span class="table-count-{{table_name}}">0</span>) </h2> 19 {{title}} (<span class="table-count-{{table_name}}">0</span>) </h2>
19 </h1> 20 </h1>
20 </div> 21 </div>
21 {% include "toastertable.html" %} 22 {% include "toastertable.html" %}
23{% endwith %}
22</div> 24</div>
23{% endblock %} 25{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templates/buildtime.html b/bitbake/lib/toaster/toastergui/templates/buildtime.html
deleted file mode 100644
index ea84ae797c..0000000000
--- a/bitbake/lib/toaster/toastergui/templates/buildtime.html
+++ /dev/null
@@ -1,4 +0,0 @@
1{% extends "basebuildpage.html" %}
2{% block localbreadcrumb %}
3<li>Build Time</li>
4{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/templates/task.html b/bitbake/lib/toaster/toastergui/templates/task.html
index 8773351fab..77391b4e35 100644
--- a/bitbake/lib/toaster/toastergui/templates/task.html
+++ b/bitbake/lib/toaster/toastergui/templates/task.html
@@ -196,7 +196,7 @@
196 <i class="icon-question-sign get-help" title="The running sequence of each task in the build"></i> 196 <i class="icon-question-sign get-help" title="The running sequence of each task in the build"></i>
197 Task order 197 Task order
198 </dt> 198 </dt>
199 <dd><a href="{%url "tasks_task" build.pk task.order %}#{{task.order}}">{{task.order}}</a></dd> 199 <dd><a href="{%url "tasks" build.pk %}?page={{task_in_tasks_table_pg}}&limit=25#task-{{task.order}}">{{task.order}}</a></dd>
200 {% if task.task_executed %} 200 {% if task.task_executed %}
201 <dt> 201 <dt>
202 <i class="icon-question-sign get-help" title="Indicates if this task executes a Python or Shell function(s)"></i> 202 <i class="icon-question-sign get-help" title="Indicates if this task executes a Python or Shell function(s)"></i>
diff --git a/bitbake/lib/toaster/toastergui/templates/tasks.html b/bitbake/lib/toaster/toastergui/templates/tasks.html
deleted file mode 100644
index b3b7621e60..0000000000
--- a/bitbake/lib/toaster/toastergui/templates/tasks.html
+++ /dev/null
@@ -1,141 +0,0 @@
1{% extends "basebuildpage.html" %}
2{% load humanize %}
3{% load projecttags %}
4
5{% block title %} {{mainheading}} - {{build.target_set.all|dictsort:"target"|join:", "}} {{build.machine}} - {{build.project.name}} - Toaster{% endblock %}
6{% block localbreadcrumb %}
7<li>{{mainheading}}</li>
8{% endblock %}
9
10{% block nav-tasks %}
11 {% if 'Tasks' == mainheading %}
12 <li class="active"><a href="{% url 'tasks' build.pk %}">Tasks</a></li>
13 {% else %}
14 <li><a href="{% url 'tasks' build.pk %}">Tasks</a></li>
15 {% endif %}
16{% endblock %}
17{% block nav-buildtime %}
18 {% if 'Time' == mainheading %}
19 <li class="active"><a href="{% url 'buildtime' build.pk %}">Time</a></li>
20 {% else %}
21 <li><a href="{% url 'buildtime' build.pk %}">Time</a></li>
22 {% endif %}
23{% endblock %}
24
25{% block nav-cputime %}
26 {% if 'CPU time' == mainheading %}
27 <li class="active"><a href="{% url 'cputime' build.pk %}">CPU time</a></li>
28 {% else %}
29 <li><a href="{% url 'cputime' build.pk %}">CPU time</a></li>
30 {% endif %}
31{% endblock %}
32
33{% block nav-diskio %}
34 {% if 'Disk I/O' == mainheading %}
35 <li class="active"><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
36 {% else %}
37 <li><a href="{% url 'diskio' build.pk %}">Disk I/O</a></li>
38 {% endif %}
39{% endblock %}
40
41{% block buildinfomain %}
42<div class="col-md-10">
43{% if not request.GET.filter and not request.GET.search and not objects.paginator.count %}
44 <!-- Empty - no data in database -->
45 <div class="page-header">
46 <h1>{{mainheading}}</h1>
47 </div>
48 <div class="alert alert-info lead">
49 No data was recorded for this build.
50 </div>
51
52{% else %}
53
54 <div class="page-header">
55 <h1>
56 {% if request.GET.filter and objects.paginator.count > 0 or request.GET.search and objects.paginator.count > 0 %}
57 {{objects.paginator.count}} task{{objects.paginator.count|pluralize}} found
58 {%elif request.GET.filter and objects.paginator.count == 0 or request.GET.search and objects.paginator.count == 0 %}
59 No tasks found
60 {%else%}
61 {{mainheading}}
62 {%endif%}
63 </h1>
64 </div>
65
66 {% if objects.paginator.count == 0 %}
67 <div class="alert">
68 <form class="no-results input-append" id="searchform">
69 <input id="search" name="search" class="input-xxlarge" type="text" value="{{request.GET.search}}"/>{% if request.GET.search %}<a href="javascript:$('#search').val('');searchform.submit()" class="input-append-addon btn" tabindex="-1"><i class="glyphicon glyphicon-remove"></i></a>{% endif %}
70 <button class="btn" type="submit" value="Search">Search</button>
71 <button class="btn btn-link" onclick="javascript:$('#search').val('');searchform.submit()">Show all tasks</button>
72 </form>
73 </div>
74
75
76 {% else %}
77 {% include "basetable_top.html" %}
78
79 {% for task in objects %}
80 <tr {{ task|task_color }} id="{{task.order}}">
81 <td class="order">
82 <a href="{%url "task" build.pk task.pk%}">{{task.order}}</a>
83 </td>
84 <td class="recipe_name" >
85 <a href="{% url "recipe" build.pk task.recipe.pk %}">{{task.recipe.name}}</a>
86 </td>
87 <td class="recipe_version">
88 <a href="{% url "recipe" build.pk task.recipe.pk %}">{{task.recipe.version}}</a>
89 </td>
90 <td class="task_name">
91 <a href="{%url "task" build.pk task.pk%}">{{task.task_name}}</a> {% if task.get_description %}<i class="icon-question-sign get-help hover-help" title="{{task.get_description}}"></i> {% endif %}
92 </td>
93 <td class="executed">
94 <a href="{%url "task" build.pk task.pk%}">{{task.get_executed_display}}</a>
95 </td>
96 <td class="outcome">
97 <a href="{%url "task" build.pk task.pk%}">{{task.get_outcome_display}} </a>
98 {% if task.outcome = task.OUTCOME_FAILED %}
99 <a href="{% url 'build_artifact' build.pk "tasklogfile" task.pk %}">
100 <i class="icon-download-alt" title="Download task log file"></i>
101 </a>
102 {% endif %}
103 <i class="icon-question-sign get-help hover-help" title="{{task.get_outcome_help}}"></i>
104 </td>
105 <td class="cache_attempt">
106 <a href="{%url "task" build.pk task.pk%}">{{task.get_sstate_result_display|format_none_and_zero}}</a>
107 </td>
108 <td class="time_taken">
109 {{task.elapsed_time|format_none_and_zero|floatformat:2}}
110 </td>
111 <td class="cpu_time_system">
112 {{task.cpu_time_system|format_none_and_zero|floatformat:2}}
113 </td>
114 <td class="cpu_time_user">
115 {{task.cpu_time_user|format_none_and_zero|floatformat:2}}
116 </td>
117 <td class="disk_io">
118 {{task.disk_io|format_none_and_zero|intcomma}}
119 </td>
120
121 </tr>
122 {% endfor %}
123
124 {% include "basetable_bottom.html" %}
125 {% endif %} {# objects.paginator.count #}
126{% endif %} {# empty #}
127</div>
128
129<script type="text/javascript">
130
131 $(document).ready(function() {
132 // highlight heading on the column for the field used for ordering
133 if (location.href.search('#') > -1) {
134 var task_order = location.href.split('#')[1];
135 $("#" + task_order).addClass("highlight");
136 }
137 });
138
139</script>
140
141{% endblock %}
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 0636c956b2..c4913f124a 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -35,9 +35,11 @@ urlpatterns = patterns('toastergui.views',
35 35
36 # build info navigation 36 # build info navigation
37 url(r'^build/(?P<build_id>\d+)$', 'builddashboard', name="builddashboard"), 37 url(r'^build/(?P<build_id>\d+)$', 'builddashboard', name="builddashboard"),
38 url(r'^build/(?P<build_id>\d+)/tasks/$',
39 buildtables.BuildTasksTable.as_view(
40 template_name="buildinfo-toastertable.html"),
41 name='tasks'),
38 42
39 url(r'^build/(?P<build_id>\d+)/tasks/$', 'tasks', name='tasks'),
40 url(r'^build/(?P<build_id>\d+)/tasks/(?P<task_id>\d+)/$', 'tasks_task', name='tasks_task'),
41 url(r'^build/(?P<build_id>\d+)/task/(?P<task_id>\d+)$', 'task', name='task'), 43 url(r'^build/(?P<build_id>\d+)/task/(?P<task_id>\d+)$', 'task', name='task'),
42 44
43 url(r'^build/(?P<build_id>\d+)/recipes/$', 45 url(r'^build/(?P<build_id>\d+)/recipes/$',
@@ -74,9 +76,20 @@ urlpatterns = patterns('toastergui.views',
74 url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/dirinfo_filepath/_(?P<file_path>(?:/[^/\n]+)*)$', 'dirinfo', name='dirinfo_filepath'), 76 url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/dirinfo_filepath/_(?P<file_path>(?:/[^/\n]+)*)$', 'dirinfo', name='dirinfo_filepath'),
75 url(r'^build/(?P<build_id>\d+)/configuration$', 'configuration', name='configuration'), 77 url(r'^build/(?P<build_id>\d+)/configuration$', 'configuration', name='configuration'),
76 url(r'^build/(?P<build_id>\d+)/configvars$', 'configvars', name='configvars'), 78 url(r'^build/(?P<build_id>\d+)/configvars$', 'configvars', name='configvars'),
77 url(r'^build/(?P<build_id>\d+)/buildtime$', 'buildtime', name='buildtime'), 79 url(r'^build/(?P<build_id>\d+)/buildtime$',
78 url(r'^build/(?P<build_id>\d+)/cputime$', 'cputime', name='cputime'), 80 buildtables.BuildTimeTable.as_view(
79 url(r'^build/(?P<build_id>\d+)/diskio$', 'diskio', name='diskio'), 81 template_name="buildinfo-toastertable.html"),
82 name='buildtime'),
83
84 url(r'^build/(?P<build_id>\d+)/cputime$',
85 buildtables.BuildCPUTimeTable.as_view(
86 template_name="buildinfo-toastertable.html"),
87 name='cputime'),
88
89 url(r'^build/(?P<build_id>\d+)/diskio$',
90 buildtables.BuildIOTable.as_view(
91 template_name="buildinfo-toastertable.html"),
92 name='diskio'),
80 93
81 # image information dir 94 # image information dir
82 url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packagefile/(?P<packagefile_id>\d+)$', 95 url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packagefile/(?P<packagefile_id>\d+)$',
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 3a25d5ea1e..35ab63a22e 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -596,6 +596,7 @@ def task( request, build_id, task_id ):
596 'log_body' : log_body, 596 'log_body' : log_body,
597 'showing_matches' : False, 597 'showing_matches' : False,
598 'uri_list' : uri_list, 598 'uri_list' : uri_list,
599 'task_in_tasks_table_pg': int(task_object.order / 25) + 1
599 } 600 }
600 if request.GET.get( 'show_matches', "" ): 601 if request.GET.get( 'show_matches', "" ):
601 context[ 'showing_matches' ] = True 602 context[ 'showing_matches' ] = True
@@ -995,285 +996,6 @@ def _find_task_provider(task_object):
995 return trc 996 return trc
996 return None 997 return None
997 998
998def tasks_common(request, build_id, variant, task_anchor):
999# This class is shared between these pages
1000#
1001# Column tasks buildtime diskio cpuusage
1002# --------- ------ ---------- ------- ---------
1003# Cache def
1004# CPU min -
1005# Disk min -
1006# Executed def def def def
1007# Log
1008# Order def +
1009# Outcome def def def def
1010# Recipe min min min min
1011# Version
1012# Task min min min min
1013# Time min -
1014#
1015# 'min':on always, 'def':on by default, else hidden
1016# '+' default column sort up, '-' default column sort down
1017
1018 anchor = request.GET.get('anchor', '')
1019 if not anchor:
1020 anchor=task_anchor
1021
1022 # default ordering depends on variant
1023 default_orderby = None
1024 filter_search_display = 'tasks'
1025
1026 if 'buildtime' == variant:
1027 default_orderby = 'elapsed_time:-'
1028 title_variant = 'Time'
1029 object_search_display = 'time data'
1030 elif 'diskio' == variant:
1031 default_orderby = 'disk_io:-'
1032 title_variant = 'Disk I/O'
1033 object_search_display = 'disk I/O data'
1034 elif 'cputime' == variant:
1035 default_orderby = 'cpu_time_system:-'
1036 title_variant='CPU time'
1037 object_search_display = 'CPU time data'
1038 else:
1039 default_orderby = 'order:+'
1040 title_variant = 'Tasks'
1041 object_search_display = 'tasks'
1042
1043 (pagesize, orderby) = _get_parameters_values(request, 25, default_orderby)
1044
1045 mandatory_parameters = {'count': pagesize, 'page' : 1, 'orderby': orderby}
1046
1047 template = 'tasks.html'
1048 retval = _verify_parameters( request.GET, mandatory_parameters )
1049 if retval:
1050 if task_anchor:
1051 mandatory_parameters['anchor']=task_anchor
1052 return _redirect_parameters( variant, request.GET, mandatory_parameters, build_id = build_id)
1053 (filter_string, search_term, ordering_string) = _search_tuple(request, Task)
1054 queryset_all = Task.objects.filter(build=build_id).exclude(order__isnull=True).exclude(outcome=Task.OUTCOME_NA)
1055 queryset_all = queryset_all.select_related("recipe", "build")
1056
1057 queryset_with_search = _get_queryset(Task, queryset_all, None , search_term, ordering_string, 'order')
1058
1059 if ordering_string.startswith('outcome'):
1060 queryset = _get_queryset(Task, queryset_all, filter_string, search_term, 'order:+', 'order')
1061 queryset = sorted(queryset, key=lambda ur: (ur.outcome_text), reverse=ordering_string.endswith('-'))
1062 elif ordering_string.startswith('sstate_result'):
1063 queryset = _get_queryset(Task, queryset_all, filter_string, search_term, 'order:+', 'order')
1064 queryset = sorted(queryset, key=lambda ur: (ur.sstate_text), reverse=ordering_string.endswith('-'))
1065 else:
1066 queryset = _get_queryset(Task, queryset_all, filter_string, search_term, ordering_string, 'order')
1067
1068
1069 # compute the anchor's page
1070 if anchor:
1071 request.GET = request.GET.copy()
1072 del request.GET['anchor']
1073 i=0
1074 a=int(anchor)
1075 count_per_page=int(pagesize)
1076 for task_object in queryset.iterator():
1077 if a == task_object.order:
1078 new_page= (i / count_per_page ) + 1
1079 request.GET.__setitem__('page', new_page)
1080 mandatory_parameters['page']=new_page
1081 return _redirect_parameters( variant, request.GET, mandatory_parameters, build_id = build_id)
1082 i += 1
1083
1084 task_objects = _build_page_range(Paginator(queryset, pagesize),request.GET.get('page', 1))
1085
1086 # define (and modify by variants) the 'tablecols' members
1087 tc_order={
1088 'name':'Order',
1089 'qhelp':'The running sequence of each task in the build',
1090 'clclass': 'order', 'hidden' : 1,
1091 'orderkey' : 'order',
1092 'orderfield':_get_toggle_order(request, "order"),
1093 'ordericon':_get_toggle_order_icon(request, "order")}
1094 if 'tasks' == variant:
1095 tc_order['hidden']='0'
1096 del tc_order['clclass']
1097
1098 tc_recipe={
1099 'name':'Recipe',
1100 'qhelp':'The name of the recipe to which each task applies',
1101 'orderkey' : 'recipe__name',
1102 'orderfield': _get_toggle_order(request, "recipe__name"),
1103 'ordericon':_get_toggle_order_icon(request, "recipe__name"),
1104 }
1105 tc_recipe_version={
1106 'name':'Recipe version',
1107 'qhelp':'The version of the recipe to which each task applies',
1108 'clclass': 'recipe_version', 'hidden' : 1,
1109 }
1110 tc_task={
1111 'name':'Task',
1112 'qhelp':'The name of the task',
1113 'orderfield': _get_toggle_order(request, "task_name"),
1114 'ordericon':_get_toggle_order_icon(request, "task_name"),
1115 'orderkey' : 'task_name',
1116 }
1117 tc_executed={
1118 'name':'Executed',
1119 'qhelp':"This value tells you if a task had to run (executed) in order to generate the task output, or if the output was provided by another task and therefore the task didn't need to run (not executed)",
1120 'clclass': 'executed', 'hidden' : 0,
1121 'orderfield': _get_toggle_order(request, "task_executed"),
1122 'ordericon':_get_toggle_order_icon(request, "task_executed"),
1123 'orderkey' : 'task_executed',
1124 'filter' : {
1125 'class' : 'executed',
1126 'label': 'Show:',
1127 'options' : [
1128 ('Executed Tasks', 'task_executed:1', queryset_with_search.filter(task_executed=1).count()),
1129 ('Not Executed Tasks', 'task_executed:0', queryset_with_search.filter(task_executed=0).count()),
1130 ]
1131 }
1132
1133 }
1134 tc_outcome={
1135 'name':'Outcome',
1136 'qhelp':"This column tells you if 'executed' tasks succeeded or failed. The column also tells you why 'not executed' tasks did not need to run",
1137 'clclass': 'outcome', 'hidden' : 0,
1138 'orderfield': _get_toggle_order(request, "outcome"),
1139 'ordericon':_get_toggle_order_icon(request, "outcome"),
1140 'orderkey' : 'outcome',
1141 'filter' : {
1142 'class' : 'outcome',
1143 'label': 'Show:',
1144 'options' : [
1145 ('Succeeded Tasks', 'outcome:%d'%Task.OUTCOME_SUCCESS, queryset_with_search.filter(outcome=Task.OUTCOME_SUCCESS).count(), "'Succeeded' tasks are those that ran and completed during the build" ),
1146 ('Failed Tasks', 'outcome:%d'%Task.OUTCOME_FAILED, queryset_with_search.filter(outcome=Task.OUTCOME_FAILED).count(), "'Failed' tasks are those that ran but did not complete during the build"),
1147 ('Cached Tasks', 'outcome:%d'%Task.OUTCOME_CACHED, queryset_with_search.filter(outcome=Task.OUTCOME_CACHED).count(), 'Cached tasks restore output from the <code>sstate-cache</code> directory or mirrors'),
1148 ('Prebuilt Tasks', 'outcome:%d'%Task.OUTCOME_PREBUILT, queryset_with_search.filter(outcome=Task.OUTCOME_PREBUILT).count(),'Prebuilt tasks didn\'t need to run because their output was reused from a previous build'),
1149 ('Covered Tasks', 'outcome:%d'%Task.OUTCOME_COVERED, queryset_with_search.filter(outcome=Task.OUTCOME_COVERED).count(), 'Covered tasks didn\'t need to run because their output is provided by another task in this build'),
1150 ('Empty Tasks', 'outcome:%d'%Task.OUTCOME_EMPTY, queryset_with_search.filter(outcome=Task.OUTCOME_EMPTY).count(), 'Empty tasks have no executable content'),
1151 ]
1152 }
1153
1154 }
1155
1156 tc_cache={
1157 'name':'Cache attempt',
1158 'qhelp':'This column tells you if a task tried to restore output from the <code>sstate-cache</code> directory or mirrors, and reports the result: Succeeded, Failed or File not in cache',
1159 'clclass': 'cache_attempt', 'hidden' : 0,
1160 'orderfield': _get_toggle_order(request, "sstate_result"),
1161 'ordericon':_get_toggle_order_icon(request, "sstate_result"),
1162 'orderkey' : 'sstate_result',
1163 'filter' : {
1164 'class' : 'cache_attempt',
1165 'label': 'Show:',
1166 'options' : [
1167 ('Tasks with cache attempts', 'sstate_result__gt:%d'%Task.SSTATE_NA, queryset_with_search.filter(sstate_result__gt=Task.SSTATE_NA).count(), 'Show all tasks that tried to restore ouput from the <code>sstate-cache</code> directory or mirrors'),
1168 ("Tasks with 'File not in cache' attempts", 'sstate_result:%d'%Task.SSTATE_MISS, queryset_with_search.filter(sstate_result=Task.SSTATE_MISS).count(), 'Show tasks that tried to restore output, but did not find it in the <code>sstate-cache</code> directory or mirrors'),
1169 ("Tasks with 'Failed' cache attempts", 'sstate_result:%d'%Task.SSTATE_FAILED, queryset_with_search.filter(sstate_result=Task.SSTATE_FAILED).count(), 'Show tasks that found the required output in the <code>sstate-cache</code> directory or mirrors, but could not restore it'),
1170 ("Tasks with 'Succeeded' cache attempts", 'sstate_result:%d'%Task.SSTATE_RESTORED, queryset_with_search.filter(sstate_result=Task.SSTATE_RESTORED).count(), 'Show tasks that successfully restored the required output from the <code>sstate-cache</code> directory or mirrors'),
1171 ]
1172 }
1173
1174 }
1175 #if 'tasks' == variant: tc_cache['hidden']='0';
1176 tc_time={
1177 'name':'Time (secs)',
1178 'qhelp':'How long it took the task to finish in seconds',
1179 'orderfield': _get_toggle_order(request, "elapsed_time", True),
1180 'ordericon':_get_toggle_order_icon(request, "elapsed_time"),
1181 'orderkey' : 'elapsed_time',
1182 'clclass': 'time_taken', 'hidden' : 1,
1183 }
1184 if 'buildtime' == variant:
1185 tc_time['hidden']='0'
1186 del tc_time['clclass']
1187 tc_cache['hidden']='1'
1188
1189 tc_cpu_time_system={
1190 'name':'System CPU time (secs)',
1191 'qhelp':'Total amount of time spent executing in kernel mode, in ' +
1192 'seconds. Note that this time can be greater than the task ' +
1193 'time due to parallel execution.',
1194 'orderfield': _get_toggle_order(request, "cpu_time_system", True),
1195 'ordericon':_get_toggle_order_icon(request, "cpu_time_system"),
1196 'orderkey' : 'cpu_time_system',
1197 'clclass': 'cpu_time_system', 'hidden' : 1,
1198 }
1199
1200 tc_cpu_time_user={
1201 'name':'User CPU time (secs)',
1202 'qhelp':'Total amount of time spent executing in user mode, in seconds. ' +
1203 'Note that this time can be greater than the task time due to ' +
1204 'parallel execution.',
1205 'orderfield': _get_toggle_order(request, "cpu_time_user", True),
1206 'ordericon':_get_toggle_order_icon(request, "cpu_time_user"),
1207 'orderkey' : 'cpu_time_user',
1208 'clclass': 'cpu_time_user', 'hidden' : 1,
1209 }
1210
1211 if 'cputime' == variant:
1212 tc_cpu_time_system['hidden']='0'
1213 tc_cpu_time_user['hidden']='0'
1214 del tc_cpu_time_system['clclass']
1215 del tc_cpu_time_user['clclass']
1216 tc_cache['hidden']='1'
1217
1218 tc_diskio={
1219 'name':'Disk I/O (bytes)',
1220 'qhelp':'Number of bytes written to and read from the disk during the task',
1221 'orderfield': _get_toggle_order(request, "disk_io", True),
1222 'ordericon':_get_toggle_order_icon(request, "disk_io"),
1223 'orderkey' : 'disk_io',
1224 'clclass': 'disk_io', 'hidden' : 1,
1225 }
1226 if 'diskio' == variant:
1227 tc_diskio['hidden']='0'
1228 del tc_diskio['clclass']
1229 tc_cache['hidden']='1'
1230
1231 build = Build.objects.get(pk=build_id)
1232
1233 context = { 'objectname': variant,
1234 'object_search_display': object_search_display,
1235 'filter_search_display': filter_search_display,
1236 'mainheading': title_variant,
1237 'build': build,
1238 'project': build.project,
1239 'objects': task_objects,
1240 'default_orderby' : default_orderby,
1241 'search_term': search_term,
1242 'total_count': queryset_with_search.count(),
1243 'tablecols':[
1244 tc_order,
1245 tc_recipe,
1246 tc_recipe_version,
1247 tc_task,
1248 tc_executed,
1249 tc_outcome,
1250 tc_cache,
1251 tc_time,
1252 tc_cpu_time_system,
1253 tc_cpu_time_user,
1254 tc_diskio,
1255 ]}
1256
1257
1258 response = render(request, template, context)
1259 _set_parameters_values(pagesize, orderby, request)
1260 return response
1261
1262def tasks(request, build_id):
1263 return tasks_common(request, build_id, 'tasks', '')
1264
1265def tasks_task(request, build_id, task_id):
1266 return tasks_common(request, build_id, 'tasks', task_id)
1267
1268def buildtime(request, build_id):
1269 return tasks_common(request, build_id, 'buildtime', '')
1270
1271def diskio(request, build_id):
1272 return tasks_common(request, build_id, 'diskio', '')
1273
1274def cputime(request, build_id):
1275 return tasks_common(request, build_id, 'cputime', '')
1276
1277def configuration(request, build_id): 999def configuration(request, build_id):
1278 template = 'configuration.html' 1000 template = 'configuration.html'
1279 1001