From c00eea79911269351a27acc28be92d2b90abe0d1 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 15 Jun 2017 14:28:35 -0400 Subject: [PATCH 01/14] Post-release version bump --- netbox/netbox/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 5bd4d2f6e..8e31ce8e9 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -13,7 +13,7 @@ except ImportError: ) -VERSION = '2.0.7' +VERSION = '2.0.8-dev' # Import required configuration parameters ALLOWED_HOSTS = DATABASE = SECRET_KEY = None From 9d89eed873d628d4f5c31e87a4866dbe4b9da39b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 16 Jun 2017 09:32:58 -0400 Subject: [PATCH 02/14] Fixes #1281: Show LLDP neighbors tab on device view only if necessary conditions are met --- netbox/templates/dcim/inc/device_header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/inc/device_header.html b/netbox/templates/dcim/inc/device_header.html index 9f31c73fc..6861abf4a 100644 --- a/netbox/templates/dcim/inc/device_header.html +++ b/netbox/templates/dcim/inc/device_header.html @@ -45,7 +45,7 @@ From ea869d4ffc127575f45e8574319bf1575c41bba0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 16 Jun 2017 10:01:47 -0400 Subject: [PATCH 03/14] Fixes #1282: Fixed tooltips on "mark connected/planned" toggle buttons for device connections --- netbox/templates/dcim/device.html | 4 ++-- netbox/templates/dcim/inc/consoleport.html | 24 +++++++++---------- .../templates/dcim/inc/consoleserverport.html | 24 +++++++++---------- netbox/templates/dcim/inc/interface.html | 2 +- netbox/templates/dcim/inc/poweroutlet.html | 24 +++++++++---------- netbox/templates/dcim/inc/powerport.html | 24 +++++++++---------- 6 files changed, 51 insertions(+), 51 deletions(-) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index a6e5d1dbe..0c63548f6 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -591,7 +591,7 @@ function toggleConnection(elem, api_url) { success: function() { elem.parents('tr').removeClass('success').addClass('info'); elem.removeClass('connected btn-warning').addClass('btn-success'); - elem.attr('title', 'Mark connected'); + elem.attr('title', 'Mark installed'); elem.children('i').removeClass('glyphicon glyphicon-ban-circle').addClass('fa fa-plug') } }); @@ -610,7 +610,7 @@ function toggleConnection(elem, api_url) { success: function() { elem.parents('tr').removeClass('info').addClass('success'); elem.removeClass('btn-success').addClass('connected btn-warning'); - elem.attr('title', 'Mark disconnected'); + elem.attr('title', 'Mark planned'); elem.children('i').removeClass('fa fa-plug').addClass('glyphicon glyphicon-ban-circle') } }); diff --git a/netbox/templates/dcim/inc/consoleport.html b/netbox/templates/dcim/inc/consoleport.html index 58f5fa7de..114f434c1 100644 --- a/netbox/templates/dcim/inc/consoleport.html +++ b/netbox/templates/dcim/inc/consoleport.html @@ -24,24 +24,24 @@ {% if perms.dcim.change_consoleport %} {% if cp.cs_port %} {% if cp.connection_status %} - - + + {% else %} - - + + {% endif %} - - + + {% else %} - - + + {% endif %} - - + + {% endif %} {% if perms.dcim.delete_consoleport %} @@ -50,8 +50,8 @@ {% else %} - - + + {% endif %} {% endif %} diff --git a/netbox/templates/dcim/inc/consoleserverport.html b/netbox/templates/dcim/inc/consoleserverport.html index cfeab9212..e40009881 100644 --- a/netbox/templates/dcim/inc/consoleserverport.html +++ b/netbox/templates/dcim/inc/consoleserverport.html @@ -24,24 +24,24 @@ {% if perms.dcim.change_consoleserverport %} {% if csp.connected_console %} {% if csp.connected_console.connection_status %} - - + + {% else %} - - + + {% endif %} - - + + {% else %} - - + + {% endif %} - - + + {% endif %} {% if perms.dcim.delete_consoleserverport %} @@ -50,8 +50,8 @@ {% else %} - - + + {% endif %} {% endif %} diff --git a/netbox/templates/dcim/inc/interface.html b/netbox/templates/dcim/inc/interface.html index 86e480710..4f1ff00e5 100644 --- a/netbox/templates/dcim/inc/interface.html +++ b/netbox/templates/dcim/inc/interface.html @@ -72,7 +72,7 @@ {% else %} - + {% endif %} diff --git a/netbox/templates/dcim/inc/poweroutlet.html b/netbox/templates/dcim/inc/poweroutlet.html index eef4874d6..061b3c682 100644 --- a/netbox/templates/dcim/inc/poweroutlet.html +++ b/netbox/templates/dcim/inc/poweroutlet.html @@ -24,24 +24,24 @@ {% if perms.dcim.change_poweroutlet %} {% if po.connected_port %} {% if po.connected_port.connection_status %} - - + + {% else %} - - + + {% endif %} - - + + {% else %} - - + + {% endif %} - - + + {% endif %} {% if perms.dcim.delete_poweroutlet %} @@ -50,8 +50,8 @@ {% else %} - - + + {% endif %} {% endif %} diff --git a/netbox/templates/dcim/inc/powerport.html b/netbox/templates/dcim/inc/powerport.html index ce4ac6967..63da4ad84 100644 --- a/netbox/templates/dcim/inc/powerport.html +++ b/netbox/templates/dcim/inc/powerport.html @@ -24,24 +24,24 @@ {% if perms.dcim.change_powerport %} {% if pp.power_outlet %} {% if pp.connection_status %} - - + + {% else %} - - + + {% endif %} - - + + {% else %} - - + + {% endif %} - - + + {% endif %} {% if perms.dcim.delete_powerport %} @@ -50,8 +50,8 @@ {% else %} - - + + {% endif %} {% endif %} From afdf5750b585ad5abad060d4ecf016bee9a1c5e7 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 16 Jun 2017 12:45:42 -0400 Subject: [PATCH 04/14] Fixes #1279: Fix primary_ip assignment during IP address import --- netbox/ipam/forms.py | 17 ++++++++++++----- netbox/ipam/views.py | 13 ------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/netbox/ipam/forms.py b/netbox/ipam/forms.py index 78deadd45..a5c3923a5 100644 --- a/netbox/ipam/forms.py +++ b/netbox/ipam/forms.py @@ -641,16 +641,23 @@ class IPAddressCSVForm(forms.ModelForm): # Set interface if self.cleaned_data['device'] and self.cleaned_data['interface_name']: - self.instance.interface = Interface.objects.get(device=self.cleaned_data['device'], - name=self.cleaned_data['interface_name']) + self.instance.interface = Interface.objects.get( + device=self.cleaned_data['device'], + name=self.cleaned_data['interface_name'] + ) + + ipaddress = super(IPAddressCSVForm, self).save(*args, **kwargs) + # Set as primary for device if self.cleaned_data['is_primary']: + device = self.cleaned_data['device'] if self.instance.address.version == 4: - self.instance.primary_ip4_for = self.cleaned_data['device'] + device.primary_ip4 = ipaddress elif self.instance.address.version == 6: - self.instance.primary_ip6_for = self.cleaned_data['device'] + device.primary_ip6 = ipaddress + device.save() - return super(IPAddressCSVForm, self).save(*args, **kwargs) + return ipaddress class IPAddressBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm): diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py index 3cc54d252..74432d180 100644 --- a/netbox/ipam/views.py +++ b/netbox/ipam/views.py @@ -665,19 +665,6 @@ class IPAddressBulkImportView(PermissionRequiredMixin, BulkImportView): table = tables.IPAddressTable default_return_url = 'ipam:ipaddress_list' - def save_obj(self, obj): - obj.save() - - # Update primary IP for device if needed. The Device must be updated directly in the database; otherwise we risk - # overwriting a previous IP assignment from the same import (see #861). - try: - if obj.family == 4 and obj.primary_ip4_for: - Device.objects.filter(pk=obj.primary_ip4_for.pk).update(primary_ip4=obj) - elif obj.family == 6 and obj.primary_ip6_for: - Device.objects.filter(pk=obj.primary_ip6_for.pk).update(primary_ip6=obj) - except Device.DoesNotExist: - pass - class IPAddressBulkEditView(PermissionRequiredMixin, BulkEditView): permission_required = 'ipam.change_ipaddress' From 5aba1d9aec316443fa1e8358e92debffeadb3c6a Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 19 Jun 2017 09:20:03 -0400 Subject: [PATCH 05/14] Fixes #1288: Corrected permission name for deleting image attachments --- netbox/extras/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 6469ba76a..06c852d68 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -25,7 +25,7 @@ class ImageAttachmentEditView(PermissionRequiredMixin, ObjectEditView): class ImageAttachmentDeleteView(PermissionRequiredMixin, ObjectDeleteView): - permission_required = 'dcim.delete_imageattachment' + permission_required = 'extras.delete_imageattachment' model = ImageAttachment def get_return_url(self, request, imageattachment): From adfcb5f7b691c0a7189783f7b603b3d589af69a0 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 26 Jun 2017 09:31:20 -0400 Subject: [PATCH 06/14] Fixes #1295: Docstring typo --- netbox/utilities/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py index 30d008a48..055f9fbba 100644 --- a/netbox/utilities/views.py +++ b/netbox/utilities/views.py @@ -234,7 +234,7 @@ class ObjectDeleteView(GetReturnURLMixin, View): """ Delete a single object. - model: The model of the object being edited + model: The model of the object being deleted template_name: The name of the template default_return_url: Name of the URL to which the user is redirected after deleting the object """ From 3f82be71929d080f4eec4446a13f3bdfc593606d Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Mon, 26 Jun 2017 17:36:24 -0400 Subject: [PATCH 07/14] Closes #1298: Calculate prefix utilization based on its status (container or non-container) --- netbox/ipam/models.py | 32 ++++++++++++++++++-------------- netbox/ipam/tables.py | 2 +- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/netbox/ipam/models.py b/netbox/ipam/models.py index 89ee0facc..208d46c4c 100644 --- a/netbox/ipam/models.py +++ b/netbox/ipam/models.py @@ -1,6 +1,6 @@ from __future__ import unicode_literals -from netaddr import IPNetwork, cidr_merge +from netaddr import IPNetwork, IPSet from django.conf import settings from django.contrib.contenttypes.fields import GenericRelation @@ -206,13 +206,9 @@ class Aggregate(CreatedUpdatedModel, CustomFieldModel): """ Determine the prefix utilization of the aggregate and return it as a percentage. """ - child_prefixes = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) - # Remove overlapping prefixes from list of children - networks = cidr_merge([c.prefix for c in child_prefixes]) - children_size = float(0) - for p in networks: - children_size += p.size - return int(children_size / self.prefix.size * 100) + queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix)) + child_prefixes = IPSet([p.prefix for p in queryset]) + return int(float(child_prefixes.size) / self.prefix.size * 100) @python_2_unicode_compatible @@ -370,13 +366,21 @@ class Prefix(CreatedUpdatedModel, CustomFieldModel): def get_utilization(self): """ - Determine the utilization of the prefix and return it as a percentage. + Determine the utilization of the prefix and return it as a percentage. For Prefixes with a status of + "container", calculate utilization based on child prefixes. For all others, count child IP addresses. """ - child_count = IPAddress.objects.filter(address__net_contained_or_equal=str(self.prefix), vrf=self.vrf).count() - prefix_size = self.prefix.size - if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool: - prefix_size -= 2 - return int(float(child_count) / prefix_size * 100) + if self.status == PREFIX_STATUS_CONTAINER: + queryset = Prefix.objects.filter(prefix__net_contained=str(self.prefix), vrf=self.vrf) + child_prefixes = IPSet([p.prefix for p in queryset]) + return int(float(child_prefixes.size) / self.prefix.size * 100) + else: + child_count = IPAddress.objects.filter( + address__net_contained_or_equal=str(self.prefix), vrf=self.vrf + ).count() + prefix_size = self.prefix.size + if self.family == 4 and self.prefix.prefixlen < 31 and not self.is_pool: + prefix_size -= 2 + return int(float(child_count) / prefix_size * 100) @property def new_subnet(self): diff --git a/netbox/ipam/tables.py b/netbox/ipam/tables.py index 767bd2cec..acb29f9e0 100644 --- a/netbox/ipam/tables.py +++ b/netbox/ipam/tables.py @@ -241,7 +241,7 @@ class PrefixTable(BaseTable): prefix = tables.TemplateColumn(PREFIX_LINK, attrs={'th': {'style': 'padding-left: 17px'}}) status = tables.TemplateColumn(STATUS_LABEL) vrf = tables.TemplateColumn(VRF_LINK, verbose_name='VRF') - get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='IP Usage') + get_utilization = tables.TemplateColumn(UTILIZATION_GRAPH, orderable=False, verbose_name='Utilization') tenant = tables.TemplateColumn(TENANT_LINK) site = tables.LinkColumn('dcim:site', args=[Accessor('site.slug')]) vlan = tables.LinkColumn('ipam:vlan', args=[Accessor('vlan.pk')], verbose_name='VLAN') From 97b67d0f93a197c100ad68aaecc4dd3188f447bd Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 28 Jun 2017 12:05:26 -0400 Subject: [PATCH 08/14] Fixes #1299: Corrected permission to add a service to a device --- netbox/templates/dcim/device.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/templates/dcim/device.html b/netbox/templates/dcim/device.html index 0c63548f6..9a73fdd18 100644 --- a/netbox/templates/dcim/device.html +++ b/netbox/templates/dcim/device.html @@ -204,7 +204,7 @@ None {% endif %} - {% if perms.dcim.add_service %} + {% if perms.ipam.add_service %}