test_views.py 58 KB

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