diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py
index 483ed7221..db8ff7a85 100644
--- a/netbox/ipam/forms.py
+++ b/netbox/ipam/forms.py
@@ -45,6 +45,21 @@ class VRFBulkDeleteForm(ConfirmationForm):
pk = forms.ModelMultipleChoiceField(queryset=VRF.objects.all(), widget=forms.MultipleHiddenInput)
+#
+# RIRs
+#
+
+class RIRForm(forms.ModelForm, BootstrapMixin):
+
+ class Meta:
+ model = RIR
+ fields = ['name', 'slug']
+
+
+class RIRBulkDeleteForm(ConfirmationForm):
+ pk = forms.ModelMultipleChoiceField(queryset=RIR.objects.all(), widget=forms.MultipleHiddenInput)
+
+
#
# Aggregates
#
diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py
index 35c8e702b..b00f16104 100644
--- a/netbox/ipam/models.py
+++ b/netbox/ipam/models.py
@@ -91,6 +91,9 @@ class RIR(models.Model):
def __unicode__(self):
return self.name
+ def get_absolute_url(self):
+ return "{}?rir={}".format(reverse('ipam:aggregate_list'), self.slug)
+
class Aggregate(models.Model):
"""
diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py
index bb5418f54..adf8617b2 100644
--- a/netbox/ipam/tables.py
+++ b/netbox/ipam/tables.py
@@ -1,9 +1,13 @@
import django_tables2 as tables
from django_tables2.utils import Accessor
-from .models import Aggregate, Prefix, IPAddress, VLAN, VRF
+from .models import VRF, RIR, Aggregate, Prefix, IPAddress, VLAN
+RIR_EDIT_LINK = """
+{% if perms.ipam.change_rir %}Edit{% endif %}
+"""
+
UTILIZATION_GRAPH = """
{% with record.get_utilization as percentage %}
@@ -59,6 +63,26 @@ class VRFTable(tables.Table):
}
+#
+# RIRs
+#
+
+class RIRTable(tables.Table):
+ pk = tables.CheckBoxColumn(visible=False, default='')
+ name = tables.LinkColumn(verbose_name='Name')
+ aggregate_count = tables.Column(verbose_name='Aggregates')
+ slug = tables.Column(verbose_name='Slug')
+ edit = tables.TemplateColumn(template_code=RIR_EDIT_LINK, verbose_name='')
+
+ class Meta:
+ model = RIR
+ fields = ('pk', 'name', 'aggregate_count', 'slug', 'edit')
+ empty_text = "No aggregates were found."
+ attrs = {
+ 'class': 'table table-hover',
+ }
+
+
#
# Aggregates
#
diff --git a/netbox/ipam/urls.py b/netbox/ipam/urls.py
index a97ee030a..97d7d7543 100644
--- a/netbox/ipam/urls.py
+++ b/netbox/ipam/urls.py
@@ -3,6 +3,8 @@ from django.conf.urls import url
from . import views
urlpatterns = [
+
+ # VRFs
url(r'^vrfs/$', views.VRFListView.as_view(), name='vrf_list'),
url(r'^vrfs/add/$', views.VRFEditView.as_view(), name='vrf_add'),
url(r'^vrfs/import/$', views.VRFBulkImportView.as_view(), name='vrf_import'),
@@ -12,6 +14,13 @@ urlpatterns = [
url(r'^vrfs/(?P
\d+)/edit/$', views.VRFEditView.as_view(), name='vrf_edit'),
url(r'^vrfs/(?P\d+)/delete/$', views.VRFDeleteView.as_view(), name='vrf_delete'),
+ # RIRs
+ url(r'^rirs/$', views.RIRListView.as_view(), name='rir_list'),
+ url(r'^rirs/add/$', views.RIREditView.as_view(), name='rir_add'),
+ url(r'^rirs/delete/$', views.RIRBulkDeleteView.as_view(), name='rir_bulk_delete'),
+ url(r'^rirs/(?P[\w-]+)/edit/$', views.RIREditView.as_view(), name='rir_edit'),
+
+ # Aggregates
url(r'^aggregates/$', views.AggregateListView.as_view(), name='aggregate_list'),
url(r'^aggregates/add/$', views.AggregateEditView.as_view(), name='aggregate_add'),
url(r'^aggregates/import/$', views.AggregateBulkImportView.as_view(), name='aggregate_import'),
@@ -21,6 +30,7 @@ urlpatterns = [
url(r'^aggregates/(?P\d+)/edit/$', views.AggregateEditView.as_view(), name='aggregate_edit'),
url(r'^aggregates/(?P\d+)/delete/$', views.AggregateDeleteView.as_view(), name='aggregate_delete'),
+ # Prefixes
url(r'^prefixes/$', views.PrefixListView.as_view(), name='prefix_list'),
url(r'^prefixes/add/$', views.PrefixEditView.as_view(), name='prefix_add'),
url(r'^prefixes/import/$', views.PrefixBulkImportView.as_view(), name='prefix_import'),
@@ -31,6 +41,7 @@ urlpatterns = [
url(r'^prefixes/(?P\d+)/delete/$', views.PrefixDeleteView.as_view(), name='prefix_delete'),
url(r'^prefixes/(?P\d+)/ip-addresses/$', views.prefix_ipaddresses, name='prefix_ipaddresses'),
+ # IP addresses
url(r'^ip-addresses/$', views.IPAddressListView.as_view(), name='ipaddress_list'),
url(r'^ip-addresses/add/$', views.IPAddressEditView.as_view(), name='ipaddress_add'),
url(r'^ip-addresses/import/$', views.IPAddressBulkImportView.as_view(), name='ipaddress_import'),
@@ -40,6 +51,7 @@ urlpatterns = [
url(r'^ip-addresses/(?P\d+)/edit/$', views.IPAddressEditView.as_view(), name='ipaddress_edit'),
url(r'^ip-addresses/(?P\d+)/delete/$', views.IPAddressDeleteView.as_view(), name='ipaddress_delete'),
+ # VLANs
url(r'^vlans/$', views.VLANListView.as_view(), name='vlan_list'),
url(r'^vlans/add/$', views.VLANEditView.as_view(), name='vlan_add'),
url(r'^vlans/import/$', views.VLANBulkImportView.as_view(), name='vlan_import'),
@@ -48,4 +60,5 @@ urlpatterns = [
url(r'^vlans/(?P\d+)/$', views.vlan, name='vlan'),
url(r'^vlans/(?P\d+)/edit/$', views.VLANEditView.as_view(), name='vlan_edit'),
url(r'^vlans/(?P\d+)/delete/$', views.VLANDeleteView.as_view(), name='vlan_delete'),
+
]
diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index e5be9ed37..9a0f53414 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -1,9 +1,10 @@
from netaddr import IPSet
-
from django_tables2 import RequestConfig
+
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.db.models import Count
from django.shortcuts import get_object_or_404, render
from dcim.models import Device
@@ -16,10 +17,10 @@ from .forms import AggregateForm, AggregateImportForm, AggregateBulkEditForm, Ag
AggregateFilterForm, PrefixForm, PrefixImportForm, PrefixBulkEditForm, PrefixBulkDeleteForm, PrefixFilterForm,\
IPAddressForm, IPAddressImportForm, IPAddressBulkEditForm, IPAddressBulkDeleteForm, IPAddressFilterForm, VLANForm,\
VLANImportForm, VLANBulkEditForm, VLANBulkDeleteForm, VRFForm, VRFImportForm, VRFBulkEditForm, VRFBulkDeleteForm,\
- VLANFilterForm
-from .models import VRF, Aggregate, Prefix, IPAddress, VLAN
-from .tables import AggregateTable, PrefixTable, PrefixBriefTable, IPAddressBriefTable, IPAddressTable, VLANTable,\
- VRFTable
+ VLANFilterForm, RIRForm, RIRBulkDeleteForm
+from .models import VRF, RIR, Aggregate, Prefix, IPAddress, VLAN
+from .tables import VRFTable, RIRTable, AggregateTable, PrefixTable, PrefixBriefTable, IPAddressBriefTable,\
+ IPAddressTable, VLANTable
def add_available_prefixes(parent, prefix_list):
@@ -107,6 +108,32 @@ class VRFBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
default_redirect_url = 'ipam:vrf_list'
+#
+# RIRs
+#
+
+class RIRListView(ObjectListView):
+ queryset = RIR.objects.annotate(aggregate_count=Count('aggregates'))
+ table = RIRTable
+ edit_permissions = ['ipam.change_rir', 'ipam.delete_rir']
+ template_name = 'ipam/rir_list.html'
+
+
+class RIREditView(PermissionRequiredMixin, ObjectEditView):
+ permission_required = 'ipam.change_rir'
+ model = RIR
+ form_class = RIRForm
+ success_url = 'ipam:rir_list'
+ cancel_url = 'ipam:rir_list'
+
+
+class RIRBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
+ permission_required = 'ipam.delete_rir'
+ cls = RIR
+ form = RIRBulkDeleteForm
+ default_redirect_url = 'ipam:rir_list'
+
+
#
# Aggregates
#
diff --git a/netbox/templates/_base.html b/netbox/templates/_base.html
index 46652e63c..c37f8dcce 100644
--- a/netbox/templates/_base.html
+++ b/netbox/templates/_base.html
@@ -101,7 +101,7 @@
{% endif %}
-
+
IP Space
diff --git a/netbox/templates/ipam/inc/rir_table.html b/netbox/templates/ipam/inc/rir_table.html
new file mode 100644
index 000000000..d39eb1e97
--- /dev/null
+++ b/netbox/templates/ipam/inc/rir_table.html
@@ -0,0 +1,14 @@
+{% load render_table from django_tables2 %}
+{% if perms.ipam.delete_rir %}
+
+{% else %}
+ {% render_table table table_template|default:'table.html' %}
+{% endif %}
diff --git a/netbox/templates/ipam/rir_list.html b/netbox/templates/ipam/rir_list.html
new file mode 100644
index 000000000..8c2ca0e09
--- /dev/null
+++ b/netbox/templates/ipam/rir_list.html
@@ -0,0 +1,21 @@
+{% extends '_base.html' %}
+{% load helpers %}
+
+{% block title %}RIRs{% endblock %}
+
+{% block content %}
+
+RIRs
+
+
+ {% include 'ipam/inc/rir_table.html' %}
+
+
+{% endblock %}