mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-23 07:56:44 -06:00
Use existing disk field to store aggregate virtual disk size
This commit is contained in:
parent
f4aa2e9f62
commit
7eb6b2fc47
@ -145,12 +145,6 @@
|
|||||||
<td>
|
<td>
|
||||||
{% if object.disk %}
|
{% if object.disk %}
|
||||||
{{ object.disk }} {% trans "GB" context "Abbreviation for gigabyte" %}
|
{{ object.disk }} {% trans "GB" context "Abbreviation for gigabyte" %}
|
||||||
<span class="text-warning">
|
|
||||||
<i class="mdi mdi-alert" title="{% trans "This field has been deprecated and will be removed in a future release." %}"></i>
|
|
||||||
</span>
|
|
||||||
{% elif object.disk_size %}
|
|
||||||
{{ object.disk_size }} {% trans "GB" context "Abbreviation for gigabyte" %}
|
|
||||||
({{ object.virtualdisks.count }} {% trans "disks" %})
|
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ ''|placeholder }}
|
{{ ''|placeholder }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -5,7 +5,7 @@ class VirtualizationConfig(AppConfig):
|
|||||||
name = 'virtualization'
|
name = 'virtualization'
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
from . import search
|
from . import search, signals
|
||||||
from .models import VirtualMachine
|
from .models import VirtualMachine
|
||||||
from utilities.counters import connect_counters
|
from utilities.counters import connect_counters
|
||||||
|
|
||||||
|
@ -240,6 +240,11 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
|
|||||||
|
|
||||||
if self.instance.pk:
|
if self.instance.pk:
|
||||||
|
|
||||||
|
# Disable the disk field if one or more VirtualDisks have been created
|
||||||
|
if self.instance.virtualdisks.exists():
|
||||||
|
self.fields['disk'].widget.attrs['disabled'] = True
|
||||||
|
self.fields['disk'].help_text = _("Disk size is managed via the attachment of virtual disks.")
|
||||||
|
|
||||||
# Compile list of choices for primary IPv4 and IPv6 addresses
|
# Compile list of choices for primary IPv4 and IPv6 addresses
|
||||||
for family in [4, 6]:
|
for family in [4, 6]:
|
||||||
ip_choices = [(None, '---------')]
|
ip_choices = [(None, '---------')]
|
||||||
|
@ -2,7 +2,7 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Q
|
from django.db.models import Q, Sum
|
||||||
from django.db.models.functions import Lower
|
from django.db.models.functions import Lower
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@ -120,12 +120,10 @@ class VirtualMachine(ContactsMixin, RenderConfigMixin, ConfigContextModel, Prima
|
|||||||
null=True,
|
null=True,
|
||||||
verbose_name=_('memory (MB)')
|
verbose_name=_('memory (MB)')
|
||||||
)
|
)
|
||||||
# TODO: Remove in v4.0
|
|
||||||
disk = models.PositiveIntegerField(
|
disk = models.PositiveIntegerField(
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
verbose_name=_('disk (GB)'),
|
verbose_name=_('disk (GB)')
|
||||||
help_text=_('deprecated - use Virtual Disks')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Counter fields
|
# Counter fields
|
||||||
@ -199,6 +197,17 @@ class VirtualMachine(ContactsMixin, RenderConfigMixin, ConfigContextModel, Prima
|
|||||||
).format(device=self.device, cluster=self.cluster)
|
).format(device=self.device, cluster=self.cluster)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
# Validate aggregate disk size
|
||||||
|
if self.pk:
|
||||||
|
total_disk = self.virtualdisks.aggregate(Sum('size', default=0))['size__sum']
|
||||||
|
if total_disk and self.disk != total_disk:
|
||||||
|
raise ValidationError({
|
||||||
|
'disk': _(
|
||||||
|
"The specified disk size ({size}) must match the aggregate size of assigned virtual disks "
|
||||||
|
"({total_size})."
|
||||||
|
).format(size=self.disk, total_size=total_disk)
|
||||||
|
})
|
||||||
|
|
||||||
# Validate primary IP addresses
|
# Validate primary IP addresses
|
||||||
interfaces = self.interfaces.all() if self.pk else None
|
interfaces = self.interfaces.all() if self.pk else None
|
||||||
for family in (4, 6):
|
for family in (4, 6):
|
||||||
|
16
netbox/virtualization/signals.py
Normal file
16
netbox/virtualization/signals.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from django.db.models import Sum
|
||||||
|
from django.db.models.signals import post_delete, post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from .models import VirtualDisk, VirtualMachine
|
||||||
|
|
||||||
|
|
||||||
|
@receiver((post_delete, post_save), sender=VirtualDisk)
|
||||||
|
def update_circuit(instance, **kwargs):
|
||||||
|
"""
|
||||||
|
When a VirtualDisk has been modified, update the aggregate disk_size value of its VM.
|
||||||
|
"""
|
||||||
|
vm = instance.virtual_machine
|
||||||
|
VirtualMachine.objects.filter(pk=vm.pk).update(
|
||||||
|
disk=vm.virtualdisks.aggregate(Sum('size'))['size__sum']
|
||||||
|
)
|
@ -90,3 +90,28 @@ class VirtualMachineTestCase(TestCase):
|
|||||||
# Uniqueness validation for name should ignore case
|
# Uniqueness validation for name should ignore case
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
vm2.full_clean()
|
vm2.full_clean()
|
||||||
|
|
||||||
|
def test_disk_size(self):
|
||||||
|
vm = VirtualMachine(
|
||||||
|
cluster=Cluster.objects.first(),
|
||||||
|
name='Virtual Machine 1'
|
||||||
|
)
|
||||||
|
vm.save()
|
||||||
|
vm.refresh_from_db()
|
||||||
|
self.assertEqual(vm.disk, None)
|
||||||
|
|
||||||
|
# Create two VirtualDisks
|
||||||
|
VirtualDisk.objects.create(virtual_machine=vm, name='Virtual Disk 1', size=10)
|
||||||
|
VirtualDisk.objects.create(virtual_machine=vm, name='Virtual Disk 2', size=10)
|
||||||
|
vm.refresh_from_db()
|
||||||
|
self.assertEqual(vm.disk, 20)
|
||||||
|
|
||||||
|
# Delete one VirtualDisk
|
||||||
|
VirtualDisk.objects.first().delete()
|
||||||
|
vm.refresh_from_db()
|
||||||
|
self.assertEqual(vm.disk, 10)
|
||||||
|
|
||||||
|
# Attempt to manually overwrite the aggregate disk size
|
||||||
|
vm.disk = 30
|
||||||
|
with self.assertRaises(ValidationError):
|
||||||
|
vm.full_clean()
|
||||||
|
Loading…
Reference in New Issue
Block a user