1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Reorganize virtualization models

This commit is contained in:
jeremystretch
2022-11-04 13:49:31 -04:00
parent f68c7fb188
commit fe73e90b7b
3 changed files with 141 additions and 147 deletions

View File

@ -0,0 +1,2 @@
from .clusters import *
from .virtualmachines import *

View File

@ -0,0 +1,135 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
from dcim.models import Device
from netbox.models import OrganizationalModel, PrimaryModel
from virtualization.choices import *
__all__ = (
'Cluster',
'ClusterGroup',
'ClusterType',
)
class ClusterType(OrganizationalModel):
"""
A type of Cluster.
"""
def get_absolute_url(self):
return reverse('virtualization:clustertype', args=[self.pk])
class ClusterGroup(OrganizationalModel):
"""
An organizational group of Clusters.
"""
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='cluster_group'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
def get_absolute_url(self):
return reverse('virtualization:clustergroup', args=[self.pk])
class Cluster(PrimaryModel):
"""
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
"""
name = models.CharField(
max_length=100
)
type = models.ForeignKey(
to=ClusterType,
on_delete=models.PROTECT,
related_name='clusters'
)
group = models.ForeignKey(
to=ClusterGroup,
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
status = models.CharField(
max_length=50,
choices=ClusterStatusChoices,
default=ClusterStatusChoices.STATUS_ACTIVE
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
site = models.ForeignKey(
to='dcim.Site',
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='cluster'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'type', 'group', 'status', 'tenant', 'site',
)
class Meta:
ordering = ['name']
constraints = (
models.UniqueConstraint(
fields=('group', 'name'),
name='%(app_label)s_%(class)s_unique_group_name'
),
models.UniqueConstraint(
fields=('site', 'name'),
name='%(app_label)s_%(class)s_unique_site_name'
),
)
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [ClusterType, ]
def get_absolute_url(self):
return reverse('virtualization:cluster', args=[self.pk])
def get_status_color(self):
return ClusterStatusChoices.colors.get(self.status)
def clean(self):
super().clean()
# If the Cluster is assigned to a Site, verify that all host Devices belong to that Site.
if self.pk and self.site:
nonsite_devices = Device.objects.filter(cluster=self).exclude(site=self.site).count()
if nonsite_devices:
raise ValidationError({
'site': "{} devices are assigned as hosts for this cluster but are not in site {}".format(
nonsite_devices, self.site
)
})

View File

@ -6,162 +6,23 @@ from django.db.models import Q
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 dcim.models import BaseInterface, Device from dcim.models import BaseInterface
from extras.models import ConfigContextModel from extras.models import ConfigContextModel
from extras.querysets import ConfigContextModelQuerySet from extras.querysets import ConfigContextModelQuerySet
from netbox.config import get_config from netbox.config import get_config
from netbox.models import NetBoxModel, OrganizationalModel, PrimaryModel from netbox.models import NetBoxModel, PrimaryModel
from utilities.fields import NaturalOrderingField from utilities.fields import NaturalOrderingField
from utilities.ordering import naturalize_interface from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar from utilities.query_functions import CollateAsChar
from .choices import * from virtualization.choices import *
from .clusters import Cluster
__all__ = ( __all__ = (
'Cluster',
'ClusterGroup',
'ClusterType',
'VirtualMachine', 'VirtualMachine',
'VMInterface', 'VMInterface',
) )
#
# Cluster types
#
class ClusterType(OrganizationalModel):
"""
A type of Cluster.
"""
def get_absolute_url(self):
return reverse('virtualization:clustertype', args=[self.pk])
#
# Cluster groups
#
class ClusterGroup(OrganizationalModel):
"""
An organizational group of Clusters.
"""
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='cluster_group'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
def get_absolute_url(self):
return reverse('virtualization:clustergroup', args=[self.pk])
#
# Clusters
#
class Cluster(PrimaryModel):
"""
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
"""
name = models.CharField(
max_length=100
)
type = models.ForeignKey(
to=ClusterType,
on_delete=models.PROTECT,
related_name='clusters'
)
group = models.ForeignKey(
to=ClusterGroup,
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
status = models.CharField(
max_length=50,
choices=ClusterStatusChoices,
default=ClusterStatusChoices.STATUS_ACTIVE
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
site = models.ForeignKey(
to='dcim.Site',
on_delete=models.PROTECT,
related_name='clusters',
blank=True,
null=True
)
# Generic relations
vlan_groups = GenericRelation(
to='ipam.VLANGroup',
content_type_field='scope_type',
object_id_field='scope_id',
related_query_name='cluster'
)
contacts = GenericRelation(
to='tenancy.ContactAssignment'
)
clone_fields = (
'type', 'group', 'status', 'tenant', 'site',
)
class Meta:
ordering = ['name']
constraints = (
models.UniqueConstraint(
fields=('group', 'name'),
name='%(app_label)s_%(class)s_unique_group_name'
),
models.UniqueConstraint(
fields=('site', 'name'),
name='%(app_label)s_%(class)s_unique_site_name'
),
)
def __str__(self):
return self.name
@classmethod
def get_prerequisite_models(cls):
return [ClusterType, ]
def get_absolute_url(self):
return reverse('virtualization:cluster', args=[self.pk])
def get_status_color(self):
return ClusterStatusChoices.colors.get(self.status)
def clean(self):
super().clean()
# If the Cluster is assigned to a Site, verify that all host Devices belong to that Site.
if self.pk and self.site:
nonsite_devices = Device.objects.filter(cluster=self).exclude(site=self.site).count()
if nonsite_devices:
raise ValidationError({
'site': "{} devices are assigned as hosts for this cluster but are not in site {}".format(
nonsite_devices, self.site
)
})
#
# Virtual machines
#
class VirtualMachine(PrimaryModel, ConfigContextModel): class VirtualMachine(PrimaryModel, ConfigContextModel):
""" """
A virtual machine which runs inside a Cluster. A virtual machine which runs inside a Cluster.
@ -357,10 +218,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
return None return None
#
# Interfaces
#
class VMInterface(NetBoxModel, BaseInterface): class VMInterface(NetBoxModel, BaseInterface):
virtual_machine = models.ForeignKey( virtual_machine = models.ForeignKey(
to='virtualization.VirtualMachine', to='virtualization.VirtualMachine',