Skip to content

Commit

Permalink
Merge branch 'develop' into develop-2.1
Browse files Browse the repository at this point in the history
Conflicts:
	netbox/ipam/models.py
	netbox/netbox/settings.py
	netbox/templates/dcim/inc/interface.html
  • Loading branch information
jeremystretch committed Jul 6, 2017
2 parents 23a8ab1 + 342c86e commit be89a78
Show file tree
Hide file tree
Showing 18 changed files with 104 additions and 93 deletions.
2 changes: 1 addition & 1 deletion docs/data-model/extras.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Each line of the **device patterns** field represents a hierarchical layer withi
```
core-switch-[abcd]
dist-switch\d
access-switch\d+,oob-switch\d+
access-switch\d+;oob-switch\d+
```

Note that you can combine multiple regexes onto one line using semicolons. The order in which regexes are listed on a line is significant: devices matching the first regex will be rendered first, and subsequent groups will be rendered to the right of those.
Expand Down
4 changes: 4 additions & 0 deletions netbox/extras/api/customfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ def to_internal_value(self, data):

# Validate selected choice
if cf.type == CF_TYPE_SELECT:
try:
value = int(value)
except ValueError:
raise ValidationError("{}: Choice selections must be passed as integers.".format(field_name))
valid_choices = [c.pk for c in cf.choices.all()]
if value not in valid_choices:
raise ValidationError("Invalid choice for field {}: {}".format(field_name, value))
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ def image_upload(instance, filename):
path = 'image-attachments/'

# Rename the file to the provided name, if any. Attempt to preserve the file extension.
extension = filename.rsplit('.')[-1]
extension = filename.rsplit('.')[-1].lower()
if instance.name and extension in ['bmp', 'gif', 'jpeg', 'jpg', 'png']:
filename = '.'.join([instance.name, extension])
elif instance.name:
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def get_return_url(self, request, imageattachment):


class ImageAttachmentDeleteView(PermissionRequiredMixin, ObjectDeleteView):
permission_required = 'dcim.delete_imageattachment'
permission_required = 'extras.delete_imageattachment'
model = ImageAttachment

def get_return_url(self, request, imageattachment):
Expand Down
17 changes: 12 additions & 5 deletions netbox/ipam/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,16 +646,23 @@ def save(self, *args, **kwargs):

