test: Replace override_settings with explicit permission grants

Remove `@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])` decorators
across test suites, replacing them with explicit `add_permissions()`
calls for required view permissions. Improves test clarity and ensures
permission checks are properly validated.

Fixes #22091
This commit is contained in:
Martin Hauser 2026-05-18 16:24:10 +02:00 committed by Jeremy Stretch
parent 90b74aaa1a
commit 9ec1633dac
9 changed files with 199 additions and 103 deletions

View File

@ -1,7 +1,6 @@
import datetime
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.urls import reverse
from circuits.choices import *
@ -210,8 +209,13 @@ class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase):
self.assertContains(response, circuit_type.name)
self.assertContains(response, 'background-color: #12ab34')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_bulk_import_objects_with_terminations(self):
self.add_permissions(
'circuits.view_circuit',
'circuits.view_provider',
'circuits.view_circuittype',
'dcim.view_site',
)
site = Site.objects.first()
json_data = f"""
[
@ -420,8 +424,13 @@ class CircuitTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'circuits.view_circuittermination',
'dcim.view_cable',
'dcim.view_interface',
'dcim.view_device',
)
device = create_test_device('Device 1')
circuittermination = CircuitTermination.objects.first()
@ -711,8 +720,13 @@ class VirtualCircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_bulk_import_objects_with_terminations(self):
self.add_permissions(
'circuits.view_virtualcircuit',
'circuits.view_providernetwork',
'circuits.view_virtualcircuittype',
'dcim.view_interface',
)
interfaces = Interface.objects.filter(type=InterfaceTypeChoices.TYPE_VIRTUAL)
json_data = f"""
[

View File

@ -1,7 +1,7 @@
import json
from django.conf import settings
from django.test import override_settings, tag
from django.test import tag
from django.urls import reverse
from django.utils.translation import gettext as _
from rest_framework import status
@ -3525,8 +3525,8 @@ class ConnectedDeviceTestCase(APITestCase):
cable = Cable(a_terminations=[interfaces[0]], b_terminations=[interfaces[1]])
cable.save()
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_get_connected_device(self):
self.add_permissions('dcim.view_device', 'dcim.view_interface')
url = reverse('dcim-api:connected-device-list')
url_params = '?peer_device=TestDevice1&peer_interface=eth0'

View File

@ -622,11 +622,11 @@ class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_list_rack_elevations(self):
"""
Test viewing the list of rack elevations.
"""
self.add_permissions('dcim.view_rack')
response = self.client.get(reverse('dcim:rack_elevation_list'))
self.assertHttpStatus(response, 200)
@ -730,8 +730,8 @@ class DeviceTypeTestCase(
'is_full_depth': False,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_consoleports(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_consoleporttemplate')
devicetype = DeviceType.objects.first()
console_ports = (
ConsolePortTemplate(device_type=devicetype, name='Console Port 1'),
@ -743,8 +743,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_consoleports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_consoleserverports(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_consoleserverporttemplate')
devicetype = DeviceType.objects.first()
console_server_ports = (
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 1'),
@ -756,8 +756,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_consoleserverports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_powerports(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_powerporttemplate')
devicetype = DeviceType.objects.first()
power_ports = (
PowerPortTemplate(device_type=devicetype, name='Power Port 1'),
@ -769,8 +769,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_powerports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_poweroutlets(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_poweroutlettemplate')
devicetype = DeviceType.objects.first()
power_outlets = (
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 1'),
@ -782,8 +782,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_poweroutlets', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_interfaces(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_interfacetemplate')
devicetype = DeviceType.objects.first()
interfaces = (
InterfaceTemplate(device_type=devicetype, name='Interface 1'),
@ -795,8 +795,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_interfaces', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_rearports(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_rearporttemplate')
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
@ -808,8 +808,12 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_rearports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_frontports(self):
self.add_permissions(
'dcim.view_devicetype',
'dcim.view_frontporttemplate',
'dcim.view_rearporttemplate',
)
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
@ -832,8 +836,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_frontports', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_modulebays(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_modulebaytemplate')
devicetype = DeviceType.objects.first()
module_bays = (
ModuleBayTemplate(device_type=devicetype, name='Module Bay 1'),
@ -845,8 +849,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_modulebays', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_devicebays(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_devicebaytemplate')
devicetype = DeviceType.objects.first()
device_bays = (
DeviceBayTemplate(device_type=devicetype, name='Device Bay 1'),
@ -858,8 +862,8 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_devicebays', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_inventoryitems(self):
self.add_permissions('dcim.view_devicetype', 'dcim.view_inventoryitemtemplate')
devicetype = DeviceType.objects.first()
inventory_items = (
DeviceBayTemplate(device_type=devicetype, name='Device Bay 1'),
@ -872,11 +876,11 @@ class DeviceTypeTestCase(
url = reverse('dcim:devicetype_inventoryitems', kwargs={'pk': devicetype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_objects(self):
"""
Custom import test for YAML-based imports (versus CSV)
"""
self.add_permissions('dcim.view_manufacturer', 'dcim.view_platform')
IMPORT_DATA = """
manufacturer: Generic
model: TEST-1000
@ -1070,12 +1074,12 @@ inventory-items:
ii1 = InventoryItemTemplate.objects.first()
self.assertEqual(ii1.name, 'Inventory Item 1')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_error_numbering(self):
# Add all required permissions to the test user
self.add_permissions(
'dcim.view_devicetype',
'dcim.add_devicetype',
'dcim.view_manufacturer',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
@ -1122,12 +1126,12 @@ module-bays:
self.assertHttpStatus(response, 200)
self.assertContains(response, "Record 2 module-bays[3].name: This field is required.")
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_nolist(self):
# Add all required permissions to the test user
self.add_permissions(
'dcim.view_devicetype',
'dcim.add_devicetype',
'dcim.view_manufacturer',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
@ -1158,12 +1162,12 @@ console-ports: {value}
self.assertHttpStatus(response, 200)
self.assertContains(response, "Record 1 console-ports: Must be a list.")
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_nodict(self):
# Add all required permissions to the test user
self.add_permissions(
'dcim.view_devicetype',
'dcim.add_devicetype',
'dcim.view_manufacturer',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
@ -1264,7 +1268,6 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
f"{module_types[0].id},test model",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_update_objects_with_permission(self):
self.add_permissions(
'dcim.add_consoleporttemplate',
@ -1281,7 +1284,6 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
super().test_bulk_update_objects_with_permission()
@tag('regression')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_bulk_import_objects_with_permission(self):
self.add_permissions(
'dcim.add_consoleporttemplate',
@ -1303,7 +1305,6 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
# run base test
super().test_bulk_import_objects_with_permission(post_import_callback=verify_module_type_profile)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_bulk_import_objects_with_constrained_permission(self):
self.add_permissions(
'dcim.add_consoleporttemplate',
@ -1318,8 +1319,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
super().test_bulk_import_objects_with_constrained_permission()
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_consoleports(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_consoleporttemplate')
moduletype = ModuleType.objects.first()
console_ports = (
ConsolePortTemplate(module_type=moduletype, name='Console Port 1'),
@ -1331,8 +1332,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_consoleports', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_consoleserverports(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_consoleserverporttemplate')
moduletype = ModuleType.objects.first()
console_server_ports = (
ConsoleServerPortTemplate(module_type=moduletype, name='Console Server Port 1'),
@ -1344,8 +1345,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_consoleserverports', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_powerports(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_powerporttemplate')
moduletype = ModuleType.objects.first()
power_ports = (
PowerPortTemplate(module_type=moduletype, name='Power Port 1'),
@ -1357,8 +1358,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_powerports', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_poweroutlets(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_poweroutlettemplate')
moduletype = ModuleType.objects.first()
power_outlets = (
PowerOutletTemplate(module_type=moduletype, name='Power Outlet 1'),
@ -1370,8 +1371,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_poweroutlets', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_interfaces(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_interfacetemplate')
moduletype = ModuleType.objects.first()
interfaces = (
InterfaceTemplate(module_type=moduletype, name='Interface 1'),
@ -1383,8 +1384,8 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_interfaces', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_rearports(self):
self.add_permissions('dcim.view_moduletype', 'dcim.view_rearporttemplate')
moduletype = ModuleType.objects.first()
rear_ports = (
RearPortTemplate(module_type=moduletype, name='Rear Port 1'),
@ -1396,8 +1397,12 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_rearports', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_frontports(self):
self.add_permissions(
'dcim.view_moduletype',
'dcim.view_frontporttemplate',
'dcim.view_rearporttemplate',
)
moduletype = ModuleType.objects.first()
rear_ports = (
RearPortTemplate(module_type=moduletype, name='Rear Port 1'),
@ -1420,11 +1425,11 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:moduletype_frontports', kwargs={'pk': moduletype.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_import_objects(self):
"""
Custom import test for YAML-based imports (versus CSV)
"""
self.add_permissions('dcim.view_manufacturer')
IMPORT_DATA = """
manufacturer: Generic
model: TEST-1000
@ -2289,8 +2294,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'status': DeviceStatusChoices.STATUS_DECOMMISSIONING,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_consoleports(self):
self.add_permissions('dcim.view_device', 'dcim.view_consoleport')
device = Device.objects.first()
console_ports = (
ConsolePort(device=device, name='Console Port 1'),
@ -2302,8 +2307,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_consoleports', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_consoleserverports(self):
self.add_permissions('dcim.view_device', 'dcim.view_consoleserverport')
device = Device.objects.first()
console_server_ports = (
ConsoleServerPort(device=device, name='Console Server Port 1'),
@ -2315,8 +2320,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_consoleserverports', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_powerports(self):
self.add_permissions('dcim.view_device', 'dcim.view_powerport')
device = Device.objects.first()
power_ports = (
PowerPort(device=device, name='Power Port 1'),
@ -2328,8 +2333,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_powerports', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_poweroutlets(self):
self.add_permissions('dcim.view_device', 'dcim.view_poweroutlet')
device = Device.objects.first()
power_outlets = (
PowerOutlet(device=device, name='Power Outlet 1'),
@ -2341,8 +2346,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_poweroutlets', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_interfaces(self):
self.add_permissions('dcim.view_device', 'dcim.view_interface')
device = Device.objects.first()
interfaces = (
Interface(device=device, name='Interface 1'),
@ -2354,8 +2359,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_interfaces', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_rearports(self):
self.add_permissions('dcim.view_device', 'dcim.view_rearport')
device = Device.objects.first()
rear_ports = (
RearPort(device=device, name='Rear Port 1'),
@ -2367,8 +2372,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_rearports', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_frontports(self):
self.add_permissions('dcim.view_device', 'dcim.view_frontport', 'dcim.view_rearport')
device = Device.objects.first()
rear_ports = (
RearPort(device=device, name='Rear Port 1'),
@ -2391,8 +2396,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_frontports', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_modulebays(self):
self.add_permissions('dcim.view_device', 'dcim.view_modulebay')
device = Device.objects.first()
ModuleBay.objects.create(device=device, name='Module Bay 1')
ModuleBay.objects.create(device=device, name='Module Bay 2')
@ -2401,8 +2406,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_modulebays', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_devicebays(self):
self.add_permissions('dcim.view_device', 'dcim.view_devicebay')
device = Device.objects.first()
device_bays = (
DeviceBay(device=device, name='Device Bay 1'),
@ -2414,8 +2419,8 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('dcim:device_devicebays', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_inventory(self):
self.add_permissions('dcim.view_device', 'dcim.view_inventoryitem')
device = Device.objects.first()
inventory_items = (
InventoryItem(device=device, name='Inventory Item 1'),
@ -2504,7 +2509,6 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
self.assertContains(response, 'background-color: #aa00bb')
self.assertNotContains(response, 'background-color: #111111')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_import_duplicate_ids_error_message(self):
device = Device.objects.first()
csv_data = (
@ -2513,7 +2517,12 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
f"{device.pk},Device Role 2",
)
self.add_permissions('dcim.add_device', 'dcim.change_device')
self.add_permissions(
'dcim.view_device',
'dcim.add_device',
'dcim.change_device',
'dcim.view_devicerole',
)
response = self.client.post(
self._get_url('bulk_import'),
{
@ -2615,15 +2624,26 @@ class ModuleTestCase(
f"{modules[2].pk},offline,Serial 1",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_detail_includes_module_type_profile(self):
self.add_permissions(
'dcim.view_module',
'dcim.view_moduletype',
'dcim.view_moduletypeprofile',
)
response = self.client.get(self._get_queryset().first().get_absolute_url())
self.assertContains(response, 'Module Type Profile 1')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_component_replication(self):
self.add_permissions('dcim.add_module')
self.add_permissions(
'dcim.view_module',
'dcim.add_module',
'dcim.view_moduletype',
'dcim.view_device',
'dcim.view_modulebay',
'dcim.view_interface',
'extras.view_tag',
)
# Add 5 InterfaceTemplates to a ModuleType
module_type = ModuleType.objects.first()
@ -2654,9 +2674,15 @@ class ModuleTestCase(
self.assertHttpStatus(self.client.post(**request), 302)
self.assertEqual(Interface.objects.filter(device=device).count(), 5)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_bulk_replication(self):
self.add_permissions('dcim.add_module')
self.add_permissions(
'dcim.view_module',
'dcim.add_module',
'dcim.view_moduletype',
'dcim.view_device',
'dcim.view_modulebay',
'dcim.view_interface',
)
# Add 5 InterfaceTemplates to a ModuleType
module_type = ModuleType.objects.first()
@ -2704,9 +2730,17 @@ class ModuleTestCase(
self.assertEqual(Module.objects.count(), initial_count + len(csv_data) - 1)
self.assertEqual(Interface.objects.filter(device=device).count(), 5)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_component_adoption(self):
self.add_permissions('dcim.add_module')
self.add_permissions(
'dcim.view_module',
'dcim.add_module',
'dcim.view_moduletype',
'dcim.view_device',
'dcim.view_modulebay',
'dcim.view_interface',
'dcim.change_interface',
'extras.view_tag',
)
interface_name = "Interface-1"
@ -2741,9 +2775,16 @@ class ModuleTestCase(
# Check that the Interface now has a module
self.assertIsNotNone(interface.module)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_bulk_adoption(self):
self.add_permissions('dcim.add_module')
self.add_permissions(
'dcim.view_module',
'dcim.add_module',
'dcim.view_moduletype',
'dcim.view_device',
'dcim.view_modulebay',
'dcim.view_interface',
'dcim.change_interface',
)
interface_name = "Interface-1"
@ -2841,8 +2882,8 @@ class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{console_ports[2].pk},Console Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_bulk_add_components_with_changelog_message(self):
self.add_permissions('dcim.view_consoleport', 'dcim.view_device')
device1 = Device.objects.get(name='Device 1')
device2 = create_test_device('Device 2')
changelog_message = 'Bulk-created console ports'
@ -2885,8 +2926,13 @@ class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
for objectchange in objectchanges:
self.assertEqual(objectchange.message, changelog_message)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_consoleport',
'dcim.view_consoleserverport',
'dcim.view_cable',
'dcim.view_device',
)
consoleport = ConsolePort.objects.first()
consoleserverport = ConsoleServerPort.objects.create(
device=consoleport.device,
@ -2950,8 +2996,13 @@ class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{console_server_ports[2].pk},Console Server Port 9,New description 9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_consoleserverport',
'dcim.view_consoleport',
'dcim.view_cable',
'dcim.view_device',
)
consoleserverport = ConsoleServerPort.objects.first()
consoleport = ConsolePort.objects.create(
device=consoleserverport.device,
@ -3021,8 +3072,13 @@ class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{power_ports[2].pk},Power Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_powerport',
'dcim.view_poweroutlet',
'dcim.view_cable',
'dcim.view_device',
)
powerport = PowerPort.objects.first()
poweroutlet = PowerOutlet.objects.create(
device=powerport.device,
@ -3101,8 +3157,13 @@ class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{power_outlets[2].pk},Power Outlet 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_poweroutlet',
'dcim.view_powerport',
'dcim.view_cable',
'dcim.view_device',
)
poweroutlet = PowerOutlet.objects.first()
powerport = PowerPort.objects.first()
Cable(a_terminations=[poweroutlet], b_terminations=[powerport]).save()
@ -3240,8 +3301,12 @@ class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{interfaces[2].pk},Interface 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_interface',
'dcim.view_cable',
'dcim.view_device',
)
interface1, interface2 = Interface.objects.all()[:2]
Cable(a_terminations=[interface1], b_terminations=[interface2]).save()
@ -3387,8 +3452,14 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{front_ports[2].pk},Front Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_frontport',
'dcim.view_rearport',
'dcim.view_interface',
'dcim.view_cable',
'dcim.view_device',
)
frontport = FrontPort.objects.first()
interface = Interface.objects.create(
device=frontport.device,
@ -3454,8 +3525,14 @@ class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
f"{rear_ports[2].pk},Rear Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_rearport',
'dcim.view_frontport',
'dcim.view_interface',
'dcim.view_cable',
'dcim.view_device',
)
rearport = RearPort.objects.first()
interface = Interface.objects.create(
device=rearport.device,
@ -4108,8 +4185,13 @@ class PowerFeedTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
self.add_permissions(
'dcim.view_powerfeed',
'dcim.view_powerport',
'dcim.view_cable',
'dcim.view_device',
)
manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
device_type = DeviceType.objects.create(
manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
@ -4255,12 +4337,12 @@ class MACAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
}
@tag('regression') # Issue #20542
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_create_macaddress_via_quickadd(self):
"""
Test creating a MAC address via quick-add modal (e.g., from Interface form).
Regression test for issue #20542 where form prefix was missing in POST handler.
"""
self.add_permissions('dcim.view_macaddress', 'dcim.view_interface', 'extras.view_tag')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)

View File

@ -1,7 +1,6 @@
import datetime
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.urls import reverse
from netaddr import IPNetwork
@ -339,8 +338,8 @@ class AggregateTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_aggregate_prefixes(self):
self.add_permissions('ipam.view_aggregate', 'ipam.view_prefix')
rir = RIR.objects.first()
aggregate = Aggregate.objects.create(prefix=IPNetwork('192.168.0.0/16'), rir=rir)
prefixes = (
@ -476,9 +475,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_add_ipv4_prefixes(self):
"""Test bulk creating IPv4 prefixes using a pattern."""
self.add_permissions('ipam.view_prefix')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)
@ -497,9 +496,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
for i in range(3):
self.assertTrue(Prefix.objects.filter(prefix=IPNetwork(f'10.0.{i}.0/24')).exists())
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_add_ipv6_prefixes(self):
"""Test bulk creating IPv6 prefixes using a pattern."""
self.add_permissions('ipam.view_prefix')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)
@ -518,9 +517,9 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
for i in range(4):
self.assertTrue(Prefix.objects.filter(prefix=IPNetwork(f'fd00:db8:{i}::/48')).exists())
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_add_ipv6_prefixes_uppercase_hex(self):
"""Test bulk creating IPv6 prefixes using uppercase hex in the pattern."""
self.add_permissions('ipam.view_prefix')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)
@ -544,8 +543,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
f'Expected prefix {prefix_str} was not created'
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_add_prefixes_with_changelog_message(self):
self.add_permissions('ipam.view_prefix')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)
@ -575,8 +574,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
for objectchange in objectchanges:
self.assertEqual(objectchange.message, changelog_message)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_prefixes(self):
self.add_permissions('ipam.view_prefix')
prefixes = (
Prefix(prefix=IPNetwork('192.168.0.0/16')),
Prefix(prefix=IPNetwork('192.168.1.0/24')),
@ -589,8 +588,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('ipam:prefix_prefixes', kwargs={'pk': prefixes[0].pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_ipranges(self):
self.add_permissions('ipam.view_prefix', 'ipam.view_iprange')
prefix = Prefix.objects.create(prefix=IPNetwork('192.168.0.0/16'))
ip_ranges = (
IPRange(start_address='192.168.0.1/24', end_address='192.168.0.100/24', size=99),
@ -603,8 +602,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('ipam:prefix_ipranges', kwargs={'pk': prefix.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_ipaddresses(self):
self.add_permissions('ipam.view_prefix', 'ipam.view_ipaddress', 'ipam.view_iprange')
prefix = Prefix.objects.create(prefix=IPNetwork('192.168.0.0/16'))
ip_addresses = (
IPAddress(address=IPNetwork('192.168.0.1/16')),
@ -617,8 +616,8 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
url = reverse('ipam:prefix_ipaddresses', kwargs={'pk': prefix.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_ipaddresses_with_single_address_range(self):
self.add_permissions('ipam.view_prefix', 'ipam.view_ipaddress', 'ipam.view_iprange')
# The IP Addresses tab annotates child IP addresses alongside any
# mark-populated child IP ranges. Make sure a single-address range
# (start_address == end_address) renders without errors and is shown
@ -639,11 +638,11 @@ class PrefixTestCase(ViewTestCases.PrimaryObjectViewTestCase):
# IPAddress row in this mixed-record view).
self.assertContains(response, '192.168.0.50-192.168.0.50/16')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import(self):
"""
Custom import test for YAML-based imports (versus CSV)
"""
self.add_permissions('dcim.view_site', 'ipam.view_vlan')
site = Site.objects.get(name='Site 1')
IMPORT_DATA = f"""
prefix: 10.1.1.0/24
@ -670,11 +669,11 @@ scope_id: {site.pk}
self.assertEqual(prefix.vlan.vid, 101)
self.assertEqual(prefix.scope, site)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_scope_name(self):
"""
Test YAML-based import using scope_name instead of scope_id.
"""
self.add_permissions('dcim.view_site')
site = Site.objects.get(name='Site 1')
IMPORT_DATA = """
prefix: 10.1.3.0/24
@ -696,11 +695,11 @@ scope_name: Site 1
self.assertEqual(prefix.status, PrefixStatusChoices.STATUS_ACTIVE)
self.assertEqual(prefix.scope, site)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_vlan_group(self):
"""
This test covers a unique import edge case where VLAN group is specified during the import.
"""
self.add_permissions('dcim.view_site', 'ipam.view_vlan', 'ipam.view_vlangroup')
site = Site.objects.get(name='Site 1')
IMPORT_DATA = f"""
prefix: 10.1.2.0/24
@ -728,12 +727,12 @@ vlan: 102
self.assertEqual(prefix.vlan.vid, 102)
self.assertEqual(prefix.scope, site)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_vlan_site_multiple_vlans_same_vid(self):
"""
Test import when multiple VLANs exist with the same vid but different sites.
Ref: #20560
"""
self.add_permissions('dcim.view_site', 'ipam.view_vlan')
site1 = Site.objects.get(name='Site 1')
site2 = Site.objects.get(name='Site 2')
@ -766,13 +765,13 @@ description: LOC02-MGMT
prefix = Prefix.objects.get(prefix='10.11.0.0/22')
self.assertEqual(prefix.vlan, vlan1)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_prefix_import_with_vlan_site_and_global_vlan(self):
"""
Test import when a global VLAN (no site) and site-specific VLAN exist with same vid.
When vlan_site is specified, should prefer the site-specific VLAN.
Ref: #20560
"""
self.add_permissions('dcim.view_site', 'ipam.view_vlan')
site1 = Site.objects.get(name='Site 1')
# Create a global VLAN (no site) and a site-specific VLAN with the same vid
@ -871,8 +870,8 @@ class IPRangeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_iprange_ipaddresses(self):
self.add_permissions('ipam.view_iprange', 'ipam.view_ipaddress')
iprange = IPRange.objects.create(
start_address=IPNetwork('192.168.0.1/24'),
end_address=IPNetwork('192.168.0.100/24'),
@ -986,8 +985,8 @@ class IPAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_add_ipaddresses_with_changelog_message(self):
self.add_permissions('ipam.view_ipaddress', 'ipam.view_vrf')
obj_perm = ObjectPermission(name='Test permission', actions=['add'])
obj_perm.save()
obj_perm.users.add(self.user)
@ -1425,8 +1424,8 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'description': 'New description',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_unassigned_ip_addresses(self):
self.add_permissions('ipam.view_service', 'dcim.view_device', 'ipam.view_ipaddress')
device = Device.objects.first()
addr = IPAddress.objects.create(address='192.0.2.4/24')
csv_data = (
@ -1455,8 +1454,8 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
self.assertIn(addr.address, form_errors['__all__'][0])
self.assertEqual(self._get_queryset().count(), initial_count)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_alternate_csv_import(self):
self.add_permissions('ipam.view_service', 'dcim.view_device', 'ipam.view_ipaddress')
device = Device.objects.first()
interface = device.interfaces.first()
addr = IPAddress.objects.create(assigned_object=interface, address='192.0.2.3/24')
@ -1485,9 +1484,13 @@ class ServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
self.assertHttpStatus(response, 302)
self.assertEqual(self._get_queryset().count(), initial_count + len(csv_data) - 1)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_create_from_template(self):
self.add_permissions('ipam.add_service')
self.add_permissions(
'ipam.view_service',
'ipam.add_service',
'dcim.view_device',
'ipam.view_servicetemplate',
)
device = Device.objects.first()
service_template = ServiceTemplate.objects.create(

View File

@ -1,5 +1,3 @@
from django.test import override_settings
from core.models import ObjectType
from dcim.models import *
from extras.models import CustomField
@ -48,8 +46,8 @@ class CSVImportTestCase(ModelViewTestCase):
self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 302)
self.assertEqual(Region.objects.count(), 3)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_valid_tags(self):
self.add_permissions('dcim.view_region', 'extras.view_tag')
csv_data = (
'name,slug,tags',
'Region 1,region-1,"alpha,bravo"',
@ -91,8 +89,8 @@ class CSVImportTestCase(ModelViewTestCase):
)
self.assertEqual(regions[3].tags.count(), 0)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_invalid_tags(self):
self.add_permissions('dcim.view_region', 'extras.view_tag')
csv_data = (
'name,slug,tags',
'Region 1,region-1,"Alpha,Bravo"', # Valid
@ -117,9 +115,8 @@ class CSVImportTestCase(ModelViewTestCase):
self.assertHttpStatus(self.client.post(self._get_url('bulk_import'), data), 200)
self.assertEqual(Region.objects.count(), 0)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_custom_field_defaults(self):
self.add_permissions('dcim.add_region')
self.add_permissions('dcim.view_region', 'dcim.add_region')
csv_data = [
'name,slug,description',
'Region 1,region-1,abc',

View File

@ -62,8 +62,8 @@ class SearchViewTestCase(TestCase):
self.assertNotIn('Site Echo', content)
self.assertNotIn('Site Foxtrot', content)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_search_no_results(self):
self.add_permissions('dcim.view_site')
url = reverse('search')
params = {
'q': 'xxxxxxxxx', # Matches nothing

View File

@ -1,4 +1,3 @@
from django.test import override_settings
from django.urls import reverse
from core.models import ObjectType
@ -268,7 +267,6 @@ class TokenOneTimeAuthStringTestCase(TestCase):
"""
user_permissions = ('users.add_token', 'users.view_token', 'users.view_user')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_create_stashes_plaintext_and_detail_view_renders_it_once(self):
target_user = create_test_user('token_owner')
@ -310,7 +308,6 @@ class TokenOneTimeAuthStringTestCase(TestCase):
# Specifically, the banner element must be gone
self.assertNotContains(response, 'id="new-token-auth-string"')
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_form_ignores_user_supplied_token_field(self):
"""
Submitting a 'token' POST parameter should be silently ignored: the model auto-generates plaintext on save.

View File

@ -1,4 +1,3 @@
from django.test import override_settings
from django.urls import reverse
from dcim.models import *
@ -82,7 +81,6 @@ class CountersTestCase(TestCase):
self.assertEqual(device1.interface_count, 1)
self.assertEqual(device2.interface_count, 3)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_mptt_child_delete(self):
device1 = Device.objects.first()
inventory_item1 = InventoryItem.objects.create(device=device1, name='Inventory Item 1')
@ -91,7 +89,7 @@ class CountersTestCase(TestCase):
self.assertEqual(device1.inventory_item_count, 2)
# Setup bulk_delete for the inventory items
self.add_permissions('dcim.delete_inventoryitem')
self.add_permissions('dcim.view_inventoryitem', 'dcim.delete_inventoryitem')
pk_list = device1.inventoryitems.values_list('pk', flat=True)
data = {
'pk': pk_list,

View File

@ -1,7 +1,6 @@
from decimal import Decimal
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.urls import reverse
from dcim.choices import InterfaceModeChoices
@ -189,15 +188,15 @@ class ClusterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_cluster_virtualmachines(self):
self.add_permissions('virtualization.view_cluster', 'virtualization.view_virtualmachine')
cluster = Cluster.objects.first()
url = reverse('virtualization:cluster_virtualmachines', kwargs={'pk': cluster.pk})
self.assertHttpStatus(self.client.get(url), 200)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_cluster_devices(self):
self.add_permissions('virtualization.view_cluster', 'dcim.view_device')
cluster = Cluster.objects.first()
url = reverse('virtualization:cluster_devices', kwargs={'pk': cluster.pk})
@ -423,9 +422,15 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
'start_on_boot': VirtualMachineStartOnBootChoices.STATUS_OFF,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
def test_create_virtualmachine_with_type_defaults(self):
self.add_permissions('virtualization.add_virtualmachine')
self.add_permissions(
'virtualization.view_virtualmachine',
'virtualization.add_virtualmachine',
'virtualization.view_cluster',
'virtualization.view_virtualmachinetype',
'dcim.view_site',
'dcim.view_platform',
)
response = self.client.post(
self._get_url('add'),
@ -449,8 +454,8 @@ class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
self.assertEqual(vm.vcpus, self.vm_types[0].default_vcpus)
self.assertEqual(vm.memory, self.vm_types[0].default_memory)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_virtualmachine_interfaces(self):
self.add_permissions('virtualization.view_virtualmachine', 'virtualization.view_vminterface')
virtualmachine = VirtualMachine.objects.first()
vminterfaces = (
VMInterface(virtual_machine=virtualmachine, name='Interface 1'),