mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Merge branch 'develop' into feature
This commit is contained in:
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v3.2.5
|
||||
placeholder: v3.2.6
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v3.2.5
|
||||
placeholder: v3.2.6
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
@ -1,3 +1,7 @@
|
||||
# HTML sanitizer
|
||||
# https://github.com/mozilla/bleach
|
||||
bleach
|
||||
|
||||
# The Python web framework on which NetBox is built
|
||||
# https://github.com/django/django
|
||||
Django
|
||||
@ -130,7 +134,3 @@ tablib
|
||||
# Timezone data (required by django-timezone-field on Python 3.9+)
|
||||
# https://github.com/python/tzdata
|
||||
tzdata
|
||||
|
||||
# HTML sanitizer
|
||||
# https://github.com/mozilla/bleach
|
||||
bleach
|
@ -10,7 +10,7 @@ Within the database, custom fields are stored as JSON data directly alongside ea
|
||||
|
||||
Custom fields may be created by navigating to Customization > Custom Fields. NetBox supports six types of custom field:
|
||||
|
||||
* Text: Free-form text (up to 255 characters)
|
||||
* Text: Free-form text (intended for single-line use)
|
||||
* Long text: Free-form of any length; supports Markdown rendering
|
||||
* Integer: A whole number (positive or negative)
|
||||
* Boolean: True or false
|
||||
|
@ -1,6 +1,10 @@
|
||||
# NetBox v3.2
|
||||
|
||||
## v3.2.6 (FUTURE)
|
||||
## v3.2.7 (FUTURE)
|
||||
|
||||
---
|
||||
|
||||
## v3.2.6 (2022-07-11)
|
||||
|
||||
### Enhancements
|
||||
|
||||
@ -8,14 +12,18 @@
|
||||
* [#9396](https://github.com/netbox-community/netbox/issues/9396) - Allow filtering modules by bay ID
|
||||
* [#9403](https://github.com/netbox-community/netbox/issues/9403) - Enable modifying virtual chassis properties when creating/editing a device
|
||||
* [#9540](https://github.com/netbox-community/netbox/issues/9540) - Add filters for assigned device & VM to IP addresses list
|
||||
* [#9686](https://github.com/netbox-community/netbox/issues/9686) - Add tenant group column for all object tables with tenant assignments
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [#8854](https://github.com/netbox-community/netbox/issues/8854) - Fix `REMOTE_AUTH_DEFAULT_GROUPS` for social-auth backends
|
||||
* [#9575](https://github.com/netbox-community/netbox/issues/9575) - Fix AttributeError exception for FHRP group with an IP address assigned
|
||||
* [#9597](https://github.com/netbox-community/netbox/issues/9597) - Include `installed_module` in module bay REST API serializer
|
||||
* [#9632](https://github.com/netbox-community/netbox/issues/9632) - Automatically focus on search box when expanding dropdowns
|
||||
* [#9657](https://github.com/netbox-community/netbox/issues/9657) - Fix filtering for custom fields and webhooks in the UI
|
||||
* [#9682](https://github.com/netbox-community/netbox/issues/9682) - Fix bulk assignment of ASNs to sites
|
||||
* [#9687](https://github.com/netbox-community/netbox/issues/9687) - Don't restrict custom text field lengths when entering via UI form
|
||||
* [#9704](https://github.com/netbox-community/netbox/issues/9704) - Include `last_updated` field on JournalEntry REST API serializer
|
||||
|
||||
---
|
||||
|
||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
|
||||
from circuits.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from .columns import CommitRateColumn
|
||||
|
||||
__all__ = (
|
||||
@ -39,7 +39,7 @@ class CircuitTypeTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'circuit_count', 'description', 'slug')
|
||||
|
||||
|
||||
class CircuitTable(NetBoxTable):
|
||||
class CircuitTable(TenancyColumnsMixin, NetBoxTable):
|
||||
cid = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name='Circuit ID'
|
||||
@ -48,7 +48,6 @@ class CircuitTable(NetBoxTable):
|
||||
linkify=True
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
termination_a = tables.TemplateColumn(
|
||||
template_code=CIRCUITTERMINATION_LINK,
|
||||
verbose_name='Side A'
|
||||
@ -69,8 +68,9 @@ class CircuitTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Circuit
|
||||
fields = (
|
||||
'pk', 'id', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'install_date',
|
||||
'termination_date', 'commit_rate', 'description', 'comments', 'contacts', 'tags', 'created', 'last_updated',
|
||||
'pk', 'id', 'cid', 'provider', 'type', 'status', 'tenant', 'tenant_group', 'termination_a', 'termination_z',
|
||||
'install_date', 'termination_date', 'commit_rate', 'description', 'comments', 'contacts', 'tags', 'created',
|
||||
'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
'pk', 'cid', 'provider', 'type', 'status', 'tenant', 'termination_a', 'termination_z', 'description',
|
||||
|
@ -30,7 +30,7 @@ class ProviderView(generic.ObjectView):
|
||||
circuits = Circuit.objects.restrict(request.user, 'view').filter(
|
||||
provider=instance
|
||||
).prefetch_related(
|
||||
'type', 'tenant', 'terminations__site'
|
||||
'type', 'tenant', 'tenant__group', 'terminations__site'
|
||||
)
|
||||
circuits_table = tables.CircuitTable(circuits, user=request.user, exclude=('provider',))
|
||||
circuits_table.configure(request)
|
||||
@ -91,7 +91,7 @@ class ProviderNetworkView(generic.ObjectView):
|
||||
Q(termination_a__provider_network=instance.pk) |
|
||||
Q(termination_z__provider_network=instance.pk)
|
||||
).prefetch_related(
|
||||
'type', 'tenant', 'terminations__site'
|
||||
'type', 'tenant', 'tenant__group', 'terminations__site'
|
||||
)
|
||||
circuits_table = tables.CircuitTable(circuits, user=request.user)
|
||||
circuits_table.configure(request)
|
||||
@ -192,7 +192,7 @@ class CircuitTypeBulkDeleteView(generic.BulkDeleteView):
|
||||
|
||||
class CircuitListView(generic.ObjectListView):
|
||||
queryset = Circuit.objects.prefetch_related(
|
||||
'provider', 'type', 'tenant', 'termination_a', 'termination_z'
|
||||
'provider', 'type', 'tenant', 'tenant__group', 'termination_a', 'termination_z'
|
||||
)
|
||||
filterset = filtersets.CircuitFilterSet
|
||||
filterset_form = forms.CircuitFilterForm
|
||||
|
@ -96,8 +96,7 @@ class ModularComponentModel(ComponentModel):
|
||||
inventory_items = GenericRelation(
|
||||
to='dcim.InventoryItem',
|
||||
content_type_field='component_type',
|
||||
object_id_field='component_id',
|
||||
related_name='%(class)ss',
|
||||
object_id_field='component_id'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
@ -4,7 +4,7 @@ from django.utils.safestring import mark_safe
|
||||
|
||||
from dcim.models import Cable
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from .template_code import CABLE_LENGTH
|
||||
|
||||
__all__ = (
|
||||
@ -46,7 +46,7 @@ class CableTerminationsColumn(tables.Column):
|
||||
# Cables
|
||||
#
|
||||
|
||||
class CableTable(NetBoxTable):
|
||||
class CableTable(TenancyColumnsMixin, NetBoxTable):
|
||||
a_terminations = CableTerminationsColumn(
|
||||
cable_end='A',
|
||||
orderable=False,
|
||||
@ -106,7 +106,6 @@ class CableTable(NetBoxTable):
|
||||
verbose_name='Site B'
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
length = columns.TemplateColumn(
|
||||
template_code=CABLE_LENGTH,
|
||||
order_by=('_abs_length', 'length_unit')
|
||||
@ -120,8 +119,8 @@ class CableTable(NetBoxTable):
|
||||
model = Cable
|
||||
fields = (
|
||||
'pk', 'id', 'label', 'a_terminations', 'b_terminations', 'device_a', 'device_b', 'rack_a', 'rack_b',
|
||||
'location_a', 'location_b', 'site_a', 'site_b', 'status', 'type', 'tenant', 'color', 'length', 'tags',
|
||||
'created', 'last_updated',
|
||||
'location_a', 'location_b', 'site_a', 'site_b', 'status', 'type', 'tenant', 'tenant_group', 'color',
|
||||
'length', 'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
'pk', 'id', 'label', 'a_terminations', 'b_terminations', 'status', 'type',
|
||||
|
@ -6,7 +6,7 @@ from dcim.models import (
|
||||
InventoryItemRole, ModuleBay, Platform, PowerOutlet, PowerPort, RearPort, VirtualChassis,
|
||||
)
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from .template_code import *
|
||||
|
||||
__all__ = (
|
||||
@ -137,13 +137,12 @@ class PlatformTable(NetBoxTable):
|
||||
# Devices
|
||||
#
|
||||
|
||||
class DeviceTable(NetBoxTable):
|
||||
class DeviceTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.TemplateColumn(
|
||||
order_by=('_name',),
|
||||
template_code=DEVICE_LINK
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -200,7 +199,7 @@ class DeviceTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Device
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'status', 'tenant', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
|
||||
'pk', 'id', 'name', 'status', 'tenant', 'tenant_group', 'device_role', 'manufacturer', 'device_type', 'platform', 'serial',
|
||||
'asset_tag', 'site', 'location', 'rack', 'position', 'face', 'primary_ip', 'airflow', 'primary_ip4',
|
||||
'primary_ip6', 'cluster', 'virtual_chassis', 'vc_position', 'vc_priority', 'comments', 'contacts', 'tags',
|
||||
'created', 'last_updated',
|
||||
@ -211,12 +210,11 @@ class DeviceTable(NetBoxTable):
|
||||
)
|
||||
|
||||
|
||||
class DeviceImportTable(NetBoxTable):
|
||||
class DeviceImportTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.TemplateColumn(
|
||||
template_code=DEVICE_LINK
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -232,7 +230,7 @@ class DeviceImportTable(NetBoxTable):
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Device
|
||||
fields = ('id', 'name', 'status', 'tenant', 'site', 'rack', 'position', 'device_role', 'device_type')
|
||||
fields = ('id', 'name', 'status', 'tenant', 'tenant_group', 'site', 'rack', 'position', 'device_role', 'device_type')
|
||||
empty_text = False
|
||||
|
||||
|
||||
|
@ -3,7 +3,7 @@ from django_tables2.utils import Accessor
|
||||
|
||||
from dcim.models import Rack, RackReservation, RackRole
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
|
||||
__all__ = (
|
||||
'RackTable',
|
||||
@ -37,7 +37,7 @@ class RackRoleTable(NetBoxTable):
|
||||
# Racks
|
||||
#
|
||||
|
||||
class RackTable(NetBoxTable):
|
||||
class RackTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
order_by=('_name',),
|
||||
linkify=True
|
||||
@ -48,7 +48,6 @@ class RackTable(NetBoxTable):
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
status = columns.ChoiceFieldColumn()
|
||||
role = columns.ColoredLabelColumn()
|
||||
u_height = tables.TemplateColumn(
|
||||
@ -87,7 +86,7 @@ class RackTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Rack
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'role', 'serial', 'asset_tag',
|
||||
'pk', 'id', 'name', 'site', 'location', 'status', 'facility_id', 'tenant', 'tenant_group', 'role', 'serial', 'asset_tag',
|
||||
'type', 'width', 'outer_width', 'outer_depth', 'u_height', 'comments', 'device_count', 'get_utilization',
|
||||
'get_power_utilization', 'contacts', 'tags', 'created', 'last_updated',
|
||||
)
|
||||
@ -101,7 +100,7 @@ class RackTable(NetBoxTable):
|
||||
# Rack reservations
|
||||
#
|
||||
|
||||
class RackReservationTable(NetBoxTable):
|
||||
class RackReservationTable(TenancyColumnsMixin, NetBoxTable):
|
||||
reservation = tables.Column(
|
||||
accessor='pk',
|
||||
linkify=True
|
||||
@ -110,7 +109,6 @@ class RackReservationTable(NetBoxTable):
|
||||
accessor=Accessor('rack__site'),
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
rack = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -125,7 +123,7 @@ class RackReservationTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = RackReservation
|
||||
fields = (
|
||||
'pk', 'id', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'description', 'tags',
|
||||
'pk', 'id', 'reservation', 'site', 'rack', 'unit_list', 'user', 'created', 'tenant', 'tenant_group', 'description', 'tags',
|
||||
'actions', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'reservation', 'site', 'rack', 'unit_list', 'user', 'description')
|
||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
|
||||
from dcim.models import Location, Region, Site, SiteGroup
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from .template_code import LOCATION_BUTTONS
|
||||
|
||||
__all__ = (
|
||||
@ -75,7 +75,7 @@ class SiteGroupTable(NetBoxTable):
|
||||
# Sites
|
||||
#
|
||||
|
||||
class SiteTable(NetBoxTable):
|
||||
class SiteTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -96,7 +96,6 @@ class SiteTable(NetBoxTable):
|
||||
url_params={'site_id': 'pk'},
|
||||
verbose_name='ASN Count'
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
comments = columns.MarkdownColumn()
|
||||
contacts = columns.ManyToManyColumn(
|
||||
linkify_item=True
|
||||
@ -108,7 +107,7 @@ class SiteTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Site
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'asns', 'asn_count',
|
||||
'pk', 'id', 'name', 'slug', 'status', 'facility', 'region', 'group', 'tenant', 'tenant_group', 'asns', 'asn_count',
|
||||
'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'comments',
|
||||
'contacts', 'tags', 'created', 'last_updated', 'actions',
|
||||
)
|
||||
@ -119,15 +118,13 @@ class SiteTable(NetBoxTable):
|
||||
# Locations
|
||||
#
|
||||
|
||||
class LocationTable(NetBoxTable):
|
||||
class LocationTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
linkify=True
|
||||
)
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
rack_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:rack_list',
|
||||
url_params={'location_id': 'pk'},
|
||||
@ -151,7 +148,7 @@ class LocationTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Location
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'site', 'status', 'tenant', 'rack_count', 'device_count', 'description', 'slug',
|
||||
'contacts', 'tags', 'actions', 'created', 'last_updated',
|
||||
'pk', 'id', 'name', 'site', 'status', 'tenant', 'tenant_group', 'rack_count', 'device_count', 'description',
|
||||
'slug', 'contacts', 'tags', 'actions', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'name', 'site', 'status', 'tenant', 'rack_count', 'device_count', 'description')
|
||||
|
@ -572,9 +572,7 @@ class RackRoleBulkDeleteView(generic.BulkDeleteView):
|
||||
#
|
||||
|
||||
class RackListView(generic.ObjectListView):
|
||||
queryset = Rack.objects.prefetch_related(
|
||||
'site', 'location', 'tenant', 'role', 'devices__device_type'
|
||||
).annotate(
|
||||
queryset = Rack.objects.prefetch_related('devices__device_type').annotate(
|
||||
device_count=count_related(Device, 'rack')
|
||||
)
|
||||
filterset = filtersets.RackFilterSet
|
||||
|
@ -222,7 +222,7 @@ class JournalEntrySerializer(NetBoxModelSerializer):
|
||||
model = JournalEntry
|
||||
fields = [
|
||||
'id', 'url', 'display', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'created',
|
||||
'created_by', 'kind', 'comments', 'tags', 'custom_fields',
|
||||
'created_by', 'kind', 'comments', 'tags', 'custom_fields', 'last_updated',
|
||||
]
|
||||
|
||||
def validate(self, data):
|
||||
|
@ -377,13 +377,8 @@ class CustomField(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
|
||||
|
||||
# Text
|
||||
else:
|
||||
if self.type == CustomFieldTypeChoices.TYPE_LONGTEXT:
|
||||
max_length = None
|
||||
widget = forms.Textarea
|
||||
else:
|
||||
max_length = 255
|
||||
widget = None
|
||||
field = forms.CharField(max_length=max_length, required=required, initial=initial, widget=widget)
|
||||
widget = forms.Textarea if self.type == CustomFieldTypeChoices.TYPE_LONGTEXT else None
|
||||
field = forms.CharField(required=required, initial=initial, widget=widget)
|
||||
if self.validation_regex:
|
||||
field.validators = [
|
||||
RegexValidator(
|
||||
|
@ -4,7 +4,7 @@ from django_tables2.utils import Accessor
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin, TenantColumn
|
||||
|
||||
__all__ = (
|
||||
'AggregateTable',
|
||||
@ -99,7 +99,7 @@ class RIRTable(NetBoxTable):
|
||||
# ASNs
|
||||
#
|
||||
|
||||
class ASNTable(NetBoxTable):
|
||||
class ASNTable(TenancyColumnsMixin, NetBoxTable):
|
||||
asn = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -122,7 +122,6 @@ class ASNTable(NetBoxTable):
|
||||
linkify_item=True,
|
||||
verbose_name='Sites'
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:asn_list'
|
||||
)
|
||||
@ -130,7 +129,7 @@ class ASNTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = ASN
|
||||
fields = (
|
||||
'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'provider_count', 'tenant', 'description', 'sites', 'tags',
|
||||
'pk', 'asn', 'asn_asdot', 'rir', 'site_count', 'provider_count', 'tenant', 'tenant_group', 'description', 'sites', 'tags',
|
||||
'created', 'last_updated', 'actions',
|
||||
)
|
||||
default_columns = ('pk', 'asn', 'rir', 'site_count', 'provider_count', 'sites', 'description', 'tenant')
|
||||
@ -140,12 +139,11 @@ class ASNTable(NetBoxTable):
|
||||
# Aggregates
|
||||
#
|
||||
|
||||
class AggregateTable(NetBoxTable):
|
||||
class AggregateTable(TenancyColumnsMixin, NetBoxTable):
|
||||
prefix = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name='Aggregate'
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
date_added = tables.DateColumn(
|
||||
format="Y-m-d",
|
||||
verbose_name='Added'
|
||||
@ -164,7 +162,7 @@ class AggregateTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Aggregate
|
||||
fields = (
|
||||
'pk', 'id', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description', 'tags',
|
||||
'pk', 'id', 'prefix', 'rir', 'tenant', 'tenant_group', 'child_count', 'utilization', 'date_added', 'description', 'tags',
|
||||
'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'prefix', 'rir', 'tenant', 'child_count', 'utilization', 'date_added', 'description')
|
||||
@ -225,7 +223,7 @@ class PrefixUtilizationColumn(columns.UtilizationColumn):
|
||||
"""
|
||||
|
||||
|
||||
class PrefixTable(NetBoxTable):
|
||||
class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
prefix = columns.TemplateColumn(
|
||||
template_code=PREFIX_LINK,
|
||||
export_raw=True,
|
||||
@ -256,7 +254,6 @@ class PrefixTable(NetBoxTable):
|
||||
template_code=VRF_LINK,
|
||||
verbose_name='VRF'
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -289,7 +286,7 @@ class PrefixTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Prefix
|
||||
fields = (
|
||||
'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site',
|
||||
'pk', 'id', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'tenant_group', 'site',
|
||||
'vlan_group', 'vlan', 'role', 'is_pool', 'mark_utilized', 'description', 'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
@ -303,7 +300,7 @@ class PrefixTable(NetBoxTable):
|
||||
#
|
||||
# IP ranges
|
||||
#
|
||||
class IPRangeTable(NetBoxTable):
|
||||
class IPRangeTable(TenancyColumnsMixin, NetBoxTable):
|
||||
start_address = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -317,7 +314,6 @@ class IPRangeTable(NetBoxTable):
|
||||
role = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
utilization = columns.UtilizationColumn(
|
||||
accessor='utilization',
|
||||
orderable=False
|
||||
@ -329,7 +325,7 @@ class IPRangeTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = IPRange
|
||||
fields = (
|
||||
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'description',
|
||||
'pk', 'id', 'start_address', 'end_address', 'size', 'vrf', 'status', 'role', 'tenant', 'tenant_group', 'description',
|
||||
'utilization', 'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
@ -344,7 +340,7 @@ class IPRangeTable(NetBoxTable):
|
||||
# IPAddresses
|
||||
#
|
||||
|
||||
class IPAddressTable(NetBoxTable):
|
||||
class IPAddressTable(TenancyColumnsMixin, NetBoxTable):
|
||||
address = tables.TemplateColumn(
|
||||
template_code=IPADDRESS_LINK,
|
||||
verbose_name='IP Address'
|
||||
@ -357,7 +353,6 @@ class IPAddressTable(NetBoxTable):
|
||||
default=AVAILABLE_LABEL
|
||||
)
|
||||
role = columns.ChoiceFieldColumn()
|
||||
tenant = TenantColumn()
|
||||
assigned_object = tables.Column(
|
||||
linkify=True,
|
||||
orderable=False,
|
||||
@ -386,7 +381,7 @@ class IPAddressTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = IPAddress
|
||||
fields = (
|
||||
'pk', 'id', 'address', 'vrf', 'status', 'role', 'tenant', 'nat_inside', 'assigned', 'dns_name', 'description',
|
||||
'pk', 'id', 'address', 'vrf', 'status', 'role', 'tenant', 'tenant_group', 'nat_inside', 'assigned', 'dns_name', 'description',
|
||||
'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
|
@ -5,7 +5,7 @@ from django_tables2.utils import Accessor
|
||||
from dcim.models import Interface
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin, TenantColumn
|
||||
from virtualization.models import VMInterface
|
||||
|
||||
__all__ = (
|
||||
@ -90,7 +90,7 @@ class VLANGroupTable(NetBoxTable):
|
||||
# VLANs
|
||||
#
|
||||
|
||||
class VLANTable(NetBoxTable):
|
||||
class VLANTable(TenancyColumnsMixin, NetBoxTable):
|
||||
vid = tables.TemplateColumn(
|
||||
template_code=VLAN_LINK,
|
||||
verbose_name='VID'
|
||||
@ -104,7 +104,6 @@ class VLANTable(NetBoxTable):
|
||||
group = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
status = columns.ChoiceFieldColumn(
|
||||
default=AVAILABLE_LABEL
|
||||
)
|
||||
@ -123,7 +122,7 @@ class VLANTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = VLAN
|
||||
fields = (
|
||||
'pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description', 'tags',
|
||||
'pk', 'id', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'tenant_group', 'status', 'role', 'description', 'tags',
|
||||
'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'vid', 'name', 'site', 'group', 'prefixes', 'tenant', 'status', 'role', 'description')
|
||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
|
||||
from ipam.models import *
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
|
||||
__all__ = (
|
||||
'RouteTargetTable',
|
||||
@ -20,14 +20,13 @@ VRF_TARGETS = """
|
||||
# VRFs
|
||||
#
|
||||
|
||||
class VRFTable(NetBoxTable):
|
||||
class VRFTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
rd = tables.Column(
|
||||
verbose_name='RD'
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
enforce_unique = columns.BooleanColumn(
|
||||
verbose_name='Unique'
|
||||
)
|
||||
@ -46,7 +45,7 @@ class VRFTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = VRF
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'import_targets', 'export_targets',
|
||||
'pk', 'id', 'name', 'rd', 'tenant', 'tenant_group', 'enforce_unique', 'description', 'import_targets', 'export_targets',
|
||||
'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'name', 'rd', 'tenant', 'description')
|
||||
@ -56,16 +55,15 @@ class VRFTable(NetBoxTable):
|
||||
# Route targets
|
||||
#
|
||||
|
||||
class RouteTargetTable(NetBoxTable):
|
||||
class RouteTargetTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tenant = TenantColumn()
|
||||
tags = columns.TagColumn(
|
||||
url_name='ipam:vrf_list'
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = RouteTarget
|
||||
fields = ('pk', 'id', 'name', 'tenant', 'description', 'tags', 'created', 'last_updated',)
|
||||
fields = ('pk', 'id', 'name', 'tenant', 'tenant_group', 'description', 'tags', 'created', 'last_updated',)
|
||||
default_columns = ('pk', 'name', 'tenant', 'description')
|
||||
|
@ -299,7 +299,7 @@ class AggregatePrefixesView(generic.ObjectChildrenView):
|
||||
def get_children(self, request, parent):
|
||||
return Prefix.objects.restrict(request.user, 'view').filter(
|
||||
prefix__net_contained_or_equal=str(parent.prefix)
|
||||
).prefetch_related('site', 'role', 'tenant', 'vlan')
|
||||
).prefetch_related('site', 'role', 'tenant', 'tenant__group', 'vlan')
|
||||
|
||||
def prep_table_data(self, request, queryset, parent):
|
||||
# Determine whether to show assigned prefixes, available prefixes, or both
|
||||
@ -471,7 +471,7 @@ class PrefixPrefixesView(generic.ObjectChildrenView):
|
||||
|
||||
def get_children(self, request, parent):
|
||||
return parent.get_child_prefixes().restrict(request.user, 'view').prefetch_related(
|
||||
'site', 'vrf', 'vlan', 'role', 'tenant',
|
||||
'site', 'vrf', 'vlan', 'role', 'tenant', 'tenant__group'
|
||||
)
|
||||
|
||||
def prep_table_data(self, request, queryset, parent):
|
||||
@ -500,7 +500,7 @@ class PrefixIPRangesView(generic.ObjectChildrenView):
|
||||
|
||||
def get_children(self, request, parent):
|
||||
return parent.get_child_ranges().restrict(request.user, 'view').prefetch_related(
|
||||
'vrf', 'role', 'tenant',
|
||||
'vrf', 'role', 'tenant', 'tenant__group',
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -587,9 +587,7 @@ class IPRangeIPAddressesView(generic.ObjectChildrenView):
|
||||
template_name = 'ipam/iprange/ip_addresses.html'
|
||||
|
||||
def get_children(self, request, parent):
|
||||
return parent.get_child_ips().restrict(request.user, 'view').prefetch_related(
|
||||
'vrf', 'tenant',
|
||||
)
|
||||
return parent.get_child_ips().restrict(request.user, 'view')
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
|
@ -34,7 +34,7 @@ CIRCUIT_TYPES = OrderedDict(
|
||||
}),
|
||||
('circuit', {
|
||||
'queryset': Circuit.objects.prefetch_related(
|
||||
'type', 'provider', 'tenant', 'terminations__site'
|
||||
'type', 'provider', 'tenant', 'tenant__group', 'terminations__site'
|
||||
),
|
||||
'filterset': circuits.filtersets.CircuitFilterSet,
|
||||
'table': circuits.tables.CircuitTable,
|
||||
@ -53,13 +53,13 @@ CIRCUIT_TYPES = OrderedDict(
|
||||
DCIM_TYPES = OrderedDict(
|
||||
(
|
||||
('site', {
|
||||
'queryset': Site.objects.prefetch_related('region', 'tenant'),
|
||||
'queryset': Site.objects.prefetch_related('region', 'tenant', 'tenant__group'),
|
||||
'filterset': dcim.filtersets.SiteFilterSet,
|
||||
'table': dcim.tables.SiteTable,
|
||||
'url': 'dcim:site_list',
|
||||
}),
|
||||
('rack', {
|
||||
'queryset': Rack.objects.prefetch_related('site', 'location', 'tenant', 'role').annotate(
|
||||
'queryset': Rack.objects.prefetch_related('site', 'location', 'tenant', 'tenant__group', 'role').annotate(
|
||||
device_count=count_related(Device, 'rack')
|
||||
),
|
||||
'filterset': dcim.filtersets.RackFilterSet,
|
||||
@ -100,7 +100,7 @@ DCIM_TYPES = OrderedDict(
|
||||
}),
|
||||
('device', {
|
||||
'queryset': Device.objects.prefetch_related(
|
||||
'device_type__manufacturer', 'device_role', 'tenant', 'site', 'rack', 'primary_ip4', 'primary_ip6',
|
||||
'device_type__manufacturer', 'device_role', 'tenant', 'tenant__group', 'site', 'rack', 'primary_ip4', 'primary_ip6',
|
||||
),
|
||||
'filterset': dcim.filtersets.DeviceFilterSet,
|
||||
'table': dcim.tables.DeviceTable,
|
||||
@ -148,7 +148,7 @@ DCIM_TYPES = OrderedDict(
|
||||
IPAM_TYPES = OrderedDict(
|
||||
(
|
||||
('vrf', {
|
||||
'queryset': VRF.objects.prefetch_related('tenant'),
|
||||
'queryset': VRF.objects.prefetch_related('tenant', 'tenant__group'),
|
||||
'filterset': ipam.filtersets.VRFFilterSet,
|
||||
'table': ipam.tables.VRFTable,
|
||||
'url': 'ipam:vrf_list',
|
||||
@ -160,25 +160,25 @@ IPAM_TYPES = OrderedDict(
|
||||
'url': 'ipam:aggregate_list',
|
||||
}),
|
||||
('prefix', {
|
||||
'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'vlan', 'role'),
|
||||
'queryset': Prefix.objects.prefetch_related('site', 'vrf__tenant', 'tenant', 'tenant__group', 'vlan', 'role'),
|
||||
'filterset': ipam.filtersets.PrefixFilterSet,
|
||||
'table': ipam.tables.PrefixTable,
|
||||
'url': 'ipam:prefix_list',
|
||||
}),
|
||||
('ipaddress', {
|
||||
'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant'),
|
||||
'queryset': IPAddress.objects.prefetch_related('vrf__tenant', 'tenant', 'tenant__group'),
|
||||
'filterset': ipam.filtersets.IPAddressFilterSet,
|
||||
'table': ipam.tables.IPAddressTable,
|
||||
'url': 'ipam:ipaddress_list',
|
||||
}),
|
||||
('vlan', {
|
||||
'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'role'),
|
||||
'queryset': VLAN.objects.prefetch_related('site', 'group', 'tenant', 'tenant__group', 'role'),
|
||||
'filterset': ipam.filtersets.VLANFilterSet,
|
||||
'table': ipam.tables.VLANTable,
|
||||
'url': 'ipam:vlan_list',
|
||||
}),
|
||||
('asn', {
|
||||
'queryset': ASN.objects.prefetch_related('rir', 'tenant'),
|
||||
'queryset': ASN.objects.prefetch_related('rir', 'tenant', 'tenant__group'),
|
||||
'filterset': ipam.filtersets.ASNFilterSet,
|
||||
'table': ipam.tables.ASNTable,
|
||||
'url': 'ipam:asn_list',
|
||||
@ -223,7 +223,7 @@ VIRTUALIZATION_TYPES = OrderedDict(
|
||||
}),
|
||||
('virtualmachine', {
|
||||
'queryset': VirtualMachine.objects.prefetch_related(
|
||||
'cluster', 'tenant', 'platform', 'primary_ip4', 'primary_ip6',
|
||||
'cluster', 'tenant', 'tenant__group', 'platform', 'primary_ip4', 'primary_ip6',
|
||||
),
|
||||
'filterset': virtualization.filtersets.VirtualMachineFilterSet,
|
||||
'table': virtualization.tables.VirtualMachineTable,
|
||||
|
2
netbox/project-static/dist/netbox.js
vendored
2
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
2
netbox/project-static/dist/netbox.js.map
vendored
2
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@ -411,6 +411,7 @@ export class APISelect {
|
||||
} finally {
|
||||
this.setOptionStyles();
|
||||
this.enable();
|
||||
this.slim.slim.search.input.focus();
|
||||
this.base.dispatchEvent(this.loadEvent);
|
||||
}
|
||||
}
|
||||
|
@ -48,9 +48,9 @@
|
||||
<th scope="row">Rack</th>
|
||||
<td>
|
||||
{% if object.rack %}
|
||||
<a href="{% url 'dcim:rack' pk=object.rack.pk %}">{{ object.rack }}</a>
|
||||
{{ object.rack|linkify }}
|
||||
<div class="float-end noprint">
|
||||
<a href="{% url 'dcim:rack' pk=object.rack.pk %}?device={{ object.pk }}" class="btn btn-primary btn-sm" title="Highlight device">
|
||||
<a href="{{ object.rack.get_absolute_url }}?device={{ object.pk }}" class="btn btn-primary btn-sm" title="Highlight device">
|
||||
<i class="mdi mdi-view-day-outline"></i>
|
||||
</a>
|
||||
</div>
|
||||
@ -166,9 +166,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Role</th>
|
||||
<td>
|
||||
<a href="{% url 'dcim:device_list' %}?role={{ object.device_role.slug }}">{{ object.device_role }}</a>
|
||||
</td>
|
||||
<td>{{ object.device_role|linkify }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Platform</th>
|
||||
@ -178,7 +176,7 @@
|
||||
<th scope="row">Primary IPv4</th>
|
||||
<td>
|
||||
{% if object.primary_ip4 %}
|
||||
<a href="{% url 'ipam:ipaddress' pk=object.primary_ip4.pk %}">{{ object.primary_ip4.address.ip }}</a>
|
||||
<a href="{{ object.primary_ip4.get_absolute_url }}">{{ object.primary_ip4.address.ip }}</a>
|
||||
{% if object.primary_ip4.nat_inside %}
|
||||
(NAT for {{ object.primary_ip4.nat_inside.address.ip|linkify }})
|
||||
{% elif object.primary_ip4.nat_outside %}
|
||||
@ -193,7 +191,7 @@
|
||||
<th scope="row">Primary IPv6</th>
|
||||
<td>
|
||||
{% if object.primary_ip6 %}
|
||||
<a href="{% url 'ipam:ipaddress' pk=object.primary_ip6.pk %}">{{ object.primary_ip6.address.ip }}</a>
|
||||
<a href="{{ object.primary_ip6.get_absolute_url }}">{{ object.primary_ip6.address.ip }}</a>
|
||||
{% if object.primary_ip6.nat_inside %}
|
||||
(NAT for {{ object.primary_ip6.nat_inside.address.ip|linkify }})
|
||||
{% elif object.primary_ip6.nat_outside %}
|
||||
|
@ -5,25 +5,29 @@
|
||||
{% render_errors form %}
|
||||
|
||||
{% block content %}
|
||||
{% if perms.extras.add_journalentry %}
|
||||
<form action="{% url 'extras:journalentry_add' %}" method="post" enctype="multipart/form-data">
|
||||
<div class="container">
|
||||
<div class="field-group">
|
||||
<h4>New Journal Entry</h4>
|
||||
{% csrf_token %}
|
||||
{% render_form form %}
|
||||
</div>
|
||||
<div class="col col-md-12 text-end my-3">
|
||||
<a href="{{ object.get_absolute_url }}" class="btn btn-outline-danger">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
<div class="card">
|
||||
<div class="card-body table-responsive">
|
||||
{% render_table table 'inc/table.html' %}
|
||||
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
|
||||
</div>
|
||||
</div>
|
||||
{% if perms.extras.add_journalentry %}
|
||||
<div class="card">
|
||||
<div class="card-body table-responsive">
|
||||
<h4 class="card-header">New Journal Entry</h4>
|
||||
<form action="{% url 'extras:journalentry_add' %}" method="post" enctype="multipart/form-data">
|
||||
<div class="container">
|
||||
<div class="field-group">
|
||||
{% csrf_token %}
|
||||
{% render_form form %}
|
||||
</div>
|
||||
<div class="col col-md-12 text-end my-3">
|
||||
<a href="{{ object.get_absolute_url }}" class="btn btn-outline-danger">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -2,6 +2,8 @@ import django_tables2 as tables
|
||||
|
||||
__all__ = (
|
||||
'TenantColumn',
|
||||
'TenantGroupColumn',
|
||||
'TenancyColumnsMixin',
|
||||
)
|
||||
|
||||
|
||||
@ -24,3 +26,32 @@ class TenantColumn(tables.TemplateColumn):
|
||||
|
||||
def value(self, value):
|
||||
return str(value) if value else None
|
||||
|
||||
|
||||
class TenantGroupColumn(tables.TemplateColumn):
|
||||
"""
|
||||
Include the tenant group description.
|
||||
"""
|
||||
template_code = """
|
||||
{% if record.tenant and record.tenant.group %}
|
||||
<a href="{{ record.tenant.group.get_absolute_url }}" title="{{ record.tenant.group.description }}">{{ record.tenant.group }}</a>
|
||||
{% elif record.vrf.tenant and record.vrf.tenant.group %}
|
||||
<a href="{{ record.vrf.tenant.group.get_absolute_url }}" title="{{ record.vrf.tenant.group.description }}">{{ record.vrf.tenant.group }}</a>*
|
||||
{% else %}
|
||||
—
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
def __init__(self, accessor=tables.A('tenant__group'), *args, **kwargs):
|
||||
if 'verbose_name' not in kwargs:
|
||||
kwargs['verbose_name'] = 'Tenant Group'
|
||||
|
||||
super().__init__(template_code=self.template_code, accessor=accessor, *args, **kwargs)
|
||||
|
||||
def value(self, value):
|
||||
return str(value) if value else None
|
||||
|
||||
|
||||
class TenancyColumnsMixin(tables.Table):
|
||||
tenant_group = TenantGroupColumn()
|
||||
tenant = TenantColumn()
|
||||
|
@ -1,6 +1,7 @@
|
||||
import django_tables2 as tables
|
||||
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||
|
||||
__all__ = (
|
||||
@ -56,7 +57,7 @@ class ClusterGroupTable(NetBoxTable):
|
||||
default_columns = ('pk', 'name', 'cluster_count', 'description')
|
||||
|
||||
|
||||
class ClusterTable(NetBoxTable):
|
||||
class ClusterTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -66,10 +67,6 @@ class ClusterTable(NetBoxTable):
|
||||
group = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
status = columns.ChoiceFieldColumn()
|
||||
tenant = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
site = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
@ -94,7 +91,7 @@ class ClusterTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Cluster
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'type', 'group', 'status', 'tenant', 'site', 'comments', 'device_count', 'vm_count',
|
||||
'contacts', 'tags', 'created', 'last_updated',
|
||||
'pk', 'id', 'name', 'type', 'group', 'status', 'tenant', 'tenant_group', 'site', 'comments', 'device_count',
|
||||
'vm_count', 'contacts', 'tags', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'name', 'type', 'group', 'status', 'tenant', 'site', 'device_count', 'vm_count')
|
||||
|
@ -2,7 +2,7 @@ import django_tables2 as tables
|
||||
|
||||
from dcim.tables.devices import BaseInterfaceTable
|
||||
from netbox.tables import NetBoxTable, columns
|
||||
from tenancy.tables import TenantColumn
|
||||
from tenancy.tables import TenancyColumnsMixin
|
||||
from virtualization.models import VirtualMachine, VMInterface
|
||||
|
||||
__all__ = (
|
||||
@ -24,7 +24,7 @@ VMINTERFACE_BUTTONS = """
|
||||
# Virtual machines
|
||||
#
|
||||
|
||||
class VirtualMachineTable(NetBoxTable):
|
||||
class VirtualMachineTable(TenancyColumnsMixin, NetBoxTable):
|
||||
name = tables.Column(
|
||||
order_by=('_name',),
|
||||
linkify=True
|
||||
@ -40,7 +40,6 @@ class VirtualMachineTable(NetBoxTable):
|
||||
linkify=True
|
||||
)
|
||||
role = columns.ColoredLabelColumn()
|
||||
tenant = TenantColumn()
|
||||
comments = columns.MarkdownColumn()
|
||||
primary_ip4 = tables.Column(
|
||||
linkify=True,
|
||||
@ -62,8 +61,9 @@ class VirtualMachineTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = VirtualMachine
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant', 'platform', 'vcpus', 'memory',
|
||||
'disk', 'primary_ip4', 'primary_ip6', 'primary_ip', 'comments', 'tags', 'created', 'last_updated',
|
||||
'pk', 'id', 'name', 'status', 'site', 'cluster', 'device', 'role', 'tenant', 'tenant_group', 'platform',
|
||||
'vcpus', 'memory', 'disk', 'primary_ip4', 'primary_ip6', 'primary_ip', 'comments', 'tags', 'created',
|
||||
'last_updated',
|
||||
)
|
||||
default_columns = (
|
||||
'pk', 'name', 'status', 'site', 'cluster', 'role', 'tenant', 'vcpus', 'memory', 'disk', 'primary_ip',
|
||||
|
@ -1,7 +1,7 @@
|
||||
bleach==5.0.0
|
||||
Django==4.0.5
|
||||
bleach==5.0.1
|
||||
Django==4.0.6
|
||||
django-cors-headers==3.13.0
|
||||
django-debug-toolbar==3.4.0
|
||||
django-debug-toolbar==3.5.0
|
||||
django-filter==22.1
|
||||
django-graphiql-debug-toolbar==0.2.0
|
||||
django-mptt==0.13.4
|
||||
@ -20,13 +20,13 @@ gunicorn==20.1.0
|
||||
Jinja2==3.1.2
|
||||
Markdown==3.3.7
|
||||
markdown-include==0.6.0
|
||||
mkdocs-material==8.3.6
|
||||
mkdocs-material==8.3.9
|
||||
mkdocstrings[python-legacy]==0.19.0
|
||||
netaddr==0.8.0
|
||||
Pillow==9.1.1
|
||||
Pillow==9.2.0
|
||||
psycopg2-binary==2.9.3
|
||||
PyYAML==6.0
|
||||
sentry-sdk==1.5.12
|
||||
sentry-sdk==1.7.0
|
||||
social-auth-app-django==5.0.0
|
||||
social-auth-core==4.3.0
|
||||
svgwrite==1.4.2
|
||||
|
Reference in New Issue
Block a user