netbox/netbox/dcim/tests/test_views.py
2025-07-10 12:48:28 -04:00

3630 lines
131 KiB
Python

import json
from decimal import Decimal
from zoneinfo import ZoneInfo
import yaml
from django.test import override_settings
from django.urls import reverse
from netaddr import EUI
from dcim.choices import *
from dcim.constants import *
from dcim.models import *
from ipam.models import ASN, RIR, VLAN, VRF
from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, WeightUnitChoices
from tenancy.models import Tenant
from users.models import User
from utilities.testing import ViewTestCases, create_tags, create_test_device, post_data
from wireless.models import WirelessLAN
class RegionTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = Region
@classmethod
def setUpTestData(cls):
# Create three Regions
regions = (
Region(name='Region 1', slug='region-1', comments=''),
Region(
name='Region 2', slug='region-2', comments="It's going to take a lot to drag me away from you"
),
Region(name='Region 3', slug='region-3'),
)
for region in regions:
region.save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Region X',
'slug': 'region-x',
'parent': regions[2].pk,
'description': 'A new region',
'tags': [t.pk for t in tags],
'comments': 'This comment is really exciting!',
}
cls.csv_data = (
"name,slug,description,comments",
"Region 4,region-4,Fourth region,",
"Region 5,region-5,Fifth region,hi guys",
"Region 6,region-6,Sixth region,bye guys",
)
cls.csv_update_data = (
"id,name,description",
f"{regions[0].pk},Region 7,Fourth region7",
f"{regions[1].pk},Region 8,Fifth region8",
f"{regions[2].pk},Region 0,Sixth region9",
)
cls.bulk_edit_data = {
'description': 'New description',
'comments': 'This comment is super exciting!!!',
}
class SiteGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = SiteGroup
@classmethod
def setUpTestData(cls):
# Create three SiteGroups
sitegroups = (
SiteGroup(name='Site Group 1', slug='site-group-1', comments='Still here'),
SiteGroup(name='Site Group 2', slug='site-group-2'),
SiteGroup(name='Site Group 3', slug='site-group-3'),
)
for sitegroup in sitegroups:
sitegroup.save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Site Group X',
'slug': 'site-group-x',
'parent': sitegroups[2].pk,
'description': 'A new site group',
'tags': [t.pk for t in tags],
'comments': 'still here',
}
cls.csv_data = (
"name,slug,description,comments",
"Site Group 4,site-group-4,Fourth site group,",
"Site Group 5,site-group-5,Fifth site group,still hear",
"Site Group 6,site-group-6,Sixth site group,"
)
cls.csv_update_data = (
"id,name,description,comments",
f"{sitegroups[0].pk},Site Group 7,Fourth site group7,",
f"{sitegroups[1].pk},Site Group 8,Fifth site group8,when will it end",
f"{sitegroups[2].pk},Site Group 0,Sixth site group9,",
)
cls.bulk_edit_data = {
'description': 'New description',
'comments': 'the end',
}
class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Site
@classmethod
def setUpTestData(cls):
regions = (
Region(name='Region 1', slug='region-1'),
Region(name='Region 2', slug='region-2'),
)
for region in regions:
region.save()
groups = (
SiteGroup(name='Site Group 1', slug='site-group-1'),
SiteGroup(name='Site Group 2', slug='site-group-2'),
)
for group in groups:
group.save()
rir = RIR.objects.create(name='RFC 6996', is_private=True)
asns = [
ASN(asn=65000 + i, rir=rir) for i in range(8)
]
ASN.objects.bulk_create(asns)
sites = Site.objects.bulk_create([
Site(name='Site 1', slug='site-1', region=regions[0], group=groups[1]),
Site(name='Site 2', slug='site-2', region=regions[0], group=groups[1]),
Site(name='Site 3', slug='site-3', region=regions[0], group=groups[1]),
])
sites[0].asns.set([asns[0], asns[1]])
sites[1].asns.set([asns[2], asns[3]])
sites[2].asns.set([asns[4], asns[5]])
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Site X',
'slug': 'site-x',
'status': SiteStatusChoices.STATUS_PLANNED,
'region': regions[1].pk,
'group': groups[1].pk,
'tenant': None,
'facility': 'Facility X',
'asns': [asns[6].pk, asns[7].pk],
'time_zone': ZoneInfo('UTC'),
'description': 'Site description',
'physical_address': '742 Evergreen Terrace, Springfield, USA',
'shipping_address': '742 Evergreen Terrace, Springfield, USA',
'latitude': Decimal('35.780000'),
'longitude': Decimal('-78.642000'),
'comments': 'Test site',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,status",
"Site 4,site-4,planned",
"Site 5,site-5,active",
"Site 6,site-6,staging",
)
cls.csv_update_data = (
"id,name,status",
f"{sites[0].pk},Site 7,staging",
f"{sites[1].pk},Site 8,planned",
f"{sites[2].pk},Site 9,active",
)
cls.bulk_edit_data = {
'status': SiteStatusChoices.STATUS_PLANNED,
'region': regions[1].pk,
'group': groups[1].pk,
'tenant': None,
'time_zone': ZoneInfo('US/Eastern'),
'description': 'New description',
}
class LocationTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = Location
@classmethod
def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1')
tenant = Tenant.objects.create(name='Tenant 1', slug='tenant-1')
locations = (
Location(
name='Location 1',
slug='location-1',
site=site,
status=LocationStatusChoices.STATUS_ACTIVE,
tenant=tenant,
comments='',
),
Location(
name='Location 2',
slug='location-2',
site=site,
status=LocationStatusChoices.STATUS_ACTIVE,
tenant=tenant,
comments='First comment!',
),
Location(
name='Location 3',
slug='location-3',
site=site,
status=LocationStatusChoices.STATUS_ACTIVE,
tenant=tenant,
comments='_This_ is a **bold comment**',
),
)
for location in locations:
location.save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Location X',
'slug': 'location-x',
'site': site.pk,
'status': LocationStatusChoices.STATUS_PLANNED,
'facility': 'Facility X',
'tenant': tenant.pk,
'description': 'A new location',
'tags': [t.pk for t in tags],
'comments': 'This comment is really boring',
}
cls.csv_data = (
"site,tenant,name,slug,status,description,comments",
"Site 1,Tenant 1,Location 4,location-4,planned,Fourth location,",
"Site 1,Tenant 1,Location 5,location-5,planned,Fifth location,",
"Site 1,Tenant 1,Location 6,location-6,planned,Sixth location,hi!",
)
cls.csv_update_data = (
"id,name,description,comments",
f"{locations[0].pk},Location 7,Fourth location7,Useful comment",
f"{locations[1].pk},Location 8,Fifth location8,unuseful comment",
f"{locations[2].pk},Location 0,Sixth location9,",
)
cls.bulk_edit_data = {
'description': 'New description',
'comments': 'This comment is also really boring',
}
class RackRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = RackRole
@classmethod
def setUpTestData(cls):
rack_roles = (
RackRole(name='Rack Role 1', slug='rack-role-1'),
RackRole(name='Rack Role 2', slug='rack-role-2'),
RackRole(name='Rack Role 3', slug='rack-role-3'),
)
RackRole.objects.bulk_create(rack_roles)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Rack Role X',
'slug': 'rack-role-x',
'color': 'c0c0c0',
'description': 'New role',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,color",
"Rack Role 4,rack-role-4,ff0000",
"Rack Role 5,rack-role-5,00ff00",
"Rack Role 6,rack-role-6,0000ff",
)
cls.csv_update_data = (
"id,name,description",
f"{rack_roles[0].pk},Rack Role 7,New description7",
f"{rack_roles[1].pk},Rack Role 8,New description8",
f"{rack_roles[2].pk},Rack Role 9,New description9",
)
cls.bulk_edit_data = {
'color': '00ff00',
'description': 'New description',
}
class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = RackReservation
@classmethod
def setUpTestData(cls):
user2 = User.objects.create_user(username='testuser2')
user3 = User.objects.create_user(username='testuser3')
site = Site.objects.create(name='Site 1', slug='site-1')
location = Location(name='Location 1', slug='location-1', site=site)
location.save()
rack = Rack(name='Rack 1', site=site, location=location)
rack.save()
rack_reservations = (
RackReservation(rack=rack, user=user2, units=[1, 2, 3], description='Reservation 1'),
RackReservation(rack=rack, user=user2, units=[4, 5, 6], description='Reservation 2'),
RackReservation(rack=rack, user=user2, units=[7, 8, 9], description='Reservation 3'),
)
RackReservation.objects.bulk_create(rack_reservations)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'rack': rack.pk,
'units': "10,11,12",
'user': user3.pk,
'tenant': None,
'description': 'Rack reservation',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
'site,location,rack,units,description',
'Site 1,Location 1,Rack 1,"10,11,12",Reservation 1',
'Site 1,Location 1,Rack 1,"13,14,15",Reservation 2',
'Site 1,Location 1,Rack 1,"16,17,18",Reservation 3',
)
cls.csv_update_data = (
'id,description',
f'{rack_reservations[0].pk},New description1',
f'{rack_reservations[1].pk},New description2',
f'{rack_reservations[2].pk},New description3',
)
cls.bulk_edit_data = {
'user': user3.pk,
'tenant': None,
'description': 'New description',
}
class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = RackType
@classmethod
def setUpTestData(cls):
manufacturers = (
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
)
Manufacturer.objects.bulk_create(manufacturers)
rack_types = (
RackType(
manufacturer=manufacturers[0],
model='RackType 1',
slug='rack-type-1',
form_factor=RackFormFactorChoices.TYPE_CABINET,
),
RackType(
manufacturer=manufacturers[0],
model='RackType 2',
slug='rack-type-2',
form_factor=RackFormFactorChoices.TYPE_CABINET,
),
RackType(
manufacturer=manufacturers[0],
model='RackType 3',
slug='rack-type-3',
form_factor=RackFormFactorChoices.TYPE_CABINET,
),
)
RackType.objects.bulk_create(rack_types)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'manufacturer': manufacturers[1].pk,
'model': 'RackType X',
'slug': 'rack-type-x',
'type': RackFormFactorChoices.TYPE_CABINET,
'width': RackWidthChoices.WIDTH_19IN,
'u_height': 48,
'desc_units': False,
'outer_width': 500,
'outer_depth': 500,
'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER,
'starting_unit': 1,
'weight': 100,
'max_weight': 2000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'form_factor': RackFormFactorChoices.TYPE_CABINET,
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"manufacturer,model,slug,width,u_height,weight,max_weight,weight_unit",
"Manufacturer 1,RackType 4,rack-type-4,19,42,100,2000,kg",
"Manufacturer 1,RackType 5,rack-type-5,19,42,100,2000,kg",
"Manufacturer 1,RackType 6,rack-type-6,19,42,100,2000,kg",
)
cls.csv_update_data = (
"id,model",
f"{rack_types[0].pk},RackType 7",
f"{rack_types[1].pk},RackType 8",
f"{rack_types[2].pk},RackType 9",
)
cls.bulk_edit_data = {
'manufacturer': manufacturers[1].pk,
'type': RackFormFactorChoices.TYPE_4POST,
'width': RackWidthChoices.WIDTH_23IN,
'u_height': 49,
'desc_units': True,
'outer_width': 30,
'outer_depth': 30,
'outer_unit': RackDimensionUnitChoices.UNIT_INCH,
'weight': 200,
'max_weight': 4000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'comments': 'New comments',
}
class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Rack
@classmethod
def setUpTestData(cls):
sites = (
Site(name='Site 1', slug='site-1'),
Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
locations = (
Location(name='Location 1', slug='location-1', site=sites[0]),
Location(name='Location 2', slug='location-2', site=sites[1])
)
for location in locations:
location.save()
rackroles = (
RackRole(name='Rack Role 1', slug='rack-role-1'),
RackRole(name='Rack Role 2', slug='rack-role-2'),
)
RackRole.objects.bulk_create(rackroles)
racks = (
Rack(name='Rack 1', site=sites[0]),
Rack(name='Rack 2', site=sites[0]),
Rack(name='Rack 3', site=sites[0]),
)
Rack.objects.bulk_create(racks)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Rack X',
'facility_id': 'Facility X',
'site': sites[1].pk,
'location': locations[1].pk,
'tenant': None,
'status': RackStatusChoices.STATUS_PLANNED,
'role': rackroles[1].pk,
'serial': '123456',
'asset_tag': 'ABCDEF',
'form_factor': RackFormFactorChoices.TYPE_CABINET,
'width': RackWidthChoices.WIDTH_19IN,
'u_height': 48,
'desc_units': False,
'outer_width': 500,
'outer_depth': 500,
'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER,
'starting_unit': 1,
'weight': 100,
'max_weight': 2000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"site,location,name,status,width,u_height,weight,max_weight,weight_unit",
"Site 1,,Rack 4,active,19,42,100,2000,kg",
"Site 1,Location 1,Rack 5,active,19,42,100,2000,kg",
"Site 2,Location 2,Rack 6,active,19,42,100,2000,kg",
)
cls.csv_update_data = (
"id,name,status",
f"{racks[0].pk},Rack 7,{RackStatusChoices.STATUS_DEPRECATED}",
f"{racks[1].pk},Rack 8,{RackStatusChoices.STATUS_DEPRECATED}",
f"{racks[2].pk},Rack 9,{RackStatusChoices.STATUS_DEPRECATED}",
)
cls.bulk_edit_data = {
'site': sites[1].pk,
'location': locations[1].pk,
'tenant': None,
'status': RackStatusChoices.STATUS_DEPRECATED,
'role': rackroles[1].pk,
'serial': '654321',
'form_factor': RackFormFactorChoices.TYPE_4POST,
'width': RackWidthChoices.WIDTH_23IN,
'u_height': 49,
'desc_units': True,
'outer_width': 30,
'outer_depth': 30,
'outer_unit': RackDimensionUnitChoices.UNIT_INCH,
'weight': 200,
'max_weight': 4000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_list_rack_elevations(self):
"""
Test viewing the list of rack elevations.
"""
response = self.client.get(reverse('dcim:rack_elevation_list'))
self.assertHttpStatus(response, 200)
class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = Manufacturer
@classmethod
def setUpTestData(cls):
manufacturers = (
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
)
Manufacturer.objects.bulk_create(manufacturers)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Manufacturer X',
'slug': 'manufacturer-x',
'description': 'A new manufacturer',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,description",
"Manufacturer 4,manufacturer-4,Fourth manufacturer",
"Manufacturer 5,manufacturer-5,Fifth manufacturer",
"Manufacturer 6,manufacturer-6,Sixth manufacturer",
)
cls.csv_update_data = (
"id,name,description",
f"{manufacturers[0].pk},Manufacturer 7,Fourth manufacturer7",
f"{manufacturers[1].pk},Manufacturer 8,Fifth manufacturer8",
f"{manufacturers[2].pk},Manufacturer 9,Sixth manufacturer9",
)
cls.bulk_edit_data = {
'description': 'New description',
}
# TODO: Change base class to PrimaryObjectViewTestCase
# Blocked by absence of bulk import view for DeviceTypes
class DeviceTypeTestCase(
ViewTestCases.GetObjectViewTestCase,
ViewTestCases.GetObjectChangelogViewTestCase,
ViewTestCases.CreateObjectViewTestCase,
ViewTestCases.EditObjectViewTestCase,
ViewTestCases.DeleteObjectViewTestCase,
ViewTestCases.ListObjectsViewTestCase,
ViewTestCases.BulkEditObjectsViewTestCase,
ViewTestCases.BulkDeleteObjectsViewTestCase
):
model = DeviceType
@classmethod
def setUpTestData(cls):
manufacturers = (
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2')
)
Manufacturer.objects.bulk_create(manufacturers)
platforms = (
Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturers[0]),
Platform(name='Platform 2', slug='platform-3', manufacturer=manufacturers[1]),
)
Platform.objects.bulk_create(platforms)
DeviceType.objects.bulk_create([
DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturers[0]),
DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturers[0]),
DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturers[0]),
])
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'manufacturer': manufacturers[1].pk,
'default_platform': platforms[0].pk,
'model': 'Device Type X',
'slug': 'device-type-x',
'part_number': '123ABC',
'u_height': 2,
'is_full_depth': True,
'subdevice_role': None,
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'manufacturer': manufacturers[1].pk,
'default_platform': platforms[1].pk,
'u_height': 3,
'is_full_depth': False,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_devicetype_consoleports(self):
devicetype = DeviceType.objects.first()
console_ports = (
ConsolePortTemplate(device_type=devicetype, name='Console Port 1'),
ConsolePortTemplate(device_type=devicetype, name='Console Port 2'),
ConsolePortTemplate(device_type=devicetype, name='Console Port 3'),
)
ConsolePortTemplate.objects.bulk_create(console_ports)
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):
devicetype = DeviceType.objects.first()
console_server_ports = (
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 1'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 2'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port 3'),
)
ConsoleServerPortTemplate.objects.bulk_create(console_server_ports)
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):
devicetype = DeviceType.objects.first()
power_ports = (
PowerPortTemplate(device_type=devicetype, name='Power Port 1'),
PowerPortTemplate(device_type=devicetype, name='Power Port 2'),
PowerPortTemplate(device_type=devicetype, name='Power Port 3'),
)
PowerPortTemplate.objects.bulk_create(power_ports)
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):
devicetype = DeviceType.objects.first()
power_outlets = (
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 1'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 2'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet 3'),
)
PowerOutletTemplate.objects.bulk_create(power_outlets)
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):
devicetype = DeviceType.objects.first()
interfaces = (
InterfaceTemplate(device_type=devicetype, name='Interface 1'),
InterfaceTemplate(device_type=devicetype, name='Interface 2'),
InterfaceTemplate(device_type=devicetype, name='Interface 3'),
)
InterfaceTemplate.objects.bulk_create(interfaces)
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):
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
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):
devicetype = DeviceType.objects.first()
rear_ports = (
RearPortTemplate(device_type=devicetype, name='Rear Port 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
front_ports = (
FrontPortTemplate(
device_type=devicetype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1
),
FrontPortTemplate(
device_type=devicetype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1
),
FrontPortTemplate(
device_type=devicetype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1
),
)
FrontPortTemplate.objects.bulk_create(front_ports)
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):
devicetype = DeviceType.objects.first()
module_bays = (
ModuleBayTemplate(device_type=devicetype, name='Module Bay 1'),
ModuleBayTemplate(device_type=devicetype, name='Module Bay 2'),
ModuleBayTemplate(device_type=devicetype, name='Module Bay 3'),
)
ModuleBayTemplate.objects.bulk_create(module_bays)
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):
devicetype = DeviceType.objects.first()
device_bays = (
DeviceBayTemplate(device_type=devicetype, name='Device Bay 1'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 2'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 3'),
)
DeviceBayTemplate.objects.bulk_create(device_bays)
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):
devicetype = DeviceType.objects.first()
inventory_items = (
DeviceBayTemplate(device_type=devicetype, name='Device Bay 1'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 2'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay 3'),
)
for inventory_item in inventory_items:
inventory_item.save()
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)
"""
IMPORT_DATA = """
manufacturer: Generic
model: TEST-1000
slug: test-1000
default_platform: Platform
u_height: 2
is_full_depth: false
airflow: front-to-rear
subdevice_role: parent
weight: 10
weight_unit: kg
comments: Test comment
console-ports:
- name: Console Port 1
type: de-9
- name: Console Port 2
type: de-9
- name: Console Port 3
type: de-9
console-server-ports:
- name: Console Server Port 1
type: rj-45
- name: Console Server Port 2
type: rj-45
- name: Console Server Port 3
type: rj-45
power-ports:
- name: Power Port 1
type: iec-60320-c14
- name: Power Port 2
type: iec-60320-c14
- name: Power Port 3
type: iec-60320-c14
power-outlets:
- name: Power Outlet 1
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
- name: Power Outlet 2
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
- name: Power Outlet 3
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
interfaces:
- name: Interface 1
type: 1000base-t
mgmt_only: true
- name: Interface 2
type: 1000base-t
enabled: false
- name: Interface 3
type: 1000base-t
rear-ports:
- name: Rear Port 1
type: 8p8c
- name: Rear Port 2
type: 8p8c
- name: Rear Port 3
type: 8p8c
front-ports:
- name: Front Port 1
type: 8p8c
rear_port: Rear Port 1
- name: Front Port 2
type: 8p8c
rear_port: Rear Port 2
- name: Front Port 3
type: 8p8c
rear_port: Rear Port 3
module-bays:
- name: Module Bay 1
- name: Module Bay 2
- name: Module Bay 3
device-bays:
- name: Device Bay 1
- name: Device Bay 2
- name: Device Bay 3
inventory-items:
- name: Inventory Item 1
manufacturer: Generic
- name: Inventory Item 2
manufacturer: Generic
- name: Inventory Item 3
manufacturer: Generic
"""
# Create the manufacturer and platform
manufacturer = Manufacturer(name='Generic', slug='generic')
manufacturer.save()
platform = Platform(name='Platform', slug='test-platform', manufacturer=manufacturer)
platform.save()
# Add all required permissions to the test user
self.add_permissions(
'dcim.view_devicetype',
'dcim.add_devicetype',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
'dcim.add_poweroutlettemplate',
'dcim.add_interfacetemplate',
'dcim.add_frontporttemplate',
'dcim.add_rearporttemplate',
'dcim.add_modulebaytemplate',
'dcim.add_devicebaytemplate',
'dcim.add_inventoryitemtemplate',
)
form_data = {
'data': IMPORT_DATA,
'format': 'yaml'
}
response = self.client.post(reverse('dcim:devicetype_bulk_import'), data=form_data, follow=True)
self.assertHttpStatus(response, 200)
device_type = DeviceType.objects.get(model='TEST-1000')
self.assertEqual(device_type.manufacturer.pk, manufacturer.pk)
self.assertEqual(device_type.default_platform.pk, platform.pk)
self.assertEqual(device_type.slug, 'test-1000')
self.assertEqual(device_type.u_height, 2)
self.assertFalse(device_type.is_full_depth)
self.assertEqual(device_type.airflow, DeviceAirflowChoices.AIRFLOW_FRONT_TO_REAR)
self.assertEqual(device_type.subdevice_role, SubdeviceRoleChoices.ROLE_PARENT)
self.assertEqual(device_type.weight, 10)
self.assertEqual(device_type.weight_unit, WeightUnitChoices.UNIT_KILOGRAM)
self.assertEqual(device_type.comments, 'Test comment')
# Verify all of the components were created
self.assertEqual(device_type.consoleporttemplates.count(), 3)
cp1 = ConsolePortTemplate.objects.first()
self.assertEqual(cp1.name, 'Console Port 1')
self.assertEqual(cp1.type, ConsolePortTypeChoices.TYPE_DE9)
self.assertEqual(device_type.consoleserverporttemplates.count(), 3)
csp1 = ConsoleServerPortTemplate.objects.first()
self.assertEqual(csp1.name, 'Console Server Port 1')
self.assertEqual(csp1.type, ConsolePortTypeChoices.TYPE_RJ45)
self.assertEqual(device_type.powerporttemplates.count(), 3)
pp1 = PowerPortTemplate.objects.first()
self.assertEqual(pp1.name, 'Power Port 1')
self.assertEqual(pp1.type, PowerPortTypeChoices.TYPE_IEC_C14)
self.assertEqual(device_type.poweroutlettemplates.count(), 3)
po1 = PowerOutletTemplate.objects.first()
self.assertEqual(po1.name, 'Power Outlet 1')
self.assertEqual(po1.type, PowerOutletTypeChoices.TYPE_IEC_C13)
self.assertEqual(po1.power_port, pp1)
self.assertEqual(po1.feed_leg, PowerOutletFeedLegChoices.FEED_LEG_A)
self.assertEqual(device_type.interfacetemplates.count(), 3)
iface1 = InterfaceTemplate.objects.first()
self.assertEqual(iface1.name, 'Interface 1')
self.assertEqual(iface1.type, InterfaceTypeChoices.TYPE_1GE_FIXED)
self.assertTrue(iface1.mgmt_only)
self.assertTrue(iface1.enabled)
iface2 = InterfaceTemplate.objects.filter(name="Interface 2").first()
self.assertFalse(iface2.enabled)
self.assertEqual(device_type.rearporttemplates.count(), 3)
rp1 = RearPortTemplate.objects.first()
self.assertEqual(rp1.name, 'Rear Port 1')
self.assertEqual(device_type.frontporttemplates.count(), 3)
fp1 = FrontPortTemplate.objects.first()
self.assertEqual(fp1.name, 'Front Port 1')
self.assertEqual(fp1.rear_port, rp1)
self.assertEqual(fp1.rear_port_position, 1)
self.assertEqual(device_type.modulebaytemplates.count(), 3)
mb1 = ModuleBayTemplate.objects.first()
self.assertEqual(mb1.name, 'Module Bay 1')
self.assertEqual(device_type.devicebaytemplates.count(), 3)
db1 = DeviceBayTemplate.objects.first()
self.assertEqual(db1.name, 'Device Bay 1')
self.assertEqual(device_type.inventoryitemtemplates.count(), 3)
ii1 = InventoryItemTemplate.objects.first()
self.assertEqual(ii1.name, 'Inventory Item 1')
def test_export_objects(self):
url = reverse('dcim:devicetype_list')
self.add_permissions('dcim.view_devicetype')
# Test default YAML export
response = self.client.get(f'{url}?export')
self.assertEqual(response.status_code, 200)
data = list(yaml.load_all(response.content, Loader=yaml.SafeLoader))
self.assertEqual(len(data), 3)
self.assertEqual(data[0]['manufacturer'], 'Manufacturer 1')
self.assertEqual(data[0]['model'], 'Device Type 1')
# Test table-based export
response = self.client.get(f'{url}?export=table')
self.assertHttpStatus(response, 200)
self.assertEqual(response.get('Content-Type'), 'text/csv; charset=utf-8')
# TODO: Change base class to PrimaryObjectViewTestCase
# Blocked by absence of bulk import view for ModuleTypes
class ModuleTypeTestCase(
ViewTestCases.GetObjectViewTestCase,
ViewTestCases.GetObjectChangelogViewTestCase,
ViewTestCases.CreateObjectViewTestCase,
ViewTestCases.EditObjectViewTestCase,
ViewTestCases.DeleteObjectViewTestCase,
ViewTestCases.ListObjectsViewTestCase,
ViewTestCases.BulkEditObjectsViewTestCase,
ViewTestCases.BulkDeleteObjectsViewTestCase
):
model = ModuleType
@classmethod
def setUpTestData(cls):
manufacturers = (
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2')
)
Manufacturer.objects.bulk_create(manufacturers)
ModuleType.objects.bulk_create([
ModuleType(model='Module Type 1', manufacturer=manufacturers[0]),
ModuleType(model='Module Type 2', manufacturer=manufacturers[0]),
ModuleType(model='Module Type 3', manufacturer=manufacturers[0]),
])
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'manufacturer': manufacturers[1].pk,
'model': 'Device Type X',
'part_number': '123ABC',
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'manufacturer': manufacturers[1].pk,
'part_number': '456DEF',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_moduletype_consoleports(self):
moduletype = ModuleType.objects.first()
console_ports = (
ConsolePortTemplate(module_type=moduletype, name='Console Port 1'),
ConsolePortTemplate(module_type=moduletype, name='Console Port 2'),
ConsolePortTemplate(module_type=moduletype, name='Console Port 3'),
)
ConsolePortTemplate.objects.bulk_create(console_ports)
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):
moduletype = ModuleType.objects.first()
console_server_ports = (
ConsoleServerPortTemplate(module_type=moduletype, name='Console Server Port 1'),
ConsoleServerPortTemplate(module_type=moduletype, name='Console Server Port 2'),
ConsoleServerPortTemplate(module_type=moduletype, name='Console Server Port 3'),
)
ConsoleServerPortTemplate.objects.bulk_create(console_server_ports)
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):
moduletype = ModuleType.objects.first()
power_ports = (
PowerPortTemplate(module_type=moduletype, name='Power Port 1'),
PowerPortTemplate(module_type=moduletype, name='Power Port 2'),
PowerPortTemplate(module_type=moduletype, name='Power Port 3'),
)
PowerPortTemplate.objects.bulk_create(power_ports)
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):
moduletype = ModuleType.objects.first()
power_outlets = (
PowerOutletTemplate(module_type=moduletype, name='Power Outlet 1'),
PowerOutletTemplate(module_type=moduletype, name='Power Outlet 2'),
PowerOutletTemplate(module_type=moduletype, name='Power Outlet 3'),
)
PowerOutletTemplate.objects.bulk_create(power_outlets)
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):
moduletype = ModuleType.objects.first()
interfaces = (
InterfaceTemplate(module_type=moduletype, name='Interface 1'),
InterfaceTemplate(module_type=moduletype, name='Interface 2'),
InterfaceTemplate(module_type=moduletype, name='Interface 3'),
)
InterfaceTemplate.objects.bulk_create(interfaces)
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):
moduletype = ModuleType.objects.first()
rear_ports = (
RearPortTemplate(module_type=moduletype, name='Rear Port 1'),
RearPortTemplate(module_type=moduletype, name='Rear Port 2'),
RearPortTemplate(module_type=moduletype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
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):
moduletype = ModuleType.objects.first()
rear_ports = (
RearPortTemplate(module_type=moduletype, name='Rear Port 1'),
RearPortTemplate(module_type=moduletype, name='Rear Port 2'),
RearPortTemplate(module_type=moduletype, name='Rear Port 3'),
)
RearPortTemplate.objects.bulk_create(rear_ports)
front_ports = (
FrontPortTemplate(
module_type=moduletype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1
),
FrontPortTemplate(
module_type=moduletype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1
),
FrontPortTemplate(
module_type=moduletype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1
),
)
FrontPortTemplate.objects.bulk_create(front_ports)
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)
"""
IMPORT_DATA = """
manufacturer: Generic
model: TEST-1000
weight: 10
weight_unit: lb
comments: Test comment
console-ports:
- name: Console Port 1
type: de-9
- name: Console Port 2
type: de-9
- name: Console Port 3
type: de-9
console-server-ports:
- name: Console Server Port 1
type: rj-45
- name: Console Server Port 2
type: rj-45
- name: Console Server Port 3
type: rj-45
power-ports:
- name: Power Port 1
type: iec-60320-c14
- name: Power Port 2
type: iec-60320-c14
- name: Power Port 3
type: iec-60320-c14
power-outlets:
- name: Power Outlet 1
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
- name: Power Outlet 2
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
- name: Power Outlet 3
type: iec-60320-c13
power_port: Power Port 1
feed_leg: A
interfaces:
- name: Interface 1
type: 1000base-t
mgmt_only: true
- name: Interface 2
type: 1000base-t
- name: Interface 3
type: 1000base-t
rear-ports:
- name: Rear Port 1
type: 8p8c
- name: Rear Port 2
type: 8p8c
- name: Rear Port 3
type: 8p8c
front-ports:
- name: Front Port 1
type: 8p8c
rear_port: Rear Port 1
- name: Front Port 2
type: 8p8c
rear_port: Rear Port 2
- name: Front Port 3
type: 8p8c
rear_port: Rear Port 3
module-bays:
- name: Module Bay 1
position: 1
- name: Module Bay 2
position: 2
- name: Module Bay 3
position: 3
"""
# Create the manufacturer
manufacturer = Manufacturer(name='Generic', slug='generic')
manufacturer.save()
# Add all required permissions to the test user
self.add_permissions(
'dcim.view_moduletype',
'dcim.add_moduletype',
'dcim.add_consoleporttemplate',
'dcim.add_consoleserverporttemplate',
'dcim.add_powerporttemplate',
'dcim.add_poweroutlettemplate',
'dcim.add_interfacetemplate',
'dcim.add_frontporttemplate',
'dcim.add_rearporttemplate',
'dcim.add_modulebaytemplate',
)
form_data = {
'data': IMPORT_DATA,
'format': 'yaml'
}
response = self.client.post(reverse('dcim:moduletype_bulk_import'), data=form_data, follow=True)
self.assertHttpStatus(response, 200)
module_type = ModuleType.objects.get(model='TEST-1000')
self.assertEqual(module_type.manufacturer.pk, manufacturer.pk)
self.assertEqual(module_type.weight, 10)
self.assertEqual(module_type.weight_unit, WeightUnitChoices.UNIT_POUND)
self.assertEqual(module_type.comments, 'Test comment')
# Verify all the components were created
self.assertEqual(module_type.consoleporttemplates.count(), 3)
cp1 = ConsolePortTemplate.objects.first()
self.assertEqual(cp1.name, 'Console Port 1')
self.assertEqual(cp1.type, ConsolePortTypeChoices.TYPE_DE9)
self.assertEqual(module_type.consoleserverporttemplates.count(), 3)
csp1 = ConsoleServerPortTemplate.objects.first()
self.assertEqual(csp1.name, 'Console Server Port 1')
self.assertEqual(csp1.type, ConsolePortTypeChoices.TYPE_RJ45)
self.assertEqual(module_type.powerporttemplates.count(), 3)
pp1 = PowerPortTemplate.objects.first()
self.assertEqual(pp1.name, 'Power Port 1')
self.assertEqual(pp1.type, PowerPortTypeChoices.TYPE_IEC_C14)
self.assertEqual(module_type.poweroutlettemplates.count(), 3)
po1 = PowerOutletTemplate.objects.first()
self.assertEqual(po1.name, 'Power Outlet 1')
self.assertEqual(po1.type, PowerOutletTypeChoices.TYPE_IEC_C13)
self.assertEqual(po1.power_port, pp1)
self.assertEqual(po1.feed_leg, PowerOutletFeedLegChoices.FEED_LEG_A)
self.assertEqual(module_type.interfacetemplates.count(), 3)
iface1 = InterfaceTemplate.objects.first()
self.assertEqual(iface1.name, 'Interface 1')
self.assertEqual(iface1.type, InterfaceTypeChoices.TYPE_1GE_FIXED)
self.assertTrue(iface1.mgmt_only)
self.assertEqual(module_type.rearporttemplates.count(), 3)
rp1 = RearPortTemplate.objects.first()
self.assertEqual(rp1.name, 'Rear Port 1')
self.assertEqual(module_type.frontporttemplates.count(), 3)
fp1 = FrontPortTemplate.objects.first()
self.assertEqual(fp1.name, 'Front Port 1')
self.assertEqual(fp1.rear_port, rp1)
self.assertEqual(fp1.rear_port_position, 1)
self.assertEqual(module_type.modulebaytemplates.count(), 3)
mb1 = ModuleBayTemplate.objects.first()
self.assertEqual(mb1.name, 'Module Bay 1')
self.assertEqual(mb1.position, '1')
def test_export_objects(self):
url = reverse('dcim:moduletype_list')
self.add_permissions('dcim.view_moduletype')
# Test default YAML export
response = self.client.get(f'{url}?export')
self.assertEqual(response.status_code, 200)
data = list(yaml.load_all(response.content, Loader=yaml.SafeLoader))
self.assertEqual(len(data), 3)
self.assertEqual(data[0]['manufacturer'], 'Manufacturer 1')
self.assertEqual(data[0]['model'], 'Module Type 1')
# Test table-based export
response = self.client.get(f'{url}?export=table')
self.assertHttpStatus(response, 200)
self.assertEqual(response.get('Content-Type'), 'text/csv; charset=utf-8')
class ModuleTypeProfileTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = ModuleTypeProfile
SCHEMAS = [
{
"properties": {
"foo": {
"type": "string"
}
}
},
{
"properties": {
"foo": {
"type": "integer"
}
}
},
{
"properties": {
"foo": {
"type": "boolean"
}
}
},
]
@classmethod
def setUpTestData(cls):
module_type_profiles = (
ModuleTypeProfile(
name='Module Type Profile 1',
schema=cls.SCHEMAS[0]
),
ModuleTypeProfile(
name='Module Type Profile 2',
schema=cls.SCHEMAS[1]
),
ModuleTypeProfile(
name='Module Type Profile 3',
schema=cls.SCHEMAS[2]
),
)
ModuleTypeProfile.objects.bulk_create(module_type_profiles)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Module Type Profile X',
'description': 'A new profile',
'schema': json.dumps(cls.SCHEMAS[0]),
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,schema",
f"Module Type Profile 4,{json.dumps(cls.SCHEMAS[0])}",
f"Module Type Profile 5,{json.dumps(cls.SCHEMAS[1])}",
f"Module Type Profile 6,{json.dumps(cls.SCHEMAS[2])}",
)
cls.csv_update_data = (
"id,description",
f"{module_type_profiles[0].pk},New description",
f"{module_type_profiles[1].pk},New description",
f"{module_type_profiles[2].pk},New description",
)
cls.bulk_edit_data = {
'description': 'New description',
}
#
# DeviceType components
#
class ConsolePortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = ConsolePortTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
ConsolePortTemplate.objects.bulk_create((
ConsolePortTemplate(device_type=devicetype, name='Console Port Template 1'),
ConsolePortTemplate(device_type=devicetype, name='Console Port Template 2'),
ConsolePortTemplate(device_type=devicetype, name='Console Port Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Console Port Template X',
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Console Port Template [4-6]',
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
cls.bulk_edit_data = {
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
class ConsoleServerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = ConsoleServerPortTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
ConsoleServerPortTemplate.objects.bulk_create((
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 1'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 2'),
ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Console Server Port Template X',
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Console Server Port Template [4-6]',
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
cls.bulk_edit_data = {
'type': ConsolePortTypeChoices.TYPE_RJ45,
}
class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = PowerPortTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
PowerPortTemplate.objects.bulk_create((
PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'),
PowerPortTemplate(device_type=devicetype, name='Power Port Template 2'),
PowerPortTemplate(device_type=devicetype, name='Power Port Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Power Port Template X',
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Power Port Template [4-6]',
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
}
cls.bulk_edit_data = {
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
}
class PowerOutletTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = PowerOutletTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
PowerOutletTemplate.objects.bulk_create((
PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'),
PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'),
))
powerports = (
PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'),
)
PowerPortTemplate.objects.bulk_create(powerports)
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Power Outlet Template X',
'type': PowerOutletTypeChoices.TYPE_IEC_C13,
'power_port': powerports[0].pk,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Power Outlet Template [4-6]',
'type': PowerOutletTypeChoices.TYPE_IEC_C13,
'power_port': powerports[0].pk,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
}
cls.bulk_edit_data = {
'type': PowerOutletTypeChoices.TYPE_IEC_C13,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
}
class InterfaceTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = InterfaceTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
InterfaceTemplate.objects.bulk_create((
InterfaceTemplate(device_type=devicetype, name='Interface Template 1'),
InterfaceTemplate(device_type=devicetype, name='Interface Template 2'),
InterfaceTemplate(device_type=devicetype, name='Interface Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Interface Template X',
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
'mgmt_only': True,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Interface Template [4-6]',
# Test that a label can be applied to each generated interface templates
'label': 'Interface Template Label [3-5]',
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
'mgmt_only': True,
}
cls.bulk_edit_data = {
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
'mgmt_only': True,
}
class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = FrontPortTemplate
validation_excluded_fields = ('name', 'label', 'rear_port')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
rearports = (
RearPortTemplate(device_type=devicetype, name='Rear Port Template 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 3'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 4'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 5'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 6'),
)
RearPortTemplate.objects.bulk_create(rearports)
FrontPortTemplate.objects.bulk_create(
(
FrontPortTemplate(
device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1
),
FrontPortTemplate(
device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1
),
FrontPortTemplate(
device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1
),
)
)
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Front Port X',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': rearports[3].pk,
'rear_port_position': 1,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Front Port [4-6]',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': [f'{rp.pk}:1' for rp in rearports[3:6]],
}
cls.bulk_edit_data = {
'type': PortTypeChoices.TYPE_8P8C,
}
class RearPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = RearPortTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
RearPortTemplate.objects.bulk_create((
RearPortTemplate(device_type=devicetype, name='Rear Port Template 1'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 2'),
RearPortTemplate(device_type=devicetype, name='Rear Port Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Rear Port Template X',
'type': PortTypeChoices.TYPE_8P8C,
'positions': 2,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Rear Port Template [4-6]',
'type': PortTypeChoices.TYPE_8P8C,
'positions': 2,
}
cls.bulk_edit_data = {
'type': PortTypeChoices.TYPE_8P8C,
}
class ModuleBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = ModuleBayTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
ModuleBayTemplate.objects.bulk_create((
ModuleBayTemplate(device_type=devicetype, name='Module Bay Template 1'),
ModuleBayTemplate(device_type=devicetype, name='Module Bay Template 2'),
ModuleBayTemplate(device_type=devicetype, name='Module Bay Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Module Bay Template X',
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Module Bay Template [4-6]',
}
cls.bulk_edit_data = {
'description': 'Foo bar',
}
class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = DeviceBayTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(
manufacturer=manufacturer,
model='Device Type 1',
slug='device-type-1',
subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
)
DeviceBayTemplate.objects.bulk_create((
DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 1'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 2'),
DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 3'),
))
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Device Bay Template X',
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Device Bay Template [4-6]',
}
cls.bulk_edit_data = {
'description': 'Foo bar',
}
class InventoryItemTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
model = InventoryItemTemplate
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
manufacturers = (
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
)
Manufacturer.objects.bulk_create(manufacturers)
devicetype = DeviceType.objects.create(
manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1'
)
inventory_item_templates = (
InventoryItemTemplate(
device_type=devicetype, name='Inventory Item Template 1', manufacturer=manufacturers[0]
),
InventoryItemTemplate(
device_type=devicetype, name='Inventory Item Template 2', manufacturer=manufacturers[0]
),
InventoryItemTemplate(
device_type=devicetype, name='Inventory Item Template 3', manufacturer=manufacturers[0]
),
)
for item in inventory_item_templates:
item.save()
cls.form_data = {
'device_type': devicetype.pk,
'name': 'Inventory Item Template X',
'manufacturer': manufacturers[1].pk,
}
cls.bulk_create_data = {
'device_type': devicetype.pk,
'name': 'Inventory Item Template [4-6]',
'manufacturer': manufacturers[1].pk,
}
cls.bulk_edit_data = {
'description': 'Foo bar',
}
class DeviceRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = DeviceRole
@classmethod
def setUpTestData(cls):
roles = [
DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'),
DeviceRole(name='Device Role 3', slug='device-role-3'),
DeviceRole(name='Device Role 4', slug='device-role-4'),
]
for role in roles:
role.save()
roles.append(DeviceRole.objects.create(name='Device Role 5', slug='device-role-5', parent=roles[3]))
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Device Role X',
'slug': 'device-role-x',
'color': 'c0c0c0',
'vm_role': False,
'description': 'New device role',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,color",
"Device Role 6,device-role-6,ff0000",
"Device Role 7,device-role-7,00ff00",
"Device Role 8,device-role-8,0000ff",
)
cls.csv_update_data = (
"id,name,description",
f"{roles[0].pk},Device Role 7,New description7",
f"{roles[1].pk},Device Role 8,New description8",
f"{roles[2].pk},Device Role 9,New description9",
f"{roles[4].pk},Device Role 10,New description10",
)
cls.bulk_edit_data = {
'color': '00ff00',
'description': 'New description',
}
class PlatformTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = Platform
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
platforms = (
Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturer),
Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturer),
Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturer),
)
Platform.objects.bulk_create(platforms)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Platform X',
'slug': 'platform-x',
'manufacturer': manufacturer.pk,
'description': 'A new platform',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,description",
"Platform 4,platform-4,Fourth platform",
"Platform 5,platform-5,Fifth platform",
"Platform 6,platform-6,Sixth platform",
)
cls.csv_update_data = (
"id,name,description",
f"{platforms[0].pk},Platform 7,Fourth platform7",
f"{platforms[1].pk},Platform 8,Fifth platform8",
f"{platforms[2].pk},Platform 9,Sixth platform9",
)
cls.bulk_edit_data = {
'description': 'New description',
}
class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Device
@classmethod
def setUpTestData(cls):
sites = (
Site(name='Site 1', slug='site-1'),
Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
location = Location(site=sites[0], name='Location 1', slug='location-1')
location.save()
racks = (
Rack(name='Rack 1', site=sites[0], location=location),
Rack(name='Rack 2', site=sites[1]),
)
Rack.objects.bulk_create(racks)
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetypes = (
DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer),
DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer),
)
DeviceType.objects.bulk_create(devicetypes)
roles = (
DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'),
)
for role in roles:
role.save()
platforms = (
Platform(name='Platform 1', slug='platform-1'),
Platform(name='Platform 2', slug='platform-2'),
)
Platform.objects.bulk_create(platforms)
devices = (
Device(
name='Device 1',
site=sites[0],
rack=racks[0],
device_type=devicetypes[0],
role=roles[0],
platform=platforms[0],
),
Device(
name='Device 2',
site=sites[0],
rack=racks[0],
device_type=devicetypes[0],
role=roles[0],
platform=platforms[0],
),
Device(
name='Device 3',
site=sites[0],
rack=racks[0],
device_type=devicetypes[0],
role=roles[0],
platform=platforms[0],
),
)
Device.objects.bulk_create(devices)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
VirtualChassis.objects.create(name='Virtual Chassis 1')
cls.form_data = {
'device_type': devicetypes[1].pk,
'role': roles[1].pk,
'tenant': None,
'platform': platforms[1].pk,
'name': 'Device X',
'serial': '123456',
'asset_tag': 'ABCDEF',
'site': sites[1].pk,
'rack': racks[1].pk,
'position': 1,
'face': DeviceFaceChoices.FACE_FRONT,
'latitude': Decimal('35.780000'),
'longitude': Decimal('-78.642000'),
'status': DeviceStatusChoices.STATUS_PLANNED,
'primary_ip4': None,
'primary_ip6': None,
'cluster': None,
'virtual_chassis': None,
'vc_position': None,
'vc_priority': None,
'comments': 'A new device',
'tags': [t.pk for t in tags],
'local_context_data': None,
}
cls.csv_data = (
(
"role,manufacturer,device_type,status,name,site,location,rack,position,face,virtual_chassis,"
"vc_position,vc_priority"
),
(
"Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Location 1,Rack 1,10,front,"
"Virtual Chassis 1,1,10"
),
(
"Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Location 1,Rack 1,20,front,"
"Virtual Chassis 1,2,20"
),
(
"Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Location 1,Rack 1,30,front,"
"Virtual Chassis 1,3,30"
),
)
cls.csv_update_data = (
"id,status",
f"{devices[0].pk},{DeviceStatusChoices.STATUS_DECOMMISSIONING}",
f"{devices[1].pk},{DeviceStatusChoices.STATUS_DECOMMISSIONING}",
f"{devices[2].pk},{DeviceStatusChoices.STATUS_DECOMMISSIONING}",
)
cls.bulk_edit_data = {
'device_type': devicetypes[1].pk,
'role': roles[1].pk,
'tenant': None,
'platform': platforms[1].pk,
'serial': '123456',
'status': DeviceStatusChoices.STATUS_DECOMMISSIONING,
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_device_consoleports(self):
device = Device.objects.first()
console_ports = (
ConsolePort(device=device, name='Console Port 1'),
ConsolePort(device=device, name='Console Port 2'),
ConsolePort(device=device, name='Console Port 3'),
)
ConsolePort.objects.bulk_create(console_ports)
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):
device = Device.objects.first()
console_server_ports = (
ConsoleServerPort(device=device, name='Console Server Port 1'),
ConsoleServerPort(device=device, name='Console Server Port 2'),
ConsoleServerPort(device=device, name='Console Server Port 3'),
)
ConsoleServerPort.objects.bulk_create(console_server_ports)
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):
device = Device.objects.first()
power_ports = (
PowerPort(device=device, name='Power Port 1'),
PowerPort(device=device, name='Power Port 2'),
PowerPort(device=device, name='Power Port 3'),
)
PowerPort.objects.bulk_create(power_ports)
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):
device = Device.objects.first()
power_outlets = (
PowerOutlet(device=device, name='Power Outlet 1'),
PowerOutlet(device=device, name='Power Outlet 2'),
PowerOutlet(device=device, name='Power Outlet 3'),
)
PowerOutlet.objects.bulk_create(power_outlets)
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):
device = Device.objects.first()
interfaces = (
Interface(device=device, name='Interface 1'),
Interface(device=device, name='Interface 2'),
Interface(device=device, name='Interface 3'),
)
Interface.objects.bulk_create(interfaces)
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):
device = Device.objects.first()
rear_ports = (
RearPort(device=device, name='Rear Port 1'),
RearPort(device=device, name='Rear Port 2'),
RearPort(device=device, name='Rear Port 3'),
)
RearPort.objects.bulk_create(rear_ports)
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):
device = Device.objects.first()
rear_ports = (
RearPort(device=device, name='Rear Port 1'),
RearPort(device=device, name='Rear Port 2'),
RearPort(device=device, name='Rear Port 3'),
)
RearPort.objects.bulk_create(rear_ports)
front_ports = (
FrontPort(device=device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1),
FrontPort(device=device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1),
FrontPort(device=device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1),
)
FrontPort.objects.bulk_create(front_ports)
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):
device = Device.objects.first()
ModuleBay.objects.create(device=device, name='Module Bay 1')
ModuleBay.objects.create(device=device, name='Module Bay 2')
ModuleBay.objects.create(device=device, name='Module Bay 3')
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):
device = Device.objects.first()
device_bays = (
DeviceBay(device=device, name='Device Bay 1'),
DeviceBay(device=device, name='Device Bay 2'),
DeviceBay(device=device, name='Device Bay 3'),
)
DeviceBay.objects.bulk_create(device_bays)
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):
device = Device.objects.first()
inventory_items = (
InventoryItem(device=device, name='Inventory Item 1'),
InventoryItem(device=device, name='Inventory Item 2'),
InventoryItem(device=device, name='Inventory Item 3'),
)
for item in inventory_items:
item.save()
url = reverse('dcim:device_inventory', kwargs={'pk': device.pk})
self.assertHttpStatus(self.client.get(url), 200)
class ModuleTestCase(
# Module does not support bulk renaming (no name field) or
# bulk creation (need to specify module bays)
ViewTestCases.GetObjectViewTestCase,
ViewTestCases.GetObjectChangelogViewTestCase,
ViewTestCases.CreateObjectViewTestCase,
ViewTestCases.EditObjectViewTestCase,
ViewTestCases.DeleteObjectViewTestCase,
ViewTestCases.ListObjectsViewTestCase,
ViewTestCases.BulkImportObjectsViewTestCase,
ViewTestCases.BulkEditObjectsViewTestCase,
ViewTestCases.BulkDeleteObjectsViewTestCase,
):
model = Module
@classmethod
def setUpTestData(cls):
manufacturer = Manufacturer.objects.create(name='Generic', slug='generic')
devices = (
create_test_device('Device 1'),
create_test_device('Device 2'),
)
module_types = (
ModuleType(manufacturer=manufacturer, model='Module Type 1'),
ModuleType(manufacturer=manufacturer, model='Module Type 2'),
ModuleType(manufacturer=manufacturer, model='Module Type 3'),
ModuleType(manufacturer=manufacturer, model='Module Type 4'),
)
ModuleType.objects.bulk_create(module_types)
module_bays = (
ModuleBay(device=devices[0], name='Module Bay 1'),
ModuleBay(device=devices[0], name='Module Bay 2'),
ModuleBay(device=devices[0], name='Module Bay 3'),
ModuleBay(device=devices[0], name='Module Bay 4'),
ModuleBay(device=devices[0], name='Module Bay 5'),
ModuleBay(device=devices[1], name='Module Bay 1'),
ModuleBay(device=devices[1], name='Module Bay 2'),
ModuleBay(device=devices[1], name='Module Bay 3'),
ModuleBay(device=devices[1], name='Module Bay 4'),
ModuleBay(device=devices[1], name='Module Bay 5'),
)
for module_bay in module_bays:
module_bay.save()
modules = (
Module(device=devices[0], module_bay=module_bays[0], module_type=module_types[0]),
Module(device=devices[0], module_bay=module_bays[1], module_type=module_types[1]),
Module(device=devices[0], module_bay=module_bays[2], module_type=module_types[2]),
)
Module.objects.bulk_create(modules)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': devices[0].pk,
'module_bay': module_bays[3].pk,
'module_type': module_types[0].pk,
'status': ModuleStatusChoices.STATUS_ACTIVE,
'serial': 'A',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'module_type': module_types[3].pk,
'status': ModuleStatusChoices.STATUS_PLANNED,
}
cls.csv_data = (
"device,module_bay,module_type,status,serial,asset_tag",
"Device 2,Module Bay 1,Module Type 1,active,A,A",
"Device 2,Module Bay 2,Module Type 2,planned,B,B",
"Device 2,Module Bay 3,Module Type 3,failed,C,C",
)
cls.csv_update_data = (
"id,status,serial",
f"{modules[0].pk},offline,Serial 2",
f"{modules[1].pk},offline,Serial 3",
f"{modules[2].pk},offline,Serial 1",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_module_component_replication(self):
self.add_permissions('dcim.add_module')
# Add 5 InterfaceTemplates to a ModuleType
module_type = ModuleType.objects.first()
interface_templates = [
InterfaceTemplate(module_type=module_type, name=f'Interface {i}') for i in range(1, 6)
]
InterfaceTemplate.objects.bulk_create(interface_templates)
form_data = self.form_data.copy()
device = Device.objects.get(pk=form_data['device'])
# Create a module *without* replicating components
form_data['replicate_components'] = False
request = {
'path': self._get_url('add'),
'data': post_data(form_data),
}
self.assertHttpStatus(self.client.post(**request), 302)
self.assertEqual(Interface.objects.filter(device=device).count(), 0)
# Create a second module (in the next bay) with replicated components
form_data['module_bay'] += 1
form_data['replicate_components'] = True
request = {
'path': self._get_url('add'),
'data': post_data(form_data),
}
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')
# Add 5 InterfaceTemplates to a ModuleType
module_type = ModuleType.objects.first()
interface_templates = [
InterfaceTemplate(module_type=module_type, name=f'Interface {i}')
for i in range(1, 6)
]
InterfaceTemplate.objects.bulk_create(interface_templates)
# Create a module *without* replicating components
device = Device.objects.get(name='Device 2')
module_bay = ModuleBay.objects.get(device=device, name='Module Bay 4')
csv_data = [
"device,module_bay,module_type,status,replicate_components",
f"{device.name},{module_bay.name},{module_type.model},active,false"
]
request = {
'path': self._get_url('bulk_import'),
'data': {
'data': '\n'.join(csv_data),
'format': ImportFormatChoices.CSV,
'csv_delimiter': CSVDelimiterChoices.AUTO,
}
}
initial_count = Module.objects.count()
self.assertHttpStatus(self.client.post(**request), 302)
self.assertEqual(Module.objects.count(), initial_count + len(csv_data) - 1)
self.assertEqual(Interface.objects.filter(device=device).count(), 0)
# Create a second module (in the next bay) with replicated components
module_bay = ModuleBay.objects.get(device=device, name='Module Bay 5')
csv_data[1] = f"{device.name},{module_bay.name},{module_type.model},active,true"
request = {
'path': self._get_url('bulk_import'),
'data': {
'data': '\n'.join(csv_data),
'format': ImportFormatChoices.CSV,
'csv_delimiter': CSVDelimiterChoices.AUTO,
}
}
initial_count = Module.objects.count()
self.assertHttpStatus(self.client.post(**request), 302)
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')
interface_name = "Interface-1"
# Add an interface to the ModuleType
module_type = ModuleType.objects.first()
InterfaceTemplate(module_type=module_type, name=interface_name).save()
form_data = self.form_data.copy()
device = Device.objects.get(pk=form_data['device'])
# Create an interface to be adopted
interface = Interface(device=device, name=interface_name, type=InterfaceTypeChoices.TYPE_10GE_FIXED)
interface.save()
# Ensure that interface is created with no module
self.assertIsNone(interface.module)
# Create a module with adopted components
form_data['module_type'] = module_type
form_data['replicate_components'] = False
form_data['adopt_components'] = True
request = {
'path': self._get_url('add'),
'data': post_data(form_data),
}
self.assertHttpStatus(self.client.post(**request), 302)
# Re-retrieve interface to get new module id
interface.refresh_from_db()
# 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')
interface_name = "Interface-1"
# Add an interface to the ModuleType
module_type = ModuleType.objects.first()
InterfaceTemplate(module_type=module_type, name=interface_name).save()
form_data = self.form_data.copy()
device = Device.objects.get(pk=form_data['device'])
# Create an interface to be adopted
interface = Interface(device=device, name=interface_name, type=InterfaceTypeChoices.TYPE_10GE_FIXED)
interface.save()
# Ensure that interface is created with no module
self.assertIsNone(interface.module)
# Create a module with adopted components
module_bay = ModuleBay.objects.get(device=device, name='Module Bay 4')
csv_data = [
"device,module_bay,module_type,status,replicate_components,adopt_components",
f"{device.name},{module_bay.name},{module_type.model},active,false,true"
]
request = {
'path': self._get_url('bulk_import'),
'data': {
'data': '\n'.join(csv_data),
'format': ImportFormatChoices.CSV,
'csv_delimiter': CSVDelimiterChoices.AUTO,
}
}
initial_count = self._get_queryset().count()
self.assertHttpStatus(self.client.post(**request), 302)
self.assertEqual(self._get_queryset().count(), initial_count + len(csv_data) - 1)
# Re-retrieve interface to get new module id
interface.refresh_from_db()
# Check that the Interface now has a module
self.assertIsNotNone(interface.module)
class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = ConsolePort
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
console_ports = (
ConsolePort(device=device, name='Console Port 1'),
ConsolePort(device=device, name='Console Port 2'),
ConsolePort(device=device, name='Console Port 3'),
)
ConsolePort.objects.bulk_create(console_ports)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Console Port X',
'type': ConsolePortTypeChoices.TYPE_RJ45,
'description': 'A console port',
'tags': sorted([t.pk for t in tags]),
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Console Port [4-6]',
# Test that a label can be applied to each generated console ports
'label': 'Serial[3-5]',
'type': ConsolePortTypeChoices.TYPE_RJ45,
'description': 'A console port',
'tags': sorted([t.pk for t in tags]),
}
cls.bulk_edit_data = {
'type': ConsolePortTypeChoices.TYPE_RJ45,
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Console Port 4",
"Device 1,Console Port 5",
"Device 1,Console Port 6",
)
cls.csv_update_data = (
"id,name,description",
f"{console_ports[0].pk},Console Port 7,New description7",
f"{console_ports[1].pk},Console Port 8,New description8",
f"{console_ports[2].pk},Console Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
consoleport = ConsolePort.objects.first()
consoleserverport = ConsoleServerPort.objects.create(
device=consoleport.device,
name='Console Server Port 1'
)
Cable(a_terminations=[consoleport], b_terminations=[consoleserverport]).save()
response = self.client.get(reverse('dcim:consoleport_trace', kwargs={'pk': consoleport.pk}))
self.assertHttpStatus(response, 200)
class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = ConsoleServerPort
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
console_server_ports = (
ConsoleServerPort(device=device, name='Console Server Port 1'),
ConsoleServerPort(device=device, name='Console Server Port 2'),
ConsoleServerPort(device=device, name='Console Server Port 3'),
)
ConsoleServerPort.objects.bulk_create(console_server_ports)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Console Server Port X',
'type': ConsolePortTypeChoices.TYPE_RJ45,
'description': 'A console server port',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Console Server Port [4-6]',
'type': ConsolePortTypeChoices.TYPE_RJ45,
'description': 'A console server port',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': ConsolePortTypeChoices.TYPE_RJ11,
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Console Server Port 4",
"Device 1,Console Server Port 5",
"Device 1,Console Server Port 6",
)
cls.csv_update_data = (
"id,name,description",
f"{console_server_ports[0].pk},Console Server Port 7,New description 7",
f"{console_server_ports[1].pk},Console Server Port 8,New description 8",
f"{console_server_ports[2].pk},Console Server Port 9,New description 9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
consoleserverport = ConsoleServerPort.objects.first()
consoleport = ConsolePort.objects.create(
device=consoleserverport.device,
name='Console Port 1'
)
Cable(a_terminations=[consoleserverport], b_terminations=[consoleport]).save()
response = self.client.get(reverse('dcim:consoleserverport_trace', kwargs={'pk': consoleserverport.pk}))
self.assertHttpStatus(response, 200)
class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = PowerPort
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
power_ports = (
PowerPort(device=device, name='Power Port 1'),
PowerPort(device=device, name='Power Port 2'),
PowerPort(device=device, name='Power Port 3'),
)
PowerPort.objects.bulk_create(power_ports)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Power Port X',
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
'description': 'A power port',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Power Port [4-6]]',
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
'description': 'A power port',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': PowerPortTypeChoices.TYPE_IEC_C14,
'maximum_draw': 100,
'allocated_draw': 50,
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Power Port 4",
"Device 1,Power Port 5",
"Device 1,Power Port 6",
)
cls.csv_update_data = (
"id,name,description",
f"{power_ports[0].pk},Power Port 7,New description7",
f"{power_ports[1].pk},Power Port 8,New description8",
f"{power_ports[2].pk},Power Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
powerport = PowerPort.objects.first()
poweroutlet = PowerOutlet.objects.create(
device=powerport.device,
name='Power Outlet 1'
)
Cable(a_terminations=[powerport], b_terminations=[poweroutlet]).save()
response = self.client.get(reverse('dcim:powerport_trace', kwargs={'pk': powerport.pk}))
self.assertHttpStatus(response, 200)
class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = PowerOutlet
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
powerports = (
PowerPort(device=device, name='Power Port 1'),
PowerPort(device=device, name='Power Port 2'),
)
PowerPort.objects.bulk_create(powerports)
power_outlets = (
PowerOutlet(device=device, name='Power Outlet 1', power_port=powerports[0]),
PowerOutlet(device=device, name='Power Outlet 2', power_port=powerports[0]),
PowerOutlet(device=device, name='Power Outlet 3', power_port=powerports[0]),
)
PowerOutlet.objects.bulk_create(power_outlets)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Power Outlet X',
'type': PowerOutletTypeChoices.TYPE_IEC_C13,
'status': PowerOutletStatusChoices.STATUS_ENABLED,
'power_port': powerports[1].pk,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
'description': 'A power outlet',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Power Outlet [4-6]',
'type': PowerOutletTypeChoices.TYPE_IEC_C13,
'status': PowerOutletStatusChoices.STATUS_ENABLED,
'power_port': powerports[1].pk,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
'description': 'A power outlet',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': PowerOutletTypeChoices.TYPE_IEC_C15,
'status': PowerOutletStatusChoices.STATUS_ENABLED,
'power_port': powerports[1].pk,
'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Power Outlet 4",
"Device 1,Power Outlet 5",
"Device 1,Power Outlet 6",
)
cls.csv_update_data = (
"id,name,description",
f"{power_outlets[0].pk},Power Outlet 7,New description7",
f"{power_outlets[1].pk},Power Outlet 8,New description8",
f"{power_outlets[2].pk},Power Outlet 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
poweroutlet = PowerOutlet.objects.first()
powerport = PowerPort.objects.first()
Cable(a_terminations=[poweroutlet], b_terminations=[powerport]).save()
response = self.client.get(reverse('dcim:poweroutlet_trace', kwargs={'pk': poweroutlet.pk}))
self.assertHttpStatus(response, 200)
class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = Interface
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
interfaces = (
Interface(device=device, name='Interface 1'),
Interface(device=device, name='Interface 2'),
Interface(device=device, name='Interface 3'),
Interface(device=device, name='LAG', type=InterfaceTypeChoices.TYPE_LAG),
Interface(device=device, name='_BRIDGE', type=InterfaceTypeChoices.TYPE_VIRTUAL), # Must be ordered last
)
Interface.objects.bulk_create(interfaces)
vlans = (
VLAN(vid=1, name='VLAN1', site=device.site),
VLAN(vid=101, name='VLAN101', site=device.site),
VLAN(vid=102, name='VLAN102', site=device.site),
VLAN(vid=103, name='VLAN103', site=device.site),
)
VLAN.objects.bulk_create(vlans)
wireless_lans = (
WirelessLAN(ssid='WLAN1'),
WirelessLAN(ssid='WLAN2'),
)
WirelessLAN.objects.bulk_create(wireless_lans)
vrfs = (
VRF(name='VRF 1'),
VRF(name='VRF 2'),
VRF(name='VRF 3'),
)
VRF.objects.bulk_create(vrfs)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Interface X',
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
'enabled': False,
'bridge': interfaces[4].pk,
'lag': interfaces[3].pk,
'wwn': EUI('01:02:03:04:05:06:07:08', version=64),
'mtu': 65000,
'speed': 1000000,
'duplex': 'full',
'mgmt_only': True,
'description': 'A front port',
'mode': InterfaceModeChoices.MODE_TAGGED,
'tx_power': 10,
'poe_mode': InterfacePoEModeChoices.MODE_PSE,
'poe_type': InterfacePoETypeChoices.TYPE_1_8023AF,
'untagged_vlan': vlans[0].pk,
'tagged_vlans': [v.pk for v in vlans[1:4]],
'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk],
'vrf': vrfs[0].pk,
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Interface [4-6]',
'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
'enabled': False,
'bridge': interfaces[4].pk,
'lag': interfaces[3].pk,
'wwn': EUI('01:02:03:04:05:06:07:08', version=64),
'mtu': 2000,
'speed': 100000,
'duplex': 'half',
'mgmt_only': True,
'description': 'A front port',
'poe_mode': InterfacePoEModeChoices.MODE_PSE,
'poe_type': InterfacePoETypeChoices.TYPE_1_8023AF,
'mode': InterfaceModeChoices.MODE_TAGGED,
'untagged_vlan': vlans[0].pk,
'tagged_vlans': [v.pk for v in vlans[1:4]],
'wireless_lans': [wireless_lans[0].pk, wireless_lans[1].pk],
'vrf': vrfs[0].pk,
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': InterfaceTypeChoices.TYPE_1GE_FIXED,
'enabled': True,
'lag': interfaces[3].pk,
'wwn': EUI('01:02:03:04:05:06:07:08', version=64),
'mtu': 2000,
'speed': 1000000,
'duplex': 'full',
'mgmt_only': True,
'description': 'New description',
'poe_mode': InterfacePoEModeChoices.MODE_PD,
'poe_type': InterfacePoETypeChoices.TYPE_2_8023AT,
'mode': InterfaceModeChoices.MODE_TAGGED,
'tx_power': 10,
'untagged_vlan': vlans[0].pk,
'tagged_vlans': [v.pk for v in vlans[1:4]],
'vrf': vrfs[1].pk,
}
cls.csv_data = (
"device,name,type,vrf.pk,poe_mode,poe_type",
f"Device 1,Interface 4,1000base-t,{vrfs[0].pk},pse,type1-ieee802.3af",
f"Device 1,Interface 5,1000base-t,{vrfs[0].pk},pse,type1-ieee802.3af",
f"Device 1,Interface 6,1000base-t,{vrfs[0].pk},pse,type1-ieee802.3af",
)
cls.csv_update_data = (
"id,name,description",
f"{interfaces[0].pk},Interface 7,New description7",
f"{interfaces[1].pk},Interface 8,New description8",
f"{interfaces[2].pk},Interface 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
interface1, interface2 = Interface.objects.all()[:2]
Cable(a_terminations=[interface1], b_terminations=[interface2]).save()
response = self.client.get(reverse('dcim:interface_trace', kwargs={'pk': interface1.pk}))
self.assertHttpStatus(response, 200)
def test_bulk_delete_child_interfaces(self):
interface1 = Interface.objects.get(name='Interface 1')
device = interface1.device
self.add_permissions('dcim.delete_interface')
# Create a child interface
child = Interface.objects.create(
device=device,
name='Interface 1A',
type=InterfaceTypeChoices.TYPE_VIRTUAL,
parent=interface1
)
self.assertEqual(device.interfaces.count(), 6)
# Attempt to delete only the parent interface
data = {
'confirm': True,
}
self.client.post(self._get_url('delete', interface1), data)
self.assertEqual(device.interfaces.count(), 6) # Parent was not deleted
# Attempt to bulk delete parent & child together
data = {
'pk': [interface1.pk, child.pk],
'confirm': True,
'_confirm': True, # Form button
}
self.client.post(self._get_url('bulk_delete'), data)
self.assertEqual(device.interfaces.count(), 4) # Child & parent were both deleted
class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = FrontPort
validation_excluded_fields = ('name', 'label', 'rear_port')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
rearports = (
RearPort(device=device, name='Rear Port 1'),
RearPort(device=device, name='Rear Port 2'),
RearPort(device=device, name='Rear Port 3'),
RearPort(device=device, name='Rear Port 4'),
RearPort(device=device, name='Rear Port 5'),
RearPort(device=device, name='Rear Port 6'),
)
RearPort.objects.bulk_create(rearports)
front_ports = (
FrontPort(device=device, name='Front Port 1', rear_port=rearports[0]),
FrontPort(device=device, name='Front Port 2', rear_port=rearports[1]),
FrontPort(device=device, name='Front Port 3', rear_port=rearports[2]),
)
FrontPort.objects.bulk_create(front_ports)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Front Port X',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': rearports[3].pk,
'rear_port_position': 1,
'description': 'New description',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Front Port [4-6]',
'type': PortTypeChoices.TYPE_8P8C,
'rear_port': [f'{rp.pk}:1' for rp in rearports[3:6]],
'description': 'New description',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': PortTypeChoices.TYPE_8P8C,
'description': 'New description',
}
cls.csv_data = (
"device,name,type,rear_port,rear_port_position",
"Device 1,Front Port 4,8p8c,Rear Port 4,1",
"Device 1,Front Port 5,8p8c,Rear Port 5,1",
"Device 1,Front Port 6,8p8c,Rear Port 6,1",
)
cls.csv_update_data = (
"id,name,description",
f"{front_ports[0].pk},Front Port 7,New description7",
f"{front_ports[1].pk},Front Port 8,New description8",
f"{front_ports[2].pk},Front Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
frontport = FrontPort.objects.first()
interface = Interface.objects.create(
device=frontport.device,
name='Interface 1'
)
Cable(a_terminations=[frontport], b_terminations=[interface]).save()
response = self.client.get(reverse('dcim:frontport_trace', kwargs={'pk': frontport.pk}))
self.assertHttpStatus(response, 200)
class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = RearPort
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
rear_ports = (
RearPort(device=device, name='Rear Port 1'),
RearPort(device=device, name='Rear Port 2'),
RearPort(device=device, name='Rear Port 3'),
)
RearPort.objects.bulk_create(rear_ports)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Rear Port X',
'type': PortTypeChoices.TYPE_8P8C,
'positions': 3,
'description': 'A rear port',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Rear Port [4-6]',
'type': PortTypeChoices.TYPE_8P8C,
'positions': 3,
'description': 'A rear port',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'type': PortTypeChoices.TYPE_8P8C,
'description': 'New description',
}
cls.csv_data = (
"device,name,type,positions",
"Device 1,Rear Port 4,8p8c,1",
"Device 1,Rear Port 5,8p8c,1",
"Device 1,Rear Port 6,8p8c,1",
)
cls.csv_update_data = (
"id,name,description",
f"{rear_ports[0].pk},Rear Port 7,New description7",
f"{rear_ports[1].pk},Rear Port 8,New description8",
f"{rear_ports[2].pk},Rear Port 9,New description9",
)
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
rearport = RearPort.objects.first()
interface = Interface.objects.create(
device=rearport.device,
name='Interface 1'
)
Cable(a_terminations=[rearport], b_terminations=[interface]).save()
response = self.client.get(reverse('dcim:rearport_trace', kwargs={'pk': rearport.pk}))
self.assertHttpStatus(response, 200)
class ModuleBayTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = ModuleBay
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
module_bays = (
ModuleBay(device=device, name='Module Bay 1'),
ModuleBay(device=device, name='Module Bay 2'),
ModuleBay(device=device, name='Module Bay 3'),
)
for module_bay in module_bays:
module_bay.save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Module Bay X',
'description': 'A device bay',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Module Bay [4-6]',
'description': 'A module bay',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Module Bay 4",
"Device 1,Module Bay 5",
"Device 1,Module Bay 6",
)
cls.csv_update_data = (
"id,name,description",
f"{module_bays[0].pk},Module Bay 7,New description7",
f"{module_bays[1].pk},Module Bay 8,New description8",
f"{module_bays[2].pk},Module Bay 9,New description9",
)
class DeviceBayTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = DeviceBay
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
# Update the DeviceType subdevice role to allow adding DeviceBays
DeviceType.objects.update(subdevice_role=SubdeviceRoleChoices.ROLE_PARENT)
device_bays = (
DeviceBay(device=device, name='Device Bay 1'),
DeviceBay(device=device, name='Device Bay 2'),
DeviceBay(device=device, name='Device Bay 3'),
)
DeviceBay.objects.bulk_create(device_bays)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'name': 'Device Bay X',
'description': 'A device bay',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Device Bay [4-6]',
'description': 'A device bay',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'description': 'New description',
}
cls.csv_data = (
"device,name",
"Device 1,Device Bay 4",
"Device 1,Device Bay 5",
"Device 1,Device Bay 6",
)
cls.csv_update_data = (
"id,name,description",
f"{device_bays[0].pk},Device Bay 7,New description7",
f"{device_bays[1].pk},Device Bay 8,New description8",
f"{device_bays[2].pk},Device Bay 9,New description9",
)
class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase):
model = InventoryItem
validation_excluded_fields = ('name', 'label')
@classmethod
def setUpTestData(cls):
device = create_test_device('Device 1')
manufacturer, _ = Manufacturer.objects.get_or_create(name='Manufacturer 1', slug='manufacturer-1')
roles = (
InventoryItemRole(name='Inventory Item Role 1', slug='inventory-item-role-1'),
InventoryItemRole(name='Inventory Item Role 2', slug='inventory-item-role-2'),
)
InventoryItemRole.objects.bulk_create(roles)
inventory_item1 = InventoryItem.objects.create(
device=device, name='Inventory Item 1', role=roles[0], manufacturer=manufacturer
)
inventory_item2 = InventoryItem.objects.create(
device=device, name='Inventory Item 2', role=roles[0], manufacturer=manufacturer
)
inventory_item3 = InventoryItem.objects.create(
device=device, name='Inventory Item 3', role=roles[0], manufacturer=manufacturer
)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': device.pk,
'role': roles[1].pk,
'manufacturer': manufacturer.pk,
'name': 'Inventory Item X',
'parent': None,
'discovered': False,
'part_id': '123456',
'serial': '123ABC',
'asset_tag': 'ABC123',
'status': InventoryItemStatusChoices.STATUS_ACTIVE,
'description': 'An inventory item',
'tags': [t.pk for t in tags],
}
cls.bulk_create_data = {
'device': device.pk,
'name': 'Inventory Item [4-6]',
'role': roles[1].pk,
'manufacturer': manufacturer.pk,
'parent': None,
'discovered': False,
'part_id': '123456',
'serial': '123ABC',
'status': InventoryItemStatusChoices.STATUS_ACTIVE,
'description': 'An inventory item',
'tags': [t.pk for t in tags],
}
cls.bulk_edit_data = {
'role': roles[1].pk,
'part_id': '123456',
'description': 'New description',
}
cls.csv_data = (
"device,name,parent,status",
"Device 1,Inventory Item 4,Inventory Item 1,active",
"Device 1,Inventory Item 5,Inventory Item 2,planned",
"Device 1,Inventory Item 6,Inventory Item 3,failed",
)
cls.csv_update_data = (
"id,name,description",
f"{inventory_item1.pk},Inventory Item 7,New description7",
f"{inventory_item2.pk},Inventory Item 8,New description8",
f"{inventory_item3.pk},Inventory Item 9,New description9",
)
class InventoryItemRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
model = InventoryItemRole
@classmethod
def setUpTestData(cls):
inventory_item_roles = (
InventoryItemRole(name='Inventory Item Role 1', slug='inventory-item-role-1'),
InventoryItemRole(name='Inventory Item Role 2', slug='inventory-item-role-2'),
InventoryItemRole(name='Inventory Item Role 3', slug='inventory-item-role-3'),
)
InventoryItemRole.objects.bulk_create(inventory_item_roles)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Inventory Item Role X',
'slug': 'inventory-item-role-x',
'color': 'c0c0c0',
'description': 'New inventory item role',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,slug,color",
"Inventory Item Role 4,inventory-item-role-4,ff0000",
"Inventory Item Role 5,inventory-item-role-5,00ff00",
"Inventory Item Role 6,inventory-item-role-6,0000ff",
)
cls.csv_update_data = (
"id,name,description",
f"{inventory_item_roles[0].pk},Inventory Item Role 7,New description7",
f"{inventory_item_roles[1].pk},Inventory Item Role 8,New description8",
f"{inventory_item_roles[2].pk},Inventory Item Role 9,New description9",
)
cls.bulk_edit_data = {
'color': '00ff00',
'description': 'New description',
}
# TODO: Change base class to PrimaryObjectViewTestCase
# Blocked by lack of common creation view for cables (termination A must be initialized)
class CableTestCase(
ViewTestCases.GetObjectViewTestCase,
ViewTestCases.GetObjectChangelogViewTestCase,
ViewTestCases.EditObjectViewTestCase,
ViewTestCases.DeleteObjectViewTestCase,
ViewTestCases.ListObjectsViewTestCase,
ViewTestCases.BulkImportObjectsViewTestCase,
ViewTestCases.BulkEditObjectsViewTestCase,
ViewTestCases.BulkDeleteObjectsViewTestCase
):
model = Cable
@classmethod
def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1')
manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
vc = VirtualChassis.objects.create(name='Virtual Chassis')
devices = (
Device(name='Device 1', site=site, device_type=devicetype, role=role),
Device(name='Device 2', site=site, device_type=devicetype, role=role),
Device(name='Device 3', site=site, device_type=devicetype, role=role),
Device(name='Device 4', site=site, device_type=devicetype, role=role),
)
Device.objects.bulk_create(devices)
vc.members.set((devices[0], devices[1], devices[2]))
vc.master = devices[0]
vc.save()
interfaces = (
Interface(device=devices[0], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[0], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[0], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[1], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[1], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[1], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[2], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[2], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[2], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[3], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[3], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[3], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[1], name='Device 2 Interface', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[2], name='Device 3 Interface', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[3], name='Interface 4', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
Interface(device=devices[3], name='Interface 5', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
)
Interface.objects.bulk_create(interfaces)
cable1 = Cable(a_terminations=[interfaces[0]], b_terminations=[interfaces[3]], type=CableTypeChoices.TYPE_CAT6)
cable1.save()
cable2 = Cable(a_terminations=[interfaces[1]], b_terminations=[interfaces[4]], type=CableTypeChoices.TYPE_CAT6)
cable2.save()
cable3 = Cable(a_terminations=[interfaces[2]], b_terminations=[interfaces[5]], type=CableTypeChoices.TYPE_CAT6)
cable3.save()
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
# TODO: Revisit this limitation
# Changing terminations not supported when editing an existing Cable
'a_terminations': [interfaces[0].pk],
'b_terminations': [interfaces[3].pk],
'type': CableTypeChoices.TYPE_CAT6,
'status': LinkStatusChoices.STATUS_PLANNED,
'label': 'Label',
'color': 'c0c0c0',
'length': 100,
'length_unit': CableLengthUnitChoices.UNIT_FOOT,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
"Device 3,dcim.interface,Interface 1,Device 4,dcim.interface,Interface 1",
"Device 3,dcim.interface,Interface 2,Device 4,dcim.interface,Interface 2",
"Device 3,dcim.interface,Interface 3,Device 4,dcim.interface,Interface 3",
"Device 1,dcim.interface,Device 2 Interface,Device 4,dcim.interface,Interface 4",
"Device 1,dcim.interface,Device 3 Interface,Device 4,dcim.interface,Interface 5",
)
cls.csv_update_data = (
"id,label,color",
f"{cable1.pk},New label7,00ff00",
f"{cable2.pk},New label8,00ff00",
f"{cable3.pk},New label9,00ff00",
)
cls.bulk_edit_data = {
'type': CableTypeChoices.TYPE_CAT5E,
'status': LinkStatusChoices.STATUS_CONNECTED,
'label': 'New label',
'color': '00ff00',
'length': 50,
'length_unit': CableLengthUnitChoices.UNIT_METER,
}
def model_to_dict(self, *args, **kwargs):
data = super().model_to_dict(*args, **kwargs)
# Serialize termination objects
if 'a_terminations' in data:
data['a_terminations'] = [obj.pk for obj in data['a_terminations']]
if 'b_terminations' in data:
data['b_terminations'] = [obj.pk for obj in data['b_terminations']]
return data
class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = VirtualChassis
@classmethod
def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1')
manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
device_type = DeviceType.objects.create(
manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
)
role = DeviceRole.objects.create(
name='Device Role', slug='device-role-1'
)
devices = (
Device(device_type=device_type, role=role, name='Device 1', site=site),
Device(device_type=device_type, role=role, name='Device 2', site=site),
Device(device_type=device_type, role=role, name='Device 3', site=site),
Device(device_type=device_type, role=role, name='Device 4', site=site),
Device(device_type=device_type, role=role, name='Device 5', site=site),
Device(device_type=device_type, role=role, name='Device 6', site=site),
Device(device_type=device_type, role=role, name='Device 7', site=site),
Device(device_type=device_type, role=role, name='Device 8', site=site),
Device(device_type=device_type, role=role, name='Device 9', site=site),
Device(device_type=device_type, role=role, name='Device 10', site=site),
Device(device_type=device_type, role=role, name='Device 11', site=site),
Device(device_type=device_type, role=role, name='Device 12', site=site),
)
Device.objects.bulk_create(devices)
# Create three VirtualChassis with three members each
vc1 = VirtualChassis.objects.create(name='VC1', master=devices[0], domain='domain-1')
Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=vc1, vc_position=1)
Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=vc1, vc_position=2)
Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=vc1, vc_position=3)
vc2 = VirtualChassis.objects.create(name='VC2', master=devices[3], domain='domain-2')
Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=vc2, vc_position=1)
Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=vc2, vc_position=2)
Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=vc2, vc_position=3)
vc3 = VirtualChassis.objects.create(name='VC3', master=devices[6], domain='domain-3')
Device.objects.filter(pk=devices[6].pk).update(virtual_chassis=vc3, vc_position=1)
Device.objects.filter(pk=devices[7].pk).update(virtual_chassis=vc3, vc_position=2)
Device.objects.filter(pk=devices[8].pk).update(virtual_chassis=vc3, vc_position=3)
cls.form_data = {
'name': 'VC4',
'domain': 'domain-4',
# Management form data for VC members
'form-TOTAL_FORMS': 0,
'form-INITIAL_FORMS': 3,
'form-MIN_NUM_FORMS': 0,
'form-MAX_NUM_FORMS': 1000,
}
cls.csv_data = (
"name,domain,master",
"VC4,Domain 4,Device 10",
"VC5,Domain 5,Device 11",
"VC6,Domain 6,Device 12",
)
cls.csv_update_data = (
"id,name,domain",
f"{vc1.pk},VC7,Domain 7",
f"{vc2.pk},VC8,Domain 8",
f"{vc3.pk},VC9,Domain 9",
)
cls.bulk_edit_data = {
'domain': 'domain-x',
}
class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = PowerPanel
@classmethod
def setUpTestData(cls):
sites = (
Site(name='Site 1', slug='site-1'),
Site(name='Site 2', slug='site-2'),
)
Site.objects.bulk_create(sites)
locations = (
Location(name='Location 1', slug='location-1', site=sites[0]),
Location(name='Location 2', slug='location-2', site=sites[1]),
)
for location in locations:
location.save()
power_panels = (
PowerPanel(site=sites[0], location=locations[0], name='Power Panel 1'),
PowerPanel(site=sites[0], location=locations[0], name='Power Panel 2'),
PowerPanel(site=sites[0], location=locations[0], name='Power Panel 3'),
)
PowerPanel.objects.bulk_create(power_panels)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'site': sites[1].pk,
'location': locations[1].pk,
'name': 'Power Panel X',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"site,location,name",
"Site 1,Location 1,Power Panel 4",
"Site 1,Location 1,Power Panel 5",
"Site 1,Location 1,Power Panel 6",
)
cls.csv_update_data = (
"id,name",
f"{power_panels[0].pk},Power Panel 7",
f"{power_panels[1].pk},Power Panel 8",
f"{power_panels[2].pk},Power Panel 9",
)
cls.bulk_edit_data = {
'site': sites[1].pk,
'location': locations[1].pk,
}
class PowerFeedTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = PowerFeed
@classmethod
def setUpTestData(cls):
site = Site.objects.create(name='Site 1', slug='site-1')
powerpanels = (
PowerPanel(site=site, name='Power Panel 1'),
PowerPanel(site=site, name='Power Panel 2'),
)
PowerPanel.objects.bulk_create(powerpanels)
racks = (
Rack(site=site, name='Rack 1'),
Rack(site=site, name='Rack 2'),
)
Rack.objects.bulk_create(racks)
power_feeds = (
PowerFeed(name='Power Feed 1', power_panel=powerpanels[0], rack=racks[0]),
PowerFeed(name='Power Feed 2', power_panel=powerpanels[0], rack=racks[0]),
PowerFeed(name='Power Feed 3', power_panel=powerpanels[0], rack=racks[0]),
)
PowerFeed.objects.bulk_create(power_feeds)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Power Feed X',
'power_panel': powerpanels[1].pk,
'rack': racks[1].pk,
'status': PowerFeedStatusChoices.STATUS_PLANNED,
'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
'supply': PowerFeedSupplyChoices.SUPPLY_DC,
'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
'voltage': 100,
'amperage': 100,
'max_utilization': 50,
'comments': 'New comments',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"site,power_panel,name,status,type,supply,phase,voltage,amperage,max_utilization",
"Site 1,Power Panel 1,Power Feed 4,active,primary,ac,single-phase,120,20,80",
"Site 1,Power Panel 1,Power Feed 5,active,primary,ac,single-phase,120,20,80",
"Site 1,Power Panel 1,Power Feed 6,active,primary,ac,single-phase,120,20,80",
)
cls.csv_update_data = (
"id,name,status",
f"{power_feeds[0].pk},Power Feed 7,{PowerFeedStatusChoices.STATUS_PLANNED}",
f"{power_feeds[1].pk},Power Feed 8,{PowerFeedStatusChoices.STATUS_PLANNED}",
f"{power_feeds[2].pk},Power Feed 9,{PowerFeedStatusChoices.STATUS_PLANNED}",
)
cls.bulk_edit_data = {
'power_panel': powerpanels[1].pk,
'rack': racks[1].pk,
'status': PowerFeedStatusChoices.STATUS_PLANNED,
'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
'supply': PowerFeedSupplyChoices.SUPPLY_DC,
'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
'voltage': 100,
'amperage': 100,
'max_utilization': 50,
'comments': 'New comments',
}
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_trace(self):
manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
device_type = DeviceType.objects.create(
manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
)
role = DeviceRole.objects.create(
name='Device Role', slug='device-role-1'
)
device = Device.objects.create(
site=Site.objects.first(), device_type=device_type, role=role
)
powerfeed = PowerFeed.objects.first()
powerport = PowerPort.objects.create(
device=device,
name='Power Port 1'
)
Cable(a_terminations=[powerfeed], b_terminations=[powerport]).save()
response = self.client.get(reverse('dcim:powerfeed_trace', kwargs={'pk': powerfeed.pk}))
self.assertHttpStatus(response, 200)
class VirtualDeviceContextTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = VirtualDeviceContext
@classmethod
def setUpTestData(cls):
devices = [create_test_device(name='Device 1')]
vdcs = (
VirtualDeviceContext(name='VDC 1', identifier=1, device=devices[0], status='active'),
VirtualDeviceContext(name='VDC 2', identifier=2, device=devices[0], status='active'),
VirtualDeviceContext(name='VDC 3', identifier=3, device=devices[0], status='active'),
)
VirtualDeviceContext.objects.bulk_create(vdcs)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'device': devices[0].pk,
'status': 'active',
'name': 'VDC 4',
'identifier': 4,
'primary_ip4': None,
'primary_ip6': None,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"device,status,name,identifier",
"Device 1,active,VDC 5,5",
"Device 1,active,VDC 6,6",
"Device 1,active,VDC 7,7",
)
cls.csv_update_data = (
"id,status",
f"{vdcs[0].pk},{VirtualDeviceContextStatusChoices.STATUS_PLANNED}",
f"{vdcs[1].pk},{VirtualDeviceContextStatusChoices.STATUS_PLANNED}",
f"{vdcs[2].pk},{VirtualDeviceContextStatusChoices.STATUS_PLANNED}",
)
cls.bulk_edit_data = {
'status': VirtualDeviceContextStatusChoices.STATUS_OFFLINE,
}
class MACAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = MACAddress
@classmethod
def setUpTestData(cls):
device = create_test_device(name='Device 1')
interfaces = (
Interface(device=device, name='Interface 1', type='1000base-t'),
Interface(device=device, name='Interface 2', type='1000base-t'),
Interface(device=device, name='Interface 3', type='1000base-t'),
Interface(device=device, name='Interface 4', type='1000base-t'),
Interface(device=device, name='Interface 5', type='1000base-t'),
Interface(device=device, name='Interface 6', type='1000base-t'),
)
Interface.objects.bulk_create(interfaces)
mac_addresses = (
MACAddress(mac_address='00:00:00:00:00:01', assigned_object=interfaces[0]),
MACAddress(mac_address='00:00:00:00:00:02', assigned_object=interfaces[1]),
MACAddress(mac_address='00:00:00:00:00:03', assigned_object=interfaces[2]),
)
MACAddress.objects.bulk_create(mac_addresses)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'mac_address': EUI('00:00:00:00:00:04'),
'description': 'New MAC address',
'interface_id': interfaces[3].pk,
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"mac_address,device,interface",
"00:00:00:00:00:04,Device 1,Interface 4",
"00:00:00:00:00:05,Device 1,Interface 5",
"00:00:00:00:00:06,Device 1,Interface 6",
)
cls.csv_update_data = (
"id,mac_address",
f"{mac_addresses[0].pk},00:00:00:00:00:0a",
f"{mac_addresses[1].pk},00:00:00:00:00:0b",
f"{mac_addresses[2].pk},00:00:00:00:00:0c",
)
cls.bulk_edit_data = {
'description': 'New description',
}