...
 
Commits (3)
......@@ -24,6 +24,7 @@ tags:
{% set available_features = {
"deploy.tftp": {"name": "deploy.tftp", "type": "device", "description": "Deploy to tftp", "action": "deploy"},
"deploy.tmpfs": {"name": "deploy.tmpfs", "type": "device", "description": "Deploy to tmpfs", "action": "deploy"},
"boot.bootloader.u-boot": {"name": "boot.bootloader.u-boot", "type": "device", "description": "Boot to u-boot", "action": "boot"},
"boot.grub.ramdisk": {"name": "boot.grub.ramdisk", "type": "device", "description": "Boot from grub with a ramdisk", "action": "boot"},
"boot.ipxe.ramdisk": {"name": "boot.ipxe.ramdisk", "type": "device", "description": "Boot from ipxe with a ramdisk", "action": "boot"},
"boot.kexec": {"name": "boot.kexec", "type": "device", "description": "Boot after a kexec call", "action": "boot"},
......@@ -32,6 +33,7 @@ tags:
"boot.u-boot.ramdisk": {"name": "boot.u-boot.ramdisk", "type": "device", "description": "Boot from u-boot with a ramdisk", "action": "boot"},
"test.definition.git": {"name": "test.definition.git", "type": "device", "description": "Test definition from git", "action": "test"},
"test.definition.inline": {"name": "test.definition.inline", "type": "device", "description": "Inline test definition", "action": "test"},
"test.interactive": {"name": "test.interactive", "type": "device", "description": "Interactive test", "action": "test"},
"master-slave": {"name": "master-slave", "type": "generic", "description": "master-slave protocol", "action": "None"},
} -%}
......
......@@ -35,13 +35,16 @@
<h1 class="jumbotron-heading">Welcome to LAVA Federation</h1>
<p class="lead text-muted">LAVA Federation is a project aiming at testing the LAVA software on community owned hardware. The tests are spread across many labs with a variety of hardware.</p>
</div>
<div>
<a href="{% url "versions.show_latest" %}"><img alt="latest version badge" src="{% url "versions.badge_latest" %}"></a>
</div>
</section>
<div class="row">
<div class="col">
<h3>Versions</h3>
<p>LAVA Fedederation is aiming at testing every versions of LAVA, including developement versions. For each version, a badge is available to know the overall status.</p>
<p><a class="btn btn-primary my-2" href="{% url "versions" %}">Versions</a></p>
<h3>Device-Types</h3>
<p>LAVA Federation is trying to test as many device-types as possible. We are however limited by the available hardware. If your prefered hardware is not tested, you should participate.</p>
<p><a class="btn btn-primary my-2" href="{% url "device_types" %}">Device-Types</a></p>
</div>
<div class="col">
<h3>Labs</h3>
......@@ -49,9 +52,9 @@
<p><a class="btn btn-primary my-2" href="{% url "labs" %}">Labs</a></p>
</div>
<div class="col">
<h3>Device-Types</h3>
<p>LAVA Federation is trying to test as many device-types as possible. We are however limited by the available hardware. If your prefered hardware is not tested, you should participate.</p>
<p><a class="btn btn-primary my-2" href="{% url "device_types" %}">Device-Types</a></p>
<h3>Versions</h3>
<p>LAVA Fedederation is aiming at testing every versions of LAVA, including developement versions. For each version, a badge is available to know the overall status.</p>
<p><a class="btn btn-primary my-2" href="{% url "versions" %}">Versions</a></p>
</div>
</div>
{% endblock %}
......@@ -38,7 +38,16 @@ urlpatterns = [
url(r"^labs/$", v.labs, name="labs"),
url(r"^labs/(?P<lab>[^/]+)/$", v.lab_show, name="labs.show"),
url(r"^versions/$", v.versions, name="versions"),
url(r"^versions/latest/$", v.version_show_latest, name="versions.show_latest"),
url(r"^versions/(?P<version>[^/]+)/$", v.version_show, name="versions.show"),
url(
r"^versions/latest/badge/$",
v.version_badge_latest,
name="versions.badge_latest",
),
url(
r"^versions/(?P<version>[^/]+)/badge/$", v.version_badge, name="versions.badge"
),
url(r"^api/v0.1/jobs/$", v.api_v0_1_jobs, name="api.v0.1.jobs"),
url(
r"^api/v0.1/versions/(?P<version>[^/]+)/$",
......
......@@ -18,6 +18,7 @@
# along with lavafed. If not, see <http://www.gnu.org/licenses/>
import json
import svgwrite
import yaml
from django.db.models import Case, Count, IntegerField, Sum, When
......@@ -26,9 +27,12 @@ from django.http import (
HttpResponse,
HttpResponseBadRequest,
HttpResponseForbidden,
HttpResponseNotFound,
HttpResponseRedirect,
JsonResponse,
)
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_GET, require_POST
......@@ -301,3 +305,155 @@ def version_show(request, version):
"version": version,
},
)
def version_show_latest(request):
try:
version = Version.objects.order_by("version").last()
return HttpResponseRedirect(reverse("versions.show", args=[version.version]))
except Version.DoesNotExist:
return HttpResponseNotFound("No Version matches the given query.")
def version_badge(request, version):
version = get_object_or_404(Version, version=version)
jobs = version.job_set.all()
jobs = jobs.aggregate(
success=Sum(
Case(
When(health=Job.HEALTH_COMPLETE, then=1),
default=0,
output_field=IntegerField(),
)
),
failure=Sum(
Case(
When(
health__in=[
Job.HEALTH_UNKNOWN,
Job.HEALTH_INCOMPLETE,
Job.HEALTH_CANCELED,
],
then=1,
),
default=0,
output_field=IntegerField(),
)
),
)
success = jobs["success"]
failure = jobs["failure"]
ratio = success / (success + failure) * 100
title_text = version.version
badge_text = "%d%%" % ratio
if ratio == 100:
badge_colour = "#5cb85c"
elif ratio >= 80:
badge_colour = "#f0ad4e"
else:
badge_colour = "#d9534f"
font_size = 110
character_width = font_size / 2
padding_width = character_width
title_width = len(title_text) * character_width + 2 * padding_width
title_x = title_width / 2 + padding_width
badge_width = len(badge_text) * character_width + 50
badge_x = badge_width / 2 + 3 * padding_width + title_width
total_width = (title_width + badge_width + 4 * padding_width) / 10
dwg = svgwrite.Drawing("version_badge.svg", (total_width, 20))
a = dwg.add(dwg.clipPath())
a.add(dwg.rect(rx=3, size=(total_width, 20), fill="#fff"))
b = dwg.add(dwg.linearGradient(end=(0, 1), id="b"))
b.add_stop_color(0, "#bbb", 0.1)
b.add_stop_color(1, None, 0.1)
g1 = dwg.add(dwg.g(clip_path=a.get_funciri()))
g1.add(
dwg.path(
fill="#555",
d=[
"M0",
"0h",
"%sv" % ((2 * padding_width + title_width) / 10),
"20H",
"0z",
],
)
)
g1.add(
dwg.path(
fill=badge_colour,
d=[
"M%s" % ((2 * padding_width + title_width) / 10),
"0h",
"%sv" % ((2 * padding_width + badge_width) / 10),
"20H",
"%sz" % ((2 * padding_width + title_width) / 10),
],
)
)
g1.add(
dwg.path(fill=b.get_funciri(), d=["M0", "0h", "%sv" % total_width, "20H", "0z"])
)
g2 = dwg.add(
dwg.g(
fill="#fff",
text_anchor="middle",
font_family="monospace",
font_size=font_size,
)
)
g2.add(
dwg.text(
title_text,
x=[title_x],
y=[150],
fill="#010101",
fill_opacity=".3",
transform="scale(.1)",
textLength=title_width,
)
)
g2.add(
dwg.text(
title_text,
x=[title_x],
y=[140],
transform="scale(.1)",
textLength=title_width,
)
)
g2.add(
dwg.text(
badge_text,
x=[badge_x],
y=[150],
fill="#010101",
fill_opacity=".3",
transform="scale(.1)",
textLength=badge_width,
)
)
g2.add(
dwg.text(
badge_text,
x=[badge_x],
y=[140],
transform="scale(.1)",
textLength=badge_width,
)
)
badge = dwg.tostring()
return HttpResponse(badge, content_type="image/svg+xml")
def version_badge_latest(request):
try:
version = Version.objects.order_by("version").last()
return HttpResponseRedirect(reverse("versions.badge", args=[version.version]))
except Version.DoesNotExist:
return HttpResponseNotFound("No Version matches the given query.")