1
0
Fork 0

Implement Station status log

* Add Celery redis vars on docker
merge-requests/478/head
Nikos Roussos 2018-03-23 15:28:23 +02:00
parent 1a27809621
commit 0f1f0d4a5b
No known key found for this signature in database
GPG Key ID: BADFF1767BA7C8E1
8 changed files with 153 additions and 3 deletions

View File

@ -26,6 +26,8 @@ services:
- redis
environment:
- DATABASE_URL=mysql://network:network@db/network
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
command:
./bin/run-celery.sh

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.10 on 2018-03-22 20:45
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('base', '0036_auto_20180316_1216'),
]
operations = [
migrations.CreateModel(
name='StationStatusLog',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.IntegerField(choices=[(2, b'Online'), (1, b'Testing'), (0, b'Offline')], default=0)),
('changed', models.DateTimeField(auto_now_add=True)),
('station', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='station_logs', to='base.Station')),
],
options={
'ordering': ['-status'],
},
),
]

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.11 on 2018-03-22 20:54
from __future__ import unicode_literals
from django.db import migrations
def initial_station_log(apps, schema_editor):
Station = apps.get_model('base', 'Station')
StationStatusLog = apps.get_model('base', 'StationStatusLog')
for station in Station.objects.all():
StationStatusLog.objects.create(station=station, status=station.status)
class Migration(migrations.Migration):
dependencies = [
('base', '0037_stationstatuslog'),
]
operations = [
migrations.RunPython(initial_station_log),
]

View File

@ -79,6 +79,7 @@ def _station_post_save(sender, instance, created, **kwargs):
"""
post_save.disconnect(_station_post_save, sender=Station)
if not created:
current_status = instance.status
if instance.is_offline:
instance.status = 0
elif instance.testing:
@ -86,6 +87,10 @@ def _station_post_save(sender, instance, created, **kwargs):
else:
instance.status = 2
instance.save()
if instance.status != current_status:
StationStatusLog.objects.create(station=instance, status=instance.status)
else:
StationStatusLog.objects.create(station=instance, status=instance.status)
post_save.connect(_station_post_save, sender=Station)
@ -218,6 +223,19 @@ class Station(models.Model):
post_save.connect(_station_post_save, sender=Station)
class StationStatusLog(models.Model):
station = models.ForeignKey(Station, related_name='station_logs',
on_delete=models.CASCADE, null=True, blank=True)
status = models.IntegerField(choices=STATION_STATUSES, default=0)
changed = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-status']
def __unicode__(self):
return '{0} - {1}'.format(self.station, self.status)
class Satellite(models.Model):
"""Model for SatNOGS satellites."""
norad_cat_id = models.PositiveIntegerField()

View File

@ -30,6 +30,7 @@ base_urlpatterns = ([
# Stations
url(r'^stations/$', views.stations_list, name='stations_list'),
url(r'^stations/(?P<id>[0-9]+)/$', views.station_view, name='station_view'),
url(r'^stations/(?P<id>[0-9]+)/log/$', views.station_log, name='station_log'),
url(r'^stations/(?P<id>[0-9]+)/delete/$', views.station_delete, name='station_delete'),
url(r'^stations/edit/$', views.station_edit, name='station_edit'),
url(r'^stations/edit/(?P<id>[0-9]+)/$', views.station_edit, name='station_edit'),

View File

@ -17,7 +17,7 @@ from django.views.generic import ListView
from rest_framework import serializers, viewsets
from network.base.models import (Station, Transmitter, Observation,
Satellite, Antenna, Tle, Rig)
Satellite, Antenna, Tle, Rig, StationStatusLog)
from network.users.models import User
from network.base.forms import StationForm, SatelliteFilterForm
from network.base.decorators import admin_required, ajax_required
@ -543,6 +543,13 @@ def station_view(request, id):
can_schedule = schedule_perms(request.user, station)
log = StationStatusLog.objects.filter(station=station).order_by('-changed')[:2]
latest = log[:1].get()
uptime = '-'
if latest.status == 2:
previous = log[1:2].get()
uptime = latest.changed - previous.changed
if request.user.is_authenticated():
if request.user == station.owner:
wiki_help = ('<a href="{0}" target="_blank" class="wiki-help"><span class="glyphicon '
@ -562,7 +569,17 @@ def station_view(request, id):
'mapbox_id': settings.MAPBOX_MAP_ID,
'mapbox_token': settings.MAPBOX_TOKEN,
'rigs': rigs, 'can_schedule': can_schedule,
'unsupported_frequencies': unsupported_frequencies})
'unsupported_frequencies': unsupported_frequencies,
'uptime': uptime})
def station_log(request, id):
"""View for single station status log."""
station = get_object_or_404(Station, id=id)
station_log = StationStatusLog.objects.filter(station=station)
return render(request, 'base/station_log.html',
{'station': station, 'station_log': station_log})
@ajax_required

View File

@ -0,0 +1,48 @@
{% extends "base.html" %}
{% load tags %}
{% load staticfiles %}
{% block title %} - Ground Station {{ station.name }} Status Log{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-12">
<h2>
<a href="{% url 'base:station_view' id=station.id %}">
{{ station.id }} - {{ station.name }}
</a>
</h2>
<div class="timezone text-muted">
<span class="glyphicon glyphicon-time" aria-hidden="true"></span>
Timeframes are in <a href="#" data-toggle="modal" data-target="#UTCModal">UTC</a>
</div>
<table class="table table-hover">
<thead>
<th>Status</th>
<th>Datetime</th>
</thead>
<tbody>
{% for log in station_log %}
<tr>
<td>
<span class="label label-{{ log.get_status_display|lower }}">{{ log.get_status_display }}</span>
</td>
<td>
<span data-toggle="tooltip" title="{{ log.changed|timesince }} ago">{{ log.changed|date:"Y-m-d H:i:s" }}</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- UTC Modal -->
{% include 'includes/utc.html' %}
{% endblock content %}
{% block javascript %}
<script src="{% static 'lib/moment/min/moment.min.js' %}"></script>
<script src="{% static 'js/utc.js' %}"></script>
{% endblock javascript %}

View File

@ -141,7 +141,7 @@
</div>
<div class="front-line">
<span class="label label-{{ station.get_status_display|lower }}">{{ station.get_status_display }}</span>
<span class="front-data"
<span class="front-data" data-toggle="tooltip"
title="{{ station.last_seen|date:"c" }}">
{% if station.last_seen %}
Last seen {{ station.last_seen|timesince }} ago
@ -150,6 +150,19 @@
{% endif %}
</span>
</div>
<div class="front-line">
<span class="label label-default">Uptime</span>
<span class="front-data">
{{ uptime }}
<div class="pull-right">
<a href="{% url 'base:station_log' id=station.id %}">
<button type="button" class="btn btn-xs btn-info">
Log
</button>
</a>
</div>
</span>
</div>
</div>
<div class="col-md-4">
<div id="map-station" data-mapboxid="{{ mapbox_id }}" data-mapboxtoken="{{ mapbox_token }}"></div>