diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py index eb41af0eb..68258aa8b 100644 --- a/netbox/dcim/forms/bulk_import.py +++ b/netbox/dcim/forms/bulk_import.py @@ -1075,12 +1075,6 @@ class FrontPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): queryset=Device.objects.all(), to_field_name='name' ) - rear_port = CSVModelChoiceField( - label=_('Rear port'), - queryset=RearPort.objects.all(), - to_field_name='name', - help_text=_('Corresponding rear port') - ) type = CSVChoiceField( label=_('Type'), choices=PortTypeChoices, @@ -1093,28 +1087,6 @@ class FrontPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): 'device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'owner', 'tags' ) - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Limit RearPort choices to those belonging to this device (or VC master) - if self.is_bound and 'device' in self.data: - try: - device = self.fields['device'].to_python(self.data['device']) - except forms.ValidationError: - device = None - else: - try: - device = self.instance.device - except Device.DoesNotExist: - device = None - - if device: - self.fields['rear_port'].queryset = RearPort.objects.filter( - device__in=[device, device.get_vc_master()] - ) - else: - self.fields['rear_port'].queryset = RearPort.objects.none() - class RearPortImportForm(OwnerCSVMixin, NetBoxModelImportForm): device = CSVModelChoiceField( diff --git a/netbox/dcim/tests/test_forms.py b/netbox/dcim/tests/test_forms.py index fa654f789..a911cbf25 100644 --- a/netbox/dcim/tests/test_forms.py +++ b/netbox/dcim/tests/test_forms.py @@ -193,7 +193,8 @@ class FrontPortTestCase(TestCase): 'name': 'FrontPort[1-4]', 'label': 'Port[1-4]', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': [f'{rear_port.pk}:1' for rear_port in self.rear_ports], + 'positions': 1, + 'rear_ports': [f'{rear_port.pk}:1' for rear_port in self.rear_ports], } form = FrontPortCreateForm(front_port_data) @@ -208,7 +209,8 @@ class FrontPortTestCase(TestCase): 'name': 'FrontPort[1-4]', 'label': 'Port[1-2]', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': [f'{rear_port.pk}:1' for rear_port in self.rear_ports], + 'positions': 1, + 'rear_ports': [f'{rear_port.pk}:1' for rear_port in self.rear_ports], } form = FrontPortCreateForm(bad_front_port_data) diff --git a/netbox/dcim/tests/test_models.py b/netbox/dcim/tests/test_models.py index 877af600b..dabd076d9 100644 --- a/netbox/dcim/tests/test_models.py +++ b/netbox/dcim/tests/test_models.py @@ -444,13 +444,18 @@ class DeviceTestCase(TestCase): ) rearport.save() - FrontPortTemplate( + frontport = FrontPortTemplate( device_type=device_type, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, + ) + frontport.save() + + PortAssignmentTemplate.objects.create( + front_port=frontport, rear_port=rearport, - rear_port_position=2 - ).save() + rear_port_position=2, + ) ModuleBayTemplate( device_type=device_type, @@ -528,8 +533,7 @@ class DeviceTestCase(TestCase): device=device, name='Front Port 1', type=PortTypeChoices.TYPE_8P8C, - rear_port=rearport, - rear_port_position=2 + positions=1 ) self.assertEqual(frontport.cf['cf1'], 'foo') @@ -835,12 +839,18 @@ class CableTestCase(TestCase): ) RearPort.objects.bulk_create(rear_ports) front_ports = ( - FrontPort(device=patch_panel, name='FP1', type='8p8c', rear_port=rear_ports[0], rear_port_position=1), - FrontPort(device=patch_panel, name='FP2', type='8p8c', rear_port=rear_ports[1], rear_port_position=1), - FrontPort(device=patch_panel, name='FP3', type='8p8c', rear_port=rear_ports[2], rear_port_position=1), - FrontPort(device=patch_panel, name='FP4', type='8p8c', rear_port=rear_ports[3], rear_port_position=1), + FrontPort(device=patch_panel, name='FP1', type='8p8c'), + FrontPort(device=patch_panel, name='FP2', type='8p8c'), + FrontPort(device=patch_panel, name='FP3', type='8p8c'), + FrontPort(device=patch_panel, name='FP4', type='8p8c'), ) FrontPort.objects.bulk_create(front_ports) + PortAssignment.objects.bulk_create([ + PortAssignment(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignment(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignment(front_port=front_ports[2], rear_port=rear_ports[2]), + PortAssignment(front_port=front_ports[3], rear_port=rear_ports[3]), + ]) provider = Provider.objects.create(name='Provider 1', slug='provider-1') provider_network = ProviderNetwork.objects.create(name='Provider Network 1', provider=provider) diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 6a34df652..3a0dc3ca2 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -741,17 +741,16 @@ class DeviceTypeTestCase( ) RearPortTemplate.objects.bulk_create(rear_ports) front_ports = ( - FrontPortTemplate( - device_type=devicetype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1 - ), - FrontPortTemplate( - device_type=devicetype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1 - ), - FrontPortTemplate( - device_type=devicetype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1 - ), + FrontPortTemplate(device_type=devicetype, name='Front Port 1'), + FrontPortTemplate(device_type=devicetype, name='Front Port 2'), + FrontPortTemplate(device_type=devicetype, name='Front Port 3'), ) FrontPortTemplate.objects.bulk_create(front_ports) + PortAssignmentTemplate.objects.bulk_create([ + PortAssignmentTemplate(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignmentTemplate(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignmentTemplate(front_port=front_ports[2], rear_port=rear_ports[2]), + ]) url = reverse('dcim:devicetype_frontports', kwargs={'pk': devicetype.pk}) self.assertHttpStatus(self.client.get(url), 200) @@ -971,8 +970,6 @@ inventory-items: self.assertEqual(device_type.frontporttemplates.count(), 3) fp1 = FrontPortTemplate.objects.first() self.assertEqual(fp1.name, 'Front Port 1') - self.assertEqual(fp1.rear_port, rp1) - self.assertEqual(fp1.rear_port_position, 1) self.assertEqual(device_type.modulebaytemplates.count(), 3) mb1 = ModuleBayTemplate.objects.first() @@ -1316,17 +1313,16 @@ class ModuleTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase): ) RearPortTemplate.objects.bulk_create(rear_ports) front_ports = ( - FrontPortTemplate( - module_type=moduletype, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1 - ), - FrontPortTemplate( - module_type=moduletype, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1 - ), - FrontPortTemplate( - module_type=moduletype, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1 - ), + FrontPortTemplate(module_type=moduletype, name='Front Port 1'), + FrontPortTemplate(module_type=moduletype, name='Front Port 2'), + FrontPortTemplate(module_type=moduletype, name='Front Port 3'), ) FrontPortTemplate.objects.bulk_create(front_ports) + PortAssignmentTemplate.objects.bulk_create([ + PortAssignmentTemplate(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignmentTemplate(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignmentTemplate(front_port=front_ports[2], rear_port=rear_ports[2]), + ]) url = reverse('dcim:moduletype_frontports', kwargs={'pk': moduletype.pk}) self.assertHttpStatus(self.client.get(url), 200) @@ -1394,13 +1390,10 @@ rear-ports: front-ports: - name: Front Port 1 type: 8p8c - rear_port: Rear Port 1 - name: Front Port 2 type: 8p8c - rear_port: Rear Port 2 - name: Front Port 3 type: 8p8c - rear_port: Rear Port 3 module-bays: - name: Module Bay 1 position: 1 @@ -1477,8 +1470,6 @@ module-bays: self.assertEqual(module_type.frontporttemplates.count(), 3) fp1 = FrontPortTemplate.objects.first() self.assertEqual(fp1.name, 'Front Port 1') - self.assertEqual(fp1.rear_port, rp1) - self.assertEqual(fp1.rear_port_position, 1) self.assertEqual(module_type.modulebaytemplates.count(), 3) mb1 = ModuleBayTemplate.objects.first() @@ -1770,7 +1761,7 @@ class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas manufacturer = Manufacturer.objects.create(name='Manufacturer 1', slug='manufacturer-1') devicetype = DeviceType.objects.create(manufacturer=manufacturer, model='Device Type 1', slug='device-type-1') - rearports = ( + rear_ports = ( RearPortTemplate(device_type=devicetype, name='Rear Port Template 1'), RearPortTemplate(device_type=devicetype, name='Rear Port Template 2'), RearPortTemplate(device_type=devicetype, name='Rear Port Template 3'), @@ -1778,35 +1769,33 @@ class FrontPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas RearPortTemplate(device_type=devicetype, name='Rear Port Template 5'), RearPortTemplate(device_type=devicetype, name='Rear Port Template 6'), ) - RearPortTemplate.objects.bulk_create(rearports) - - FrontPortTemplate.objects.bulk_create( - ( - FrontPortTemplate( - device_type=devicetype, name='Front Port Template 1', rear_port=rearports[0], rear_port_position=1 - ), - FrontPortTemplate( - device_type=devicetype, name='Front Port Template 2', rear_port=rearports[1], rear_port_position=1 - ), - FrontPortTemplate( - device_type=devicetype, name='Front Port Template 3', rear_port=rearports[2], rear_port_position=1 - ), - ) + RearPortTemplate.objects.bulk_create(rear_ports) + front_ports = ( + FrontPortTemplate(device_type=devicetype, name='Front Port Template 1'), + FrontPortTemplate(device_type=devicetype, name='Front Port Template 2'), + FrontPortTemplate(device_type=devicetype, name='Front Port Template 3'), ) + FrontPortTemplate.objects.bulk_create(front_ports) + PortAssignmentTemplate.objects.bulk_create([ + PortAssignmentTemplate(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignmentTemplate(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignmentTemplate(front_port=front_ports[2], rear_port=rear_ports[2]), + ]) cls.form_data = { 'device_type': devicetype.pk, 'name': 'Front Port X', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rearports[3].pk, - 'rear_port_position': 1, + 'positions': 1, + 'rear_ports': [f'{rear_ports[3].pk}:1'], } cls.bulk_create_data = { 'device_type': devicetype.pk, 'name': 'Front Port [4-6]', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': [f'{rp.pk}:1' for rp in rearports[3:6]], + 'positions': 1, + 'rear_ports': [f'{rp.pk}:1' for rp in rear_ports[3:6]], } cls.bulk_edit_data = { @@ -2276,11 +2265,16 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase): ) RearPort.objects.bulk_create(rear_ports) front_ports = ( - FrontPort(device=device, name='Front Port 1', rear_port=rear_ports[0], rear_port_position=1), - FrontPort(device=device, name='Front Port 2', rear_port=rear_ports[1], rear_port_position=1), - FrontPort(device=device, name='Front Port 3', rear_port=rear_ports[2], rear_port_position=1), + FrontPort(device=device, name='Front Port Template 1'), + FrontPort(device=device, name='Front Port Template 2'), + FrontPort(device=device, name='Front Port Template 3'), ) FrontPort.objects.bulk_create(front_ports) + PortAssignment.objects.bulk_create([ + PortAssignment(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignment(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignment(front_port=front_ports[2], rear_port=rear_ports[2]), + ]) url = reverse('dcim:device_frontports', kwargs={'pk': device.pk}) self.assertHttpStatus(self.client.get(url), 200) @@ -3065,7 +3059,7 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): def setUpTestData(cls): device = create_test_device('Device 1') - rearports = ( + rear_ports = ( RearPort(device=device, name='Rear Port 1'), RearPort(device=device, name='Rear Port 2'), RearPort(device=device, name='Rear Port 3'), @@ -3073,14 +3067,19 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): RearPort(device=device, name='Rear Port 5'), RearPort(device=device, name='Rear Port 6'), ) - RearPort.objects.bulk_create(rearports) + RearPort.objects.bulk_create(rear_ports) front_ports = ( - FrontPort(device=device, name='Front Port 1', rear_port=rearports[0]), - FrontPort(device=device, name='Front Port 2', rear_port=rearports[1]), - FrontPort(device=device, name='Front Port 3', rear_port=rearports[2]), + FrontPort(device=device, name='Front Port 1'), + FrontPort(device=device, name='Front Port 2'), + FrontPort(device=device, name='Front Port 3'), ) FrontPort.objects.bulk_create(front_ports) + PortAssignment.objects.bulk_create([ + PortAssignment(front_port=front_ports[0], rear_port=rear_ports[0]), + PortAssignment(front_port=front_ports[1], rear_port=rear_ports[1]), + PortAssignment(front_port=front_ports[2], rear_port=rear_ports[2]), + ]) tags = create_tags('Alpha', 'Bravo', 'Charlie') @@ -3088,8 +3087,8 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 'device': device.pk, 'name': 'Front Port X', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': rearports[3].pk, - 'rear_port_position': 1, + 'positions': 1, + 'rear_ports': [f'{rear_ports[3].pk}:1'], 'description': 'New description', 'tags': [t.pk for t in tags], } @@ -3098,7 +3097,8 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): 'device': device.pk, 'name': 'Front Port [4-6]', 'type': PortTypeChoices.TYPE_8P8C, - 'rear_port': [f'{rp.pk}:1' for rp in rearports[3:6]], + 'positions': 1, + 'rear_ports': [f'{rp.pk}:1' for rp in rear_ports[3:6]], 'description': 'New description', 'tags': [t.pk for t in tags], } @@ -3109,10 +3109,10 @@ class FrontPortTestCase(ViewTestCases.DeviceComponentViewTestCase): } cls.csv_data = ( - "device,name,type,rear_port,rear_port_position", - "Device 1,Front Port 4,8p8c,Rear Port 4,1", - "Device 1,Front Port 5,8p8c,Rear Port 5,1", - "Device 1,Front Port 6,8p8c,Rear Port 6,1", + "device,name,type,positions", + "Device 1,Front Port 4,8p8c,1", + "Device 1,Front Port 5,8p8c,1", + "Device 1,Front Port 6,8p8c,1", ) cls.csv_update_data = (