diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 3af825d30..21dc72545 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
- placeholder: v3.1.9
+ placeholder: v3.1.10
validations:
required: true
- type: dropdown
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml
index f5bf198b8..f64f5ccba 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yaml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yaml
@@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
- placeholder: v3.1.9
+ placeholder: v3.1.10
validations:
required: true
- type: dropdown
diff --git a/docs/release-notes/version-3.1.md b/docs/release-notes/version-3.1.md
index ea18a0834..df9c9c7bb 100644
--- a/docs/release-notes/version-3.1.md
+++ b/docs/release-notes/version-3.1.md
@@ -1,13 +1,19 @@
# NetBox v3.1
-## v3.1.10 (FUTURE)
+## v3.1.11 (FUTURE)
+
+---
+
+## v3.1.10 (2022-03-25)
### Enhancements
+* [#8232](https://github.com/netbox-community/netbox/issues/8232) - Use a different color for 100% utilization bars
* [#8457](https://github.com/netbox-community/netbox/issues/8457) - Enable adding non-racked devices from site & location views
* [#8553](https://github.com/netbox-community/netbox/issues/8553) - Add missing object types to global search form
* [#8575](https://github.com/netbox-community/netbox/issues/8575) - Add rack columns to cables list
* [#8645](https://github.com/netbox-community/netbox/issues/8645) - Enable filtering objects by assigned contacts & contact roles
+* [#8926](https://github.com/netbox-community/netbox/issues/8926) - Add device type, role columns to device bay table
### Bug Fixes
diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py
index 8f6bde3fb..81d699b11 100644
--- a/netbox/dcim/models/racks.py
+++ b/netbox/dcim/models/racks.py
@@ -409,7 +409,7 @@ class Rack(NetBoxModel):
available_units.remove(u)
occupied_unit_count = self.u_height - len(available_units)
- percentage = int(float(occupied_unit_count) / self.u_height * 100)
+ percentage = float(occupied_unit_count) / self.u_height * 100
return percentage
diff --git a/netbox/dcim/tables/devices.py b/netbox/dcim/tables/devices.py
index d12a8327f..ffa95c119 100644
--- a/netbox/dcim/tables/devices.py
+++ b/netbox/dcim/tables/devices.py
@@ -679,6 +679,15 @@ class DeviceBayTable(DeviceComponentTable):
'args': [Accessor('device_id')],
}
)
+ device_role = columns.ColoredLabelColumn(
+ accessor=Accessor('installed_device__device_role'),
+ verbose_name='Role'
+ )
+ device_type = tables.Column(
+ accessor=Accessor('installed_device__device_type'),
+ linkify=True,
+ verbose_name='Type'
+ )
status = tables.TemplateColumn(
template_code=DEVICEBAY_STATUS,
order_by=Accessor('installed_device__status')
@@ -693,7 +702,7 @@ class DeviceBayTable(DeviceComponentTable):
class Meta(DeviceComponentTable.Meta):
model = DeviceBay
fields = (
- 'pk', 'id', 'name', 'device', 'label', 'status', 'installed_device', 'description', 'tags',
+ 'pk', 'id', 'name', 'device', 'label', 'status', 'device_role', 'device_type', 'installed_device', 'description', 'tags',
'created', 'last_updated',
)
diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py
index 6c9784cde..9aec0cff8 100644
--- a/netbox/ipam/models/ip.py
+++ b/netbox/ipam/models/ip.py
@@ -244,7 +244,7 @@ class Aggregate(GetAvailablePrefixesMixin, NetBoxModel):
"""
queryset = Prefix.objects.filter(prefix__net_contained_or_equal=str(self.prefix))
child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
- utilization = int(float(child_prefixes.size) / self.prefix.size * 100)
+ utilization = float(child_prefixes.size) / self.prefix.size * 100
return min(utilization, 100)
@@ -542,7 +542,7 @@ class Prefix(GetAvailablePrefixesMixin, NetBoxModel):
vrf=self.vrf
)
child_prefixes = netaddr.IPSet([p.prefix for p in queryset])
- utilization = int(float(child_prefixes.size) / self.prefix.size * 100)
+ utilization = float(child_prefixes.size) / self.prefix.size * 100
else:
# Compile an IPSet to avoid counting duplicate IPs
child_ips = netaddr.IPSet(
@@ -552,7 +552,7 @@ class Prefix(GetAvailablePrefixesMixin, NetBoxModel):
prefix_size = self.prefix.size
if self.prefix.version == 4 and self.prefix.prefixlen < 31 and not self.is_pool:
prefix_size -= 2
- utilization = int(float(child_ips.size) / prefix_size * 100)
+ utilization = float(child_ips.size) / prefix_size * 100
return min(utilization, 100)
diff --git a/netbox/ipam/tests/test_models.py b/netbox/ipam/tests/test_models.py
index 06ac9b843..a664b34f4 100644
--- a/netbox/ipam/tests/test_models.py
+++ b/netbox/ipam/tests/test_models.py
@@ -204,11 +204,11 @@ class TestPrefix(TestCase):
IPAddress.objects.bulk_create([
IPAddress(address=IPNetwork(f'10.0.0.{i}/24')) for i in range(1, 33)
])
- self.assertEqual(prefix.get_utilization(), 12) # 12.5% utilization
+ self.assertEqual(prefix.get_utilization(), 32 / 254 * 100) # ~12.5% utilization
# Create a child range with 32 additional IPs
IPRange.objects.create(start_address=IPNetwork('10.0.0.33/24'), end_address=IPNetwork('10.0.0.64/24'))
- self.assertEqual(prefix.get_utilization(), 25) # 25% utilization
+ self.assertEqual(prefix.get_utilization(), 64 / 254 * 100) # ~25% utilization
#
# Uniqueness enforcement tests
diff --git a/netbox/utilities/templates/helpers/utilization_graph.html b/netbox/utilities/templates/helpers/utilization_graph.html
index fe1c0fc9a..e6829befc 100644
--- a/netbox/utilities/templates/helpers/utilization_graph.html
+++ b/netbox/utilities/templates/helpers/utilization_graph.html
@@ -12,10 +12,10 @@
class="progress-bar {{ bar_class }}"
style="width: {{ utilization }}%;"
>
- {% if utilization >= 25 %}{{ utilization }}%{% endif %}
+ {% if utilization >= 25 %}{{ utilization|floatformat:0 }}%{% endif %}
{% if utilization < 25 %}
- {{ utilization }}%
+ {{ utilization|floatformat:0 }}%
{% endif %}
{% endif %}
diff --git a/netbox/utilities/templatetags/helpers.py b/netbox/utilities/templatetags/helpers.py
index 47808630b..db4d14c24 100644
--- a/netbox/utilities/templatetags/helpers.py
+++ b/netbox/utilities/templatetags/helpers.py
@@ -264,7 +264,9 @@ def utilization_graph(utilization, warning_threshold=75, danger_threshold=90):
"""
Display a horizontal bar graph indicating a percentage of utilization.
"""
- if danger_threshold and utilization >= danger_threshold:
+ if utilization == 100:
+ bar_class = 'bg-secondary'
+ elif danger_threshold and utilization >= danger_threshold:
bar_class = 'bg-danger'
elif warning_threshold and utilization >= warning_threshold:
bar_class = 'bg-warning'
diff --git a/requirements.txt b/requirements.txt
index ca7cb41be..ee24e0a6c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -19,7 +19,7 @@ gunicorn==20.1.0
Jinja2==3.0.3
Markdown==3.3.6
markdown-include==0.6.0
-mkdocs-material==8.2.5
+mkdocs-material==8.2.7
mkdocstrings==0.17.0
netaddr==0.8.0
Pillow==9.0.1
@@ -27,7 +27,7 @@ psycopg2-binary==2.9.3
PyYAML==6.0
social-auth-app-django==5.0.0
social-auth-core==4.2.0
-svgwrite==1.4.1
+svgwrite==1.4.2
tablib==3.2.0
tzdata==2021.5