Élie Bouttier 7 years ago
parent
commit
753c0f73a5
3 changed files with 87 additions and 6 deletions
  1. 30 5
      services/admin.py
  2. 49 0
      services/management/commands/fetchping.py
  3. 8 1
      services/models.py

+ 30 - 5
services/admin.py

@@ -283,10 +283,23 @@ class IPResourceAdmin(admin.ModelAdmin):
         ('prefixes', admin.RelatedOnlyFieldListFilter),
         RouteFilter,
     )
-    fields = ('ip', 'reserved', 'last_use', 'last_time_up', 'last_check', 'notes')
-    readonly_fields = ('ip', 'reserved', 'last_use', 'last_time_up', 'last_check',)
     search_fields = ('=ip', 'notes',)
 
+    def get_fields(self, request, obj=None):
+        return self.get_readonly_fields(request, obj) + ['notes']
+
+    def get_readonly_fields(self, request, obj=None):
+        fields = ['ip']
+        if obj and obj.reserved:
+            fields += ['reserved']
+        if obj and not obj.in_use:
+            fields += ['last_use']
+        if obj and obj.last_time_up and obj.last_check:
+            fields += ['last_time_up', 'last_check']
+        if obj and obj.checkmk_label:
+            fields += ['checkmk']
+        return fields
+
     def get_inline_instances(self, request, obj=None):
         if obj:
             if obj.category == 0:
@@ -302,6 +315,7 @@ class IPResourceAdmin(admin.ModelAdmin):
         qs = qs.annotate(last_use=models.Case(
                     models.When(category=0, then=models.Max('service_allocation__end')),
                     models.When(category=1, then=models.Max('antenna_allocation__end')),
+                    default=None,
                 ))
         qs = qs.annotate(downtime=Cast(
                     models.Case(
@@ -319,20 +333,31 @@ class IPResourceAdmin(admin.ModelAdmin):
     available_display.boolean = True
 
     def last_use(self, obj):
-        return naturaltime(obj.last_use)
+        if obj.last_use:
+            return naturaltime(obj.last_use)
+        else:
+            return '-'
     last_use.short_description = 'Dernière utilisation'
     last_use.admin_order_field = 'last_use'
 
     def ping(self, obj):
         if obj.downtime:
-            return 'down depuis >' + str(obj.downtime)
+            label = 'down depuis >' + str(obj.downtime)
         elif obj.downtime == timedelta(days=0):
-            return 'UP'
+            label = 'UP'
         else:
             return None
+        if obj.checkmk_url:
+            return format_html('<a href="{}">{}</a>', obj.checkmk_url, label)
+        else:
+            return label
     ping.short_description = 'ping'
     ping.admin_order_field = 'downtime'
 
+    def checkmk(self, obj):
+        return format_html('<a href="{}">{}</a>', obj.checkmk_url, 'voir')
+    checkmk.short_description = 'CheckMK'
+
     def get_actions(self, request):
         actions = super().get_actions(request)
         if 'delete_selected' in actions:

+ 49 - 0
services/management/commands/fetchping.py

@@ -0,0 +1,49 @@
+from django.core.management.base import BaseCommand
+
+import socket, csv
+from pytz import timezone
+from datetime import datetime
+from collections import namedtuple
+from itertools import groupby
+
+from services.models import IPResource
+
+
+def from_livestatus(get, query=[], columns=[]):
+    query = ['GET %s' % get]
+    if columns:
+        query += ["Columns: " + ' '.join(columns)]
+    query = ''.join(map(lambda s: s + '\n', query))
+    if columns:
+        Line = namedtuple(get.capitalize(), columns)
+    else:
+        Line = None
+    lines = []
+    with socket.create_connection(("nucnagios.tetaneutral.net", "8622")) as sock:
+        sock.send(query.encode('utf-8'))
+        sock.shutdown(socket.SHUT_WR)
+        infile = sock.makefile(encoding='utf-8')
+        for row in csv.reader(infile, delimiter=';'):
+            if not Line:
+                Line = namedtuple(get.capitalize(), row)
+                continue
+            lines.append(Line(*row))
+    return lines
+
+
+class Command(BaseCommand):
+    help = 'Récupération du dernier ping depuis check_mk'
+
+    def handle(self, *args, **options):
+        paris = timezone('Europe/Paris')
+        hosts = from_livestatus('hosts', columns=['name', 'address', 'last_check', 'last_time_up'])
+        data = {}
+        # quelques IP sont listées curieusement plusieurs fois, on prend la première occurence
+        for address, group in groupby(sorted(hosts, key=lambda host: host.address), lambda host: host.address):
+            last_check = last_time_up = 0
+            host = next(group)
+            IPResource.objects.filter(ip=address).update(
+                checkmk_label=host.name,
+                last_check=paris.localize(datetime.fromtimestamp(int(host.last_check))),
+                last_time_up=paris.localize(datetime.fromtimestamp(int(host.last_time_up))),
+            )

+ 8 - 1
services/models.py

@@ -8,7 +8,7 @@ from django.contrib.contenttypes.fields import GenericRelation
 from django.core.exceptions import ValidationError
 from django.urls import reverse
 from django.utils import timezone
-from django.utils.html import format_html, mark_safe
+from django.utils.html import format_html, mark_safe, escape
 from django.core.exceptions import PermissionDenied
 from django.core.validators import RegexValidator
 
@@ -111,6 +111,13 @@ class IPResource(models.Model):
         if self.category == 1:
             return self.antenna_allocations
 
+    @property
+    def checkmk_url(self):
+        if self.checkmk_label:
+            return mark_safe('https://nagios.tetaneutral.net/check_mk/view.py?host={}&view_name=host'.format(escape(self.checkmk_label)))
+        else:
+            return None
+
     class Meta:
         ordering = ['ip']
         verbose_name = 'IP'