|
@@ -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é')
|