Merge branch 'feature' into 7336-vlan-translation-feature

This commit is contained in:
Brian Tiemann 2024-10-21 13:58:07 -04:00
commit 38fe3d319f
23 changed files with 622 additions and 25 deletions

View File

@ -0,0 +1,43 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
Circuit = apps.get_model('circuits', 'Circuit')
CircuitGroupAssignment = apps.get_model('circuits', 'CircuitGroupAssignment')
CircuitTermination = apps.get_model('circuits', 'CircuitTermination')
Circuit.objects.filter(distance_unit='').update(distance_unit=None)
CircuitGroupAssignment.objects.filter(priority='').update(priority=None)
CircuitTermination.objects.filter(cable_end='').update(cable_end=None)
class Migration(migrations.Migration):
dependencies = [
('circuits', '0045_circuit_distance'),
]
operations = [
migrations.AlterField(
model_name='circuit',
name='distance_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='circuitgroupassignment',
name='priority',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='circuittermination',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -187,7 +187,8 @@ class CircuitGroupAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin,
verbose_name=_('priority'),
max_length=50,
choices=CircuitPriorityChoices,
blank=True
blank=True,
null=True
)
prerequisite_models = (
'circuits.Circuit',

View File

@ -0,0 +1,287 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
Cable = apps.get_model('dcim', 'Cable')
ConsolePort = apps.get_model('dcim', 'ConsolePort')
ConsolePortTemplate = apps.get_model('dcim', 'ConsolePortTemplate')
ConsoleServerPort = apps.get_model('dcim', 'ConsoleServerPort')
ConsoleServerPortTemplate = apps.get_model('dcim', 'ConsoleServerPortTemplate')
Device = apps.get_model('dcim', 'Device')
DeviceType = apps.get_model('dcim', 'DeviceType')
FrontPort = apps.get_model('dcim', 'FrontPort')
Interface = apps.get_model('dcim', 'Interface')
InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate')
ModuleType = apps.get_model('dcim', 'ModuleType')
PowerFeed = apps.get_model('dcim', 'PowerFeed')
PowerOutlet = apps.get_model('dcim', 'PowerOutlet')
PowerOutletTemplate = apps.get_model('dcim', 'PowerOutletTemplate')
PowerPort = apps.get_model('dcim', 'PowerPort')
PowerPortTemplate = apps.get_model('dcim', 'PowerPortTemplate')
Rack = apps.get_model('dcim', 'Rack')
RackType = apps.get_model('dcim', 'RackType')
RearPort = apps.get_model('dcim', 'RearPort')
Cable.objects.filter(length_unit='').update(length_unit=None)
Cable.objects.filter(type='').update(type=None)
ConsolePort.objects.filter(cable_end='').update(cable_end=None)
ConsolePort.objects.filter(type='').update(type=None)
ConsolePortTemplate.objects.filter(type='').update(type=None)
ConsoleServerPort.objects.filter(cable_end='').update(cable_end=None)
ConsoleServerPort.objects.filter(type='').update(type=None)
ConsoleServerPortTemplate.objects.filter(type='').update(type=None)
Device.objects.filter(airflow='').update(airflow=None)
Device.objects.filter(face='').update(face=None)
DeviceType.objects.filter(airflow='').update(airflow=None)
DeviceType.objects.filter(subdevice_role='').update(subdevice_role=None)
DeviceType.objects.filter(weight_unit='').update(weight_unit=None)
FrontPort.objects.filter(cable_end='').update(cable_end=None)
Interface.objects.filter(cable_end='').update(cable_end=None)
Interface.objects.filter(mode='').update(mode=None)
Interface.objects.filter(poe_mode='').update(poe_mode=None)
Interface.objects.filter(poe_type='').update(poe_type=None)
Interface.objects.filter(rf_channel='').update(rf_channel=None)
Interface.objects.filter(rf_role='').update(rf_role=None)
InterfaceTemplate.objects.filter(poe_mode='').update(poe_mode=None)
InterfaceTemplate.objects.filter(poe_type='').update(poe_type=None)
InterfaceTemplate.objects.filter(rf_role='').update(rf_role=None)
ModuleType.objects.filter(airflow='').update(airflow=None)
ModuleType.objects.filter(weight_unit='').update(weight_unit=None)
PowerFeed.objects.filter(cable_end='').update(cable_end=None)
PowerOutlet.objects.filter(cable_end='').update(cable_end=None)
PowerOutlet.objects.filter(feed_leg='').update(feed_leg=None)
PowerOutlet.objects.filter(type='').update(type=None)
PowerOutletTemplate.objects.filter(feed_leg='').update(feed_leg=None)
PowerOutletTemplate.objects.filter(type='').update(type=None)
PowerPort.objects.filter(cable_end='').update(cable_end=None)
PowerPort.objects.filter(type='').update(type=None)
PowerPortTemplate.objects.filter(type='').update(type=None)
Rack.objects.filter(airflow='').update(airflow=None)
Rack.objects.filter(form_factor='').update(form_factor=None)
Rack.objects.filter(outer_unit='').update(outer_unit=None)
Rack.objects.filter(weight_unit='').update(weight_unit=None)
RackType.objects.filter(outer_unit='').update(outer_unit=None)
RackType.objects.filter(weight_unit='').update(weight_unit=None)
RearPort.objects.filter(cable_end='').update(cable_end=None)
class Migration(migrations.Migration):
dependencies = [
('dcim', '0193_poweroutlet_color'),
]
operations = [
migrations.AlterField(
model_name='cable',
name='length_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='cable',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='consoleport',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='consoleport',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='consoleporttemplate',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='consoleserverport',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='consoleserverport',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='consoleserverporttemplate',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='device',
name='airflow',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='device',
name='face',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='devicetype',
name='airflow',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='devicetype',
name='subdevice_role',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='devicetype',
name='weight_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='frontport',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='interface',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='interface',
name='mode',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interface',
name='poe_mode',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interface',
name='poe_type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interface',
name='rf_channel',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interface',
name='rf_role',
field=models.CharField(blank=True, max_length=30, null=True),
),
migrations.AlterField(
model_name='interfacetemplate',
name='poe_mode',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interfacetemplate',
name='poe_type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='interfacetemplate',
name='rf_role',
field=models.CharField(blank=True, max_length=30, null=True),
),
migrations.AlterField(
model_name='moduletype',
name='airflow',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='moduletype',
name='weight_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='powerfeed',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='poweroutlet',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='poweroutlet',
name='feed_leg',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='poweroutlet',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='poweroutlettemplate',
name='feed_leg',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='poweroutlettemplate',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='powerport',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.AlterField(
model_name='powerport',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='powerporttemplate',
name='type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='rack',
name='airflow',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='rack',
name='form_factor',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='rack',
name='outer_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='rack',
name='weight_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='racktype',
name='outer_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='racktype',
name='weight_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='rearport',
name='cable_end',
field=models.CharField(blank=True, max_length=1, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -42,7 +42,8 @@ class Cable(PrimaryModel):
verbose_name=_('type'),
max_length=50,
choices=CableTypeChoices,
blank=True
blank=True,
null=True
)
status = models.CharField(
verbose_name=_('status'),
@ -78,6 +79,7 @@ class Cable(PrimaryModel):
max_length=50,
choices=CableLengthUnitChoices,
blank=True,
null=True
)
# Stores the normalized length (in meters) for database ordering
_abs_length = models.DecimalField(
@ -206,7 +208,7 @@ class Cable(PrimaryModel):
# Clear length_unit if no length is defined
if self.length is None:
self.length_unit = ''
self.length_unit = None
super().save(*args, **kwargs)
@ -365,7 +367,7 @@ class CableTermination(ChangeLoggedModel):
termination = self.termination._meta.model.objects.get(pk=self.termination_id)
termination.snapshot()
termination.cable = None
termination.cable_end = ''
termination.cable_end = None
termination.save()
super().delete(*args, **kwargs)

View File

@ -203,7 +203,8 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
verbose_name=_('type'),
max_length=50,
choices=ConsolePortTypeChoices,
blank=True
blank=True,
null=True
)
component_model = ConsolePort
@ -237,7 +238,8 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
verbose_name=_('type'),
max_length=50,
choices=ConsolePortTypeChoices,
blank=True
blank=True,
null=True
)
component_model = ConsoleServerPort
@ -272,7 +274,8 @@ class PowerPortTemplate(ModularComponentTemplateModel):
verbose_name=_('type'),
max_length=50,
choices=PowerPortTypeChoices,
blank=True
blank=True,
null=True
)
maximum_draw = models.PositiveIntegerField(
verbose_name=_('maximum draw'),
@ -334,7 +337,8 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
verbose_name=_('type'),
max_length=50,
choices=PowerOutletTypeChoices,
blank=True
blank=True,
null=True
)
power_port = models.ForeignKey(
to='dcim.PowerPortTemplate',
@ -348,6 +352,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
max_length=50,
choices=PowerOutletFeedLegChoices,
blank=True,
null=True,
help_text=_('Phase (for three-phase feeds)')
)
@ -434,18 +439,21 @@ class InterfaceTemplate(ModularComponentTemplateModel):
max_length=50,
choices=InterfacePoEModeChoices,
blank=True,
null=True,
verbose_name=_('PoE mode')
)
poe_type = models.CharField(
max_length=50,
choices=InterfacePoETypeChoices,
blank=True,
null=True,
verbose_name=_('PoE type')
)
rf_role = models.CharField(
max_length=30,
choices=WirelessRoleChoices,
blank=True,
null=True,
verbose_name=_('wireless role')
)

View File

@ -142,8 +142,9 @@ class CabledObjectModel(models.Model):
cable_end = models.CharField(
verbose_name=_('cable end'),
max_length=1,
choices=CableEndChoices,
blank=True,
choices=CableEndChoices
null=True
)
mark_connected = models.BooleanField(
verbose_name=_('mark connected'),
@ -283,6 +284,7 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
max_length=50,
choices=ConsolePortTypeChoices,
blank=True,
null=True,
help_text=_('Physical port type')
)
speed = models.PositiveIntegerField(
@ -309,6 +311,7 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint,
max_length=50,
choices=ConsolePortTypeChoices,
blank=True,
null=True,
help_text=_('Physical port type')
)
speed = models.PositiveIntegerField(
@ -339,6 +342,7 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracking
max_length=50,
choices=PowerPortTypeChoices,
blank=True,
null=True,
help_text=_('Physical port type')
)
maximum_draw = models.PositiveIntegerField(
@ -454,6 +458,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
max_length=50,
choices=PowerOutletTypeChoices,
blank=True,
null=True,
help_text=_('Physical port type')
)
power_port = models.ForeignKey(
@ -468,6 +473,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint, Tracki
max_length=50,
choices=PowerOutletFeedLegChoices,
blank=True,
null=True,
help_text=_('Phase (for three-phase feeds)')
)
color = ColorField(
@ -522,6 +528,7 @@ class BaseInterface(models.Model):
max_length=50,
choices=InterfaceModeChoices,
blank=True,
null=True,
help_text=_('IEEE 802.1Q tagging strategy')
)
parent = models.ForeignKey(
@ -631,12 +638,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
max_length=30,
choices=WirelessRoleChoices,
blank=True,
null=True,
verbose_name=_('wireless role')
)
rf_channel = models.CharField(
max_length=50,
choices=WirelessChannelChoices,
blank=True,
null=True,
verbose_name=_('wireless channel')
)
rf_channel_frequency = models.DecimalField(
@ -665,12 +674,14 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
max_length=50,
choices=InterfacePoEModeChoices,
blank=True,
null=True,
verbose_name=_('PoE mode')
)
poe_type = models.CharField(
max_length=50,
choices=InterfacePoETypeChoices,
blank=True,
null=True,
verbose_name=_('PoE type')
)
wireless_link = models.ForeignKey(

View File

@ -118,6 +118,7 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
max_length=50,
choices=SubdeviceRoleChoices,
blank=True,
null=True,
verbose_name=_('parent/child status'),
help_text=_('Parent devices house child devices in device bays. Leave blank '
'if this device type is neither a parent nor a child.')
@ -126,7 +127,8 @@ class DeviceType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
verbose_name=_('airflow'),
max_length=50,
choices=DeviceAirflowChoices,
blank=True
blank=True,
null=True
)
front_image = models.ImageField(
upload_to='devicetype-images',
@ -387,7 +389,8 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
verbose_name=_('airflow'),
max_length=50,
choices=ModuleAirflowChoices,
blank=True
blank=True,
null=True
)
clone_fields = ('manufacturer', 'weight', 'weight_unit', 'airflow')
@ -632,6 +635,7 @@ class Device(
face = models.CharField(
max_length=50,
blank=True,
null=True,
choices=DeviceFaceChoices,
verbose_name=_('rack face')
)
@ -645,7 +649,8 @@ class Device(
verbose_name=_('airflow'),
max_length=50,
choices=DeviceAirflowChoices,
blank=True
blank=True,
null=True
)
primary_ip4 = models.OneToOneField(
to='ipam.IPAddress',

View File

@ -83,7 +83,8 @@ class RackBase(WeightMixin, PrimaryModel):
verbose_name=_('outer unit'),
max_length=50,
choices=RackDimensionUnitChoices,
blank=True
blank=True,
null=True
)
mounting_depth = models.PositiveSmallIntegerField(
verbose_name=_('mounting depth'),
@ -188,7 +189,7 @@ class RackType(RackBase):
# Clear unit if outer width & depth are not set
if self.outer_width is None and self.outer_depth is None:
self.outer_unit = ''
self.outer_unit = None
super().save(*args, **kwargs)
@ -242,6 +243,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
choices=RackFormFactorChoices,
max_length=50,
blank=True,
null=True,
verbose_name=_('form factor')
)
rack_type = models.ForeignKey(
@ -317,7 +319,8 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
verbose_name=_('airflow'),
max_length=50,
choices=RackAirflowChoices,
blank=True
blank=True,
null=True
)
# Generic relations
@ -409,7 +412,7 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
# Clear unit if outer width & depth are not set
if self.outer_width is None and self.outer_depth is None:
self.outer_unit = ''
self.outer_unit = None
super().save(*args, **kwargs)

View File

@ -871,7 +871,6 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_outer_unit(self):
self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 5)
params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

View File

@ -592,7 +592,7 @@ class DeviceTypeTestCase(
'part_number': '123ABC',
'u_height': 2,
'is_full_depth': True,
'subdevice_role': '', # CharField
'subdevice_role': None,
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}

View File

@ -0,0 +1,29 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
CustomFieldChoiceSet = apps.get_model('extras', 'CustomFieldChoiceSet')
CustomFieldChoiceSet.objects.filter(base_choices='').update(base_choices=None)
class Migration(migrations.Migration):
dependencies = [
('extras', '0121_customfield_related_object_filter'),
]
operations = [
migrations.AlterField(
model_name='customfieldchoiceset',
name='base_choices',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -760,6 +760,7 @@ class CustomFieldChoiceSet(CloningMixin, ExportTemplatesMixin, ChangeLoggedModel
max_length=50,
choices=CustomFieldChoiceSetBaseChoices,
blank=True,
null=True,
help_text=_('Base set of predefined choices (optional)')
)
extra_choices = ArrayField(

View File

@ -0,0 +1,36 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
FHRPGroup = apps.get_model('ipam', 'FHRPGroup')
IPAddress = apps.get_model('ipam', 'IPAddress')
FHRPGroup.objects.filter(auth_type='').update(auth_type=None)
IPAddress.objects.filter(role='').update(role=None)
class Migration(migrations.Migration):
dependencies = [
('ipam', '0072_prefix_cached_relations'),
]
operations = [
migrations.AlterField(
model_name='fhrpgroup',
name='auth_type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='ipaddress',
name='role',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -34,6 +34,7 @@ class FHRPGroup(PrimaryModel):
max_length=50,
choices=FHRPGroupAuthTypeChoices,
blank=True,
null=True,
verbose_name=_('authentication type')
)
auth_key = models.CharField(

View File

@ -784,6 +784,7 @@ class IPAddress(ContactsMixin, PrimaryModel):
max_length=50,
choices=IPAddressRoleChoices,
blank=True,
null=True,
help_text=_('The functional role of this IP')
)
assigned_object_type = models.ForeignKey(

View File

@ -23,6 +23,7 @@ class WeightMixin(models.Model):
max_length=50,
choices=WeightUnitChoices,
blank=True,
null=True,
)
# Stores the normalized weight (in grams) for database ordering
_abs_weight = models.PositiveBigIntegerField(
@ -64,6 +65,7 @@ class DistanceMixin(models.Model):
max_length=50,
choices=DistanceUnitChoices,
blank=True,
null=True,
)
# Stores the normalized distance (in meters) for database ordering
_abs_distance = models.DecimalField(
@ -85,7 +87,7 @@ class DistanceMixin(models.Model):
# Clear distance_unit if no distance is defined
if self.distance is None:
self.distance_unit = ''
self.distance_unit = None
super().save(*args, **kwargs)

View File

@ -0,0 +1,29 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
ContactAssignment = apps.get_model('tenancy', 'ContactAssignment')
ContactAssignment.objects.filter(priority='').update(priority=None)
class Migration(migrations.Migration):
dependencies = [
('tenancy', '0015_contactassignment_rename_content_type'),
]
operations = [
migrations.AlterField(
model_name='contactassignment',
name='priority',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -125,7 +125,8 @@ class ContactAssignment(CustomFieldsMixin, ExportTemplatesMixin, TagsMixin, Chan
verbose_name=_('priority'),
max_length=50,
choices=ContactPriorityChoices,
blank=True
blank=True,
null=True
)
clone_fields = ('object_type', 'object_id', 'role', 'priority')

View File

@ -0,0 +1,29 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
VMInterface = apps.get_model('virtualization', 'VMInterface')
VMInterface.objects.filter(mode='').update(mode=None)
class Migration(migrations.Migration):
dependencies = [
('virtualization', '0040_convert_disk_size'),
]
operations = [
migrations.AlterField(
model_name='vminterface',
name='mode',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -0,0 +1,49 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
IKEPolicy = apps.get_model('vpn', 'IKEPolicy')
IKEProposal = apps.get_model('vpn', 'IKEProposal')
IPSecProposal = apps.get_model('vpn', 'IPSecProposal')
IKEPolicy.objects.filter(mode='').update(mode=None)
IKEProposal.objects.filter(authentication_algorithm='').update(authentication_algorithm=None)
IPSecProposal.objects.filter(authentication_algorithm='').update(authentication_algorithm=None)
IPSecProposal.objects.filter(encryption_algorithm='').update(encryption_algorithm=None)
class Migration(migrations.Migration):
dependencies = [
('vpn', '0005_rename_indexes'),
]
operations = [
migrations.AlterField(
model_name='ikepolicy',
name='mode',
field=models.CharField(blank=True, null=True),
),
migrations.AlterField(
model_name='ikeproposal',
name='authentication_algorithm',
field=models.CharField(blank=True, null=True),
),
migrations.AlterField(
model_name='ipsecproposal',
name='authentication_algorithm',
field=models.CharField(blank=True, null=True),
),
migrations.AlterField(
model_name='ipsecproposal',
name='encryption_algorithm',
field=models.CharField(blank=True, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -35,7 +35,8 @@ class IKEProposal(PrimaryModel):
authentication_algorithm = models.CharField(
verbose_name=_('authentication algorithm'),
choices=AuthenticationAlgorithmChoices,
blank=True
blank=True,
null=True
)
group = models.PositiveSmallIntegerField(
verbose_name=_('group'),
@ -76,7 +77,8 @@ class IKEPolicy(PrimaryModel):
mode = models.CharField(
verbose_name=_('mode'),
choices=IKEModeChoices,
blank=True
blank=True,
null=True
)
proposals = models.ManyToManyField(
to='vpn.IKEProposal',
@ -128,12 +130,14 @@ class IPSecProposal(PrimaryModel):
encryption_algorithm = models.CharField(
verbose_name=_('encryption'),
choices=EncryptionAlgorithmChoices,
blank=True
blank=True,
null=True
)
authentication_algorithm = models.CharField(
verbose_name=_('authentication'),
choices=AuthenticationAlgorithmChoices,
blank=True
blank=True,
null=True
)
sa_lifetime_seconds = models.PositiveIntegerField(
verbose_name=_('SA lifetime (seconds)'),

View File

@ -0,0 +1,54 @@
from django.db import migrations, models
def set_null_values(apps, schema_editor):
"""
Replace empty strings with null values.
"""
WirelessLAN = apps.get_model('wireless', 'WirelessLAN')
WirelessLink = apps.get_model('wireless', 'WirelessLink')
WirelessLAN.objects.filter(auth_cipher='').update(auth_cipher=None)
WirelessLAN.objects.filter(auth_type='').update(auth_type=None)
WirelessLink.objects.filter(auth_cipher='').update(auth_cipher=None)
WirelessLink.objects.filter(auth_type='').update(auth_type=None)
WirelessLink.objects.filter(distance_unit='').update(distance_unit=None)
class Migration(migrations.Migration):
dependencies = [
('wireless', '0009_wirelesslink_distance'),
]
operations = [
migrations.AlterField(
model_name='wirelesslan',
name='auth_cipher',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='wirelesslan',
name='auth_type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='wirelesslink',
name='auth_cipher',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='wirelesslink',
name='auth_type',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.AlterField(
model_name='wirelesslink',
name='distance_unit',
field=models.CharField(blank=True, max_length=50, null=True),
),
migrations.RunPython(
code=set_null_values,
reverse_code=migrations.RunPython.noop
),
]

View File

@ -24,13 +24,15 @@ class WirelessAuthenticationBase(models.Model):
max_length=50,
choices=WirelessAuthTypeChoices,
blank=True,
null=True,
verbose_name=_("authentication type"),
)
auth_cipher = models.CharField(
verbose_name=_('authentication cipher'),
max_length=50,
choices=WirelessAuthCipherChoices,
blank=True
blank=True,
null=True
)
auth_psk = models.CharField(
max_length=PSK_MAX_LENGTH,