mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-20 04:12:25 -06:00
6347 Cache the number of each component type assigned to devices/VMs (#12632)
--------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
@@ -80,12 +80,15 @@ class VirtualMachineSerializer(NetBoxModelSerializer):
|
||||
primary_ip4 = NestedIPAddressSerializer(required=False, allow_null=True)
|
||||
primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
|
||||
|
||||
# Counter fields
|
||||
interface_count = serializers.IntegerField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = VirtualMachine
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant', 'platform',
|
||||
'primary_ip', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'description', 'comments',
|
||||
'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated', 'interface_count',
|
||||
]
|
||||
validators = []
|
||||
|
||||
@@ -98,6 +101,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
|
||||
'id', 'url', 'display', 'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant', 'platform',
|
||||
'primary_ip', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'description', 'comments',
|
||||
'local_context_data', 'tags', 'custom_fields', 'config_context', 'created', 'last_updated',
|
||||
'interface_count',
|
||||
]
|
||||
|
||||
@extend_schema_field(serializers.JSONField(allow_null=True))
|
||||
|
||||
@@ -6,3 +6,8 @@ class VirtualizationConfig(AppConfig):
|
||||
|
||||
def ready(self):
|
||||
from . import search
|
||||
from .models import VirtualMachine
|
||||
from utilities.counters import connect_counters
|
||||
|
||||
# Register counters
|
||||
connect_counters(VirtualMachine)
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
from django.db import migrations
|
||||
from django.db.models import Count
|
||||
|
||||
import utilities.fields
|
||||
|
||||
|
||||
def populate_virtualmachine_counts(apps, schema_editor):
|
||||
VirtualMachine = apps.get_model('virtualization', 'VirtualMachine')
|
||||
|
||||
vms = list(VirtualMachine.objects.annotate(_interface_count=Count('interfaces', distinct=True)))
|
||||
|
||||
for vm in vms:
|
||||
vm.interface_count = vm._interface_count
|
||||
|
||||
VirtualMachine.objects.bulk_update(vms, ['interface_count'])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('virtualization', '0034_standardize_description_comments'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='virtualmachine',
|
||||
name='interface_count',
|
||||
field=utilities.fields.CounterCacheField(
|
||||
default=0, to_field='virtual_machine', to_model='virtualization.VMInterface'
|
||||
),
|
||||
),
|
||||
migrations.RunPython(
|
||||
code=populate_virtualmachine_counts,
|
||||
reverse_code=migrations.RunPython.noop
|
||||
),
|
||||
]
|
||||
@@ -11,9 +11,10 @@ from extras.models import ConfigContextModel
|
||||
from extras.querysets import ConfigContextModelQuerySet
|
||||
from netbox.config import get_config
|
||||
from netbox.models import NetBoxModel, PrimaryModel
|
||||
from utilities.fields import NaturalOrderingField
|
||||
from utilities.fields import CounterCacheField, NaturalOrderingField
|
||||
from utilities.ordering import naturalize_interface
|
||||
from utilities.query_functions import CollateAsChar
|
||||
from utilities.tracking import TrackingModelMixin
|
||||
from virtualization.choices import *
|
||||
|
||||
__all__ = (
|
||||
@@ -120,6 +121,12 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
||||
verbose_name='Disk (GB)'
|
||||
)
|
||||
|
||||
# Counter fields
|
||||
interface_count = CounterCacheField(
|
||||
to_model='virtualization.VMInterface',
|
||||
to_field='virtual_machine'
|
||||
)
|
||||
|
||||
# Generic relation
|
||||
contacts = GenericRelation(
|
||||
to='tenancy.ContactAssignment'
|
||||
@@ -222,7 +229,7 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
||||
return None
|
||||
|
||||
|
||||
class VMInterface(NetBoxModel, BaseInterface):
|
||||
class VMInterface(NetBoxModel, BaseInterface, TrackingModelMixin):
|
||||
virtual_machine = models.ForeignKey(
|
||||
to='virtualization.VirtualMachine',
|
||||
on_delete=models.CASCADE,
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import django_tables2 as tables
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.tables.devices import BaseInterfaceTable
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
|
||||
__all__ = (
|
||||
'VirtualMachineTable',
|
||||
'VirtualMachineVMInterfaceTable',
|
||||
@@ -70,6 +71,9 @@ class VirtualMachineTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable)
|
||||
tags = columns.TagColumn(
|
||||
url_name='virtualization:virtualmachine_list'
|
||||
)
|
||||
interface_count = tables.Column(
|
||||
verbose_name=_('Interfaces')
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = VirtualMachine
|
||||
|
||||
@@ -349,7 +349,7 @@ class VirtualMachineInterfacesView(generic.ObjectChildrenView):
|
||||
template_name = 'virtualization/virtualmachine/interfaces.html'
|
||||
tab = ViewTab(
|
||||
label=_('Interfaces'),
|
||||
badge=lambda obj: obj.interfaces.count(),
|
||||
badge=lambda obj: obj.interface_count,
|
||||
permission='virtualization.view_vminterface',
|
||||
weight=500
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user