17686 config option for disk divider (#18011)

This commit is contained in:
Mika Busch 2025-03-07 19:47:27 +01:00 committed by GitHub
parent 6d69c76b83
commit 29c25e39fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 59 additions and 16 deletions

View File

@ -233,3 +233,15 @@ This parameter controls how frequently a failed job is retried, up to the maximu
Default: `0` (retries disabled) Default: `0` (retries disabled)
The maximum number of times a background task will be retried before being marked as failed. The maximum number of times a background task will be retried before being marked as failed.
## DISK_BASE_UNIT
Default: `1000`
The base unit for disk sizes. Set this to `1024` to use binary prefixes (MiB, GiB, etc.) instead of decimal prefixes (MB, GB, etc.).
## RAM_BASE_UNIT
Default: `1000`
The base unit for RAM sizes. Set this to `1024` to use binary prefixes (MiB, GiB, etc.) instead of decimal prefixes (MB, GB, etc.).

View File

@ -221,6 +221,11 @@ SESSION_COOKIE_NAME = 'sessionid'
# database access.) Note that the user as which NetBox runs must have read and write permissions to this path. # database access.) Note that the user as which NetBox runs must have read and write permissions to this path.
SESSION_FILE_PATH = None SESSION_FILE_PATH = None
# By default the memory and disk sizes are displayed using base 10 (e.g. 1000 MB = 1 GB).
# If you would like to use base 2 (e.g. 1024 MB = 1 GB) set this to 1024.
# DISK_BASE_UNIT = 1024
# RAM_BASE_UNIT = 1024
# By default, uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the # By default, uploaded media is stored on the local filesystem. Using Django-storages is also supported. Provide the
# class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example: # class path of the storage driver in STORAGE_BACKEND and any configuration options in STORAGE_CONFIG. For example:
# STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage' # STORAGE_BACKEND = 'storages.backends.s3boto3.S3Boto3Storage'

View File

@ -176,6 +176,12 @@ STORAGE_BACKEND = getattr(configuration, 'STORAGE_BACKEND', None)
STORAGE_CONFIG = getattr(configuration, 'STORAGE_CONFIG', {}) STORAGE_CONFIG = getattr(configuration, 'STORAGE_CONFIG', {})
TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC') TIME_ZONE = getattr(configuration, 'TIME_ZONE', 'UTC')
TRANSLATION_ENABLED = getattr(configuration, 'TRANSLATION_ENABLED', True) TRANSLATION_ENABLED = getattr(configuration, 'TRANSLATION_ENABLED', True)
DISK_BASE_UNIT = getattr(configuration, 'DISK_BASE_UNIT', 1000)
if DISK_BASE_UNIT not in [1000, 1024]:
raise ImproperlyConfigured(f"DISK_BASE_UNIT must be 1000 or 1024 (found {DISK_BASE_UNIT})")
RAM_BASE_UNIT = getattr(configuration, 'RAM_BASE_UNIT', 1000)
if RAM_BASE_UNIT not in [1000, 1024]:
raise ImproperlyConfigured(f"RAM_BASE_UNIT must be 1000 or 1024 (found {RAM_BASE_UNIT})")
# Load any dynamic configuration parameters which have been hard-coded in the configuration file # Load any dynamic configuration parameters which have been hard-coded in the configuration file
for param in CONFIG_PARAMS: for param in CONFIG_PARAMS:

View File

@ -63,7 +63,7 @@
<th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th> <th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th>
<td> <td>
{% if memory_sum %} {% if memory_sum %}
<span title={{ memory_sum }}>{{ memory_sum|humanize_megabytes }}</span> <span title={{ memory_sum }}>{{ memory_sum|humanize_ram_megabytes }}</span>
{% else %} {% else %}
{{ ''|placeholder }} {{ ''|placeholder }}
{% endif %} {% endif %}
@ -73,7 +73,7 @@
<th scope="row"><i class="mdi mdi-harddisk"></i> {% trans "Disk Space" %}</th> <th scope="row"><i class="mdi mdi-harddisk"></i> {% trans "Disk Space" %}</th>
<td> <td>
{% if disk_sum %} {% if disk_sum %}
{{ disk_sum|humanize_megabytes }} {{ disk_sum|humanize_disk_megabytes }}
{% else %} {% else %}
{{ ''|placeholder }} {{ ''|placeholder }}
{% endif %} {% endif %}

View File

@ -29,7 +29,7 @@
<th scope="row"><i class="mdi mdi-harddisk"></i> {% trans "Size" %}</th> <th scope="row"><i class="mdi mdi-harddisk"></i> {% trans "Size" %}</th>
<td> <td>
{% if object.size %} {% if object.size %}
{{ object.size|humanize_megabytes }} {{ object.size|humanize_disk_megabytes }}
{% else %} {% else %}
{{ ''|placeholder }} {{ ''|placeholder }}
{% endif %} {% endif %}

View File

@ -129,7 +129,7 @@
<th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th> <th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th>
<td> <td>
{% if object.memory %} {% if object.memory %}
<span title={{ object.memory }}>{{ object.memory|humanize_megabytes }}</span> <span title={{ object.memory }}>{{ object.memory|humanize_ram_megabytes }}</span>
{% else %} {% else %}
{{ ''|placeholder }} {{ ''|placeholder }}
{% endif %} {% endif %}
@ -141,7 +141,7 @@
</th> </th>
<td> <td>
{% if object.disk %} {% if object.disk %}
{{ object.disk|humanize_megabytes }} {{ object.disk|humanize_disk_megabytes }}
{% else %} {% else %}
{{ ''|placeholder }} {{ ''|placeholder }}
{% endif %} {% endif %}

View File

@ -8,6 +8,7 @@ from django.urls import NoReverseMatch, reverse
from core.models import ObjectType from core.models import ObjectType
from utilities.forms import get_selected_values, TableConfigForm from utilities.forms import get_selected_values, TableConfigForm
from utilities.views import get_viewname from utilities.views import get_viewname
from netbox.settings import DISK_BASE_UNIT, RAM_BASE_UNIT
__all__ = ( __all__ = (
'applied_filters', 'applied_filters',
@ -15,7 +16,8 @@ __all__ = (
'divide', 'divide',
'get_item', 'get_item',
'get_key', 'get_key',
'humanize_megabytes', 'humanize_disk_megabytes',
'humanize_ram_megabytes',
'humanize_speed', 'humanize_speed',
'icon_from_status', 'icon_from_status',
'kg_to_pounds', 'kg_to_pounds',
@ -84,17 +86,16 @@ def humanize_speed(speed):
return '{} Kbps'.format(speed) return '{} Kbps'.format(speed)
@register.filter() def _humanize_megabytes(mb, divisor=1000):
def humanize_megabytes(mb):
""" """
Express a number of megabytes in the most suitable unit (e.g. gigabytes, terabytes, etc.). Express a number of megabytes in the most suitable unit (e.g. gigabytes, terabytes, etc.).
""" """
if not mb: if not mb:
return "" return ""
PB_SIZE = 1000000000 PB_SIZE = divisor**3
TB_SIZE = 1000000 TB_SIZE = divisor**2
GB_SIZE = 1000 GB_SIZE = divisor
if mb >= PB_SIZE: if mb >= PB_SIZE:
return f"{mb / PB_SIZE:.2f} PB" return f"{mb / PB_SIZE:.2f} PB"
@ -105,6 +106,24 @@ def humanize_megabytes(mb):
return f"{mb} MB" return f"{mb} MB"
@register.filter()
def humanize_disk_megabytes(mb):
"""
Express a number of megabytes in the most suitable unit (e.g. gigabytes, terabytes, etc.).
Use the DISK_BASE_UNIT setting to determine the divisor. Default is 1000.
"""
return _humanize_megabytes(mb, DISK_BASE_UNIT)
@register.filter()
def humanize_ram_megabytes(mb):
"""
Express a number of megabytes in the most suitable unit (e.g. gigabytes, terabytes, etc.).
Use the RAM_BASE_UNIT setting to determine the divisor. Default is 1000.
"""
return _humanize_megabytes(mb, RAM_BASE_UNIT)
@register.filter() @register.filter()
def divide(x, y): def divide(x, y):
""" """

View File

@ -1,13 +1,14 @@
from django.db import migrations from django.db import migrations
from django.db.models import F, Sum from django.db.models import F, Sum
from netbox.settings import DISK_BASE_UNIT
def convert_disk_size(apps, schema_editor): def convert_disk_size(apps, schema_editor):
VirtualMachine = apps.get_model('virtualization', 'VirtualMachine') VirtualMachine = apps.get_model('virtualization', 'VirtualMachine')
VirtualMachine.objects.filter(disk__isnull=False).update(disk=F('disk') * 1000) VirtualMachine.objects.filter(disk__isnull=False).update(disk=F('disk') * DISK_BASE_UNIT)
VirtualDisk = apps.get_model('virtualization', 'VirtualDisk') VirtualDisk = apps.get_model('virtualization', 'VirtualDisk')
VirtualDisk.objects.filter(size__isnull=False).update(size=F('size') * 1000) VirtualDisk.objects.filter(size__isnull=False).update(size=F('size') * DISK_BASE_UNIT)
# Recalculate disk size on all VMs with virtual disks # Recalculate disk size on all VMs with virtual disks
id_list = VirtualDisk.objects.values_list('virtual_machine_id').distinct() id_list = VirtualDisk.objects.values_list('virtual_machine_id').distinct()

View File

@ -4,7 +4,7 @@ from django.utils.translation import gettext_lazy as _
from dcim.tables.devices import BaseInterfaceTable from dcim.tables.devices import BaseInterfaceTable
from netbox.tables import NetBoxTable, columns from netbox.tables import NetBoxTable, columns
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
from utilities.templatetags.helpers import humanize_megabytes from utilities.templatetags.helpers import humanize_disk_megabytes
from virtualization.models import VirtualDisk, VirtualMachine, VMInterface from virtualization.models import VirtualDisk, VirtualMachine, VMInterface
from .template_code import * from .template_code import *
@ -93,7 +93,7 @@ class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable)
) )
def render_disk(self, value): def render_disk(self, value):
return humanize_megabytes(value) return humanize_disk_megabytes(value)
# #
@ -183,7 +183,7 @@ class VirtualDiskTable(NetBoxTable):
} }
def render_size(self, value): def render_size(self, value):
return humanize_megabytes(value) return humanize_disk_megabytes(value)
class VirtualMachineVirtualDiskTable(VirtualDiskTable): class VirtualMachineVirtualDiskTable(VirtualDiskTable):