test_api.py 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. from django.test import tag
  2. from django.urls import reverse
  3. from rest_framework import status
  4. from circuits.choices import *
  5. from circuits.models import *
  6. from core.models import ObjectType
  7. from dcim.choices import InterfaceTypeChoices
  8. from dcim.models import Device, DeviceRole, DeviceType, Interface, Manufacturer, Site
  9. from extras.choices import CustomFieldTypeChoices
  10. from extras.models import CustomField
  11. from ipam.models import ASN, RIR
  12. from utilities.testing import APITestCase, APIViewTestCases
  13. class AppTestCase(APITestCase):
  14. def test_root(self):
  15. url = reverse('circuits-api:api-root')
  16. response = self.client.get('{}?format=api'.format(url), **self.header)
  17. self.assertEqual(response.status_code, 200)
  18. class ProviderTestCase(APIViewTestCases.APIViewTestCase):
  19. model = Provider
  20. brief_fields = ['circuit_count', 'description', 'display', 'id', 'name', 'slug', 'url']
  21. bulk_update_data = {
  22. 'comments': 'New comments',
  23. }
  24. bulk_update_invalid_data = {
  25. 'owner': 99999,
  26. }
  27. @classmethod
  28. def setUpTestData(cls):
  29. rir = RIR.objects.create(name='RFC 6996', is_private=True)
  30. asns = [
  31. ASN(asn=65000 + i, rir=rir) for i in range(8)
  32. ]
  33. ASN.objects.bulk_create(asns)
  34. providers = (
  35. Provider(name='Provider 1', slug='provider-1'),
  36. Provider(name='Provider 2', slug='provider-2'),
  37. Provider(name='Provider 3', slug='provider-3'),
  38. )
  39. Provider.objects.bulk_create(providers)
  40. cls.create_data = [
  41. {
  42. 'name': 'Provider 4',
  43. 'slug': 'provider-4',
  44. 'asns': [asns[0].pk, asns[1].pk],
  45. },
  46. {
  47. 'name': 'Provider 5',
  48. 'slug': 'provider-5',
  49. 'asns': [asns[2].pk, asns[3].pk],
  50. },
  51. {
  52. 'name': 'Provider 6',
  53. 'slug': 'provider-6',
  54. 'asns': [asns[4].pk, asns[5].pk],
  55. },
  56. ]
  57. class CircuitTypeTestCase(APIViewTestCases.APIViewTestCase):
  58. model = CircuitType
  59. brief_fields = ['circuit_count', 'description', 'display', 'id', 'name', 'slug', 'url']
  60. create_data = (
  61. {
  62. 'name': 'Circuit Type 4',
  63. 'slug': 'circuit-type-4',
  64. },
  65. {
  66. 'name': 'Circuit Type 5',
  67. 'slug': 'circuit-type-5',
  68. },
  69. {
  70. 'name': 'Circuit Type 6',
  71. 'slug': 'circuit-type-6',
  72. },
  73. )
  74. bulk_update_data = {
  75. 'description': 'New description',
  76. }
  77. bulk_update_invalid_data = {
  78. 'color': 'not-a-color',
  79. }
  80. @classmethod
  81. def setUpTestData(cls):
  82. circuit_types = (
  83. CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
  84. CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
  85. CircuitType(name='Circuit Type 3', slug='circuit-type-3'),
  86. )
  87. CircuitType.objects.bulk_create(circuit_types)
  88. class CircuitTestCase(APIViewTestCases.APIViewTestCase):
  89. model = Circuit
  90. brief_fields = ['cid', 'description', 'display', 'id', 'provider', 'url']
  91. bulk_update_data = {
  92. 'status': 'planned',
  93. }
  94. bulk_update_invalid_data = {
  95. 'status': 'not-a-valid-status',
  96. }
  97. user_permissions = ('circuits.view_provider', 'circuits.view_circuittype')
  98. @classmethod
  99. def setUpTestData(cls):
  100. providers = (
  101. Provider(name='Provider 1', slug='provider-1'),
  102. Provider(name='Provider 2', slug='provider-2'),
  103. )
  104. Provider.objects.bulk_create(providers)
  105. provider_accounts = (
  106. ProviderAccount(name='Provider Account 1', provider=providers[0], account='1234'),
  107. ProviderAccount(name='Provider Account 2', provider=providers[1], account='2345'),
  108. )
  109. ProviderAccount.objects.bulk_create(provider_accounts)
  110. circuit_types = (
  111. CircuitType(name='Circuit Type 1', slug='circuit-type-1'),
  112. CircuitType(name='Circuit Type 2', slug='circuit-type-2'),
  113. )
  114. CircuitType.objects.bulk_create(circuit_types)
  115. circuits = (
  116. Circuit(
  117. cid='Circuit 1', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]
  118. ),
  119. Circuit(
  120. cid='Circuit 2', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]
  121. ),
  122. Circuit(
  123. cid='Circuit 3', provider=providers[0], provider_account=provider_accounts[0], type=circuit_types[0]
  124. ),
  125. )
  126. Circuit.objects.bulk_create(circuits)
  127. circuit_groups = (
  128. CircuitGroup(name='Circuit Group 1', slug='circuit-group-1'),
  129. CircuitGroup(name='Circuit Group 2', slug='circuit-group-2'),
  130. )
  131. CircuitGroup.objects.bulk_create(circuit_groups)
  132. assignments = (
  133. CircuitGroupAssignment(
  134. group=circuit_groups[0],
  135. member=circuits[0],
  136. priority=CircuitPriorityChoices.PRIORITY_PRIMARY
  137. ),
  138. CircuitGroupAssignment(
  139. group=circuit_groups[1],
  140. member=circuits[1],
  141. priority=CircuitPriorityChoices.PRIORITY_SECONDARY
  142. ),
  143. )
  144. CircuitGroupAssignment.objects.bulk_create(assignments)
  145. cls.create_data = [
  146. {
  147. 'cid': 'Circuit 4',
  148. 'provider': providers[1].pk,
  149. 'provider_account': provider_accounts[1].pk,
  150. 'type': circuit_types[1].pk,
  151. },
  152. {
  153. 'cid': 'Circuit 5',
  154. 'provider': providers[1].pk,
  155. 'provider_account': provider_accounts[1].pk,
  156. 'type': circuit_types[1].pk,
  157. },
  158. {
  159. 'cid': 'Circuit 6',
  160. 'provider': providers[1].pk,
  161. # Omit provider account to test uniqueness constraint
  162. 'type': circuit_types[1].pk,
  163. },
  164. ]
  165. @tag('regression') # Ref: #23324
  166. def test_assignments_field(self):
  167. """The assignments field lists the group assignments of each circuit."""
  168. self.add_permissions('circuits.view_circuit')
  169. assignment1 = Circuit.objects.get(cid='Circuit 1').group_assignments.get()
  170. assignment2 = Circuit.objects.get(cid='Circuit 2').group_assignments.get()
  171. response = self.client.get(self._get_list_url(), **self.header)
  172. self.assertHttpStatus(response, status.HTTP_200_OK)
  173. assignments = {
  174. circuit['cid']: [(obj['id'], obj['group']['id']) for obj in circuit['assignments']]
  175. for circuit in response.data['results']
  176. }
  177. self.assertEqual(assignments, {
  178. 'Circuit 1': [(assignment1.pk, assignment1.group_id)],
  179. 'Circuit 2': [(assignment2.pk, assignment2.group_id)],
  180. 'Circuit 3': [],
  181. })
  182. @tag('regression') # Ref: #23324
  183. def test_create_ignores_assignments(self):
  184. """Assignments sent when creating a circuit are ignored."""
  185. self.add_permissions('circuits.add_circuit')
  186. circuit = Circuit.objects.get(cid='Circuit 1')
  187. assignment = circuit.group_assignments.get()
  188. data = {
  189. **self.create_data[0],
  190. 'assignments': [{'id': assignment.pk}],
  191. }
  192. response = self.client.post(self._get_list_url(), data, format='json', **self.header)
  193. self.assertHttpStatus(response, status.HTTP_201_CREATED)
  194. self.assertEqual(response.data['assignments'], [])
  195. self.assertEqual(list(circuit.group_assignments.all()), [assignment])
  196. @tag('regression') # Ref: #23324
  197. def test_update_ignores_assignments(self):
  198. """Assignments sent when updating a circuit are ignored."""
  199. self.add_permissions('circuits.change_circuit')
  200. circuit = Circuit.objects.get(cid='Circuit 1')
  201. assignment = circuit.group_assignments.get()
  202. data = {
  203. 'description': 'New description',
  204. 'assignments': [],
  205. }
  206. response = self.client.patch(self._get_detail_url(circuit), data, format='json', **self.header)
  207. self.assertHttpStatus(response, status.HTTP_200_OK)
  208. self.assertEqual([obj['id'] for obj in response.data['assignments']], [assignment.pk])
  209. circuit.refresh_from_db()
  210. self.assertEqual(circuit.description, 'New description')
  211. self.assertEqual(list(circuit.group_assignments.all()), [assignment])
  212. @tag('regression') # Ref: #23469
  213. def test_graphql_filter_by_status(self):
  214. """Circuits can be filtered by status in GraphQL using the prefixed enum values."""
  215. self.add_permissions('circuits.view_circuit')
  216. Circuit.objects.filter(cid='Circuit 1').update(status=CircuitStatusChoices.STATUS_PLANNED)
  217. query = '{ circuit_list(filters: {status: {exact: STATUS_PLANNED}}) { cid } }'
  218. response = self.client.post(reverse('graphql'), data={'query': query}, format='json', **self.header)
  219. self.assertHttpStatus(response, status.HTTP_200_OK)
  220. data = response.json()
  221. self.assertNotIn('errors', data)
  222. self.assertEqual([circuit['cid'] for circuit in data['data']['circuit_list']], ['Circuit 1'])
  223. class CircuitTerminationTestCase(APIViewTestCases.APIViewTestCase):
  224. model = CircuitTermination
  225. brief_fields = ['_occupied', 'cable', 'circuit', 'description', 'display', 'id', 'term_side', 'url']
  226. user_permissions = ('circuits.view_circuit', )
  227. @classmethod
  228. def setUpTestData(cls):
  229. SIDE_A = CircuitTerminationSideChoices.SIDE_A
  230. SIDE_Z = CircuitTerminationSideChoices.SIDE_Z
  231. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  232. circuit_type = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  233. sites = (
  234. Site(name='Site 1', slug='site-1'),
  235. Site(name='Site 2', slug='site-2'),
  236. )
  237. Site.objects.bulk_create(sites)
  238. provider_networks = (
  239. ProviderNetwork(provider=provider, name='Provider Network 1'),
  240. ProviderNetwork(provider=provider, name='Provider Network 2'),
  241. )
  242. ProviderNetwork.objects.bulk_create(provider_networks)
  243. circuits = (
  244. Circuit(cid='Circuit 1', provider=provider, type=circuit_type),
  245. Circuit(cid='Circuit 2', provider=provider, type=circuit_type),
  246. Circuit(cid='Circuit 3', provider=provider, type=circuit_type),
  247. )
  248. Circuit.objects.bulk_create(circuits)
  249. circuit_terminations = (
  250. CircuitTermination(circuit=circuits[0], term_side=SIDE_A, termination=sites[0]),
  251. CircuitTermination(circuit=circuits[0], term_side=SIDE_Z, termination=provider_networks[0]),
  252. CircuitTermination(circuit=circuits[1], term_side=SIDE_A, termination=sites[1]),
  253. CircuitTermination(circuit=circuits[1], term_side=SIDE_Z, termination=provider_networks[1]),
  254. )
  255. CircuitTermination.objects.bulk_create(circuit_terminations)
  256. cls.create_data = [
  257. {
  258. 'circuit': circuits[2].pk,
  259. 'term_side': SIDE_A,
  260. 'termination_type': 'dcim.site',
  261. 'termination_id': sites[0].pk,
  262. 'port_speed': 200000,
  263. },
  264. {
  265. 'circuit': circuits[2].pk,
  266. 'term_side': SIDE_Z,
  267. 'termination_type': 'circuits.providernetwork',
  268. 'termination_id': provider_networks[0].pk,
  269. 'port_speed': 200000,
  270. },
  271. ]
  272. cls.bulk_update_data = {
  273. 'port_speed': 123456
  274. }
  275. cls.bulk_update_invalid_data = {
  276. 'term_side': 'not-a-valid-term-side',
  277. }
  278. class CircuitGroupTestCase(APIViewTestCases.APIViewTestCase):
  279. model = CircuitGroup
  280. brief_fields = ['display', 'id', 'name', 'url']
  281. bulk_update_data = {
  282. 'description': 'New description',
  283. }
  284. bulk_update_invalid_data = {
  285. 'tenant': 99999,
  286. }
  287. @classmethod
  288. def setUpTestData(cls):
  289. circuit_groups = (
  290. CircuitGroup(name="Circuit Group 1", slug='circuit-group-1'),
  291. CircuitGroup(name="Circuit Group 2", slug='circuit-group-2'),
  292. CircuitGroup(name="Circuit Group 3", slug='circuit-group-3'),
  293. )
  294. CircuitGroup.objects.bulk_create(circuit_groups)
  295. cls.create_data = [
  296. {
  297. 'name': 'Circuit Group 4',
  298. 'slug': 'circuit-group-4',
  299. },
  300. {
  301. 'name': 'Circuit Group 5',
  302. 'slug': 'circuit-group-5',
  303. },
  304. {
  305. 'name': 'Circuit Group 6',
  306. 'slug': 'circuit-group-6',
  307. },
  308. ]
  309. class ProviderAccountTestCase(APIViewTestCases.APIViewTestCase):
  310. model = ProviderAccount
  311. brief_fields = ['account', 'description', 'display', 'id', 'name', 'url']
  312. user_permissions = ('circuits.view_provider',)
  313. @classmethod
  314. def setUpTestData(cls):
  315. providers = (
  316. Provider(name='Provider 1', slug='provider-1'),
  317. Provider(name='Provider 2', slug='provider-2'),
  318. )
  319. Provider.objects.bulk_create(providers)
  320. provider_accounts = (
  321. ProviderAccount(name='Provider Account 1', provider=providers[0], account='1234'),
  322. ProviderAccount(name='Provider Account 2', provider=providers[0], account='2345'),
  323. ProviderAccount(name='Provider Account 3', provider=providers[0], account='3456'),
  324. )
  325. ProviderAccount.objects.bulk_create(provider_accounts)
  326. cls.create_data = [
  327. {
  328. 'name': 'Provider Account 4',
  329. 'provider': providers[0].pk,
  330. 'account': '4567',
  331. },
  332. {
  333. 'name': 'Provider Account 5',
  334. 'provider': providers[0].pk,
  335. 'account': '5678',
  336. },
  337. {
  338. # Omit name to test uniqueness constraint
  339. 'provider': providers[0].pk,
  340. 'account': '6789',
  341. },
  342. ]
  343. cls.bulk_update_data = {
  344. 'provider': providers[1].pk,
  345. 'description': 'New description',
  346. }
  347. cls.bulk_update_invalid_data = {
  348. 'provider': 99999,
  349. }
  350. class CircuitGroupAssignmentTestCase(APIViewTestCases.APIViewTestCase):
  351. model = CircuitGroupAssignment
  352. brief_fields = ['display', 'group', 'id', 'member', 'member_id', 'member_type', 'priority', 'url']
  353. bulk_update_data = {
  354. 'priority': CircuitPriorityChoices.PRIORITY_INACTIVE,
  355. }
  356. bulk_update_invalid_data = {
  357. 'priority': 'not-a-valid-priority',
  358. }
  359. user_permissions = ('circuits.view_circuit', 'circuits.view_circuitgroup')
  360. @classmethod
  361. def setUpTestData(cls):
  362. circuit_groups = (
  363. CircuitGroup(name='Circuit Group 1', slug='circuit-group-1'),
  364. CircuitGroup(name='Circuit Group 2', slug='circuit-group-2'),
  365. CircuitGroup(name='Circuit Group 3', slug='circuit-group-3'),
  366. CircuitGroup(name='Circuit Group 4', slug='circuit-group-4'),
  367. CircuitGroup(name='Circuit Group 5', slug='circuit-group-5'),
  368. CircuitGroup(name='Circuit Group 6', slug='circuit-group-6'),
  369. )
  370. CircuitGroup.objects.bulk_create(circuit_groups)
  371. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  372. circuittype = CircuitType.objects.create(name='Circuit Type 1', slug='circuit-type-1')
  373. circuits = (
  374. Circuit(cid='Circuit 1', provider=provider, type=circuittype),
  375. Circuit(cid='Circuit 2', provider=provider, type=circuittype),
  376. Circuit(cid='Circuit 3', provider=provider, type=circuittype),
  377. Circuit(cid='Circuit 4', provider=provider, type=circuittype),
  378. Circuit(cid='Circuit 5', provider=provider, type=circuittype),
  379. Circuit(cid='Circuit 6', provider=provider, type=circuittype),
  380. )
  381. Circuit.objects.bulk_create(circuits)
  382. assignments = (
  383. CircuitGroupAssignment(
  384. group=circuit_groups[0],
  385. member=circuits[0],
  386. priority=CircuitPriorityChoices.PRIORITY_PRIMARY
  387. ),
  388. CircuitGroupAssignment(
  389. group=circuit_groups[1],
  390. member=circuits[1],
  391. priority=CircuitPriorityChoices.PRIORITY_SECONDARY
  392. ),
  393. CircuitGroupAssignment(
  394. group=circuit_groups[2],
  395. member=circuits[2],
  396. priority=CircuitPriorityChoices.PRIORITY_TERTIARY
  397. ),
  398. )
  399. CircuitGroupAssignment.objects.bulk_create(assignments)
  400. cls.create_data = [
  401. {
  402. 'group': circuit_groups[3].pk,
  403. 'member_type': 'circuits.circuit',
  404. 'member_id': circuits[3].pk,
  405. 'priority': CircuitPriorityChoices.PRIORITY_PRIMARY,
  406. },
  407. {
  408. 'group': circuit_groups[4].pk,
  409. 'member_type': 'circuits.circuit',
  410. 'member_id': circuits[4].pk,
  411. 'priority': CircuitPriorityChoices.PRIORITY_SECONDARY,
  412. },
  413. {
  414. 'group': circuit_groups[5].pk,
  415. 'member_type': 'circuits.circuit',
  416. 'member_id': circuits[5].pk,
  417. 'priority': CircuitPriorityChoices.PRIORITY_TERTIARY,
  418. },
  419. ]
  420. @tag('regression') # Ref: #23369
  421. def test_update_custom_fields(self):
  422. """Custom field data sent when updating an assignment is saved and rendered."""
  423. custom_field = CustomField.objects.create(name='cf1', type=CustomFieldTypeChoices.TYPE_TEXT)
  424. custom_field.object_types.set([ObjectType.objects.get_for_model(CircuitGroupAssignment)])
  425. self.add_permissions('circuits.change_circuitgroupassignment')
  426. assignment = CircuitGroupAssignment.objects.first()
  427. data = {
  428. 'custom_fields': {'cf1': 'foo'},
  429. }
  430. response = self.client.patch(self._get_detail_url(assignment), data, format='json', **self.header)
  431. self.assertHttpStatus(response, status.HTTP_200_OK)
  432. self.assertIn('custom_fields', response.data)
  433. self.assertEqual(response.data['custom_fields'], {'cf1': 'foo'})
  434. assignment.refresh_from_db()
  435. self.assertEqual(assignment.custom_field_data, {'cf1': 'foo'})
  436. @tag('regression') # Ref: #23369
  437. def test_graphql_custom_fields(self):
  438. """The GraphQL type renders the custom field data of an assignment."""
  439. custom_field = CustomField.objects.create(name='cf1', type=CustomFieldTypeChoices.TYPE_TEXT)
  440. custom_field.object_types.set([ObjectType.objects.get_for_model(CircuitGroupAssignment)])
  441. self.add_permissions('circuits.view_circuitgroupassignment')
  442. assignment = CircuitGroupAssignment.objects.first()
  443. CircuitGroupAssignment.objects.filter(pk=assignment.pk).update(custom_field_data={'cf1': 'foo'})
  444. query = '{ circuit_group_assignment(id: ' + str(assignment.pk) + ') { custom_fields } }'
  445. response = self.client.post(reverse('graphql'), data={'query': query}, format='json', **self.header)
  446. self.assertHttpStatus(response, status.HTTP_200_OK)
  447. data = response.json()
  448. self.assertNotIn('errors', data)
  449. self.assertEqual(data['data']['circuit_group_assignment']['custom_fields'], {'cf1': 'foo'})
  450. class ProviderNetworkTestCase(APIViewTestCases.APIViewTestCase):
  451. model = ProviderNetwork
  452. brief_fields = ['description', 'display', 'id', 'name', 'url']
  453. user_permissions = ('circuits.view_provider', )
  454. @classmethod
  455. def setUpTestData(cls):
  456. providers = (
  457. Provider(name='Provider 1', slug='provider-1'),
  458. Provider(name='Provider 2', slug='provider-2'),
  459. )
  460. Provider.objects.bulk_create(providers)
  461. provider_networks = (
  462. ProviderNetwork(name='Provider Network 1', provider=providers[0]),
  463. ProviderNetwork(name='Provider Network 2', provider=providers[0]),
  464. ProviderNetwork(name='Provider Network 3', provider=providers[0]),
  465. )
  466. ProviderNetwork.objects.bulk_create(provider_networks)
  467. cls.create_data = [
  468. {
  469. 'name': 'Provider Network 4',
  470. 'provider': providers[0].pk,
  471. },
  472. {
  473. 'name': 'Provider Network 5',
  474. 'provider': providers[0].pk,
  475. },
  476. {
  477. 'name': 'Provider Network 6',
  478. 'provider': providers[0].pk,
  479. },
  480. ]
  481. cls.bulk_update_data = {
  482. 'provider': providers[1].pk,
  483. 'description': 'New description',
  484. }
  485. cls.bulk_update_invalid_data = {
  486. 'provider': 99999,
  487. }
  488. class VirtualCircuitTypeTestCase(APIViewTestCases.APIViewTestCase):
  489. model = VirtualCircuitType
  490. brief_fields = ['description', 'display', 'id', 'name', 'slug', 'url', 'virtual_circuit_count']
  491. create_data = (
  492. {
  493. 'name': 'Virtual Circuit Type 4',
  494. 'slug': 'virtual-circuit-type-4',
  495. },
  496. {
  497. 'name': 'Virtual Circuit Type 5',
  498. 'slug': 'virtual-circuit-type-5',
  499. },
  500. {
  501. 'name': 'Virtual Circuit Type 6',
  502. 'slug': 'virtual-circuit-type-6',
  503. },
  504. )
  505. bulk_update_data = {
  506. 'description': 'New description',
  507. }
  508. bulk_update_invalid_data = {
  509. 'color': 'not-a-color',
  510. }
  511. @classmethod
  512. def setUpTestData(cls):
  513. virtual_circuit_types = (
  514. VirtualCircuitType(name='Virtual Circuit Type 1', slug='virtual-circuit-type-1'),
  515. VirtualCircuitType(name='Virtual Circuit Type 2', slug='virtual-circuit-type-2'),
  516. VirtualCircuitType(name='Virtual Circuit Type 3', slug='virtual-circuit-type-3'),
  517. )
  518. VirtualCircuitType.objects.bulk_create(virtual_circuit_types)
  519. class VirtualCircuitTestCase(APIViewTestCases.APIViewTestCase):
  520. model = VirtualCircuit
  521. brief_fields = ['cid', 'description', 'display', 'id', 'provider_network', 'url']
  522. bulk_update_data = {
  523. 'status': 'planned',
  524. }
  525. bulk_update_invalid_data = {
  526. 'status': 'not-a-valid-status',
  527. }
  528. @classmethod
  529. def setUpTestData(cls):
  530. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  531. provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1')
  532. provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1')
  533. virtual_circuit_type = VirtualCircuitType.objects.create(
  534. name='Virtual Circuit Type 1',
  535. slug='virtual-circuit-type-1'
  536. )
  537. virtual_circuits = (
  538. VirtualCircuit(
  539. provider_network=provider_network,
  540. provider_account=provider_account,
  541. type=virtual_circuit_type,
  542. cid='Virtual Circuit 1'
  543. ),
  544. VirtualCircuit(
  545. provider_network=provider_network,
  546. provider_account=provider_account,
  547. type=virtual_circuit_type,
  548. cid='Virtual Circuit 2'
  549. ),
  550. VirtualCircuit(
  551. provider_network=provider_network,
  552. provider_account=provider_account,
  553. type=virtual_circuit_type,
  554. cid='Virtual Circuit 3'
  555. ),
  556. )
  557. VirtualCircuit.objects.bulk_create(virtual_circuits)
  558. cls.create_data = [
  559. {
  560. 'cid': 'Virtual Circuit 4',
  561. 'provider_network': provider_network.pk,
  562. 'provider_account': provider_account.pk,
  563. 'type': virtual_circuit_type.pk,
  564. 'status': CircuitStatusChoices.STATUS_PLANNED,
  565. },
  566. {
  567. 'cid': 'Virtual Circuit 5',
  568. 'provider_network': provider_network.pk,
  569. 'provider_account': provider_account.pk,
  570. 'type': virtual_circuit_type.pk,
  571. 'status': CircuitStatusChoices.STATUS_PLANNED,
  572. },
  573. {
  574. 'cid': 'Virtual Circuit 6',
  575. 'provider_network': provider_network.pk,
  576. 'provider_account': provider_account.pk,
  577. 'type': virtual_circuit_type.pk,
  578. 'status': CircuitStatusChoices.STATUS_PLANNED,
  579. },
  580. ]
  581. class VirtualCircuitTerminationTestCase(APIViewTestCases.APIViewTestCase):
  582. model = VirtualCircuitTermination
  583. brief_fields = ['description', 'display', 'id', 'interface', 'role', 'url', 'virtual_circuit']
  584. bulk_update_data = {
  585. 'description': 'New description',
  586. }
  587. bulk_update_invalid_data = {
  588. 'role': 'not-a-valid-role',
  589. }
  590. @classmethod
  591. def setUpTestData(cls):
  592. manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1')
  593. device_type = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1')
  594. device_role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  595. site = Site.objects.create(name='Site 1', slug='site-1')
  596. devices = (
  597. Device(site=site, name='hub', device_type=device_type, role=device_role),
  598. Device(site=site, name='spoke1', device_type=device_type, role=device_role),
  599. Device(site=site, name='spoke2', device_type=device_type, role=device_role),
  600. Device(site=site, name='spoke3', device_type=device_type, role=device_role),
  601. )
  602. Device.objects.bulk_create(devices)
  603. physical_interfaces = (
  604. Interface(device=devices[0], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  605. Interface(device=devices[1], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  606. Interface(device=devices[2], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  607. Interface(device=devices[3], name='eth0', type=InterfaceTypeChoices.TYPE_1GE_FIXED),
  608. )
  609. Interface.objects.bulk_create(physical_interfaces)
  610. virtual_interfaces = (
  611. # Point-to-point VCs
  612. Interface(
  613. device=devices[0],
  614. name='eth0.1',
  615. parent=physical_interfaces[0],
  616. type=InterfaceTypeChoices.TYPE_VIRTUAL
  617. ),
  618. Interface(
  619. device=devices[0],
  620. name='eth0.2',
  621. parent=physical_interfaces[0],
  622. type=InterfaceTypeChoices.TYPE_VIRTUAL
  623. ),
  624. Interface(
  625. device=devices[0],
  626. name='eth0.3',
  627. parent=physical_interfaces[0],
  628. type=InterfaceTypeChoices.TYPE_VIRTUAL
  629. ),
  630. Interface(
  631. device=devices[1],
  632. name='eth0.1',
  633. parent=physical_interfaces[1],
  634. type=InterfaceTypeChoices.TYPE_VIRTUAL
  635. ),
  636. Interface(
  637. device=devices[2],
  638. name='eth0.1',
  639. parent=physical_interfaces[2],
  640. type=InterfaceTypeChoices.TYPE_VIRTUAL
  641. ),
  642. Interface(
  643. device=devices[3],
  644. name='eth0.1',
  645. parent=physical_interfaces[3],
  646. type=InterfaceTypeChoices.TYPE_VIRTUAL
  647. ),
  648. # Hub and spoke VCs
  649. Interface(
  650. device=devices[0],
  651. name='eth0.9',
  652. parent=physical_interfaces[0],
  653. type=InterfaceTypeChoices.TYPE_VIRTUAL
  654. ),
  655. Interface(
  656. device=devices[1],
  657. name='eth0.9',
  658. parent=physical_interfaces[0],
  659. type=InterfaceTypeChoices.TYPE_VIRTUAL
  660. ),
  661. Interface(
  662. device=devices[2],
  663. name='eth0.9',
  664. parent=physical_interfaces[0],
  665. type=InterfaceTypeChoices.TYPE_VIRTUAL
  666. ),
  667. Interface(
  668. device=devices[3],
  669. name='eth0.9',
  670. parent=physical_interfaces[0],
  671. type=InterfaceTypeChoices.TYPE_VIRTUAL
  672. ),
  673. )
  674. Interface.objects.bulk_create(virtual_interfaces)
  675. provider = Provider.objects.create(name='Provider 1', slug='provider-1')
  676. provider_network = ProviderNetwork.objects.create(provider=provider, name='Provider Network 1')
  677. provider_account = ProviderAccount.objects.create(provider=provider, account='Provider Account 1')
  678. virtual_circuit_type = VirtualCircuitType.objects.create(
  679. name='Virtual Circuit Type 1',
  680. slug='virtual-circuit-type-1'
  681. )
  682. virtual_circuits = (
  683. VirtualCircuit(
  684. provider_network=provider_network,
  685. provider_account=provider_account,
  686. cid='Virtual Circuit 1',
  687. type=virtual_circuit_type
  688. ),
  689. VirtualCircuit(
  690. provider_network=provider_network,
  691. provider_account=provider_account,
  692. cid='Virtual Circuit 2',
  693. type=virtual_circuit_type
  694. ),
  695. VirtualCircuit(
  696. provider_network=provider_network,
  697. provider_account=provider_account,
  698. cid='Virtual Circuit 3',
  699. type=virtual_circuit_type
  700. ),
  701. VirtualCircuit(
  702. provider_network=provider_network,
  703. provider_account=provider_account,
  704. cid='Virtual Circuit 4',
  705. type=virtual_circuit_type
  706. ),
  707. )
  708. VirtualCircuit.objects.bulk_create(virtual_circuits)
  709. virtual_circuit_terminations = (
  710. VirtualCircuitTermination(
  711. virtual_circuit=virtual_circuits[0],
  712. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  713. interface=virtual_interfaces[0]
  714. ),
  715. VirtualCircuitTermination(
  716. virtual_circuit=virtual_circuits[0],
  717. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  718. interface=virtual_interfaces[3]
  719. ),
  720. VirtualCircuitTermination(
  721. virtual_circuit=virtual_circuits[1],
  722. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  723. interface=virtual_interfaces[1]
  724. ),
  725. VirtualCircuitTermination(
  726. virtual_circuit=virtual_circuits[1],
  727. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  728. interface=virtual_interfaces[4]
  729. ),
  730. VirtualCircuitTermination(
  731. virtual_circuit=virtual_circuits[2],
  732. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  733. interface=virtual_interfaces[2]
  734. ),
  735. VirtualCircuitTermination(
  736. virtual_circuit=virtual_circuits[2],
  737. role=VirtualCircuitTerminationRoleChoices.ROLE_PEER,
  738. interface=virtual_interfaces[5]
  739. ),
  740. )
  741. VirtualCircuitTermination.objects.bulk_create(virtual_circuit_terminations)
  742. cls.create_data = [
  743. {
  744. 'virtual_circuit': virtual_circuits[3].pk,
  745. 'role': VirtualCircuitTerminationRoleChoices.ROLE_HUB,
  746. 'interface': virtual_interfaces[6].pk
  747. },
  748. {
  749. 'virtual_circuit': virtual_circuits[3].pk,
  750. 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE,
  751. 'interface': virtual_interfaces[7].pk
  752. },
  753. {
  754. 'virtual_circuit': virtual_circuits[3].pk,
  755. 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE,
  756. 'interface': virtual_interfaces[8].pk
  757. },
  758. {
  759. 'virtual_circuit': virtual_circuits[3].pk,
  760. 'role': VirtualCircuitTerminationRoleChoices.ROLE_SPOKE,
  761. 'interface': virtual_interfaces[9].pk
  762. },
  763. ]