test_views.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. import datetime
  2. from django.contrib.contenttypes.models import ContentType
  3. from django.test import override_settings
  4. from django.urls import reverse
  5. from circuits.choices import *
  6. from circuits.models import *
  7. from core.models import ObjectType
  8. from dcim.choices import InterfaceTypeChoices
  9. from dcim.models import Cable, Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
  10. from ipam.models import ASN, RIR
  11. from netbox.choices import ImportFormatChoices
  12. from users.models import ObjectPermission
  13. from utilities.testing import ViewTestCases, create_tags, create_test_device
  14. class ProviderTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  15. model = Provider
  16. @classmethod
  17. def setUpTestData(cls):
  18. rir = RIR.objects.create(name='RFC 6996', is_private=True)
  19. asns = [
  20. ASN(asn=65000 + i, rir=rir) for i in range(8)
  21. ]
  22. ASN.objects.bulk_create(asns)
  23. providers = (
  24. Provider(name='Provider 1', slug='provider-1'),
  25. Provider(name='Provider 2', slug='provider-2'),
  26. Provider(name='Provider 3', slug='provider-3'),
  27. )
  28. Provider.objects.bulk_create(providers)
  29. providers[0].asns.set([asns[0], asns[1]])
  30. providers[1].asns.set([asns[2], asns[3]])
  31. providers[2].asns.set([asns[4], asns[5]])
  32. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  33. cls.form_data = {
  34. 'name': 'Provider X',
  35. 'slug': 'provider-x',
  36. 'asns': [asns[6].pk, asns[7].pk],
  37. 'comments': 'Another provider',
  38. 'tags': [t.pk for t in tags],
  39. }
  40. cls.csv_data = (
  41. "name,slug",
  42. "Provider 4,provider-4",
  43. "Provider 5,provider-5",
  44. "Provider 6,provider-6",
  45. )
  46. cls.csv_update_data = (
  47. "id,name,comments",
  48. f"{providers[0].pk},Provider 7,New comment7",
  49. f"{providers[1].pk},Provider 8,New comment8",
  50. f"{providers[2].pk},Provider 9,New comment9",
  51. )
  52. cls.bulk_edit_data = {
  53. 'comments': 'New comments',
  54. }
  55. class CircuitTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  56. model = CircuitType
  57. @classmethod
  58. def setUpTestData(cls):
  59. circuit_types = (
  60. CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
  61. CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
  62. CircuitType(name='Circuit Type 3', slug='circuit-type-3'),
  63. )
  64. CircuitType.objects.bulk_create(circuit_types)
  65. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  66. cls.form_data = {
  67. 'name': 'Circuit Type X',
  68. 'slug': 'circuit-type-x',
  69. 'description': 'A new circuit type',
  70. 'tags': [t.pk for t in tags],
  71. }
  72. cls.csv_data = (
  73. "name,slug",
  74. "Circuit Type 4,circuit-type-4",
  75. "Circuit Type 5,circuit-type-5",
  76. "Circuit Type 6,circuit-type-6",
  77. )
  78. cls.csv_update_data = (
  79. "id,name,description",
  80. f"{circuit_types[0].pk},Circuit Type 7,New description7",
  81. f"{circuit_types[1].pk},Circuit Type 8,New description8",
  82. f"{circuit_types[2].pk},Circuit Type 9,New description9",
  83. )
  84. cls.bulk_edit_data = {
  85. 'description': 'Foo',
  86. }
  87. class CircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  88. model = Circuit
  89. def setUp(self):
  90. super().setUp()
  91. self.add_permissions(
  92. 'circuits.add_circuittermination',
  93. )
  94. @classmethod
  95. def setUpTestData(cls):
  96. Site.objects.create(name='Site 1', slug='site-1')
  97. providers = (
  98. Provider(name='Provider 1', slug='provider-1'),
  99. Provider(name='Provider 2', slug='provider-2'),
  100. )
  101. Provider.objects.bulk_create(providers)
  102. provider_accounts = (
  103. ProviderAccount(name='Provider Account 1', provider=providers[0], account='1234'),
  104. ProviderAccount(name='Provider Account 2', provider=providers[1], account='2345'),
  105. )
  106. ProviderAccount.objects.bulk_create(provider_accounts)
  107. circuittypes = (
  108. CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
  109. CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
  110. )
  111. CircuitType.objects.bulk_create(circuittypes)
  112. circuits = (
  113. Circuit(cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]),
  114. Circuit(cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]),
  115. Circuit(cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuittypes[0]),
  116. )
  117. Circuit.objects.bulk_create(circuits)
  118. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  119. cls.form_data = {
  120. 'cid': 'Circuit X',
  121. 'provider': providers[1].pk,
  122. 'provider_account': provider_accounts[1].pk,
  123. 'type': circuittypes[1].pk,
  124. 'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
  125. 'tenant': None,
  126. 'install_date': datetime.date(2020, 1, 1),
  127. 'termination_date': datetime.date(2021, 1, 1),
  128. 'commit_rate': 1000,
  129. 'description': 'A new circuit',
  130. 'comments': 'Some comments',
  131. 'tags': [t.pk for t in tags],
  132. }
  133. cls.csv_data = (
  134. "cid,provider,provider_account,type,status",
  135. "Circuit 4,Provider 1,Provider Account 1,Circuit Type 1,active",
  136. "Circuit 5,Provider 1,Provider Account 1,Circuit Type 1,active",
  137. "Circuit 6,Provider 1,Provider Account 1,Circuit Type 1,active",
  138. )
  139. cls.csv_update_data = (
  140. "id,cid,description,status",
  141. f"{circuits[0].pk},Circuit 7,New description7,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  142. f"{circuits[1].pk},Circuit 8,New description8,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  143. f"{circuits[2].pk},Circuit 9,New description9,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  144. )
  145. cls.bulk_edit_data = {
  146. 'provider': providers[1].pk,
  147. 'provider_account': provider_accounts[1].pk,
  148. 'type': circuittypes[1].pk,
  149. 'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
  150. 'tenant': None,
  151. 'commit_rate': 2000,
  152. 'description': 'New description',
  153. 'comments': 'New comments',
  154. }
  155. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
  156. def test_bulk_import_objects_with_terminations(self):
  157. site = Site.objects.first()
  158. json_data = f"""
  159. [
  160. {{
  161. "cid": "Circuit 7",
  162. "provider": "Provider 1",
  163. "type": "Circuit Type 1",
  164. "status": "active",
  165. "description": "Testing Import",
  166. "terminations": [
  167. {{
  168. "term_side": "A",
  169. "termination_type": "dcim.site",
  170. "termination_id": "{site.pk}"
  171. }},
  172. {{
  173. "term_side": "Z",
  174. "termination_type": "dcim.site",
  175. "termination_id": "{site.pk}"
  176. }}
  177. ]
  178. }}
  179. ]
  180. """
  181. initial_count = self._get_queryset().count()
  182. data = {
  183. 'data': json_data,
  184. 'format': ImportFormatChoices.JSON,
  185. }
  186. # Assign model-level permission
  187. obj_perm = ObjectPermission(
  188. name='Test permission',
  189. actions=['add']
  190. )
  191. obj_perm.save()
  192. obj_perm.users.add(self.user)
  193. obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
  194. # Try GET with model-level permission
  195. self.assertHttpStatus(self.client.get(self._get_url('import')), 200)
  196. # Test POST with permission
  197. self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302)
  198. self.assertEqual(self._get_queryset().count(), initial_count + 1)
  199. class ProviderAccountTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  200. model = ProviderAccount
  201. @classmethod
  202. def setUpTestData(cls):
  203. providers = (
  204. Provider(name='Provider 1', slug='provider-1'),
  205. Provider(name='Provider 2', slug='provider-2'),
  206. )
  207. Provider.objects.bulk_create(providers)
  208. provider_accounts = (
  209. ProviderAccount(name='Provider Account 1', provider=providers[0], account='1234'),
  210. ProviderAccount(name='Provider Account 2', provider=providers[0], account='2345'),
  211. ProviderAccount(name='Provider Account 3', provider=providers[0], account='3456'),
  212. )
  213. ProviderAccount.objects.bulk_create(provider_accounts)
  214. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  215. cls.form_data = {
  216. 'name': 'Provider Account X',
  217. 'provider': providers[1].pk,
  218. 'account': 'XXXX',
  219. 'description': 'A new provider network',
  220. 'comments': 'Longer description goes here',
  221. 'tags': [t.pk for t in tags],
  222. }
  223. cls.csv_data = (
  224. "name,provider,account,description",
  225. "Provider Account 4,Provider 1,4567,Foo",
  226. "Provider Account 5,Provider 1,5678,Bar",
  227. "Provider Account 6,Provider 1,6789,Baz",
  228. )
  229. cls.csv_update_data = (
  230. "id,name,account,description",
  231. f"{provider_accounts[0].pk},Provider Network 7,7890,New description7",
  232. f"{provider_accounts[1].pk},Provider Network 8,8901,New description8",
  233. f"{provider_accounts[2].pk},Provider Network 9,9012,New description9",
  234. )
  235. cls.bulk_edit_data = {
  236. 'provider': providers[1].pk,
  237. 'description': 'New description',
  238. 'comments': 'New comments',
  239. }
  240. class ProviderNetworkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  241. model = ProviderNetwork
  242. @classmethod
  243. def setUpTestData(cls):
  244. providers = (
  245. Provider(name='Provider 1', slug='provider-1'),
  246. Provider(name='Provider 2', slug='provider-2'),
  247. )
  248. Provider.objects.bulk_create(providers)
  249. provider_networks = (
  250. ProviderNetwork(name='Provider Network 1', provider=providers[0]),
  251. ProviderNetwork(name='Provider Network 2', provider=providers[0]),
  252. ProviderNetwork(name='Provider Network 3', provider=providers[0]),
  253. )
  254. ProviderNetwork.objects.bulk_create(provider_networks)
  255. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  256. cls.form_data = {
  257. 'name': 'Provider Network X',
  258. 'provider': providers[1].pk,
  259. 'description': 'A new provider network',
  260. 'comments': 'Longer description goes here',
  261. 'tags': [t.pk for t in tags],
  262. }
  263. cls.csv_data = (
  264. "name,provider,description",
  265. "Provider Network 4,Provider 1,Foo",
  266. "Provider Network 5,Provider 1,Bar",
  267. "Provider Network 6,Provider 1,Baz",
  268. )
  269. cls.csv_update_data = (
  270. "id,name,description",
  271. f"{provider_networks[0].pk},Provider Network 7,New description7",
  272. f"{provider_networks[1].pk},Provider Network 8,New description8",
  273. f"{provider_networks[2].pk},Provider Network 9,New description9",
  274. )
  275. cls.bulk_edit_data = {
  276. 'provider': providers[1].pk,
  277. 'description': 'New description',
  278. 'comments': 'New comments',
  279. }
  280. class CircuitTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  281. model = CircuitTermination
  282. @classmethod
  283. def setUpTestData(cls):
  284. sites = (
  285. Site(name='Site 1', slug='site-1'),
  286. Site(name='Site 2', slug='site-2'),
  287. Site(name='Site 3', slug='site-3'),
  288. )
  289. Site.objects.bulk_create(sites)
  290. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  291. circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  292. circuits = (
  293. Circuit(cid='Circuit 1', provider=provider, type=circuittype),
  294. Circuit(cid='Circuit 2', provider=provider, type=circuittype),
  295. Circuit(cid='Circuit 3', provider=provider, type=circuittype),
  296. )
  297. Circuit.objects.bulk_create(circuits)
  298. circuit_terminations = (
  299. CircuitTermination(circuit=circuits[0], term_side='A', termination=sites[0]),
  300. CircuitTermination(circuit=circuits[0], term_side='Z', termination=sites[1]),
  301. CircuitTermination(circuit=circuits[1], term_side='A', termination=sites[0]),
  302. CircuitTermination(circuit=circuits[1], term_side='Z', termination=sites[1]),
  303. )
  304. for ct in circuit_terminations:
  305. ct.save()
  306. cls.form_data = {
  307. 'circuit': circuits[2].pk,
  308. 'term_side': 'A',
  309. 'termination_type': ContentType.objects.get_for_model(Site).pk,
  310. 'termination': sites[2].pk,
  311. 'description': 'New description',
  312. }
  313. site = sites[0].pk
  314. cls.csv_data = (
  315. "circuit,term_side,termination_type,termination_id,description",
  316. f"Circuit 3,A,dcim.site,{site},Foo",
  317. f"Circuit 3,Z,dcim.site,{site},Bar",
  318. )
  319. cls.csv_update_data = (
  320. "id,port_speed,description",
  321. f"{circuit_terminations[0].pk},100,New description7",
  322. f"{circuit_terminations[1].pk},200,New description8",
  323. f"{circuit_terminations[2].pk},300,New description9",
  324. )
  325. cls.bulk_edit_data = {
  326. 'port_speed': 400,
  327. 'description': 'New description',
  328. }
  329. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  330. def test_trace(self):
  331. device = create_test_device('Device 1')
  332. circuittermination = CircuitTermination.objects.first()
  333. interface = Interface.objects.create(
  334. device=device,
  335. name='Interface 1'
  336. )
  337. Cable(a_terminations=[circuittermination], b_terminations=[interface]).save()
  338. response = self.client.get(reverse('circuits:circuittermination_trace', kwargs={'pk': circuittermination.pk}))
  339. self.assertHttpStatus(response, 200)
  340. class CircuitGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  341. model = CircuitGroup
  342. @classmethod
  343. def setUpTestData(cls):
  344. circuit_groups = (
  345. CircuitGroup(name='Circuit Group 1', slug='circuit-group-1'),
  346. CircuitGroup(name='Circuit Group 2', slug='circuit-group-2'),
  347. CircuitGroup(name='Circuit Group 3', slug='circuit-group-3'),
  348. )
  349. CircuitGroup.objects.bulk_create(circuit_groups)
  350. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  351. cls.form_data = {
  352. 'name': 'Circuit Group X',
  353. 'slug': 'circuit-group-x',
  354. 'description': 'A new Circuit Group',
  355. 'tags': [t.pk for t in tags],
  356. }
  357. cls.csv_data = (
  358. "name,slug",
  359. "Circuit Group 4,circuit-group-4",
  360. "Circuit Group 5,circuit-group-5",
  361. "Circuit Group 6,circuit-group-6",
  362. )
  363. cls.csv_update_data = (
  364. "id,name,description",
  365. f"{circuit_groups[0].pk},Circuit Group 7,New description7",
  366. f"{circuit_groups[1].pk},Circuit Group 8,New description8",
  367. f"{circuit_groups[2].pk},Circuit Group 9,New description9",
  368. )
  369. cls.bulk_edit_data = {
  370. 'description': 'Foo',
  371. }
  372. class CircuitGroupAssignmentTestCase(
  373. ViewTestCases.CreateObjectViewTestCase,
  374. ViewTestCases.EditObjectViewTestCase,
  375. ViewTestCases.DeleteObjectViewTestCase,
  376. ViewTestCases.ListObjectsViewTestCase,
  377. ViewTestCases.BulkEditObjectsViewTestCase,
  378. ViewTestCases.BulkDeleteObjectsViewTestCase
  379. ):
  380. model = CircuitGroupAssignment
  381. @classmethod
  382. def setUpTestData(cls):
  383. circuit_groups = (
  384. CircuitGroup(name='Circuit Group 1', slug='circuit-group-1'),
  385. CircuitGroup(name='Circuit Group 2', slug='circuit-group-2'),
  386. CircuitGroup(name='Circuit Group 3', slug='circuit-group-3'),
  387. CircuitGroup(name='Circuit Group 4', slug='circuit-group-4'),
  388. )
  389. CircuitGroup.objects.bulk_create(circuit_groups)
  390. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  391. circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  392. circuits = (
  393. Circuit(cid='Circuit 1', provider=provider, type=circuittype),
  394. Circuit(cid='Circuit 2', provider=provider, type=circuittype),
  395. Circuit(cid='Circuit 3', provider=provider, type=circuittype),
  396. Circuit(cid='Circuit 4', provider=provider, type=circuittype),
  397. )
  398. Circuit.objects.bulk_create(circuits)
  399. assignments = (
  400. CircuitGroupAssignment(
  401. group=circuit_groups[0],
  402. circuit=circuits[0],
  403. priority=CircuitPriorityChoices.PRIORITY_PRIMARY
  404. ),
  405. CircuitGroupAssignment(
  406. group=circuit_groups[1],
  407. circuit=circuits[1],
  408. priority=CircuitPriorityChoices.PRIORITY_SECONDARY
  409. ),
  410. CircuitGroupAssignment(
  411. group=circuit_groups[2],
  412. circuit=circuits[2],
  413. priority=CircuitPriorityChoices.PRIORITY_TERTIARY
  414. ),
  415. )
  416. CircuitGroupAssignment.objects.bulk_create(assignments)
  417. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  418. cls.form_data = {
  419. 'group': circuit_groups[3].pk,
  420. 'circuit': circuits[3].pk,
  421. 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE,
  422. 'tags': [t.pk for t in tags],
  423. }
  424. cls.bulk_edit_data = {
  425. 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE,
  426. }
  427. class VirtualCircuitTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  428. model = VirtualCircuit
  429. def setUp(self):
  430. super().setUp()
  431. self.add_permissions(
  432. 'circuits.add_virtualcircuittermination',
  433. )
  434. @classmethod
  435. def setUpTestData(cls):
  436. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  437. provider_networks = (
  438. ProviderNetwork(provider=provider, name='Provider Network 1'),
  439. ProviderNetwork(provider=provider, name='Provider Network 2'),
  440. )
  441. ProviderNetwork.objects.bulk_create(provider_networks)
  442. provider_accounts = (
  443. ProviderAccount(provider=provider, account='Provider Account 1'),
  444. ProviderAccount(provider=provider, account='Provider Account 2'),
  445. )
  446. ProviderAccount.objects.bulk_create(provider_accounts)
  447. virtual_circuits = (
  448. VirtualCircuit(
  449. provider_network=provider_networks[0],
  450. provider_account=provider_accounts[0],
  451. cid='Virtual Circuit 1'
  452. ),
  453. VirtualCircuit(
  454. provider_network=provider_networks[0],
  455. provider_account=provider_accounts[0],
  456. cid='Virtual Circuit 2'
  457. ),
  458. VirtualCircuit(
  459. provider_network=provider_networks[0],
  460. provider_account=provider_accounts[0],
  461. cid='Virtual Circuit 3'
  462. ),
  463. )
  464. VirtualCircuit.objects.bulk_create(virtual_circuits)
  465. device = create_test_device('Device 1')
  466. interfaces = (
  467. Interface(device=device, name='Interface 1', type=InterfaceTypeChoices.TYPE_VIRTUAL),
  468. Interface(device=device, name='Interface 2', type=InterfaceTypeChoices.TYPE_VIRTUAL),
  469. Interface(device=device, name='Interface 3', type=InterfaceTypeChoices.TYPE_VIRTUAL),
  470. )
  471. Interface.objects.bulk_create(interfaces)
  472. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  473. cls.form_data = {
  474. 'cid': 'Virtual Circuit X',
  475. 'provider_network': provider_networks[1].pk,
  476. 'provider_account': provider_accounts[1].pk,
  477. 'status': CircuitStatusChoices.STATUS_PLANNED,
  478. 'description': 'A new virtual circuit',
  479. 'comments': 'Some comments',
  480. 'tags': [t.pk for t in tags],
  481. }
  482. cls.csv_data = (
  483. "cid,provider_network,provider_account,status",
  484. f"Virtual Circuit 4,Provider Network 1,Provider Account 1,{CircuitStatusChoices.STATUS_PLANNED}",
  485. f"Virtual Circuit 5,Provider Network 1,Provider Account 1,{CircuitStatusChoices.STATUS_PLANNED}",
  486. f"Virtual Circuit 6,Provider Network 1,Provider Account 1,{CircuitStatusChoices.STATUS_PLANNED}",
  487. )
  488. cls.csv_update_data = (
  489. "id,cid,description,status",
  490. f"{virtual_circuits[0].pk},Virtual Circuit A,New description,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  491. f"{virtual_circuits[1].pk},Virtual Circuit B,New description,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  492. f"{virtual_circuits[2].pk},Virtual Circuit C,New description,{CircuitStatusChoices.STATUS_DECOMMISSIONED}",
  493. )
  494. cls.bulk_edit_data = {
  495. 'provider_network': provider_networks[1].pk,
  496. 'provider_account': provider_accounts[1].pk,
  497. 'status': CircuitStatusChoices.STATUS_DECOMMISSIONED,
  498. 'description': 'New description',
  499. 'comments': 'New comments',
  500. }
  501. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'], EXEMPT_EXCLUDE_MODELS=[])
  502. def test_bulk_import_objects_with_terminations(self):
  503. interfaces = Interface.objects.filter(type=InterfaceTypeChoices.TYPE_VIRTUAL)
  504. json_data = f"""
  505. [
  506. {{
  507. "cid": "Virtual Circuit 7",
  508. "provider_network": "Provider Network 1",
  509. "status": "active",
  510. "terminations": [
  511. {{
  512. "role": "hub",
  513. "interface": {interfaces[0].pk}
  514. }},
  515. {{
  516. "role": "spoke",
  517. "interface": {interfaces[1].pk}
  518. }},
  519. {{
  520. "role": "spoke",
  521. "interface": {interfaces[2].pk}
  522. }}
  523. ]
  524. }}
  525. ]
  526. """
  527. initial_count = self._get_queryset().count()
  528. data = {
  529. 'data': json_data,
  530. 'format': ImportFormatChoices.JSON,
  531. }
  532. # Assign model-level permission
  533. obj_perm = ObjectPermission(
  534. name='Test permission',
  535. actions=['add']
  536. )
  537. obj_perm.save()
  538. obj_perm.users.add(self.user)
  539. obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
  540. # Try GET with model-level permission
  541. self.assertHttpStatus(self.client.get(self._get_url('import')), 200)
  542. # Test POST with permission
  543. self.assertHttpStatus(self.client.post(self._get_url('import'), data), 302)
  544. self.assertEqual(self._get_queryset().count(), initial_count + 1)
  545. class VirtualCircuitTerminationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  546. model = VirtualCircuitTermination
  547. @classmethod
  548. def setUpTestData(cls):
  549. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  550. device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1')
  551. device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  552. site = Site.objects.create(name='Site 1', slug='site-1')
  553. devices = (
  554. Device(site=site, name='hub', device_type=device_type, role=device_role),
  555. Device(site=site, name='spoke1', device_type=device_type, role=device_role),
  556. Device(site=site, name='spoke2', device_type=device_type, role=device_role),
  557. Device(site=site, name='spoke3', device_type=device_type, role=device_role),
  558. )
  559. Device.objects.bulk_create(devices)
  560. physical_interfaces = (
  561. Interface(device=devices[0], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  562. Interface(device=devices[1], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  563. Interface(device=devices[2], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  564. Interface(device=devices[3], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  565. )
  566. Interface.objects.bulk_create(physical_interfaces)
  567. virtual_interfaces = (
  568. # Point-to-point VCs
  569. Interface(
  570. device=devices[0],
  571. name='eth0.1',
  572. parent=physical_interfaces[0],
  573. type=InterfaceTypeChoices.TYPE_VIRTUAL
  574. ),
  575. Interface(
  576. device=devices[0],
  577. name='eth0.2',
  578. parent=physical_interfaces[0],
  579. type=InterfaceTypeChoices.TYPE_VIRTUAL
  580. ),
  581. Interface(
  582. device=devices[0],
  583. name='eth0.3',
  584. parent=physical_interfaces[0],
  585. type=InterfaceTypeChoices.TYPE_VIRTUAL
  586. ),
  587. Interface(
  588. device=devices[1],
  589. name='eth0.1',
  590. parent=physical_interfaces[1],
  591. type=InterfaceTypeChoices.TYPE_VIRTUAL
  592. ),
  593. Interface(
  594. device=devices[2],
  595. name='eth0.1',
  596. parent=physical_interfaces[2],
  597. type=InterfaceTypeChoices.TYPE_VIRTUAL
  598. ),
  599. Interface(
  600. device=devices[3],
  601. name='eth0.1',
  602. parent=physical_interfaces[3],
  603. type=InterfaceTypeChoices.TYPE_VIRTUAL
  604. ),
  605. # Hub and spoke VCs
  606. Interface(
  607. device=devices[0],
  608. name='eth0.9',
  609. parent=physical_interfaces[0],
  610. type=InterfaceTypeChoices.TYPE_VIRTUAL
  611. ),
  612. Interface(
  613. device=devices[1],
  614. name='eth0.9',
  615. parent=physical_interfaces[0],
  616. type=InterfaceTypeChoices.TYPE_VIRTUAL
  617. ),
  618. Interface(
  619. device=devices[2],
  620. name='eth0.9',
  621. parent=physical_interfaces[0],
  622. type=InterfaceTypeChoices.TYPE_VIRTUAL
  623. ),
  624. Interface(
  625. device=devices[3],
  626. name='eth0.9',
  627. parent=physical_interfaces[0],
  628. type=InterfaceTypeChoices.TYPE_VIRTUAL
  629. ),
  630. )
  631. Interface.objects.bulk_create(virtual_interfaces)
  632. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  633. provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1')
  634. provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1')
  635. virtual_circuits = (
  636. VirtualCircuit(
  637. provider_network=provider_network,
  638. provider_account=provider_account,
  639. cid='Virtual Circuit 1'
  640. ),
  641. VirtualCircuit(
  642. provider_network=provider_network,
  643. provider_account=provider_account,
  644. cid='Virtual Circuit 2'
  645. ),
  646. VirtualCircuit(
  647. provider_network=provider_network,
  648. provider_account=provider_account,
  649. cid='Virtual Circuit 3'
  650. ),
  651. VirtualCircuit(
  652. provider_network=provider_network,
  653. provider_account=provider_account,
  654. cid='Virtual Circuit 4'
  655. ),
  656. )
  657. VirtualCircuit.objects.bulk_create(virtual_circuits)
  658. virtual_circuit_terminations = (
  659. VirtualCircuitTermination(
  660. virtual_circuit=virtual_circuits[0],
  661. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  662. interface=virtual_interfaces[0]
  663. ),
  664. VirtualCircuitTermination(
  665. virtual_circuit=virtual_circuits[0],
  666. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  667. interface=virtual_interfaces[3]
  668. ),
  669. VirtualCircuitTermination(
  670. virtual_circuit=virtual_circuits[1],
  671. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  672. interface=virtual_interfaces[1]
  673. ),
  674. VirtualCircuitTermination(
  675. virtual_circuit=virtual_circuits[1],
  676. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  677. interface=virtual_interfaces[4]
  678. ),
  679. VirtualCircuitTermination(
  680. virtual_circuit=virtual_circuits[2],
  681. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  682. interface=virtual_interfaces[2]
  683. ),
  684. VirtualCircuitTermination(
  685. virtual_circuit=virtual_circuits[2],
  686. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  687. interface=virtual_interfaces[5]
  688. ),
  689. )
  690. VirtualCircuitTermination.objects.bulk_create(virtual_circuit_terminations)
  691. cls.form_data = {
  692. 'virtual_circuit': virtual_circuits[3].pk,
  693. 'role': VirtualCircuitTerminationRoleChoices.ROLE_HUB,
  694. 'interface': virtual_interfaces[6].pk
  695. }
  696. cls.csv_data = (
  697. "virtual_circuit,role,interface,description",
  698. f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_HUB},{virtual_interfaces[6].pk},Hub",
  699. f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[7].pk},Spoke 1",
  700. f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[8].pk},Spoke 2",
  701. f"Virtual Circuit 4,{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},{virtual_interfaces[9].pk},Spoke 3",
  702. )
  703. cls.csv_update_data = (
  704. "id,role,description",
  705. f"{virtual_circuit_terminations[0].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description",
  706. f"{virtual_circuit_terminations[1].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description",
  707. f"{virtual_circuit_terminations[2].pk},{VirtualCircuitTerminationRoleChoices.ROLE_SPOKE},New description",
  708. )
  709. cls.bulk_edit_data = {
  710. 'description': 'New description',
  711. }