Moves common Module form clean logic to new class

This commit is contained in:
sleepinggenius2 2022-06-17 18:09:23 -04:00 committed by jeremystretch
parent 33ac713470
commit 40de5dd846
3 changed files with 62 additions and 127 deletions

View File

@ -13,6 +13,7 @@ from tenancy.models import Tenant
from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField, SlugField from utilities.forms import CSVChoiceField, CSVContentTypeField, CSVModelChoiceField, CSVTypedChoiceField, SlugField
from virtualization.models import Cluster from virtualization.models import Cluster
from wireless.choices import WirelessRoleChoices from wireless.choices import WirelessRoleChoices
from .common import ModuleCommonForm
__all__ = ( __all__ = (
'CableCSVForm', 'CableCSVForm',
@ -407,7 +408,7 @@ class DeviceCSVForm(BaseDeviceCSVForm):
self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params) self.fields['rack'].queryset = self.fields['rack'].queryset.filter(**params)
class ModuleCSVForm(NetBoxModelCSVForm): class ModuleCSVForm(ModuleCommonForm, NetBoxModelCSVForm):
device = CSVModelChoiceField( device = CSVModelChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
to_field_name='name' to_field_name='name'
@ -444,17 +445,6 @@ class ModuleCSVForm(NetBoxModelCSVForm):
params = {f"device__{self.fields['device'].to_field_name}": data.get('device')} params = {f"device__{self.fields['device'].to_field_name}": data.get('device')}
self.fields['module_bay'].queryset = self.fields['module_bay'].queryset.filter(**params) self.fields['module_bay'].queryset = self.fields['module_bay'].queryset.filter(**params)
def save(self, *args, **kwargs):
# If replicate_components is False, disable automatic component replication on the instance
if not self.cleaned_data['replicate_components']:
self.instance._disable_replication = True
if self.cleaned_data['adopt_components']:
self.instance._adopt_components = True
return super().save(*args, **kwargs)
def clean_replicate_components(self): def clean_replicate_components(self):
# Make sure replicate_components is True when it's not included in the uploaded data # Make sure replicate_components is True when it's not included in the uploaded data
if 'replicate_components' not in self.data: if 'replicate_components' not in self.data:
@ -462,57 +452,6 @@ class ModuleCSVForm(NetBoxModelCSVForm):
else: else:
return self.cleaned_data['replicate_components'] return self.cleaned_data['replicate_components']
def clean(self):
super().clean()
replicate_components = self.cleaned_data.get("replicate_components")
adopt_components = self.cleaned_data.get("adopt_components")
device = self.cleaned_data['device']
module_type = self.cleaned_data['module_type']
module_bay = self.cleaned_data['module_bay']
# Bail out if we are not installing a new module or if we are not replicating components
if not replicate_components:
return
for templates, component_attribute in [
("consoleporttemplates", "consoleports"),
("consoleserverporttemplates", "consoleserverports"),
("interfacetemplates", "interfaces"),
("powerporttemplates", "powerports"),
("poweroutlettemplates", "poweroutlets"),
("rearporttemplates", "rearports"),
("frontporttemplates", "frontports")
]:
# Prefetch installed components
installed_components = {
component.name: component for component in getattr(device, component_attribute).all()
}
# Get the templates for the module type.
for template in getattr(module_type, templates).all():
# Installing modules with placeholders require that the bay has a position value
if MODULE_TOKEN in template.name and not module_bay.position:
raise forms.ValidationError(
"Cannot install module with placeholder values in a module bay with no position defined"
)
resolved_name = template.name.replace(MODULE_TOKEN, module_bay.position)
existing_item = installed_components.get(resolved_name)
# It is not possible to adopt components already belonging to a module
if adopt_components and existing_item and existing_item.module:
raise forms.ValidationError(
f"Cannot adopt {template.component_model.__name__} '{resolved_name}' as it already belongs "
f"to a module"
)
# If we are not adopting components we error if the component exists
if not adopt_components and resolved_name in installed_components:
raise forms.ValidationError(
f"{template.component_model.__name__} - {resolved_name} already exists"
)
class ChildDeviceCSVForm(BaseDeviceCSVForm): class ChildDeviceCSVForm(BaseDeviceCSVForm):
parent = CSVModelChoiceField( parent = CSVModelChoiceField(

View File

@ -5,6 +5,7 @@ from dcim.constants import *
__all__ = ( __all__ = (
'InterfaceCommonForm', 'InterfaceCommonForm',
'ModuleCommonForm'
) )
@ -47,3 +48,60 @@ class InterfaceCommonForm(forms.Form):
'tagged_vlans': f"The tagged VLANs ({', '.join(invalid_vlans)}) must belong to the same site as " 'tagged_vlans': f"The tagged VLANs ({', '.join(invalid_vlans)}) must belong to the same site as "
f"the interface's parent device/VM, or they must be global" f"the interface's parent device/VM, or they must be global"
}) })
class ModuleCommonForm(forms.Form):
def clean(self):
super().clean()
replicate_components = self.cleaned_data.get("replicate_components")
adopt_components = self.cleaned_data.get("adopt_components")
device = self.cleaned_data['device']
module_type = self.cleaned_data['module_type']
module_bay = self.cleaned_data['module_bay']
if adopt_components:
self.instance._adopt_components = True
# Bail out if we are not installing a new module or if we are not replicating components
if self.instance.pk or not replicate_components:
self.instance._disable_replication = True
return
for templates, component_attribute in [
("consoleporttemplates", "consoleports"),
("consoleserverporttemplates", "consoleserverports"),
("interfacetemplates", "interfaces"),
("powerporttemplates", "powerports"),
("poweroutlettemplates", "poweroutlets"),
("rearporttemplates", "rearports"),
("frontporttemplates", "frontports")
]:
# Prefetch installed components
installed_components = {
component.name: component for component in getattr(device, component_attribute).all()
}
# Get the templates for the module type.
for template in getattr(module_type, templates).all():
# Installing modules with placeholders require that the bay has a position value
if MODULE_TOKEN in template.name and not module_bay.position:
raise forms.ValidationError(
"Cannot install module with placeholder values in a module bay with no position defined"
)
resolved_name = template.name.replace(MODULE_TOKEN, module_bay.position)
existing_item = installed_components.get(resolved_name)
# It is not possible to adopt components already belonging to a module
if adopt_components and existing_item and existing_item.module:
raise forms.ValidationError(
f"Cannot adopt {template.component_model.__name__} '{resolved_name}' as it already belongs "
f"to a module"
)
# If we are not adopting components we error if the component exists
if not adopt_components and resolved_name in installed_components:
raise forms.ValidationError(
f"{template.component_model.__name__} - {resolved_name} already exists"
)

