Fix missing NestedSerializer.

This commit is contained in:
Daniel Sheppard 2022-10-28 14:52:05 -05:00
parent 04af1e12b2
commit b78eebed31
9 changed files with 56 additions and 25 deletions

View File

@ -45,6 +45,7 @@ __all__ = [
'NestedSiteSerializer',
'NestedSiteGroupSerializer',
'NestedVirtualChassisSerializer',
'NestedVirtualDeviceContextSerializer',
]
@ -466,3 +467,12 @@ class NestedPowerFeedSerializer(WritableNestedSerializer):
class Meta:
model = models.PowerFeed
fields = ['id', 'url', 'display', 'name', 'cable', '_occupied']
class NestedVirtualDeviceContextSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualdevicecontext-detail')
device = NestedDeviceSerializer()
class Meta:
model = models.VirtualDeviceContext
fields = ['id', 'url', 'display', 'name', 'identifier', 'device', 'vdc_type']

View File

@ -317,6 +317,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
)
subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, allow_blank=True, required=False)
airflow = ChoiceField(choices=DeviceAirflowChoices, allow_blank=True, required=False)
vdc_type = ChoiceField(choices=VirtualDeviceContextTypeChoices, allow_blank=True, required=False)
weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False)
device_count = serializers.IntegerField(read_only=True)
@ -324,8 +325,8 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
model = DeviceType
fields = [
'id', 'url', 'display', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
'subdevice_role', 'airflow', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
'custom_fields', 'created', 'last_updated', 'device_count',
'subdevice_role', 'vdc_type', 'airflow', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments',
'tags', 'custom_fields', 'created', 'last_updated', 'device_count',
]
@ -840,6 +841,11 @@ class PowerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
device = NestedDeviceSerializer()
vdcs = NestedVirtualDeviceContextSerializer(
required=False,
allow_null=True,
many=True
)
module = ComponentNestedModuleSerializer(
required=False,
allow_null=True
@ -876,13 +882,13 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect
class Meta:
model = Interface
fields = [
'id', 'url', 'display', 'device', 'module', 'name', 'label', 'type', 'enabled', 'parent', 'bridge', 'lag',
'mtu', 'mac_address', 'speed', 'duplex', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role', 'rf_channel',
'poe_mode', 'poe_type', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'untagged_vlan',
'tagged_vlans', 'mark_connected', 'cable', 'cable_end', 'wireless_link', 'link_peers', 'link_peers_type',
'wireless_lans', 'vrf', 'l2vpn_termination', 'connected_endpoints', 'connected_endpoints_type',
'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses',
'count_fhrp_groups', '_occupied',
'id', 'url', 'display', 'device', 'vdcs', 'module', 'name', 'label', 'type', 'enabled', 'parent', 'bridge',
'lag', 'mtu', 'mac_address', 'speed', 'duplex', 'wwn', 'mgmt_only', 'description', 'mode', 'rf_role',
'rf_channel', 'poe_mode', 'poe_type', 'rf_channel_frequency', 'rf_channel_width', 'tx_power',
'untagged_vlan', 'tagged_vlans', 'mark_connected', 'cable', 'cable_end', 'wireless_link', 'link_peers',
'link_peers_type', 'wireless_lans', 'vrf', 'l2vpn_termination', 'connected_endpoints',
'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created',
'last_updated', 'count_ipaddresses', 'count_fhrp_groups', '_occupied',
]
def validate(self, data):

View File

@ -397,7 +397,7 @@ class DeviceTypeForm(NetBoxModelForm):
model = DeviceType
fields = [
'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'subdevice_role', 'airflow',
'vdc_type', 'vdc_type', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
'vdc_type', 'weight', 'weight_unit', 'front_image', 'rear_image', 'comments', 'tags',
]
widgets = {
'airflow': StaticSelect(),
@ -1375,7 +1375,7 @@ class PowerOutletForm(ModularDeviceComponentForm):
class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
vdc = DynamicModelMultipleChoiceField(
vdcs = DynamicModelMultipleChoiceField(
queryset=VirtualDeviceContext.objects.all(),
required=False,
label='Virtual Device Contexts',
@ -1457,7 +1457,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
)
fieldsets = (
('Interface', ('device', 'module', 'vdc', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags')),
('Interface', ('device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'description', 'tags')),
('Addressing', ('vrf', 'mac_address', 'wwn')),
('Operation', ('mtu', 'tx_power', 'enabled', 'mgmt_only', 'mark_connected')),
('Related Interfaces', ('parent', 'bridge', 'lag')),
@ -1471,7 +1471,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
class Meta:
model = Interface
fields = [
'device', 'module', 'vdc', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', 'lag',
'device', 'module', 'vdcs', 'name', 'label', 'type', 'speed', 'duplex', 'enabled', 'parent', 'bridge', 'lag',
'mac_address', 'wwn', 'mtu', 'mgmt_only', 'mark_connected', 'description', 'poe_mode', 'poe_type', 'mode',
'rf_role', 'rf_channel', 'rf_channel_frequency', 'rf_channel_width', 'tx_power', 'wireless_lans',
'untagged_vlan', 'tagged_vlans', 'vrf', 'tags',
@ -1498,9 +1498,9 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
def clean_vdc(self):
device = self.cleaned_data.get('device')
if device.device_type.vdc_type not in [VirtualDeviceContextTypeChoices.CISCO_ASA_CONTEXT, VirtualDeviceContextTypeChoices.CISCO_FTD_INSTANCE]\
and len(self.cleaned_data.get('vdc')) > 1:
and len(self.cleaned_data.get('vdcs')) > 1:
raise forms.ValidationError(f"You cannot assign more then 1 VDC for {device.device_type}")
return self.cleaned_data.get('vdc')
return self.cleaned_data.get('vdcs')
class FrontPortForm(ModularDeviceComponentForm):

View File

@ -45,7 +45,7 @@ class Migration(migrations.Migration):
),
migrations.AddField(
model_name='interface',
name='vdc',
name='vdcs',
field=models.ManyToManyField(related_name='interfaces', to='dcim.virtualdevicecontext'),
),
migrations.AddConstraint(

View File

@ -531,7 +531,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
max_length=100,
blank=True
)
vdc = models.ManyToManyField(
vdcs = models.ManyToManyField(
to='dcim.VirtualDeviceContext',
related_name='interfaces'
)

View File

@ -124,17 +124,17 @@ class DeviceType(NetBoxModel, WeightMixin):
help_text='Parent devices house child devices in device bays. Leave blank '
'if this device type is neither a parent nor a child.'
)
airflow = models.CharField(
max_length=50,
choices=DeviceAirflowChoices,
blank=True
)
vdc_type = models.CharField(
max_length=50,
blank=True,
choices=VirtualDeviceContextTypeChoices,
verbose_name='VDC Type'
)
airflow = models.CharField(
max_length=50,
choices=DeviceAirflowChoices,
blank=True
)
front_image = models.ImageField(
upload_to='devicetype-images',
blank=True
@ -1217,3 +1217,7 @@ class VirtualDeviceContext(NetBoxModel):
return self.primary_ip4
else:
return None
@property
def vdc_type(self):
return self.device.device_type.vdc_type

View File

@ -127,13 +127,13 @@ def nullify_connected_endpoints(instance, **kwargs):
cablepath.retrace()
@receiver(m2m_changed, sender=Interface.vdc.through)
@receiver(m2m_changed, sender=Interface.vdcs.through)
def enforce_vdc_type_restrictions(instance, **kwargs):
if 'action' == 'post_add':
device = instance.device
if device.device_type.vdc_type not in [VirtualDeviceContextTypeChoices.CISCO_ASA_CONTEXT, VirtualDeviceContextTypeChoices.CISCO_FTD_INSTANCE] \
and len(instance.vdc) > 1:
and len(instance.vdcs) > 1:
print('Error')
raise forms.ValidationError({
'vdc': f"You cannot assign more then 1 VDC for {device.device_type}"
'vdcs': f"You cannot assign more then 1 VDC for {device.device_type}"
})

View File

@ -57,6 +57,12 @@
{{ object.get_airflow_display|placeholder }}
</td>
</tr>
<tr>
<td>VDC Type</td>
<td>
{{ object.get_vdc_type_display|placeholder }}
</td>
</tr>
<tr>
<td>Front Image</td>
<td>

View File

@ -36,6 +36,11 @@
<th scope="row">Identifier</th>
<td>{{ object.identifier|placeholder }}</td>
</tr>
</tr>
<tr>
<th scope="row">VDC Type</th>
<td>{{ object.device.device_type.get_vdc_type_display |placeholder }}</td>
</tr>
<tr>
<th scope="row">Primary IPv4</th>
<td>