4283: adds maintenance mode to device status, adds unit tests

This commit is contained in:
Aaron Iles ayiles 2024-02-07 13:05:11 -05:00
parent 28aee9b69a
commit 2fe3c7035a
4 changed files with 145 additions and 5 deletions

View File

@ -167,6 +167,7 @@ class DeviceStatusChoices(ChoiceSet):
STATUS_FAILED = 'failed' STATUS_FAILED = 'failed'
STATUS_INVENTORY = 'inventory' STATUS_INVENTORY = 'inventory'
STATUS_DECOMMISSIONING = 'decommissioning' STATUS_DECOMMISSIONING = 'decommissioning'
STATUS_MAINTENANCE = 'maintenance'
CHOICES = [ CHOICES = [
(STATUS_OFFLINE, _('Offline'), 'gray'), (STATUS_OFFLINE, _('Offline'), 'gray'),
@ -176,6 +177,7 @@ class DeviceStatusChoices(ChoiceSet):
(STATUS_FAILED, _('Failed'), 'red'), (STATUS_FAILED, _('Failed'), 'red'),
(STATUS_INVENTORY, _('Inventory'), 'purple'), (STATUS_INVENTORY, _('Inventory'), 'purple'),
(STATUS_DECOMMISSIONING, _('Decommissioning'), 'yellow'), (STATUS_DECOMMISSIONING, _('Decommissioning'), 'yellow'),
(STATUS_MAINTENANCE, _('Maintenance'), 'orange'),
] ]

View File

