From 1a997eb2022a13564f33afb0e47da8d1e6354ae9 Mon Sep 17 00:00:00 2001 From: Dmitry Novikov Date: Thu, 11 Oct 2018 16:40:19 +0300 Subject: [PATCH] Add autofill free ip --- abonapp/forms.py | 24 +++++++++++++++++++++++- abonapp/views.py | 7 +++++++ ip_pool/forms.py | 5 +++++ ip_pool/models.py | 28 +++++++++++++++++++++++++++- 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/abonapp/forms.py b/abonapp/forms.py index e06c553..e91bf26 100644 --- a/abonapp/forms.py +++ b/abonapp/forms.py @@ -4,6 +4,8 @@ from django.contrib.auth.hashers import make_password from random import choice from string import digits, ascii_lowercase +from djing.lib import LogicError +from ip_pool.models import NetworkModel from nas_app.models import NASModel from . import models from django.conf import settings @@ -166,11 +168,31 @@ class MarkersForm(forms.ModelForm): class AmountMoneyForm(forms.Form): - amount = forms.FloatField(max_value=50000, label=_('Amount of money')) + amount = forms.FloatField(max_value=5000, label=_('Amount of money')) comment = forms.CharField(max_length=128, label=_('Comment'), required=False) class AddIpForm(forms.ModelForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + instance = getattr(self, 'instance') + if instance: + if instance.group: + self.fields['networks'].queryset = NetworkModel.objects.filter(groups=instance.group) + if not self.initial['ip_address']: + if instance: + net = NetworkModel.objects.filter(groups=instance.group).first() + if net is not None: + ips = (ip.ip_address for ip in + models.Abon.objects.filter(group=instance.group).order_by('ip_address').only( + 'ip_address').iterator()) + free_ip = net.get_free_ip(ips) + self.initial['ip_address'] = free_ip + else: + raise LogicError(_('Subnet has not attached to current group')) + + networks = forms.ModelChoiceField(label=_('Networks'), queryset=NetworkModel.objects.none(), empty_label=None) + class Meta: model = models.Abon fields = 'ip_address', diff --git a/abonapp/views.py b/abonapp/views.py index 40f048a..73fc7ab 100644 --- a/abonapp/views.py +++ b/abonapp/views.py @@ -557,6 +557,13 @@ class IpUpdateView(AbonappPermissionMixin, UpdateView): slug_field = 'username' template_name = 'abonapp/modal_ip_form.html' + def dispatch(self, request, *args, **kwargs): + try: + return super(IpUpdateView, self).dispatch(request, *args, **kwargs) + except lib.LogicError as e: + messages.error(request, e) + return self.render_to_response(self.get_context_data(**kwargs)) + def get_context_data(self, **kwargs): context = super(IpUpdateView, self).get_context_data(**kwargs) context['group'] = self.object.group diff --git a/ip_pool/forms.py b/ip_pool/forms.py index e6e2a28..45b5ef5 100644 --- a/ip_pool/forms.py +++ b/ip_pool/forms.py @@ -20,3 +20,8 @@ class NetworkForm(forms.ModelForm): class Meta: model = models.NetworkModel fields = '__all__' + widgets = { + 'groups': forms.SelectMultiple(attrs={ + 'size': 12 + }) + } diff --git a/ip_pool/models.py b/ip_pool/models.py index db0a068..daf15bd 100644 --- a/ip_pool/models.py +++ b/ip_pool/models.py @@ -1,6 +1,6 @@ from datetime import timedelta from ipaddress import ip_network, ip_address -from typing import Optional +from typing import Optional, Generator from django.conf import settings from django.db.utils import IntegrityError @@ -105,6 +105,32 @@ class NetworkModel(models.Model): return _('Unspecified') return "I don't know" + def get_free_ip(self, employed_ips: Optional[Generator]): + """ + Find free ip in network. + :param employed_ips: Sorted from less to more ip addresses from current network. + :return: single finded ip + """ + network = self.get_network() + work_range_start_ip = ip_address(self.ip_start) + work_range_end_ip = ip_address(self.ip_end) + if employed_ips is None: + for ip in network.hosts(): + if work_range_start_ip <= ip <= work_range_end_ip: + return ip + return + for ip in network.hosts(): + if ip < work_range_start_ip: + continue + elif ip > work_range_end_ip: + break # Not found + used_ip = next(employed_ips) + if used_ip is None: + return ip + used_ip = ip_address(used_ip) + if ip < used_ip: + return ip + class Meta: db_table = 'ip_pool_network' verbose_name = _('Network')