test_models.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. from django.core.exceptions import ValidationError
  2. from django.test import TestCase
  3. from circuits.models import *
  4. from core.models import ObjectType
  5. from dcim.choices import *
  6. from dcim.models import *
  7. from extras.models import CustomField
  8. from tenancy.models import Tenant
  9. from utilities.data import drange
  10. class LocationTestCase(TestCase):
  11. def test_change_location_site(self):
  12. """
  13. Check that all child Locations and Racks get updated when a Location is moved to a new Site. Topology:
  14. Site A
  15. - Location A1
  16. - Location A2
  17. - Rack 2
  18. - Device 2
  19. - Rack 1
  20. - Device 1
  21. """
  22. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  23. device_type = DeviceType.objects.create(
  24. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  25. )
  26. role = DeviceRole.objects.create(
  27. name='Device Role 1', slug='device-role-1', color='ff0000'
  28. )
  29. site_a = Site.objects.create(name='Site A', slug='site-a')
  30. site_b = Site.objects.create(name='Site B', slug='site-b')
  31. location_a1 = Location(site=site_a, name='Location A1', slug='location-a1')
  32. location_a1.save()
  33. location_a2 = Location(site=site_a, parent=location_a1, name='Location A2', slug='location-a2')
  34. location_a2.save()
  35. rack1 = Rack.objects.create(site=site_a, location=location_a1, name='Rack 1')
  36. rack2 = Rack.objects.create(site=site_a, location=location_a2, name='Rack 2')
  37. device1 = Device.objects.create(
  38. site=site_a,
  39. location=location_a1,
  40. name='Device 1',
  41. device_type=device_type,
  42. role=role
  43. )
  44. device2 = Device.objects.create(
  45. site=site_a,
  46. location=location_a2,
  47. name='Device 2',
  48. device_type=device_type,
  49. role=role
  50. )
  51. powerpanel1 = PowerPanel.objects.create(site=site_a, location=location_a1, name='Power Panel 1')
  52. # Move Location A1 to Site B
  53. location_a1.site = site_b
  54. location_a1.save()
  55. # Check that all objects within Location A1 now belong to Site B
  56. self.assertEqual(Location.objects.get(pk=location_a1.pk).site, site_b)
  57. self.assertEqual(Location.objects.get(pk=location_a2.pk).site, site_b)
  58. self.assertEqual(Rack.objects.get(pk=rack1.pk).site, site_b)
  59. self.assertEqual(Rack.objects.get(pk=rack2.pk).site, site_b)
  60. self.assertEqual(Device.objects.get(pk=device1.pk).site, site_b)
  61. self.assertEqual(Device.objects.get(pk=device2.pk).site, site_b)
  62. self.assertEqual(PowerPanel.objects.get(pk=powerpanel1.pk).site, site_b)
  63. class RackTestCase(TestCase):
  64. @classmethod
  65. def setUpTestData(cls):
  66. sites = (
  67. Site(name='Site 1', slug='site-1'),
  68. Site(name='Site 2', slug='site-2'),
  69. )
  70. Site.objects.bulk_create(sites)
  71. locations = (
  72. Location(name='Location 1', slug='location-1', site=sites[0]),
  73. Location(name='Location 2', slug='location-2', site=sites[1]),
  74. )
  75. for location in locations:
  76. location.save()
  77. Rack.objects.create(
  78. name='Rack 1',
  79. facility_id='A101',
  80. site=sites[0],
  81. location=locations[0],
  82. u_height=42
  83. )
  84. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  85. device_types = (
  86. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1', u_height=1),
  87. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2', u_height=0),
  88. DeviceType(manufacturer=manufacturer, model='Device Type 3', slug='device-type-3', u_height=0.5),
  89. )
  90. DeviceType.objects.bulk_create(device_types)
  91. DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  92. def test_rack_device_outside_height(self):
  93. site = Site.objects.first()
  94. rack = Rack.objects.first()
  95. device1 = Device(
  96. name='Device 1',
  97. device_type=DeviceType.objects.first(),
  98. role=DeviceRole.objects.first(),
  99. site=site,
  100. rack=rack,
  101. position=43,
  102. face=DeviceFaceChoices.FACE_FRONT,
  103. )
  104. device1.save()
  105. with self.assertRaises(ValidationError):
  106. rack.clean()
  107. def test_location_site(self):
  108. site1 = Site.objects.get(name='Site 1')
  109. location2 = Location.objects.get(name='Location 2')
  110. rack2 = Rack(
  111. name='Rack 2',
  112. site=site1,
  113. location=location2,
  114. u_height=42
  115. )
  116. rack2.save()
  117. with self.assertRaises(ValidationError):
  118. rack2.clean()
  119. def test_mount_single_device(self):
  120. site = Site.objects.first()
  121. rack = Rack.objects.first()
  122. device1 = Device(
  123. name='TestSwitch1',
  124. device_type=DeviceType.objects.first(),
  125. role=DeviceRole.objects.first(),
  126. site=site,
  127. rack=rack,
  128. position=10.0,
  129. face=DeviceFaceChoices.FACE_REAR,
  130. )
  131. device1.save()
  132. # Validate rack height
  133. self.assertEqual(list(rack.units), list(drange(42.5, 0.5, -0.5)))
  134. # Validate inventory (front face)
  135. rack1_inventory_front = {
  136. u['id']: u for u in rack.get_rack_units(face=DeviceFaceChoices.FACE_FRONT)
  137. }
  138. self.assertEqual(rack1_inventory_front[10.0]['device'], device1)
  139. self.assertEqual(rack1_inventory_front[10.5]['device'], device1)
  140. del rack1_inventory_front[10.0]
  141. del rack1_inventory_front[10.5]
  142. for u in rack1_inventory_front.values():
  143. self.assertIsNone(u['device'])
  144. # Validate inventory (rear face)
  145. rack1_inventory_rear = {
  146. u['id']: u for u in rack.get_rack_units(face=DeviceFaceChoices.FACE_REAR)
  147. }
  148. self.assertEqual(rack1_inventory_rear[10.0]['device'], device1)
  149. self.assertEqual(rack1_inventory_rear[10.5]['device'], device1)
  150. del rack1_inventory_rear[10.0]
  151. del rack1_inventory_rear[10.5]
  152. for u in rack1_inventory_rear.values():
  153. self.assertIsNone(u['device'])
  154. def test_mount_zero_ru(self):
  155. """
  156. Check that a 0RU device can be mounted in a rack with no face/position.
  157. """
  158. site = Site.objects.first()
  159. rack = Rack.objects.first()
  160. Device(
  161. name='Device 1',
  162. role=DeviceRole.objects.first(),
  163. device_type=DeviceType.objects.first(),
  164. site=site,
  165. rack=rack
  166. ).save()
  167. def test_mount_half_u_devices(self):
  168. """
  169. Check that two 0.5U devices can be mounted in the same rack unit.
  170. """
  171. rack = Rack.objects.first()
  172. attrs = {
  173. 'device_type': DeviceType.objects.get(u_height=0.5),
  174. 'role': DeviceRole.objects.first(),
  175. 'site': Site.objects.first(),
  176. 'rack': rack,
  177. 'face': DeviceFaceChoices.FACE_FRONT,
  178. }
  179. Device(name='Device 1', position=1, **attrs).save()
  180. Device(name='Device 2', position=1.5, **attrs).save()
  181. self.assertEqual(len(rack.get_available_units()), rack.u_height * 2 - 3)
  182. def test_change_rack_site(self):
  183. """
  184. Check that child Devices get updated when a Rack is moved to a new Site.
  185. """
  186. site_a = Site.objects.create(name='Site A', slug='site-a')
  187. site_b = Site.objects.create(name='Site B', slug='site-b')
  188. # Create Rack1 in Site A
  189. rack1 = Rack.objects.create(site=site_a, name='Rack 1')
  190. # Create Device1 in Rack1
  191. device1 = Device.objects.create(
  192. site=site_a,
  193. rack=rack1,
  194. device_type=DeviceType.objects.first(),
  195. role=DeviceRole.objects.first()
  196. )
  197. # Move Rack1 to Site B
  198. rack1.site = site_b
  199. rack1.save()
  200. # Check that Device1 is now assigned to Site B
  201. self.assertEqual(Device.objects.get(pk=device1.pk).site, site_b)
  202. def test_utilization(self):
  203. site = Site.objects.first()
  204. rack = Rack.objects.first()
  205. Device(
  206. name='Device 1',
  207. role=DeviceRole.objects.first(),
  208. device_type=DeviceType.objects.first(),
  209. site=site,
  210. rack=rack,
  211. position=1
  212. ).save()
  213. rack.refresh_from_db()
  214. self.assertEqual(rack.get_utilization(), 1 / 42 * 100)
  215. # create device excluded from utilization calculations
  216. dt = DeviceType.objects.create(
  217. manufacturer=Manufacturer.objects.first(),
  218. model='Device Type 4',
  219. slug='device-type-4',
  220. u_height=1,
  221. exclude_from_utilization=True
  222. )
  223. Device(
  224. name='Device 2',
  225. role=DeviceRole.objects.first(),
  226. device_type=dt,
  227. site=site,
  228. rack=rack,
  229. position=5
  230. ).save()
  231. rack.refresh_from_db()
  232. self.assertEqual(rack.get_utilization(), 1 / 42 * 100)
  233. class DeviceTestCase(TestCase):
  234. @classmethod
  235. def setUpTestData(cls):
  236. Site.objects.create(name='Test Site 1', slug='test-site-1')
  237. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  238. device_type = DeviceType.objects.create(
  239. manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
  240. )
  241. roles = (
  242. DeviceRole(name='Test Role 1', slug='test-role-1'),
  243. DeviceRole(name='Test Role 2', slug='test-role-2'),
  244. )
  245. DeviceRole.objects.bulk_create(roles)
  246. # Create a CustomField with a default value & assign it to all component models
  247. cf1 = CustomField.objects.create(name='cf1', default='foo')
  248. cf1.object_types.set(
  249. ObjectType.objects.filter(app_label='dcim', model__in=[
  250. 'consoleport',
  251. 'consoleserverport',
  252. 'powerport',
  253. 'poweroutlet',
  254. 'interface',
  255. 'rearport',
  256. 'frontport',
  257. 'modulebay',
  258. 'devicebay',
  259. 'inventoryitem',
  260. ])
  261. )
  262. # Create DeviceType components
  263. ConsolePortTemplate(
  264. device_type=device_type,
  265. name='Console Port 1'
  266. ).save()
  267. ConsoleServerPortTemplate(
  268. device_type=device_type,
  269. name='Console Server Port 1'
  270. ).save()
  271. powerport = PowerPortTemplate(
  272. device_type=device_type,
  273. name='Power Port 1',
  274. maximum_draw=1000,
  275. allocated_draw=500
  276. )
  277. powerport.save()
  278. PowerOutletTemplate(
  279. device_type=device_type,
  280. name='Power Outlet 1',
  281. power_port=powerport,
  282. feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A
  283. ).save()
  284. InterfaceTemplate(
  285. device_type=device_type,
  286. name='Interface 1',
  287. type=InterfaceTypeChoices.TYPE_1GE_FIXED,
  288. mgmt_only=True
  289. ).save()
  290. rearport = RearPortTemplate(
  291. device_type=device_type,
  292. name='Rear Port 1',
  293. type=PortTypeChoices.TYPE_8P8C,
  294. positions=8
  295. )
  296. rearport.save()
  297. FrontPortTemplate(
  298. device_type=device_type,
  299. name='Front Port 1',
  300. type=PortTypeChoices.TYPE_8P8C,
  301. rear_port=rearport,
  302. rear_port_position=2
  303. ).save()
  304. ModuleBayTemplate(
  305. device_type=device_type,
  306. name='Module Bay 1'
  307. ).save()
  308. DeviceBayTemplate(
  309. device_type=device_type,
  310. name='Device Bay 1'
  311. ).save()
  312. InventoryItemTemplate(
  313. device_type=device_type,
  314. name='Inventory Item 1'
  315. ).save()
  316. def test_device_creation(self):
  317. """
  318. Ensure that all Device components are copied automatically from the DeviceType.
  319. """
  320. device = Device(
  321. site=Site.objects.first(),
  322. device_type=DeviceType.objects.first(),
  323. role=DeviceRole.objects.first(),
  324. name='Test Device 1'
  325. )
  326. device.save()
  327. consoleport = ConsolePort.objects.get(
  328. device=device,
  329. name='Console Port 1'
  330. )
  331. self.assertEqual(consoleport.cf['cf1'], 'foo')
  332. consoleserverport = ConsoleServerPort.objects.get(
  333. device=device,
  334. name='Console Server Port 1'
  335. )
  336. self.assertEqual(consoleserverport.cf['cf1'], 'foo')
  337. powerport = PowerPort.objects.get(
  338. device=device,
  339. name='Power Port 1',
  340. maximum_draw=1000,
  341. allocated_draw=500
  342. )
  343. self.assertEqual(powerport.cf['cf1'], 'foo')
  344. poweroutlet = PowerOutlet.objects.get(
  345. device=device,
  346. name='Power Outlet 1',
  347. power_port=powerport,
  348. feed_leg=PowerOutletFeedLegChoices.FEED_LEG_A
  349. )
  350. self.assertEqual(poweroutlet.cf['cf1'], 'foo')
  351. interface = Interface.objects.get(
  352. device=device,
  353. name='Interface 1',
  354. type=InterfaceTypeChoices.TYPE_1GE_FIXED,
  355. mgmt_only=True
  356. )
  357. self.assertEqual(interface.cf['cf1'], 'foo')
  358. rearport = RearPort.objects.get(
  359. device=device,
  360. name='Rear Port 1',
  361. type=PortTypeChoices.TYPE_8P8C,
  362. positions=8
  363. )
  364. self.assertEqual(rearport.cf['cf1'], 'foo')
  365. frontport = FrontPort.objects.get(
  366. device=device,
  367. name='Front Port 1',
  368. type=PortTypeChoices.TYPE_8P8C,
  369. rear_port=rearport,
  370. rear_port_position=2
  371. )
  372. self.assertEqual(frontport.cf['cf1'], 'foo')
  373. modulebay = ModuleBay.objects.get(
  374. device=device,
  375. name='Module Bay 1'
  376. )
  377. self.assertEqual(modulebay.cf['cf1'], 'foo')
  378. devicebay = DeviceBay.objects.get(
  379. device=device,
  380. name='Device Bay 1'
  381. )
  382. self.assertEqual(devicebay.cf['cf1'], 'foo')
  383. inventoryitem = InventoryItem.objects.get(
  384. device=device,
  385. name='Inventory Item 1'
  386. )
  387. self.assertEqual(inventoryitem.cf['cf1'], 'foo')
  388. def test_multiple_unnamed_devices(self):
  389. device1 = Device(
  390. site=Site.objects.first(),
  391. device_type=DeviceType.objects.first(),
  392. role=DeviceRole.objects.first(),
  393. name=None
  394. )
  395. device1.save()
  396. device2 = Device(
  397. site=device1.site,
  398. device_type=device1.device_type,
  399. role=device1.role,
  400. name=None
  401. )
  402. device2.full_clean()
  403. device2.save()
  404. self.assertEqual(Device.objects.filter(name__isnull=True).count(), 2)
  405. def test_device_name_case_sensitivity(self):
  406. device1 = Device(
  407. site=Site.objects.first(),
  408. device_type=DeviceType.objects.first(),
  409. role=DeviceRole.objects.first(),
  410. name='device 1'
  411. )
  412. device1.save()
  413. device2 = Device(
  414. site=device1.site,
  415. device_type=device1.device_type,
  416. role=device1.role,
  417. name='DEVICE 1'
  418. )
  419. # Uniqueness validation for name should ignore case
  420. with self.assertRaises(ValidationError):
  421. device2.full_clean()
  422. def test_device_duplicate_names(self):
  423. device1 = Device(
  424. site=Site.objects.first(),
  425. device_type=DeviceType.objects.first(),
  426. role=DeviceRole.objects.first(),
  427. name='Test Device 1'
  428. )
  429. device1.save()
  430. device2 = Device(
  431. site=device1.site,
  432. device_type=device1.device_type,
  433. role=device1.role,
  434. name=device1.name
  435. )
  436. # Two devices assigned to the same Site and no Tenant should fail validation
  437. with self.assertRaises(ValidationError):
  438. device2.full_clean()
  439. tenant = Tenant.objects.create(name='Test Tenant 1', slug='test-tenant-1')
  440. device1.tenant = tenant
  441. device1.save()
  442. device2.tenant = tenant
  443. # Two devices assigned to the same Site and the same Tenant should fail validation
  444. with self.assertRaises(ValidationError):
  445. device2.full_clean()
  446. device2.tenant = None
  447. # Two devices assigned to the same Site and different Tenants should pass validation
  448. device2.full_clean()
  449. device2.save()
  450. class CableTestCase(TestCase):
  451. @classmethod
  452. def setUpTestData(cls):
  453. site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  454. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  455. devicetype = DeviceType.objects.create(
  456. manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
  457. )
  458. role = DeviceRole.objects.create(
  459. name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
  460. )
  461. device1 = Device.objects.create(
  462. device_type=devicetype, role=role, name='TestDevice1', site=site
  463. )
  464. device2 = Device.objects.create(
  465. device_type=devicetype, role=role, name='TestDevice2', site=site
  466. )
  467. interface1 = Interface.objects.create(device=device1, name='eth0')
  468. interface2 = Interface.objects.create(device=device2, name='eth0')
  469. interface3 = Interface.objects.create(device=device2, name='eth1')
  470. Cable(a_terminations=[interface1], b_terminations=[interface2]).save()
  471. power_port1 = PowerPort.objects.create(device=device2, name='psu1')
  472. patch_pannel = Device.objects.create(
  473. device_type=devicetype, role=role, name='TestPatchPanel', site=site
  474. )
  475. rear_port1 = RearPort.objects.create(device=patch_pannel, name='RP1', type='8p8c')
  476. front_port1 = FrontPort.objects.create(
  477. device=patch_pannel, name='FP1', type='8p8c', rear_port=rear_port1, rear_port_position=1
  478. )
  479. rear_port2 = RearPort.objects.create(device=patch_pannel, name='RP2', type='8p8c', positions=2)
  480. front_port2 = FrontPort.objects.create(
  481. device=patch_pannel, name='FP2', type='8p8c', rear_port=rear_port2, rear_port_position=1
  482. )
  483. rear_port3 = RearPort.objects.create(device=patch_pannel, name='RP3', type='8p8c', positions=3)
  484. front_port3 = FrontPort.objects.create(
  485. device=patch_pannel, name='FP3', type='8p8c', rear_port=rear_port3, rear_port_position=1
  486. )
  487. rear_port4 = RearPort.objects.create(device=patch_pannel, name='RP4', type='8p8c', positions=3)
  488. front_port4 = FrontPort.objects.create(
  489. device=patch_pannel, name='FP4', type='8p8c', rear_port=rear_port4, rear_port_position=1
  490. )
  491. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  492. provider_network = ProviderNetwork.objects.create(name='Provider Network 1', provider=provider)
  493. circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  494. circuit1 = Circuit.objects.create(provider=provider, type=circuittype, cid='1')
  495. circuit2 = Circuit.objects.create(provider=provider, type=circuittype, cid='2')
  496. circuittermination1 = CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='A')
  497. circuittermination2 = CircuitTermination.objects.create(circuit=circuit1, site=site, term_side='Z')
  498. circuittermination3 = CircuitTermination.objects.create(circuit=circuit2, provider_network=provider_network, term_side='A')
  499. def test_cable_creation(self):
  500. """
  501. When a new Cable is created, it must be cached on either termination point.
  502. """
  503. interface1 = Interface.objects.get(device__name='TestDevice1', name='eth0')
  504. interface2 = Interface.objects.get(device__name='TestDevice2', name='eth0')
  505. cable = Cable.objects.first()
  506. self.assertEqual(interface1.cable, cable)
  507. self.assertEqual(interface2.cable, cable)
  508. self.assertEqual(interface1.cable_end, 'A')
  509. self.assertEqual(interface2.cable_end, 'B')
  510. self.assertEqual(interface1.link_peers, [interface2])
  511. self.assertEqual(interface2.link_peers, [interface1])
  512. def test_cable_deletion(self):
  513. """
  514. When a Cable is deleted, the `cable` field on its termination points must be nullified. The str() method
  515. should still return the PK of the string even after being nullified.
  516. """
  517. interface1 = Interface.objects.get(device__name='TestDevice1', name='eth0')
  518. interface2 = Interface.objects.get(device__name='TestDevice2', name='eth0')
  519. cable = Cable.objects.first()
  520. cable.delete()
  521. self.assertIsNone(cable.pk)
  522. self.assertNotEqual(str(cable), '#None')
  523. interface1 = Interface.objects.get(pk=interface1.pk)
  524. self.assertIsNone(interface1.cable)
  525. self.assertListEqual(interface1.link_peers, [])
  526. interface2 = Interface.objects.get(pk=interface2.pk)
  527. self.assertIsNone(interface2.cable)
  528. self.assertListEqual(interface2.link_peers, [])
  529. def test_cable_validates_same_parent_object(self):
  530. """
  531. The clean method should ensure that all terminations at either end of a Cable belong to the same parent object.
  532. """
  533. interface1 = Interface.objects.get(device__name='TestDevice1', name='eth0')
  534. powerport1 = PowerPort.objects.get(device__name='TestDevice2', name='psu1')
  535. cable = Cable(a_terminations=[interface1], b_terminations=[powerport1])
  536. with self.assertRaises(ValidationError):
  537. cable.clean()
  538. def test_cable_validates_same_type(self):
  539. """
  540. The clean method should ensure that all terminations at either end of a Cable are of the same type.
  541. """
  542. interface1 = Interface.objects.get(device__name='TestDevice1', name='eth0')
  543. frontport1 = FrontPort.objects.get(device__name='TestPatchPanel', name='FP1')
  544. rearport1 = RearPort.objects.get(device__name='TestPatchPanel', name='RP1')
  545. cable = Cable(a_terminations=[frontport1, rearport1], b_terminations=[interface1])
  546. with self.assertRaises(ValidationError):
  547. cable.clean()
  548. def test_cable_validates_compatible_types(self):
  549. """
  550. The clean method should have a check to ensure only compatible port types can be connected by a cable
  551. """
  552. interface1 = Interface.objects.get(device__name='TestDevice1', name='eth0')
  553. powerport1 = PowerPort.objects.get(device__name='TestDevice2', name='psu1')
  554. # An interface cannot be connected to a power port, for example
  555. cable = Cable(a_terminations=[interface1], b_terminations=[powerport1])
  556. with self.assertRaises(ValidationError):
  557. cable.clean()
  558. def test_cable_cannot_terminate_to_a_provider_network_circuittermination(self):
  559. """
  560. Neither side of a cable can be terminated to a CircuitTermination which is attached to a ProviderNetwork
  561. """
  562. interface3 = Interface.objects.get(device__name='TestDevice2', name='eth1')
  563. circuittermination3 = CircuitTermination.objects.get(circuit__cid='2', term_side='A')
  564. cable = Cable(a_terminations=[interface3], b_terminations=[circuittermination3])
  565. with self.assertRaises(ValidationError):
  566. cable.clean()
  567. def test_cable_cannot_terminate_to_a_virtual_interface(self):
  568. """
  569. A cable cannot terminate to a virtual interface
  570. """
  571. device1 = Device.objects.get(name='TestDevice1')
  572. interface2 = Interface.objects.get(device__name='TestDevice2', name='eth0')
  573. virtual_interface = Interface(device=device1, name="V1", type=InterfaceTypeChoices.TYPE_VIRTUAL)
  574. cable = Cable(a_terminations=[interface2], b_terminations=[virtual_interface])
  575. with self.assertRaises(ValidationError):
  576. cable.clean()
  577. def test_cable_cannot_terminate_to_a_wireless_interface(self):
  578. """
  579. A cable cannot terminate to a wireless interface
  580. """
  581. device1 = Device.objects.get(name='TestDevice1')
  582. interface2 = Interface.objects.get(device__name='TestDevice2', name='eth0')
  583. wireless_interface = Interface(device=device1, name="W1", type=InterfaceTypeChoices.TYPE_80211A)
  584. cable = Cable(a_terminations=[interface2], b_terminations=[wireless_interface])
  585. with self.assertRaises(ValidationError):
  586. cable.clean()
  587. class VirtualDeviceContextTestCase(TestCase):
  588. @classmethod
  589. def setUpTestData(cls):
  590. site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  591. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  592. devicetype = DeviceType.objects.create(
  593. manufacturer=manufacturer, model='Test Device Type 1', slug='test-device-type-1'
  594. )
  595. role = DeviceRole.objects.create(
  596. name='Test Device Role 1', slug='test-device-role-1', color='ff0000'
  597. )
  598. Device.objects.create(
  599. device_type=devicetype, role=role, name='TestDevice1', site=site
  600. )
  601. def test_vdc_and_interface_creation(self):
  602. device = Device.objects.first()
  603. vdc = VirtualDeviceContext(device=device, name="VDC 1", identifier=1, status='active')
  604. vdc.full_clean()
  605. vdc.save()
  606. interface = Interface(device=device, name='Eth1/1', type='10gbase-t')
  607. interface.full_clean()
  608. interface.save()
  609. interface.vdcs.set([vdc])
  610. def test_vdc_duplicate_name(self):
  611. device = Device.objects.first()
  612. vdc1 = VirtualDeviceContext(device=device, name="VDC 1", identifier=1, status='active')
  613. vdc1.full_clean()
  614. vdc1.save()
  615. vdc2 = VirtualDeviceContext(device=device, name="VDC 1", identifier=2, status='active')
  616. with self.assertRaises(ValidationError):
  617. vdc2.full_clean()
  618. def test_vdc_duplicate_identifier(self):
  619. device = Device.objects.first()
  620. vdc1 = VirtualDeviceContext(device=device, name="VDC 1", identifier=1, status='active')
  621. vdc1.full_clean()
  622. vdc1.save()
  623. vdc2 = VirtualDeviceContext(device=device, name="VDC 2", identifier=1, status='active')
  624. with self.assertRaises(ValidationError):
  625. vdc2.full_clean()