Loading services/admin.py +51 −28 Original line number Diff line number Diff line Loading @@ -26,9 +26,9 @@ from datetime import timedelta from djadhere.utils import get_active_filter from adhesions.models import Adhesion from banking.models import PaymentUpdate from .models import Service, ServiceType, IPPrefix, IPResource, Route, Tunnel, \ from .models import Service, ServiceType, IPPrefix, IPResource, IPResourceState, \ ServiceAllocation, Antenna, AntennaAllocation, Allocation, \ Switch, Port Route, Tunnel, Switch, Port from .utils.notifications import notify_allocation from .forms import AntennaForm Loading Loading @@ -67,13 +67,15 @@ class ResourcePingFilter(admin.SimpleListFilter): def queryset(self, request, queryset): if self.value() == 'up': return queryset.filter(up=True) return queryset.filter(last_state__state=IPResourceState.STATE_UP) if self.value() == 'down': return queryset.filter(models.Q(up__isnull=True) | models.Q(up=False)) return queryset.exclude(last_state__state=IPResourceState.STATE_UP) # DOWN + UNKNOWN if self.value() == 'down-since': return queryset.filter(up=False) queryset = queryset.exclude(last_state__state=IPResourceState.STATE_UP) return queryset.filter(last_time_up__isnull=False) if self.value() == 'never-up': return queryset.filter(up__isnull=True) queryset = queryset.exclude(last_state__state=IPResourceState.STATE_UP) # DOWN + UNKWON return queryset.filter(last_time_up__isnull=True) class ActiveServiceFilter(admin.SimpleListFilter): Loading Loading @@ -265,6 +267,22 @@ class InactiveAntennaAllocationInline(AntennaAllocationMixin, InactiveAllocation pass class IPResourceStateInline(admin.TabularInline): model = IPResourceState verbose_name_plural = 'Historique des changements d’état' fields = ['date'] ordering = ['-date'] def has_add_permission(self, request): return False def has_change_permission(self, request, obj): return False def has_delete_permission(self, request, obj=None): return False class PortInline(admin.TabularInline): model = Port max_num = 0 Loading Loading @@ -385,27 +403,32 @@ class IPResourceAdmin(admin.ModelAdmin): ) search_fields = ('=ip', 'notes',) actions = ['contact_ip_owners'] ordering = ['ip'] inlines = [ IPResourceStateInline ] def get_fields(self, request, obj=None): return self.get_readonly_fields(request, obj) def get_readonly_fields(self, request, obj=None): fields = ['ip'] if obj and obj.reserved: if obj: if obj.reserved: fields += ['reserved'] if obj and not obj.in_use: if not obj.in_use: fields += ['last_use'] if obj and obj.last_time_up and obj.last_check: fields += ['last_time_up', 'last_check'] fields += ['last_state'] if obj.last_state.state != IPResourceState.STATE_UP: fields += ['last_time_up'] if obj.category == IPResource.CATEGORY_PUBLIC: fields += ['password'] if obj and obj.checkmk_label: if obj.checkmk_label: fields += ['checkmk'] if obj and obj.notes: if obj.notes: fields += ['notes'] return fields def get_inline_instances(self, request, obj=None): super_inlines = super().get_inline_instances(request, obj) if obj: if obj.category == 0: inlines = (ActiveServiceAllocationInline, InactiveServiceAllocationInline,) Loading @@ -413,7 +436,7 @@ class IPResourceAdmin(admin.ModelAdmin): inlines = (ActiveAntennaAllocationInline, InactiveAntennaAllocationInline,) else: inlines = () return [inline(self.model, self.admin_site) for inline in inlines] return [inline(self.model, self.admin_site) for inline in inlines] + super_inlines def get_queryset(self, request): qs = super().get_queryset(request) Loading @@ -426,13 +449,12 @@ class IPResourceAdmin(admin.ModelAdmin): default=None, )) qs = qs.annotate( up=models.Case( models.When(last_check__isnull=False, last_time_up__isnull=False, last_time_up=models.F('last_check'), then=True), models.When(last_check__isnull=False, last_time_up__isnull=False, then=False), downtime=models.Case( models.When(last_state__state=IPResourceState.STATE_UP, then=models.F('last_state__date')-models.Value(now)), models.When(last_state__state=IPResourceState.STATE_DOWN, then=models.Value(now)-models.F('last_time_up')), default=None, output_field=models.NullBooleanField(), output_field=models.DurationField(), )) qs = qs.annotate(downtime=models.F('last_check') - models.F('last_time_up')) qs = qs.annotate( route=models.Case( models.When( Loading Loading @@ -461,9 +483,10 @@ class IPResourceAdmin(admin.ModelAdmin): last_use.admin_order_field = 'last_use' def ping(self, obj): if obj.up: if obj.last_state.state == IPResourceState.STATE_UP: label = 'UP' elif obj.last_time_up: else: if obj.last_time_up: label = 'dernier ping : ' + naturaltime(obj.last_time_up) else: label = 'DOWN' Loading services/migrations/0052_auto_20190219_2146.py 0 → 100644 +28 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 20:46 from django.db import migrations, models from django.utils import timezone class Migration(migrations.Migration): dependencies = [ ('services', '0051_auto_20180602_1346'), ] operations = [ migrations.CreateModel( name='IPResourceState', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('date', models.DateTimeField(default=timezone.now)), ('state', models.IntegerField(choices=[(0, 'DOWN'), (1, 'UP'), (2, 'Inconnu')])), ('ip', models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='state_set', to='services.IPResource')), ], ), migrations.AddField( model_name='ipresource', name='last_state', field=models.ForeignKey(null=True, on_delete=models.deletion.PROTECT, to='services.IPResourceState', related_name='+'), ), ] services/migrations/0053_auto_20190219_2147.py 0 → 100644 +51 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 20:47 from django.db import migrations from django.utils import timezone from datetime import timedelta def forward(apps, schema_editor): db_alias = schema_editor.connection.alias IPResource = apps.get_model('services', 'IPResource') IPResourceState = apps.get_model('services', 'IPResourceState') now = timezone.now() for ip in IPResource.objects.all(): if ip.last_check: if ip.last_time_up: if ip.last_check == ip.last_time_up: # UP ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_time_up, state=1) # UP ip.save() else: # DOWN but UP some time before ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_time_up, state=0) # DOWN ip.save() else: # Always DOWN ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_check, state=0) # DOWN ip.save() else: ip.last_state = IPResourceState.objects.create(ip=ip, date=now, state=2) # UNKNOWN ip.save() def backward(apps, schema_editor): db_alias = schema_editor.connection.alias IPResource = apps.get_model('services', 'IPResource') IPResourceState = apps.get_model('services', 'IPResourceState') for ip in IPResource.objects.all(): if ip.last_state.state != 2: ip.last_check = ip.last_state.date if ip.last_state.state == 1: ip.last_time_up = ip.last_check ip.save() class Migration(migrations.Migration): dependencies = [ ('services', '0052_auto_20190219_2146'), ] operations = [ migrations.RunPython(forward, backward) ] services/migrations/0054_auto_20190219_2206.py 0 → 100644 +22 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 21:06 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('services', '0053_auto_20190219_2147'), ] operations = [ migrations.RemoveField( model_name='ipresource', name='last_check', ), migrations.AlterField( model_name='ipresource', name='last_state', field=models.ForeignKey(on_delete=models.deletion.PROTECT, to='services.IPResourceState', related_name='+'), ), ] services/models.py +18 −1 Original line number Diff line number Diff line Loading @@ -102,8 +102,8 @@ class IPResource(models.Model): category = models.IntegerField(choices=CATEGORIES, verbose_name='catégorie') notes = models.TextField(blank=True, default='') checkmk_label = models.CharField(max_length=128, blank=True, default='') last_state = models.ForeignKey("IPResourceState", on_delete=models.PROTECT, related_name='+', verbose_name='dernier état') last_time_up = models.DateTimeField(null=True, blank=True, verbose_name='Dernière réponse au ping') last_check = models.DateTimeField(null=True, blank=True, verbose_name='Dernier contrôle') objects = IPResourceManager() Loading Loading @@ -135,6 +135,23 @@ class IPResource(models.Model): return str(self.ip) class IPResourceState(models.Model): STATE_DOWN = 0 STATE_UP = 1 STATE_UNKNOWN = 2 STATE_CHOICES = ( (STATE_DOWN, 'DOWN'), (STATE_UP, 'UP'), (STATE_UNKNOWN, 'Inconnu'), ) ip = models.ForeignKey(IPResource, on_delete=models.CASCADE, related_name='state_set') date = models.DateTimeField(default=timezone.now) state = models.IntegerField(choices=STATE_CHOICES) def __str__(self): return self.get_state_display() class ServiceType(models.Model): name = models.CharField(max_length=64, verbose_name='Nom', unique=True) contact = models.CharField(max_length=64, verbose_name='Contact en cas de problème', blank=True, default='') Loading Loading
services/admin.py +51 −28 Original line number Diff line number Diff line Loading @@ -26,9 +26,9 @@ from datetime import timedelta from djadhere.utils import get_active_filter from adhesions.models import Adhesion from banking.models import PaymentUpdate from .models import Service, ServiceType, IPPrefix, IPResource, Route, Tunnel, \ from .models import Service, ServiceType, IPPrefix, IPResource, IPResourceState, \ ServiceAllocation, Antenna, AntennaAllocation, Allocation, \ Switch, Port Route, Tunnel, Switch, Port from .utils.notifications import notify_allocation from .forms import AntennaForm Loading Loading @@ -67,13 +67,15 @@ class ResourcePingFilter(admin.SimpleListFilter): def queryset(self, request, queryset): if self.value() == 'up': return queryset.filter(up=True) return queryset.filter(last_state__state=IPResourceState.STATE_UP) if self.value() == 'down': return queryset.filter(models.Q(up__isnull=True) | models.Q(up=False)) return queryset.exclude(last_state__state=IPResourceState.STATE_UP) # DOWN + UNKNOWN if self.value() == 'down-since': return queryset.filter(up=False) queryset = queryset.exclude(last_state__state=IPResourceState.STATE_UP) return queryset.filter(last_time_up__isnull=False) if self.value() == 'never-up': return queryset.filter(up__isnull=True) queryset = queryset.exclude(last_state__state=IPResourceState.STATE_UP) # DOWN + UNKWON return queryset.filter(last_time_up__isnull=True) class ActiveServiceFilter(admin.SimpleListFilter): Loading Loading @@ -265,6 +267,22 @@ class InactiveAntennaAllocationInline(AntennaAllocationMixin, InactiveAllocation pass class IPResourceStateInline(admin.TabularInline): model = IPResourceState verbose_name_plural = 'Historique des changements d’état' fields = ['date'] ordering = ['-date'] def has_add_permission(self, request): return False def has_change_permission(self, request, obj): return False def has_delete_permission(self, request, obj=None): return False class PortInline(admin.TabularInline): model = Port max_num = 0 Loading Loading @@ -385,27 +403,32 @@ class IPResourceAdmin(admin.ModelAdmin): ) search_fields = ('=ip', 'notes',) actions = ['contact_ip_owners'] ordering = ['ip'] inlines = [ IPResourceStateInline ] def get_fields(self, request, obj=None): return self.get_readonly_fields(request, obj) def get_readonly_fields(self, request, obj=None): fields = ['ip'] if obj and obj.reserved: if obj: if obj.reserved: fields += ['reserved'] if obj and not obj.in_use: if not obj.in_use: fields += ['last_use'] if obj and obj.last_time_up and obj.last_check: fields += ['last_time_up', 'last_check'] fields += ['last_state'] if obj.last_state.state != IPResourceState.STATE_UP: fields += ['last_time_up'] if obj.category == IPResource.CATEGORY_PUBLIC: fields += ['password'] if obj and obj.checkmk_label: if obj.checkmk_label: fields += ['checkmk'] if obj and obj.notes: if obj.notes: fields += ['notes'] return fields def get_inline_instances(self, request, obj=None): super_inlines = super().get_inline_instances(request, obj) if obj: if obj.category == 0: inlines = (ActiveServiceAllocationInline, InactiveServiceAllocationInline,) Loading @@ -413,7 +436,7 @@ class IPResourceAdmin(admin.ModelAdmin): inlines = (ActiveAntennaAllocationInline, InactiveAntennaAllocationInline,) else: inlines = () return [inline(self.model, self.admin_site) for inline in inlines] return [inline(self.model, self.admin_site) for inline in inlines] + super_inlines def get_queryset(self, request): qs = super().get_queryset(request) Loading @@ -426,13 +449,12 @@ class IPResourceAdmin(admin.ModelAdmin): default=None, )) qs = qs.annotate( up=models.Case( models.When(last_check__isnull=False, last_time_up__isnull=False, last_time_up=models.F('last_check'), then=True), models.When(last_check__isnull=False, last_time_up__isnull=False, then=False), downtime=models.Case( models.When(last_state__state=IPResourceState.STATE_UP, then=models.F('last_state__date')-models.Value(now)), models.When(last_state__state=IPResourceState.STATE_DOWN, then=models.Value(now)-models.F('last_time_up')), default=None, output_field=models.NullBooleanField(), output_field=models.DurationField(), )) qs = qs.annotate(downtime=models.F('last_check') - models.F('last_time_up')) qs = qs.annotate( route=models.Case( models.When( Loading Loading @@ -461,9 +483,10 @@ class IPResourceAdmin(admin.ModelAdmin): last_use.admin_order_field = 'last_use' def ping(self, obj): if obj.up: if obj.last_state.state == IPResourceState.STATE_UP: label = 'UP' elif obj.last_time_up: else: if obj.last_time_up: label = 'dernier ping : ' + naturaltime(obj.last_time_up) else: label = 'DOWN' Loading
services/migrations/0052_auto_20190219_2146.py 0 → 100644 +28 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 20:46 from django.db import migrations, models from django.utils import timezone class Migration(migrations.Migration): dependencies = [ ('services', '0051_auto_20180602_1346'), ] operations = [ migrations.CreateModel( name='IPResourceState', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('date', models.DateTimeField(default=timezone.now)), ('state', models.IntegerField(choices=[(0, 'DOWN'), (1, 'UP'), (2, 'Inconnu')])), ('ip', models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='state_set', to='services.IPResource')), ], ), migrations.AddField( model_name='ipresource', name='last_state', field=models.ForeignKey(null=True, on_delete=models.deletion.PROTECT, to='services.IPResourceState', related_name='+'), ), ]
services/migrations/0053_auto_20190219_2147.py 0 → 100644 +51 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 20:47 from django.db import migrations from django.utils import timezone from datetime import timedelta def forward(apps, schema_editor): db_alias = schema_editor.connection.alias IPResource = apps.get_model('services', 'IPResource') IPResourceState = apps.get_model('services', 'IPResourceState') now = timezone.now() for ip in IPResource.objects.all(): if ip.last_check: if ip.last_time_up: if ip.last_check == ip.last_time_up: # UP ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_time_up, state=1) # UP ip.save() else: # DOWN but UP some time before ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_time_up, state=0) # DOWN ip.save() else: # Always DOWN ip.last_state = IPResourceState.objects.create(ip=ip, date=ip.last_check, state=0) # DOWN ip.save() else: ip.last_state = IPResourceState.objects.create(ip=ip, date=now, state=2) # UNKNOWN ip.save() def backward(apps, schema_editor): db_alias = schema_editor.connection.alias IPResource = apps.get_model('services', 'IPResource') IPResourceState = apps.get_model('services', 'IPResourceState') for ip in IPResource.objects.all(): if ip.last_state.state != 2: ip.last_check = ip.last_state.date if ip.last_state.state == 1: ip.last_time_up = ip.last_check ip.save() class Migration(migrations.Migration): dependencies = [ ('services', '0052_auto_20190219_2146'), ] operations = [ migrations.RunPython(forward, backward) ]
services/migrations/0054_auto_20190219_2206.py 0 → 100644 +22 −0 Original line number Diff line number Diff line # Generated by Django 2.1.1 on 2019-02-19 21:06 from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ ('services', '0053_auto_20190219_2147'), ] operations = [ migrations.RemoveField( model_name='ipresource', name='last_check', ), migrations.AlterField( model_name='ipresource', name='last_state', field=models.ForeignKey(on_delete=models.deletion.PROTECT, to='services.IPResourceState', related_name='+'), ), ]
services/models.py +18 −1 Original line number Diff line number Diff line Loading @@ -102,8 +102,8 @@ class IPResource(models.Model): category = models.IntegerField(choices=CATEGORIES, verbose_name='catégorie') notes = models.TextField(blank=True, default='') checkmk_label = models.CharField(max_length=128, blank=True, default='') last_state = models.ForeignKey("IPResourceState", on_delete=models.PROTECT, related_name='+', verbose_name='dernier état') last_time_up = models.DateTimeField(null=True, blank=True, verbose_name='Dernière réponse au ping') last_check = models.DateTimeField(null=True, blank=True, verbose_name='Dernier contrôle') objects = IPResourceManager() Loading Loading @@ -135,6 +135,23 @@ class IPResource(models.Model): return str(self.ip) class IPResourceState(models.Model): STATE_DOWN = 0 STATE_UP = 1 STATE_UNKNOWN = 2 STATE_CHOICES = ( (STATE_DOWN, 'DOWN'), (STATE_UP, 'UP'), (STATE_UNKNOWN, 'Inconnu'), ) ip = models.ForeignKey(IPResource, on_delete=models.CASCADE, related_name='state_set') date = models.DateTimeField(default=timezone.now) state = models.IntegerField(choices=STATE_CHOICES) def __str__(self): return self.get_state_display() class ServiceType(models.Model): name = models.CharField(max_length=64, verbose_name='Nom', unique=True) contact = models.CharField(max_length=64, verbose_name='Contact en cas de problème', blank=True, default='') Loading