test_views.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  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(name='Cluster 1', group=clustergroups[0], type=clustertypes[0], status=ClusterStatusChoices.STATUS_ACTIVE, scope=sites[0]),
  95. Cluster(name='Cluster 2', group=clustergroups[0], type=clustertypes[0], status=ClusterStatusChoices.STATUS_ACTIVE, scope=sites[0]),
  96. Cluster(name='Cluster 3', group=clustergroups[0], type=clustertypes[0], status=ClusterStatusChoices.STATUS_ACTIVE, scope=sites[0]),
  97. )
  98. for cluster in clusters:
  99. cluster.save()
  100. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  101. cls.form_data = {
  102. 'name': 'Cluster X',
  103. 'group': clustergroups[1].pk,
  104. 'type': clustertypes[1].pk,
  105. 'status': ClusterStatusChoices.STATUS_OFFLINE,
  106. 'tenant': None,
  107. 'scope_type': ContentType.objects.get_for_model(Site).pk,
  108. 'scope': sites[1].pk,
  109. 'comments': 'Some comments',
  110. 'tags': [t.pk for t in tags],
  111. }
  112. cls.csv_data = (
  113. "name,type,status",
  114. "Cluster 4,Cluster Type 1,active",
  115. "Cluster 5,Cluster Type 1,active",
  116. "Cluster 6,Cluster Type 1,active",
  117. )
  118. cls.csv_update_data = (
  119. "id,name,comments",
  120. f"{clusters[0].pk},Cluster 7,New comments 7",
  121. f"{clusters[1].pk},Cluster 8,New comments 8",
  122. f"{clusters[2].pk},Cluster 9,New comments 9",
  123. )
  124. cls.bulk_edit_data = {
  125. 'group': clustergroups[1].pk,
  126. 'type': clustertypes[1].pk,
  127. 'status': ClusterStatusChoices.STATUS_OFFLINE,
  128. 'tenant': None,
  129. 'comments': 'New comments',
  130. }
  131. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  132. def test_cluster_virtualmachines(self):
  133. cluster = Cluster.objects.first()
  134. url = reverse('virtualization:cluster_virtualmachines', kwargs={'pk': cluster.pk})
  135. self.assertHttpStatus(self.client.get(url), 200)
  136. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  137. def test_cluster_devices(self):
  138. cluster = Cluster.objects.first()
  139. url = reverse('virtualization:cluster_devices', kwargs={'pk': cluster.pk})
  140. self.assertHttpStatus(self.client.get(url), 200)
  141. class VirtualMachineTestCase(ViewTestCases.PrimaryObjectViewTestCase):
  142. model = VirtualMachine
  143. @classmethod
  144. def setUpTestData(cls):
  145. roles = (
  146. DeviceRole(name='Device Role 1', slug='device-role-1'),
  147. DeviceRole(name='Device Role 2', slug='device-role-2'),
  148. )
  149. DeviceRole.objects.bulk_create(roles)
  150. platforms = (
  151. Platform(name='Platform 1', slug='platform-1'),
  152. Platform(name='Platform 2', slug='platform-2'),
  153. )
  154. Platform.objects.bulk_create(platforms)
  155. sites = (
  156. Site(name='Site 1', slug='site-1'),
  157. Site(name='Site 2', slug='site-2'),
  158. )
  159. Site.objects.bulk_create(sites)
  160. clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
  161. clusters = (
  162. Cluster(name='Cluster 1', type=clustertype, scope=sites[0]),
  163. Cluster(name='Cluster 2', type=clustertype, scope=sites[1]),
  164. )
  165. for cluster in clusters:
  166. cluster.save()
  167. devices = (
  168. create_test_device('device1', site=sites[0], cluster=clusters[0]),
  169. create_test_device('device2', site=sites[1], cluster=clusters[1]),
  170. )
  171. virtual_machines = (
  172. VirtualMachine(name='Virtual Machine 1', site=sites[0], cluster=clusters[0], device=devices[0], role=roles[0], platform=platforms[0]),
  173. VirtualMachine(name='Virtual Machine 2', site=sites[0], cluster=clusters[0], device=devices[0], role=roles[0], platform=platforms[0]),
  174. VirtualMachine(name='Virtual Machine 3', site=sites[0], cluster=clusters[0], device=devices[0], role=roles[0], platform=platforms[0]),
  175. )
  176. VirtualMachine.objects.bulk_create(virtual_machines)
  177. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  178. cls.form_data = {
  179. 'cluster': clusters[1].pk,
  180. 'device': devices[1].pk,
  181. 'site': sites[1].pk,
  182. 'tenant': None,
  183. 'platform': platforms[1].pk,
  184. 'name': 'Virtual Machine X',
  185. 'status': VirtualMachineStatusChoices.STATUS_STAGED,
  186. 'role': roles[1].pk,
  187. 'primary_ip4': None,
  188. 'primary_ip6': None,
  189. 'vcpus': 4,
  190. 'memory': 32768,
  191. 'disk': 4000,
  192. 'serial': 'aaa-111',
  193. 'comments': 'Some comments',
  194. 'tags': [t.pk for t in tags],
  195. 'local_context_data': None,
  196. }
  197. cls.csv_data = (
  198. "name,status,site,cluster,device",
  199. "Virtual Machine 4,active,Site 1,Cluster 1,device1",
  200. "Virtual Machine 5,active,Site 1,Cluster 1,device1",
  201. "Virtual Machine 6,active,Site 1,Cluster 1,",
  202. )
  203. cls.csv_update_data = (
  204. "id,name,comments",
  205. f"{virtual_machines[0].pk},Virtual Machine 7,New comments 7",
  206. f"{virtual_machines[1].pk},Virtual Machine 8,New comments 8",
  207. f"{virtual_machines[2].pk},Virtual Machine 9,New comments 9",
  208. )
  209. cls.bulk_edit_data = {
  210. 'site': sites[1].pk,
  211. 'cluster': clusters[1].pk,
  212. 'device': devices[1].pk,
  213. 'tenant': None,
  214. 'platform': platforms[1].pk,
  215. 'status': VirtualMachineStatusChoices.STATUS_STAGED,
  216. 'role': roles[1].pk,
  217. 'vcpus': 8,
  218. 'memory': 65535,
  219. 'disk': 8000,
  220. 'comments': 'New comments',
  221. }
  222. @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
  223. def test_virtualmachine_interfaces(self):
  224. virtualmachine = VirtualMachine.objects.first()
  225. vminterfaces = (
  226. VMInterface(virtual_machine=virtualmachine, name='Interface 1'),
  227. VMInterface(virtual_machine=virtualmachine, name='Interface 2'),
  228. VMInterface(virtual_machine=virtualmachine, name='Interface 3'),
  229. )
  230. VMInterface.objects.bulk_create(vminterfaces)
  231. url = reverse('virtualization:virtualmachine_interfaces', kwargs={'pk': virtualmachine.pk})
  232. self.assertHttpStatus(self.client.get(url), 200)
  233. class VMInterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
  234. model = VMInterface
  235. validation_excluded_fields = ('name',)
  236. @classmethod
  237. def setUpTestData(cls):
  238. site = Site.objects.create(name='Site 1', slug='site-1')
  239. role = DeviceRole.objects.create(name='Device Role 1', slug='device-role-1')
  240. clustertype = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
  241. cluster = Cluster.objects.create(name='Cluster 1', type=clustertype, scope=site)
  242. virtualmachines = (
  243. VirtualMachine(name='Virtual Machine 1', site=site, cluster=cluster, role=role),
  244. VirtualMachine(name='Virtual Machine 2', site=site, cluster=cluster, role=role),
  245. )
  246. VirtualMachine.objects.bulk_create(virtualmachines)
  247. interfaces = VMInterface.objects.bulk_create([
  248. VMInterface(virtual_machine=virtualmachines[0], name='Interface 1'),
  249. VMInterface(virtual_machine=virtualmachines[0], name='Interface 2'),
  250. VMInterface(virtual_machine=virtualmachines[0], name='Interface 3'),
  251. VMInterface(virtual_machine=virtualmachines[1], name='BRIDGE'),
  252. ])
  253. vlans = (
  254. VLAN(vid=1, name='VLAN1', site=site),
  255. VLAN(vid=101, name='VLAN101', site=site),
  256. VLAN(vid=102, name='VLAN102', site=site),
  257. VLAN(vid=103, name='VLAN103', site=site),
  258. )
  259. VLAN.objects.bulk_create(vlans)
  260. vrfs = (
  261. VRF(name='VRF 1'),
  262. VRF(name='VRF 2'),
  263. VRF(name='VRF 3'),
  264. )
  265. VRF.objects.bulk_create(vrfs)
  266. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  267. cls.form_data = {
  268. 'virtual_machine': virtualmachines[0].pk,
  269. 'name': 'Interface X',
  270. 'enabled': False,
  271. 'bridge': interfaces[1].pk,
  272. 'mtu': 65000,
  273. 'description': 'New description',
  274. 'mode': InterfaceModeChoices.MODE_TAGGED,
  275. 'untagged_vlan': vlans[0].pk,
  276. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  277. 'vrf': vrfs[0].pk,
  278. 'tags': [t.pk for t in tags],
  279. }
  280. cls.bulk_create_data = {
  281. 'virtual_machine': virtualmachines[1].pk,
  282. 'name': 'Interface [4-6]',
  283. 'enabled': False,
  284. 'bridge': interfaces[3].pk,
  285. 'mtu': 2000,
  286. 'description': 'New description',
  287. 'mode': InterfaceModeChoices.MODE_TAGGED,
  288. 'untagged_vlan': vlans[0].pk,
  289. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  290. 'vrf': vrfs[0].pk,
  291. 'tags': [t.pk for t in tags],
  292. }
  293. cls.csv_data = (
  294. "virtual_machine,name,vrf.pk",
  295. f"Virtual Machine 2,Interface 4,{vrfs[0].pk}",
  296. f"Virtual Machine 2,Interface 5,{vrfs[0].pk}",
  297. f"Virtual Machine 2,Interface 6,{vrfs[0].pk}",
  298. )
  299. cls.csv_update_data = (
  300. "id,name,description",
  301. f"{interfaces[0].pk},Interface 7,New description 7",
  302. f"{interfaces[1].pk},Interface 8,New description 8",
  303. f"{interfaces[2].pk},Interface 9,New description 9",
  304. )
  305. cls.bulk_edit_data = {
  306. 'enabled': False,
  307. 'mtu': 2000,
  308. 'description': 'New description',
  309. 'mode': InterfaceModeChoices.MODE_TAGGED,
  310. 'untagged_vlan': vlans[0].pk,
  311. 'tagged_vlans': [v.pk for v in vlans[1:4]],
  312. }
  313. def test_bulk_delete_child_interfaces(self):
  314. interface1 = VMInterface.objects.get(name='Interface 1')
  315. virtual_machine = interface1.virtual_machine
  316. self.add_permissions('virtualization.delete_vminterface')
  317. # Create a child interface
  318. child = VMInterface.objects.create(
  319. virtual_machine=virtual_machine,
  320. name='Interface 1A',
  321. parent=interface1
  322. )
  323. self.assertEqual(virtual_machine.interfaces.count(), 4)
  324. # Attempt to delete only the parent interface
  325. data = {
  326. 'confirm': True,
  327. }
  328. self.client.post(self._get_url('delete', interface1), data)
  329. self.assertEqual(virtual_machine.interfaces.count(), 4) # Parent was not deleted
  330. # Attempt to bulk delete parent & child together
  331. data = {
  332. 'pk': [interface1.pk, child.pk],
  333. 'confirm': True,
  334. '_confirm': True, # Form button
  335. }
  336. self.client.post(self._get_url('bulk_delete'), data)
  337. self.assertEqual(virtual_machine.interfaces.count(), 2) # Child & parent were both deleted
  338. class VirtualDiskTestCase(ViewTestCases.DeviceComponentViewTestCase):
  339. model = VirtualDisk
  340. validation_excluded_fields = ('name',)
  341. @classmethod
  342. def setUpTestData(cls):
  343. virtualmachine = create_test_virtualmachine('Virtual Machine 1')
  344. disks = VirtualDisk.objects.bulk_create([
  345. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 1', size=10),
  346. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 2', size=10),
  347. VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 3', size=10),
  348. ])
  349. tags = create_tags('Alpha', 'Bravo', 'Charlie')
  350. cls.form_data = {
  351. 'virtual_machine': virtualmachine.pk,
  352. 'name': 'Virtual Disk X',
  353. 'size': 20,
  354. 'description': 'New description',
  355. 'tags': [t.pk for t in tags],
  356. }
  357. cls.bulk_create_data = {
  358. 'virtual_machine': virtualmachine.pk,
  359. 'name': 'Virtual Disk [4-6]',
  360. 'size': 10,
  361. 'tags': [t.pk for t in tags],
  362. }
  363. cls.csv_data = (
  364. "virtual_machine,name,size,description",
  365. "Virtual Machine 1,Disk 4,20,Fourth",
  366. "Virtual Machine 1,Disk 5,20,Fifth",
  367. "Virtual Machine 1,Disk 6,20,Sixth",
  368. )
  369. cls.csv_update_data = (
  370. "id,name,size",
  371. f"{disks[0].pk},disk1,20",
  372. f"{disks[1].pk},disk2,20",
  373. f"{disks[2].pk},disk3,20",
  374. )
  375. cls.bulk_edit_data = {
  376. 'size': 30,
  377. 'description': 'New description',
  378. }