test_views.py 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861
  1. from decimal import Decimal
  2. import pytz
  3. import yaml
  4. from django.contrib.auth.models import User
  5. from django.contrib.contenttypes.models import ContentType
  6. from django.test import override_settings
  7. from django.urls import reverse
  8. from netaddr import EUI
  9. from dcim.choices import *
  10. from dcim.constants import *
  11. from dcim.models import *
  12. from ipam.models import VLAN
  13. from utilities.testing import ViewTestCases
  14. def create_test_device(name):
  15. """
  16. Convenience method for creating a Device (e.g. for component testing).
  17. """
  18. site, _ = Site.objects.get_or_create(name='Site 1', slug='site-1')
  19. manufacturer, _ = Manufacturer.objects.get_or_create(name='Manufacturer 1', slug='manufacturer-1')
  20. devicetype, _ = DeviceType.objects.get_or_create(model='Device Type 1', manufacturer=manufacturer)
  21. devicerole, _ = DeviceRole.objects.get_or_create(name='Device Role 1', slug='device-role-1')
  22. device = Device.objects.create(name=name, site=site, device_type=devicetype, device_role=devicerole)
  23. return device
  24. class RegionTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  25. model = Region
  26. @classmethod
  27. def setUpTestData(cls):
  28. # Create three Regions
  29. regions = (
  30. Region(name='Region 1', slug='region-1'),
  31. Region(name='Region 2', slug='region-2'),
  32. Region(name='Region 3', slug='region-3'),
  33. )
  34. for region in regions:
  35. region.save()
  36. cls.form_data = {
  37. 'name': 'Region X',
  38. 'slug': 'region-x',
  39. 'parent': regions[2].pk,
  40. 'description': 'A new region',
  41. }
  42. cls.csv_data = (
  43. "name,slug,description",
  44. "Region 4,region-4,Fourth region",
  45. "Region 5,region-5,Fifth region",
  46. "Region 6,region-6,Sixth region",
  47. )
  48. class SiteTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  49. model = Site
  50. @classmethod
  51. def setUpTestData(cls):
  52. regions = (
  53. Region(name='Region 1', slug='region-1'),
  54. Region(name='Region 2', slug='region-2'),
  55. )
  56. for region in regions:
  57. region.save()
  58. Site.objects.bulk_create([
  59. Site(name='Site 1', slug='site-1', region=regions[0]),
  60. Site(name='Site 2', slug='site-2', region=regions[0]),
  61. Site(name='Site 3', slug='site-3', region=regions[0]),
  62. ])
  63. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  64. cls.form_data = {
  65. 'name': 'Site X',
  66. 'slug': 'site-x',
  67. 'status': SiteStatusChoices.STATUS_PLANNED,
  68. 'region': regions[1].pk,
  69. 'tenant': None,
  70. 'facility': 'Facility X',
  71. 'asn': 65001,
  72. 'time_zone': pytz.UTC,
  73. 'description': 'Site description',
  74. 'physical_address': '742 Evergreen Terrace, Springfield, USA',
  75. 'shipping_address': '742 Evergreen Terrace, Springfield, USA',
  76. 'latitude': Decimal('35.780000'),
  77. 'longitude': Decimal('-78.642000'),
  78. 'contact_name': 'Hank Hill',
  79. 'contact_phone': '123-555-9999',
  80. 'contact_email': 'hank@stricklandpropane.com',
  81. 'comments': 'Test site',
  82. 'tags': [t.pk for t in tags],
  83. }
  84. cls.csv_data = (
  85. "name,slug,status",
  86. "Site 4,site-4,planned",
  87. "Site 5,site-5,active",
  88. "Site 6,site-6,staging",
  89. )
  90. cls.bulk_edit_data = {
  91. 'status': SiteStatusChoices.STATUS_PLANNED,
  92. 'region': regions[1].pk,
  93. 'tenant': None,
  94. 'asn': 65009,
  95. 'time_zone': pytz.timezone('US/Eastern'),
  96. 'description': 'New description',
  97. }
  98. class RackGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  99. model = RackGroup
  100. @classmethod
  101. def setUpTestData(cls):
  102. site = Site(name='Site 1', slug='site-1')
  103. site.save()
  104. rack_groups = (
  105. RackGroup(name='Rack Group 1', slug='rack-group-1', site=site),
  106. RackGroup(name='Rack Group 2', slug='rack-group-2', site=site),
  107. RackGroup(name='Rack Group 3', slug='rack-group-3', site=site),
  108. )
  109. for rackgroup in rack_groups:
  110. rackgroup.save()
  111. cls.form_data = {
  112. 'name': 'Rack Group X',
  113. 'slug': 'rack-group-x',
  114. 'site': site.pk,
  115. 'description': 'A new rack group',
  116. }
  117. cls.csv_data = (
  118. "site,name,slug,description",
  119. "Site 1,Rack Group 4,rack-group-4,Fourth rack group",
  120. "Site 1,Rack Group 5,rack-group-5,Fifth rack group",
  121. "Site 1,Rack Group 6,rack-group-6,Sixth rack group",
  122. )
  123. class RackRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  124. model = RackRole
  125. @classmethod
  126. def setUpTestData(cls):
  127. RackRole.objects.bulk_create([
  128. RackRole(name='Rack Role 1', slug='rack-role-1'),
  129. RackRole(name='Rack Role 2', slug='rack-role-2'),
  130. RackRole(name='Rack Role 3', slug='rack-role-3'),
  131. ])
  132. cls.form_data = {
  133. 'name': 'Rack Role X',
  134. 'slug': 'rack-role-x',
  135. 'color': 'c0c0c0',
  136. 'description': 'New role',
  137. }
  138. cls.csv_data = (
  139. "name,slug,color",
  140. "Rack Role 4,rack-role-4,ff0000",
  141. "Rack Role 5,rack-role-5,00ff00",
  142. "Rack Role 6,rack-role-6,0000ff",
  143. )
  144. class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  145. model = RackReservation
  146. @classmethod
  147. def setUpTestData(cls):
  148. user2 = User.objects.create_user(username='testuser2')
  149. user3 = User.objects.create_user(username='testuser3')
  150. site = Site.objects.create(name='Site 1', slug='site-1')
  151. rack_group = RackGroup(name='Rack Group 1', slug='rack-group-1', site=site)
  152. rack_group.save()
  153. rack = Rack(name='Rack 1', site=site, group=rack_group)
  154. rack.save()
  155. RackReservation.objects.bulk_create([
  156. RackReservation(rack=rack, user=user2, units=[1, 2, 3], description='Reservation 1'),
  157. RackReservation(rack=rack, user=user2, units=[4, 5, 6], description='Reservation 2'),
  158. RackReservation(rack=rack, user=user2, units=[7, 8, 9], description='Reservation 3'),
  159. ])
  160. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  161. cls.form_data = {
  162. 'rack': rack.pk,
  163. 'units': "10,11,12",
  164. 'user': user3.pk,
  165. 'tenant': None,
  166. 'description': 'Rack reservation',
  167. 'tags': [t.pk for t in tags],
  168. }
  169. cls.csv_data = (
  170. 'site,rack_group,rack,units,description',
  171. 'Site 1,Rack Group 1,Rack 1,"10,11,12",Reservation 1',
  172. 'Site 1,Rack Group 1,Rack 1,"13,14,15",Reservation 2',
  173. 'Site 1,Rack Group 1,Rack 1,"16,17,18",Reservation 3',
  174. )
  175. cls.bulk_edit_data = {
  176. 'user': user3.pk,
  177. 'tenant': None,
  178. 'description': 'New description',
  179. }
  180. class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  181. model = Rack
  182. @classmethod
  183. def setUpTestData(cls):
  184. sites = (
  185. Site(name='Site 1', slug='site-1'),
  186. Site(name='Site 2', slug='site-2'),
  187. )
  188. Site.objects.bulk_create(sites)
  189. rackgroups = (
  190. RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]),
  191. RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1])
  192. )
  193. for rackgroup in rackgroups:
  194. rackgroup.save()
  195. rackroles = (
  196. RackRole(name='Rack Role 1', slug='rack-role-1'),
  197. RackRole(name='Rack Role 2', slug='rack-role-2'),
  198. )
  199. RackRole.objects.bulk_create(rackroles)
  200. Rack.objects.bulk_create((
  201. Rack(name='Rack 1', site=sites[0]),
  202. Rack(name='Rack 2', site=sites[0]),
  203. Rack(name='Rack 3', site=sites[0]),
  204. ))
  205. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  206. cls.form_data = {
  207. 'name': 'Rack X',
  208. 'facility_id': 'Facility X',
  209. 'site': sites[1].pk,
  210. 'group': rackgroups[1].pk,
  211. 'tenant': None,
  212. 'status': RackStatusChoices.STATUS_PLANNED,
  213. 'role': rackroles[1].pk,
  214. 'serial': '123456',
  215. 'asset_tag': 'ABCDEF',
  216. 'type': RackTypeChoices.TYPE_CABINET,
  217. 'width': RackWidthChoices.WIDTH_19IN,
  218. 'u_height': 48,
  219. 'desc_units': False,
  220. 'outer_width': 500,
  221. 'outer_depth': 500,
  222. 'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER,
  223. 'comments': 'Some comments',
  224. 'tags': [t.pk for t in tags],
  225. }
  226. cls.csv_data = (
  227. "site,group,name,width,u_height",
  228. "Site 1,,Rack 4,19,42",
  229. "Site 1,Rack Group 1,Rack 5,19,42",
  230. "Site 2,Rack Group 2,Rack 6,19,42",
  231. )
  232. cls.bulk_edit_data = {
  233. 'site': sites[1].pk,
  234. 'group': rackgroups[1].pk,
  235. 'tenant': None,
  236. 'status': RackStatusChoices.STATUS_DEPRECATED,
  237. 'role': rackroles[1].pk,
  238. 'serial': '654321',
  239. 'type': RackTypeChoices.TYPE_4POST,
  240. 'width': RackWidthChoices.WIDTH_23IN,
  241. 'u_height': 49,
  242. 'desc_units': True,
  243. 'outer_width': 30,
  244. 'outer_depth': 30,
  245. 'outer_unit': RackDimensionUnitChoices.UNIT_INCH,
  246. 'comments': 'New comments',
  247. }
  248. class ManufacturerTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  249. model = Manufacturer
  250. @classmethod
  251. def setUpTestData(cls):
  252. Manufacturer.objects.bulk_create([
  253. Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
  254. Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
  255. Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
  256. ])
  257. cls.form_data = {
  258. 'name': 'Manufacturer X',
  259. 'slug': 'manufacturer-x',
  260. 'description': 'A new manufacturer',
  261. }
  262. cls.csv_data = (
  263. "name,slug,description",
  264. "Manufacturer 4,manufacturer-4,Fourth manufacturer",
  265. "Manufacturer 5,manufacturer-5,Fifth manufacturer",
  266. "Manufacturer 6,manufacturer-6,Sixth manufacturer",
  267. )
  268. # TODO: Change base class to PrimaryObjectViewTestCase
  269. # Blocked by absence of bulk import view for DeviceTypes
  270. class DeviceTypeTestCase(
  271. ViewTestCases.GetObjectViewTestCase,
  272. ViewTestCases.GetObjectChangelogViewTestCase,
  273. ViewTestCases.CreateObjectViewTestCase,
  274. ViewTestCases.EditObjectViewTestCase,
  275. ViewTestCases.DeleteObjectViewTestCase,
  276. ViewTestCases.ListObjectsViewTestCase,
  277. ViewTestCases.BulkEditObjectsViewTestCase,
  278. ViewTestCases.BulkDeleteObjectsViewTestCase
  279. ):
  280. model = DeviceType
  281. @classmethod
  282. def setUpTestData(cls):
  283. manufacturers = (
  284. Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
  285. Manufacturer(name='Manufacturer 2', slug='manufacturer-2')
  286. )
  287. Manufacturer.objects.bulk_create(manufacturers)
  288. DeviceType.objects.bulk_create([
  289. DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturers[0]),
  290. DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturers[0]),
  291. DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturers[0]),
  292. ])
  293. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  294. cls.form_data = {
  295. 'manufacturer': manufacturers[1].pk,
  296. 'model': 'Device Type X',
  297. 'slug': 'device-type-x',
  298. 'part_number': '123ABC',
  299. 'u_height': 2,
  300. 'is_full_depth': True,
  301. 'subdevice_role': '', # CharField
  302. 'comments': 'Some comments',
  303. 'tags': [t.pk for t in tags],
  304. }
  305. cls.bulk_edit_data = {
  306. 'manufacturer': manufacturers[1].pk,
  307. 'u_height': 3,
  308. 'is_full_depth': False,
  309. }
  310. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  311. def test_import_objects(self):
  312. """
  313. Custom import test for YAML-based imports (versus CSV)
  314. """
  315. IMPORT_DATA = """
  316. manufacturer: Generic
  317. model: TEST-1000
  318. slug: test-1000
  319. u_height: 2
  320. comments: test comment
  321. console-ports:
  322. - name: Console Port 1
  323. type: de-9
  324. - name: Console Port 2
  325. type: de-9
  326. - name: Console Port 3
  327. type: de-9
  328. console-server-ports:
  329. - name: Console Server Port 1
  330. type: rj-45
  331. - name: Console Server Port 2
  332. type: rj-45
  333. - name: Console Server Port 3
  334. type: rj-45
  335. power-ports:
  336. - name: Power Port 1
  337. type: iec-60320-c14
  338. - name: Power Port 2
  339. type: iec-60320-c14
  340. - name: Power Port 3
  341. type: iec-60320-c14
  342. power-outlets:
  343. - name: Power Outlet 1
  344. type: iec-60320-c13
  345. power_port: Power Port 1
  346. feed_leg: A
  347. - name: Power Outlet 2
  348. type: iec-60320-c13
  349. power_port: Power Port 1
  350. feed_leg: A
  351. - name: Power Outlet 3
  352. type: iec-60320-c13
  353. power_port: Power Port 1
  354. feed_leg: A
  355. interfaces:
  356. - name: Interface 1
  357. type: 1000base-t
  358. mgmt_only: true
  359. - name: Interface 2
  360. type: 1000base-t
  361. - name: Interface 3
  362. type: 1000base-t
  363. rear-ports:
  364. - name: Rear Port 1
  365. type: 8p8c
  366. - name: Rear Port 2
  367. type: 8p8c
  368. - name: Rear Port 3
  369. type: 8p8c
  370. front-ports:
  371. - name: Front Port 1
  372. type: 8p8c
  373. rear_port: Rear Port 1
  374. - name: Front Port 2
  375. type: 8p8c
  376. rear_port: Rear Port 2
  377. - name: Front Port 3
  378. type: 8p8c
  379. rear_port: Rear Port 3
  380. device-bays:
  381. - name: Device Bay 1
  382. - name: Device Bay 2
  383. - name: Device Bay 3
  384. """
  385. # Create the manufacturer
  386. Manufacturer(name='Generic', slug='generic').save()
  387. # Add all required permissions to the test user
  388. self.add_permissions(
  389. 'dcim.view_devicetype',
  390. 'dcim.add_devicetype',
  391. 'dcim.add_consoleporttemplate',
  392. 'dcim.add_consoleserverporttemplate',
  393. 'dcim.add_powerporttemplate',
  394. 'dcim.add_poweroutlettemplate',
  395. 'dcim.add_interfacetemplate',
  396. 'dcim.add_frontporttemplate',
  397. 'dcim.add_rearporttemplate',
  398. 'dcim.add_devicebaytemplate',
  399. )
  400. form_data = {
  401. 'data': IMPORT_DATA,
  402. 'format': 'yaml'
  403. }
  404. response = self.client.post(reverse('dcim:devicetype_import'), data=form_data, follow=True)
  405. self.assertHttpStatus(response, 200)
  406. dt = DeviceType.objects.get(model='TEST-1000')
  407. self.assertEqual(dt.comments, 'test comment')
  408. # Verify all of the components were created
  409. self.assertEqual(dt.consoleporttemplates.count(), 3)
  410. cp1 = ConsolePortTemplate.objects.first()
  411. self.assertEqual(cp1.name, 'Console Port 1')
  412. self.assertEqual(cp1.type, ConsolePortTypeChoices.TYPE_DE9)
  413. self.assertEqual(dt.consoleserverporttemplates.count(), 3)
  414. csp1 = ConsoleServerPortTemplate.objects.first()
  415. self.assertEqual(csp1.name, 'Console Server Port 1')
  416. self.assertEqual(csp1.type, ConsolePortTypeChoices.TYPE_RJ45)
  417. self.assertEqual(dt.powerporttemplates.count(), 3)
  418. pp1 = PowerPortTemplate.objects.first()
  419. self.assertEqual(pp1.name, 'Power Port 1')
  420. self.assertEqual(pp1.type, PowerPortTypeChoices.TYPE_IEC_C14)
  421. self.assertEqual(dt.poweroutlettemplates.count(), 3)
  422. po1 = PowerOutletTemplate.objects.first()
  423. self.assertEqual(po1.name, 'Power Outlet 1')
  424. self.assertEqual(po1.type, PowerOutletTypeChoices.TYPE_IEC_C13)
  425. self.assertEqual(po1.power_port, pp1)
  426. self.assertEqual(po1.feed_leg, PowerOutletFeedLegChoices.FEED_LEG_A)
  427. self.assertEqual(dt.interfacetemplates.count(), 3)
  428. iface1 = InterfaceTemplate.objects.first()
  429. self.assertEqual(iface1.name, 'Interface 1')
  430. self.assertEqual(iface1.type, InterfaceTypeChoices.TYPE_1GE_FIXED)
  431. self.assertTrue(iface1.mgmt_only)
  432. self.assertEqual(dt.rearporttemplates.count(), 3)
  433. rp1 = RearPortTemplate.objects.first()
  434. self.assertEqual(rp1.name, 'Rear Port 1')
  435. self.assertEqual(dt.frontporttemplates.count(), 3)
  436. fp1 = FrontPortTemplate.objects.first()
  437. self.assertEqual(fp1.name, 'Front Port 1')
  438. self.assertEqual(fp1.rear_port, rp1)
  439. self.assertEqual(fp1.rear_port_position, 1)
  440. self.assertEqual(dt.devicebaytemplates.count(), 3)
  441. db1 = DeviceBayTemplate.objects.first()
  442. self.assertEqual(db1.name, 'Device Bay 1')
  443. def test_devicetype_export(self):
  444. url = reverse('dcim:devicetype_list')
  445. self.add_permissions('dcim.view_devicetype')
  446. response = self.client.get('{}?export'.format(url))
  447. self.assertEqual(response.status_code, 200)
  448. data = list(yaml.load_all(response.content, Loader=yaml.SafeLoader))
  449. self.assertEqual(len(data), 3)
  450. self.assertEqual(data[0]['manufacturer'], 'Manufacturer 1')
  451. self.assertEqual(data[0]['model'], 'Device Type 1')
  452. #
  453. # DeviceType components
  454. #
  455. class ConsolePortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  456. model = ConsolePortTemplate
  457. @classmethod
  458. def setUpTestData(cls):
  459. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  460. devicetypes = (
  461. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  462. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  463. )
  464. DeviceType.objects.bulk_create(devicetypes)
  465. ConsolePortTemplate.objects.bulk_create((
  466. ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 1'),
  467. ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 2'),
  468. ConsolePortTemplate(device_type=devicetypes[0], name='Console Port Template 3'),
  469. ))
  470. cls.form_data = {
  471. 'device_type': devicetypes[1].pk,
  472. 'name': 'Console Port Template X',
  473. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  474. }
  475. cls.bulk_create_data = {
  476. 'device_type': devicetypes[1].pk,
  477. 'name_pattern': 'Console Port Template [4-6]',
  478. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  479. }
  480. cls.bulk_edit_data = {
  481. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  482. }
  483. class ConsoleServerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  484. model = ConsoleServerPortTemplate
  485. @classmethod
  486. def setUpTestData(cls):
  487. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  488. devicetypes = (
  489. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  490. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  491. )
  492. DeviceType.objects.bulk_create(devicetypes)
  493. ConsoleServerPortTemplate.objects.bulk_create((
  494. ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 1'),
  495. ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 2'),
  496. ConsoleServerPortTemplate(device_type=devicetypes[0], name='Console Server Port Template 3'),
  497. ))
  498. cls.form_data = {
  499. 'device_type': devicetypes[1].pk,
  500. 'name': 'Console Server Port Template X',
  501. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  502. }
  503. cls.bulk_create_data = {
  504. 'device_type': devicetypes[1].pk,
  505. 'name_pattern': 'Console Server Port Template [4-6]',
  506. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  507. }
  508. cls.bulk_edit_data = {
  509. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  510. }
  511. class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  512. model = PowerPortTemplate
  513. @classmethod
  514. def setUpTestData(cls):
  515. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  516. devicetypes = (
  517. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  518. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  519. )
  520. DeviceType.objects.bulk_create(devicetypes)
  521. PowerPortTemplate.objects.bulk_create((
  522. PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 1'),
  523. PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 2'),
  524. PowerPortTemplate(device_type=devicetypes[0], name='Power Port Template 3'),
  525. ))
  526. cls.form_data = {
  527. 'device_type': devicetypes[1].pk,
  528. 'name': 'Power Port Template X',
  529. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  530. 'maximum_draw': 100,
  531. 'allocated_draw': 50,
  532. }
  533. cls.bulk_create_data = {
  534. 'device_type': devicetypes[1].pk,
  535. 'name_pattern': 'Power Port Template [4-6]',
  536. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  537. 'maximum_draw': 100,
  538. 'allocated_draw': 50,
  539. }
  540. cls.bulk_edit_data = {
  541. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  542. 'maximum_draw': 100,
  543. 'allocated_draw': 50,
  544. }
  545. class PowerOutletTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  546. model = PowerOutletTemplate
  547. @classmethod
  548. def setUpTestData(cls):
  549. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  550. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  551. PowerOutletTemplate.objects.bulk_create((
  552. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'),
  553. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'),
  554. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'),
  555. ))
  556. powerports = (
  557. PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'),
  558. )
  559. PowerPortTemplate.objects.bulk_create(powerports)
  560. cls.form_data = {
  561. 'device_type': devicetype.pk,
  562. 'name': 'Power Outlet Template X',
  563. 'type': PowerOutletTypeChoices.TYPE_IEC_C13,
  564. 'power_port': powerports[0].pk,
  565. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  566. }
  567. cls.bulk_create_data = {
  568. 'device_type': devicetype.pk,
  569. 'name_pattern': 'Power Outlet Template [4-6]',
  570. 'type': PowerOutletTypeChoices.TYPE_IEC_C13,
  571. 'power_port': powerports[0].pk,
  572. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  573. }
  574. cls.bulk_edit_data = {
  575. 'type': PowerOutletTypeChoices.TYPE_IEC_C13,
  576. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  577. }
  578. class InterfaceTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  579. model = InterfaceTemplate
  580. @classmethod
  581. def setUpTestData(cls):
  582. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  583. devicetypes = (
  584. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  585. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  586. )
  587. DeviceType.objects.bulk_create(devicetypes)
  588. InterfaceTemplate.objects.bulk_create((
  589. InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 1'),
  590. InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 2'),
  591. InterfaceTemplate(device_type=devicetypes[0], name='Interface Template 3'),
  592. ))
  593. cls.form_data = {
  594. 'device_type': devicetypes[1].pk,
  595. 'name': 'Interface Template X',
  596. 'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
  597. 'mgmt_only': True,
  598. }
  599. cls.bulk_create_data = {
  600. 'device_type': devicetypes[1].pk,
  601. 'name_pattern': 'Interface Template [4-6]',
  602. # Test that a label can be applied to each generated interface templates
  603. 'label_pattern': 'Interface Template Label [3-5]',
  604. 'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
  605. 'mgmt_only': True,
  606. }
  607. cls.bulk_edit_data = {
  608. 'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
  609. 'mgmt_only': True,
  610. }
  611. class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  612. model = FrontPortTemplate
  613. @classmethod
  614. def setUpTestData(cls):
  615. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  616. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  617. rearports = (
  618. RearPortTemplate(device_type=devicetype, name='Rear Port Template 1'),
  619. RearPortTemplate(device_type=devicetype, name='Rear Port Template 2'),
  620. RearPortTemplate(device_type=devicetype, name='Rear Port Template 3'),
  621. RearPortTemplate(device_type=devicetype, name='Rear Port Template 4'),
  622. RearPortTemplate(device_type=devicetype, name='Rear Port Template 5'),
  623. RearPortTemplate(device_type=devicetype, name='Rear Port Template 6'),
  624. )
  625. RearPortTemplate.objects.bulk_create(rearports)
  626. FrontPortTemplate.objects.bulk_create((
  627. FrontPortTemplate(device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1),
  628. FrontPortTemplate(device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1),
  629. FrontPortTemplate(device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1),
  630. ))
  631. cls.form_data = {
  632. 'device_type': devicetype.pk,
  633. 'name': 'Front Port X',
  634. 'type': PortTypeChoices.TYPE_8P8C,
  635. 'rear_port': rearports[3].pk,
  636. 'rear_port_position': 1,
  637. }
  638. cls.bulk_create_data = {
  639. 'device_type': devicetype.pk,
  640. 'name_pattern': 'Front Port [4-6]',
  641. 'type': PortTypeChoices.TYPE_8P8C,
  642. 'rear_port_set': [
  643. '{}:1'.format(rp.pk) for rp in rearports[3:6]
  644. ],
  645. }
  646. cls.bulk_edit_data = {
  647. 'type': PortTypeChoices.TYPE_8P8C,
  648. }
  649. class RearPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  650. model = RearPortTemplate
  651. @classmethod
  652. def setUpTestData(cls):
  653. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  654. devicetypes = (
  655. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  656. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  657. )
  658. DeviceType.objects.bulk_create(devicetypes)
  659. RearPortTemplate.objects.bulk_create((
  660. RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 1'),
  661. RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 2'),
  662. RearPortTemplate(device_type=devicetypes[0], name='Rear Port Template 3'),
  663. ))
  664. cls.form_data = {
  665. 'device_type': devicetypes[1].pk,
  666. 'name': 'Rear Port Template X',
  667. 'type': PortTypeChoices.TYPE_8P8C,
  668. 'positions': 2,
  669. }
  670. cls.bulk_create_data = {
  671. 'device_type': devicetypes[1].pk,
  672. 'name_pattern': 'Rear Port Template [4-6]',
  673. 'type': PortTypeChoices.TYPE_8P8C,
  674. 'positions': 2,
  675. }
  676. cls.bulk_edit_data = {
  677. 'type': PortTypeChoices.TYPE_8P8C,
  678. }
  679. class DeviceBayTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCase):
  680. model = DeviceBayTemplate
  681. @classmethod
  682. def setUpTestData(cls):
  683. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  684. devicetypes = (
  685. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  686. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  687. )
  688. DeviceType.objects.bulk_create(devicetypes)
  689. DeviceBayTemplate.objects.bulk_create((
  690. DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 1'),
  691. DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 2'),
  692. DeviceBayTemplate(device_type=devicetypes[0], name='Device Bay Template 3'),
  693. ))
  694. cls.form_data = {
  695. 'device_type': devicetypes[1].pk,
  696. 'name': 'Device Bay Template X',
  697. }
  698. cls.bulk_create_data = {
  699. 'device_type': devicetypes[1].pk,
  700. 'name_pattern': 'Device Bay Template [4-6]',
  701. }
  702. cls.bulk_edit_data = {
  703. 'description': 'Foo bar',
  704. }
  705. class DeviceRoleTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  706. model = DeviceRole
  707. @classmethod
  708. def setUpTestData(cls):
  709. DeviceRole.objects.bulk_create([
  710. DeviceRole(name='Device Role 1', slug='device-role-1'),
  711. DeviceRole(name='Device Role 2', slug='device-role-2'),
  712. DeviceRole(name='Device Role 3', slug='device-role-3'),
  713. ])
  714. cls.form_data = {
  715. 'name': 'Devie Role X',
  716. 'slug': 'device-role-x',
  717. 'color': 'c0c0c0',
  718. 'vm_role': False,
  719. 'description': 'New device role',
  720. }
  721. cls.csv_data = (
  722. "name,slug,color",
  723. "Device Role 4,device-role-4,ff0000",
  724. "Device Role 5,device-role-5,00ff00",
  725. "Device Role 6,device-role-6,0000ff",
  726. )
  727. class PlatformTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  728. model = Platform
  729. @classmethod
  730. def setUpTestData(cls):
  731. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  732. Platform.objects.bulk_create([
  733. Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturer),
  734. Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturer),
  735. Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturer),
  736. ])
  737. cls.form_data = {
  738. 'name': 'Platform X',
  739. 'slug': 'platform-x',
  740. 'manufacturer': manufacturer.pk,
  741. 'napalm_driver': 'junos',
  742. 'napalm_args': None,
  743. 'description': 'A new platform',
  744. }
  745. cls.csv_data = (
  746. "name,slug,description",
  747. "Platform 4,platform-4,Fourth platform",
  748. "Platform 5,platform-5,Fifth platform",
  749. "Platform 6,platform-6,Sixth platform",
  750. )
  751. class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  752. model = Device
  753. @classmethod
  754. def setUpTestData(cls):
  755. sites = (
  756. Site(name='Site 1', slug='site-1'),
  757. Site(name='Site 2', slug='site-2'),
  758. )
  759. Site.objects.bulk_create(sites)
  760. rack_group = RackGroup(site=sites[0], name='Rack Group 1', slug='rack-group-1')
  761. rack_group.save()
  762. racks = (
  763. Rack(name='Rack 1', site=sites[0], group=rack_group),
  764. Rack(name='Rack 2', site=sites[1]),
  765. )
  766. Rack.objects.bulk_create(racks)
  767. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  768. devicetypes = (
  769. DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer),
  770. DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer),
  771. )
  772. DeviceType.objects.bulk_create(devicetypes)
  773. deviceroles = (
  774. DeviceRole(name='Device Role 1', slug='device-role-1'),
  775. DeviceRole(name='Device Role 2', slug='device-role-2'),
  776. )
  777. DeviceRole.objects.bulk_create(deviceroles)
  778. platforms = (
  779. Platform(name='Platform 1', slug='platform-1'),
  780. Platform(name='Platform 2', slug='platform-2'),
  781. )
  782. Platform.objects.bulk_create(platforms)
  783. Device.objects.bulk_create([
  784. Device(name='Device 1', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
  785. Device(name='Device 2', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
  786. Device(name='Device 3', site=sites[0], rack=racks[0], device_type=devicetypes[0], device_role=deviceroles[0], platform=platforms[0]),
  787. ])
  788. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  789. cls.form_data = {
  790. 'device_type': devicetypes[1].pk,
  791. 'device_role': deviceroles[1].pk,
  792. 'tenant': None,
  793. 'platform': platforms[1].pk,
  794. 'name': 'Device X',
  795. 'serial': '123456',
  796. 'asset_tag': 'ABCDEF',
  797. 'site': sites[1].pk,
  798. 'rack': racks[1].pk,
  799. 'position': 1,
  800. 'face': DeviceFaceChoices.FACE_FRONT,
  801. 'status': DeviceStatusChoices.STATUS_PLANNED,
  802. 'primary_ip4': None,
  803. 'primary_ip6': None,
  804. 'cluster': None,
  805. 'virtual_chassis': None,
  806. 'vc_position': None,
  807. 'vc_priority': None,
  808. 'comments': 'A new device',
  809. 'tags': [t.pk for t in tags],
  810. 'local_context_data': None,
  811. }
  812. cls.csv_data = (
  813. "device_role,manufacturer,device_type,status,name,site,rack_group,rack,position,face",
  814. "Device Role 1,Manufacturer 1,Device Type 1,active,Device 4,Site 1,Rack Group 1,Rack 1,10,front",
  815. "Device Role 1,Manufacturer 1,Device Type 1,active,Device 5,Site 1,Rack Group 1,Rack 1,20,front",
  816. "Device Role 1,Manufacturer 1,Device Type 1,active,Device 6,Site 1,Rack Group 1,Rack 1,30,front",
  817. )
  818. cls.bulk_edit_data = {
  819. 'device_type': devicetypes[1].pk,
  820. 'device_role': deviceroles[1].pk,
  821. 'tenant': None,
  822. 'platform': platforms[1].pk,
  823. 'serial': '123456',
  824. 'status': DeviceStatusChoices.STATUS_DECOMMISSIONING,
  825. }
  826. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  827. def test_device_consoleports(self):
  828. device = Device.objects.first()
  829. console_ports = (
  830. ConsolePort(device=device, name='Console Port 1'),
  831. ConsolePort(device=device, name='Console Port 2'),
  832. ConsolePort(device=device, name='Console Port 3'),
  833. )
  834. ConsolePort.objects.bulk_create(console_ports)
  835. url = reverse('dcim:device_consoleports', kwargs={'pk': device.pk})
  836. self.assertHttpStatus(self.client.get(url), 200)
  837. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  838. def test_device_consoleserverports(self):
  839. device = Device.objects.first()
  840. console_server_ports = (
  841. ConsoleServerPort(device=device, name='Console Server Port 1'),
  842. ConsoleServerPort(device=device, name='Console Server Port 2'),
  843. ConsoleServerPort(device=device, name='Console Server Port 3'),
  844. )
  845. ConsoleServerPort.objects.bulk_create(console_server_ports)
  846. url = reverse('dcim:device_consoleserverports', kwargs={'pk': device.pk})
  847. self.assertHttpStatus(self.client.get(url), 200)
  848. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  849. def test_device_powerports(self):
  850. device = Device.objects.first()
  851. power_ports = (
  852. PowerPort(device=device, name='Power Port 1'),
  853. PowerPort(device=device, name='Power Port 2'),
  854. PowerPort(device=device, name='Power Port 3'),
  855. )
  856. PowerPort.objects.bulk_create(power_ports)
  857. url = reverse('dcim:device_powerports', kwargs={'pk': device.pk})
  858. self.assertHttpStatus(self.client.get(url), 200)
  859. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  860. def test_device_poweroutlets(self):
  861. device = Device.objects.first()
  862. power_outlets = (
  863. PowerOutlet(device=device, name='Power Outlet 1'),
  864. PowerOutlet(device=device, name='Power Outlet 2'),
  865. PowerOutlet(device=device, name='Power Outlet 3'),
  866. )
  867. PowerOutlet.objects.bulk_create(power_outlets)
  868. url = reverse('dcim:device_poweroutlets', kwargs={'pk': device.pk})
  869. self.assertHttpStatus(self.client.get(url), 200)
  870. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  871. def test_device_interfaces(self):
  872. device = Device.objects.first()
  873. interfaces = (
  874. Interface(device=device, name='Interface 1'),
  875. Interface(device=device, name='Interface 2'),
  876. Interface(device=device, name='Interface 3'),
  877. )
  878. Interface.objects.bulk_create(interfaces)
  879. url = reverse('dcim:device_interfaces', kwargs={'pk': device.pk})
  880. self.assertHttpStatus(self.client.get(url), 200)
  881. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  882. def test_device_rearports(self):
  883. device = Device.objects.first()
  884. rear_ports = (
  885. RearPort(device=device, name='Rear Port 1'),
  886. RearPort(device=device, name='Rear Port 2'),
  887. RearPort(device=device, name='Rear Port 3'),
  888. )
  889. RearPort.objects.bulk_create(rear_ports)
  890. url = reverse('dcim:device_rearports', kwargs={'pk': device.pk})
  891. self.assertHttpStatus(self.client.get(url), 200)
  892. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  893. def test_device_frontports(self):
  894. device = Device.objects.first()
  895. rear_ports = (
  896. RearPort(device=device, name='Rear Port 1'),
  897. RearPort(device=device, name='Rear Port 2'),
  898. RearPort(device=device, name='Rear Port 3'),
  899. )
  900. RearPort.objects.bulk_create(rear_ports)
  901. front_ports = (
  902. FrontPort(device=device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1),
  903. FrontPort(device=device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1),
  904. FrontPort(device=device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1),
  905. )
  906. FrontPort.objects.bulk_create(front_ports)
  907. url = reverse('dcim:device_frontports', kwargs={'pk': device.pk})
  908. self.assertHttpStatus(self.client.get(url), 200)
  909. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  910. def test_device_devicebays(self):
  911. device = Device.objects.first()
  912. device_bays = (
  913. DeviceBay(device=device, name='Device Bay 1'),
  914. DeviceBay(device=device, name='Device Bay 2'),
  915. DeviceBay(device=device, name='Device Bay 3'),
  916. )
  917. DeviceBay.objects.bulk_create(device_bays)
  918. url = reverse('dcim:device_devicebays', kwargs={'pk': device.pk})
  919. self.assertHttpStatus(self.client.get(url), 200)
  920. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  921. def test_device_inventory(self):
  922. device = Device.objects.first()
  923. inventory_items = (
  924. InventoryItem(device=device, name='Inventory Item 1'),
  925. InventoryItem(device=device, name='Inventory Item 2'),
  926. InventoryItem(device=device, name='Inventory Item 3'),
  927. )
  928. for item in inventory_items:
  929. item.save()
  930. url = reverse('dcim:device_inventory', kwargs={'pk': device.pk})
  931. self.assertHttpStatus(self.client.get(url), 200)
  932. class ConsolePortTestCase(ViewTestCases.DeviceComponentViewTestCase):
  933. model = ConsolePort
  934. @classmethod
  935. def setUpTestData(cls):
  936. device = create_test_device('Device 1')
  937. ConsolePort.objects.bulk_create([
  938. ConsolePort(device=device, name='Console Port 1'),
  939. ConsolePort(device=device, name='Console Port 2'),
  940. ConsolePort(device=device, name='Console Port 3'),
  941. ])
  942. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  943. cls.form_data = {
  944. 'device': device.pk,
  945. 'name': 'Console Port X',
  946. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  947. 'description': 'A console port',
  948. 'tags': sorted([t.pk for t in tags]),
  949. }
  950. cls.bulk_create_data = {
  951. 'device': device.pk,
  952. 'name_pattern': 'Console Port [4-6]',
  953. # Test that a label can be applied to each generated console ports
  954. 'label_pattern': 'Serial[3-5]',
  955. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  956. 'description': 'A console port',
  957. 'tags': sorted([t.pk for t in tags]),
  958. }
  959. cls.bulk_edit_data = {
  960. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  961. 'description': 'New description',
  962. }
  963. cls.csv_data = (
  964. "device,name",
  965. "Device 1,Console Port 4",
  966. "Device 1,Console Port 5",
  967. "Device 1,Console Port 6",
  968. )
  969. class ConsoleServerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
  970. model = ConsoleServerPort
  971. @classmethod
  972. def setUpTestData(cls):
  973. device = create_test_device('Device 1')
  974. ConsoleServerPort.objects.bulk_create([
  975. ConsoleServerPort(device=device, name='Console Server Port 1'),
  976. ConsoleServerPort(device=device, name='Console Server Port 2'),
  977. ConsoleServerPort(device=device, name='Console Server Port 3'),
  978. ])
  979. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  980. cls.form_data = {
  981. 'device': device.pk,
  982. 'name': 'Console Server Port X',
  983. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  984. 'description': 'A console server port',
  985. 'tags': [t.pk for t in tags],
  986. }
  987. cls.bulk_create_data = {
  988. 'device': device.pk,
  989. 'name_pattern': 'Console Server Port [4-6]',
  990. 'type': ConsolePortTypeChoices.TYPE_RJ45,
  991. 'description': 'A console server port',
  992. 'tags': [t.pk for t in tags],
  993. }
  994. cls.bulk_edit_data = {
  995. 'type': ConsolePortTypeChoices.TYPE_RJ11,
  996. 'description': 'New description',
  997. }
  998. cls.csv_data = (
  999. "device,name",
  1000. "Device 1,Console Server Port 4",
  1001. "Device 1,Console Server Port 5",
  1002. "Device 1,Console Server Port 6",
  1003. )
  1004. class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1005. model = PowerPort
  1006. @classmethod
  1007. def setUpTestData(cls):
  1008. device = create_test_device('Device 1')
  1009. PowerPort.objects.bulk_create([
  1010. PowerPort(device=device, name='Power Port 1'),
  1011. PowerPort(device=device, name='Power Port 2'),
  1012. PowerPort(device=device, name='Power Port 3'),
  1013. ])
  1014. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1015. cls.form_data = {
  1016. 'device': device.pk,
  1017. 'name': 'Power Port X',
  1018. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  1019. 'maximum_draw': 100,
  1020. 'allocated_draw': 50,
  1021. 'description': 'A power port',
  1022. 'tags': [t.pk for t in tags],
  1023. }
  1024. cls.bulk_create_data = {
  1025. 'device': device.pk,
  1026. 'name_pattern': 'Power Port [4-6]]',
  1027. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  1028. 'maximum_draw': 100,
  1029. 'allocated_draw': 50,
  1030. 'description': 'A power port',
  1031. 'tags': [t.pk for t in tags],
  1032. }
  1033. cls.bulk_edit_data = {
  1034. 'type': PowerPortTypeChoices.TYPE_IEC_C14,
  1035. 'maximum_draw': 100,
  1036. 'allocated_draw': 50,
  1037. 'description': 'New description',
  1038. }
  1039. cls.csv_data = (
  1040. "device,name",
  1041. "Device 1,Power Port 4",
  1042. "Device 1,Power Port 5",
  1043. "Device 1,Power Port 6",
  1044. )
  1045. class PowerOutletTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1046. model = PowerOutlet
  1047. @classmethod
  1048. def setUpTestData(cls):
  1049. device = create_test_device('Device 1')
  1050. powerports = (
  1051. PowerPort(device=device, name='Power Port 1'),
  1052. PowerPort(device=device, name='Power Port 2'),
  1053. )
  1054. PowerPort.objects.bulk_create(powerports)
  1055. PowerOutlet.objects.bulk_create([
  1056. PowerOutlet(device=device, name='Power Outlet 1', power_port=powerports[0]),
  1057. PowerOutlet(device=device, name='Power Outlet 2', power_port=powerports[0]),
  1058. PowerOutlet(device=device, name='Power Outlet 3', power_port=powerports[0]),
  1059. ])
  1060. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1061. cls.form_data = {
  1062. 'device': device.pk,
  1063. 'name': 'Power Outlet X',
  1064. 'type': PowerOutletTypeChoices.TYPE_IEC_C13,
  1065. 'power_port': powerports[1].pk,
  1066. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  1067. 'description': 'A power outlet',
  1068. 'tags': [t.pk for t in tags],
  1069. }
  1070. cls.bulk_create_data = {
  1071. 'device': device.pk,
  1072. 'name_pattern': 'Power Outlet [4-6]',
  1073. 'type': PowerOutletTypeChoices.TYPE_IEC_C13,
  1074. 'power_port': powerports[1].pk,
  1075. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  1076. 'description': 'A power outlet',
  1077. 'tags': [t.pk for t in tags],
  1078. }
  1079. cls.bulk_edit_data = {
  1080. 'type': PowerOutletTypeChoices.TYPE_IEC_C15,
  1081. 'power_port': powerports[1].pk,
  1082. 'feed_leg': PowerOutletFeedLegChoices.FEED_LEG_B,
  1083. 'description': 'New description',
  1084. }
  1085. cls.csv_data = (
  1086. "device,name",
  1087. "Device 1,Power Outlet 4",
  1088. "Device 1,Power Outlet 5",
  1089. "Device 1,Power Outlet 6",
  1090. )
  1091. class InterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1092. model = Interface
  1093. @classmethod
  1094. def setUpTestData(cls):
  1095. device = create_test_device('Device 1')
  1096. interfaces = (
  1097. Interface(device=device, name='Interface 1'),
  1098. Interface(device=device, name='Interface 2'),
  1099. Interface(device=device, name='Interface 3'),
  1100. Interface(device=device, name='LAG', type=InterfaceTypeChoices.TYPE_LAG),
  1101. )
  1102. Interface.objects.bulk_create(interfaces)
  1103. vlans = (
  1104. VLAN(vid=1, name='VLAN1', site=device.site),
  1105. VLAN(vid=101, name='VLAN101', site=device.site),
  1106. VLAN(vid=102, name='VLAN102', site=device.site),
  1107. VLAN(vid=103, name='VLAN103', site=device.site),
  1108. )
  1109. VLAN.objects.bulk_create(vlans)
  1110. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1111. cls.form_data = {
  1112. 'device': device.pk,
  1113. 'virtual_machine': None,
  1114. 'name': 'Interface X',
  1115. 'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
  1116. 'enabled': False,
  1117. 'lag': interfaces[3].pk,
  1118. 'mac_address': EUI('01:02:03:04:05:06'),
  1119. 'mtu': 2000,
  1120. 'mgmt_only': True,
  1121. 'description': 'A front port',
  1122. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1123. 'untagged_vlan': vlans[0].pk,
  1124. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  1125. 'tags': [t.pk for t in tags],
  1126. }
  1127. cls.bulk_create_data = {
  1128. 'device': device.pk,
  1129. 'name_pattern': 'Interface [4-6]',
  1130. 'type': InterfaceTypeChoices.TYPE_1GE_GBIC,
  1131. 'enabled': False,
  1132. 'lag': interfaces[3].pk,
  1133. 'mac_address': EUI('01:02:03:04:05:06'),
  1134. 'mtu': 2000,
  1135. 'mgmt_only': True,
  1136. 'description': 'A front port',
  1137. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1138. 'untagged_vlan': vlans[0].pk,
  1139. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  1140. 'tags': [t.pk for t in tags],
  1141. }
  1142. cls.bulk_edit_data = {
  1143. 'type': InterfaceTypeChoices.TYPE_1GE_FIXED,
  1144. 'enabled': True,
  1145. 'lag': interfaces[3].pk,
  1146. 'mac_address': EUI('01:02:03:04:05:06'),
  1147. 'mtu': 2000,
  1148. 'mgmt_only': True,
  1149. 'description': 'New description',
  1150. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1151. 'untagged_vlan': vlans[0].pk,
  1152. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  1153. }
  1154. cls.csv_data = (
  1155. "device,name,type",
  1156. "Device 1,Interface 4,1000base-t",
  1157. "Device 1,Interface 5,1000base-t",
  1158. "Device 1,Interface 6,1000base-t",
  1159. )
  1160. class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1161. model = FrontPort
  1162. @classmethod
  1163. def setUpTestData(cls):
  1164. device = create_test_device('Device 1')
  1165. rearports = (
  1166. RearPort(device=device, name='Rear Port 1'),
  1167. RearPort(device=device, name='Rear Port 2'),
  1168. RearPort(device=device, name='Rear Port 3'),
  1169. RearPort(device=device, name='Rear Port 4'),
  1170. RearPort(device=device, name='Rear Port 5'),
  1171. RearPort(device=device, name='Rear Port 6'),
  1172. )
  1173. RearPort.objects.bulk_create(rearports)
  1174. FrontPort.objects.bulk_create([
  1175. FrontPort(device=device, name='Front Port 1', rear_port=rearports[0]),
  1176. FrontPort(device=device, name='Front Port 2', rear_port=rearports[1]),
  1177. FrontPort(device=device, name='Front Port 3', rear_port=rearports[2]),
  1178. ])
  1179. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1180. cls.form_data = {
  1181. 'device': device.pk,
  1182. 'name': 'Front Port X',
  1183. 'type': PortTypeChoices.TYPE_8P8C,
  1184. 'rear_port': rearports[3].pk,
  1185. 'rear_port_position': 1,
  1186. 'description': 'New description',
  1187. 'tags': [t.pk for t in tags],
  1188. }
  1189. cls.bulk_create_data = {
  1190. 'device': device.pk,
  1191. 'name_pattern': 'Front Port [4-6]',
  1192. 'type': PortTypeChoices.TYPE_8P8C,
  1193. 'rear_port_set': [
  1194. '{}:1'.format(rp.pk) for rp in rearports[3:6]
  1195. ],
  1196. 'description': 'New description',
  1197. 'tags': [t.pk for t in tags],
  1198. }
  1199. cls.bulk_edit_data = {
  1200. 'type': PortTypeChoices.TYPE_8P8C,
  1201. 'description': 'New description',
  1202. }
  1203. cls.csv_data = (
  1204. "device,name,type,rear_port,rear_port_position",
  1205. "Device 1,Front Port 4,8p8c,Rear Port 4,1",
  1206. "Device 1,Front Port 5,8p8c,Rear Port 5,1",
  1207. "Device 1,Front Port 6,8p8c,Rear Port 6,1",
  1208. )
  1209. class RearPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1210. model = RearPort
  1211. @classmethod
  1212. def setUpTestData(cls):
  1213. device = create_test_device('Device 1')
  1214. RearPort.objects.bulk_create([
  1215. RearPort(device=device, name='Rear Port 1'),
  1216. RearPort(device=device, name='Rear Port 2'),
  1217. RearPort(device=device, name='Rear Port 3'),
  1218. ])
  1219. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1220. cls.form_data = {
  1221. 'device': device.pk,
  1222. 'name': 'Rear Port X',
  1223. 'type': PortTypeChoices.TYPE_8P8C,
  1224. 'positions': 3,
  1225. 'description': 'A rear port',
  1226. 'tags': [t.pk for t in tags],
  1227. }
  1228. cls.bulk_create_data = {
  1229. 'device': device.pk,
  1230. 'name_pattern': 'Rear Port [4-6]',
  1231. 'type': PortTypeChoices.TYPE_8P8C,
  1232. 'positions': 3,
  1233. 'description': 'A rear port',
  1234. 'tags': [t.pk for t in tags],
  1235. }
  1236. cls.bulk_edit_data = {
  1237. 'type': PortTypeChoices.TYPE_8P8C,
  1238. 'description': 'New description',
  1239. }
  1240. cls.csv_data = (
  1241. "device,name,type,positions",
  1242. "Device 1,Rear Port 4,8p8c,1",
  1243. "Device 1,Rear Port 5,8p8c,1",
  1244. "Device 1,Rear Port 6,8p8c,1",
  1245. )
  1246. class DeviceBayTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1247. model = DeviceBay
  1248. @classmethod
  1249. def setUpTestData(cls):
  1250. device = create_test_device('Device 1')
  1251. # Update the DeviceType subdevice role to allow adding DeviceBays
  1252. DeviceType.objects.update(subdevice_role=SubdeviceRoleChoices.ROLE_PARENT)
  1253. DeviceBay.objects.bulk_create([
  1254. DeviceBay(device=device, name='Device Bay 1'),
  1255. DeviceBay(device=device, name='Device Bay 2'),
  1256. DeviceBay(device=device, name='Device Bay 3'),
  1257. ])
  1258. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1259. cls.form_data = {
  1260. 'device': device.pk,
  1261. 'name': 'Device Bay X',
  1262. 'description': 'A device bay',
  1263. 'tags': [t.pk for t in tags],
  1264. }
  1265. cls.bulk_create_data = {
  1266. 'device': device.pk,
  1267. 'name_pattern': 'Device Bay [4-6]',
  1268. 'description': 'A device bay',
  1269. 'tags': [t.pk for t in tags],
  1270. }
  1271. cls.bulk_edit_data = {
  1272. 'description': 'New description',
  1273. }
  1274. cls.csv_data = (
  1275. "device,name",
  1276. "Device 1,Device Bay 4",
  1277. "Device 1,Device Bay 5",
  1278. "Device 1,Device Bay 6",
  1279. )
  1280. class InventoryItemTestCase(ViewTestCases.DeviceComponentViewTestCase):
  1281. model = InventoryItem
  1282. @classmethod
  1283. def setUpTestData(cls):
  1284. device = create_test_device('Device 1')
  1285. manufacturer, _ = Manufacturer.objects.get_or_create(name='Manufacturer 1', slug='manufacturer-1')
  1286. InventoryItem.objects.create(device=device, name='Inventory Item 1')
  1287. InventoryItem.objects.create(device=device, name='Inventory Item 2')
  1288. InventoryItem.objects.create(device=device, name='Inventory Item 3')
  1289. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1290. cls.form_data = {
  1291. 'device': device.pk,
  1292. 'manufacturer': manufacturer.pk,
  1293. 'name': 'Inventory Item X',
  1294. 'parent': None,
  1295. 'discovered': False,
  1296. 'part_id': '123456',
  1297. 'serial': '123ABC',
  1298. 'asset_tag': 'ABC123',
  1299. 'description': 'An inventory item',
  1300. 'tags': [t.pk for t in tags],
  1301. }
  1302. cls.bulk_create_data = {
  1303. 'device': device.pk,
  1304. 'name_pattern': 'Inventory Item [4-6]',
  1305. 'manufacturer': manufacturer.pk,
  1306. 'parent': None,
  1307. 'discovered': False,
  1308. 'part_id': '123456',
  1309. 'serial': '123ABC',
  1310. 'description': 'An inventory item',
  1311. 'tags': [t.pk for t in tags],
  1312. }
  1313. cls.bulk_edit_data = {
  1314. 'part_id': '123456',
  1315. 'description': 'New description',
  1316. }
  1317. cls.csv_data = (
  1318. "device,name",
  1319. "Device 1,Inventory Item 4",
  1320. "Device 1,Inventory Item 5",
  1321. "Device 1,Inventory Item 6",
  1322. )
  1323. # TODO: Change base class to PrimaryObjectViewTestCase
  1324. # Blocked by lack of common creation view for cables (termination A must be initialized)
  1325. class CableTestCase(
  1326. ViewTestCases.GetObjectViewTestCase,
  1327. ViewTestCases.GetObjectChangelogViewTestCase,
  1328. ViewTestCases.EditObjectViewTestCase,
  1329. ViewTestCases.DeleteObjectViewTestCase,
  1330. ViewTestCases.ListObjectsViewTestCase,
  1331. ViewTestCases.BulkImportObjectsViewTestCase,
  1332. ViewTestCases.BulkEditObjectsViewTestCase,
  1333. ViewTestCases.BulkDeleteObjectsViewTestCase
  1334. ):
  1335. model = Cable
  1336. @classmethod
  1337. def setUpTestData(cls):
  1338. site = Site.objects.create(name='Site 1', slug='site-1')
  1339. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  1340. devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
  1341. devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  1342. devices = (
  1343. Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole),
  1344. Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole),
  1345. Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole),
  1346. Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole),
  1347. )
  1348. Device.objects.bulk_create(devices)
  1349. interfaces = (
  1350. Interface(device=devices[0], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1351. Interface(device=devices[0], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1352. Interface(device=devices[0], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1353. Interface(device=devices[1], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1354. Interface(device=devices[1], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1355. Interface(device=devices[1], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1356. Interface(device=devices[2], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1357. Interface(device=devices[2], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1358. Interface(device=devices[2], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1359. Interface(device=devices[3], name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1360. Interface(device=devices[3], name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1361. Interface(device=devices[3], name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  1362. )
  1363. Interface.objects.bulk_create(interfaces)
  1364. Cable(termination_a=interfaces[0], termination_b=interfaces[3], type=CableTypeChoices.TYPE_CAT6).save()
  1365. Cable(termination_a=interfaces[1], termination_b=interfaces[4], type=CableTypeChoices.TYPE_CAT6).save()
  1366. Cable(termination_a=interfaces[2], termination_b=interfaces[5], type=CableTypeChoices.TYPE_CAT6).save()
  1367. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1368. interface_ct = ContentType.objects.get_for_model(Interface)
  1369. cls.form_data = {
  1370. # Changing terminations not supported when editing an existing Cable
  1371. 'termination_a_type': interface_ct.pk,
  1372. 'termination_a_id': interfaces[0].pk,
  1373. 'termination_b_type': interface_ct.pk,
  1374. 'termination_b_id': interfaces[3].pk,
  1375. 'type': CableTypeChoices.TYPE_CAT6,
  1376. 'status': CableStatusChoices.STATUS_PLANNED,
  1377. 'label': 'Label',
  1378. 'color': 'c0c0c0',
  1379. 'length': 100,
  1380. 'length_unit': CableLengthUnitChoices.UNIT_FOOT,
  1381. 'tags': [t.pk for t in tags],
  1382. }
  1383. cls.csv_data = (
  1384. "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
  1385. "Device 3,dcim.interface,Interface 1,Device 4,dcim.interface,Interface 1",
  1386. "Device 3,dcim.interface,Interface 2,Device 4,dcim.interface,Interface 2",
  1387. "Device 3,dcim.interface,Interface 3,Device 4,dcim.interface,Interface 3",
  1388. )
  1389. cls.bulk_edit_data = {
  1390. 'type': CableTypeChoices.TYPE_CAT5E,
  1391. 'status': CableStatusChoices.STATUS_CONNECTED,
  1392. 'label': 'New label',
  1393. 'color': '00ff00',
  1394. 'length': 50,
  1395. 'length_unit': CableLengthUnitChoices.UNIT_METER,
  1396. }
  1397. class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  1398. model = VirtualChassis
  1399. @classmethod
  1400. def setUpTestData(cls):
  1401. site = Site.objects.create(name='Site 1', slug='site-1')
  1402. manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
  1403. device_type = DeviceType.objects.create(
  1404. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  1405. )
  1406. device_role = DeviceRole.objects.create(
  1407. name='Device Role', slug='device-role-1'
  1408. )
  1409. devices = (
  1410. Device(device_type=device_type, device_role=device_role, name='Device 1', site=site),
  1411. Device(device_type=device_type, device_role=device_role, name='Device 2', site=site),
  1412. Device(device_type=device_type, device_role=device_role, name='Device 3', site=site),
  1413. Device(device_type=device_type, device_role=device_role, name='Device 4', site=site),
  1414. Device(device_type=device_type, device_role=device_role, name='Device 5', site=site),
  1415. Device(device_type=device_type, device_role=device_role, name='Device 6', site=site),
  1416. Device(device_type=device_type, device_role=device_role, name='Device 7', site=site),
  1417. Device(device_type=device_type, device_role=device_role, name='Device 8', site=site),
  1418. Device(device_type=device_type, device_role=device_role, name='Device 9', site=site),
  1419. Device(device_type=device_type, device_role=device_role, name='Device 10', site=site),
  1420. Device(device_type=device_type, device_role=device_role, name='Device 11', site=site),
  1421. Device(device_type=device_type, device_role=device_role, name='Device 12', site=site),
  1422. )
  1423. Device.objects.bulk_create(devices)
  1424. # Create three VirtualChassis with three members each
  1425. vc1 = VirtualChassis.objects.create(name='VC1', master=devices[0], domain='domain-1')
  1426. Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=vc1, vc_position=1)
  1427. Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=vc1, vc_position=2)
  1428. Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=vc1, vc_position=3)
  1429. vc2 = VirtualChassis.objects.create(name='VC2', master=devices[3], domain='domain-2')
  1430. Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=vc2, vc_position=1)
  1431. Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=vc2, vc_position=2)
  1432. Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=vc2, vc_position=3)
  1433. vc3 = VirtualChassis.objects.create(name='VC3', master=devices[6], domain='domain-3')
  1434. Device.objects.filter(pk=devices[6].pk).update(virtual_chassis=vc3, vc_position=1)
  1435. Device.objects.filter(pk=devices[7].pk).update(virtual_chassis=vc3, vc_position=2)
  1436. Device.objects.filter(pk=devices[8].pk).update(virtual_chassis=vc3, vc_position=3)
  1437. cls.form_data = {
  1438. 'name': 'VC4',
  1439. 'domain': 'domain-4',
  1440. # Management form data for VC members
  1441. 'form-TOTAL_FORMS': 0,
  1442. 'form-INITIAL_FORMS': 3,
  1443. 'form-MIN_NUM_FORMS': 0,
  1444. 'form-MAX_NUM_FORMS': 1000,
  1445. }
  1446. cls.csv_data = (
  1447. "name,domain,master",
  1448. "VC4,Domain 4,Device 10",
  1449. "VC5,Domain 5,Device 11",
  1450. "VC6,Domain 6,Device 12",
  1451. )
  1452. cls.bulk_edit_data = {
  1453. 'domain': 'domain-x',
  1454. }
  1455. class PowerPanelTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  1456. model = PowerPanel
  1457. @classmethod
  1458. def setUpTestData(cls):
  1459. sites = (
  1460. Site(name='Site 1', slug='site-1'),
  1461. Site(name='Site 2', slug='site-2'),
  1462. )
  1463. Site.objects.bulk_create(sites)
  1464. rackgroups = (
  1465. RackGroup(name='Rack Group 1', slug='rack-group-1', site=sites[0]),
  1466. RackGroup(name='Rack Group 2', slug='rack-group-2', site=sites[1]),
  1467. )
  1468. for rackgroup in rackgroups:
  1469. rackgroup.save()
  1470. PowerPanel.objects.bulk_create((
  1471. PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 1'),
  1472. PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 2'),
  1473. PowerPanel(site=sites[0], rack_group=rackgroups[0], name='Power Panel 3'),
  1474. ))
  1475. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1476. cls.form_data = {
  1477. 'site': sites[1].pk,
  1478. 'rack_group': rackgroups[1].pk,
  1479. 'name': 'Power Panel X',
  1480. 'tags': [t.pk for t in tags],
  1481. }
  1482. cls.csv_data = (
  1483. "site,rack_group,name",
  1484. "Site 1,Rack Group 1,Power Panel 4",
  1485. "Site 1,Rack Group 1,Power Panel 5",
  1486. "Site 1,Rack Group 1,Power Panel 6",
  1487. )
  1488. cls.bulk_edit_data = {
  1489. 'site': sites[1].pk,
  1490. 'rack_group': rackgroups[1].pk,
  1491. }
  1492. class PowerFeedTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  1493. model = PowerFeed
  1494. @classmethod
  1495. def setUpTestData(cls):
  1496. site = Site.objects.create(name='Site 1', slug='site-1')
  1497. powerpanels = (
  1498. PowerPanel(site=site, name='Power Panel 1'),
  1499. PowerPanel(site=site, name='Power Panel 2'),
  1500. )
  1501. PowerPanel.objects.bulk_create(powerpanels)
  1502. racks = (
  1503. Rack(site=site, name='Rack 1'),
  1504. Rack(site=site, name='Rack 2'),
  1505. )
  1506. Rack.objects.bulk_create(racks)
  1507. PowerFeed.objects.bulk_create((
  1508. PowerFeed(name='Power Feed 1', power_panel=powerpanels[0], rack=racks[0]),
  1509. PowerFeed(name='Power Feed 2', power_panel=powerpanels[0], rack=racks[0]),
  1510. PowerFeed(name='Power Feed 3', power_panel=powerpanels[0], rack=racks[0]),
  1511. ))
  1512. tags = cls.create_tags('Alpha', 'Bravo', 'Charlie')
  1513. cls.form_data = {
  1514. 'name': 'Power Feed X',
  1515. 'power_panel': powerpanels[1].pk,
  1516. 'rack': racks[1].pk,
  1517. 'status': PowerFeedStatusChoices.STATUS_PLANNED,
  1518. 'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
  1519. 'supply': PowerFeedSupplyChoices.SUPPLY_DC,
  1520. 'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
  1521. 'voltage': 100,
  1522. 'amperage': 100,
  1523. 'max_utilization': 50,
  1524. 'comments': 'New comments',
  1525. 'tags': [t.pk for t in tags],
  1526. }
  1527. cls.csv_data = (
  1528. "site,power_panel,name,voltage,amperage,max_utilization",
  1529. "Site 1,Power Panel 1,Power Feed 4,120,20,80",
  1530. "Site 1,Power Panel 1,Power Feed 5,120,20,80",
  1531. "Site 1,Power Panel 1,Power Feed 6,120,20,80",
  1532. )
  1533. cls.bulk_edit_data = {
  1534. 'power_panel': powerpanels[1].pk,
  1535. 'rack': racks[1].pk,
  1536. 'status': PowerFeedStatusChoices.STATUS_PLANNED,
  1537. 'type': PowerFeedTypeChoices.TYPE_REDUNDANT,
  1538. 'supply': PowerFeedSupplyChoices.SUPPLY_DC,
  1539. 'phase': PowerFeedPhaseChoices.PHASE_3PHASE,
  1540. 'voltage': 100,
  1541. 'amperage': 100,
  1542. 'max_utilization': 50,
  1543. 'comments': 'New comments',
  1544. }