mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 09:28:38 -06:00
Merge branch 'feature' into 5284-vlangroup-scope
This commit is contained in:
commit
f4e49495e2
@ -1,12 +1,11 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.fields import ASNField
|
from dcim.fields import ASNField
|
||||||
from dcim.models import CableTermination, PathEndpoint
|
from dcim.models import CableTermination, PathEndpoint
|
||||||
from extras.models import ObjectChange, TaggedItem
|
from extras.models import ObjectChange
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import BigIDModel, ChangeLoggingMixin, OrganizationalModel, PrimaryModel
|
from netbox.models import BigIDModel, ChangeLoggedModel, OrganizationalModel, PrimaryModel
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from .choices import *
|
from .choices import *
|
||||||
from .querysets import CircuitQuerySet
|
from .querysets import CircuitQuerySet
|
||||||
@ -60,7 +59,6 @@ class Provider(PrimaryModel):
|
|||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -184,7 +182,6 @@ class Circuit(PrimaryModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
objects = CircuitQuerySet.as_manager()
|
objects = CircuitQuerySet.as_manager()
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
|
'cid', 'provider', 'type', 'status', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
|
||||||
@ -234,7 +231,8 @@ class Circuit(PrimaryModel):
|
|||||||
return self._get_termination('Z')
|
return self._get_termination('Z')
|
||||||
|
|
||||||
|
|
||||||
class CircuitTermination(ChangeLoggingMixin, BigIDModel, PathEndpoint, CableTermination):
|
@extras_features('webhooks')
|
||||||
|
class CircuitTermination(ChangeLoggedModel, PathEndpoint, CableTermination):
|
||||||
circuit = models.ForeignKey(
|
circuit = models.ForeignKey(
|
||||||
to='circuits.Circuit',
|
to='circuits.Circuit',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
|
@ -6,13 +6,11 @@ from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from dcim.fields import PathField
|
from dcim.fields import PathField
|
||||||
from dcim.utils import decompile_path_node, object_to_path_node, path_node_to_object
|
from dcim.utils import decompile_path_node, object_to_path_node, path_node_to_object
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import BigIDModel, PrimaryModel
|
from netbox.models import BigIDModel, PrimaryModel
|
||||||
from utilities.fields import ColorField
|
from utilities.fields import ColorField
|
||||||
@ -108,7 +106,6 @@ class Cable(PrimaryModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from django.db import models
|
|||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import BigIDModel, ChangeLoggingMixin
|
from netbox.models import ChangeLoggedModel
|
||||||
from utilities.fields import NaturalOrderingField
|
from utilities.fields import NaturalOrderingField
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from utilities.ordering import naturalize_interface
|
from utilities.ordering import naturalize_interface
|
||||||
@ -26,7 +26,7 @@ __all__ = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ComponentTemplateModel(ChangeLoggingMixin, BigIDModel):
|
class ComponentTemplateModel(ChangeLoggedModel):
|
||||||
device_type = models.ForeignKey(
|
device_type = models.ForeignKey(
|
||||||
to='dcim.DeviceType',
|
to='dcim.DeviceType',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@ -76,7 +76,7 @@ class ComponentTemplateModel(ChangeLoggingMixin, BigIDModel):
|
|||||||
return super().to_objectchange(action, related_object=device_type)
|
return super().to_objectchange(action, related_object=device_type)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class ConsolePortTemplate(ComponentTemplateModel):
|
class ConsolePortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a ConsolePort to be created for a new Device.
|
A template for a ConsolePort to be created for a new Device.
|
||||||
@ -100,7 +100,7 @@ class ConsolePortTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class ConsoleServerPortTemplate(ComponentTemplateModel):
|
class ConsoleServerPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a ConsoleServerPort to be created for a new Device.
|
A template for a ConsoleServerPort to be created for a new Device.
|
||||||
@ -124,7 +124,7 @@ class ConsoleServerPortTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class PowerPortTemplate(ComponentTemplateModel):
|
class PowerPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a PowerPort to be created for a new Device.
|
A template for a PowerPort to be created for a new Device.
|
||||||
@ -171,7 +171,7 @@ class PowerPortTemplate(ComponentTemplateModel):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class PowerOutletTemplate(ComponentTemplateModel):
|
class PowerOutletTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a PowerOutlet to be created for a new Device.
|
A template for a PowerOutlet to be created for a new Device.
|
||||||
@ -223,7 +223,7 @@ class PowerOutletTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class InterfaceTemplate(ComponentTemplateModel):
|
class InterfaceTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a physical data interface on a new Device.
|
A template for a physical data interface on a new Device.
|
||||||
@ -258,7 +258,7 @@ class InterfaceTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class FrontPortTemplate(ComponentTemplateModel):
|
class FrontPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
Template for a pass-through port on the front of a new Device.
|
Template for a pass-through port on the front of a new Device.
|
||||||
@ -319,7 +319,7 @@ class FrontPortTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class RearPortTemplate(ComponentTemplateModel):
|
class RearPortTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
Template for a pass-through port on the rear of a new Device.
|
Template for a pass-through port on the rear of a new Device.
|
||||||
@ -350,7 +350,7 @@ class RearPortTemplate(ComponentTemplateModel):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@extras_features('custom_fields', 'export_templates', 'webhooks')
|
@extras_features('webhooks')
|
||||||
class DeviceBayTemplate(ComponentTemplateModel):
|
class DeviceBayTemplate(ComponentTemplateModel):
|
||||||
"""
|
"""
|
||||||
A template for a DeviceBay to be created for a new parent Device.
|
A template for a DeviceBay to be created for a new parent Device.
|
||||||
|
@ -6,12 +6,10 @@ from django.db import models
|
|||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from mptt.models import MPTTModel, TreeForeignKey
|
from mptt.models import MPTTModel, TreeForeignKey
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from dcim.fields import MACAddressField
|
from dcim.fields import MACAddressField
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import PrimaryModel
|
from netbox.models import PrimaryModel
|
||||||
from utilities.fields import NaturalOrderingField
|
from utilities.fields import NaturalOrderingField
|
||||||
@ -227,7 +225,6 @@ class ConsolePort(ComponentModel, CableTermination, PathEndpoint):
|
|||||||
null=True,
|
null=True,
|
||||||
help_text='Port speed in bits per second'
|
help_text='Port speed in bits per second'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = ['device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description']
|
csv_headers = ['device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description']
|
||||||
|
|
||||||
@ -271,7 +268,6 @@ class ConsoleServerPort(ComponentModel, CableTermination, PathEndpoint):
|
|||||||
null=True,
|
null=True,
|
||||||
help_text='Port speed in bits per second'
|
help_text='Port speed in bits per second'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = ['device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description']
|
csv_headers = ['device', 'name', 'label', 'type', 'speed', 'mark_connected', 'description']
|
||||||
|
|
||||||
@ -321,7 +317,6 @@ class PowerPort(ComponentModel, CableTermination, PathEndpoint):
|
|||||||
validators=[MinValueValidator(1)],
|
validators=[MinValueValidator(1)],
|
||||||
help_text="Allocated power draw (watts)"
|
help_text="Allocated power draw (watts)"
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description',
|
'device', 'name', 'label', 'type', 'mark_connected', 'maximum_draw', 'allocated_draw', 'description',
|
||||||
@ -434,7 +429,6 @@ class PowerOutlet(ComponentModel, CableTermination, PathEndpoint):
|
|||||||
blank=True,
|
blank=True,
|
||||||
help_text="Phase (for three-phase feeds)"
|
help_text="Phase (for three-phase feeds)"
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = ['device', 'name', 'label', 'type', 'mark_connected', 'power_port', 'feed_leg', 'description']
|
csv_headers = ['device', 'name', 'label', 'type', 'mark_connected', 'power_port', 'feed_leg', 'description']
|
||||||
|
|
||||||
@ -568,7 +562,6 @@ class Interface(ComponentModel, BaseInterface, CableTermination, PathEndpoint):
|
|||||||
object_id_field='assigned_object_id',
|
object_id_field='assigned_object_id',
|
||||||
related_query_name='interface'
|
related_query_name='interface'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
'device', 'name', 'label', 'parent', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address', 'mtu',
|
'device', 'name', 'label', 'parent', 'lag', 'type', 'enabled', 'mark_connected', 'mac_address', 'mtu',
|
||||||
@ -705,7 +698,6 @@ class FrontPort(ComponentModel, CableTermination):
|
|||||||
MaxValueValidator(REARPORT_POSITIONS_MAX)
|
MaxValueValidator(REARPORT_POSITIONS_MAX)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
'device', 'name', 'label', 'type', 'mark_connected', 'rear_port', 'rear_port_position', 'description',
|
'device', 'name', 'label', 'type', 'mark_connected', 'rear_port', 'rear_port_position', 'description',
|
||||||
@ -766,7 +758,6 @@ class RearPort(ComponentModel, CableTermination):
|
|||||||
MaxValueValidator(REARPORT_POSITIONS_MAX)
|
MaxValueValidator(REARPORT_POSITIONS_MAX)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = ['device', 'name', 'label', 'type', 'mark_connected', 'positions', 'description']
|
csv_headers = ['device', 'name', 'label', 'type', 'mark_connected', 'positions', 'description']
|
||||||
|
|
||||||
@ -816,7 +807,6 @@ class DeviceBay(ComponentModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
csv_headers = ['device', 'name', 'label', 'installed_device', 'description']
|
csv_headers = ['device', 'name', 'label', 'installed_device', 'description']
|
||||||
|
|
||||||
@ -909,8 +899,6 @@ class InventoryItem(MPTTModel, ComponentModel):
|
|||||||
help_text='This item was automatically discovered'
|
help_text='This item was automatically discovered'
|
||||||
)
|
)
|
||||||
|
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = TreeManager()
|
objects = TreeManager()
|
||||||
|
|
||||||
csv_headers = [
|
csv_headers = [
|
||||||
|
@ -9,11 +9,10 @@ from django.db import models
|
|||||||
from django.db.models import F, ProtectedError
|
from django.db.models import F, ProtectedError
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from extras.models import ConfigContextModel, TaggedItem
|
from extras.models import ConfigContextModel
|
||||||
from extras.querysets import ConfigContextModelQuerySet
|
from extras.querysets import ConfigContextModelQuerySet
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, PrimaryModel
|
||||||
@ -136,7 +135,6 @@ class DeviceType(PrimaryModel):
|
|||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -601,7 +599,6 @@ class Device(PrimaryModel, ConfigContextModel):
|
|||||||
object_id_field='assigned_object_id',
|
object_id_field='assigned_object_id',
|
||||||
related_query_name='device'
|
related_query_name='device'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = ConfigContextModelQuerySet.as_manager()
|
objects = ConfigContextModelQuerySet.as_manager()
|
||||||
|
|
||||||
@ -916,7 +913,6 @@ class VirtualChassis(PrimaryModel):
|
|||||||
max_length=30,
|
max_length=30,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import PrimaryModel
|
from netbox.models import PrimaryModel
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
@ -41,7 +39,6 @@ class PowerPanel(PrimaryModel):
|
|||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=100
|
max_length=100
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -133,7 +130,6 @@ class PowerFeed(PrimaryModel, PathEndpoint, CableTermination):
|
|||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -11,12 +11,10 @@ from django.db import models
|
|||||||
from django.db.models import Count, Sum
|
from django.db.models import Count, Sum
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from mptt.models import TreeForeignKey
|
from mptt.models import TreeForeignKey
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from dcim.elevations import RackElevationSVG
|
from dcim.elevations import RackElevationSVG
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import NestedGroupModel, OrganizationalModel, PrimaryModel
|
from netbox.models import NestedGroupModel, OrganizationalModel, PrimaryModel
|
||||||
from utilities.choices import ColorChoices
|
from utilities.choices import ColorChoices
|
||||||
@ -251,7 +249,6 @@ class Rack(PrimaryModel):
|
|||||||
images = GenericRelation(
|
images = GenericRelation(
|
||||||
to='extras.ImageAttachment'
|
to='extras.ImageAttachment'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -558,7 +555,6 @@ class RackReservation(PrimaryModel):
|
|||||||
description = models.CharField(
|
description = models.CharField(
|
||||||
max_length=200
|
max_length=200
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -2,13 +2,11 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from mptt.models import TreeForeignKey
|
from mptt.models import TreeForeignKey
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
from timezone_field import TimeZoneField
|
from timezone_field import TimeZoneField
|
||||||
|
|
||||||
from dcim.choices import *
|
from dcim.choices import *
|
||||||
from dcim.constants import *
|
from dcim.constants import *
|
||||||
from dcim.fields import ASNField
|
from dcim.fields import ASNField
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import NestedGroupModel, PrimaryModel
|
from netbox.models import NestedGroupModel, PrimaryModel
|
||||||
from utilities.fields import NaturalOrderingField
|
from utilities.fields import NaturalOrderingField
|
||||||
@ -232,7 +230,6 @@ class Site(PrimaryModel):
|
|||||||
images = GenericRelation(
|
images = GenericRelation(
|
||||||
to='extras.ImageAttachment'
|
to='extras.ImageAttachment'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ from extras.choices import *
|
|||||||
from extras.constants import *
|
from extras.constants import *
|
||||||
from extras.querysets import ConfigContextQuerySet
|
from extras.querysets import ConfigContextQuerySet
|
||||||
from extras.utils import extras_features, FeatureQuery, image_upload
|
from extras.utils import extras_features, FeatureQuery, image_upload
|
||||||
from netbox.models import BigIDModel, ChangeLoggingMixin
|
from netbox.models import BigIDModel, ChangeLoggedModel
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
from utilities.utils import deepmerge, render_jinja2
|
from utilities.utils import deepmerge, render_jinja2
|
||||||
|
|
||||||
@ -379,7 +379,8 @@ class ImageAttachment(BigIDModel):
|
|||||||
# Config contexts
|
# Config contexts
|
||||||
#
|
#
|
||||||
|
|
||||||
class ConfigContext(ChangeLoggingMixin, BigIDModel):
|
@extras_features('webhooks')
|
||||||
|
class ConfigContext(ChangeLoggedModel):
|
||||||
"""
|
"""
|
||||||
A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned
|
A ConfigContext represents a set of arbitrary data available to any Device or VirtualMachine matching its assigned
|
||||||
qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B
|
qualifiers (region, site, etc.). For example, the data stored in a ConfigContext assigned to site A and tenant B
|
||||||
|
@ -2,7 +2,8 @@ from django.db import models
|
|||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
from taggit.models import TagBase, GenericTaggedItemBase
|
from taggit.models import TagBase, GenericTaggedItemBase
|
||||||
|
|
||||||
from netbox.models import BigIDModel, ChangeLoggingMixin
|
from extras.utils import extras_features
|
||||||
|
from netbox.models import BigIDModel, ChangeLoggedModel
|
||||||
from utilities.choices import ColorChoices
|
from utilities.choices import ColorChoices
|
||||||
from utilities.fields import ColorField
|
from utilities.fields import ColorField
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
@ -12,7 +13,8 @@ from utilities.querysets import RestrictedQuerySet
|
|||||||
# Tags
|
# Tags
|
||||||
#
|
#
|
||||||
|
|
||||||
class Tag(ChangeLoggingMixin, BigIDModel, TagBase):
|
@extras_features('webhooks')
|
||||||
|
class Tag(ChangeLoggedModel, TagBase):
|
||||||
color = ColorField(
|
color = ColorField(
|
||||||
default=ColorChoices.COLOR_GREY
|
default=ColorChoices.COLOR_GREY
|
||||||
)
|
)
|
||||||
|
@ -6,10 +6,8 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.models import Device
|
from dcim.models import Device
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, PrimaryModel
|
||||||
from ipam.choices import *
|
from ipam.choices import *
|
||||||
@ -107,7 +105,6 @@ class Aggregate(PrimaryModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -292,7 +289,6 @@ class Prefix(PrimaryModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = PrefixQuerySet.as_manager()
|
objects = PrefixQuerySet.as_manager()
|
||||||
|
|
||||||
@ -564,7 +560,6 @@ class IPAddress(PrimaryModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = IPAddressManager()
|
objects = IPAddressManager()
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from ipam.choices import *
|
from ipam.choices import *
|
||||||
from ipam.constants import *
|
from ipam.constants import *
|
||||||
@ -66,7 +64,6 @@ class Service(PrimaryModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -4,10 +4,8 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from ipam.choices import *
|
from ipam.choices import *
|
||||||
from ipam.constants import *
|
from ipam.constants import *
|
||||||
@ -149,7 +147,6 @@ class VLAN(PrimaryModel):
|
|||||||
max_length=200,
|
max_length=200,
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from ipam.constants import *
|
from ipam.constants import *
|
||||||
from netbox.models import PrimaryModel
|
from netbox.models import PrimaryModel
|
||||||
@ -59,7 +57,6 @@ class VRF(PrimaryModel):
|
|||||||
related_name='exporting_vrfs',
|
related_name='exporting_vrfs',
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -116,7 +113,6 @@ class RouteTarget(PrimaryModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True
|
null=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from django.core.serializers.json import DjangoJSONEncoder
|
|||||||
from django.core.validators import ValidationError
|
from django.core.validators import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from mptt.models import MPTTModel, TreeForeignKey
|
from mptt.models import MPTTModel, TreeForeignKey
|
||||||
|
from taggit.managers import TaggableManager
|
||||||
|
|
||||||
from extras.choices import ObjectChangeActionChoices
|
from extras.choices import ObjectChangeActionChoices
|
||||||
from utilities.mptt import TreeManager
|
from utilities.mptt import TreeManager
|
||||||
@ -12,8 +13,7 @@ from utilities.utils import serialize_object
|
|||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'BigIDModel',
|
'BigIDModel',
|
||||||
'ChangeLoggingMixin',
|
'ChangeLoggedModel',
|
||||||
'CustomFieldsMixin',
|
|
||||||
'NestedGroupModel',
|
'NestedGroupModel',
|
||||||
'OrganizationalModel',
|
'OrganizationalModel',
|
||||||
'PrimaryModel',
|
'PrimaryModel',
|
||||||
@ -137,12 +137,19 @@ class BigIDModel(models.Model):
|
|||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class ChangeLoggedModel(ChangeLoggingMixin, BigIDModel):
|
||||||
|
"""
|
||||||
|
Base model for all objects which support change logging.
|
||||||
|
"""
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
class PrimaryModel(ChangeLoggingMixin, CustomFieldsMixin, BigIDModel):
|
class PrimaryModel(ChangeLoggingMixin, CustomFieldsMixin, BigIDModel):
|
||||||
"""
|
"""
|
||||||
Primary models represent real objects within the infrastructure being modeled.
|
Primary models represent real objects within the infrastructure being modeled.
|
||||||
"""
|
"""
|
||||||
# TODO
|
tags = TaggableManager(through='extras.TaggedItem')
|
||||||
# tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
@ -12,9 +12,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.encoding import force_bytes
|
from django.utils.encoding import force_bytes
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import BigIDModel, OrganizationalModel, PrimaryModel
|
from netbox.models import BigIDModel, OrganizationalModel, PrimaryModel
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
@ -312,7 +310,6 @@ class Secret(PrimaryModel):
|
|||||||
max_length=128,
|
max_length=128,
|
||||||
editable=False
|
editable=False
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -57,9 +57,10 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{% plugin_left_page object %}
|
{% plugin_left_page object %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
{% include 'inc/custom_fields_panel.html' %}
|
||||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all %}
|
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all %}
|
||||||
{% plugin_right_page object %}
|
{% plugin_right_page object %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,14 @@
|
|||||||
{% render_field form.tagged_vlans %}
|
{% render_field form.tagged_vlans %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% if form.custom_fields %}
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading"><strong>Custom Fields</strong></div>
|
||||||
|
<div class="panel-body">
|
||||||
|
{% render_custom_fields form %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block buttons %}
|
{% block buttons %}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from mptt.models import MPTTModel, TreeForeignKey
|
from mptt.models import MPTTModel, TreeForeignKey
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from extras.models import TaggedItem
|
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import NestedGroupModel, PrimaryModel
|
from netbox.models import NestedGroupModel, PrimaryModel
|
||||||
from utilities.mptt import TreeManager
|
|
||||||
from utilities.querysets import RestrictedQuerySet
|
from utilities.querysets import RestrictedQuerySet
|
||||||
|
|
||||||
|
|
||||||
@ -42,8 +39,6 @@ class TenantGroup(NestedGroupModel):
|
|||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
|
|
||||||
objects = TreeManager()
|
|
||||||
|
|
||||||
csv_headers = ['name', 'slug', 'parent', 'description']
|
csv_headers = ['name', 'slug', 'parent', 'description']
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@ -89,7 +84,6 @@ class Tenant(PrimaryModel):
|
|||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ class VirtualMachineWithConfigContextSerializer(VirtualMachineSerializer):
|
|||||||
# VM interfaces
|
# VM interfaces
|
||||||
#
|
#
|
||||||
|
|
||||||
class VMInterfaceSerializer(TaggedObjectSerializer, ValidatedModelSerializer):
|
class VMInterfaceSerializer(TaggedObjectSerializer, CustomFieldModelSerializer):
|
||||||
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:vminterface-detail')
|
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:vminterface-detail')
|
||||||
virtual_machine = NestedVirtualMachineSerializer()
|
virtual_machine = NestedVirtualMachineSerializer()
|
||||||
mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False)
|
mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False)
|
||||||
@ -119,7 +119,7 @@ class VMInterfaceSerializer(TaggedObjectSerializer, ValidatedModelSerializer):
|
|||||||
model = VMInterface
|
model = VMInterface
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'url', 'virtual_machine', 'name', 'enabled', 'mtu', 'mac_address', 'description', 'mode',
|
'id', 'url', 'virtual_machine', 'name', 'enabled', 'mtu', 'mac_address', 'description', 'mode',
|
||||||
'untagged_vlan', 'tagged_vlans', 'tags',
|
'untagged_vlan', 'tagged_vlans', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate(self, data):
|
def validate(self, data):
|
||||||
|
@ -237,7 +237,7 @@ class VirtualMachineFilterSet(
|
|||||||
return queryset.exclude(params)
|
return queryset.exclude(params)
|
||||||
|
|
||||||
|
|
||||||
class VMInterfaceFilterSet(BaseFilterSet):
|
class VMInterfaceFilterSet(BaseFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet):
|
||||||
q = django_filters.CharFilter(
|
q = django_filters.CharFilter(
|
||||||
method='search',
|
method='search',
|
||||||
label='Search',
|
label='Search',
|
||||||
|
@ -576,7 +576,7 @@ class VirtualMachineFilterForm(BootstrapMixin, TenancyFilterForm, CustomFieldFil
|
|||||||
# VM interfaces
|
# VM interfaces
|
||||||
#
|
#
|
||||||
|
|
||||||
class VMInterfaceForm(BootstrapMixin, InterfaceCommonForm, forms.ModelForm):
|
class VMInterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
|
||||||
untagged_vlan = DynamicModelChoiceField(
|
untagged_vlan = DynamicModelChoiceField(
|
||||||
queryset=VLAN.objects.all(),
|
queryset=VLAN.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import django.core.serializers.json
|
import django.core.serializers.json
|
||||||
|
import taggit.managers
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
@ -54,4 +55,14 @@ class Migration(migrations.Migration):
|
|||||||
name='last_updated',
|
name='last_updated',
|
||||||
field=models.DateTimeField(auto_now=True, null=True),
|
field=models.DateTimeField(auto_now=True, null=True),
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vminterface',
|
||||||
|
name='custom_field_data',
|
||||||
|
field=models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='vminterface',
|
||||||
|
name='tags',
|
||||||
|
field=taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
@ -3,13 +3,12 @@ from django.contrib.contenttypes.fields import GenericRelation
|
|||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from taggit.managers import TaggableManager
|
|
||||||
|
|
||||||
from dcim.models import BaseInterface, Device
|
from dcim.models import BaseInterface, Device
|
||||||
from extras.models import ConfigContextModel, TaggedItem
|
from extras.models import ConfigContextModel
|
||||||
from extras.querysets import ConfigContextModelQuerySet
|
from extras.querysets import ConfigContextModelQuerySet
|
||||||
from extras.utils import extras_features
|
from extras.utils import extras_features
|
||||||
from netbox.models import BigIDModel, ChangeLoggingMixin, OrganizationalModel, PrimaryModel
|
from netbox.models import OrganizationalModel, 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
|
||||||
@ -154,7 +153,6 @@ class Cluster(PrimaryModel):
|
|||||||
comments = models.TextField(
|
comments = models.TextField(
|
||||||
blank=True
|
blank=True
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
@ -281,7 +279,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
object_id_field='assigned_object_id',
|
object_id_field='assigned_object_id',
|
||||||
related_query_name='virtual_machine'
|
related_query_name='virtual_machine'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(through=TaggedItem)
|
|
||||||
|
|
||||||
objects = ConfigContextModelQuerySet.as_manager()
|
objects = ConfigContextModelQuerySet.as_manager()
|
||||||
|
|
||||||
@ -372,9 +369,8 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
|
|||||||
# Interfaces
|
# Interfaces
|
||||||
#
|
#
|
||||||
|
|
||||||
# TODO: Inherit from PrimaryModel
|
@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks')
|
||||||
@extras_features('export_templates', 'webhooks')
|
class VMInterface(PrimaryModel, BaseInterface):
|
||||||
class VMInterface(ChangeLoggingMixin, BigIDModel, BaseInterface):
|
|
||||||
virtual_machine = models.ForeignKey(
|
virtual_machine = models.ForeignKey(
|
||||||
to='virtualization.VirtualMachine',
|
to='virtualization.VirtualMachine',
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
@ -413,10 +409,6 @@ class VMInterface(ChangeLoggingMixin, BigIDModel, BaseInterface):
|
|||||||
object_id_field='assigned_object_id',
|
object_id_field='assigned_object_id',
|
||||||
related_query_name='vminterface'
|
related_query_name='vminterface'
|
||||||
)
|
)
|
||||||
tags = TaggableManager(
|
|
||||||
through=TaggedItem,
|
|
||||||
related_name='vminterface'
|
|
||||||
)
|
|
||||||
|
|
||||||
objects = RestrictedQuerySet.as_manager()
|
objects = RestrictedQuerySet.as_manager()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user