View File

@ -17,7 +17,7 @@ from utilities.forms import (
) )
from virtualization.models import Cluster, ClusterGroup from virtualization.models import Cluster, ClusterGroup
from wireless.models import WirelessLAN, WirelessLANGroup from wireless.models import WirelessLAN, WirelessLANGroup
from .common import InterfaceCommonForm from .common import InterfaceCommonForm, ModuleCommonForm
__all__ = ( __all__ = (
'CableForm', 'CableForm',
@ -657,7 +657,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
self.fields['position'].widget.choices = [(position, f'U{position}')] self.fields['position'].widget.choices = [(position, f'U{position}')]
class ModuleForm(NetBoxModelForm): class ModuleForm(ModuleCommonForm, NetBoxModelForm):
device = DynamicModelChoiceField( device = DynamicModelChoiceField(
queryset=Device.objects.all(), queryset=Device.objects.all(),
initial_params={ initial_params={
@ -722,68 +722,6 @@ class ModuleForm(NetBoxModelForm):
self.fields['adopt_components'].initial = False self.fields['adopt_components'].initial = False
self.fields['adopt_components'].disabled = True self.fields['adopt_components'].disabled = True
def save(self, *args, **kwargs):
# If replicate_components is False, disable automatic component replication on the instance
if self.instance.pk or not self.cleaned_data['replicate_components']:
self.instance._disable_replication = True
if self.cleaned_data['adopt_components']:
self.instance._adopt_components = True
return super().save(*args, **kwargs)
def clean(self):
super().clean()
replicate_components = self.cleaned_data.get("replicate_components")
adopt_components = self.cleaned_data.get("adopt_components")
device = self.cleaned_data['device']
module_type = self.cleaned_data['module_type']
module_bay = self.cleaned_data['module_bay']
# Bail out if we are not installing a new module or if we are not replicating components
if self.instance.pk or not replicate_components:
return
for templates, component_attribute in [
("consoleporttemplates", "consoleports"),
("consoleserverporttemplates", "consoleserverports"),
("interfacetemplates", "interfaces"),
("powerporttemplates", "powerports"),
("poweroutlettemplates", "poweroutlets"),
("rearporttemplates", "rearports"),
("frontporttemplates", "frontports")
]:
# Prefetch installed components
installed_components = {
component.name: component for component in getattr(device, component_attribute).all()
}
# Get the templates for the module type.
for template in getattr(module_type, templates).all():
# Installing modules with placeholders require that the bay has a position value
if MODULE_TOKEN in template.name and not module_bay.position:
raise forms.ValidationError(
"Cannot install module with placeholder values in a module bay with no position defined"
)
resolved_name = template.name.replace(MODULE_TOKEN, module_bay.position)
existing_item = installed_components.get(resolved_name)
# It is not possible to adopt components already belonging to a module
if adopt_components and existing_item and existing_item.module:
raise forms.ValidationError(
f"Cannot adopt {template.component_model.__name__} '{resolved_name}' as it already belongs "
f"to a module"
)
# If we are not adopting components we error if the component exists
if not adopt_components and resolved_name in installed_components:
raise forms.ValidationError(
f"{template.component_model.__name__} - {resolved_name} already exists"
)
class CableForm(TenancyForm, NetBoxModelForm): class CableForm(TenancyForm, NetBoxModelForm):