Evvverything!
This commit is contained in:
parent
8dbd77dc79
commit
81bbcda8eb
|
@ -0,0 +1,3 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ApiConfig(AppConfig):
|
||||
name = 'api'
|
|
@ -0,0 +1,3 @@
|
|||
from django.db import models
|
||||
|
||||
# Create your models here.
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,9 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from . import views as api_views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'asblock/free-as/$', api_views.asblockFreeAS, name='asblock-free-as'),
|
||||
url(r'asblock/free-subnet/$', api_views.freeSubnet, name='inetnum-free-subnet'),
|
||||
|
||||
]
|
|
@ -0,0 +1,107 @@
|
|||
#from django.shortcuts import render
|
||||
from django.http import JsonResponse
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.contrib.auth.views import login_required
|
||||
|
||||
from whoisdb.models import ASBlock, ASNumber, InetNum
|
||||
|
||||
@login_required
|
||||
def asblockFreeAS(request):
|
||||
|
||||
ret = {
|
||||
"success": False,
|
||||
"errorMsg": None,
|
||||
"number": -1,
|
||||
}
|
||||
|
||||
try:
|
||||
blockName = request.GET.get('block', None)
|
||||
if not blockName:
|
||||
raise ValidationError("No block given")
|
||||
|
||||
try:
|
||||
mnts = request.user.maintainer_set.all()
|
||||
block = ASBlock.objects.filter(mnt_by__in=mnts).distinct().get(handle=blockName)
|
||||
if block.asblock_set.count() > 0:
|
||||
raise ValidationError("AS Block already has sub AS Blocks")
|
||||
if block.asnumber_set.count() > 0:
|
||||
num = block.asnumber_set.order_by("-number")[0].number + 1
|
||||
if num > block.asEnd:
|
||||
num = None
|
||||
for n in range(block.asBegin, block.asEnd+1):
|
||||
try:
|
||||
ASNumber.objects.get(number=n)
|
||||
except ASNumber.DoesNotExist:
|
||||
num = n
|
||||
break
|
||||
if not num:
|
||||
raise ValidationError("No free AS Number in block")
|
||||
ret["number"] = num
|
||||
else:
|
||||
ret["number"] = block.asBegin
|
||||
except ASBlock.DoesNotExist:
|
||||
raise ValidationError("Could not get AS Block")
|
||||
|
||||
ret["success"] = True
|
||||
except ValidationError as e:
|
||||
ret["errorMsg"] = e.message
|
||||
return JsonResponse(ret)
|
||||
@login_required
|
||||
def freeSubnet(request):
|
||||
|
||||
ret = {
|
||||
"success": False,
|
||||
"errorMsg": None,
|
||||
"network": None,
|
||||
}
|
||||
|
||||
|
||||
try:
|
||||
parentRangeName = request.GET.get('parentRange', None)
|
||||
if not parentRangeName:
|
||||
raise ValidationError("No subnet given")
|
||||
|
||||
parentRange = None
|
||||
try:
|
||||
mnts = request.user.maintainer_set.all()
|
||||
parentRange = InetNum.objects.filter(mnt_by__in=mnts).distinct().get(handle=parentRangeName)
|
||||
except InetNum.DoesNotExist:
|
||||
raise ValidationError("Parent range does not exist / is not maintained by you")
|
||||
|
||||
prefixLen = 0
|
||||
try:
|
||||
prefixLen = int(request.GET.get("prefixLen", 27))
|
||||
if prefixLen < 8 or \
|
||||
(parentRange.protocol == InetNum.IPv4 and prefixLen > 32) or \
|
||||
(parentRange.protocol == InetNum.IPv6 and prefixLen > 128):
|
||||
raise ValidationError("Given prefix length is out of range")
|
||||
except ValueError:
|
||||
raise ValidationError("PrefixLen is not a number")
|
||||
nets = list(parentRange.getNetwork().subnets())
|
||||
for subRange in parentRange.inetnum_set.all():
|
||||
newNet = None
|
||||
for net in nets:
|
||||
if subRange.getNetwork().network_address in net:
|
||||
newNet = net
|
||||
if not newNet:
|
||||
# critical error, we want a 500 here
|
||||
raise ValueError("Subnet not in range")
|
||||
|
||||
nets.remove(newNet)
|
||||
nets.extend(newNet.address_exclude(subRange.getNetwork()))
|
||||
|
||||
nets = sorted(nets)
|
||||
usableNet = None
|
||||
for net in nets:
|
||||
if net.prefixlen <= prefixLen:
|
||||
usableNet = net
|
||||
break
|
||||
|
||||
if not usableNet:
|
||||
raise ValidationError("No space left in given range")
|
||||
|
||||
ret["network"] = "%s/%s" % (usableNet.network_address, prefixLen)
|
||||
ret["success"] = True
|
||||
except ValidationError as e:
|
||||
ret["errorMsg"] = e.message
|
||||
return JsonResponse(ret)
|
|
@ -39,10 +39,12 @@ INSTALLED_APPS = [
|
|||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'crispy_forms',
|
||||
'formtools',
|
||||
'dncore',
|
||||
'whoisdb',
|
||||
'rrequests',
|
||||
'domains',
|
||||
'api',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
|
|
@ -21,6 +21,7 @@ import dncore.views
|
|||
import whoisdb.urls
|
||||
import rrequests.urls
|
||||
import domains.urls
|
||||
import api.urls
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -32,4 +33,5 @@ urlpatterns = [
|
|||
url(r'^whoisdb/', include(whoisdb.urls, namespace='whoisdb')),
|
||||
url(r'^rrequests/', include(rrequests.urls, namespace='rrequests')),
|
||||
url(r'^domains/', include(domains.urls, namespace='domains')),
|
||||
url(r'^api/', include(api.urls, namespace='api')),
|
||||
]
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10.5 on 2017-03-22 18:01
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('domains', '0002_auto_20170321_1854'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='nameserver',
|
||||
name='name',
|
||||
field=models.CharField(max_length=256),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,76 @@
|
|||
<script>
|
||||
function findASNumber(step) {
|
||||
// extra field foo
|
||||
var ef = ""
|
||||
if(step >= 0)
|
||||
ef = "" + step + "-";
|
||||
|
||||
var asNumInp = $('#div_id_'+ef+'number input');
|
||||
asNumInp.val("");
|
||||
asNumInp.attr("placeholder", "Getting AS number...");
|
||||
|
||||
var blockOpt = $('#id_'+ef+'asblock option:selected');
|
||||
if(blockOpt.val()) {
|
||||
$.get("{% url "api:asblock-free-as" %}", {block: blockOpt.text()}, function(data) {
|
||||
if(data.success) {
|
||||
asNumInp.attr("placeholder", "")
|
||||
asNumInp.val(data.number);
|
||||
} else {
|
||||
errorMsg = "Nothing returned via API";
|
||||
if(data.errorMsg)
|
||||
errorMsg = data.errorMsg;
|
||||
asNumInp.attr("placeholder", data.errorMsg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
asNumInp.attr("placeholder", "No AS Block selected!");
|
||||
}
|
||||
}
|
||||
|
||||
function findPrefix(size, step) {
|
||||
// extra field foo
|
||||
var ef = ""
|
||||
if(step >= 0)
|
||||
ef = "" + step + "-";
|
||||
|
||||
var netInp = $('#div_id_'+ef+'prefix input');
|
||||
var netInpText = netInp.val();
|
||||
netInp.val("");
|
||||
netInp.attr("placeholder", "Searching free prefix...");
|
||||
|
||||
var parentRangeOpt = $('#id_'+ef+'parent_range option:selected');
|
||||
if(parentRangeOpt.val()) {
|
||||
var prefixLen = 27;
|
||||
var m = netInpText.match("([0-9.:]+/)?(\\d+)");
|
||||
console.log(prefixLen)
|
||||
console.log(netInpText);
|
||||
if(m) {
|
||||
prefixLen = m[2];
|
||||
}
|
||||
|
||||
|
||||
$.get("{% url "api:inetnum-free-subnet" %}", {parentRange: parentRangeOpt.text(), prefixLen: prefixLen}, function(data) {
|
||||
if(data.success) {
|
||||
netInp.attr("placeholder", "")
|
||||
netInp.val(data.network);
|
||||
} else {
|
||||
errorMsg = "Nothing returned via API";
|
||||
if(data.errorMsg)
|
||||
errorMsg = data.errorMsg;
|
||||
netInp.attr("placeholder", data.errorMsg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
netInp.attr("placeholder", "No Parent Range selected!");
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
console.log("NOOT NOOT");
|
||||
$('#div_id_number label').append(' <small>(<a onClick="findASNumber();">next free number</a>)</small>');
|
||||
$('#div_id_0-number label').append(' <small>(<a onClick="findASNumber(0);">next free number</a>)</small>');
|
||||
$('#div_id_prefix label').append(' <small>(<a onClick="findPrefix(27);">next free /27</a>)</small>');
|
||||
$('#div_id_1-prefix label').append(' <small>(<a onClick="findPrefix(27, 1);">next free /27</a>)</small>');
|
||||
});
|
||||
</script>
|
||||
|
|
@ -17,5 +17,8 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "whoisdb/create_js.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
</p>
|
||||
|
||||
</p>
|
||||
Create <a href="{% url "whoisdb:mnt-create" %}">new Maintainer</a>, create <a href="{% url "whoisdb:contact-create" %}">new Contact</a>, <a href="{% url "rrequests:dashboard" %}">request resources</a>{% if netblocks %}, create <a href="{% url "whoisdb:inetnum-create" %}">Subnet</a>{% endif %}{% if asblocks %}, create <a href="{% url "whoisdb:asnumber-create" %}">AS</a>, create <a href="{% url "whoisdb:asblock-create" %}">ASblock</a>{% endif %}
|
||||
Create <a href="{% url "whoisdb:mnt-create" %}">new Maintainer</a>, create <a href="{% url "whoisdb:contact-create" %}">new Contact</a>, <a href="{% url "rrequests:dashboard" %}">request resources</a>{% if netblocks %}, create <a href="{% url "whoisdb:inetnum-create" %}">Subnet</a>{% endif %}{% if asblocks %}, create <a href="{% url "whoisdb:asnumber-create" %}">AS</a>, create <a href="{% url "whoisdb:asblock-create" %}">ASblock</a>{% endif %}{% if netblocks and asblocks %}, create <a href="{% url "whoisdb:asandsubnet-wizard" %}">AS / Subnet pair</a>{% endif %}
|
||||
</p>
|
||||
<!--
|
||||
<h3>Create Database Objects</h3>
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
{% extends "base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Create AS & Net - Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</div>
|
||||
<div class="panel-body">
|
||||
<p>Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}</p>
|
||||
<p>{{ message }}</p>
|
||||
<form action="" method="post">{% csrf_token %}
|
||||
<table>
|
||||
{{ wizard.management_form }}
|
||||
{% if wizard.form.forms %}
|
||||
{{ wizard.form.management_form }}
|
||||
{% for form in wizard.form.forms %}
|
||||
{{ form }}
|
||||
{% endfor %}
|
||||
|
||||
{% else %}
|
||||
{{ wizard.form|crispy }}
|
||||
{% endif %}
|
||||
</table>
|
||||
{% if wizard.steps.prev %}
|
||||
<button class="btn" name="wizard_goto_step" type="submit" value="{{ wizard.steps.first }}">Back</button>
|
||||
{% endif %}
|
||||
{% if wizard.steps.next %}
|
||||
{# <button class="btn" name="wizard_goto_step" type="submit" value="{{ wizard.steps.next }}">Next</button> #}
|
||||
{# <button class="btn" name="wizard_goto_step" type="submit" value="{{ wizard.steps.next }}">{% if wizard.steps.next %}Next{% else %}Create{% endif %}</button> #}
|
||||
{% else %}
|
||||
{# <button class="btn btn-primary" type="submit" value="submit">Create</button> #}
|
||||
{% endif %}
|
||||
<button class="btn" type="submit" value="{{ wizard.steps.next }}">{% if wizard.steps.next %}Next{% else %}Create{% endif %}</button>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% include "whoisdb/create_js.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -37,4 +37,7 @@ urlpatterns = [
|
|||
url(r'^asnumber/show/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDetail.as_view(), name='asnumber-detail'),
|
||||
url(r'^asnumber/edit/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberEdit.as_view(), name='asnumber-edit'),
|
||||
url(r'^asnumber/delete/(?P<handle>[A-Z0-9-]+)/$', whoisdb_views.ASNumberDelete.as_view(), name='asnumber-delete'),
|
||||
|
||||
|
||||
url(r'^assubnetset/create/$', whoisdb_views.ASAndSubnetWizard.as_view(), name='asandsubnet-wizard'),
|
||||
]
|
||||
|
|
|
@ -5,6 +5,8 @@ from django.http import HttpResponseRedirect, Http404
|
|||
from django.urls import reverse, reverse_lazy
|
||||
from django.views.generic import DetailView, CreateView, UpdateView
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib import messages
|
||||
from formtools.wizard.views import SessionWizardView
|
||||
|
||||
from .models import Maintainer, Contact, InetNum, ASBlock, ASNumber
|
||||
from .forms import MntForm, MntInitialForm, ContactForm, ContactInitialForm, InetNumForm, ASBlockForm, ASNumberForm
|
||||
|
@ -307,3 +309,37 @@ class ASNumberDelete(MntGenericMixin, LoginRequiredMixin, DeleteCheckView):
|
|||
slug_field = "handle"
|
||||
slug_url_kwarg = "handle"
|
||||
success_url = reverse_lazy("whoisdb:dashboard")
|
||||
|
||||
|
||||
class ASAndSubnetWizard(LoginRequiredMixin, SessionWizardView):
|
||||
form_list = [ASNumberForm, InetNumForm]
|
||||
template_name = "whoisdb/wizard.html"
|
||||
|
||||
def get_form_initial(self, step):
|
||||
return {"handle": "AUTO"}
|
||||
|
||||
def done(self, form_list, **kwargs):
|
||||
fl = list(form_list)
|
||||
asNum = fl[0].save()
|
||||
net = fl[1].save()
|
||||
|
||||
messages.info(self.request, "The following objects have been created: AS %s %s, Subnet %s %s" % (asNum.handle, asNum.number, net.handle, net.getNetwork()))
|
||||
|
||||
return HttpResponseRedirect(reverse("whoisdb:dashboard"))
|
||||
|
||||
def get_form_kwargs(self, *args, **kwargs):
|
||||
kwargs = super(ASAndSubnetWizard, self).get_form_kwargs(*args, **kwargs)
|
||||
kwargs["user"] = self.request.user
|
||||
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, *args, **kwargs):
|
||||
d = super(ASAndSubnetWizard, self).get_context_data(*args, **kwargs)
|
||||
|
||||
step = d["wizard"]["steps"].step1
|
||||
if step == 1:
|
||||
d["message"] = "Create an AS object"
|
||||
elif step == 2:
|
||||
d["message"] = "Create a Subnet"
|
||||
|
||||
return d
|
||||
|
|
Loading…
Reference in New Issue