diff options
Diffstat (limited to 'tools/pharos-dashboard')
14 files changed, 275 insertions, 213 deletions
diff --git a/tools/pharos-dashboard/dashboard/admin.py b/tools/pharos-dashboard/dashboard/admin.py index 990e63e8..71a1e7d2 100644 --- a/tools/pharos-dashboard/dashboard/admin.py +++ b/tools/pharos-dashboard/dashboard/admin.py @@ -1,5 +1,6 @@ from django.contrib import admin -from dashboard.models import Resource +from dashboard.models import * admin.site.register(Resource) +admin.site.register(Server) diff --git a/tools/pharos-dashboard/dashboard/models.py b/tools/pharos-dashboard/dashboard/models.py index 971af6a2..d645cd55 100644 --- a/tools/pharos-dashboard/dashboard/models.py +++ b/tools/pharos-dashboard/dashboard/models.py @@ -1,6 +1,5 @@ from django.contrib.auth.models import User from django.db import models -from django.utils import timezone from jenkins.models import JenkinsSlave @@ -17,4 +16,20 @@ class Resource(models.Model): db_table = 'resource' def __str__(self): - return self.name
\ No newline at end of file + return self.name + + +class Server(models.Model): + id = models.AutoField(primary_key=True) + resource = models.ForeignKey(Resource, on_delete=models.CASCADE) + name = models.CharField(max_length=100, blank=True) + model = models.CharField(max_length=100, blank=True) + cpu = models.CharField(max_length=100, blank=True) + ram = models.CharField(max_length=100, blank=True) + storage = models.CharField(max_length=100, blank=True) + + class Meta: + db_table = 'server' + + def __str__(self): + return self.name diff --git a/tools/pharos-dashboard/dashboard/templatetags/jenkins_filters.py b/tools/pharos-dashboard/dashboard/templatetags/jenkins_filters.py index f7e00a87..f5038ea5 100644 --- a/tools/pharos-dashboard/dashboard/templatetags/jenkins_filters.py +++ b/tools/pharos-dashboard/dashboard/templatetags/jenkins_filters.py @@ -9,7 +9,7 @@ def jenkins_job_color(job_result): return '#d9534f' if job_result == 'UNSTABLE': return '#EDD62B' - return '#646F73' # job is still building + return '#646F73' # job is still building @register.filter @@ -21,7 +21,8 @@ def jenkins_status_color(slave_status): if slave_status == 'online / idle': return '#5bc0de' + @register.filter def jenkins_job_blink(job_result): - if job_result == '': # job is still building - return 'class=blink_me'
\ No newline at end of file + if job_result == '': # job is still building + return 'class=blink_me' diff --git a/tools/pharos-dashboard/dashboard/templatetags/jira_filters.py b/tools/pharos-dashboard/dashboard/templatetags/jira_filters.py new file mode 100644 index 00000000..d9c27612 --- /dev/null +++ b/tools/pharos-dashboard/dashboard/templatetags/jira_filters.py @@ -0,0 +1,8 @@ +from django.template.defaultfilters import register + +from pharos_dashboard import settings + + +@register.filter +def jira_issue_url(issue): + return settings.JIRA_URL + '/browse/' + str(issue) diff --git a/tools/pharos-dashboard/dashboard/urls.py b/tools/pharos-dashboard/dashboard/urls.py index 51d764c4..809204c1 100644 --- a/tools/pharos-dashboard/dashboard/urls.py +++ b/tools/pharos-dashboard/dashboard/urls.py @@ -21,8 +21,8 @@ urlpatterns = [ url(r'^ci_pods/$', CIPodsView.as_view(), name='ci_pods'), url(r'^dev_pods/$', DevelopmentPodsView.as_view(), name='dev_pods'), url(r'^jenkins_slaves/$', JenkinsSlavesView.as_view(), name='jenkins_slaves'), - url(r'^resource/all/', LabOwnerView.as_view(), - name='resources'), + url(r'^resource/all/$', LabOwnerView.as_view(), name='resources'), + url(r'^resource/(?P<resource_id>[0-9]+)/$', ResourceView.as_view(), name='resource'), url(r'^$', DevelopmentPodsView.as_view(), name="index"), ] diff --git a/tools/pharos-dashboard/dashboard/views.py b/tools/pharos-dashboard/dashboard/views.py index 56b3a510..ef1845c8 100644 --- a/tools/pharos-dashboard/dashboard/views.py +++ b/tools/pharos-dashboard/dashboard/views.py @@ -1,12 +1,12 @@ from datetime import timedelta -from django.contrib.auth.models import User +from django.shortcuts import get_object_or_404 from django.utils import timezone from django.views.generic import TemplateView from booking.models import Booking from dashboard.models import Resource -from jenkins.models import JenkinsSlave, JenkinsStatistic +from jenkins.models import JenkinsSlave class JenkinsSlavesView(TemplateView): @@ -51,25 +51,27 @@ class DevelopmentPodsView(TemplateView): return context +class ResourceView(TemplateView): + template_name = "dashboard/resource.html" + + def get_context_data(self, **kwargs): + resource = get_object_or_404(Resource, id=self.kwargs['resource_id']) + utilization = resource.slave.get_utilization(timedelta(days=7)) + bookings = Booking.objects.filter(resource=resource, end__gt=timezone.now()) + context = super(ResourceView, self).get_context_data(**kwargs) + context.update({'title': str(resource), 'resource': resource, 'utilization': utilization, 'bookings': bookings}) + return context + + class LabOwnerView(TemplateView): - template_name = "dashboard/lab_owner.html" + template_name = "dashboard/resource_all.html" def get_context_data(self, **kwargs): resources = Resource.objects.filter(slave__dev_pod=True) pods = [] for resource in resources: - utilization = {'idle': 0, 'online': 0, 'offline': 0} - # query measurement points for the last week - statistics = JenkinsStatistic.objects.filter(slave=resource.slave, - timestamp__gte=timezone.now() - timedelta( - days=7)) - - utilization['idle'] = statistics.filter(idle=True).count() - utilization['online'] = statistics.filter(online=True).count() - utilization['offline'] = statistics.filter(offline=True).count() - + utilization = resource.slave.get_utilization(timedelta(days=7)) bookings = Booking.objects.filter(resource=resource, end__gt=timezone.now()) - pods.append((resource, utilization, bookings)) context = super(LabOwnerView, self).get_context_data(**kwargs) context.update({'title': "Overview", 'pods': pods}) diff --git a/tools/pharos-dashboard/jenkins/models.py b/tools/pharos-dashboard/jenkins/models.py index 438a8827..354887ab 100644 --- a/tools/pharos-dashboard/jenkins/models.py +++ b/tools/pharos-dashboard/jenkins/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.utils import timezone class JenkinsSlave(models.Model): @@ -18,6 +19,18 @@ class JenkinsSlave(models.Model): last_job_installer = models.CharField(max_length=50, default='') last_job_result = models.CharField(max_length=30, default='') + def get_utilization(self, timedelta): + """ + Return a dictionary containing the count of idle, online and offline measurements in the time from + now-timedelta to now + """ + utilization = {'idle': 0, 'online': 0, 'offline': 0} + statistics = self.jenkinsstatistic_set.filter(timestamp__gte=timezone.now() - timedelta) + utilization['idle'] = statistics.filter(idle=True).count() + utilization['online'] = statistics.filter(online=True).count() + utilization['offline'] = statistics.filter(offline=True).count() + return utilization + class Meta: db_table = 'jenkins_slave' diff --git a/tools/pharos-dashboard/templates/booking/booking_table.html b/tools/pharos-dashboard/templates/booking/booking_table.html new file mode 100644 index 00000000..3d0b7575 --- /dev/null +++ b/tools/pharos-dashboard/templates/booking/booking_table.html @@ -0,0 +1,33 @@ +{% load jira_filters %} + + +<thead> +<tr> + <th>User</th> + <th>Purpose</th> + <th>Start</th> + <th>End</th> + <th>Jira</th> +</tr> +</thead> +<tbody> +{% for booking in bookings %} + <tr> + <th> + {{ booking.user.username }} + </th> + <th> + {{ booking.purpose }} + </th> + <th> + {{ booking.start }} + </th> + <th> + {{ booking.end }} + </th> + <th><a target='_blank' + href={{ booking.get_jira_issue | jira_issue_url }}>{{ booking.get_jira_issue }}</a> + </th> + </tr> +{% endfor %} +</tbody>
\ No newline at end of file diff --git a/tools/pharos-dashboard/templates/dashboard/dev_pods.html b/tools/pharos-dashboard/templates/dashboard/dev_pods.html index 532a3a11..9c84bb91 100644 --- a/tools/pharos-dashboard/templates/dashboard/dev_pods.html +++ b/tools/pharos-dashboard/templates/dashboard/dev_pods.html @@ -18,7 +18,7 @@ {% for pod, booking in dev_pods %} <tr> <th> - <a target='_blank' href={{ pod.url }}>{{ pod.name }}</a> + <a href={% url 'dashboard:resource' resource_id=pod.id %}>{{ pod.name }}</a> </th> <th> <a target='_blank' href={{ pod.slave.url }}>{{ pod.slave.name }}</a> diff --git a/tools/pharos-dashboard/templates/dashboard/lab_owner.html b/tools/pharos-dashboard/templates/dashboard/lab_owner.html deleted file mode 100644 index a4f428c7..00000000 --- a/tools/pharos-dashboard/templates/dashboard/lab_owner.html +++ /dev/null @@ -1,151 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - <!-- Morris Charts CSS --> - <link href="{% static "bower_components/morrisjs/morris.css" %}" rel="stylesheet"> - - <!-- DataTables CSS --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - <!-- DataTables Responsive CSS --> - <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" - rel="stylesheet"> -{% endblock extrahead %} - - -{% block content %} - {% for resource, utilization, bookings in pods %} - <div class="row"> - <div class="col-lg-3"> - <div class="panel panel-default"> - <div class="panel-heading"> - {{ resource.name }} - </div> - <div class="panel-body"> - <div class="flot-chart"> - <div class="flot-chart-content" id="{{ resource.slave.name }}"></div> - </div> - </div> - </div> - </div> - <div class="col-lg-6"> - <div class="panel panel-default"> - <div class="panel-heading"> - {{ resource.name }} Bookings - </div> - <div class="panel-body"> - <div class="dataTables_wrapper"> - <table class="table table-striped table-bordered table-hover" - id="{{ resource.slave.name }}_bookings" cellspacing="0" - width="100%"> - <thead> - <tr> - <th>User</th> - <th>Purpose</th> - <th>Start</th> - <th>End</th> - <th>Status</th> - </tr> - </thead> - <tbody> - {% for booking in bookings %} - <tr> - <th> - {{ booking.user.username }} - </th> - <th> - {{ booking.purpose }} - </th> - <th> - {{ booking.start }} - </th> - <th> - {{ booking.end }} - </th> - <th> - Jira Status - </th> - </tr> - {% endfor %}` - </tbody> - </table> - </div> - </div> - </div> - </div> - </div> - {% endfor %} - -{% endblock content %} - - -{% block extrajs %} - <!-- DataTables JavaScript --> - <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" - rel="stylesheet"> - - - <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> - <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> - - - - <!-- Flot Charts JavaScript --> - <script src="{% static "bower_components/flot/excanvas.min.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.pie.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.resize.js" %}"></script> - <script src="{% static "bower_components/flot/jquery.flot.time.js" %}"></script> - <script src="{% static "bower_components/flot.tooltip/js/jquery.flot.tooltip.min.js" %}"></script> - - <script type="text/javascript"> - $(document).ready(function () { - - - {% for resource, utilization, bookings in pods %} - $('#{{ resource.slave.name }}_bookings').DataTable({}); - - $(function () { - var data = [{ - label: "Offline", - data: {{ utilization.offline }}, - color: '#d9534f' - }, { - label: "Online", - data: {{ utilization.online }}, - color: '#5cb85c' - }, { - label: "Idle", - data: {{ utilization.idle }}, - color: '#5bc0de' - }]; - - var plotObj = $.plot($("#{{ resource.slave.name }}"), data, { - series: { - pie: { - show: true - } - }, - grid: { - hoverable: false - }, - tooltip: true, - tooltipOpts: { - content: "%p.0%, %s", // show percentages, rounding to 2 decimal places - shifts: { - x: 20, - y: 0 - }, - defaultTheme: false - } - }); - - }); - {% endfor %} - - }); - </script> - -{% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/templates/dashboard/resource.html b/tools/pharos-dashboard/templates/dashboard/resource.html new file mode 100644 index 00000000..92d02f66 --- /dev/null +++ b/tools/pharos-dashboard/templates/dashboard/resource.html @@ -0,0 +1,58 @@ +{% extends "base.html" %} +{% load staticfiles %} + +{% block extrahead %} + <!-- Morris Charts CSS --> + <link href="{% static "bower_components/morrisjs/morris.css" %}" rel="stylesheet"> + + <!-- DataTables CSS --> + <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" + rel="stylesheet"> + + <!-- DataTables Responsive CSS --> + <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" + rel="stylesheet"> +{% endblock extrahead %} + + +{% block content %} + {% include "dashboard/resource_detail.html" %} +{% endblock content %} + + +{% block extrajs %} + <!-- DataTables JavaScript --> + <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" + rel="stylesheet"> + + <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> + <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> + + + + <!-- Flot Charts JavaScript --> + <script src="{% static "bower_components/flot/excanvas.min.js" %}"></script> + <script src="{% static "bower_components/flot/jquery.flot.js" %}"></script> + <script src="{% static "bower_components/flot/jquery.flot.pie.js" %}"></script> + <script src="{% static "bower_components/flot/jquery.flot.resize.js" %}"></script> + <script src="{% static "bower_components/flot/jquery.flot.time.js" %}"></script> + <script src="{% static "bower_components/flot.tooltip/js/jquery.flot.tooltip.min.js" %}"></script> + + <script type="text/javascript"> + $(document).ready(function () { + $('#{{ resource.id }}_server_table').DataTable({}); + $('#{{ resource.id }}_bookings_table').DataTable({}); + + $(function () { + var plotObj = $.plot($("#{{ resource.id }}_slave_utilization"), data_{{ resource.id }}, { + series: { + pie: { + show: true + } + } + }); + + }); + }); + </script> +{% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/templates/dashboard/resource_utilization.html b/tools/pharos-dashboard/templates/dashboard/resource_all.html index fb483d60..2078475f 100644 --- a/tools/pharos-dashboard/templates/dashboard/resource_utilization.html +++ b/tools/pharos-dashboard/templates/dashboard/resource_all.html @@ -5,31 +5,43 @@ <!-- Morris Charts CSS --> <link href="{% static "bower_components/morrisjs/morris.css" %}" rel="stylesheet"> + <!-- DataTables CSS --> + <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" + rel="stylesheet"> + + <!-- DataTables Responsive CSS --> + <link href="{% static "bower_components/datatables-responsive/css/dataTables.responsive.css" %}" + rel="stylesheet"> {% endblock extrahead %} {% block content %} - <div class="row"> - {% for resource, utilization in pods %} - <div class="col-lg-3"> + {% for resource, utilization, bookings in pods %} + <div class="row"> + <div class="col-lg-12"> <div class="panel panel-default"> <div class="panel-heading"> {{ resource.name }} </div> <div class="panel-body"> - <div class="flot-chart"> - <div class="flot-chart-content" id="{{ resource.slave.name }}"></div> - </div> + {% include "dashboard/resource_detail.html" %} </div> </div> </div> - {% endfor %} - </div> - + </div> + {% endfor %} {% endblock content %} {% block extrajs %} + <!-- DataTables JavaScript --> + <link href="{% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.css" %}" + rel="stylesheet"> + + <script src={% static "bower_components/datatables/media/js/jquery.dataTables.min.js" %}></script> + <script src={% static "bower_components/datatables-plugins/integration/bootstrap/3/dataTables.bootstrap.min.js" %}></script> + + <!-- Flot Charts JavaScript --> <script src="{% static "bower_components/flot/excanvas.min.js" %}"></script> @@ -41,46 +53,22 @@ <script type="text/javascript"> $(document).ready(function () { - {% for resource, utilization in pods %} - $(function () { - var data = [{ - label: "Offline", - data: {{ utilization.offline }}, - color: '#d9534f' - }, { - label: "Online", - data: {{ utilization.online }}, - color: '#5cb85c' - }, { - label: "Idle", - data: {{ utilization.idle }}, - color: '#5bc0de' - }]; + {% for resource, utilization, bookings in pods %} + + $('#{{ resource.id }}_server_table').DataTable({}); + $('#{{ resource.id }}_bookings_table').DataTable({}); - var plotObj = $.plot($("#{{ resource.slave.name }}"), data, { + $(function () { + var plotObj = $.plot($("#{{ resource.id }}_slave_utilization"), data_{{ resource.id }}, { series: { pie: { show: true } - }, - grid: { - hoverable: true - }, - tooltip: true, - tooltipOpts: { - content: "%p.0%, %s", // show percentages, rounding to 2 decimal places - shifts: { - x: 20, - y: 0 - }, - defaultTheme: false } }); }); {% endfor %} - }); </script> - {% endblock extrajs %}
\ No newline at end of file diff --git a/tools/pharos-dashboard/templates/dashboard/resource_detail.html b/tools/pharos-dashboard/templates/dashboard/resource_detail.html new file mode 100644 index 00000000..4fba4766 --- /dev/null +++ b/tools/pharos-dashboard/templates/dashboard/resource_detail.html @@ -0,0 +1,64 @@ +<div class="row"> + <div class="col-lg-3"> + <div class="panel panel-default"> + <div class="panel-heading"> + Utilization + </div> + <div class="panel-body"> + <div class="flot-chart"> + <div class="flot-chart-content" id="{{ resource.id }}_slave_utilization"></div> + </div> + </div> + </div> + </div> + <div class="col-lg-9"> + <div class="panel panel-default"> + <div class="panel-heading"> + Servers + </div> + <div class="panel-body"> + <div class="dataTables_wrapper"> + <table class="table table-striped table-bordered table-hover" + id="{{ resource.id }}_server_table" cellspacing="0" + width="100%"> + {% include "dashboard/server_table.html" %} + </table> + </div> + </div> + </div> + </div> +</div> +<div class="row"> + <div class="col-lg-6"> + <div class="panel panel-default"> + <div class="panel-heading"> + Bookings + </div> + <div class="panel-body"> + <div class="dataTables_wrapper"> + <table class="table table-striped table-bordered table-hover" + id="{{ resource.id }}_bookings_table" cellspacing="0" + width="100%"> + {% include "booking/booking_table.html" %} + </table> + </div> + </div> + </div> + </div> +</div> + +<script type="text/javascript"> + var data_{{ resource.id }} = [{ + label: "Offline", + data: {{ utilization.offline }}, + color: '#d9534f' + }, { + label: "Online", + data: {{ utilization.online }}, + color: '#5cb85c' + }, { + label: "Idle", + data: {{ utilization.idle }}, + color: '#5bc0de' + }]; +</script>
\ No newline at end of file diff --git a/tools/pharos-dashboard/templates/dashboard/server_table.html b/tools/pharos-dashboard/templates/dashboard/server_table.html new file mode 100644 index 00000000..d47e5204 --- /dev/null +++ b/tools/pharos-dashboard/templates/dashboard/server_table.html @@ -0,0 +1,30 @@ +<thead> +<tr> + <th>Server</th> + <th>Model</th> + <th>CPU</th> + <th>RAM</th> + <th>Storage</th> +</tr> +</thead> +<tbody> +{% for server in resource.server_set.all %} + <tr> + <th> + {{ server.name }} + </th> + <th> + {{ server.model }} + </th> + <th> + {{ server.cpu }} + </th> + <th> + {{ server.ram }} + </th> + <th> + {{ server.storage }} + </th> + </tr> +{% endfor %}` +</tbody>
\ No newline at end of file |