test_views.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. from django.contrib.contenttypes.models import ContentType
  2. from django.test import override_settings
  3. from django.urls import reverse
  4. from dcim.choices import InterfaceModeChoices
  5. from dcim.models import DeviceRole, Platform, Site
  6. from ipam.models import VLAN, VRF
  7. from utilities.testing import ViewTestCases, create_tags, create_test_device, create_test_virtualmachine
  8. from virtualization.choices import *
  9. from virtualization.models import *
  10. class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  11. model = ClusterGroup
  12. @classmethod
  13. def setUpTestData(cls):
  14. cluster_groups = (
  15. ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
  16. ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
  17. ClusterGroup(name='Cluster Group 3', slug='cluster-group-3'),
  18. )
  19. ClusterGroup.objects.bulk_create(cluster_groups)
  20. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  21. cls.form_data = {
  22. 'name': 'Cluster Group X',
  23. 'slug': 'cluster-group-x',
  24. 'description': 'A new cluster group',
  25. 'tags': [t.pk for t in tags],
  26. }
  27. cls.csv_data = (
  28. "name,slug,description",
  29. "Cluster Group 4,cluster-group-4,Fourth cluster group",
  30. "Cluster Group 5,cluster-group-5,Fifth cluster group",
  31. "Cluster Group 6,cluster-group-6,Sixth cluster group",
  32. )
  33. cls.csv_update_data = (
  34. "id,name,description",
  35. f"{cluster_groups[0].pk},Cluster Group 7,Fourth cluster group7",
  36. f"{cluster_groups[1].pk},Cluster Group 8,Fifth cluster group8",
  37. f"{cluster_groups[2].pk},Cluster Group 9,Sixth cluster group9",
  38. )
  39. cls.bulk_edit_data = {
  40. 'description': 'New description',
  41. }
  42. class ClusterTypeTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
  43. model = ClusterType
  44. @classmethod
  45. def setUpTestData(cls):
  46. cluster_types = (
  47. ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
  48. ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
  49. ClusterType(name='Cluster Type 3', slug='cluster-type-3'),
  50. )
  51. ClusterType.objects.bulk_create(cluster_types)
  52. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  53. cls.form_data = {
  54. 'name': 'Cluster Type X',
  55. 'slug': 'cluster-type-x',
  56. 'description': 'A new cluster type',
  57. 'tags': [t.pk for t in tags],
  58. }
  59. cls.csv_data = (
  60. "name,slug,description",
  61. "Cluster Type 4,cluster-type-4,Fourth cluster type",
  62. "Cluster Type 5,cluster-type-5,Fifth cluster type",
  63. "Cluster Type 6,cluster-type-6,Sixth cluster type",
  64. )
  65. cls.csv_update_data = (
  66. "id,name,description",
  67. f"{cluster_types[0].pk},Cluster Type 7,Fourth cluster type7",
  68. f"{cluster_types[1].pk},Cluster Type 8,Fifth cluster type8",
  69. f"{cluster_types[2].pk},Cluster Type 9,Sixth cluster type9",
  70. )
  71. cls.bulk_edit_data = {
  72. 'description': 'New description',
  73. }
  74. class ClusterTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  75. model = Cluster
  76. @classmethod
  77. def setUpTestData(cls):
  78. sites = (
  79. Site(name='Site 1', slug='site-1'),
  80. Site(name='Site 2', slug='site-2'),
  81. )
  82. Site.objects.bulk_create(sites)
  83. clustergroups = (
  84. ClusterGroup(name='Cluster Group 1', slug='cluster-group-1'),
  85. ClusterGroup(name='Cluster Group 2', slug='cluster-group-2'),
  86. )
  87. ClusterGroup.objects.bulk_create(clustergroups)
  88. clustertypes = (
  89. ClusterType(name='Cluster Type 1', slug='cluster-type-1'),
  90. ClusterType(name='Cluster Type 2', slug='cluster-type-2'),
  91. )
  92. ClusterType.objects.bulk_create(clustertypes)
  93. clusters = (
  94. Cluster(
  95. name='Cluster 1',
  96. group=clustergroups[0],
  97. type=clustertypes[0],
  98. status=ClusterStatusChoices.STATUS_ACTIVE,
  99. scope=sites[0],
  100. ),
  101. Cluster(
  102. name='Cluster 2',
  103. group=clustergroups[0],
  104. type=clustertypes[0],
  105. status=ClusterStatusChoices.STATUS_ACTIVE,
  106. scope=sites[0],
  107. ),
  108. Cluster(
  109. name='Cluster 3',
  110. group=clustergroups[0],
  111. type=clustertypes[0],
  112. status=ClusterStatusChoices.STATUS_ACTIVE,
  113. scope=sites[0],
  114. ),
  115. )
  116. for cluster in clusters:
  117. cluster.save()
  118. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  119. cls.form_data = {
  120. 'name': 'Cluster X',
  121. 'group': clustergroups[1].pk,
  122. 'type': clustertypes[1].pk,
  123. 'status': ClusterStatusChoices.STATUS_OFFLINE,
  124. 'tenant': None,
  125. 'scope_type': ContentType.objects.get_for_model(Site).pk,
  126. 'scope': sites[1].pk,
  127. 'comments': 'Some comments',
  128. 'tags': [t.pk for t in tags],
  129. }
  130. cls.csv_data = (
  131. "name,type,status",
  132. "Cluster 4,Cluster Type 1,active",
  133. "Cluster 5,Cluster Type 1,active",
  134. "Cluster 6,Cluster Type 1,active",
  135. )
  136. cls.csv_update_data = (
  137. "id,name,comments",
  138. f"{clusters[0].pk},Cluster 7,New comments 7",
  139. f"{clusters[1].pk},Cluster 8,New comments 8",
  140. f"{clusters[2].pk},Cluster 9,New comments 9",
  141. )
  142. cls.bulk_edit_data = {
  143. 'group': clustergroups[1].pk,
  144. 'type': clustertypes[1].pk,
  145. 'status': ClusterStatusChoices.STATUS_OFFLINE,
  146. 'tenant': None,
  147. 'comments': 'New comments',
  148. }
  149. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  150. def test_cluster_virtualmachines(self):
  151. cluster = Cluster.objects.first()
  152. url = reverse('virtualization:cluster_virtualmachines', kwargs={'pk': cluster.pk})
  153. self.assertHttpStatus(self.client.get(url), 200)
  154. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  155. def test_cluster_devices(self):
  156. cluster = Cluster.objects.first()
  157. url = reverse('virtualization:cluster_devices', kwargs={'pk': cluster.pk})
  158. self.assertHttpStatus(self.client.get(url), 200)
  159. class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  160. model = VirtualMachine
  161. @classmethod
  162. def setUpTestData(cls):
  163. roles = (
  164. DeviceRole(name='Device Role 1', slug='device-role-1'),
  165. DeviceRole(name='Device Role 2', slug='device-role-2'),
  166. )
  167. for role in roles:
  168. role.save()
  169. platforms = (
  170. Platform(name='Platform 1', slug='platform-1'),
  171. Platform(name='Platform 2', slug='platform-2'),
  172. )
  173. for platform in platforms:
  174. platform.save()
  175. sites = (
  176. Site(name='Site 1', slug='site-1'),
  177. Site(name='Site 2', slug='site-2'),
  178. )
  179. Site.objects.bulk_create(sites)
  180. clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
  181. clusters = (
  182. Cluster(name='Cluster 1', type=clustertype, scope=sites[0]),
  183. Cluster(name='Cluster 2', type=clustertype, scope=sites[1]),
  184. )
  185. for cluster in clusters:
  186. cluster.save()
  187. devices = (
  188. create_test_device('device1', site=sites[0], cluster=clusters[0]),
  189. create_test_device('device2', site=sites[1], cluster=clusters[1]),
  190. )
  191. virtual_machines = (
  192. VirtualMachine(
  193. name='Virtual Machine 1',
  194. site=sites[0],
  195. cluster=clusters[0],
  196. device=devices[0],
  197. role=roles[0],
  198. platform=platforms[0],
  199. ),
  200. VirtualMachine(
  201. name='Virtual Machine 2',
  202. site=sites[0],
  203. cluster=clusters[0],
  204. device=devices[0],
  205. role=roles[0],
  206. platform=platforms[0],
  207. ),
  208. VirtualMachine(
  209. name='Virtual Machine 3',
  210. site=sites[0],
  211. cluster=clusters[0],
  212. device=devices[0],
  213. role=roles[0],
  214. platform=platforms[0],
  215. ),
  216. )
  217. VirtualMachine.objects.bulk_create(virtual_machines)
  218. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  219. cls.form_data = {
  220. 'cluster': clusters[1].pk,
  221. 'device': devices[1].pk,
  222. 'site': sites[1].pk,
  223. 'tenant': None,
  224. 'platform': platforms[1].pk,
  225. 'name': 'Virtual Machine X',
  226. 'status': VirtualMachineStatusChoices.STATUS_STAGED,
  227. 'role': roles[1].pk,
  228. 'primary_ip4': None,
  229. 'primary_ip6': None,
  230. 'vcpus': 4,
  231. 'memory': 32768,
  232. 'disk': 4000,
  233. 'serial': 'aaa-111',
  234. 'comments': 'Some comments',
  235. 'tags': [t.pk for t in tags],
  236. 'local_context_data': None,
  237. }
  238. cls.csv_data = (
  239. "name,status,site,cluster,device",
  240. "Virtual Machine 4,active,Site 1,Cluster 1,device1",
  241. "Virtual Machine 5,active,Site 1,Cluster 1,device1",
  242. "Virtual Machine 6,active,Site 1,Cluster 1,",
  243. )
  244. cls.csv_update_data = (
  245. "id,name,comments",
  246. f"{virtual_machines[0].pk},Virtual Machine 7,New comments 7",
  247. f"{virtual_machines[1].pk},Virtual Machine 8,New comments 8",
  248. f"{virtual_machines[2].pk},Virtual Machine 9,New comments 9",
  249. )
  250. cls.bulk_edit_data = {
  251. 'site': sites[1].pk,
  252. 'cluster': clusters[1].pk,
  253. 'device': devices[1].pk,
  254. 'tenant': None,
  255. 'platform': platforms[1].pk,
  256. 'status': VirtualMachineStatusChoices.STATUS_STAGED,
  257. 'role': roles[1].pk,
  258. 'vcpus': 8,
  259. 'memory': 65535,
  260. 'disk': 8000,
  261. 'comments': 'New comments',
  262. }
  263. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  264. def test_virtualmachine_interfaces(self):
  265. virtualmachine = VirtualMachine.objects.first()
  266. vminterfaces = (
  267. VMInterface(virtual_machine=virtualmachine, name='Interface 1'),
  268. VMInterface(virtual_machine=virtualmachine, name='Interface 2'),
  269. VMInterface(virtual_machine=virtualmachine, name='Interface 3'),
  270. )
  271. VMInterface.objects.bulk_create(vminterfaces)
  272. url = reverse('virtualization:virtualmachine_interfaces', kwargs={'pk': virtualmachine.pk})
  273. self.assertHttpStatus(self.client.get(url), 200)
  274. class VMInterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
  275. model = VMInterface
  276. validation_excluded_fields = ('name',)
  277. @classmethod
  278. def setUpTestData(cls):
  279. site = Site.objects.create(name='Site 1', slug='site-1')
  280. role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  281. clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
  282. cluster = Cluster.objects.create(name='Cluster 1', type=clustertype, scope=site)
  283. virtualmachines = (
  284. VirtualMachine(name='Virtual Machine 1', site=site, cluster=cluster, role=role),
  285. VirtualMachine(name='Virtual Machine 2', site=site, cluster=cluster, role=role),
  286. )
  287. VirtualMachine.objects.bulk_create(virtualmachines)
  288. interfaces = VMInterface.objects.bulk_create([
  289. VMInterface(virtual_machine=virtualmachines[0], name='Interface 1'),
  290. VMInterface(virtual_machine=virtualmachines[0], name='Interface 2'),
  291. VMInterface(virtual_machine=virtualmachines[0], name='Interface 3'),
  292. VMInterface(virtual_machine=virtualmachines[1], name='BRIDGE'),
  293. ])
  294. vlans = (
  295. VLAN(vid=1, name='VLAN1', site=site),
  296. VLAN(vid=101, name='VLAN101', site=site),
  297. VLAN(vid=102, name='VLAN102', site=site),
  298. VLAN(vid=103, name='VLAN103', site=site),
  299. )
  300. VLAN.objects.bulk_create(vlans)
  301. vrfs = (
  302. VRF(name='VRF 1'),
  303. VRF(name='VRF 2'),
  304. VRF(name='VRF 3'),
  305. )
  306. VRF.objects.bulk_create(vrfs)
  307. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  308. cls.form_data = {
  309. 'virtual_machine': virtualmachines[0].pk,
  310. 'name': 'Interface X',
  311. 'enabled': False,
  312. 'bridge': interfaces[1].pk,
  313. 'mtu': 65000,
  314. 'description': 'New description',
  315. 'mode': InterfaceModeChoices.MODE_TAGGED,
  316. 'untagged_vlan': vlans[0].pk,
  317. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  318. 'vrf': vrfs[0].pk,
  319. 'tags': [t.pk for t in tags],
  320. }
  321. cls.bulk_create_data = {
  322. 'virtual_machine': virtualmachines[1].pk,
  323. 'name': 'Interface [4-6]',
  324. 'enabled': False,
  325. 'bridge': interfaces[3].pk,
  326. 'mtu': 2000,
  327. 'description': 'New description',
  328. 'mode': InterfaceModeChoices.MODE_TAGGED,
  329. 'untagged_vlan': vlans[0].pk,
  330. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  331. 'vrf': vrfs[0].pk,
  332. 'tags': [t.pk for t in tags],
  333. }
  334. cls.csv_data = (
  335. "virtual_machine,name,vrf.pk",
  336. f"Virtual Machine 2,Interface 4,{vrfs[0].pk}",
  337. f"Virtual Machine 2,Interface 5,{vrfs[0].pk}",
  338. f"Virtual Machine 2,Interface 6,{vrfs[0].pk}",
  339. )
  340. cls.csv_update_data = (
  341. "id,name,description",
  342. f"{interfaces[0].pk},Interface 7,New description 7",
  343. f"{interfaces[1].pk},Interface 8,New description 8",
  344. f"{interfaces[2].pk},Interface 9,New description 9",
  345. )
  346. cls.bulk_edit_data = {
  347. 'enabled': False,
  348. 'mtu': 2000,
  349. 'description': 'New description',
  350. 'mode': InterfaceModeChoices.MODE_TAGGED,
  351. 'untagged_vlan': vlans[0].pk,
  352. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  353. }
  354. def test_bulk_delete_child_interfaces(self):
  355. interface1 = VMInterface.objects.get(name='Interface 1')
  356. virtual_machine = interface1.virtual_machine
  357. self.add_permissions('virtualization.delete_vminterface')
  358. # Create a child interface
  359. child = VMInterface.objects.create(
  360. virtual_machine=virtual_machine,
  361. name='Interface 1A',
  362. parent=interface1
  363. )
  364. self.assertEqual(virtual_machine.interfaces.count(), 4)
  365. # Attempt to delete only the parent interface
  366. data = {
  367. 'confirm': True,
  368. }
  369. self.client.post(self._get_url('delete', interface1), data)
  370. self.assertEqual(virtual_machine.interfaces.count(), 4) # Parent was not deleted
  371. # Attempt to bulk delete parent & child together
  372. data = {
  373. 'pk': [interface1.pk, child.pk],
  374. 'confirm': True,
  375. '_confirm': True, # Form button
  376. }
  377. self.client.post(self._get_url('bulk_delete'), data)
  378. self.assertEqual(virtual_machine.interfaces.count(), 2) # Child & parent were both deleted
  379. class VirtualDiskTestCase(ViewTestCases.DeviceComponentViewTestCase):
  380. model = VirtualDisk
  381. validation_excluded_fields = ('name',)
  382. @classmethod
  383. def setUpTestData(cls):
  384. virtualmachine = create_test_virtualmachine('Virtual Machine 1')
  385. disks = VirtualDisk.objects.bulk_create([
  386. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 1', size=10),
  387. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 2', size=10),
  388. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 3', size=10),
  389. ])
  390. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  391. cls.form_data = {
  392. 'virtual_machine': virtualmachine.pk,
  393. 'name': 'Virtual Disk X',
  394. 'size': 20,
  395. 'description': 'New description',
  396. 'tags': [t.pk for t in tags],
  397. }
  398. cls.bulk_create_data = {
  399. 'virtual_machine': virtualmachine.pk,
  400. 'name': 'Virtual Disk [4-6]',
  401. 'size': 10,
  402. 'tags': [t.pk for t in tags],
  403. }
  404. cls.csv_data = (
  405. "virtual_machine,name,size,description",
  406. "Virtual Machine 1,Disk 4,20,Fourth",
  407. "Virtual Machine 1,Disk 5,20,Fifth",
  408. "Virtual Machine 1,Disk 6,20,Sixth",
  409. )
  410. cls.csv_update_data = (
  411. "id,name,size",
  412. f"{disks[0].pk},disk1,20",
  413. f"{disks[1].pk},disk2,20",
  414. f"{disks[2].pk},disk3,20",
  415. )
  416. cls.bulk_edit_data = {
  417. 'size': 30,
  418. 'description': 'New description',
  419. }