mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
* 8356 add virtual disk model * 8356 add supplemental forms * 8356 add menu * 8356 cleanup views * 8356 virtual machine tab * 8356 migrations * 8356 vm disk tables * 8356 cleanup * 8356 graphql * 8356 graphql * 8356 add components button * 8356 bulk add on virtualmachine * 8356 bulk add fixes * 8356 api tests * 8356 news tests add rename * 8356 VirtualDiskCreateForm * 8356 fix test * 8356 add todo to remove disk from vm * 8356 review changes * 8356 fix test * 8356 deprecate disk field * 8356 review changes * 8356 fix test * 8356 fix test * Simplify view actions * 8356 review changes * 8356 split trans tag * 8356 add total virtual disk size to api * 8356 add virtual disk list to virtual machine detail view * 8356 move virtual disk size to property * 8356 revert property * Tweak display of deprecated disk field * 8356 render single disk field * 8356 update serializer * 8356 model property * 8356 fix test * 8356 review changes * Revert disk space annotation * Use existing disk field to store aggregate virtual disk size * Introduce abstract ComponentModel for VM components * Add search index for VirtualDisk * Misc cleanup --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
@@ -5,9 +5,9 @@ from dcim.choices import InterfaceModeChoices
|
||||
from dcim.models import Site
|
||||
from extras.models import ConfigTemplate
|
||||
from ipam.models import VLAN, VRF
|
||||
from utilities.testing import APITestCase, APIViewTestCases, create_test_device
|
||||
from utilities.testing import APITestCase, APIViewTestCases, create_test_device, create_test_virtualmachine
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||
from virtualization.models import *
|
||||
|
||||
|
||||
class AppTest(APITestCase):
|
||||
@@ -256,10 +256,7 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
|
||||
clustertype = ClusterType.objects.create(name='Test Cluster Type 1', slug='test-cluster-type-1')
|
||||
cluster = Cluster.objects.create(name='Test Cluster 1', type=clustertype)
|
||||
virtualmachine = VirtualMachine.objects.create(cluster=cluster, name='Test VM 1')
|
||||
virtualmachine = create_test_virtualmachine('Virtual Machine 1')
|
||||
|
||||
interfaces = (
|
||||
VMInterface(virtual_machine=virtualmachine, name='Interface 1'),
|
||||
@@ -336,3 +333,41 @@ class VMInterfaceTest(APIViewTestCases.APIViewTestCase):
|
||||
]
|
||||
self.client.delete(self._get_list_url(), data, format='json', **self.header)
|
||||
self.assertEqual(virtual_machine.interfaces.count(), 2) # Child & parent were both deleted
|
||||
|
||||
|
||||
class VirtualDiskTest(APIViewTestCases.APIViewTestCase):
|
||||
model = VirtualDisk
|
||||
brief_fields = ['display', 'id', 'name', 'size', 'url', 'virtual_machine']
|
||||
bulk_update_data = {
|
||||
'size': 888,
|
||||
}
|
||||
graphql_base_name = 'virtual_disk'
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
virtualmachine = create_test_virtualmachine('Virtual Machine 1')
|
||||
|
||||
disks = (
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Disk 1', size=10),
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Disk 2', size=20),
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Disk 3', size=30),
|
||||
)
|
||||
VirtualDisk.objects.bulk_create(disks)
|
||||
|
||||
cls.create_data = [
|
||||
{
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Disk 4',
|
||||
'size': 10,
|
||||
},
|
||||
{
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Disk 5',
|
||||
'size': 20,
|
||||
},
|
||||
{
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Disk 6',
|
||||
'size': 30,
|
||||
},
|
||||
]
|
||||
|
@@ -6,7 +6,7 @@ from tenancy.models import Tenant, TenantGroup
|
||||
from utilities.testing import ChangeLoggedFilterSetTests, create_test_device
|
||||
from virtualization.choices import *
|
||||
from virtualization.filtersets import *
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||
from virtualization.models import *
|
||||
|
||||
|
||||
class ClusterTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
@@ -534,3 +534,46 @@ class VMInterfaceTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
def test_description(self):
|
||||
params = {'description': ['foobar1', 'foobar2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
|
||||
class VirtualDiskTestCase(TestCase, ChangeLoggedFilterSetTests):
|
||||
queryset = VirtualDisk.objects.all()
|
||||
filterset = VirtualDiskFilterSet
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
cluster_type = ClusterType.objects.create(name='Cluster Type 1', slug='cluster-type-1')
|
||||
cluster = Cluster.objects.create(name='Cluster 1', type=cluster_type)
|
||||
|
||||
vms = (
|
||||
VirtualMachine(name='Virtual Machine 1', cluster=cluster),
|
||||
VirtualMachine(name='Virtual Machine 2', cluster=cluster),
|
||||
VirtualMachine(name='Virtual Machine 3', cluster=cluster),
|
||||
)
|
||||
VirtualMachine.objects.bulk_create(vms)
|
||||
|
||||
disks = (
|
||||
VirtualDisk(virtual_machine=vms[0], name='Disk 1', size=1, description='A'),
|
||||
VirtualDisk(virtual_machine=vms[1], name='Disk 2', size=2, description='B'),
|
||||
VirtualDisk(virtual_machine=vms[2], name='Disk 3', size=3, description='C'),
|
||||
)
|
||||
VirtualDisk.objects.bulk_create(disks)
|
||||
|
||||
def test_virtual_machine(self):
|
||||
vms = VirtualMachine.objects.all()[:2]
|
||||
params = {'virtual_machine_id': [vms[0].pk, vms[1].pk]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
params = {'virtual_machine': [vms[0].name, vms[1].name]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_name(self):
|
||||
params = {'name': ['Disk 1', 'Disk 2']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_size(self):
|
||||
params = {'size': [1, 2]}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
||||
def test_description(self):
|
||||
params = {'description': ['A', 'B']}
|
||||
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
||||
|
@@ -90,3 +90,28 @@ class VirtualMachineTestCase(TestCase):
|
||||
# Uniqueness validation for name should ignore case
|
||||
with self.assertRaises(ValidationError):
|
||||
vm2.full_clean()
|
||||
|
||||
def test_disk_size(self):
|
||||
vm = VirtualMachine(
|
||||
cluster=Cluster.objects.first(),
|
||||
name='Virtual Machine 1'
|
||||
)
|
||||
vm.save()
|
||||
vm.refresh_from_db()
|
||||
self.assertEqual(vm.disk, None)
|
||||
|
||||
# Create two VirtualDisks
|
||||
VirtualDisk.objects.create(virtual_machine=vm, name='Virtual Disk 1', size=10)
|
||||
VirtualDisk.objects.create(virtual_machine=vm, name='Virtual Disk 2', size=10)
|
||||
vm.refresh_from_db()
|
||||
self.assertEqual(vm.disk, 20)
|
||||
|
||||
# Delete one VirtualDisk
|
||||
VirtualDisk.objects.first().delete()
|
||||
vm.refresh_from_db()
|
||||
self.assertEqual(vm.disk, 10)
|
||||
|
||||
# Attempt to manually overwrite the aggregate disk size
|
||||
vm.disk = 30
|
||||
with self.assertRaises(ValidationError):
|
||||
vm.full_clean()
|
||||
|
@@ -5,9 +5,9 @@ from netaddr import EUI
|
||||
from dcim.choices import InterfaceModeChoices
|
||||
from dcim.models import DeviceRole, Platform, Site
|
||||
from ipam.models import VLAN, VRF
|
||||
from utilities.testing import ViewTestCases, create_tags, create_test_device
|
||||
from utilities.testing import ViewTestCases, create_tags, create_test_device, create_test_virtualmachine
|
||||
from virtualization.choices import *
|
||||
from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||
from virtualization.models import *
|
||||
|
||||
|
||||
class ClusterGroupTestCase(ViewTestCases.OrganizationalObjectViewTestCase):
|
||||
@@ -403,3 +403,54 @@ class VMInterfaceTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
||||
}
|
||||
self.client.post(self._get_url('bulk_delete'), data)
|
||||
self.assertEqual(virtual_machine.interfaces.count(), 2) # Child & parent were both deleted
|
||||
|
||||
|
||||
class VirtualDiskTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
||||
model = VirtualDisk
|
||||
validation_excluded_fields = ('name',)
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
virtualmachine = create_test_virtualmachine('Virtual Machine 1')
|
||||
|
||||
disks = VirtualDisk.objects.bulk_create([
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 1', size=10),
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 2', size=10),
|
||||
VirtualDisk(virtual_machine=virtualmachine, name='Virtual Disk 3', size=10),
|
||||
])
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Virtual Disk X',
|
||||
'size': 20,
|
||||
'description': 'New description',
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.bulk_create_data = {
|
||||
'virtual_machine': virtualmachine.pk,
|
||||
'name': 'Virtual Disk [4-6]',
|
||||
'size': 10,
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
f"virtual_machine,name,size,description",
|
||||
f"Virtual Machine 1,Disk 4,20,Fourth",
|
||||
f"Virtual Machine 1,Disk 5,20,Fifth",
|
||||
f"Virtual Machine 1,Disk 6,20,Sixth",
|
||||
)
|
||||
|
||||
cls.csv_update_data = (
|
||||
f"id,name,size",
|
||||
f"{disks[0].pk},disk1,20",
|
||||
f"{disks[1].pk},disk2,20",
|
||||
f"{disks[2].pk},disk3,20",
|
||||
)
|
||||
|
||||
cls.bulk_edit_data = {
|
||||
'size': 30,
|
||||
'description': 'New description',
|
||||
}
|
||||
|
Reference in New Issue
Block a user