Browse Source

commande services

Élie Bouttier 8 years ago
parent
commit
adf335d8e4
1 changed files with 112 additions and 9 deletions
  1. 112 9
      services/management/commands/services.py

+ 112 - 9
services/management/commands/services.py

@@ -1,9 +1,44 @@
 from django.core.management.base import BaseCommand, CommandParser, CommandError
 from django.db.models import DecimalField, F, Sum, Func, Q
+from django.core.validators import validate_ipv4_address, validate_ipv6_address
+from django.core.exceptions import ValidationError
 
+import argparse
 from decimal import Decimal
 
-from services.models import Service, ServiceType
+from services.models import Service, ServiceType, IPResource
+
+
+class IPAction(argparse.Action):
+    def __call__(self, parser, namespace, values, option_string=None):
+        args = values.split('/')
+        if len(args) == 1:
+            ip, = args
+            mask = 0
+        elif len(args) == 2:
+            ip, mask = args
+        else:
+            raise argparse.ArgumentError(self, '"%s" n’est pas une IP valide' % values)
+        try:
+            validate_ipv4_address(ip)
+            protocol = 'ipv4'
+        except ValidationError:
+            try:
+                validate_ipv6_address(ip)
+                protocol = 'ipv6'
+            except ValidationError:
+                raise argparse.ArgumentError(self, '"%s" n’est pas une IP valide' % values)
+        try:
+            mask = int(mask)
+        except ValueError:
+            raise argparse.ArgumentError(self, 'masque invalide')
+        if (mask < 0) or \
+                (protocol == 'ipv4' and mask > 32) or \
+                (protocol == 'ipv6' and mask > 128):
+            raise argparse.ArgumentError(self, 'masque invalide')
+        ip, created = IPResource.objects.get_or_create(ip=ip, mask=mask)
+        ip_set = getattr(namespace, 'ip')
+        ip_set.append(ip)
 
 
 class Command(BaseCommand):
@@ -19,10 +54,26 @@ class Command(BaseCommand):
 
         parser_stats = subparsers.add_parser('stats', help='Afficher les statistiques sur les services')
 
-        parser_add = subparsers.add_parser('add', help='Ajouter un nouveau service')
+        parser_list = subparsers.add_parser('list', help='Lister les services')
+        parser_list.add_argument('--type',
+            choices=ServiceType.objects.all().values_list('name', flat=True),
+            help='Afficher uniquement les services d’un certain type')
+        group = parser_list.add_mutually_exclusive_group()
+        group.add_argument('--ongoing', action='store_true',
+            help='Afficher uniquement les services actifs')
+        group.add_argument('--forthcoming', action='store_true',
+            help='Afficher uniquement les services à venir (non configuré ou à date de début dans le futur)')
+        group.add_argument('--finished', action='store_true',
+            help='Afficher uniquement les services terminés')
 
-        parser_change = subparsers.add_parser('change', help='Modifier un service existant')
-        parser_change.add_argument('id', type=int)
+        parser_show = subparsers.add_parser('show', help='Afficher les informations concernant un service')
+        parser_show.add_argument('id', type=int)
+
+        parser_add = subparsers.add_parser('add', help='Ajouter un nouveau service')
+        parser_add.add_argument('--type', required=True,
+            choices=ServiceType.objects.all().values_list('name', flat=True),
+            help='Afficher uniquement les services d’un certain type')
+        parser_add.add_argument('--ip', action=IPAction, default=[], help='Assigner une IP au service')
 
         parser_delete = subparsers.add_parser('delete', help='Supprimer un service existant')
         parser_delete.add_argument('id', type=int)
@@ -64,11 +115,63 @@ class Command(BaseCommand):
                 percent = 0
             self.stdout.write("%-16s%12d%12d%12d%12.2f%12.1f" % (service_type, npay, ninf, ngra, income, percent))
 
-    def handle_add(self, *args, **options):
-        raise CommandError("Non implémenté")
+    def handle_list(self, *args, **options):
+        services = Service.objects.all()
+        if options['type']:
+            st = ServiceType.objects.get(name=options['type'])
+            services = services.filter(service_type=st)
+        if options['ongoing']:
+            services = services.filter(Service.get_ongoing_filter())
+        if options['forthcoming']:
+            services = services.filter(Service.get_forthcoming_filter())
+        if options['finished']:
+            services = services.filter(Service.get_finished_filter())
+
+        fmt = '{:<8}{:<20}{:<20}{:<10}{:<40}'
+        print(fmt.format('ID', 'Type', 'Adhérent', 'En cours', 'IPs'))
+        for service in services:
+            adh = str(service.adherent) if service.adherent else '-'
+            ips = ', '.join(map(str, service.ip_resources.all())) or '-'
+            ongoing = '✔' if service.is_ongoing else '✘'
+            print(fmt.format(service.pk, str(service.service_type), adh, ongoing, ips))
 
-    def handle_change(self, *args, **options):
-        raise CommandError("Non implémenté")
+    def handle_show(self, *args, **options):
+        try:
+            service = Service.objects.get(pk=options['id'])
+        except Service.DoesNotExist:
+            raise CommandError('Le service n°%d n’existe pas' % options['id'])
+        self.stdout.write('Service n°%d' % service.pk)
+        self.stdout.write('\tType de service : %s' % service.service_type)
+        self.stdout.write('\tAdhérent : %s' % (service.adherent or 'aucun'))
+        self.stdout.write('\tDébut du service : %s' % (service.start or '-'))
+        self.stdout.write('\tFin du service : %s' % (service.end or '-'))
+        self.stdout.write('\tService en cours : %s' % ('oui' if service.is_ongoing else 'non'))
+
+    def handle_add(self, *args, **options):
+        for ip in options['ip']:
+            services = Service.objects.filter(ip_resources=ip).exclude(Service.get_finished_filter())
+            if services.exists():
+                self.stdout.write(self.style.WARNING('Note : la ressource IP "%s" est également affecté aux '
+                                                     'services suivants :' % ip))
+                for service in services:
+                    self.stdout.write(self.style.WARNING('\t%d (%s)' % (service.pk, service.service_type)))
+                value = input('Continuer ? [y/N] ')
+                if value.lower() != 'y':
+                    raise CommandError('Opération annulée')
+        st = ServiceType.objects.get(name=options['type'])
+        service = Service.objects.create(service_type=st)
+        service.ip_resources = options['ip']
+        service.save()
+        self.stdout.write(self.style.SUCCESS('Service n°%d créé avec succès' % service.pk))
 
     def handle_delete(self, *args, **options):
-        raise CommandError("Non implémenté")
+        try:
+            service = Service.objects.get(pk=options['id'])
+        except Service.DoesNotExist:
+            raise CommandError('Le service n°%d n’existe pas' % options['id'])
+        value = input('Êtes vous sûr de vouloir supprimer ce service ? [y/N] ')
+        if value.lower() == 'y':
+            service.delete()
+            self.stdout.write(self.style.SUCCESS('Service supprimé'))
+        else:
+            self.stdout.write('Service non supprimé')