test_views.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176
  1. import urllib.parse
  2. from decimal import Decimal
  3. import pytz
  4. import yaml
  5. from django.contrib.auth.models import User
  6. from django.contrib.contenttypes.models import ContentType
  7. from django.urls import reverse
  8. from dcim.choices import *
  9. from dcim.constants import *
  10. from dcim.models import *
  11. from utilities.testing import StandardTestCases, TestCase
  12. class RegionTestCase(StandardTestCases.Views):
  13. model = Region
  14. # Disable inapplicable tests
  15. test_get_object = None
  16. test_delete_object = None
  17. @classmethod
  18. def setUpTestData(cls):
  19. # Create three Regions
  20. regions = (
  21. Region(name='Region 1', slug='region-1'),
  22. Region(name='Region 2', slug='region-2'),
  23. Region(name='Region 3', slug='region-3'),
  24. )
  25. for region in regions:
  26. region.save()
  27. cls.form_data = {
  28. 'name': 'Region X',
  29. 'slug': 'region-x',
  30. 'parent': regions[2].pk,
  31. }
  32. cls.csv_data = (
  33. "name,slug",
  34. "Region 4,region-4",
  35. "Region 5,region-5",
  36. "Region 6,region-6",
  37. )
  38. class SiteTestCase(StandardTestCases.Views):
  39. model = Site
  40. @classmethod
  41. def setUpTestData(cls):
  42. region = Region(name='Region 1', slug='region-1')
  43. region.save()
  44. Site.objects.bulk_create([
  45. Site(name='Site 1', slug='site-1', region=region),
  46. Site(name='Site 2', slug='site-2', region=region),
  47. Site(name='Site 3', slug='site-3', region=region),
  48. ])
  49. cls.form_data = {
  50. 'name': 'Site X',
  51. 'slug': 'site-x',
  52. 'status': SiteStatusChoices.STATUS_PLANNED,
  53. 'region': region.pk,
  54. 'tenant': None,
  55. 'facility': 'Facility X',
  56. 'asn': 65001,
  57. 'time_zone': pytz.UTC,
  58. 'description': 'Site description',
  59. 'physical_address': '742 Evergreen Terrace, Springfield, USA',
  60. 'shipping_address': '742 Evergreen Terrace, Springfield, USA',
  61. 'latitude': Decimal('35.780000'),
  62. 'longitude': Decimal('-78.642000'),
  63. 'contact_name': 'Hank Hill',
  64. 'contact_phone': '123-555-9999',
  65. 'contact_email': 'hank@stricklandpropane.com',
  66. 'comments': 'Test site',
  67. 'tags': 'Alpha,Bravo,Charlie',
  68. }
  69. cls.csv_data = (
  70. "name,slug",
  71. "Site 4,site-4",
  72. "Site 5,site-5",
  73. "Site 6,site-6",
  74. )
  75. class RackGroupTestCase(StandardTestCases.Views):
  76. model = RackGroup
  77. # Disable inapplicable tests
  78. test_get_object = None
  79. test_delete_object = None
  80. @classmethod
  81. def setUpTestData(cls):
  82. site = Site(name='Site 1', slug='site-1')
  83. site.save()
  84. RackGroup.objects.bulk_create([
  85. RackGroup(name='Rack Group 1', slug='rack-group-1', site=site),
  86. RackGroup(name='Rack Group 2', slug='rack-group-2', site=site),
  87. RackGroup(name='Rack Group 3', slug='rack-group-3', site=site),
  88. ])
  89. cls.form_data = {
  90. 'name': 'Rack Group X',
  91. 'slug': 'rack-group-x',
  92. 'site': site.pk,
  93. }
  94. cls.csv_data = (
  95. "site,name,slug",
  96. "Site 1,Rack Group 4,rack-group-4",
  97. "Site 1,Rack Group 5,rack-group-5",
  98. "Site 1,Rack Group 6,rack-group-6",
  99. )
  100. class RackRoleTestCase(StandardTestCases.Views):
  101. model = RackRole
  102. # Disable inapplicable tests
  103. test_get_object = None
  104. test_delete_object = None
  105. @classmethod
  106. def setUpTestData(cls):
  107. RackRole.objects.bulk_create([
  108. RackRole(name='Rack Role 1', slug='rack-role-1'),
  109. RackRole(name='Rack Role 2', slug='rack-role-2'),
  110. RackRole(name='Rack Role 3', slug='rack-role-3'),
  111. ])
  112. cls.form_data = {
  113. 'name': 'Rack Role X',
  114. 'slug': 'rack-role-x',
  115. 'color': 'c0c0c0',
  116. 'description': 'New role',
  117. }
  118. cls.csv_data = (
  119. "name,slug,color",
  120. "Rack Role 4,rack-role-4,ff0000",
  121. "Rack Role 5,rack-role-5,00ff00",
  122. "Rack Role 6,rack-role-6,0000ff",
  123. )
  124. class RackReservationTestCase(StandardTestCases.Views):
  125. model = RackReservation
  126. # Disable inapplicable tests
  127. test_get_object = None
  128. test_create_object = None # TODO: Fix URL name for view
  129. test_import_objects = None
  130. @classmethod
  131. def setUpTestData(cls):
  132. user = User.objects.create_user(username='testuser2')
  133. site = Site(name='Site 1', slug='site-1')
  134. site.save()
  135. rack = Rack(name='Rack 1', site=site)
  136. rack.save()
  137. RackReservation.objects.bulk_create([
  138. RackReservation(rack=rack, user=user, units=[1, 2, 3], description='Reservation 1'),
  139. RackReservation(rack=rack, user=user, units=[4, 5, 6], description='Reservation 2'),
  140. RackReservation(rack=rack, user=user, units=[7, 8, 9], description='Reservation 3'),
  141. ])
  142. cls.form_data = {
  143. 'rack': rack.pk,
  144. 'units': [10, 11, 12],
  145. 'user': user.pk,
  146. 'tenant': None,
  147. 'description': 'New reservation',
  148. }
  149. class RackTestCase(StandardTestCases.Views):
  150. model = Rack
  151. @classmethod
  152. def setUpTestData(cls):
  153. site = Site.objects.create(name='Site 1', slug='site-1')
  154. rackgroup = RackGroup.objects.create(name='Rack Group 1', slug='rack-group-1', site=site)
  155. rackrole = RackRole.objects.create(name='Rack Role 1', slug='rack-role-1')
  156. Rack.objects.bulk_create([
  157. Rack(name='Rack 1', site=site),
  158. Rack(name='Rack 2', site=site),
  159. Rack(name='Rack 3', site=site),
  160. ])
  161. cls.form_data = {
  162. 'name': 'Rack X',
  163. 'facility_id': 'Facility X',
  164. 'site': site.pk,
  165. 'group': rackgroup.pk,
  166. 'tenant': None,
  167. 'status': RackStatusChoices.STATUS_PLANNED,
  168. 'role': rackrole.pk,
  169. 'serial': '123456',
  170. 'asset_tag': 'ABCDEF',
  171. 'type': RackTypeChoices.TYPE_CABINET,
  172. 'width': RackWidthChoices.WIDTH_19IN,
  173. 'u_height': 48,
  174. 'desc_units': False,
  175. 'outer_width': 500,
  176. 'outer_depth': 500,
  177. 'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER,
  178. 'comments': 'Some comments',
  179. 'tags': 'Alpha,Bravo,Charlie',
  180. }
  181. cls.csv_data = (
  182. "site,name,width,u_height",
  183. "Site 1,Rack 4,19,42",
  184. "Site 1,Rack 5,19,42",
  185. "Site 1,Rack 6,19,42",
  186. )
  187. class ManufacturerTestCase(StandardTestCases.Views):
  188. model = Manufacturer
  189. # Disable inapplicable tests
  190. test_get_object = None
  191. test_delete_object = None
  192. @classmethod
  193. def setUpTestData(cls):
  194. Manufacturer.objects.bulk_create([
  195. Manufacturer(name='Manufacturer 1', slug='manufacturer-1'),
  196. Manufacturer(name='Manufacturer 2', slug='manufacturer-2'),
  197. Manufacturer(name='Manufacturer 3', slug='manufacturer-3'),
  198. ])
  199. cls.form_data = {
  200. 'name': 'Manufacturer X',
  201. 'slug': 'manufacturer-x',
  202. }
  203. cls.csv_data = (
  204. "name,slug",
  205. "Manufacturer 4,manufacturer-4",
  206. "Manufacturer 5,manufacturer-5",
  207. "Manufacturer 6,manufacturer-6",
  208. )
  209. class DeviceTypeTestCase(StandardTestCases.Views):
  210. model = DeviceType
  211. @classmethod
  212. def setUpTestData(cls):
  213. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  214. manufacturer.save()
  215. DeviceType.objects.bulk_create([
  216. DeviceType(model='Device Type 1', slug='device-type-1', manufacturer=manufacturer),
  217. DeviceType(model='Device Type 2', slug='device-type-2', manufacturer=manufacturer),
  218. DeviceType(model='Device Type 3', slug='device-type-3', manufacturer=manufacturer),
  219. ])
  220. cls.form_data = {
  221. 'manufacturer': manufacturer.pk,
  222. 'model': 'Device Type X',
  223. 'slug': 'device-type-x',
  224. 'part_number': '123ABC',
  225. 'u_height': 2,
  226. 'is_full_depth': True,
  227. 'subdevice_role': '', # CharField
  228. 'comments': 'Some comments',
  229. 'tags': 'Alpha,Bravo,Charlie',
  230. }
  231. def test_import_objects(self):
  232. """
  233. Custom import test for YAML-based imports (versus CSV)
  234. """
  235. IMPORT_DATA = """
  236. manufacturer: Generic
  237. model: TEST-1000
  238. slug: test-1000
  239. u_height: 2
  240. console-ports:
  241. - name: Console Port 1
  242. type: de-9
  243. - name: Console Port 2
  244. type: de-9
  245. - name: Console Port 3
  246. type: de-9
  247. console-server-ports:
  248. - name: Console Server Port 1
  249. type: rj-45
  250. - name: Console Server Port 2
  251. type: rj-45
  252. - name: Console Server Port 3
  253. type: rj-45
  254. power-ports:
  255. - name: Power Port 1
  256. type: iec-60320-c14
  257. - name: Power Port 2
  258. type: iec-60320-c14
  259. - name: Power Port 3
  260. type: iec-60320-c14
  261. power-outlets:
  262. - name: Power Outlet 1
  263. type: iec-60320-c13
  264. power_port: Power Port 1
  265. feed_leg: A
  266. - name: Power Outlet 2
  267. type: iec-60320-c13
  268. power_port: Power Port 1
  269. feed_leg: A
  270. - name: Power Outlet 3
  271. type: iec-60320-c13
  272. power_port: Power Port 1
  273. feed_leg: A
  274. interfaces:
  275. - name: Interface 1
  276. type: 1000base-t
  277. mgmt_only: true
  278. - name: Interface 2
  279. type: 1000base-t
  280. - name: Interface 3
  281. type: 1000base-t
  282. rear-ports:
  283. - name: Rear Port 1
  284. type: 8p8c
  285. - name: Rear Port 2
  286. type: 8p8c
  287. - name: Rear Port 3
  288. type: 8p8c
  289. front-ports:
  290. - name: Front Port 1
  291. type: 8p8c
  292. rear_port: Rear Port 1
  293. - name: Front Port 2
  294. type: 8p8c
  295. rear_port: Rear Port 2
  296. - name: Front Port 3
  297. type: 8p8c
  298. rear_port: Rear Port 3
  299. device-bays:
  300. - name: Device Bay 1
  301. - name: Device Bay 2
  302. - name: Device Bay 3
  303. """
  304. # Create the manufacturer
  305. Manufacturer(name='Generic', slug='generic').save()
  306. # Add all required permissions to the test user
  307. self.add_permissions(
  308. 'dcim.view_devicetype',
  309. 'dcim.add_devicetype',
  310. 'dcim.add_consoleporttemplate',
  311. 'dcim.add_consoleserverporttemplate',
  312. 'dcim.add_powerporttemplate',
  313. 'dcim.add_poweroutlettemplate',
  314. 'dcim.add_interfacetemplate',
  315. 'dcim.add_frontporttemplate',
  316. 'dcim.add_rearporttemplate',
  317. 'dcim.add_devicebaytemplate',
  318. )
  319. form_data = {
  320. 'data': IMPORT_DATA,
  321. 'format': 'yaml'
  322. }
  323. response = self.client.post(reverse('dcim:devicetype_import'), data=form_data, follow=True)
  324. self.assertHttpStatus(response, 200)
  325. dt = DeviceType.objects.get(model='TEST-1000')
  326. # Verify all of the components were created
  327. self.assertEqual(dt.consoleport_templates.count(), 3)
  328. cp1 = ConsolePortTemplate.objects.first()
  329. self.assertEqual(cp1.name, 'Console Port 1')
  330. self.assertEqual(cp1.type, ConsolePortTypeChoices.TYPE_DE9)
  331. self.assertEqual(dt.consoleserverport_templates.count(), 3)
  332. csp1 = ConsoleServerPortTemplate.objects.first()
  333. self.assertEqual(csp1.name, 'Console Server Port 1')
  334. self.assertEqual(csp1.type, ConsolePortTypeChoices.TYPE_RJ45)
  335. self.assertEqual(dt.powerport_templates.count(), 3)
  336. pp1 = PowerPortTemplate.objects.first()
  337. self.assertEqual(pp1.name, 'Power Port 1')
  338. self.assertEqual(pp1.type, PowerPortTypeChoices.TYPE_IEC_C14)
  339. self.assertEqual(dt.poweroutlet_templates.count(), 3)
  340. po1 = PowerOutletTemplate.objects.first()
  341. self.assertEqual(po1.name, 'Power Outlet 1')
  342. self.assertEqual(po1.type, PowerOutletTypeChoices.TYPE_IEC_C13)
  343. self.assertEqual(po1.power_port, pp1)
  344. self.assertEqual(po1.feed_leg, PowerOutletFeedLegChoices.FEED_LEG_A)
  345. self.assertEqual(dt.interface_templates.count(), 3)
  346. iface1 = InterfaceTemplate.objects.first()
  347. self.assertEqual(iface1.name, 'Interface 1')
  348. self.assertEqual(iface1.type, InterfaceTypeChoices.TYPE_1GE_FIXED)
  349. self.assertTrue(iface1.mgmt_only)
  350. self.assertEqual(dt.rearport_templates.count(), 3)
  351. rp1 = RearPortTemplate.objects.first()
  352. self.assertEqual(rp1.name, 'Rear Port 1')
  353. self.assertEqual(dt.frontport_templates.count(), 3)
  354. fp1 = FrontPortTemplate.objects.first()
  355. self.assertEqual(fp1.name, 'Front Port 1')
  356. self.assertEqual(fp1.rear_port, rp1)
  357. self.assertEqual(fp1.rear_port_position, 1)
  358. self.assertEqual(dt.device_bay_templates.count(), 3)
  359. db1 = DeviceBayTemplate.objects.first()
  360. self.assertEqual(db1.name, 'Device Bay 1')
  361. def test_devicetype_export(self):
  362. url = reverse('dcim:devicetype_list')
  363. self.add_permissions('dcim.view_devicetype')
  364. response = self.client.get('{}?export'.format(url))
  365. self.assertEqual(response.status_code, 200)
  366. data = list(yaml.load_all(response.content, Loader=yaml.SafeLoader))
  367. self.assertEqual(len(data), 3)
  368. self.assertEqual(data[0]['manufacturer'], 'Manufacturer 1')
  369. self.assertEqual(data[0]['model'], 'Device Type 1')
  370. class DeviceRoleTestCase(StandardTestCases.Views):
  371. model = DeviceRole
  372. # Disable inapplicable tests
  373. test_get_object = None
  374. test_delete_object = None
  375. @classmethod
  376. def setUpTestData(cls):
  377. DeviceRole.objects.bulk_create([
  378. DeviceRole(name='Device Role 1', slug='device-role-1'),
  379. DeviceRole(name='Device Role 2', slug='device-role-2'),
  380. DeviceRole(name='Device Role 3', slug='device-role-3'),
  381. ])
  382. cls.form_data = {
  383. 'name': 'Devie Role X',
  384. 'slug': 'device-role-x',
  385. 'color': 'c0c0c0',
  386. 'vm_role': False,
  387. 'description': 'New device role',
  388. }
  389. cls.csv_data = (
  390. "name,slug,color",
  391. "Device Role 4,device-role-4,ff0000",
  392. "Device Role 5,device-role-5,00ff00",
  393. "Device Role 6,device-role-6,0000ff",
  394. )
  395. class PlatformTestCase(StandardTestCases.Views):
  396. model = Platform
  397. # Disable inapplicable tests
  398. test_get_object = None
  399. test_delete_object = None
  400. @classmethod
  401. def setUpTestData(cls):
  402. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  403. Platform.objects.bulk_create([
  404. Platform(name='Platform 1', slug='platform-1', manufacturer=manufacturer),
  405. Platform(name='Platform 2', slug='platform-2', manufacturer=manufacturer),
  406. Platform(name='Platform 3', slug='platform-3', manufacturer=manufacturer),
  407. ])
  408. cls.form_data = {
  409. 'name': 'Platform X',
  410. 'slug': 'platform-x',
  411. 'manufacturer': manufacturer.pk,
  412. 'napalm_driver': 'junos',
  413. 'napalm_args': None,
  414. }
  415. cls.csv_data = (
  416. "name,slug",
  417. "Platform 4,platform-4",
  418. "Platform 5,platform-5",
  419. "Platform 6,platform-6",
  420. )
  421. class DeviceTestCase(StandardTestCases.Views):
  422. model = Device
  423. @classmethod
  424. def setUpTestData(cls):
  425. site = Site.objects.create(name='Site 1', slug='site-1')
  426. rack = Rack.objects.create(name='Rack 1', site=site)
  427. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  428. devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
  429. devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  430. platform = Platform.objects.create(name='Platform 1', slug='platform-1')
  431. Device.objects.bulk_create([
  432. Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole),
  433. Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole),
  434. Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole),
  435. ])
  436. cls.form_data = {
  437. 'device_type': devicetype.pk,
  438. 'device_role': devicerole.pk,
  439. 'tenant': None,
  440. 'platform': platform.pk,
  441. 'name': 'Device X',
  442. 'serial': '123456',
  443. 'asset_tag': 'ABCDEF',
  444. 'site': site.pk,
  445. 'rack': rack.pk,
  446. 'position': 1,
  447. 'face': DeviceFaceChoices.FACE_FRONT,
  448. 'status': DeviceStatusChoices.STATUS_PLANNED,
  449. 'primary_ip4': None,
  450. 'primary_ip6': None,
  451. 'cluster': None,
  452. 'virtual_chassis': None,
  453. 'vc_position': None,
  454. 'vc_priority': None,
  455. 'comments': 'A new device',
  456. 'tags': 'Alpha,Bravo,Charlie',
  457. 'local_context_data': None,
  458. }
  459. cls.csv_data = (
  460. "device_role,manufacturer,model_name,status,site,name",
  461. "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 4",
  462. "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 5",
  463. "Device Role 1,Manufacturer 1,Device Type 1,Active,Site 1,Device 6",
  464. )
  465. # TODO: Convert to StandardTestCases.Views
  466. class ConsolePortTestCase(TestCase):
  467. user_permissions = (
  468. 'dcim.view_consoleport',
  469. )
  470. @classmethod
  471. def setUpTestData(cls):
  472. site = Site(name='Site 1', slug='site-1')
  473. site.save()
  474. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  475. manufacturer.save()
  476. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  477. devicetype.save()
  478. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  479. devicerole.save()
  480. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  481. device.save()
  482. ConsolePort.objects.bulk_create([
  483. ConsolePort(device=device, name='Console Port 1'),
  484. ConsolePort(device=device, name='Console Port 2'),
  485. ConsolePort(device=device, name='Console Port 3'),
  486. ])
  487. def test_consoleport_list(self):
  488. url = reverse('dcim:consoleport_list')
  489. response = self.client.get(url)
  490. self.assertHttpStatus(response, 200)
  491. def test_consoleport_import(self):
  492. self.add_permissions('dcim.add_consoleport')
  493. csv_data = (
  494. "device,name",
  495. "Device 1,Console Port 4",
  496. "Device 1,Console Port 5",
  497. "Device 1,Console Port 6",
  498. )
  499. response = self.client.post(reverse('dcim:consoleport_import'), {'csv': '\n'.join(csv_data)})
  500. self.assertHttpStatus(response, 200)
  501. self.assertEqual(ConsolePort.objects.count(), 6)
  502. # TODO: Convert to StandardTestCases.Views
  503. class ConsoleServerPortTestCase(TestCase):
  504. user_permissions = (
  505. 'dcim.view_consoleserverport',
  506. )
  507. @classmethod
  508. def setUpTestData(cls):
  509. site = Site(name='Site 1', slug='site-1')
  510. site.save()
  511. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  512. manufacturer.save()
  513. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  514. devicetype.save()
  515. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  516. devicerole.save()
  517. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  518. device.save()
  519. ConsoleServerPort.objects.bulk_create([
  520. ConsoleServerPort(device=device, name='Console Server Port 1'),
  521. ConsoleServerPort(device=device, name='Console Server Port 2'),
  522. ConsoleServerPort(device=device, name='Console Server Port 3'),
  523. ])
  524. def test_consoleserverport_list(self):
  525. url = reverse('dcim:consoleserverport_list')
  526. response = self.client.get(url)
  527. self.assertHttpStatus(response, 200)
  528. def test_consoleserverport_import(self):
  529. self.add_permissions('dcim.add_consoleserverport')
  530. csv_data = (
  531. "device,name",
  532. "Device 1,Console Server Port 4",
  533. "Device 1,Console Server Port 5",
  534. "Device 1,Console Server Port 6",
  535. )
  536. response = self.client.post(reverse('dcim:consoleserverport_import'), {'csv': '\n'.join(csv_data)})
  537. self.assertHttpStatus(response, 200)
  538. self.assertEqual(ConsoleServerPort.objects.count(), 6)
  539. # TODO: Convert to StandardTestCases.Views
  540. class PowerPortTestCase(TestCase):
  541. user_permissions = (
  542. 'dcim.view_powerport',
  543. )
  544. @classmethod
  545. def setUpTestData(cls):
  546. site = Site(name='Site 1', slug='site-1')
  547. site.save()
  548. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  549. manufacturer.save()
  550. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  551. devicetype.save()
  552. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  553. devicerole.save()
  554. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  555. device.save()
  556. PowerPort.objects.bulk_create([
  557. PowerPort(device=device, name='Power Port 1'),
  558. PowerPort(device=device, name='Power Port 2'),
  559. PowerPort(device=device, name='Power Port 3'),
  560. ])
  561. def test_powerport_list(self):
  562. url = reverse('dcim:powerport_list')
  563. response = self.client.get(url)
  564. self.assertHttpStatus(response, 200)
  565. def test_powerport_import(self):
  566. self.add_permissions('dcim.add_powerport')
  567. csv_data = (
  568. "device,name",
  569. "Device 1,Power Port 4",
  570. "Device 1,Power Port 5",
  571. "Device 1,Power Port 6",
  572. )
  573. response = self.client.post(reverse('dcim:powerport_import'), {'csv': '\n'.join(csv_data)})
  574. self.assertHttpStatus(response, 200)
  575. self.assertEqual(PowerPort.objects.count(), 6)
  576. # TODO: Convert to StandardTestCases.Views
  577. class PowerOutletTestCase(TestCase):
  578. user_permissions = (
  579. 'dcim.view_poweroutlet',
  580. )
  581. @classmethod
  582. def setUpTestData(cls):
  583. site = Site(name='Site 1', slug='site-1')
  584. site.save()
  585. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  586. manufacturer.save()
  587. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  588. devicetype.save()
  589. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  590. devicerole.save()
  591. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  592. device.save()
  593. PowerOutlet.objects.bulk_create([
  594. PowerOutlet(device=device, name='Power Outlet 1'),
  595. PowerOutlet(device=device, name='Power Outlet 2'),
  596. PowerOutlet(device=device, name='Power Outlet 3'),
  597. ])
  598. def test_poweroutlet_list(self):
  599. url = reverse('dcim:poweroutlet_list')
  600. response = self.client.get(url)
  601. self.assertHttpStatus(response, 200)
  602. def test_poweroutlet_import(self):
  603. self.add_permissions('dcim.add_poweroutlet')
  604. csv_data = (
  605. "device,name",
  606. "Device 1,Power Outlet 4",
  607. "Device 1,Power Outlet 5",
  608. "Device 1,Power Outlet 6",
  609. )
  610. response = self.client.post(reverse('dcim:poweroutlet_import'), {'csv': '\n'.join(csv_data)})
  611. self.assertHttpStatus(response, 200)
  612. self.assertEqual(PowerOutlet.objects.count(), 6)
  613. # TODO: Convert to StandardTestCases.Views
  614. class InterfaceTestCase(TestCase):
  615. user_permissions = (
  616. 'dcim.view_interface',
  617. )
  618. @classmethod
  619. def setUpTestData(cls):
  620. site = Site(name='Site 1', slug='site-1')
  621. site.save()
  622. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  623. manufacturer.save()
  624. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  625. devicetype.save()
  626. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  627. devicerole.save()
  628. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  629. device.save()
  630. Interface.objects.bulk_create([
  631. Interface(device=device, name='Interface 1'),
  632. Interface(device=device, name='Interface 2'),
  633. Interface(device=device, name='Interface 3'),
  634. ])
  635. def test_interface_list(self):
  636. url = reverse('dcim:interface_list')
  637. response = self.client.get(url)
  638. self.assertHttpStatus(response, 200)
  639. def test_interface_import(self):
  640. self.add_permissions('dcim.add_interface')
  641. csv_data = (
  642. "device,name,type",
  643. "Device 1,Interface 4,1000BASE-T (1GE)",
  644. "Device 1,Interface 5,1000BASE-T (1GE)",
  645. "Device 1,Interface 6,1000BASE-T (1GE)",
  646. )
  647. response = self.client.post(reverse('dcim:interface_import'), {'csv': '\n'.join(csv_data)})
  648. self.assertHttpStatus(response, 200)
  649. self.assertEqual(Interface.objects.count(), 6)
  650. # TODO: Convert to StandardTestCases.Views
  651. class FrontPortTestCase(TestCase):
  652. user_permissions = (
  653. 'dcim.view_frontport',
  654. )
  655. @classmethod
  656. def setUpTestData(cls):
  657. site = Site(name='Site 1', slug='site-1')
  658. site.save()
  659. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  660. manufacturer.save()
  661. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  662. devicetype.save()
  663. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  664. devicerole.save()
  665. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  666. device.save()
  667. rearport1 = RearPort(device=device, name='Rear Port 1')
  668. rearport1.save()
  669. rearport2 = RearPort(device=device, name='Rear Port 2')
  670. rearport2.save()
  671. rearport3 = RearPort(device=device, name='Rear Port 3')
  672. rearport3.save()
  673. # RearPorts for CSV import test
  674. RearPort(device=device, name='Rear Port 4').save()
  675. RearPort(device=device, name='Rear Port 5').save()
  676. RearPort(device=device, name='Rear Port 6').save()
  677. FrontPort.objects.bulk_create([
  678. FrontPort(device=device, name='Front Port 1', rear_port=rearport1),
  679. FrontPort(device=device, name='Front Port 2', rear_port=rearport2),
  680. FrontPort(device=device, name='Front Port 3', rear_port=rearport3),
  681. ])
  682. def test_frontport_list(self):
  683. url = reverse('dcim:frontport_list')
  684. response = self.client.get(url)
  685. self.assertHttpStatus(response, 200)
  686. def test_frontport_import(self):
  687. self.add_permissions('dcim.add_frontport')
  688. csv_data = (
  689. "device,name,type,rear_port,rear_port_position",
  690. "Device 1,Front Port 4,8P8C,Rear Port 4,1",
  691. "Device 1,Front Port 5,8P8C,Rear Port 5,1",
  692. "Device 1,Front Port 6,8P8C,Rear Port 6,1",
  693. )
  694. response = self.client.post(reverse('dcim:frontport_import'), {'csv': '\n'.join(csv_data)})
  695. self.assertHttpStatus(response, 200)
  696. self.assertEqual(FrontPort.objects.count(), 6)
  697. # TODO: Convert to StandardTestCases.Views
  698. class RearPortTestCase(TestCase):
  699. user_permissions = (
  700. 'dcim.view_rearport',
  701. )
  702. @classmethod
  703. def setUpTestData(cls):
  704. site = Site(name='Site 1', slug='site-1')
  705. site.save()
  706. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  707. manufacturer.save()
  708. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  709. devicetype.save()
  710. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  711. devicerole.save()
  712. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  713. device.save()
  714. RearPort.objects.bulk_create([
  715. RearPort(device=device, name='Rear Port 1'),
  716. RearPort(device=device, name='Rear Port 2'),
  717. RearPort(device=device, name='Rear Port 3'),
  718. ])
  719. def test_rearport_list(self):
  720. url = reverse('dcim:rearport_list')
  721. response = self.client.get(url)
  722. self.assertHttpStatus(response, 200)
  723. def test_rearport_import(self):
  724. self.add_permissions('dcim.add_rearport')
  725. csv_data = (
  726. "device,name,type,positions",
  727. "Device 1,Rear Port 4,8P8C,1",
  728. "Device 1,Rear Port 5,8P8C,1",
  729. "Device 1,Rear Port 6,8P8C,1",
  730. )
  731. response = self.client.post(reverse('dcim:rearport_import'), {'csv': '\n'.join(csv_data)})
  732. self.assertHttpStatus(response, 200)
  733. self.assertEqual(RearPort.objects.count(), 6)
  734. # TODO: Convert to StandardTestCases.Views
  735. class DeviceBayTestCase(TestCase):
  736. user_permissions = (
  737. 'dcim.view_devicebay',
  738. )
  739. @classmethod
  740. def setUpTestData(cls):
  741. site = Site(name='Site 1', slug='site-1')
  742. site.save()
  743. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  744. manufacturer.save()
  745. devicetype = DeviceType(
  746. model='Device Type 1',
  747. manufacturer=manufacturer,
  748. subdevice_role=SubdeviceRoleChoices.ROLE_PARENT
  749. )
  750. devicetype.save()
  751. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  752. devicerole.save()
  753. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  754. device.save()
  755. DeviceBay.objects.bulk_create([
  756. DeviceBay(device=device, name='Device Bay 1'),
  757. DeviceBay(device=device, name='Device Bay 2'),
  758. DeviceBay(device=device, name='Device Bay 3'),
  759. ])
  760. def test_devicebay_list(self):
  761. url = reverse('dcim:devicebay_list')
  762. response = self.client.get(url)
  763. self.assertHttpStatus(response, 200)
  764. def test_devicebay_import(self):
  765. self.add_permissions('dcim.add_devicebay')
  766. csv_data = (
  767. "device,name",
  768. "Device 1,Device Bay 4",
  769. "Device 1,Device Bay 5",
  770. "Device 1,Device Bay 6",
  771. )
  772. response = self.client.post(reverse('dcim:devicebay_import'), {'csv': '\n'.join(csv_data)})
  773. self.assertHttpStatus(response, 200)
  774. self.assertEqual(DeviceBay.objects.count(), 6)
  775. # TODO: Convert to StandardTestCases.Views
  776. class InventoryItemTestCase(TestCase):
  777. user_permissions = (
  778. 'dcim.view_inventoryitem',
  779. )
  780. @classmethod
  781. def setUpTestData(cls):
  782. site = Site(name='Site 1', slug='site-1')
  783. site.save()
  784. manufacturer = Manufacturer(name='Manufacturer 1', slug='manufacturer-1')
  785. manufacturer.save()
  786. devicetype = DeviceType(model='Device Type 1', manufacturer=manufacturer)
  787. devicetype.save()
  788. devicerole = DeviceRole(name='Device Role 1', slug='device-role-1')
  789. devicerole.save()
  790. device = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  791. device.save()
  792. InventoryItem.objects.bulk_create([
  793. InventoryItem(device=device, name='Inventory Item 1'),
  794. InventoryItem(device=device, name='Inventory Item 2'),
  795. InventoryItem(device=device, name='Inventory Item 3'),
  796. ])
  797. def test_inventoryitem_list(self):
  798. url = reverse('dcim:inventoryitem_list')
  799. params = {
  800. "device_id": Device.objects.first().pk,
  801. }
  802. response = self.client.get('{}?{}'.format(url, urllib.parse.urlencode(params)))
  803. self.assertHttpStatus(response, 200)
  804. def test_inventoryitem_import(self):
  805. self.add_permissions('dcim.add_inventoryitem')
  806. csv_data = (
  807. "device,name",
  808. "Device 1,Inventory Item 4",
  809. "Device 1,Inventory Item 5",
  810. "Device 1,Inventory Item 6",
  811. )
  812. response = self.client.post(reverse('dcim:inventoryitem_import'), {'csv': '\n'.join(csv_data)})
  813. self.assertHttpStatus(response, 200)
  814. self.assertEqual(InventoryItem.objects.count(), 6)
  815. class CableTestCase(StandardTestCases.Views):
  816. model = Cable
  817. # TODO: Creation URL needs termination context
  818. test_create_object = None
  819. @classmethod
  820. def setUpTestData(cls):
  821. site = Site.objects.create(name='Site 1', slug='site-1')
  822. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  823. devicetype = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
  824. devicerole = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  825. device1 = Device(name='Device 1', site=site, device_type=devicetype, device_role=devicerole)
  826. device1.save()
  827. device2 = Device(name='Device 2', site=site, device_type=devicetype, device_role=devicerole)
  828. device2.save()
  829. device3 = Device(name='Device 3', site=site, device_type=devicetype, device_role=devicerole)
  830. device3.save()
  831. device4 = Device(name='Device 4', site=site, device_type=devicetype, device_role=devicerole)
  832. device4.save()
  833. interfaces = (
  834. Interface(device=device1, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  835. Interface(device=device1, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  836. Interface(device=device1, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  837. Interface(device=device2, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  838. Interface(device=device2, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  839. Interface(device=device2, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  840. Interface(device=device3, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  841. Interface(device=device3, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  842. Interface(device=device3, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  843. Interface(device=device4, name='Interface 1', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  844. Interface(device=device4, name='Interface 2', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  845. Interface(device=device4, name='Interface 3', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  846. )
  847. Interface.objects.bulk_create(interfaces)
  848. Cable(termination_a=interfaces[0], termination_b=interfaces[3], type=CableTypeChoices.TYPE_CAT6).save()
  849. Cable(termination_a=interfaces[1], termination_b=interfaces[4], type=CableTypeChoices.TYPE_CAT6).save()
  850. Cable(termination_a=interfaces[2], termination_b=interfaces[5], type=CableTypeChoices.TYPE_CAT6).save()
  851. interface_ct = ContentType.objects.get_for_model(Interface)
  852. cls.form_data = {
  853. # Changing terminations not supported when editing an existing Cable
  854. 'termination_a_type': interface_ct.pk,
  855. 'termination_a_id': interfaces[0].pk,
  856. 'termination_b_type': interface_ct.pk,
  857. 'termination_b_id': interfaces[3].pk,
  858. 'type': CableTypeChoices.TYPE_CAT6,
  859. 'status': CableStatusChoices.STATUS_PLANNED,
  860. 'label': 'New cable',
  861. 'color': 'c0c0c0',
  862. 'length': 100,
  863. 'length_unit': CableLengthUnitChoices.UNIT_FOOT,
  864. }
  865. cls.csv_data = (
  866. "side_a_device,side_a_type,side_a_name,side_b_device,side_b_type,side_b_name",
  867. "Device 3,interface,Interface 1,Device 4,interface,Interface 1",
  868. "Device 3,interface,Interface 2,Device 4,interface,Interface 2",
  869. "Device 3,interface,Interface 3,Device 4,interface,Interface 3",
  870. )
  871. class VirtualChassisTestCase(StandardTestCases.Views):
  872. model = VirtualChassis
  873. # Disable inapplicable tests
  874. test_get_object = None
  875. test_import_objects = None
  876. test_bulk_delete_objects = None
  877. # TODO: Requires special form handling
  878. test_create_object = None
  879. test_edit_object = None
  880. @classmethod
  881. def setUpTestData(cls):
  882. site = Site.objects.create(name='Site 1', slug='site-1')
  883. manufacturer = Manufacturer.objects.create(name='Manufacturer', slug='manufacturer-1')
  884. device_type = DeviceType.objects.create(
  885. manufacturer=manufacturer, model='Device Type 1', slug='device-type-1'
  886. )
  887. device_role = DeviceRole.objects.create(
  888. name='Device Role', slug='device-role-1'
  889. )
  890. # Create 9 member Devices
  891. device1 = Device.objects.create(
  892. device_type=device_type, device_role=device_role, name='Device 1', site=site
  893. )
  894. device2 = Device.objects.create(
  895. device_type=device_type, device_role=device_role, name='Device 2', site=site
  896. )
  897. device3 = Device.objects.create(
  898. device_type=device_type, device_role=device_role, name='Device 3', site=site
  899. )
  900. device4 = Device.objects.create(
  901. device_type=device_type, device_role=device_role, name='Device 4', site=site
  902. )
  903. device5 = Device.objects.create(
  904. device_type=device_type, device_role=device_role, name='Device 5', site=site
  905. )
  906. device6 = Device.objects.create(
  907. device_type=device_type, device_role=device_role, name='Device 6', site=site
  908. )
  909. # Create three VirtualChassis with two members each
  910. vc1 = VirtualChassis.objects.create(master=device1, domain='test-domain-1')
  911. Device.objects.filter(pk=device2.pk).update(virtual_chassis=vc1, vc_position=2)
  912. vc2 = VirtualChassis.objects.create(master=device3, domain='test-domain-2')
  913. Device.objects.filter(pk=device4.pk).update(virtual_chassis=vc2, vc_position=2)
  914. vc3 = VirtualChassis.objects.create(master=device5, domain='test-domain-3')
  915. Device.objects.filter(pk=device6.pk).update(virtual_chassis=vc3, vc_position=2)