@ -1825,6 +1825,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
Manufacturer(name='Manufacturer 4', slug='manufacturer-4'),
) )
Manufacturer.objects.bulk_create(manufacturers) Manufacturer.objects.bulk_create(manufacturers)
@ -1832,6 +1833,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', is_full_depth=True), DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', is_full_depth=True),
DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', is_full_depth=True), DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', is_full_depth=True),
DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', is_full_depth=False), DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', is_full_depth=False),
DeviceType(manufacturer=manufacturers[3], model='Model 4', slug='model-4', is_full_depth=False),
) )
DeviceType.objects.bulk_create(device_types) DeviceType.objects.bulk_create(device_types)
@ -1839,6 +1841,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
DeviceRole(name='Device Role 1', slug='device-role-1'), DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'), DeviceRole(name='Device Role 2', slug='device-role-2'),
DeviceRole(name='Device Role 3', slug='device-role-3'), DeviceRole(name='Device Role 3', slug='device-role-3'),
DeviceRole(name='Device Role 4', slug='device-role-4'),
) )
DeviceRole.objects.bulk_create(roles) DeviceRole.objects.bulk_create(roles)
@ -1846,6 +1849,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Platform(name='Platform 1', slug='platform-1'), Platform(name='Platform 1', slug='platform-1'),
Platform(name='Platform 2', slug='platform-2'), Platform(name='Platform 2', slug='platform-2'),
Platform(name='Platform 3', slug='platform-3'), Platform(name='Platform 3', slug='platform-3'),
Platform(name='Platform 4', slug='platform-4'),
) )
Platform.objects.bulk_create(platforms) Platform.objects.bulk_create(platforms)
@ -1853,6 +1857,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Region(name='Region 1', slug='region-1'), Region(name='Region 1', slug='region-1'),
Region(name='Region 2', slug='region-2'), Region(name='Region 2', slug='region-2'),
Region(name='Region 3', slug='region-3'), Region(name='Region 3', slug='region-3'),
Region(name='Region 4', slug='region-4'),
) )
for region in regions: for region in regions:
region.save() region.save()
@ -1861,6 +1866,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
SiteGroup(name='Site Group 1', slug='site-group-1'), SiteGroup(name='Site Group 1', slug='site-group-1'),
SiteGroup(name='Site Group 2', slug='site-group-2'), SiteGroup(name='Site Group 2', slug='site-group-2'),
SiteGroup(name='Site Group 3', slug='site-group-3'), SiteGroup(name='Site Group 3', slug='site-group-3'),
SiteGroup(name='Site Group 4', slug='site-group-4'),
) )
for group in groups: for group in groups:
group.save() group.save()
@ -1869,6 +1875,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Site(name='Site 1', slug='site-1', region=regions[0], group=groups[0]), Site(name='Site 1', slug='site-1', region=regions[0], group=groups[0]),
Site(name='Site 2', slug='site-2', region=regions[1], group=groups[1]), Site(name='Site 2', slug='site-2', region=regions[1], group=groups[1]),
Site(name='Site 3', slug='site-3', region=regions[2], group=groups[2]), Site(name='Site 3', slug='site-3', region=regions[2], group=groups[2]),
Site(name='Site 4', slug='site-4', region=regions[3], group=groups[3]),
) )
Site.objects.bulk_create(sites) Site.objects.bulk_create(sites)
@ -1876,6 +1883,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Location(name='Location 1', slug='location-1', site=sites[0]), Location(name='Location 1', slug='location-1', site=sites[0]),
Location(name='Location 2', slug='location-2', site=sites[1]), Location(name='Location 2', slug='location-2', site=sites[1]),
Location(name='Location 3', slug='location-3', site=sites[2]), Location(name='Location 3', slug='location-3', site=sites[2]),
Location(name='Location 4', slug='location-4', site=sites[3]),
) )
for location in locations: for location in locations:
location.save() location.save()
@ -1884,6 +1892,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Rack(name='Rack 1', site=sites[0], location=locations[0]), Rack(name='Rack 1', site=sites[0], location=locations[0]),
Rack(name='Rack 2', site=sites[1], location=locations[1]), Rack(name='Rack 2', site=sites[1], location=locations[1]),
Rack(name='Rack 3', site=sites[2], location=locations[2]), Rack(name='Rack 3', site=sites[2], location=locations[2]),
Rack(name='Rack 4', site=sites[3], location=locations[3]),
) )
Rack.objects.bulk_create(racks) Rack.objects.bulk_create(racks)
@ -1892,6 +1901,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Cluster(name='Cluster 1', type=cluster_type), Cluster(name='Cluster 1', type=cluster_type),
Cluster(name='Cluster 2', type=cluster_type), Cluster(name='Cluster 2', type=cluster_type),
Cluster(name='Cluster 3', type=cluster_type), Cluster(name='Cluster 3', type=cluster_type),
Cluster(name='Cluster 4', type=cluster_type),
) )
Cluster.objects.bulk_create(clusters) Cluster.objects.bulk_create(clusters)
@ -1899,6 +1909,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
TenantGroup(name='Tenant group 1', slug='tenant-group-1'), TenantGroup(name='Tenant group 1', slug='tenant-group-1'),
TenantGroup(name='Tenant group 2', slug='tenant-group-2'), TenantGroup(name='Tenant group 2', slug='tenant-group-2'),
TenantGroup(name='Tenant group 3', slug='tenant-group-3'), TenantGroup(name='Tenant group 3', slug='tenant-group-3'),
TenantGroup(name='Tenant group 4', slug='tenant-group-4'),
) )
for tenantgroup in tenant_groups: for tenantgroup in tenant_groups:
tenantgroup.save() tenantgroup.save()
@ -1907,6 +1918,7 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]), Tenant(name='Tenant 1', slug='tenant-1', group=tenant_groups[0]),
Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]), Tenant(name='Tenant 2', slug='tenant-2', group=tenant_groups[1]),
Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]), Tenant(name='Tenant 3', slug='tenant-3', group=tenant_groups[2]),
Tenant(name='Tenant 4', slug='tenant-4', group=tenant_groups[4]),
) )
Tenant.objects.bulk_create(tenants) Tenant.objects.bulk_create(tenants)
@ -1971,6 +1983,26 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
cluster=clusters[2], cluster=clusters[2],
description='foobar3' description='foobar3'
), ),
Device(
name='Device 4',
device_type=device_types[3],
role=roles[3],
platform=platforms[3],
tenant=tenants[3],
serial='JKL',
asset_tag='1004',
site=sites[3],
location=locations[3],
rack=racks[3],
position=4,
face=DeviceFaceChoices.FACE_FRONT,
latitude=40,
longitude=40,
status=DeviceStatusChoices.STATUS_MAINTENANCE,
airflow=DeviceAirflowChoices.AIRFLOW_REAR_TO_FRONT,
cluster=clusters[3],
description='foobar4'
),
) )
Device.objects.bulk_create(devices) Device.objects.bulk_create(devices)
@ -2036,6 +2068,10 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'q': 'foobar1'} params = {'q': 'foobar1'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_q_maintenance(self):
params = {'q': 'foobar4'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_name(self): def test_name(self):
params = {'name': ['Device 1', 'Device 2']} params = {'name': ['Device 1', 'Device 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
@ -2143,10 +2179,14 @@ class DeviceTestCase(TestCase, ChangeLoggedFilterSetTests):
params = {'model': ['model-1', 'model-2']} params = {'model': ['model-1', 'model-2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_status(self): def test_status_active_and_staged(self):
params = {'status': [DeviceStatusChoices.STATUS_ACTIVE, DeviceStatusChoices.STATUS_STAGED]} params = {'status': [DeviceStatusChoices.STATUS_ACTIVE, DeviceStatusChoices.STATUS_STAGED]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_status_maintenance(self):
params = {'status': [DeviceStatusChoices.STATUS_MAINTENANCE]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_is_full_depth(self): def test_is_full_depth(self):
params = {'is_full_depth': 'true'} params = {'is_full_depth': 'true'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

View File

@ -50,6 +50,24 @@ class DeviceTestCase(TestCase):
self.assertTrue(form.is_valid()) self.assertTrue(form.is_valid())
self.assertTrue(form.save()) self.assertTrue(form.save())
def test_racked_device_maintenance_status(self):
form = DeviceForm(data={
'name': 'Maintenance Device',
'role': DeviceRole.objects.first().pk,
'tenant': None,
'manufacturer': Manufacturer.objects.first().pk,
'device_type': DeviceType.objects.first().pk,
'site': Site.objects.first().pk,
'rack': Rack.objects.first().pk,
'face': DeviceFaceChoices.FACE_FRONT,
'position': 3,
'platform': Platform.objects.first().pk,
'status': DeviceStatusChoices.STATUS_MAINTENANCE,
})
self.assertTrue(form.is_valid())
self.assertTrue(form.save())
def test_racked_device_occupied(self): def test_racked_device_occupied(self):
form = DeviceForm(data={ form = DeviceForm(data={
'name': 'test', 'name': 'test',

View File

@ -368,6 +368,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
ASN(asn=65001, rir=rir), ASN(asn=65001, rir=rir),
ASN(asn=65101, rir=rir), ASN(asn=65101, rir=rir),
ASN(asn=65201, rir=rir), ASN(asn=65201, rir=rir),
ASN(asn=65301, rir=rir),
) )
ASN.objects.bulk_create(asns) ASN.objects.bulk_create(asns)
@ -375,6 +376,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
Manufacturer(name='Manufacturer 1', slug='manufacturer-1'), Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
Manufacturer(name='Manufacturer 2', slug='manufacturer-2'), Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
Manufacturer(name='Manufacturer 3', slug='manufacturer-3'), Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
Manufacturer(name='Manufacturer 4', slug='manufacturer-4'),
) )
Manufacturer.objects.bulk_create(manufacturers) Manufacturer.objects.bulk_create(manufacturers)
@ -382,6 +384,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', is_full_depth=True), DeviceType(manufacturer=manufacturers[0], model='Model 1', slug='model-1', is_full_depth=True),
DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', is_full_depth=True), DeviceType(manufacturer=manufacturers[1], model='Model 2', slug='model-2', is_full_depth=True),
DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', is_full_depth=False), DeviceType(manufacturer=manufacturers[2], model='Model 3', slug='model-3', is_full_depth=False),
DeviceType(manufacturer=manufacturers[3], model='Model 4', slug='model-4', is_full_depth=False),
) )
DeviceType.objects.bulk_create(device_types) DeviceType.objects.bulk_create(device_types)
@ -389,6 +392,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
DeviceRole(name='Device Role 1', slug='device-role-1'), DeviceRole(name='Device Role 1', slug='device-role-1'),
DeviceRole(name='Device Role 2', slug='device-role-2'), DeviceRole(name='Device Role 2', slug='device-role-2'),
DeviceRole(name='Device Role 3', slug='device-role-3'), DeviceRole(name='Device Role 3', slug='device-role-3'),
DeviceRole(name='Device Role 4', slug='device-role-4'),
) )
DeviceRole.objects.bulk_create(roles) DeviceRole.objects.bulk_create(roles)
@ -396,6 +400,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
Platform(name='Platform 1', slug='platform-1'), Platform(name='Platform 1', slug='platform-1'),
Platform(name='Platform 2', slug='platform-2'), Platform(name='Platform 2', slug='platform-2'),
Platform(name='Platform 3', slug='platform-3'), Platform(name='Platform 3', slug='platform-3'),
Platform(name='Platform 4', slug='platform-4'),
) )
Platform.objects.bulk_create(platforms) Platform.objects.bulk_create(platforms)
@ -403,6 +408,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
Region(name='Region 1', slug='region-1'), Region(name='Region 1', slug='region-1'),
Region(name='Region 2', slug='region-2'), Region(name='Region 2', slug='region-2'),
Region(name='Region 3', slug='region-3'), Region(name='Region 3', slug='region-3'),
Region(name='Region 4', slug='region-4'),
) )
for region in regions: for region in regions:
region.save() region.save()
@ -411,25 +417,80 @@ class DynamicFilterLookupExpressionTest(TestCase):
Site(name='Site 1', slug='abc-site-1', region=regions[0]), Site(name='Site 1', slug='abc-site-1', region=regions[0]),
Site(name='Site 2', slug='def-site-2', region=regions[1]), Site(name='Site 2', slug='def-site-2', region=regions[1]),
Site(name='Site 3', slug='ghi-site-3', region=regions[2]), Site(name='Site 3', slug='ghi-site-3', region=regions[2]),
Site(name='Site 4', slug='jkl-site-4', region=regions[3]),
) )
Site.objects.bulk_create(sites) Site.objects.bulk_create(sites)
asns[0].sites.add(sites[0]) asns[0].sites.add(sites[0])
asns[1].sites.add(sites[1]) asns[1].sites.add(sites[1])
asns[2].sites.add(sites[2]) asns[2].sites.add(sites[2])
asns[3].sites.add(sites[3])
racks = ( racks = (
Rack(name='Rack 1', site=sites[0]), Rack(name='Rack 1', site=sites[0]),
Rack(name='Rack 2', site=sites[1]), Rack(name='Rack 2', site=sites[1]),
Rack(name='Rack 3', site=sites[2]), Rack(name='Rack 3', site=sites[2]),
Rack(name='Rack 4', site=sites[3]),
) )
Rack.objects.bulk_create(racks) Rack.objects.bulk_create(racks)
# Assemble the tuple of devices to be created in bulk.
devices = ( devices = (
Device(name='Device 1', device_type=device_types[0], role=roles[0], platform=platforms[0], serial='ABC', asset_tag='1001', site=sites[0], rack=racks[0], position=1, face=DeviceFaceChoices.FACE_FRONT, status=DeviceStatusChoices.STATUS_ACTIVE, local_context_data={"foo": 123}), Device(
Device(name='Device 2', device_type=device_types[1], role=roles[1], platform=platforms[1], serial='DEF', asset_tag='1002', site=sites[1], rack=racks[1], position=2, face=DeviceFaceChoices.FACE_FRONT, status=DeviceStatusChoices.STATUS_STAGED), name='Device 1',
Device(name='Device 3', device_type=device_types[2], role=roles[2], platform=platforms[2], serial='GHI', asset_tag='1003', site=sites[2], rack=racks[2], position=3, face=DeviceFaceChoices.FACE_REAR, status=DeviceStatusChoices.STATUS_FAILED), device_type=device_types[0],
role=roles[0],
platform=platforms[0],
serial='ABC',
asset_tag='1001',
site=sites[0],
rack=racks[0],
position=1,
face=DeviceFaceChoices.FACE_FRONT,
status=DeviceStatusChoices.STATUS_ACTIVE,
local_context_data={"foo": 123},
),
Device(
name='Device 2',
device_type=device_types[1],
role=roles[1],
platform=platforms[1],
serial='DEF',
asset_tag='1002',
site=sites[1],
rack=racks[1],
position=2,
face=DeviceFaceChoices.FACE_FRONT,
status=DeviceStatusChoices.STATUS_STAGED,
),
Device(
name='Device 3',
device_type=device_types[2],
role=roles[2],
platform=platforms[2],
serial='GHI',
asset_tag='1003',
site=sites[2],
rack=racks[2],
position=3,
face=DeviceFaceChoices.FACE_REAR,
status=DeviceStatusChoices.STATUS_FAILED,
),
Device(
name='Device 4',
device_type=device_types[3],
role=roles[3],
platform=platforms[3],
serial='JKL',
asset_tag='1004',
site=sites[3],
rack=racks[3],
position=4,
face=DeviceFaceChoices.FACE_REAR,
status=DeviceStatusChoices.STATUS_MAINTENANCE,
),
) )
Device.objects.bulk_create(devices) Device.objects.bulk_create(devices)
interfaces = ( interfaces = (
@ -439,6 +500,9 @@ class DynamicFilterLookupExpressionTest(TestCase):
Interface(device=devices[1], name='Interface 4', mac_address='bb-00-00-00-00-02'), Interface(device=devices[1], name='Interface 4', mac_address='bb-00-00-00-00-02'),
Interface(device=devices[2], name='Interface 5', mac_address='00-00-00-00-00-03'), Interface(device=devices[2], name='Interface 5', mac_address='00-00-00-00-00-03'),
Interface(device=devices[2], name='Interface 6', mac_address='cc-00-00-00-00-03'), Interface(device=devices[2], name='Interface 6', mac_address='cc-00-00-00-00-03'),
Interface(device=devices[3], name='Interface 7', mac_address='00-00-00-00-00-04'),
Interface(device=devices[3], name='Interface 8', mac_address='cc-00-00-00-00-04'),
) )
Interface.objects.bulk_create(interfaces) Interface.objects.bulk_create(interfaces)
@ -504,7 +568,7 @@ class DynamicFilterLookupExpressionTest(TestCase):
def test_device_name_startswith(self): def test_device_name_startswith(self):
params = {'name__isw': ['Device']} params = {'name__isw': ['Device']}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 3) self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 4)
def test_device_name_startswith_negation(self): def test_device_name_startswith_negation(self):
params = {'name__nisw': ['Device 1']} params = {'name__nisw': ['Device 1']}
@ -553,3 +617,19 @@ class DynamicFilterLookupExpressionTest(TestCase):
def test_device_mac_address_icontains_negation(self): def test_device_mac_address_icontains_negation(self):
params = {'mac_address__nic': ['aa:', 'bb']} params = {'mac_address__nic': ['aa:', 'bb']}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 1) self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 1)
def test_device_status_negation_active(self):
params = {'status__n': 'active'}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 3)
def test_device_status_negation_maintenance(self):
params = {'status__n': 'maintenance'}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 3)
def test_device_status_active(self):
params = {'status': 'active'}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 1)
def test_device_status_maintenance(self):
params = {'status': 'maintenance'}
self.assertEqual(DeviceFilterSet(params, Device.objects.all()).qs.count(), 1)