Browse Source

récupération état des ports depuis check_mk

Élie Bouttier 7 years ago
parent
commit
2d9e610139

+ 27 - 0
djadhere/utils.py

@@ -6,6 +6,9 @@ from django.utils.safestring import mark_safe
 from django.conf import settings
 from django.contrib.admin import SimpleListFilter
 
+import socket, json
+from collections import namedtuple
+
 
 class ActiveFilter(SimpleListFilter):
     title = 'actif'
@@ -85,3 +88,27 @@ def send_notification(subject, message, recipients, **kwargs):
         settings.SERVER_EMAIL, recipients, **kwargs,
     )
     mail.send()
+
+
+def from_livestatus(get, query=[], columns=[]):
+    query = ['GET %s' % get] + query
+    if columns:
+        query += ["Columns: " + ' '.join(columns)]
+    query += ['OutputFormat: json']
+    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')
+        data = json.load(infile)
+    for entry in data:
+        if not Line:
+            Line = namedtuple(get.capitalize(), entry)
+            continue
+        lines.append(Line(*entry))
+    return lines

+ 4 - 4
services/admin.py

@@ -275,8 +275,8 @@ class PortInline(admin.TabularInline):
 
 
 class SwitchPortInline(PortInline):
-    fields = ('port', 'reserved', 'service', 'notes',)
-    readonly_fields = ('port',)
+    fields = ('port', 'up', 'reserved', 'service', 'notes',)
+    readonly_fields = ('port', 'up',)
     autocomplete_fields = ('service',)
 
     def get_queryset(self, request):
@@ -286,8 +286,8 @@ class SwitchPortInline(PortInline):
 
 
 class ServicePortInline(PortInline):
-    fields = ('switch', 'port', 'notes',)
-    readonly_fields = ('switch', 'port',)
+    fields = ('switch', 'port', 'up', 'notes',)
+    readonly_fields = ('switch', 'port', 'up',)
     max_num = 0
 
 

+ 43 - 0
services/management/commands/fetchport.py

@@ -0,0 +1,43 @@
+from django.core.management.base import BaseCommand
+
+from services.models import Switch
+from djadhere.utils import from_livestatus
+
+import re
+
+
+class Command(BaseCommand):
+    help = 'Récupération du dernier ping depuis check_mk'
+
+    def handle(self, *args, **options):
+        dell_iface_regex = re.compile('^Interface TenGigabitEthernet 0/(?P<id>[0-9]+)$')
+        ubnt_iface_regex = re.compile('^Interface Slot: 0 Port: (?P<id>[0-9]+) (Gigabit|10G) - Level$')
+        status_regex = re.compile('^OK .* \((?P<status>up|down)\)')
+        for sw in Switch.objects.all():
+            up, down = [], []
+            hosts = from_livestatus('hosts', query=['Filter: host_name = %s' % sw.name], columns=['services_with_info'])
+            if len(hosts) != 1:
+                return
+            host = hosts[0]
+            for service in host.services_with_info:
+                description, _, _, info = service
+                g = dell_iface_regex.match(description)
+                if not g:
+                    g = ubnt_iface_regex.match(description)
+                if not g:
+                    continue
+                port = int(g.group('id'))
+                g = status_regex.match(info)
+                if not g:
+                    continue
+                status = g.group('status')
+                if status == 'up':
+                    up.append(port)
+                else:
+                    assert(status == 'down')
+                    down.append(port)
+            unknown = [] # TODO
+            upped = sw.ports.filter(port__in=up).exclude(up=True).update(up=True)
+            downed = sw.ports.filter(port__in=down).exclude(up=False).update(up=False)
+            unknowned = sw.ports.filter(port__in=unknown).exclude(up__isnull=True).update(up=None)
+            print("Switch %s: UP: %d (%+d), DOWN: %d (%+d), UNKNOWN: %d (%+d)" % (sw.name, len(up), upped, len(down), downed, len(unknown), unknowned))

+ 23 - 0
services/migrations/0046_auto_20180210_1824.py

@@ -0,0 +1,23 @@
+# Generated by Django 2.0.2 on 2018-02-10 17:24
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('services', '0045_auto_20180210_1612'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='port',
+            name='up',
+            field=models.NullBooleanField(),
+        ),
+        migrations.AlterField(
+            model_name='port',
+            name='notes',
+            field=models.CharField(blank=True, default='', max_length=256),
+        ),
+    ]

+ 2 - 1
services/models.py

@@ -334,7 +334,8 @@ class Port(models.Model):
     service = models.ForeignKey(Service, null=True, blank=True, related_name='ports', on_delete=models.SET_NULL)
     port = models.IntegerField(verbose_name='N° de port')
     reserved = models.BooleanField(default=False, verbose_name='réservé')
-    notes = models.CharField(max_length=128, blank=True, default='')
+    notes = models.CharField(max_length=256, blank=True, default='')
+    up = models.NullBooleanField()
 
     def clean(self):
         if self.reserved and self.service:

+ 1 - 1
services/templates/services/service_detail.html

@@ -36,7 +36,7 @@
             Port{{ service.ports.count|pluralize }} :
             {% for port in service.ports.all %}
             {% if forloop.first %}<ul>{% endif %}
-                <li>Switch {{ port.switch }} port {{ port.port }}
+                <li>Switch {{ port.switch }} port {{ port.port }}{% if port.up is not None %} ({{ port.up|yesno:"UP,DOWN" }}){% endif %}
             {% if forloop.last %}</ul>{% endif %}
             {% endfor %}
         </p>