2
0

test_api.py 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706
  1. from django.contrib.auth.models import User
  2. from django.test import override_settings
  3. from django.urls import reverse
  4. from rest_framework import status
  5. from dcim.choices import *
  6. from dcim.constants import *
  7. from dcim.models import *
  8. from ipam.models import VLAN
  9. from utilities.testing import APITestCase, APIViewTestCases
  10. from virtualization.models import Cluster, ClusterType
  11. class AppTest(APITestCase):
  12. def test_root(self):
  13. url = reverse('dcim-api:api-root')
  14. response = self.client.get('{}?format=api'.format(url), **self.header)
  15. self.assertEqual(response.status_code, 200)
  16. class Mixins:
  17. class ComponentTraceMixin(APITestCase):
  18. peer_termination_type = None
  19. def test_trace(self):
  20. """
  21. Test tracing a device component's attached cable.
  22. """
  23. obj = self.model.objects.first()
  24. peer_device = Device.objects.create(
  25. site=Site.objects.first(),
  26. device_type=DeviceType.objects.first(),
  27. device_role=DeviceRole.objects.first(),
  28. name='Peer Device'
  29. )
  30. if self.peer_termination_type is None:
  31. raise NotImplementedError("Test case must set peer_termination_type")
  32. peer_obj = self.peer_termination_type.objects.create(
  33. device=peer_device,
  34. name='Peer Termination'
  35. )
  36. cable = Cable(termination_a=obj, termination_b=peer_obj, label='Cable 1')
  37. cable.save()
  38. self.add_permissions(f'dcim.view_{self.model._meta.model_name}')
  39. url = reverse(f'dcim-api:{self.model._meta.model_name}-trace', kwargs={'pk': obj.pk})
  40. response = self.client.get(url, **self.header)
  41. self.assertHttpStatus(response, status.HTTP_200_OK)
  42. self.assertEqual(len(response.data), 1)
  43. segment1 = response.data[0]
  44. self.assertEqual(segment1[0]['name'], obj.name)
  45. self.assertEqual(segment1[1]['label'], cable.label)
  46. self.assertEqual(segment1[2]['name'], peer_obj.name)
  47. class RegionTest(APIViewTestCases.APIViewTestCase):
  48. model = Region
  49. brief_fields = ['_depth', 'display', 'id', 'name', 'site_count', 'slug', 'url']
  50. create_data = [
  51. {
  52. 'name': 'Region 4',
  53. 'slug': 'region-4',
  54. },
  55. {
  56. 'name': 'Region 5',
  57. 'slug': 'region-5',
  58. },
  59. {
  60. 'name': 'Region 6',
  61. 'slug': 'region-6',
  62. },
  63. ]
  64. bulk_update_data = {
  65. 'description': 'New description',
  66. }
  67. @classmethod
  68. def setUpTestData(cls):
  69. Region.objects.create(name='Region 1', slug='region-1')
  70. Region.objects.create(name='Region 2', slug='region-2')
  71. Region.objects.create(name='Region 3', slug='region-3')
  72. class SiteGroupTest(APIViewTestCases.APIViewTestCase):
  73. model = SiteGroup
  74. brief_fields = ['_depth', 'display', 'id', 'name', 'site_count', 'slug', 'url']
  75. create_data = [
  76. {
  77. 'name': 'Site Group 4',
  78. 'slug': 'site-group-4',
  79. },
  80. {
  81. 'name': 'Site Group 5',
  82. 'slug': 'site-group-5',
  83. },
  84. {
  85. 'name': 'Site Group 6',
  86. 'slug': 'site-group-6',
  87. },
  88. ]
  89. bulk_update_data = {
  90. 'description': 'New description',
  91. }
  92. @classmethod
  93. def setUpTestData(cls):
  94. SiteGroup.objects.create(name='Site Group 1', slug='site-group-1')
  95. SiteGroup.objects.create(name='Site Group 2', slug='site-group-2')
  96. SiteGroup.objects.create(name='Site Group 3', slug='site-group-3')
  97. class SiteTest(APIViewTestCases.APIViewTestCase):
  98. model = Site
  99. brief_fields = ['display', 'id', 'name', 'slug', 'url']
  100. bulk_update_data = {
  101. 'status': 'planned',
  102. }
  103. @classmethod
  104. def setUpTestData(cls):
  105. regions = (
  106. Region.objects.create(name='Region 1', slug='region-1'),
  107. Region.objects.create(name='Region 2', slug='region-2'),
  108. )
  109. groups = (
  110. SiteGroup.objects.create(name='Site Group 1', slug='site-group-1'),
  111. SiteGroup.objects.create(name='Site Group 2', slug='site-group-2'),
  112. )
  113. sites = (
  114. Site(region=regions[0], group=groups[0], name='Site 1', slug='site-1'),
  115. Site(region=regions[0], group=groups[0], name='Site 2', slug='site-2'),
  116. Site(region=regions[0], group=groups[0], name='Site 3', slug='site-3'),
  117. )
  118. Site.objects.bulk_create(sites)
  119. cls.create_data = [
  120. {
  121. 'name': 'Site 4',
  122. 'slug': 'site-4',
  123. 'region': regions[1].pk,
  124. 'group': groups[1].pk,
  125. 'status': SiteStatusChoices.STATUS_ACTIVE,
  126. },
  127. {
  128. 'name': 'Site 5',
  129. 'slug': 'site-5',
  130. 'region': regions[1].pk,
  131. 'group': groups[1].pk,
  132. 'status': SiteStatusChoices.STATUS_ACTIVE,
  133. },
  134. {
  135. 'name': 'Site 6',
  136. 'slug': 'site-6',
  137. 'region': regions[1].pk,
  138. 'group': groups[1].pk,
  139. 'status': SiteStatusChoices.STATUS_ACTIVE,
  140. },
  141. ]
  142. class LocationTest(APIViewTestCases.APIViewTestCase):
  143. model = Location
  144. brief_fields = ['_depth', 'display', 'id', 'name', 'rack_count', 'slug', 'url']
  145. bulk_update_data = {
  146. 'description': 'New description',
  147. }
  148. @classmethod
  149. def setUpTestData(cls):
  150. sites = (
  151. Site(name='Site 1', slug='site-1'),
  152. Site(name='Site 2', slug='site-2'),
  153. )
  154. Site.objects.bulk_create(sites)
  155. parent_locations = (
  156. Location.objects.create(site=sites[0], name='Parent Location 1', slug='parent-location-1'),
  157. Location.objects.create(site=sites[1], name='Parent Location 2', slug='parent-location-2'),
  158. )
  159. Location.objects.create(site=sites[0], name='Location 1', slug='location-1', parent=parent_locations[0])
  160. Location.objects.create(site=sites[0], name='Location 2', slug='location-2', parent=parent_locations[0])
  161. Location.objects.create(site=sites[0], name='Location 3', slug='location-3', parent=parent_locations[0])
  162. cls.create_data = [
  163. {
  164. 'name': 'Test Location 4',
  165. 'slug': 'test-location-4',
  166. 'site': sites[1].pk,
  167. 'parent': parent_locations[1].pk,
  168. },
  169. {
  170. 'name': 'Test Location 5',
  171. 'slug': 'test-location-5',
  172. 'site': sites[1].pk,
  173. 'parent': parent_locations[1].pk,
  174. },
  175. {
  176. 'name': 'Test Location 6',
  177. 'slug': 'test-location-6',
  178. 'site': sites[1].pk,
  179. 'parent': parent_locations[1].pk,
  180. },
  181. ]
  182. class RackRoleTest(APIViewTestCases.APIViewTestCase):
  183. model = RackRole
  184. brief_fields = ['display', 'id', 'name', 'rack_count', 'slug', 'url']
  185. create_data = [
  186. {
  187. 'name': 'Rack Role 4',
  188. 'slug': 'rack-role-4',
  189. 'color': 'ffff00',
  190. },
  191. {
  192. 'name': 'Rack Role 5',
  193. 'slug': 'rack-role-5',
  194. 'color': 'ffff00',
  195. },
  196. {
  197. 'name': 'Rack Role 6',
  198. 'slug': 'rack-role-6',
  199. 'color': 'ffff00',
  200. },
  201. ]
  202. bulk_update_data = {
  203. 'description': 'New description',
  204. }
  205. @classmethod
  206. def setUpTestData(cls):
  207. rack_roles = (
  208. RackRole(name='Rack Role 1', slug='rack-role-1', color='ff0000'),
  209. RackRole(name='Rack Role 2', slug='rack-role-2', color='00ff00'),
  210. RackRole(name='Rack Role 3', slug='rack-role-3', color='0000ff'),
  211. )
  212. RackRole.objects.bulk_create(rack_roles)
  213. class RackTest(APIViewTestCases.APIViewTestCase):
  214. model = Rack
  215. brief_fields = ['device_count', 'display', 'id', 'name', 'url']
  216. bulk_update_data = {
  217. 'status': 'planned',
  218. }
  219. @classmethod
  220. def setUpTestData(cls):
  221. sites = (
  222. Site(name='Site 1', slug='site-1'),
  223. Site(name='Site 2', slug='site-2'),
  224. )
  225. Site.objects.bulk_create(sites)
  226. locations = (
  227. Location.objects.create(site=sites[0], name='Location 1', slug='location-1'),
  228. Location.objects.create(site=sites[1], name='Location 2', slug='location-2'),
  229. )
  230. rack_roles = (
  231. RackRole(name='Rack Role 1', slug='rack-role-1', color='ff0000'),
  232. RackRole(name='Rack Role 2', slug='rack-role-2', color='00ff00'),
  233. )
  234. RackRole.objects.bulk_create(rack_roles)
  235. racks = (
  236. Rack(site=sites[0], location=locations[0], role=rack_roles[0], name='Rack 1'),
  237. Rack(site=sites[0], location=locations[0], role=rack_roles[0], name='Rack 2'),
  238. Rack(site=sites[0], location=locations[0], role=rack_roles[0], name='Rack 3'),
  239. )
  240. Rack.objects.bulk_create(racks)
  241. cls.create_data = [
  242. {
  243. 'name': 'Test Rack 4',
  244. 'site': sites[1].pk,
  245. 'location': locations[1].pk,
  246. 'role': rack_roles[1].pk,
  247. },
  248. {
  249. 'name': 'Test Rack 5',
  250. 'site': sites[1].pk,
  251. 'location': locations[1].pk,
  252. 'role': rack_roles[1].pk,
  253. },
  254. {
  255. 'name': 'Test Rack 6',
  256. 'site': sites[1].pk,
  257. 'location': locations[1].pk,
  258. 'role': rack_roles[1].pk,
  259. },
  260. ]
  261. def test_get_rack_elevation(self):
  262. """
  263. GET a single rack elevation.
  264. """
  265. rack = Rack.objects.first()
  266. self.add_permissions('dcim.view_rack')
  267. url = reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk})
  268. # Retrieve all units
  269. response = self.client.get(url, **self.header)
  270. self.assertEqual(response.data['count'], 42)
  271. # Search for specific units
  272. response = self.client.get(f'{url}?q=3', **self.header)
  273. self.assertEqual(response.data['count'], 13)
  274. response = self.client.get(f'{url}?q=U3', **self.header)
  275. self.assertEqual(response.data['count'], 11)
  276. response = self.client.get(f'{url}?q=U10', **self.header)
  277. self.assertEqual(response.data['count'], 1)
  278. def test_get_rack_elevation_svg(self):
  279. """
  280. GET a single rack elevation in SVG format.
  281. """
  282. rack = Rack.objects.first()
  283. self.add_permissions('dcim.view_rack')
  284. url = '{}?render=svg'.format(reverse('dcim-api:rack-elevation', kwargs={'pk': rack.pk}))
  285. response = self.client.get(url, **self.header)
  286. self.assertHttpStatus(response, status.HTTP_200_OK)
  287. self.assertEqual(response.get('Content-Type'), 'image/svg+xml')
  288. class RackReservationTest(APIViewTestCases.APIViewTestCase):
  289. model = RackReservation
  290. brief_fields = ['display', 'id', 'units', 'url', 'user']
  291. bulk_update_data = {
  292. 'description': 'New description',
  293. }
  294. @classmethod
  295. def setUpTestData(cls):
  296. user = User.objects.create(username='user1', is_active=True)
  297. site = Site.objects.create(name='Test Site 1', slug='test-site-1')
  298. racks = (
  299. Rack(site=site, name='Rack 1'),
  300. Rack(site=site, name='Rack 2'),
  301. )
  302. Rack.objects.bulk_create(racks)
  303. rack_reservations = (
  304. RackReservation(rack=racks[0], units=[1, 2, 3], user=user, description='Reservation #1'),
  305. RackReservation(rack=racks[0], units=[4, 5, 6], user=user, description='Reservation #2'),
  306. RackReservation(rack=racks[0], units=[7, 8, 9], user=user, description='Reservation #3'),
  307. )
  308. RackReservation.objects.bulk_create(rack_reservations)
  309. cls.create_data = [
  310. {
  311. 'rack': racks[1].pk,
  312. 'units': [10, 11, 12],
  313. 'user': user.pk,
  314. 'description': 'Reservation #4',
  315. },
  316. {
  317. 'rack': racks[1].pk,
  318. 'units': [13, 14, 15],
  319. 'user': user.pk,
  320. 'description': 'Reservation #5',
  321. },
  322. {
  323. 'rack': racks[1].pk,
  324. 'units': [16, 17, 18],
  325. 'user': user.pk,
  326. 'description': 'Reservation #6',
  327. },
  328. ]
  329. class ManufacturerTest(APIViewTestCases.APIViewTestCase):
  330. model = Manufacturer
  331. brief_fields = ['devicetype_count', 'display', 'id', 'name', 'slug', 'url']
  332. create_data = [
  333. {
  334. 'name': 'Manufacturer 4',
  335. 'slug': 'manufacturer-4',
  336. },
  337. {
  338. 'name': 'Manufacturer 5',
  339. 'slug': 'manufacturer-5',
  340. },
  341. {
  342. 'name': 'Manufacturer 6',
  343. 'slug': 'manufacturer-6',
  344. },
  345. ]
  346. bulk_update_data = {
  347. 'description': 'New description',
  348. }
  349. @classmethod
  350. def setUpTestData(cls):
  351. manufacturers = (
  352. Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
  353. Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
  354. Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
  355. )
  356. Manufacturer.objects.bulk_create(manufacturers)
  357. class DeviceTypeTest(APIViewTestCases.APIViewTestCase):
  358. model = DeviceType
  359. brief_fields = ['device_count', 'display', 'id', 'manufacturer', 'model', 'slug', 'url']
  360. bulk_update_data = {
  361. 'part_number': 'ABC123',
  362. }
  363. @classmethod
  364. def setUpTestData(cls):
  365. manufacturers = (
  366. Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
  367. Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
  368. )
  369. Manufacturer.objects.bulk_create(manufacturers)
  370. device_types = (
  371. DeviceType(manufacturer=manufacturers[0], model='Device Type 1', slug='device-type-1'),
  372. DeviceType(manufacturer=manufacturers[0], model='Device Type 2', slug='device-type-2'),
  373. DeviceType(manufacturer=manufacturers[0], model='Device Type 3', slug='device-type-3'),
  374. )
  375. DeviceType.objects.bulk_create(device_types)
  376. cls.create_data = [
  377. {
  378. 'manufacturer': manufacturers[1].pk,
  379. 'model': 'Device Type 4',
  380. 'slug': 'device-type-4',
  381. },
  382. {
  383. 'manufacturer': manufacturers[1].pk,
  384. 'model': 'Device Type 5',
  385. 'slug': 'device-type-5',
  386. },
  387. {
  388. 'manufacturer': manufacturers[1].pk,
  389. 'model': 'Device Type 6',
  390. 'slug': 'device-type-6',
  391. },
  392. ]
  393. class ConsolePortTemplateTest(APIViewTestCases.APIViewTestCase):
  394. model = ConsolePortTemplate
  395. brief_fields = ['display', 'id', 'name', 'url']
  396. bulk_update_data = {
  397. 'description': 'New description',
  398. }
  399. @classmethod
  400. def setUpTestData(cls):
  401. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  402. devicetype = DeviceType.objects.create(
  403. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  404. )
  405. console_port_templates = (
  406. ConsolePortTemplate(device_type=devicetype, name='Console Port Template 1'),
  407. ConsolePortTemplate(device_type=devicetype, name='Console Port Template 2'),
  408. ConsolePortTemplate(device_type=devicetype, name='Console Port Template 3'),
  409. )
  410. ConsolePortTemplate.objects.bulk_create(console_port_templates)
  411. cls.create_data = [
  412. {
  413. 'device_type': devicetype.pk,
  414. 'name': 'Console Port Template 4',
  415. },
  416. {
  417. 'device_type': devicetype.pk,
  418. 'name': 'Console Port Template 5',
  419. },
  420. {
  421. 'device_type': devicetype.pk,
  422. 'name': 'Console Port Template 6',
  423. },
  424. ]
  425. class ConsoleServerPortTemplateTest(APIViewTestCases.APIViewTestCase):
  426. model = ConsoleServerPortTemplate
  427. brief_fields = ['display', 'id', 'name', 'url']
  428. bulk_update_data = {
  429. 'description': 'New description',
  430. }
  431. @classmethod
  432. def setUpTestData(cls):
  433. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  434. devicetype = DeviceType.objects.create(
  435. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  436. )
  437. console_server_port_templates = (
  438. ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 1'),
  439. ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 2'),
  440. ConsoleServerPortTemplate(device_type=devicetype, name='Console Server Port Template 3'),
  441. )
  442. ConsoleServerPortTemplate.objects.bulk_create(console_server_port_templates)
  443. cls.create_data = [
  444. {
  445. 'device_type': devicetype.pk,
  446. 'name': 'Console Server Port Template 4',
  447. },
  448. {
  449. 'device_type': devicetype.pk,
  450. 'name': 'Console Server Port Template 5',
  451. },
  452. {
  453. 'device_type': devicetype.pk,
  454. 'name': 'Console Server Port Template 6',
  455. },
  456. ]
  457. class PowerPortTemplateTest(APIViewTestCases.APIViewTestCase):
  458. model = PowerPortTemplate
  459. brief_fields = ['display', 'id', 'name', 'url']
  460. bulk_update_data = {
  461. 'description': 'New description',
  462. }
  463. @classmethod
  464. def setUpTestData(cls):
  465. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  466. devicetype = DeviceType.objects.create(
  467. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  468. )
  469. power_port_templates = (
  470. PowerPortTemplate(device_type=devicetype, name='Power Port Template 1'),
  471. PowerPortTemplate(device_type=devicetype, name='Power Port Template 2'),
  472. PowerPortTemplate(device_type=devicetype, name='Power Port Template 3'),
  473. )
  474. PowerPortTemplate.objects.bulk_create(power_port_templates)
  475. cls.create_data = [
  476. {
  477. 'device_type': devicetype.pk,
  478. 'name': 'Power Port Template 4',
  479. },
  480. {
  481. 'device_type': devicetype.pk,
  482. 'name': 'Power Port Template 5',
  483. },
  484. {
  485. 'device_type': devicetype.pk,
  486. 'name': 'Power Port Template 6',
  487. },
  488. ]
  489. class PowerOutletTemplateTest(APIViewTestCases.APIViewTestCase):
  490. model = PowerOutletTemplate
  491. brief_fields = ['display', 'id', 'name', 'url']
  492. bulk_update_data = {
  493. 'description': 'New description',
  494. }
  495. @classmethod
  496. def setUpTestData(cls):
  497. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  498. devicetype = DeviceType.objects.create(
  499. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  500. )
  501. power_outlet_templates = (
  502. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 1'),
  503. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 2'),
  504. PowerOutletTemplate(device_type=devicetype, name='Power Outlet Template 3'),
  505. )
  506. PowerOutletTemplate.objects.bulk_create(power_outlet_templates)
  507. cls.create_data = [
  508. {
  509. 'device_type': devicetype.pk,
  510. 'name': 'Power Outlet Template 4',
  511. },
  512. {
  513. 'device_type': devicetype.pk,
  514. 'name': 'Power Outlet Template 5',
  515. },
  516. {
  517. 'device_type': devicetype.pk,
  518. 'name': 'Power Outlet Template 6',
  519. },
  520. ]
  521. class InterfaceTemplateTest(APIViewTestCases.APIViewTestCase):
  522. model = InterfaceTemplate
  523. brief_fields = ['display', 'id', 'name', 'url']
  524. bulk_update_data = {
  525. 'description': 'New description',
  526. }
  527. @classmethod
  528. def setUpTestData(cls):
  529. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  530. devicetype = DeviceType.objects.create(
  531. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  532. )
  533. interface_templates = (
  534. InterfaceTemplate(device_type=devicetype, name='Interface Template 1', type='1000base-t'),
  535. InterfaceTemplate(device_type=devicetype, name='Interface Template 2', type='1000base-t'),
  536. InterfaceTemplate(device_type=devicetype, name='Interface Template 3', type='1000base-t'),
  537. )
  538. InterfaceTemplate.objects.bulk_create(interface_templates)
  539. cls.create_data = [
  540. {
  541. 'device_type': devicetype.pk,
  542. 'name': 'Interface Template 4',
  543. 'type': '1000base-t',
  544. },
  545. {
  546. 'device_type': devicetype.pk,
  547. 'name': 'Interface Template 5',
  548. 'type': '1000base-t',
  549. },
  550. {
  551. 'device_type': devicetype.pk,
  552. 'name': 'Interface Template 6',
  553. 'type': '1000base-t',
  554. },
  555. ]
  556. class FrontPortTemplateTest(APIViewTestCases.APIViewTestCase):
  557. model = FrontPortTemplate
  558. brief_fields = ['display', 'id', 'name', 'url']
  559. bulk_update_data = {
  560. 'description': 'New description',
  561. }
  562. @classmethod
  563. def setUpTestData(cls):
  564. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  565. devicetype = DeviceType.objects.create(
  566. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  567. )
  568. rear_port_templates = (
  569. RearPortTemplate(device_type=devicetype, name='Rear Port Template 1', type=PortTypeChoices.TYPE_8P8C),
  570. RearPortTemplate(device_type=devicetype, name='Rear Port Template 2', type=PortTypeChoices.TYPE_8P8C),
  571. RearPortTemplate(device_type=devicetype, name='Rear Port Template 3', type=PortTypeChoices.TYPE_8P8C),
  572. RearPortTemplate(device_type=devicetype, name='Rear Port Template 4', type=PortTypeChoices.TYPE_8P8C),
  573. RearPortTemplate(device_type=devicetype, name='Rear Port Template 5', type=PortTypeChoices.TYPE_8P8C),
  574. RearPortTemplate(device_type=devicetype, name='Rear Port Template 6', type=PortTypeChoices.TYPE_8P8C),
  575. )
  576. RearPortTemplate.objects.bulk_create(rear_port_templates)
  577. front_port_templates = (
  578. FrontPortTemplate(
  579. device_type=devicetype,
  580. name='Front Port Template 1',
  581. type=PortTypeChoices.TYPE_8P8C,
  582. rear_port=rear_port_templates[0]
  583. ),
  584. FrontPortTemplate(
  585. device_type=devicetype,
  586. name='Front Port Template 2',
  587. type=PortTypeChoices.TYPE_8P8C,
  588. rear_port=rear_port_templates[1]
  589. ),
  590. FrontPortTemplate(
  591. device_type=devicetype,
  592. name='Front Port Template 3',
  593. type=PortTypeChoices.TYPE_8P8C,
  594. rear_port=rear_port_templates[2]
  595. ),
  596. )
  597. FrontPortTemplate.objects.bulk_create(front_port_templates)
  598. cls.create_data = [
  599. {
  600. 'device_type': devicetype.pk,
  601. 'name': 'Front Port Template 4',
  602. 'type': PortTypeChoices.TYPE_8P8C,
  603. 'rear_port': rear_port_templates[3].pk,
  604. 'rear_port_position': 1,
  605. },
  606. {
  607. 'device_type': devicetype.pk,
  608. 'name': 'Front Port Template 5',
  609. 'type': PortTypeChoices.TYPE_8P8C,
  610. 'rear_port': rear_port_templates[4].pk,
  611. 'rear_port_position': 1,
  612. },
  613. {
  614. 'device_type': devicetype.pk,
  615. 'name': 'Front Port Template 6',
  616. 'type': PortTypeChoices.TYPE_8P8C,
  617. 'rear_port': rear_port_templates[5].pk,
  618. 'rear_port_position': 1,
  619. },
  620. ]
  621. class RearPortTemplateTest(APIViewTestCases.APIViewTestCase):
  622. model = RearPortTemplate
  623. brief_fields = ['display', 'id', 'name', 'url']
  624. bulk_update_data = {
  625. 'description': 'New description',
  626. }
  627. @classmethod
  628. def setUpTestData(cls):
  629. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  630. devicetype = DeviceType.objects.create(
  631. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  632. )
  633. rear_port_templates = (
  634. RearPortTemplate(device_type=devicetype, name='Rear Port Template 1', type=PortTypeChoices.TYPE_8P8C),
  635. RearPortTemplate(device_type=devicetype, name='Rear Port Template 2', type=PortTypeChoices.TYPE_8P8C),
  636. RearPortTemplate(device_type=devicetype, name='Rear Port Template 3', type=PortTypeChoices.TYPE_8P8C),
  637. )
  638. RearPortTemplate.objects.bulk_create(rear_port_templates)
  639. cls.create_data = [
  640. {
  641. 'device_type': devicetype.pk,
  642. 'name': 'Rear Port Template 4',
  643. 'type': PortTypeChoices.TYPE_8P8C,
  644. },
  645. {
  646. 'device_type': devicetype.pk,
  647. 'name': 'Rear Port Template 5',
  648. 'type': PortTypeChoices.TYPE_8P8C,
  649. },
  650. {
  651. 'device_type': devicetype.pk,
  652. 'name': 'Rear Port Template 6',
  653. 'type': PortTypeChoices.TYPE_8P8C,
  654. },
  655. ]
  656. class DeviceBayTemplateTest(APIViewTestCases.APIViewTestCase):
  657. model = DeviceBayTemplate
  658. brief_fields = ['display', 'id', 'name', 'url']
  659. bulk_update_data = {
  660. 'description': 'New description',
  661. }
  662. @classmethod
  663. def setUpTestData(cls):
  664. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  665. devicetype = DeviceType.objects.create(
  666. manufacturer=manufacturer,
  667. model='Device Type 1',
  668. slug='device-type-1',
  669. subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
  670. )
  671. device_bay_templates = (
  672. DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 1'),
  673. DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 2'),
  674. DeviceBayTemplate(device_type=devicetype, name='Device Bay Template 3'),
  675. )
  676. DeviceBayTemplate.objects.bulk_create(device_bay_templates)
  677. cls.create_data = [
  678. {
  679. 'device_type': devicetype.pk,
  680. 'name': 'Device Bay Template 4',
  681. },
  682. {
  683. 'device_type': devicetype.pk,
  684. 'name': 'Device Bay Template 5',
  685. },
  686. {
  687. 'device_type': devicetype.pk,
  688. 'name': 'Device Bay Template 6',
  689. },
  690. ]
  691. class DeviceRoleTest(APIViewTestCases.APIViewTestCase):
  692. model = DeviceRole
  693. brief_fields = ['device_count', 'display', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
  694. create_data = [
  695. {
  696. 'name': 'Device Role 4',
  697. 'slug': 'device-role-4',
  698. 'color': 'ffff00',
  699. },
  700. {
  701. 'name': 'Device Role 5',
  702. 'slug': 'device-role-5',
  703. 'color': 'ffff00',
  704. },
  705. {
  706. 'name': 'Device Role 6',
  707. 'slug': 'device-role-6',
  708. 'color': 'ffff00',
  709. },
  710. ]
  711. bulk_update_data = {
  712. 'description': 'New description',
  713. }
  714. @classmethod
  715. def setUpTestData(cls):
  716. device_roles = (
  717. DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'),
  718. DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'),
  719. DeviceRole(name='Device Role 3', slug='device-role-3', color='0000ff'),
  720. )
  721. DeviceRole.objects.bulk_create(device_roles)
  722. class PlatformTest(APIViewTestCases.APIViewTestCase):
  723. model = Platform
  724. brief_fields = ['device_count', 'display', 'id', 'name', 'slug', 'url', 'virtualmachine_count']
  725. create_data = [
  726. {
  727. 'name': 'Platform 4',
  728. 'slug': 'platform-4',
  729. },
  730. {
  731. 'name': 'Platform 5',
  732. 'slug': 'platform-5',
  733. },
  734. {
  735. 'name': 'Platform 6',
  736. 'slug': 'platform-6',
  737. },
  738. ]
  739. bulk_update_data = {
  740. 'description': 'New description',
  741. }
  742. @classmethod
  743. def setUpTestData(cls):
  744. platforms = (
  745. Platform(name='Platform 1', slug='platform-1'),
  746. Platform(name='Platform 2', slug='platform-2'),
  747. Platform(name='Platform 3', slug='platform-3'),
  748. )
  749. Platform.objects.bulk_create(platforms)
  750. class DeviceTest(APIViewTestCases.APIViewTestCase):
  751. model = Device
  752. brief_fields = ['display', 'id', 'name', 'url']
  753. bulk_update_data = {
  754. 'status': 'failed',
  755. }
  756. @classmethod
  757. def setUpTestData(cls):
  758. sites = (
  759. Site(name='Site 1', slug='site-1'),
  760. Site(name='Site 2', slug='site-2'),
  761. )
  762. Site.objects.bulk_create(sites)
  763. racks = (
  764. Rack(name='Rack 1', site=sites[0]),
  765. Rack(name='Rack 2', site=sites[1]),
  766. )
  767. Rack.objects.bulk_create(racks)
  768. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  769. device_types = (
  770. DeviceType(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'),
  771. DeviceType(manufacturer=manufacturer, model='Device Type 2', slug='device-type-2'),
  772. )
  773. DeviceType.objects.bulk_create(device_types)
  774. device_roles = (
  775. DeviceRole(name='Device Role 1', slug='device-role-1', color='ff0000'),
  776. DeviceRole(name='Device Role 2', slug='device-role-2', color='00ff00'),
  777. )
  778. DeviceRole.objects.bulk_create(device_roles)
  779. cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
  780. clusters = (
  781. Cluster(name='Cluster 1', type=cluster_type),
  782. Cluster(name='Cluster 2', type=cluster_type),
  783. )
  784. Cluster.objects.bulk_create(clusters)
  785. devices = (
  786. Device(
  787. device_type=device_types[0],
  788. device_role=device_roles[0],
  789. name='Device 1',
  790. site=sites[0],
  791. rack=racks[0],
  792. cluster=clusters[0],
  793. local_context_data={'A': 1}
  794. ),
  795. Device(
  796. device_type=device_types[0],
  797. device_role=device_roles[0],
  798. name='Device 2',
  799. site=sites[0],
  800. rack=racks[0],
  801. cluster=clusters[0],
  802. local_context_data={'B': 2}
  803. ),
  804. Device(
  805. device_type=device_types[0],
  806. device_role=device_roles[0],
  807. name='Device 3',
  808. site=sites[0],
  809. rack=racks[0],
  810. cluster=clusters[0],
  811. local_context_data={'C': 3}
  812. ),
  813. )
  814. Device.objects.bulk_create(devices)
  815. cls.create_data = [
  816. {
  817. 'device_type': device_types[1].pk,
  818. 'device_role': device_roles[1].pk,
  819. 'name': 'Test Device 4',
  820. 'site': sites[1].pk,
  821. 'rack': racks[1].pk,
  822. 'cluster': clusters[1].pk,
  823. },
  824. {
  825. 'device_type': device_types[1].pk,
  826. 'device_role': device_roles[1].pk,
  827. 'name': 'Test Device 5',
  828. 'site': sites[1].pk,
  829. 'rack': racks[1].pk,
  830. 'cluster': clusters[1].pk,
  831. },
  832. {
  833. 'device_type': device_types[1].pk,
  834. 'device_role': device_roles[1].pk,
  835. 'name': 'Test Device 6',
  836. 'site': sites[1].pk,
  837. 'rack': racks[1].pk,
  838. 'cluster': clusters[1].pk,
  839. },
  840. ]
  841. def test_config_context_included_by_default_in_list_view(self):
  842. """
  843. Check that config context data is included by default in the devices list.
  844. """
  845. self.add_permissions('dcim.view_device')
  846. url = reverse('dcim-api:device-list') + '?slug=device-with-context-data'
  847. response = self.client.get(url, **self.header)
  848. self.assertEqual(response.data['results'][0].get('config_context', {}).get('A'), 1)
  849. def test_config_context_excluded(self):
  850. """
  851. Check that config context data can be excluded by passing ?exclude=config_context.
  852. """
  853. self.add_permissions('dcim.view_device')
  854. url = reverse('dcim-api:device-list') + '?exclude=config_context'
  855. response = self.client.get(url, **self.header)
  856. self.assertFalse('config_context' in response.data['results'][0])
  857. def test_unique_name_per_site_constraint(self):
  858. """
  859. Check that creating a device with a duplicate name within a site fails.
  860. """
  861. device = Device.objects.first()
  862. data = {
  863. 'device_type': device.device_type.pk,
  864. 'device_role': device.device_role.pk,
  865. 'site': device.site.pk,
  866. 'name': device.name,
  867. }
  868. self.add_permissions('dcim.add_device')
  869. url = reverse('dcim-api:device-list')
  870. response = self.client.post(url, data, format='json', **self.header)
  871. self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
  872. class ConsolePortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
  873. model = ConsolePort
  874. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  875. bulk_update_data = {
  876. 'description': 'New description',
  877. }
  878. peer_termination_type = ConsoleServerPort
  879. @classmethod
  880. def setUpTestData(cls):
  881. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  882. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  883. site = Site.objects.create(name='Site 1', slug='site-1')
  884. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  885. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  886. console_ports = (
  887. ConsolePort(device=device, name='Console Port 1'),
  888. ConsolePort(device=device, name='Console Port 2'),
  889. ConsolePort(device=device, name='Console Port 3'),
  890. )
  891. ConsolePort.objects.bulk_create(console_ports)
  892. cls.create_data = [
  893. {
  894. 'device': device.pk,
  895. 'name': 'Console Port 4',
  896. },
  897. {
  898. 'device': device.pk,
  899. 'name': 'Console Port 5',
  900. },
  901. {
  902. 'device': device.pk,
  903. 'name': 'Console Port 6',
  904. },
  905. ]
  906. class ConsoleServerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
  907. model = ConsoleServerPort
  908. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  909. bulk_update_data = {
  910. 'description': 'New description',
  911. }
  912. peer_termination_type = ConsolePort
  913. @classmethod
  914. def setUpTestData(cls):
  915. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  916. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  917. site = Site.objects.create(name='Site 1', slug='site-1')
  918. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  919. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  920. console_server_ports = (
  921. ConsoleServerPort(device=device, name='Console Server Port 1'),
  922. ConsoleServerPort(device=device, name='Console Server Port 2'),
  923. ConsoleServerPort(device=device, name='Console Server Port 3'),
  924. )
  925. ConsoleServerPort.objects.bulk_create(console_server_ports)
  926. cls.create_data = [
  927. {
  928. 'device': device.pk,
  929. 'name': 'Console Server Port 4',
  930. },
  931. {
  932. 'device': device.pk,
  933. 'name': 'Console Server Port 5',
  934. },
  935. {
  936. 'device': device.pk,
  937. 'name': 'Console Server Port 6',
  938. },
  939. ]
  940. class PowerPortTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
  941. model = PowerPort
  942. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  943. bulk_update_data = {
  944. 'description': 'New description',
  945. }
  946. peer_termination_type = PowerOutlet
  947. @classmethod
  948. def setUpTestData(cls):
  949. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  950. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  951. site = Site.objects.create(name='Site 1', slug='site-1')
  952. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  953. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  954. power_ports = (
  955. PowerPort(device=device, name='Power Port 1'),
  956. PowerPort(device=device, name='Power Port 2'),
  957. PowerPort(device=device, name='Power Port 3'),
  958. )
  959. PowerPort.objects.bulk_create(power_ports)
  960. cls.create_data = [
  961. {
  962. 'device': device.pk,
  963. 'name': 'Power Port 4',
  964. },
  965. {
  966. 'device': device.pk,
  967. 'name': 'Power Port 5',
  968. },
  969. {
  970. 'device': device.pk,
  971. 'name': 'Power Port 6',
  972. },
  973. ]
  974. class PowerOutletTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
  975. model = PowerOutlet
  976. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  977. bulk_update_data = {
  978. 'description': 'New description',
  979. }
  980. peer_termination_type = PowerPort
  981. @classmethod
  982. def setUpTestData(cls):
  983. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  984. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  985. site = Site.objects.create(name='Site 1', slug='site-1')
  986. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  987. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  988. power_outlets = (
  989. PowerOutlet(device=device, name='Power Outlet 1'),
  990. PowerOutlet(device=device, name='Power Outlet 2'),
  991. PowerOutlet(device=device, name='Power Outlet 3'),
  992. )
  993. PowerOutlet.objects.bulk_create(power_outlets)
  994. cls.create_data = [
  995. {
  996. 'device': device.pk,
  997. 'name': 'Power Outlet 4',
  998. },
  999. {
  1000. 'device': device.pk,
  1001. 'name': 'Power Outlet 5',
  1002. },
  1003. {
  1004. 'device': device.pk,
  1005. 'name': 'Power Outlet 6',
  1006. },
  1007. ]
  1008. class InterfaceTest(Mixins.ComponentTraceMixin, APIViewTestCases.APIViewTestCase):
  1009. model = Interface
  1010. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  1011. bulk_update_data = {
  1012. 'description': 'New description',
  1013. }
  1014. peer_termination_type = Interface
  1015. @classmethod
  1016. def setUpTestData(cls):
  1017. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  1018. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1019. site = Site.objects.create(name='Site 1', slug='site-1')
  1020. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  1021. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  1022. interfaces = (
  1023. Interface(device=device, name='Interface 1', type='1000base-t'),
  1024. Interface(device=device, name='Interface 2', type='1000base-t'),
  1025. Interface(device=device, name='Interface 3', type='1000base-t'),
  1026. )
  1027. Interface.objects.bulk_create(interfaces)
  1028. vlans = (
  1029. VLAN(name='VLAN 1', vid=1),
  1030. VLAN(name='VLAN 2', vid=2),
  1031. VLAN(name='VLAN 3', vid=3),
  1032. )
  1033. VLAN.objects.bulk_create(vlans)
  1034. cls.create_data = [
  1035. {
  1036. 'device': device.pk,
  1037. 'name': 'Interface 4',
  1038. 'type': '1000base-t',
  1039. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1040. 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
  1041. 'untagged_vlan': vlans[2].pk,
  1042. },
  1043. {
  1044. 'device': device.pk,
  1045. 'name': 'Interface 5',
  1046. 'type': '1000base-t',
  1047. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1048. 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
  1049. 'untagged_vlan': vlans[2].pk,
  1050. },
  1051. {
  1052. 'device': device.pk,
  1053. 'name': 'Interface 6',
  1054. 'type': 'virtual',
  1055. 'mode': InterfaceModeChoices.MODE_TAGGED,
  1056. 'parent': interfaces[0].pk,
  1057. 'tagged_vlans': [vlans[0].pk, vlans[1].pk],
  1058. 'untagged_vlan': vlans[2].pk,
  1059. },
  1060. ]
  1061. class FrontPortTest(APIViewTestCases.APIViewTestCase):
  1062. model = FrontPort
  1063. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  1064. bulk_update_data = {
  1065. 'description': 'New description',
  1066. }
  1067. peer_termination_type = Interface
  1068. @classmethod
  1069. def setUpTestData(cls):
  1070. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  1071. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1072. site = Site.objects.create(name='Site 1', slug='site-1')
  1073. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  1074. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  1075. rear_ports = (
  1076. RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C),
  1077. RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C),
  1078. RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C),
  1079. RearPort(device=device, name='Rear Port 4', type=PortTypeChoices.TYPE_8P8C),
  1080. RearPort(device=device, name='Rear Port 5', type=PortTypeChoices.TYPE_8P8C),
  1081. RearPort(device=device, name='Rear Port 6', type=PortTypeChoices.TYPE_8P8C),
  1082. )
  1083. RearPort.objects.bulk_create(rear_ports)
  1084. front_ports = (
  1085. FrontPort(device=device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[0]),
  1086. FrontPort(device=device, name='Front Port 2', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[1]),
  1087. FrontPort(device=device, name='Front Port 3', type=PortTypeChoices.TYPE_8P8C, rear_port=rear_ports[2]),
  1088. )
  1089. FrontPort.objects.bulk_create(front_ports)
  1090. cls.create_data = [
  1091. {
  1092. 'device': device.pk,
  1093. 'name': 'Front Port 4',
  1094. 'type': PortTypeChoices.TYPE_8P8C,
  1095. 'rear_port': rear_ports[3].pk,
  1096. 'rear_port_position': 1,
  1097. },
  1098. {
  1099. 'device': device.pk,
  1100. 'name': 'Front Port 5',
  1101. 'type': PortTypeChoices.TYPE_8P8C,
  1102. 'rear_port': rear_ports[4].pk,
  1103. 'rear_port_position': 1,
  1104. },
  1105. {
  1106. 'device': device.pk,
  1107. 'name': 'Front Port 6',
  1108. 'type': PortTypeChoices.TYPE_8P8C,
  1109. 'rear_port': rear_ports[5].pk,
  1110. 'rear_port_position': 1,
  1111. },
  1112. ]
  1113. class RearPortTest(APIViewTestCases.APIViewTestCase):
  1114. model = RearPort
  1115. brief_fields = ['_occupied', 'cable', 'device', 'display', 'id', 'name', 'url']
  1116. bulk_update_data = {
  1117. 'description': 'New description',
  1118. }
  1119. peer_termination_type = Interface
  1120. @classmethod
  1121. def setUpTestData(cls):
  1122. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  1123. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1124. site = Site.objects.create(name='Site 1', slug='site-1')
  1125. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  1126. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  1127. rear_ports = (
  1128. RearPort(device=device, name='Rear Port 1', type=PortTypeChoices.TYPE_8P8C),
  1129. RearPort(device=device, name='Rear Port 2', type=PortTypeChoices.TYPE_8P8C),
  1130. RearPort(device=device, name='Rear Port 3', type=PortTypeChoices.TYPE_8P8C),
  1131. )
  1132. RearPort.objects.bulk_create(rear_ports)
  1133. cls.create_data = [
  1134. {
  1135. 'device': device.pk,
  1136. 'name': 'Rear Port 4',
  1137. 'type': PortTypeChoices.TYPE_8P8C,
  1138. },
  1139. {
  1140. 'device': device.pk,
  1141. 'name': 'Rear Port 5',
  1142. 'type': PortTypeChoices.TYPE_8P8C,
  1143. },
  1144. {
  1145. 'device': device.pk,
  1146. 'name': 'Rear Port 6',
  1147. 'type': PortTypeChoices.TYPE_8P8C,
  1148. },
  1149. ]
  1150. class DeviceBayTest(APIViewTestCases.APIViewTestCase):
  1151. model = DeviceBay
  1152. brief_fields = ['device', 'display', 'id', 'name', 'url']
  1153. bulk_update_data = {
  1154. 'description': 'New description',
  1155. }
  1156. @classmethod
  1157. def setUpTestData(cls):
  1158. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  1159. site = Site.objects.create(name='Site 1', slug='site-1')
  1160. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  1161. device_types = (
  1162. DeviceType(
  1163. manufacturer=manufacturer,
  1164. model='Device Type 1',
  1165. slug='device-type-1',
  1166. subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
  1167. ),
  1168. DeviceType(
  1169. manufacturer=manufacturer,
  1170. model='Device Type 2',
  1171. slug='device-type-2',
  1172. subdevice_role=SubdeviceRoleChoices.ROLE_CHILD
  1173. ),
  1174. )
  1175. DeviceType.objects.bulk_create(device_types)
  1176. devices = (
  1177. Device(device_type=device_types[0], device_role=devicerole, name='Device 1', site=site),
  1178. Device(device_type=device_types[1], device_role=devicerole, name='Device 2', site=site),
  1179. Device(device_type=device_types[1], device_role=devicerole, name='Device 3', site=site),
  1180. Device(device_type=device_types[1], device_role=devicerole, name='Device 4', site=site),
  1181. )
  1182. Device.objects.bulk_create(devices)
  1183. device_bays = (
  1184. DeviceBay(device=devices[0], name='Device Bay 1'),
  1185. DeviceBay(device=devices[0], name='Device Bay 2'),
  1186. DeviceBay(device=devices[0], name='Device Bay 3'),
  1187. )
  1188. DeviceBay.objects.bulk_create(device_bays)
  1189. cls.create_data = [
  1190. {
  1191. 'device': devices[0].pk,
  1192. 'name': 'Device Bay 4',
  1193. 'installed_device': devices[1].pk,
  1194. },
  1195. {
  1196. 'device': devices[0].pk,
  1197. 'name': 'Device Bay 5',
  1198. 'installed_device': devices[2].pk,
  1199. },
  1200. {
  1201. 'device': devices[0].pk,
  1202. 'name': 'Device Bay 6',
  1203. 'installed_device': devices[3].pk,
  1204. },
  1205. ]
  1206. class InventoryItemTest(APIViewTestCases.APIViewTestCase):
  1207. model = InventoryItem
  1208. brief_fields = ['_depth', 'device', 'display', 'id', 'name', 'url']
  1209. bulk_update_data = {
  1210. 'description': 'New description',
  1211. }
  1212. @classmethod
  1213. def setUpTestData(cls):
  1214. manufacturer = Manufacturer.objects.create(name='Test Manufacturer 1', slug='test-manufacturer-1')
  1215. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1216. site = Site.objects.create(name='Site 1', slug='site-1')
  1217. devicerole = DeviceRole.objects.create(name='Test Device Role 1', slug='test-device-role-1', color='ff0000')
  1218. device = Device.objects.create(device_type=devicetype, device_role=devicerole, name='Device 1', site=site)
  1219. InventoryItem.objects.create(device=device, name='Inventory Item 1', manufacturer=manufacturer)
  1220. InventoryItem.objects.create(device=device, name='Inventory Item 2', manufacturer=manufacturer)
  1221. InventoryItem.objects.create(device=device, name='Inventory Item 3', manufacturer=manufacturer)
  1222. cls.create_data = [
  1223. {
  1224. 'device': device.pk,
  1225. 'name': 'Inventory Item 4',
  1226. 'manufacturer': manufacturer.pk,
  1227. },
  1228. {
  1229. 'device': device.pk,
  1230. 'name': 'Inventory Item 5',
  1231. 'manufacturer': manufacturer.pk,
  1232. },
  1233. {
  1234. 'device': device.pk,
  1235. 'name': 'Inventory Item 6',
  1236. 'manufacturer': manufacturer.pk,
  1237. },
  1238. ]
  1239. class CableTest(APIViewTestCases.APIViewTestCase):
  1240. model = Cable
  1241. brief_fields = ['display', 'id', 'label', 'url']
  1242. bulk_update_data = {
  1243. 'length': 100,
  1244. 'length_unit': 'm',
  1245. }
  1246. # TODO: Allow updating cable terminations
  1247. test_update_object = None
  1248. @classmethod
  1249. def setUpTestData(cls):
  1250. site = Site.objects.create(name='Site 1', slug='site-1')
  1251. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  1252. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1253. devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1', color='ff0000')
  1254. devices = (
  1255. Device(device_type=devicetype, device_role=devicerole, name='Device 1', site=site),
  1256. Device(device_type=devicetype, device_role=devicerole, name='Device 2', site=site),
  1257. )
  1258. Device.objects.bulk_create(devices)
  1259. interfaces = []
  1260. for device in devices:
  1261. for i in range(0, 10):
  1262. interfaces.append(Interface(device=device, type=InterfaceTypeChoices.TYPE_1GE_FIXED, name=f'eth{i}'))
  1263. Interface.objects.bulk_create(interfaces)
  1264. cables = (
  1265. Cable(termination_a=interfaces[0], termination_b=interfaces[10], label='Cable 1'),
  1266. Cable(termination_a=interfaces[1], termination_b=interfaces[11], label='Cable 2'),
  1267. Cable(termination_a=interfaces[2], termination_b=interfaces[12], label='Cable 3'),
  1268. )
  1269. for cable in cables:
  1270. cable.save()
  1271. cls.create_data = [
  1272. {
  1273. 'termination_a_type': 'dcim.interface',
  1274. 'termination_a_id': interfaces[4].pk,
  1275. 'termination_b_type': 'dcim.interface',
  1276. 'termination_b_id': interfaces[14].pk,
  1277. 'label': 'Cable 4',
  1278. },
  1279. {
  1280. 'termination_a_type': 'dcim.interface',
  1281. 'termination_a_id': interfaces[5].pk,
  1282. 'termination_b_type': 'dcim.interface',
  1283. 'termination_b_id': interfaces[15].pk,
  1284. 'label': 'Cable 5',
  1285. },
  1286. {
  1287. 'termination_a_type': 'dcim.interface',
  1288. 'termination_a_id': interfaces[6].pk,
  1289. 'termination_b_type': 'dcim.interface',
  1290. 'termination_b_id': interfaces[16].pk,
  1291. 'label': 'Cable 6',
  1292. },
  1293. ]
  1294. class ConnectedDeviceTest(APITestCase):
  1295. def setUp(self):
  1296. super().setUp()
  1297. site = Site.objects.create(name='Site 1', slug='site-1')
  1298. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  1299. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1')
  1300. devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1', color='ff0000')
  1301. self.device1 = Device.objects.create(
  1302. device_type=devicetype, device_role=devicerole, name='TestDevice1', site=site
  1303. )
  1304. self.device2 = Device.objects.create(
  1305. device_type=devicetype, device_role=devicerole, name='TestDevice2', site=site
  1306. )
  1307. self.interface1 = Interface.objects.create(device=self.device1, name='eth0')
  1308. self.interface2 = Interface.objects.create(device=self.device2, name='eth0')
  1309. self.interface3 = Interface.objects.create(device=self.device1, name='eth1') # Not connected
  1310. cable = Cable(termination_a=self.interface1, termination_b=self.interface2)
  1311. cable.save()
  1312. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  1313. def test_get_connected_device(self):
  1314. url = reverse('dcim-api:connected-device-list')
  1315. url_params = f'?peer_device={self.device1.name}&peer_interface={self.interface1.name}'
  1316. response = self.client.get(url + url_params, **self.header)
  1317. self.assertHttpStatus(response, status.HTTP_200_OK)
  1318. self.assertEqual(response.data['name'], self.device2.name)
  1319. url_params = f'?peer_device={self.device1.name}&peer_interface={self.interface3.name}'
  1320. response = self.client.get(url + url_params, **self.header)
  1321. self.assertHttpStatus(response, status.HTTP_404_NOT_FOUND)
  1322. class VirtualChassisTest(APIViewTestCases.APIViewTestCase):
  1323. model = VirtualChassis
  1324. brief_fields = ['display', 'id', 'master', 'member_count', 'name', 'url']
  1325. @classmethod
  1326. def setUpTestData(cls):
  1327. site = Site.objects.create(name='Test Site', slug='test-site')
  1328. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  1329. devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type', slug='device-type')
  1330. devicerole = DeviceRole.objects.create(name='Device Role', slug='device-role', color='ff0000')
  1331. devices = (
  1332. Device(name='Device 1', device_type=devicetype, device_role=devicerole, site=site),
  1333. Device(name='Device 2', device_type=devicetype, device_role=devicerole, site=site),
  1334. Device(name='Device 3', device_type=devicetype, device_role=devicerole, site=site),
  1335. Device(name='Device 4', device_type=devicetype, device_role=devicerole, site=site),
  1336. Device(name='Device 5', device_type=devicetype, device_role=devicerole, site=site),
  1337. Device(name='Device 6', device_type=devicetype, device_role=devicerole, site=site),
  1338. Device(name='Device 7', device_type=devicetype, device_role=devicerole, site=site),
  1339. Device(name='Device 8', device_type=devicetype, device_role=devicerole, site=site),
  1340. Device(name='Device 9', device_type=devicetype, device_role=devicerole, site=site),
  1341. Device(name='Device 10', device_type=devicetype, device_role=devicerole, site=site),
  1342. Device(name='Device 11', device_type=devicetype, device_role=devicerole, site=site),
  1343. Device(name='Device 12', device_type=devicetype, device_role=devicerole, site=site),
  1344. )
  1345. Device.objects.bulk_create(devices)
  1346. # Create 12 interfaces per device
  1347. interfaces = []
  1348. for i, device in enumerate(devices):
  1349. for j in range(0, 13):
  1350. interfaces.append(
  1351. # Interface name starts with parent device's position in VC; e.g. 1/1, 1/2, 1/3...
  1352. Interface(device=device, name=f'{i%3+1}/{j}', type=InterfaceTypeChoices.TYPE_1GE_FIXED)
  1353. )
  1354. Interface.objects.bulk_create(interfaces)
  1355. # Create three VirtualChassis with three members each
  1356. virtual_chassis = (
  1357. VirtualChassis(name='Virtual Chassis 1', master=devices[0], domain='domain-1'),
  1358. VirtualChassis(name='Virtual Chassis 2', master=devices[3], domain='domain-2'),
  1359. VirtualChassis(name='Virtual Chassis 3', master=devices[6], domain='domain-3'),
  1360. )
  1361. VirtualChassis.objects.bulk_create(virtual_chassis)
  1362. Device.objects.filter(pk=devices[0].pk).update(virtual_chassis=virtual_chassis[0], vc_position=1)
  1363. Device.objects.filter(pk=devices[1].pk).update(virtual_chassis=virtual_chassis[0], vc_position=2)
  1364. Device.objects.filter(pk=devices[2].pk).update(virtual_chassis=virtual_chassis[0], vc_position=3)
  1365. Device.objects.filter(pk=devices[3].pk).update(virtual_chassis=virtual_chassis[1], vc_position=1)
  1366. Device.objects.filter(pk=devices[4].pk).update(virtual_chassis=virtual_chassis[1], vc_position=2)
  1367. Device.objects.filter(pk=devices[5].pk).update(virtual_chassis=virtual_chassis[1], vc_position=3)
  1368. Device.objects.filter(pk=devices[6].pk).update(virtual_chassis=virtual_chassis[2], vc_position=1)
  1369. Device.objects.filter(pk=devices[7].pk).update(virtual_chassis=virtual_chassis[2], vc_position=2)
  1370. Device.objects.filter(pk=devices[8].pk).update(virtual_chassis=virtual_chassis[2], vc_position=3)
  1371. cls.update_data = {
  1372. 'name': 'Virtual Chassis X',
  1373. 'domain': 'domain-x',
  1374. 'master': devices[1].pk,
  1375. }
  1376. cls.create_data = [
  1377. {
  1378. 'name': 'Virtual Chassis 4',
  1379. 'domain': 'domain-4',
  1380. },
  1381. {
  1382. 'name': 'Virtual Chassis 5',
  1383. 'domain': 'domain-5',
  1384. },
  1385. {
  1386. 'name': 'Virtual Chassis 6',
  1387. 'domain': 'domain-6',
  1388. },
  1389. ]
  1390. cls.bulk_update_data = {
  1391. 'domain': 'newdomain',
  1392. }
  1393. class PowerPanelTest(APIViewTestCases.APIViewTestCase):
  1394. model = PowerPanel
  1395. brief_fields = ['display', 'id', 'name', 'powerfeed_count', 'url']
  1396. @classmethod
  1397. def setUpTestData(cls):
  1398. sites = (
  1399. Site.objects.create(name='Site 1', slug='site-1'),
  1400. Site.objects.create(name='Site 2', slug='site-2'),
  1401. )
  1402. locations = (
  1403. Location.objects.create(name='Location 1', slug='location-1', site=sites[0]),
  1404. Location.objects.create(name='Location 2', slug='location-2', site=sites[0]),
  1405. Location.objects.create(name='Location 3', slug='location-3', site=sites[0]),
  1406. Location.objects.create(name='Location 4', slug='location-3', site=sites[1]),
  1407. )
  1408. power_panels = (
  1409. PowerPanel(site=sites[0], location=locations[0], name='Power Panel 1'),
  1410. PowerPanel(site=sites[0], location=locations[1], name='Power Panel 2'),
  1411. PowerPanel(site=sites[0], location=locations[2], name='Power Panel 3'),
  1412. )
  1413. PowerPanel.objects.bulk_create(power_panels)
  1414. cls.create_data = [
  1415. {
  1416. 'name': 'Power Panel 4',
  1417. 'site': sites[0].pk,
  1418. 'location': locations[0].pk,
  1419. },
  1420. {
  1421. 'name': 'Power Panel 5',
  1422. 'site': sites[0].pk,
  1423. 'location': locations[1].pk,
  1424. },
  1425. {
  1426. 'name': 'Power Panel 6',
  1427. 'site': sites[0].pk,
  1428. 'location': locations[2].pk,
  1429. },
  1430. ]
  1431. cls.bulk_update_data = {
  1432. 'site': sites[1].pk,
  1433. 'location': locations[3].pk
  1434. }
  1435. class PowerFeedTest(APIViewTestCases.APIViewTestCase):
  1436. model = PowerFeed
  1437. brief_fields = ['_occupied', 'cable', 'display', 'id', 'name', 'url']
  1438. bulk_update_data = {
  1439. 'status': 'planned',
  1440. }
  1441. @classmethod
  1442. def setUpTestData(cls):
  1443. site = Site.objects.create(name='Site 1', slug='site-1')
  1444. location = Location.objects.create(site=site, name='Location 1', slug='location-1')
  1445. rackrole = RackRole.objects.create(name='Rack Role 1', slug='rack-role-1', color='ff0000')
  1446. racks = (
  1447. Rack(site=site, location=location, role=rackrole, name='Rack 1'),
  1448. Rack(site=site, location=location, role=rackrole, name='Rack 2'),
  1449. Rack(site=site, location=location, role=rackrole, name='Rack 3'),
  1450. Rack(site=site, location=location, role=rackrole, name='Rack 4'),
  1451. )
  1452. Rack.objects.bulk_create(racks)
  1453. power_panels = (
  1454. PowerPanel(site=site, location=location, name='Power Panel 1'),
  1455. PowerPanel(site=site, location=location, name='Power Panel 2'),
  1456. )
  1457. PowerPanel.objects.bulk_create(power_panels)
  1458. PRIMARY = PowerFeedTypeChoices.TYPE_PRIMARY
  1459. REDUNDANT = PowerFeedTypeChoices.TYPE_REDUNDANT
  1460. power_feeds = (
  1461. PowerFeed(power_panel=power_panels[0], rack=racks[0], name='Power Feed 1A', type=PRIMARY),
  1462. PowerFeed(power_panel=power_panels[1], rack=racks[0], name='Power Feed 1B', type=REDUNDANT),
  1463. PowerFeed(power_panel=power_panels[0], rack=racks[1], name='Power Feed 2A', type=PRIMARY),
  1464. PowerFeed(power_panel=power_panels[1], rack=racks[1], name='Power Feed 2B', type=REDUNDANT),
  1465. PowerFeed(power_panel=power_panels[0], rack=racks[2], name='Power Feed 3A', type=PRIMARY),
  1466. PowerFeed(power_panel=power_panels[1], rack=racks[2], name='Power Feed 3B', type=REDUNDANT),
  1467. )
  1468. PowerFeed.objects.bulk_create(power_feeds)
  1469. cls.create_data = [
  1470. {
  1471. 'name': 'Power Feed 4A',
  1472. 'power_panel': power_panels[0].pk,
  1473. 'rack': racks[3].pk,
  1474. 'type': PRIMARY,
  1475. },
  1476. {
  1477. 'name': 'Power Feed 4B',
  1478. 'power_panel': power_panels[1].pk,
  1479. 'rack': racks[3].pk,
  1480. 'type': REDUNDANT,
  1481. },
  1482. ]