mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-16 20:22:53 -06:00
Adds tenant on power feed (#13300)
* adds tenant on power feed * cleanup * adds power feed count on tenant object view * Misc cleanup; add filterset tests --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
parent
07f68ae579
commit
36f95f7842
@ -1236,6 +1236,10 @@ class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
|||||||
choices=PowerFeedPhaseChoices,
|
choices=PowerFeedPhaseChoices,
|
||||||
default=lambda: PowerFeedPhaseChoices.PHASE_SINGLE,
|
default=lambda: PowerFeedPhaseChoices.PHASE_SINGLE,
|
||||||
)
|
)
|
||||||
|
tenant = NestedTenantSerializer(
|
||||||
|
required=False,
|
||||||
|
allow_null=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
@ -1243,5 +1247,5 @@ class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
|
|||||||
'id', 'url', 'display', 'power_panel', 'rack', 'name', 'status', 'type', 'supply', 'phase', 'voltage',
|
'id', 'url', 'display', 'power_panel', 'rack', 'name', 'status', 'type', 'supply', 'phase', 'voltage',
|
||||||
'amperage', 'max_utilization', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
|
'amperage', 'max_utilization', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type',
|
||||||
'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'description',
|
'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'description',
|
||||||
'comments', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
|
'tenant', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied',
|
||||||
]
|
]
|
||||||
|
@ -6,7 +6,6 @@ from netaddr import AddrFormatError, EUI, eui64_unix_expanded, mac_unix_expanded
|
|||||||
from .lookups import PathContains
|
from .lookups import PathContains
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ASNField',
|
|
||||||
'MACAddressField',
|
'MACAddressField',
|
||||||
'PathField',
|
'PathField',
|
||||||
'WWNField',
|
'WWNField',
|
||||||
|
@ -1880,7 +1880,7 @@ class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
|
|||||||
return queryset.filter(qs_filter)
|
return queryset.filter(qs_filter)
|
||||||
|
|
||||||
|
|
||||||
class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet):
|
class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpointFilterSet, TenancyFilterSet):
|
||||||
region_id = TreeNodeMultipleChoiceFilter(
|
region_id = TreeNodeMultipleChoiceFilter(
|
||||||
queryset=Region.objects.all(),
|
queryset=Region.objects.all(),
|
||||||
field_name='power_panel__site__region',
|
field_name='power_panel__site__region',
|
||||||
|
@ -754,6 +754,10 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
|
|||||||
required=False,
|
required=False,
|
||||||
widget=BulkEditNullBooleanSelect
|
widget=BulkEditNullBooleanSelect
|
||||||
)
|
)
|
||||||
|
tenant = DynamicModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
description = forms.CharField(
|
description = forms.CharField(
|
||||||
max_length=200,
|
max_length=200,
|
||||||
required=False
|
required=False
|
||||||
@ -764,10 +768,10 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
|
|||||||
|
|
||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('power_panel', 'rack', 'status', 'type', 'mark_connected', 'description')),
|
(None, ('power_panel', 'rack', 'status', 'type', 'mark_connected', 'description', 'tenant')),
|
||||||
('Power', ('supply', 'phase', 'voltage', 'amperage', 'max_utilization'))
|
('Power', ('supply', 'phase', 'voltage', 'amperage', 'max_utilization'))
|
||||||
)
|
)
|
||||||
nullable_fields = ('location', 'description', 'comments')
|
nullable_fields = ('location', 'tenant', 'description', 'comments')
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1174,6 +1174,12 @@ class PowerFeedImportForm(NetBoxModelImportForm):
|
|||||||
required=False,
|
required=False,
|
||||||
help_text=_('Rack')
|
help_text=_('Rack')
|
||||||
)
|
)
|
||||||
|
tenant = CSVModelChoiceField(
|
||||||
|
queryset=Tenant.objects.all(),
|
||||||
|
to_field_name='name',
|
||||||
|
required=False,
|
||||||
|
help_text=_('Assigned tenant')
|
||||||
|
)
|
||||||
status = CSVChoiceField(
|
status = CSVChoiceField(
|
||||||
choices=PowerFeedStatusChoices,
|
choices=PowerFeedStatusChoices,
|
||||||
help_text=_('Operational status')
|
help_text=_('Operational status')
|
||||||
@ -1195,7 +1201,7 @@ class PowerFeedImportForm(NetBoxModelImportForm):
|
|||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
fields = (
|
fields = (
|
||||||
'site', 'power_panel', 'location', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase',
|
'site', 'power_panel', 'location', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase',
|
||||||
'voltage', 'amperage', 'max_utilization', 'description', 'comments', 'tags',
|
'voltage', 'amperage', 'max_utilization', 'tenant', 'description', 'comments', 'tags',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, data=None, *args, **kwargs):
|
def __init__(self, data=None, *args, **kwargs):
|
||||||
|
@ -985,11 +985,12 @@ class PowerPanelFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm):
|
|||||||
tag = TagFilterField(model)
|
tag = TagFilterField(model)
|
||||||
|
|
||||||
|
|
||||||
class PowerFeedFilterForm(NetBoxModelFilterSetForm):
|
class PowerFeedFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(None, ('q', 'filter_id', 'tag')),
|
(None, ('q', 'filter_id', 'tag')),
|
||||||
('Location', ('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id')),
|
('Location', ('region_id', 'site_group_id', 'site_id', 'power_panel_id', 'rack_id')),
|
||||||
|
('Tenant', ('tenant_group_id', 'tenant_id')),
|
||||||
('Attributes', ('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization')),
|
('Attributes', ('status', 'type', 'supply', 'phase', 'voltage', 'amperage', 'max_utilization')),
|
||||||
)
|
)
|
||||||
region_id = DynamicModelMultipleChoiceField(
|
region_id = DynamicModelMultipleChoiceField(
|
||||||
|
@ -611,7 +611,7 @@ class PowerPanelForm(NetBoxModelForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class PowerFeedForm(NetBoxModelForm):
|
class PowerFeedForm(TenancyForm, NetBoxModelForm):
|
||||||
power_panel = DynamicModelChoiceField(
|
power_panel = DynamicModelChoiceField(
|
||||||
queryset=PowerPanel.objects.all(),
|
queryset=PowerPanel.objects.all(),
|
||||||
selector=True
|
selector=True
|
||||||
@ -626,13 +626,14 @@ class PowerFeedForm(NetBoxModelForm):
|
|||||||
fieldsets = (
|
fieldsets = (
|
||||||
('Power Feed', ('power_panel', 'rack', 'name', 'status', 'type', 'description', 'mark_connected', 'tags')),
|
('Power Feed', ('power_panel', 'rack', 'name', 'status', 'type', 'description', 'mark_connected', 'tags')),
|
||||||
('Characteristics', ('supply', 'voltage', 'amperage', 'phase', 'max_utilization')),
|
('Characteristics', ('supply', 'voltage', 'amperage', 'phase', 'max_utilization')),
|
||||||
|
('Tenancy', ('tenant_group', 'tenant')),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
fields = [
|
fields = [
|
||||||
'power_panel', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
|
'power_panel', 'rack', 'name', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
|
||||||
'max_utilization', 'description', 'comments', 'tags',
|
'max_utilization', 'tenant_group', 'tenant', 'description', 'comments', 'tags'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
20
netbox/dcim/migrations/0180_powerfeed_tenant.py
Normal file
20
netbox/dcim/migrations/0180_powerfeed_tenant.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 4.1.8 on 2023-07-29 11:29
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('tenancy', '0010_tenant_relax_uniqueness'),
|
||||||
|
('dcim', '0179_interfacetemplate_rf_role'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='powerfeed',
|
||||||
|
name='tenant',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='power_feeds', to='tenancy.tenant'),
|
||||||
|
),
|
||||||
|
]
|
@ -131,10 +131,17 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
|
|||||||
default=0,
|
default=0,
|
||||||
editable=False
|
editable=False
|
||||||
)
|
)
|
||||||
|
tenant = models.ForeignKey(
|
||||||
|
to='tenancy.Tenant',
|
||||||
|
on_delete=models.PROTECT,
|
||||||
|
related_name='power_feeds',
|
||||||
|
blank=True,
|
||||||
|
null=True
|
||||||
|
)
|
||||||
|
|
||||||
clone_fields = (
|
clone_fields = (
|
||||||
'power_panel', 'rack', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
|
'power_panel', 'rack', 'status', 'type', 'mark_connected', 'supply', 'phase', 'voltage', 'amperage',
|
||||||
'max_utilization',
|
'max_utilization', 'tenant',
|
||||||
)
|
)
|
||||||
prerequisite_models = (
|
prerequisite_models = (
|
||||||
'dcim.PowerPanel',
|
'dcim.PowerPanel',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from dcim.models import PowerFeed, PowerPanel
|
from dcim.models import PowerFeed, PowerPanel
|
||||||
from tenancy.tables import ContactsColumnMixin
|
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
|
||||||
|
|
||||||
from netbox.tables import NetBoxTable, columns
|
from netbox.tables import NetBoxTable, columns
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ class PowerPanelTable(ContactsColumnMixin, NetBoxTable):
|
|||||||
|
|
||||||
# We're not using PathEndpointTable for PowerFeed because power connections
|
# We're not using PathEndpointTable for PowerFeed because power connections
|
||||||
# cannot traverse pass-through ports.
|
# cannot traverse pass-through ports.
|
||||||
class PowerFeedTable(CableTerminationTable):
|
class PowerFeedTable(TenancyColumnsMixin, CableTerminationTable):
|
||||||
name = tables.Column(
|
name = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
@ -69,6 +69,9 @@ class PowerFeedTable(CableTerminationTable):
|
|||||||
available_power = tables.Column(
|
available_power = tables.Column(
|
||||||
verbose_name='Available power (VA)'
|
verbose_name='Available power (VA)'
|
||||||
)
|
)
|
||||||
|
tenant = tables.Column(
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
comments = columns.MarkdownColumn()
|
comments = columns.MarkdownColumn()
|
||||||
tags = columns.TagColumn(
|
tags = columns.TagColumn(
|
||||||
url_name='dcim:powerfeed_list'
|
url_name='dcim:powerfeed_list'
|
||||||
@ -78,8 +81,8 @@ class PowerFeedTable(CableTerminationTable):
|
|||||||
model = PowerFeed
|
model = PowerFeed
|
||||||
fields = (
|
fields = (
|
||||||
'pk', 'id', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
|
'pk', 'id', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase',
|
||||||
'max_utilization', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'available_power',
|
'max_utilization', 'mark_connected', 'cable', 'cable_color', 'link_peer', 'available_power', 'tenant',
|
||||||
'description', 'comments', 'tags', 'created', 'last_updated',
|
'tenant_group', 'description', 'comments', 'tags', 'created', 'last_updated',
|
||||||
)
|
)
|
||||||
default_columns = (
|
default_columns = (
|
||||||
'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable',
|
'pk', 'name', 'power_panel', 'rack', 'status', 'type', 'supply', 'voltage', 'amperage', 'phase', 'cable',
|
||||||
|
@ -4419,6 +4419,21 @@ class PowerFeedTestCase(TestCase, ChangeLoggedFilterSetTests):
|
|||||||
)
|
)
|
||||||
Rack.objects.bulk_create(racks)
|
Rack.objects.bulk_create(racks)
|
||||||
|
|
||||||
|
tenant_groups = (
|
||||||
|
TenantGroup(name='Tenant group 1', slug='tenant-group-1'),
|
||||||
|
TenantGroup(name='Tenant group 2', slug='tenant-group-2'),
|
||||||
|
TenantGroup(name='Tenant group 3', slug='tenant-group-3'),
|
||||||
|
)
|
||||||
|
for tenantgroup in tenant_groups:
|
||||||
|
tenantgroup.save()
|
||||||
|
|
||||||
|
tenants = (
|
||||||
|
Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]),
|
||||||
|
Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]),
|
||||||
|
Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]),
|
||||||
|
)
|
||||||
|
Tenant.objects.bulk_create(tenants)
|
||||||
|
|
||||||
power_panels = (
|
power_panels = (
|
||||||
PowerPanel(name='Power Panel 1', site=sites[0]),
|
PowerPanel(name='Power Panel 1', site=sites[0]),
|
||||||
PowerPanel(name='Power Panel 2', site=sites[1]),
|
PowerPanel(name='Power Panel 2', site=sites[1]),
|
||||||
@ -4427,9 +4442,44 @@ class PowerFeedTestCase(TestCase, ChangeLoggedFilterSetTests):
|
|||||||
PowerPanel.objects.bulk_create(power_panels)
|
PowerPanel.objects.bulk_create(power_panels)
|
||||||
|
|
||||||
power_feeds = (
|
power_feeds = (
|
||||||
PowerFeed(power_panel=power_panels[0], rack=racks[0], name='Power Feed 1', status=PowerFeedStatusChoices.STATUS_ACTIVE, type=PowerFeedTypeChoices.TYPE_PRIMARY, supply=PowerFeedSupplyChoices.SUPPLY_AC, phase=PowerFeedPhaseChoices.PHASE_3PHASE, voltage=100, amperage=100, max_utilization=10),
|
PowerFeed(
|
||||||
PowerFeed(power_panel=power_panels[1], rack=racks[1], name='Power Feed 2', status=PowerFeedStatusChoices.STATUS_FAILED, type=PowerFeedTypeChoices.TYPE_PRIMARY, supply=PowerFeedSupplyChoices.SUPPLY_AC, phase=PowerFeedPhaseChoices.PHASE_3PHASE, voltage=200, amperage=200, max_utilization=20),
|
power_panel=power_panels[0],
|
||||||
PowerFeed(power_panel=power_panels[2], rack=racks[2], name='Power Feed 3', status=PowerFeedStatusChoices.STATUS_OFFLINE, type=PowerFeedTypeChoices.TYPE_REDUNDANT, supply=PowerFeedSupplyChoices.SUPPLY_DC, phase=PowerFeedPhaseChoices.PHASE_SINGLE, voltage=300, amperage=300, max_utilization=30),
|
rack=racks[0],
|
||||||
|
name='Power Feed 1',
|
||||||
|
tenant=tenants[0],
|
||||||
|
status=PowerFeedStatusChoices.STATUS_ACTIVE,
|
||||||
|
type=PowerFeedTypeChoices.TYPE_PRIMARY,
|
||||||
|
supply=PowerFeedSupplyChoices.SUPPLY_AC,
|
||||||
|
phase=PowerFeedPhaseChoices.PHASE_3PHASE,
|
||||||
|
voltage=100,
|
||||||
|
amperage=100,
|
||||||
|
max_utilization=10
|
||||||
|
),
|
||||||
|
PowerFeed(
|
||||||
|
power_panel=power_panels[1],
|
||||||
|
rack=racks[1],
|
||||||
|
name='Power Feed 2',
|
||||||
|
tenant=tenants[1],
|
||||||
|
status=PowerFeedStatusChoices.STATUS_FAILED,
|
||||||
|
type=PowerFeedTypeChoices.TYPE_PRIMARY,
|
||||||
|
supply=PowerFeedSupplyChoices.SUPPLY_AC,
|
||||||
|
phase=PowerFeedPhaseChoices.PHASE_3PHASE,
|
||||||
|
voltage=200,
|
||||||
|
amperage=200,
|
||||||
|
max_utilization=20),
|
||||||
|
PowerFeed(
|
||||||
|
power_panel=power_panels[2],
|
||||||
|
rack=racks[2],
|
||||||
|
name='Power Feed 3',
|
||||||
|
tenant=tenants[2],
|
||||||
|
status=PowerFeedStatusChoices.STATUS_OFFLINE,
|
||||||
|
type=PowerFeedTypeChoices.TYPE_REDUNDANT,
|
||||||
|
supply=PowerFeedSupplyChoices.SUPPLY_DC,
|
||||||
|
phase=PowerFeedPhaseChoices.PHASE_SINGLE,
|
||||||
|
voltage=300,
|
||||||
|
amperage=300,
|
||||||
|
max_utilization=30
|
||||||
|
),
|
||||||
)
|
)
|
||||||
PowerFeed.objects.bulk_create(power_feeds)
|
PowerFeed.objects.bulk_create(power_feeds)
|
||||||
|
|
||||||
@ -4520,6 +4570,20 @@ class PowerFeedTestCase(TestCase, ChangeLoggedFilterSetTests):
|
|||||||
params = {'connected': False}
|
params = {'connected': False}
|
||||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
|
||||||
|
|
||||||
|
def test_tenant(self):
|
||||||
|
tenants = Tenant.objects.all()[:2]
|
||||||
|
params = {'tenant_id': [tenants[0].pk, tenants[1].pk]}
|
||||||
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
params = {'tenant': [tenants[0].slug, tenants[1].slug]}
|
||||||
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
|
||||||
|
def test_tenant_group(self):
|
||||||
|
tenant_groups = TenantGroup.objects.all()[:2]
|
||||||
|
params = {'tenant_group_id': [tenant_groups[0].pk, tenant_groups[1].pk]}
|
||||||
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
params = {'tenant_group': [tenant_groups[0].slug, tenant_groups[1].slug]}
|
||||||
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||||
|
|
||||||
|
|
||||||
class VirtualDeviceContextTestCase(TestCase, ChangeLoggedFilterSetTests):
|
class VirtualDeviceContextTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||||
queryset = VirtualDeviceContext.objects.all()
|
queryset = VirtualDeviceContext.objects.all()
|
||||||
|
@ -43,6 +43,15 @@
|
|||||||
<th scope="row">{% trans "Description" %}</th>
|
<th scope="row">{% trans "Description" %}</th>
|
||||||
<td>{{ object.description|placeholder }}</td>
|
<td>{{ object.description|placeholder }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">{% trans "Tenant" %}</th>
|
||||||
|
<td>
|
||||||
|
{% if object.tenant.group %}
|
||||||
|
{{ object.tenant.group|linkify }} /
|
||||||
|
{% endif %}
|
||||||
|
{{ object.tenant|linkify|placeholder }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="row">{% trans "Connected Device" %}</th>
|
<th scope="row">{% trans "Connected Device" %}</th>
|
||||||
<td>
|
<td>
|
||||||
|
@ -3,7 +3,7 @@ from django.shortcuts import get_object_or_404
|
|||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from circuits.models import Circuit
|
from circuits.models import Circuit
|
||||||
from dcim.models import Cable, Device, Location, Rack, RackReservation, Site, VirtualDeviceContext
|
from dcim.models import Cable, Device, Location, PowerFeed, Rack, RackReservation, Site, VirtualDeviceContext
|
||||||
from ipam.models import Aggregate, ASN, IPAddress, IPRange, L2VPN, Prefix, VLAN, VRF
|
from ipam.models import Aggregate, ASN, IPAddress, IPRange, L2VPN, Prefix, VLAN, VRF
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from utilities.utils import count_related
|
from utilities.utils import count_related
|
||||||
@ -145,6 +145,7 @@ class TenantView(generic.ObjectView):
|
|||||||
(Device.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
(Device.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
(VirtualDeviceContext.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
(VirtualDeviceContext.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
(Cable.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
(Cable.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
|
(PowerFeed.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
# IPAM
|
# IPAM
|
||||||
(VRF.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
(VRF.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
(Aggregate.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
(Aggregate.objects.restrict(request.user, 'view').filter(tenant=instance), 'tenant_id'),
|
||||||
|
Loading…
Reference in New Issue
Block a user