# 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):
Expand Down
30 changes: 17 additions & 13 deletions netbox/ipam/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,9 @@ def get_utilization(self):
"""
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 = netaddr.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 = netaddr.IPSet([p.prefix for p in queryset])
return int(float(child_prefixes.size) / self.prefix.size * 100)


@python_2_unicode_compatible
Expand Down Expand Up @@ -345,13 +341,21 @@ def get_available_ips(self):

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 = self.get_child_ips().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 = netaddr.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):
Expand Down
2 changes: 1 addition & 1 deletion netbox/ipam/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down
13 changes: 0 additions & 13 deletions netbox/ipam/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
6 changes: 3 additions & 3 deletions netbox/templates/dcim/device.html
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
None
</div>
{% endif %}
{% if perms.dcim.add_service %}
{% if perms.ipam.add_service %}
<div class="panel-footer text-right">
<a href="{% url 'dcim:service_assign' device=device.pk %}" class="btn btn-xs btn-primary">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Assign service
Expand Down Expand Up @@ -572,7 +572,7 @@
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')
}
});
Expand All @@ -591,7 +591,7 @@
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')
}
});
Expand Down
24 changes: 12 additions & 12 deletions netbox/templates/dcim/inc/consoleport.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@
{% if perms.dcim.change_consoleport %}
{% if cp.cs_port %}
{% if cp.connection_status %}
<a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" data="{{ cp.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
<a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" title="Mark planned" data="{{ cp.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
</a>
{% else %}
<a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ cp.pk }}">
<i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
<a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ cp.pk }}">
<i class="fa fa-plug" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:consoleport_disconnect' pk=cp.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
<a href="{% url 'dcim:consoleport_disconnect' pk=cp.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
</a>
{% else %}
<a href="{% url 'dcim:consoleport_connect' pk=cp.pk %}" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
<a href="{% url 'dcim:consoleport_connect' pk=cp.pk %}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit port"></i>
<a href="{% url 'dcim:consoleport_edit' pk=cp.pk %}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_consoleport %}
Expand All @@ -44,8 +44,8 @@
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:consoleport_delete' pk=cp.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete port"></i>
<a href="{% url 'dcim:consoleport_delete' pk=cp.pk %}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
Expand Down
24 changes: 12 additions & 12 deletions netbox/templates/dcim/inc/consoleserverport.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@
{% if perms.dcim.change_consoleserverport %}
{% if csp.connected_console %}
{% if csp.connected_console.connection_status %}
<a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" data="{{ csp.connected_console.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
<a href="#" class="btn btn-warning btn-xs consoleport-toggle connected" title="Mark planned" data="{{ csp.connected_console.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
</a>
{% else %}
<a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ csp.connected_console.pk }}">
<i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
<a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ csp.connected_console.pk }}">
<i class="fa fa-plug" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:consoleserverport_disconnect' pk=csp.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
<a href="{% url 'dcim:consoleserverport_disconnect' pk=csp.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
</a>
{% else %}
<a href="{% url 'dcim:consoleserverport_connect' pk=csp.pk %}" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
<a href="{% url 'dcim:consoleserverport_connect' pk=csp.pk %}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit port"></i>
<a href="{% url 'dcim:consoleserverport_edit' pk=csp.pk %}" title="Edit port" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_consoleserverport %}
Expand All @@ -50,8 +50,8 @@
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:consoleserverport_delete' pk=csp.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete port"></i>
<a href="{% url 'dcim:consoleserverport_delete' pk=csp.pk %}" title="Delete port" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion netbox/templates/dcim/inc/device_header.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ <h1>{{ device }}</h1>
<ul class="nav nav-tabs" style="margin-bottom: 20px">
<li role="presentation"{% if active_tab == 'info' %} class="active"{% endif %}><a href="{% url 'dcim:device' pk=device.pk %}">Info</a></li>
<li role="presentation"{% if active_tab == 'inventory' %} class="active"{% endif %}><a href="{% url 'dcim:device_inventory' pk=device.pk %}">Inventory</a></li>
{% if device.status %}
{% if device.status == 1 and device.platform.rpc_client and device.primary_ip %}
<li role="presentation"{% if active_tab == 'lldp-neighbors' %} class="active"{% endif %}><a href="{% url 'dcim:device_lldp_neighbors' pk=device.pk %}">LLDP Neighbors</a></li>
{% endif %}
</ul>
4 changes: 2 additions & 2 deletions netbox/templates/dcim/inc/interface.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<tr class="interface{% if not iface.enabled %} danger{% elif iface.connection and not iface.connection.connection_status %} info{% endif %}">
<tr class="interface{% if not iface.enabled %} danger{% elif iface.connection and iface.connection.connection_status %} success{% elif iface.connection and not iface.connection.connection_status %} info{% endif %}">
{% if selectable and perms.dcim.change_interface or perms.dcim.delete_interface %}
<td class="pk">
<input name="pk" type="checkbox" value="{{ iface.pk }}" />
Expand Down Expand Up @@ -76,7 +76,7 @@
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
</a>
{% else %}
<a href="#" class="btn btn-success btn-xs interface-toggle" data="{{ iface.connection.pk }}" title="Mark connected">
<a href="#" class="btn btn-success btn-xs interface-toggle" data="{{ iface.connection.pk }}" title="Mark installed">
<i class="fa fa-plug" aria-hidden="true"></i>
</a>
{% endif %}
Expand Down
24 changes: 12 additions & 12 deletions netbox/templates/dcim/inc/poweroutlet.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@
{% if perms.dcim.change_poweroutlet %}
{% if po.connected_port %}
{% if po.connected_port.connection_status %}
<a href="#" class="btn btn-warning btn-xs powerport-toggle connected" data="{{ po.connected_port.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true" title="Mark planned"></i>
<a href="#" class="btn btn-warning btn-xs powerport-toggle connected" title="Mark planned" data="{{ po.connected_port.pk }}">
<i class="glyphicon glyphicon-ban-circle" aria-hidden="true"></i>
</a>
{% else %}
<a href="#" class="btn btn-success btn-xs consoleport-toggle" data="{{ po.connected_port.pk }}">
<i class="fa fa-plug" aria-hidden="true" title="Mark connected"></i>
<a href="#" class="btn btn-success btn-xs consoleport-toggle" title="Mark installed" data="{{ po.connected_port.pk }}">
<i class="fa fa-plug" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:poweroutlet_disconnect' pk=po.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true" title="Delete connection"></i>
<a href="{% url 'dcim:poweroutlet_disconnect' pk=po.pk %}" title="Delete connection" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-resize-full" aria-hidden="true"></i>
</a>
{% else %}
<a href="{% url 'dcim:poweroutlet_connect' pk=po.pk %}" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true" title="Connect"></i>
<a href="{% url 'dcim:poweroutlet_connect' pk=po.pk %}" title="Connect" class="btn btn-success btn-xs">
<i class="glyphicon glyphicon-resize-small" aria-hidden="true"></i>
</a>
{% endif %}
<a href="{% url 'dcim:poweroutlet_edit' pk=po.pk %}" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true" title="Edit outlet"></i>
<a href="{% url 'dcim:poweroutlet_edit' pk=po.pk %}" title="Edit outlet" class="btn btn-info btn-xs">
<i class="glyphicon glyphicon-pencil" aria-hidden="true"></i>
</a>
{% endif %}
{% if perms.dcim.delete_poweroutlet %}
Expand All @@ -50,8 +50,8 @@
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</button>
{% else %}
<a href="{% url 'dcim:poweroutlet_delete' pk=po.pk %}" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true" title="Delete outlet"></i>
<a href="{% url 'dcim:poweroutlet_delete' pk=po.pk %}" title="Delete outlet" class="btn btn-danger btn-xs">
<i class="glyphicon glyphicon-trash" aria-hidden="true"></i>
</a>
{% endif %}
{% endif %}
Expand Down
Loading

0 comments on commit be89a78

Please sign in to comment.