mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Show parent device/VM when creating new components
This commit is contained in:
@ -8,7 +8,8 @@ from utilities.forms import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ComponentCreateForm',
|
'DeviceComponentCreateForm',
|
||||||
|
'DeviceTypeComponentCreateForm',
|
||||||
'FrontPortCreateForm',
|
'FrontPortCreateForm',
|
||||||
'FrontPortTemplateCreateForm',
|
'FrontPortTemplateCreateForm',
|
||||||
'VirtualChassisCreateForm',
|
'VirtualChassisCreateForm',
|
||||||
@ -43,14 +44,28 @@ class ComponentCreateForm(BootstrapMixin, forms.Form):
|
|||||||
}, code='label_pattern_mismatch')
|
}, code='label_pattern_mismatch')
|
||||||
|
|
||||||
|
|
||||||
class FrontPortTemplateCreateForm(ComponentCreateForm):
|
class DeviceTypeComponentCreateForm(ComponentCreateForm):
|
||||||
|
device_type = DynamicModelChoiceField(
|
||||||
|
queryset=DeviceType.objects.all(),
|
||||||
|
)
|
||||||
|
field_order = ('device_type', 'name_pattern', 'label_pattern')
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceComponentCreateForm(ComponentCreateForm):
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all()
|
||||||
|
)
|
||||||
|
field_order = ('device', 'name_pattern', 'label_pattern')
|
||||||
|
|
||||||
|
|
||||||
|
class FrontPortTemplateCreateForm(DeviceTypeComponentCreateForm):
|
||||||
rear_port_set = forms.MultipleChoiceField(
|
rear_port_set = forms.MultipleChoiceField(
|
||||||
choices=[],
|
choices=[],
|
||||||
label='Rear ports',
|
label='Rear ports',
|
||||||
help_text='Select one rear port assignment for each front port being created.',
|
help_text='Select one rear port assignment for each front port being created.',
|
||||||
)
|
)
|
||||||
field_order = (
|
field_order = (
|
||||||
'name_pattern', 'label_pattern', 'rear_port_set',
|
'device_type', 'name_pattern', 'label_pattern', 'rear_port_set',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -88,14 +103,14 @@ class FrontPortTemplateCreateForm(ComponentCreateForm):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FrontPortCreateForm(ComponentCreateForm):
|
class FrontPortCreateForm(DeviceComponentCreateForm):
|
||||||
rear_port_set = forms.MultipleChoiceField(
|
rear_port_set = forms.MultipleChoiceField(
|
||||||
choices=[],
|
choices=[],
|
||||||
label='Rear ports',
|
label='Rear ports',
|
||||||
help_text='Select one rear port assignment for each front port being created.',
|
help_text='Select one rear port assignment for each front port being created.',
|
||||||
)
|
)
|
||||||
field_order = (
|
field_order = (
|
||||||
'name_pattern', 'label_pattern', 'rear_port_set',
|
'device', 'name_pattern', 'label_pattern', 'rear_port_set',
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from dcim.choices import DeviceFaceChoices, DeviceStatusChoices, InterfaceTypeChoices
|
from dcim.choices import DeviceFaceChoices, DeviceStatusChoices
|
||||||
from dcim.forms import *
|
from dcim.forms import *
|
||||||
from dcim.models import *
|
from dcim.models import *
|
||||||
|
from utilities.testing import create_test_device
|
||||||
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
from virtualization.models import Cluster, ClusterGroup, ClusterType
|
||||||
|
|
||||||
|
|
||||||
@ -118,15 +119,20 @@ class DeviceTestCase(TestCase):
|
|||||||
|
|
||||||
class LabelTestCase(TestCase):
|
class LabelTestCase(TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.device = create_test_device('Device 1')
|
||||||
|
|
||||||
def test_interface_label_count_valid(self):
|
def test_interface_label_count_valid(self):
|
||||||
"""
|
"""
|
||||||
Test that generating an equal number of names and labels passes form validation.
|
Test that generating an equal number of names and labels passes form validation.
|
||||||
"""
|
"""
|
||||||
interface_data = {
|
interface_data = {
|
||||||
|
'device': self.device.pk,
|
||||||
'name_pattern': 'eth[0-9]',
|
'name_pattern': 'eth[0-9]',
|
||||||
'label_pattern': 'Interface[0-9]',
|
'label_pattern': 'Interface[0-9]',
|
||||||
}
|
}
|
||||||
form = ComponentCreateForm(interface_data)
|
form = DeviceComponentCreateForm(interface_data)
|
||||||
|
|
||||||
self.assertTrue(form.is_valid())
|
self.assertTrue(form.is_valid())
|
||||||
|
|
||||||
@ -135,10 +141,11 @@ class LabelTestCase(TestCase):
|
|||||||
Check that attempting to generate a differing number of names and labels results in a validation error.
|
Check that attempting to generate a differing number of names and labels results in a validation error.
|
||||||
"""
|
"""
|
||||||
bad_interface_data = {
|
bad_interface_data = {
|
||||||
|
'device': self.device.pk,
|
||||||
'name_pattern': 'eth[0-9]',
|
'name_pattern': 'eth[0-9]',
|
||||||
'label_pattern': 'Interface[0-1]',
|
'label_pattern': 'Interface[0-1]',
|
||||||
}
|
}
|
||||||
form = ComponentCreateForm(bad_interface_data)
|
form = DeviceComponentCreateForm(bad_interface_data)
|
||||||
|
|
||||||
self.assertFalse(form.is_valid())
|
self.assertFalse(form.is_valid())
|
||||||
self.assertIn('label_pattern', form.errors)
|
self.assertIn('label_pattern', form.errors)
|
||||||
|
@ -1054,6 +1054,7 @@ class ModuleTypeBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class ConsolePortTemplateCreateView(generic.ComponentCreateView):
|
class ConsolePortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsolePortTemplate.objects.all()
|
queryset = ConsolePortTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.ConsolePortTemplateForm
|
model_form = forms.ConsolePortTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1087,6 +1088,7 @@ class ConsolePortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView):
|
class ConsoleServerPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsoleServerPortTemplate.objects.all()
|
queryset = ConsoleServerPortTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.ConsoleServerPortTemplateForm
|
model_form = forms.ConsoleServerPortTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1120,6 +1122,7 @@ class ConsoleServerPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class PowerPortTemplateCreateView(generic.ComponentCreateView):
|
class PowerPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerPortTemplate.objects.all()
|
queryset = PowerPortTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.PowerPortTemplateForm
|
model_form = forms.PowerPortTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1153,6 +1156,7 @@ class PowerPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class PowerOutletTemplateCreateView(generic.ComponentCreateView):
|
class PowerOutletTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerOutletTemplate.objects.all()
|
queryset = PowerOutletTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.PowerOutletTemplateForm
|
model_form = forms.PowerOutletTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1186,6 +1190,7 @@ class PowerOutletTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class InterfaceTemplateCreateView(generic.ComponentCreateView):
|
class InterfaceTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = InterfaceTemplate.objects.all()
|
queryset = InterfaceTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.InterfaceTemplateForm
|
model_form = forms.InterfaceTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1261,6 +1266,7 @@ class FrontPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class RearPortTemplateCreateView(generic.ComponentCreateView):
|
class RearPortTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = RearPortTemplate.objects.all()
|
queryset = RearPortTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.RearPortTemplateForm
|
model_form = forms.RearPortTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1294,6 +1300,7 @@ class RearPortTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class ModuleBayTemplateCreateView(generic.ComponentCreateView):
|
class ModuleBayTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = ModuleBayTemplate.objects.all()
|
queryset = ModuleBayTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.ModuleBayTemplateForm
|
model_form = forms.ModuleBayTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1327,6 +1334,7 @@ class ModuleBayTemplateBulkDeleteView(generic.BulkDeleteView):
|
|||||||
|
|
||||||
class DeviceBayTemplateCreateView(generic.ComponentCreateView):
|
class DeviceBayTemplateCreateView(generic.ComponentCreateView):
|
||||||
queryset = DeviceBayTemplate.objects.all()
|
queryset = DeviceBayTemplate.objects.all()
|
||||||
|
form = forms.DeviceTypeComponentCreateForm
|
||||||
model_form = forms.DeviceBayTemplateForm
|
model_form = forms.DeviceBayTemplateForm
|
||||||
|
|
||||||
|
|
||||||
@ -1741,6 +1749,7 @@ class ConsolePortView(generic.ObjectView):
|
|||||||
|
|
||||||
class ConsolePortCreateView(generic.ComponentCreateView):
|
class ConsolePortCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsolePort.objects.all()
|
queryset = ConsolePort.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.ConsolePortForm
|
model_form = forms.ConsolePortForm
|
||||||
|
|
||||||
|
|
||||||
@ -1799,6 +1808,7 @@ class ConsoleServerPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class ConsoleServerPortCreateView(generic.ComponentCreateView):
|
class ConsoleServerPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = ConsoleServerPort.objects.all()
|
queryset = ConsoleServerPort.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.ConsoleServerPortForm
|
model_form = forms.ConsoleServerPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -1857,6 +1867,7 @@ class PowerPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class PowerPortCreateView(generic.ComponentCreateView):
|
class PowerPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerPort.objects.all()
|
queryset = PowerPort.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.PowerPortForm
|
model_form = forms.PowerPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -1915,6 +1926,7 @@ class PowerOutletView(generic.ObjectView):
|
|||||||
|
|
||||||
class PowerOutletCreateView(generic.ComponentCreateView):
|
class PowerOutletCreateView(generic.ComponentCreateView):
|
||||||
queryset = PowerOutlet.objects.all()
|
queryset = PowerOutlet.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.PowerOutletForm
|
model_form = forms.PowerOutletForm
|
||||||
|
|
||||||
|
|
||||||
@ -2008,6 +2020,7 @@ class InterfaceView(generic.ObjectView):
|
|||||||
|
|
||||||
class InterfaceCreateView(generic.ComponentCreateView):
|
class InterfaceCreateView(generic.ComponentCreateView):
|
||||||
queryset = Interface.objects.all()
|
queryset = Interface.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.InterfaceForm
|
model_form = forms.InterfaceForm
|
||||||
# template_name = 'dcim/interface_create.html'
|
# template_name = 'dcim/interface_create.html'
|
||||||
|
|
||||||
@ -2161,6 +2174,7 @@ class RearPortView(generic.ObjectView):
|
|||||||
|
|
||||||
class RearPortCreateView(generic.ComponentCreateView):
|
class RearPortCreateView(generic.ComponentCreateView):
|
||||||
queryset = RearPort.objects.all()
|
queryset = RearPort.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.RearPortForm
|
model_form = forms.RearPortForm
|
||||||
|
|
||||||
|
|
||||||
@ -2219,6 +2233,7 @@ class ModuleBayView(generic.ObjectView):
|
|||||||
|
|
||||||
class ModuleBayCreateView(generic.ComponentCreateView):
|
class ModuleBayCreateView(generic.ComponentCreateView):
|
||||||
queryset = ModuleBay.objects.all()
|
queryset = ModuleBay.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.ModuleBayForm
|
model_form = forms.ModuleBayForm
|
||||||
|
|
||||||
|
|
||||||
@ -2273,6 +2288,7 @@ class DeviceBayView(generic.ObjectView):
|
|||||||
|
|
||||||
class DeviceBayCreateView(generic.ComponentCreateView):
|
class DeviceBayCreateView(generic.ComponentCreateView):
|
||||||
queryset = DeviceBay.objects.all()
|
queryset = DeviceBay.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.DeviceBayForm
|
model_form = forms.DeviceBayForm
|
||||||
|
|
||||||
|
|
||||||
@ -2398,6 +2414,7 @@ class InventoryItemEditView(generic.ObjectEditView):
|
|||||||
|
|
||||||
class InventoryItemCreateView(generic.ComponentCreateView):
|
class InventoryItemCreateView(generic.ComponentCreateView):
|
||||||
queryset = InventoryItem.objects.all()
|
queryset = InventoryItem.objects.all()
|
||||||
|
form = forms.DeviceComponentCreateForm
|
||||||
model_form = forms.InventoryItemForm
|
model_form = forms.InventoryItemForm
|
||||||
template_name = 'dcim/inventoryitem_create.html'
|
template_name = 'dcim/inventoryitem_create.html'
|
||||||
|
|
||||||
|
@ -681,7 +681,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|||||||
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
||||||
"""
|
"""
|
||||||
queryset = None
|
queryset = None
|
||||||
form = ComponentCreateForm
|
form = None
|
||||||
model_form = None
|
model_form = None
|
||||||
template_name = 'dcim/component_create.html'
|
template_name = 'dcim/component_create.html'
|
||||||
patterned_fields = ('name', 'label')
|
patterned_fields = ('name', 'label')
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
from utilities.forms import BootstrapMixin, ExpandableNameField
|
from utilities.forms import BootstrapMixin, DynamicModelChoiceField, ExpandableNameField
|
||||||
|
from .models import VirtualMachine
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'VMInterfaceCreateForm',
|
'VMInterfaceCreateForm',
|
||||||
@ -8,6 +9,9 @@ __all__ = (
|
|||||||
|
|
||||||
|
|
||||||
class VMInterfaceCreateForm(BootstrapMixin, forms.Form):
|
class VMInterfaceCreateForm(BootstrapMixin, forms.Form):
|
||||||
|
virtual_machine = DynamicModelChoiceField(
|
||||||
|
queryset=VirtualMachine.objects.all()
|
||||||
|
)
|
||||||
name_pattern = ExpandableNameField(
|
name_pattern = ExpandableNameField(
|
||||||
label='Name'
|
label='Name'
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user