Commit fea96244 authored by Élie Bouttier's avatar Élie Bouttier

détection de corrélation entre les coupures

parent 07c6c92c
from django.core.management.base import BaseCommand
from django.utils import timezone
from django.conf import settings
from datetime import timedelta
from datetime import datetime, timedelta
from itertools import groupby
import logging
import argparse
from services.models import ServiceAllocation, IPResource, IPResourceState
logger = logging.getLogger(__name__)
def datehourmin(s):
try:
return timezone.make_aware(datetime.strptime(s, "%Y-%m-%d %H:%M"))
except ValueError:
msg = "Not a valid date: '{0}'.".format(s)
raise argparse.ArgumentTypeError(msg)
class Command(BaseCommand):
help = 'Détection des pannes'
def handle(self, *args, **options):
down = IPResource.objects.filter(
category=IPResource.CATEGORY_PUBLIC,
last_state__state=IPResourceState.STATE_DOWN,
last_time_up__gt=timezone.now()-timedelta(minutes=5))
allocations = ServiceAllocation.objects.filter(resource__pk__in=down)
#allocations = allocations.values('resource', 'route')
def add_arguments(self, parser):
parser.add_argument('-d', '--date',
help='Chercher une panne à une date donnée (%Y-%m-%d %H:%M).',
type=datehourmin,
default=timezone.now())
parser.add_argument('--before', type=int, default=5)
parser.add_argument('--after', type=int, default=0)
parser.add_argument('--threshold', type=int, default=3)
parser.add_argument('--verbose', action='store_true')
def handle(self, *args, date, before, after, threshold, verbose, **options):
"""
Requête :
- On sélectionne les évènements sur la période voulu ;
- puis on sélectionne le dernier évènement pour chaque IP ;
- et enfin on ne garde que les évènements DOWN.
Si on filtrait dès le début par évènement DOWN, on garderait les IP à nouveau UP dans les résultats.
"""
states = IPResourceState.objects.all()
if before:
states = states.filter(date__gt=date-timedelta(minutes=before))
if after:
states = states.filter(date__lte=date+timedelta(hours=24, minutes=after))
states = states.order_by('ip__pk', '-date').distinct('ip__pk')
# Il faut faire une deuxième requête sans quoi l’ORM réorganise et filtre par DOWN avant.
down = IPResourceState.objects.filter(pk__in=states).filter(state=IPResourceState.STATE_DOWN)
# On sélectionne les allocations de manière à pouvoir grouper les évènements par route.
allocations = ServiceAllocation.objects.filter(resource__ip__in=down.values('ip'))
allocations = sorted(allocations, key=lambda a: a.route.pk)
for route, allocs in groupby(allocations, key=lambda a: a.route.pk):
allocs = list(allocs)
route = allocs[0].route
print("%s: %d" % (route, len(allocs)))
for alloc in allocs:
print("\t%s" % alloc.resource)
if len(allocs) >= 4:
logger.info('%s %s' % (route, allocs))
self.stdout.write(self.style.SUCCESS('Aucune panne détectée.'))
if verbose:
self.stdout.write("%s: %d" % (route, len(allocs)))
for alloc in allocs:
self.stdout.write("\t%s" % alloc.resource)
if len(allocs) >= threshold:
#logger.info('%s %s' % (route, allocs))
self.stdout.write(self.style.ERROR('Coupure corrélée de {} IPs sur {} :'.format(len(allocs), route)))
for alloc in allocs:
self.stdout.write(self.style.ERROR('\t- {}'.format(alloc.resource)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment