Remove extras_features() decorator

This commit is contained in:
jeremystretch 2022-01-19 15:16:10 -05:00
parent c7825e391c
commit cdae0c2bef
26 changed files with 58 additions and 143 deletions

View File

@ -5,8 +5,8 @@ from django.urls import reverse
from circuits.choices import *
from dcim.models import LinkTermination
from extras.utils import extras_features
from netbox.models import ChangeLoggedModel, OrganizationalModel, PrimaryModel
from netbox.models.features import WebhooksMixin
__all__ = (
'Circuit',
@ -15,7 +15,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class CircuitType(OrganizationalModel):
"""
Circuits can be organized by their functional role. For example, a user might wish to define CircuitTypes named
@ -44,7 +43,6 @@ class CircuitType(OrganizationalModel):
return reverse('circuits:circuittype', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Circuit(PrimaryModel):
"""
A communications circuit connects two points. Each Circuit belongs to a Provider; Providers may have multiple
@ -138,8 +136,7 @@ class Circuit(PrimaryModel):
return CircuitStatusChoices.colors.get(self.status, 'secondary')
@extras_features('webhooks')
class CircuitTermination(ChangeLoggedModel, LinkTermination):
class CircuitTermination(WebhooksMixin, ChangeLoggedModel, LinkTermination):
circuit = models.ForeignKey(
to='circuits.Circuit',
on_delete=models.CASCADE,

View File

@ -3,7 +3,6 @@ from django.db import models
from django.urls import reverse
from dcim.fields import ASNField
from extras.utils import extras_features
from netbox.models import PrimaryModel
__all__ = (
@ -12,7 +11,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Provider(PrimaryModel):
"""
Each Circuit belongs to a Provider. This is usually a telecommunications company or similar organization. This model
@ -72,7 +70,6 @@ class Provider(PrimaryModel):
return reverse('circuits:provider', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ProviderNetwork(PrimaryModel):
"""
This represents a provider network which exists outside of NetBox, the details of which are unknown or

View File

@ -11,7 +11,6 @@ from dcim.choices import *
from dcim.constants import *
from dcim.fields import PathField
from dcim.utils import decompile_path_node, object_to_path_node, path_node_to_object
from extras.utils import extras_features
from netbox.models import BigIDModel, PrimaryModel
from utilities.fields import ColorField
from utilities.utils import to_meters
@ -29,7 +28,6 @@ __all__ = (
# Cables
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Cable(PrimaryModel):
"""
A physical connection between two endpoints.

View File

@ -1,4 +1,4 @@
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
@ -7,8 +7,8 @@ from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import *
from dcim.constants import *
from extras.utils import extras_features
from netbox.models import ChangeLoggedModel
from netbox.models.features import WebhooksMixin
from utilities.fields import ColorField, NaturalOrderingField
from utilities.mptt import TreeManager
from utilities.ordering import naturalize_interface
@ -32,7 +32,7 @@ __all__ = (
)
class ComponentTemplateModel(ChangeLoggedModel):
class ComponentTemplateModel(WebhooksMixin, ChangeLoggedModel):
device_type = models.ForeignKey(
to='dcim.DeviceType',
on_delete=models.CASCADE,
@ -135,7 +135,6 @@ class ModularComponentTemplateModel(ComponentTemplateModel):
return self.name
@extras_features('webhooks')
class ConsolePortTemplate(ModularComponentTemplateModel):
"""
A template for a ConsolePort to be created for a new Device.
@ -164,7 +163,6 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class ConsoleServerPortTemplate(ModularComponentTemplateModel):
"""
A template for a ConsoleServerPort to be created for a new Device.
@ -193,7 +191,6 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class PowerPortTemplate(ModularComponentTemplateModel):
"""
A template for a PowerPort to be created for a new Device.
@ -245,7 +242,6 @@ class PowerPortTemplate(ModularComponentTemplateModel):
})
@extras_features('webhooks')
class PowerOutletTemplate(ModularComponentTemplateModel):
"""
A template for a PowerOutlet to be created for a new Device.
@ -307,7 +303,6 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class InterfaceTemplate(ModularComponentTemplateModel):
"""
A template for a physical data interface on a new Device.
@ -347,7 +342,6 @@ class InterfaceTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class FrontPortTemplate(ModularComponentTemplateModel):
"""
Template for a pass-through port on the front of a new Device.
@ -420,7 +414,6 @@ class FrontPortTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class RearPortTemplate(ModularComponentTemplateModel):
"""
Template for a pass-through port on the rear of a new Device.
@ -460,7 +453,6 @@ class RearPortTemplate(ModularComponentTemplateModel):
)
@extras_features('webhooks')
class ModuleBayTemplate(ComponentTemplateModel):
"""
A template for a ModuleBay to be created for a new parent Device.
@ -486,7 +478,6 @@ class ModuleBayTemplate(ComponentTemplateModel):
)
@extras_features('webhooks')
class DeviceBayTemplate(ComponentTemplateModel):
"""
A template for a DeviceBay to be created for a new parent Device.
@ -511,7 +502,6 @@ class DeviceBayTemplate(ComponentTemplateModel):
)
@extras_features('webhooks')
class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
"""
A template for an InventoryItem to be created for a new parent Device.

View File

@ -11,7 +11,6 @@ from dcim.choices import *
from dcim.constants import *
from dcim.fields import MACAddressField, WWNField
from dcim.svg import CableTraceSVG
from extras.utils import extras_features
from netbox.models import OrganizationalModel, PrimaryModel
from utilities.choices import ColorChoices
from utilities.fields import ColorField, NaturalOrderingField
@ -254,7 +253,6 @@ class PathEndpoint(models.Model):
# Console components
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ConsolePort(ModularComponentModel, LinkTermination, PathEndpoint):
"""
A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts.
@ -282,7 +280,6 @@ class ConsolePort(ModularComponentModel, LinkTermination, PathEndpoint):
return reverse('dcim:consoleport', kwargs={'pk': self.pk})
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ConsoleServerPort(ModularComponentModel, LinkTermination, PathEndpoint):
"""
A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
@ -314,7 +311,6 @@ class ConsoleServerPort(ModularComponentModel, LinkTermination, PathEndpoint):
# Power components
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class PowerPort(ModularComponentModel, LinkTermination, PathEndpoint):
"""
A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets.
@ -407,7 +403,6 @@ class PowerPort(ModularComponentModel, LinkTermination, PathEndpoint):
}
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class PowerOutlet(ModularComponentModel, LinkTermination, PathEndpoint):
"""
A physical power outlet (output) within a Device which provides power to a PowerPort.
@ -522,7 +517,6 @@ class BaseInterface(models.Model):
return self.fhrp_group_assignments.count()
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Interface(ModularComponentModel, BaseInterface, LinkTermination, PathEndpoint):
"""
A network interface within a Device. A physical Interface can connect to exactly one other Interface.
@ -793,7 +787,6 @@ class Interface(ModularComponentModel, BaseInterface, LinkTermination, PathEndpo
# Pass-through ports
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class FrontPort(ModularComponentModel, LinkTermination):
"""
A pass-through port on the front of a Device.
@ -847,7 +840,6 @@ class FrontPort(ModularComponentModel, LinkTermination):
})
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class RearPort(ModularComponentModel, LinkTermination):
"""
A pass-through port on the rear of a Device.
@ -891,7 +883,6 @@ class RearPort(ModularComponentModel, LinkTermination):
# Bays
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ModuleBay(ComponentModel):
"""
An empty space within a Device which can house a child device
@ -912,7 +903,6 @@ class ModuleBay(ComponentModel):
return reverse('dcim:modulebay', kwargs={'pk': self.pk})
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class DeviceBay(ComponentModel):
"""
An empty space within a Device which can house a child device
@ -963,7 +953,6 @@ class DeviceBay(ComponentModel):
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class InventoryItemRole(OrganizationalModel):
"""
Inventory items may optionally be assigned a functional role.
@ -994,7 +983,6 @@ class InventoryItemRole(OrganizationalModel):
return reverse('dcim:inventoryitemrole', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class InventoryItem(MPTTModel, ComponentModel):
"""
An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply.

View File

@ -13,7 +13,6 @@ from dcim.choices import *
from dcim.constants import *
from extras.models import ConfigContextModel
from extras.querysets import ConfigContextModelQuerySet
from extras.utils import extras_features
from netbox.config import ConfigItem
from netbox.models import OrganizationalModel, PrimaryModel
from utilities.choices import ColorChoices
@ -37,7 +36,6 @@ __all__ = (
# Device Types
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Manufacturer(OrganizationalModel):
"""
A Manufacturer represents a company which produces hardware devices; for example, Juniper or Dell.
@ -70,7 +68,6 @@ class Manufacturer(OrganizationalModel):
return reverse('dcim:manufacturer', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class DeviceType(PrimaryModel):
"""
A DeviceType represents a particular make (Manufacturer) and model of device. It specifies rack height and depth, as
@ -353,7 +350,6 @@ class DeviceType(PrimaryModel):
return self.subdevice_role == SubdeviceRoleChoices.ROLE_CHILD
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ModuleType(PrimaryModel):
"""
A ModuleType represents a hardware element that can be installed within a device and which houses additional
@ -487,7 +483,6 @@ class ModuleType(PrimaryModel):
# Devices
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class DeviceRole(OrganizationalModel):
"""
Devices are organized by functional role; for example, "Core Switch" or "File Server". Each DeviceRole is assigned a
@ -525,7 +520,6 @@ class DeviceRole(OrganizationalModel):
return reverse('dcim:devicerole', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Platform(OrganizationalModel):
"""
Platform refers to the software or firmware running on a Device. For example, "Cisco IOS-XR" or "Juniper Junos".
@ -575,7 +569,6 @@ class Platform(OrganizationalModel):
return reverse('dcim:platform', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Device(PrimaryModel, ConfigContextModel):
"""
A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType,
@ -1012,7 +1005,6 @@ class Device(PrimaryModel, ConfigContextModel):
return DeviceStatusChoices.colors.get(self.status, 'secondary')
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Module(PrimaryModel, ConfigContextModel):
"""
A Module represents a field-installable component within a Device which may itself hold multiple device components
@ -1095,7 +1087,6 @@ class Module(PrimaryModel, ConfigContextModel):
# Virtual chassis
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VirtualChassis(PrimaryModel):
"""
A collection of Devices which operate with a shared control plane (e.g. a switch stack).

View File

@ -6,7 +6,6 @@ from django.urls import reverse
from dcim.choices import *
from dcim.constants import *
from extras.utils import extras_features
from netbox.models import PrimaryModel
from utilities.validators import ExclusionValidator
from .device_components import LinkTermination, PathEndpoint
@ -21,7 +20,6 @@ __all__ = (
# Power
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class PowerPanel(PrimaryModel):
"""
A distribution point for electrical power; e.g. a data center RPP.
@ -68,7 +66,6 @@ class PowerPanel(PrimaryModel):
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class PowerFeed(PrimaryModel, PathEndpoint, LinkTermination):
"""
An electrical circuit delivered from a PowerPanel.

View File

@ -13,7 +13,6 @@ from django.urls import reverse
from dcim.choices import *
from dcim.constants import *
from dcim.svg import RackElevationSVG
from extras.utils import extras_features
from netbox.config import get_config
from netbox.models import OrganizationalModel, PrimaryModel
from utilities.choices import ColorChoices
@ -34,7 +33,6 @@ __all__ = (
# Racks
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class RackRole(OrganizationalModel):
"""
Racks can be organized by functional role, similar to Devices.
@ -65,7 +63,6 @@ class RackRole(OrganizationalModel):
return reverse('dcim:rackrole', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Rack(PrimaryModel):
"""
Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face.
@ -438,7 +435,6 @@ class Rack(PrimaryModel):
return int(allocated_draw_total / available_power_total * 100)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class RackReservation(PrimaryModel):
"""
One or more reserved units within a Rack.

View File

@ -7,8 +7,6 @@ from timezone_field import TimeZoneField
from dcim.choices import *
from dcim.constants import *
from dcim.fields import ASNField
from extras.utils import extras_features
from netbox.models import NestedGroupModel, PrimaryModel
from utilities.fields import NaturalOrderingField
@ -24,7 +22,6 @@ __all__ = (
# Regions
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Region(NestedGroupModel):
"""
A region represents a geographic collection of sites. For example, you might create regions representing countries,
@ -111,7 +108,6 @@ class Region(NestedGroupModel):
# Site groups
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class SiteGroup(NestedGroupModel):
"""
A site group is an arbitrary grouping of sites. For example, you might have corporate sites and customer sites; and
@ -198,7 +194,6 @@ class SiteGroup(NestedGroupModel):
# Sites
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Site(PrimaryModel):
"""
A Site represents a geographic location within a network; typically a building or campus. The optional facility
@ -322,7 +317,6 @@ class Site(PrimaryModel):
# Locations
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Location(NestedGroupModel):
"""
A Location represents a subgroup of Racks and/or Devices within a Site. A Location may represent a building within a

View File

@ -7,6 +7,7 @@ EXTRAS_FEATURES = [
'custom_links',
'export_templates',
'job_results',
'journaling',
'tags',
'webhooks'
]

View File

@ -5,8 +5,8 @@ from django.db import models
from django.urls import reverse
from extras.querysets import ConfigContextQuerySet
from extras.utils import extras_features
from netbox.models import ChangeLoggedModel
from netbox.models.features import WebhooksMixin
from utilities.utils import deepmerge
@ -20,8 +20,7 @@ __all__ = (
# Config contexts
#
@extras_features('webhooks')
class ConfigContext(ChangeLoggedModel):
class ConfigContext(WebhooksMixin, ChangeLoggedModel):
"""
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

View File

@ -12,8 +12,9 @@ from django.utils.html import escape
from django.utils.safestring import mark_safe
from extras.choices import *
from extras.utils import FeatureQuery, extras_features
from extras.utils import FeatureQuery
from netbox.models import ChangeLoggedModel
from netbox.models.features import ExportTemplatesMixin, WebhooksMixin
from utilities import filters
from utilities.forms import (
CSVChoiceField, CSVMultipleChoiceField, DatePicker, DynamicModelChoiceField, DynamicModelMultipleChoiceField,
@ -40,8 +41,7 @@ class CustomFieldManager(models.Manager.from_queryset(RestrictedQuerySet)):
return self.get_queryset().filter(content_types=content_type)
@extras_features('webhooks', 'export_templates')
class CustomField(ChangeLoggedModel):
class CustomField(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
content_types = models.ManyToManyField(
to=ContentType,
related_name='custom_fields',

View File

@ -17,8 +17,9 @@ from rest_framework.utils.encoders import JSONEncoder
from extras.choices import *
from extras.constants import *
from extras.conditions import ConditionSet
from extras.utils import extras_features, FeatureQuery, image_upload
from extras.utils import FeatureQuery, image_upload
from netbox.models import BigIDModel, ChangeLoggedModel
from netbox.models.features import ExportTemplatesMixin, JobResultsMixin, WebhooksMixin
from utilities.querysets import RestrictedQuerySet
from utilities.utils import render_jinja2
@ -35,8 +36,7 @@ __all__ = (
)
@extras_features('webhooks', 'export_templates')
class Webhook(ChangeLoggedModel):
class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
"""
A Webhook defines a request that will be sent to a remote application when an object is created, updated, and/or
delete in NetBox. The request will contain a representation of the object, which the remote application can act on.
@ -184,8 +184,7 @@ class Webhook(ChangeLoggedModel):
return render_jinja2(self.payload_url, context)
@extras_features('webhooks', 'export_templates')
class CustomLink(ChangeLoggedModel):
class CustomLink(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
"""
A custom link to an external representation of a NetBox object. The link text and URL fields accept Jinja2 template
code to be rendered with an object as context.
@ -258,8 +257,7 @@ class CustomLink(ChangeLoggedModel):
}
@extras_features('webhooks', 'export_templates')
class ExportTemplate(ChangeLoggedModel):
class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
content_type = models.ForeignKey(
to=ContentType,
on_delete=models.CASCADE,
@ -345,8 +343,7 @@ class ExportTemplate(ChangeLoggedModel):
return response
@extras_features('webhooks')
class ImageAttachment(ChangeLoggedModel):
class ImageAttachment(WebhooksMixin, ChangeLoggedModel):
"""
An uploaded image which is associated with an object.
"""
@ -424,8 +421,7 @@ class ImageAttachment(ChangeLoggedModel):
return super().to_objectchange(action, related_object=self.parent)
@extras_features('webhooks')
class JournalEntry(ChangeLoggedModel):
class JournalEntry(WebhooksMixin, ChangeLoggedModel):
"""
A historical remark concerning an object; collectively, these form an object's journal. The journal is used to
preserve historical context around an object, and complements NetBox's built-in change logging. For example, you
@ -603,8 +599,7 @@ class ConfigRevision(models.Model):
# Custom scripts & reports
#
@extras_features('job_results')
class Script(models.Model):
class Script(JobResultsMixin, models.Model):
"""
Dummy model used to generate permissions for custom scripts. Does not exist in the database.
"""
@ -616,8 +611,7 @@ class Script(models.Model):
# Reports
#
@extras_features('job_results')
class Report(models.Model):
class Report(JobResultsMixin, models.Model):
"""
Dummy model used to generate permissions for reports. Does not exist in the database.
"""

View File

@ -3,8 +3,8 @@ from django.urls import reverse
from django.utils.text import slugify
from taggit.models import TagBase, GenericTaggedItemBase
from extras.utils import extras_features
from netbox.models import BigIDModel, ChangeLoggedModel
from netbox.models.features import ExportTemplatesMixin, WebhooksMixin
from utilities.choices import ColorChoices
from utilities.fields import ColorField
@ -13,8 +13,7 @@ from utilities.fields import ColorField
# Tags
#
@extras_features('webhooks', 'export_templates')
class Tag(ChangeLoggedModel, TagBase):
class Tag(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel, TagBase):
color = ColorField(
default=ColorChoices.COLOR_GREY
)

View File

@ -67,14 +67,3 @@ def register_features(model, features):
raise ValueError(f"{feature} is not a valid extras feature!")
app_label, model_name = model._meta.label_lower.split('.')
registry['model_features'][feature][app_label].append(model_name)
def extras_features(*features):
"""
Decorator used to register extras provided features to a model
"""
def wrapper(model_class):
# Initialize the model_features store if not already defined
register_features(model_class, features)
return model_class
return wrapper

View File

@ -4,8 +4,8 @@ from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.urls import reverse
from extras.utils import extras_features
from netbox.models import ChangeLoggedModel, PrimaryModel
from netbox.models.features import WebhooksMixin
from ipam.choices import *
from ipam.constants import *
@ -15,7 +15,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class FHRPGroup(PrimaryModel):
"""
A grouping of next hope resolution protocol (FHRP) peers. (For instance, VRRP or HSRP.)
@ -70,8 +69,7 @@ class FHRPGroup(PrimaryModel):
return reverse('ipam:fhrpgroup', args=[self.pk])
@extras_features('webhooks')
class FHRPGroupAssignment(ChangeLoggedModel):
class FHRPGroupAssignment(WebhooksMixin, ChangeLoggedModel):
interface_type = models.ForeignKey(
to=ContentType,
on_delete=models.CASCADE

View File

@ -9,7 +9,6 @@ from django.utils.functional import cached_property
from dcim.fields import ASNField
from dcim.models import Device
from extras.utils import extras_features
from netbox.models import OrganizationalModel, PrimaryModel
from ipam.choices import *
from ipam.constants import *
@ -54,7 +53,6 @@ class GetAvailablePrefixesMixin:
return available_prefixes.iter_cidrs()[0]
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class RIR(OrganizationalModel):
"""
A Regional Internet Registry (RIR) is responsible for the allocation of a large portion of the global IP address
@ -90,7 +88,6 @@ class RIR(OrganizationalModel):
return reverse('ipam:rir', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ASN(PrimaryModel):
"""
An autonomous system (AS) number is typically used to represent an independent routing domain. A site can have
@ -150,7 +147,6 @@ class ASN(PrimaryModel):
return self.asn
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
"""
An aggregate exists at the root level of the IP address space hierarchy in NetBox. Aggregates are used to organize
@ -253,7 +249,6 @@ class Aggregate(GetAvailablePrefixesMixin, PrimaryModel):
return min(utilization, 100)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Role(OrganizationalModel):
"""
A Role represents the functional role of a Prefix or VLAN; for example, "Customer," "Infrastructure," or
@ -285,7 +280,6 @@ class Role(OrganizationalModel):
return reverse('ipam:role', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
"""
A Prefix represents an IPv4 or IPv6 network, including mask length. Prefixes can optionally be assigned to Sites and
@ -563,7 +557,6 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
return min(utilization, 100)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class IPRange(PrimaryModel):
"""
A range of IP addresses, defined by start and end addresses.
@ -759,7 +752,6 @@ class IPRange(PrimaryModel):
return int(float(child_count) / self.size * 100)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class IPAddress(PrimaryModel):
"""
An IPAddress represents an individual IPv4 or IPv6 address and its mask. The mask length should match what is

View File

@ -4,7 +4,6 @@ from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.urls import reverse
from extras.utils import extras_features
from ipam.choices import *
from ipam.constants import *
from netbox.models import PrimaryModel
@ -47,7 +46,6 @@ class ServiceBase(models.Model):
return array_to_string(self.ports)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ServiceTemplate(ServiceBase, PrimaryModel):
"""
A template for a Service to be applied to a device or virtual machine.
@ -64,7 +62,6 @@ class ServiceTemplate(ServiceBase, PrimaryModel):
return reverse('ipam:servicetemplate', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Service(ServiceBase, PrimaryModel):
"""
A Service represents a layer-four service (e.g. HTTP or SSH) running on a Device or VirtualMachine. A Service may

View File

@ -6,7 +6,6 @@ from django.db import models
from django.urls import reverse
from dcim.models import Interface
from extras.utils import extras_features
from ipam.choices import *
from ipam.constants import *
from ipam.querysets import VLANQuerySet
@ -20,7 +19,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VLANGroup(OrganizationalModel):
"""
A VLAN group is an arbitrary collection of VLANs within which VLAN IDs and names must be unique.
@ -118,7 +116,6 @@ class VLANGroup(OrganizationalModel):
return None
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VLAN(PrimaryModel):
"""
A VLAN is a distinct layer two forwarding domain identified by a 12-bit integer (1-4094). Each VLAN must be assigned

View File

@ -1,7 +1,6 @@
from django.db import models
from django.urls import reverse
from extras.utils import extras_features
from ipam.constants import *
from netbox.models import PrimaryModel
@ -12,7 +11,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VRF(PrimaryModel):
"""
A virtual routing and forwarding (VRF) table represents a discrete layer three forwarding domain (e.g. a routing
@ -75,7 +73,6 @@ class VRF(PrimaryModel):
return reverse('ipam:vrf', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class RouteTarget(PrimaryModel):
"""
A BGP extended community used to control the redistribution of routes among VRFs, as defined in RFC 4364.

View File

@ -1,4 +1,3 @@
from django.contrib.contenttypes.fields import GenericRelation
from django.core.validators import ValidationError
from django.db import models
from mptt.models import MPTTModel, TreeForeignKey
@ -20,6 +19,18 @@ __all__ = (
# Base model classes
#
class BaseModel(
CustomFieldsMixin,
CustomLinksMixin,
ExportTemplatesMixin,
JournalingMixin,
TagsMixin,
WebhooksMixin,
):
class Meta:
abstract = True
class BigIDModel(models.Model):
"""
Abstract base model for all data objects. Ensures the use of a 64-bit PK.
@ -42,23 +53,17 @@ class ChangeLoggedModel(ChangeLoggingMixin, CustomValidationMixin, BigIDModel):
abstract = True
class PrimaryModel(ChangeLoggingMixin, CustomFieldsMixin, CustomValidationMixin, TagsMixin, BigIDModel):
class PrimaryModel(BaseModel, ChangeLoggingMixin, CustomValidationMixin, BigIDModel):
"""
Primary models represent real objects within the infrastructure being modeled.
"""
journal_entries = GenericRelation(
to='extras.JournalEntry',
object_id_field='assigned_object_id',
content_type_field='assigned_object_type'
)
objects = RestrictedQuerySet.as_manager()
class Meta:
abstract = True
class NestedGroupModel(ChangeLoggingMixin, CustomFieldsMixin, CustomValidationMixin, TagsMixin, BigIDModel, MPTTModel):
class NestedGroupModel(BaseModel, ChangeLoggingMixin, CustomValidationMixin, BigIDModel, MPTTModel):
"""
Base model for objects which are used to form a hierarchy (regions, locations, etc.). These models nest
recursively using MPTT. Within each parent, each child instance must have a unique name.
@ -100,7 +105,7 @@ class NestedGroupModel(ChangeLoggingMixin, CustomFieldsMixin, CustomValidationMi
})
class OrganizationalModel(ChangeLoggingMixin, CustomFieldsMixin, CustomValidationMixin, TagsMixin, BigIDModel):
class OrganizationalModel(BaseModel, ChangeLoggingMixin, CustomValidationMixin, BigIDModel):
"""
Organizational models are those which are used solely to categorize and qualify other objects, and do not convey
any real information about the infrastructure being modeled (for example, functional device roles). Organizational

View File

@ -1,5 +1,6 @@
import logging
from django.contrib.contenttypes.fields import GenericRelation
from django.db.models.signals import class_prepared
from django.dispatch import receiver
@ -20,6 +21,7 @@ __all__ = (
'CustomValidationMixin',
'ExportTemplatesMixin',
'JobResultsMixin',
'JournalingMixin',
'TagsMixin',
'WebhooksMixin',
)
@ -169,6 +171,20 @@ class JobResultsMixin(models.Model):
abstract = True
class JournalingMixin(models.Model):
"""
Enables support for JournalEntry assignment.
"""
journal_entries = GenericRelation(
to='extras.JournalEntry',
object_id_field='assigned_object_id',
content_type_field='assigned_object_type'
)
class Meta:
abstract = True
class TagsMixin(models.Model):
"""
Enable the assignment of Tags to a model.
@ -194,6 +210,7 @@ FEATURES_MAP = (
('custom_links', CustomLinksMixin),
('export_templates', ExportTemplatesMixin),
('job_results', JobResultsMixin),
('journaling', JournalingMixin),
('tags', TagsMixin),
('webhooks', WebhooksMixin),
)

View File

@ -4,8 +4,8 @@ from django.db import models
from django.urls import reverse
from mptt.models import TreeForeignKey
from extras.utils import extras_features
from netbox.models import ChangeLoggedModel, NestedGroupModel, OrganizationalModel, PrimaryModel
from netbox.models.features import WebhooksMixin
from tenancy.choices import *
__all__ = (
@ -16,7 +16,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ContactGroup(NestedGroupModel):
"""
An arbitrary collection of Contacts.
@ -50,7 +49,6 @@ class ContactGroup(NestedGroupModel):
return reverse('tenancy:contactgroup', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ContactRole(OrganizationalModel):
"""
Functional role for a Contact assigned to an object.
@ -78,7 +76,6 @@ class ContactRole(OrganizationalModel):
return reverse('tenancy:contactrole', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Contact(PrimaryModel):
"""
Contact information for a particular object(s) in NetBox.
@ -129,8 +126,7 @@ class Contact(PrimaryModel):
return reverse('tenancy:contact', args=[self.pk])
@extras_features('webhooks')
class ContactAssignment(ChangeLoggedModel):
class ContactAssignment(WebhooksMixin, ChangeLoggedModel):
content_type = models.ForeignKey(
to=ContentType,
on_delete=models.CASCADE

View File

@ -3,7 +3,6 @@ from django.db import models
from django.urls import reverse
from mptt.models import TreeForeignKey
from extras.utils import extras_features
from netbox.models import NestedGroupModel, PrimaryModel
__all__ = (
@ -12,7 +11,6 @@ __all__ = (
)
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class TenantGroup(NestedGroupModel):
"""
An arbitrary collection of Tenants.
@ -45,7 +43,6 @@ class TenantGroup(NestedGroupModel):
return reverse('tenancy:tenantgroup', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Tenant(PrimaryModel):
"""
A Tenant represents an organization served by the NetBox owner. This is typically a customer or an internal

View File

@ -7,7 +7,6 @@ from django.urls import reverse
from dcim.models import BaseInterface, Device
from extras.models import ConfigContextModel
from extras.querysets import ConfigContextModelQuerySet
from extras.utils import extras_features
from netbox.config import get_config
from netbox.models import OrganizationalModel, PrimaryModel
from utilities.fields import NaturalOrderingField
@ -15,7 +14,6 @@ from utilities.ordering import naturalize_interface
from utilities.query_functions import CollateAsChar
from .choices import *
__all__ = (
'Cluster',
'ClusterGroup',
@ -29,7 +27,6 @@ __all__ = (
# Cluster types
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ClusterType(OrganizationalModel):
"""
A type of Cluster.
@ -61,7 +58,6 @@ class ClusterType(OrganizationalModel):
# Cluster groups
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class ClusterGroup(OrganizationalModel):
"""
An organizational group of Clusters.
@ -104,7 +100,6 @@ class ClusterGroup(OrganizationalModel):
# Clusters
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class Cluster(PrimaryModel):
"""
A cluster of VirtualMachines. Each Cluster may optionally be associated with one or more Devices.
@ -188,7 +183,6 @@ class Cluster(PrimaryModel):
# Virtual machines
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VirtualMachine(PrimaryModel, ConfigContextModel):
"""
A virtual machine which runs inside a Cluster.
@ -351,7 +345,6 @@ class VirtualMachine(PrimaryModel, ConfigContextModel):
# Interfaces
#
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class VMInterface(PrimaryModel, BaseInterface):
virtual_machine = models.ForeignKey(
to='virtualization.VirtualMachine',

View File

@ -5,7 +5,6 @@ from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import LinkStatusChoices
from dcim.constants import WIRELESS_IFACE_TYPES
from extras.utils import extras_features
from netbox.models import BigIDModel, NestedGroupModel, PrimaryModel
from .choices import *
from .constants import *
@ -41,7 +40,6 @@ class WirelessAuthenticationBase(models.Model):
abstract = True
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class WirelessLANGroup(NestedGroupModel):
"""
A nested grouping of WirelessLANs
@ -81,7 +79,6 @@ class WirelessLANGroup(NestedGroupModel):
return reverse('wireless:wirelesslangroup', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class WirelessLAN(WirelessAuthenticationBase, PrimaryModel):
"""
A wireless network formed among an arbitrary number of access point and clients.
@ -120,7 +117,6 @@ class WirelessLAN(WirelessAuthenticationBase, PrimaryModel):
return reverse('wireless:wirelesslan', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class WirelessLink(WirelessAuthenticationBase, PrimaryModel):
"""
A point-to-point connection between two wireless Interfaces.