Commit 6eadfc62 authored by Rémi Duraffort's avatar Rémi Duraffort Committed by Rémi Duraffort

List Infrastructure, Bug and Configuration errors

Add an index on TestCase results to improve sql queries speed.
Add links to Recent job errors and Maintenance devices to
job table and device table templates.

Change-Id: Ib6e67b25bf8ae88e20f03ed73230ea7a752f3e71
parent 1481ac98
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-01-17 09:21
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('lava_results_app', '0014_xaxis_maxlength_increase'),
]
operations = [
migrations.AlterField(
model_name='testcase',
name='result',
field=models.PositiveSmallIntegerField(choices=[(0, 'Test passed'), (1, 'Test failed'), (2, 'Test skipped'), (3, 'Unknown outcome')], db_index=True, help_text='Result classification to pass/fail group', verbose_name='Result'),
),
]
......@@ -370,7 +370,8 @@ class TestCase(models.Model, Queryable):
result = models.PositiveSmallIntegerField(
verbose_name=_(u"Result"),
help_text=_(u"Result classification to pass/fail group"),
choices=RESULT_CHOICES
choices=RESULT_CHOICES,
db_index=True
)
measurement = models.DecimalField(
......
......@@ -14,6 +14,7 @@ from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.timesince import timesince
import django_tables2 as tables
from lava_results_app.models import TestCase
from lava_scheduler_app.models import (
TestJob,
Device,
......@@ -141,6 +142,49 @@ def all_jobs_with_custom_sort():
return jobs.order_by('-submit_time')
class JobErrorsTable(LavaTable):
def __init__(self, *args, **kwargs):
super(LavaTable, self).__init__(*args, **kwargs)
self.length = 10
job = tables.Column(verbose_name="Job", empty_values=[""])
job.orderable = False
device = tables.Column(empty_values=[""])
device.orderable = False
error_type = tables.Column(empty_values=[""])
error_type.orderable = False
error_msg = tables.Column(empty_values=[""])
error_msg.orderable = False
def render_device(self, record):
if record.suite.job.actual_device is None:
return ""
else:
return mark_safe(
'<a href="%s" title="device details">%s</a>' % (
record.suite.job.actual_device.get_absolute_url(),
escape(record.suite.job.actual_device.hostname)))
def render_error_type(self, record):
return record.action_metadata["error_type"]
def render_error_msg(self, record):
return record.action_metadata["error_msg"]
def render_job(self, record):
return mark_safe('<a href="%s">%s</a>' % (record.suite.job.get_absolute_url(), record.suite.job.pk))
class Meta(LavaTable.Meta):
model = TestCase
fields = (
'job', 'device', 'error_type', 'error_msg',
)
sequence = (
'job', 'device', 'error_type', 'error_msg',
)
class JobTable(LavaTable):
"""
Common table for the TestJob model.
......
......@@ -13,6 +13,8 @@
<a href="{% url 'lava.scheduler.queue' %}">Queued Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-heart">
<a href="{% url 'lava.scheduler.healthcheck' %}">Healthcheck Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-flag">
<a href="{% url 'lava.scheduler.job.errors' %}">Job Errors</a></span></li>
</ul>
{% render_table active_jobs_table %}
......
......@@ -12,6 +12,8 @@
<a href="{% url 'lava.scheduler.active_devices' %}">Active Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-check">
<a href="{% url 'lava.scheduler.online_devices' %}">Online Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-wrench">
<a href="{% url 'lava.scheduler.maintenance_devices' %}">Maintenance Devices</a></span></li>
</ul>
{% render_table active_devices_table %}
......
......@@ -12,6 +12,8 @@
<a href="{% url 'lava.scheduler.active_devices' %}">Active Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-check">
<a href="{% url 'lava.scheduler.online_devices' %}">Online Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-wrench">
<a href="{% url 'lava.scheduler.maintenance_devices' %}">Maintenance Devices</a></span></li>
</ul>
{% render_table devices_table %}
......
......@@ -14,6 +14,8 @@
<a href="{% url 'lava.scheduler.queue' %}">Queued Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-heart">
<a href="{% url 'lava.scheduler.healthcheck' %}">Healthcheck Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-flag">
<a href="{% url 'lava.scheduler.job.errors' %}">Job Errors</a></span></li>
</ul>
{% render_table alljobs_table %}
......
......@@ -14,6 +14,8 @@
<a href="{% url 'lava.scheduler.queue' %}">Queued Jobs</a></span></li>
<li class="btn btn-sm disabled"><span class="glyphicon glyphicon-heart">
<a href="{% url 'lava.scheduler.healthcheck' %}">Healthcheck Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-flag">
<a href="{% url 'lava.scheduler.job.errors' %}">Job Errors</a></span></li>
</ul>
{% render_table health_check_table %}
......
......@@ -42,6 +42,8 @@
</span>Running test jobs
</a>
</li>
<li><a href="{% url 'lava.scheduler.reports' %}"><span
class="glyphicon glyphicon-stats pull-right"></span> Reports</a></li>
</ul>
</div>
<div class="col-md-4">
......@@ -53,6 +55,8 @@
class="glyphicon glyphicon-phone pull-right green"></span> Active Devices</a></li>
<li><a href="{% url 'lava.scheduler.labhealth' %}"><span
class="glyphicon glyphicon-heart pull-right"></span> Devices Health</a></li>
<li><a href="{% url 'lava.scheduler.maintenance_devices' %}"><span
class="glyphicon glyphicon-wrench pull-right"></span> Maintenance Devices</a></li>
</ul>
</div>
<div class="col-md-4">
......@@ -64,6 +68,8 @@
class="glyphicon glyphicon-pause pull-right grey"></span>Queued Jobs</a></li>
<li><a href="{% url 'lava.scheduler.job.active' %}"><span
class="glyphicon glyphicon-play pull-right grey"></span>Active Jobs</a></li>
<li><a href="{% url 'lava.scheduler.job.errors' %}"><span
class="glyphicon glyphicon-flag pull-right grey"></span>Recent Job Errors</a></li>
</ul>
</div>
</div>
......
{% extends "layouts/content.html" %}
{% load django_tables2 %}
{% block content %}
<h2>Recent job errors</h2>
<ul class="pager">
<li class="btn btn-sm"><span class="glyphicon glyphicon-asterisk">
<a href="{% url 'lava.scheduler.job.list' %}">All Jobs</a></span></li>
<li class="btn btn-sm disabled"><span class="glyphicon glyphicon-play">
<a href="{% url 'lava.scheduler.job.active' %}">Active Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-pause">
<a href="{% url 'lava.scheduler.queue' %}">Queued Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-heart">
<a href="{% url 'lava.scheduler.healthcheck' %}">Healthcheck Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-flag">
<a href="{% url 'lava.scheduler.job.errors' %}">Job Errors</a></span></li>
</ul>
{% render_table job_errors_table %}
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="{{ STATIC_URL }}lava_scheduler_app/js/tables.min.js"></script>
{% endblock %}
{% extends "layouts/content.html" %}
{% load django_tables2 %}
{% block content %}
<h2>Maintenance Devices</small></h2>
<ul class="pager">
<li class="btn btn-sm"><span class="glyphicon glyphicon-move">
<a href="{% url 'lava.scheduler.alldevices' %}">All Devices</a></span></li>
<li class="btn btn-sm disabled"><span class="glyphicon glyphicon-play">
<a href="{% url 'lava.scheduler.active_devices' %}">Active Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-check">
<a href="{% url 'lava.scheduler.online_devices' %}">Online Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-wrench">
<a href="{% url 'lava.scheduler.maintenance_devices' %}">Maintenance Devices</a></span></li>
</ul>
{% render_table maintenance_devices_table %}
{% endblock %}
{% block scripts %}
<script type="text/javascript" src="{{ STATIC_URL }}lava_scheduler_app/js/tables.min.js"></script>
{% endblock %}
......@@ -12,6 +12,8 @@
<a href="{% url 'lava.scheduler.active_devices' %}">Active Devices</a></span></li>
<li class="btn btn-sm disabled"><span class="glyphicon glyphicon-check">
<a href="{% url 'lava.scheduler.online_devices' %}">Online Devices</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-wrench">
<a href="{% url 'lava.scheduler.maintenance_devices' %}">Maintenance Devices</a></span></li>
</ul>
{% render_table online_devices_table %}
......
......@@ -13,6 +13,8 @@
<a href="{% url 'lava.scheduler.queue' %}">Queued Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-heart">
<a href="{% url 'lava.scheduler.healthcheck' %}">Healthcheck Jobs</a></span></li>
<li class="btn btn-sm"><span class="glyphicon glyphicon-flag">
<a href="{% url 'lava.scheduler.job.errors' %}">Job Errors</a></span></li>
</ul>
<h3>TestJobs in state 'submitted'</h3>
......
......@@ -7,13 +7,13 @@ from lava_scheduler_app.views import (
device_type_health_history_log,
mydevices_health_history_log, device_list, device_reports,
device_restrict_device, device_type_detail, device_dictionary,
device_dictionary_plain,
device_dictionary_plain, maintenance_devices,
device_type_reports, edit_worker_desc,
failure_report, favorite_jobs,
get_remote_definition, health_job_list, healthcheck, index,
job_annotate_failure, job_cancel, job_fail, job_change_priority, job_complete_log,
job_definition, job_definition_plain, job_description_yaml, job_detail,
job_list, job_configuration,
job_list, job_configuration, job_errors,
job_log_file_plain, job_log_pipeline_incremental,
job_pipeline_timing, job_resubmit, job_section_log, job_status,
job_submit, job_toggle_favorite, lab_health,
......@@ -32,6 +32,7 @@ urlpatterns = [
url(r'^edit_worker_desc', edit_worker_desc, name='lava.scheduler.edit_worker_desc'),
url(r'^activejobs$', active_jobs, name='lava.scheduler.job.active'),
url(r'^alljobs$', job_list, name='lava.scheduler.job.list'),
url(r'joberrors$', job_errors, name='lava.scheduler.job.errors'),
url(r'^jobsubmit$', job_submit, name='lava.scheduler.job.submit'),
url(r'^device_type/(?P<pk>[-_a-zA-Z0-9]+)$', device_type_detail,
name='lava.scheduler.device_type.detail'),
......@@ -120,6 +121,8 @@ urlpatterns = [
name='lava.scheduler.online_devices'),
url(r'^alldevices/passinghealthchecks$', passing_health_checks,
name='lava.scheduler.passing_health_checks'),
url(r'^alldevices/maintenance$', maintenance_devices,
name='lava.scheduler.maintenance_devices'),
url(r'^reports/device/(?P<pk>[-_a-zA-Z0-9.]+)', device_reports,
name='lava.scheduler.device_report'),
url(r'^reports/device_type/(?P<pk>[-_a-zA-Z0-9]+)', device_type_reports,
......
......@@ -88,6 +88,7 @@ from lava_results_app.models import (
from django.contrib.auth.models import User, Group
from lava_scheduler_app.tables import (
JobErrorsTable,
JobTable,
all_jobs_with_custom_sort,
IndexJobTable,
......@@ -321,10 +322,19 @@ class DeviceTableView(JobTableView):
.order_by("hostname")
class JobErrorsView(LavaView):
def get_queryset(self):
q = TestCase.objects.filter(suite__name="lava", result=TestCase.RESULT_FAIL)
q = q.filter(metadata__regex="error_type: (Configuration|Infrastructure|Bug)")
q = q.select_related("suite", "suite__job__actual_device")
return q.order_by('-suite__job__id')
@BreadCrumb("Scheduler", parent=lava_index)
def index(request):
data = DeviceTypeOverView(request, model=DeviceType, table_class=DeviceTypeTable)
ptable = DeviceTypeTable(data.get_table_data())
ptable = DeviceTypeTable(data.get_table_data(), prefix="device_type_")
RequestConfig(request, paginate={"per_page": ptable.length}).configure(ptable)
(num_online, num_not_retired) = _online_total()
......@@ -335,6 +345,7 @@ def index(request):
state=TestJob.STATE_RUNNING, actual_device__isnull=False).count()
active_devices_count = Device.objects.filter(
state__in=[Device.STATE_RESERVED, Device.STATE_RUNNING]).count()
return render(
request,
"lava_scheduler_app/index.html",
......@@ -641,6 +652,12 @@ class ActiveDeviceView(DeviceTableView):
return q.exclude(health=Device.HEALTH_RETIRED)
class MaintenanceDeviceView(DeviceTableView):
def get_queryset(self):
return super(MaintenanceDeviceView, self).get_queryset().filter(health=Device.HEALTH_MAINTENANCE)
class DeviceHealthView(DeviceTableView):
def get_queryset(self):
......@@ -662,6 +679,24 @@ class NoDTDeviceView(DeviceTableView):
return Device.objects.exclude(health=Device.HEALTH_RETIRED).order_by('hostname')
@BreadCrumb("Maintenance", parent=device_list)
def maintenance_devices(request):
data = MaintenanceDeviceView(request, model=Device, table_class=DeviceTable)
ptable = DeviceTable(data.get_table_data())
RequestConfig(request, paginate={"per_page": ptable.length}).configure(ptable)
template = loader.get_template("lava_scheduler_app/maintenance_devices.html")
return HttpResponse(template.render(
{
'maintenance_devices_table': ptable,
"length": ptable.length,
"terms_data": ptable.prepare_terms_data(data),
"search_data": ptable.prepare_search_data(data),
"discrete_data": ptable.prepare_discrete_data(data),
'bread_crumb_trail': BreadCrumbTrail.leading_to(active_device_list),
},
request=request))
@BreadCrumb("Device Type {pk}", parent=index, needs=['pk'])
def device_type_detail(request, pk):
try:
......@@ -974,6 +1009,25 @@ def job_list(request):
request=request))
@BreadCrumb("Errors", parent=job_list)
def job_errors(request):
data = JobErrorsView(request, model=TestCase, table_class=JobErrorsTable)
ptable = JobErrorsTable(data.get_table_data(), prefix="job_errors_")
RequestConfig(request, paginate={"per_page": ptable.length}).configure(ptable)
return render(
request,
"lava_scheduler_app/job_errors.html",
{
'job_errors_table': ptable,
"sort": '-submit_time',
"terms_data": ptable.prepare_terms_data(data),
"search_data": ptable.prepare_search_data(data),
"discrete_data": ptable.prepare_discrete_data(data),
"times_data": ptable.prepare_times_data(data),
'bread_crumb_trail': BreadCrumbTrail.leading_to(job_errors),
})
@BreadCrumb("Active", parent=job_list)
def active_jobs(request):
data = IndexTableView(request, model=TestJob, table_class=IndexJobTable)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment