From 26159065269cb5109362219a551d11062c299855 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Tue, 14 Jan 2020 10:59:44 -0500 Subject: [PATCH] Squashed all migrations --- ...0001_initial_squashed_0006_terminations.py | 134 +++ ...n_squashed_0017_circuittype_description.py | 253 ++++++ ...010_devicebay_installed_device_set_null.py | 101 +++ ...number_squashed_0022_color_names_to_rgb.py | 154 ++++ ...shed_0043_device_component_name_lengths.py | 478 ++++++++++ ...tion_squashed_0061_platform_napalm_args.py | 354 ++++++++ ...face_mtu_squashed_0065_front_rear_ports.py | 124 +++ ...lifiers_squashed_0070_custom_tag_models.py | 146 +++ ...squashed_0088_powerfeed_available_power.py | 839 ++++++++++++++++++ ...0001_initial_squashed_0013_objectchange.py | 265 ++++++ ...igcontexts_squashed_0019_tag_taggeditem.py | 106 +++ ...021_add_color_comments_changelog_to_tag.py | 93 ++ ..._links_squashed_0034_configcontext_tags.py | 227 +++++ ...groups_squashed_0011_rir_add_is_private.py | 100 +++ ...18_remove_service_uniqueness_constraint.py | 171 ++++ ...n_squashed_0020_ipaddress_add_role_carp.py | 34 + ...rdering_squashed_0025_custom_tag_models.py | 145 +++ ...ls_first_squashed_0032_role_description.py | 140 +++ ...initial_squashed_0006_custom_tag_models.py | 81 ++ ...01_initial_squashed_0005_change_logging.py | 45 + ..._tokens_squashed_0003_token_permissions.py | 35 + ..._status_squashed_0009_custom_tag_models.py | 89 ++ ..._tenant_squashed_0012_vm_name_nonunique.py | 50 ++ 23 files changed, 4164 insertions(+) create mode 100644 netbox/circuits/migrations/0001_initial_squashed_0006_terminations.py create mode 100644 netbox/circuits/migrations/0007_circuit_add_description_squashed_0017_circuittype_description.py create mode 100644 netbox/dcim/migrations/0003_auto_20160628_1721_squashed_0010_devicebay_installed_device_set_null.py create mode 100644 netbox/dcim/migrations/0011_devicetype_part_number_squashed_0022_color_names_to_rgb.py create mode 100644 netbox/dcim/migrations/0023_devicetype_comments_squashed_0043_device_component_name_lengths.py create mode 100644 netbox/dcim/migrations/0044_virtualization_squashed_0061_platform_napalm_args.py create mode 100644 netbox/dcim/migrations/0062_interface_mtu_squashed_0065_front_rear_ports.py create mode 100644 netbox/dcim/migrations/0067_device_type_remove_qualifiers_squashed_0070_custom_tag_models.py create mode 100644 netbox/dcim/migrations/0071_device_components_add_description_squashed_0088_powerfeed_available_power.py create mode 100644 netbox/extras/migrations/0001_initial_squashed_0013_objectchange.py create mode 100644 netbox/extras/migrations/0014_configcontexts_squashed_0019_tag_taggeditem.py create mode 100644 netbox/extras/migrations/0020_tag_data_squashed_0021_add_color_comments_changelog_to_tag.py create mode 100644 netbox/extras/migrations/0022_custom_links_squashed_0034_configcontext_tags.py create mode 100644 netbox/ipam/migrations/0003_ipam_add_vlangroups_squashed_0011_rir_add_is_private.py create mode 100644 netbox/ipam/migrations/0012_services_squashed_0018_remove_service_uniqueness_constraint.py create mode 100644 netbox/ipam/migrations/0019_virtualization_squashed_0020_ipaddress_add_role_carp.py create mode 100644 netbox/ipam/migrations/0021_vrf_ordering_squashed_0025_custom_tag_models.py create mode 100644 netbox/ipam/migrations/0026_prefix_ordering_vrf_nulls_first_squashed_0032_role_description.py create mode 100644 netbox/secrets/migrations/0001_initial_squashed_0006_custom_tag_models.py create mode 100644 netbox/tenancy/migrations/0001_initial_squashed_0005_change_logging.py create mode 100644 netbox/users/migrations/0001_api_tokens_squashed_0003_token_permissions.py create mode 100644 netbox/virtualization/migrations/0002_virtualmachine_add_status_squashed_0009_custom_tag_models.py create mode 100644 netbox/virtualization/migrations/0010_cluster_add_tenant_squashed_0012_vm_name_nonunique.py diff --git a/netbox/circuits/migrations/0001_initial_squashed_0006_terminations.py b/netbox/circuits/migrations/0001_initial_squashed_0006_terminations.py new file mode 100644 index 000000000..4eec30667 --- /dev/null +++ b/netbox/circuits/migrations/0001_initial_squashed_0006_terminations.py @@ -0,0 +1,134 @@ +import django.db.models.deletion +from django.db import migrations, models + +import dcim.fields + + +def circuits_to_terms(apps, schema_editor): + Circuit = apps.get_model('circuits', 'Circuit') + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + for c in Circuit.objects.all(): + CircuitTermination( + circuit=c, + term_side=b'A', + site=c.site, + interface=c.interface, + port_speed=c.port_speed, + upstream_speed=c.upstream_speed, + xconnect_id=c.xconnect_id, + pp_info=c.pp_info, + ).save() + + +class Migration(migrations.Migration): + + replaces = [('circuits', '0001_initial'), ('circuits', '0002_auto_20160622_1821'), ('circuits', '0003_provider_32bit_asn_support'), ('circuits', '0004_circuit_add_tenant'), ('circuits', '0005_circuit_add_upstream_speed'), ('circuits', '0006_terminations')] + + dependencies = [ + ('tenancy', '0001_initial'), + ('dcim', '0001_initial'), + ('dcim', '0022_color_names_to_rgb'), + ] + + operations = [ + migrations.CreateModel( + name='CircuitType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Provider', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True)), + ('last_updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('asn', dcim.fields.ASNField(blank=True, null=True, verbose_name=b'ASN')), + ('account', models.CharField(blank=True, max_length=30, verbose_name=b'Account number')), + ('portal_url', models.URLField(blank=True, verbose_name=b'Portal')), + ('noc_contact', models.TextField(blank=True, verbose_name=b'NOC contact')), + ('admin_contact', models.TextField(blank=True, verbose_name=b'Admin contact')), + ('comments', models.TextField(blank=True)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Circuit', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True)), + ('last_updated', models.DateTimeField(auto_now=True)), + ('cid', models.CharField(max_length=50, verbose_name=b'Circuit ID')), + ('install_date', models.DateField(blank=True, null=True, verbose_name=b'Date installed')), + ('port_speed', models.PositiveIntegerField(verbose_name=b'Port speed (Kbps)')), + ('commit_rate', models.PositiveIntegerField(blank=True, null=True, verbose_name=b'Commit rate (Kbps)')), + ('xconnect_id', models.CharField(blank=True, max_length=50, verbose_name=b'Cross-connect ID')), + ('pp_info', models.CharField(blank=True, max_length=100, verbose_name=b'Patch panel/port(s)')), + ('comments', models.TextField(blank=True)), + ('interface', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='circuit', to='dcim.Interface')), + ('provider', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.Provider')), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='dcim.Site')), + ('type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='circuits.CircuitType')), + ('tenant', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuits', to='tenancy.Tenant')), + ('upstream_speed', models.PositiveIntegerField(blank=True, help_text=b'Upstream speed, if different from port speed', null=True, verbose_name=b'Upstream speed (Kbps)')), + ], + options={ + 'ordering': ['provider', 'cid'], + 'unique_together': {('provider', 'cid')}, + }, + ), + migrations.CreateModel( + name='CircuitTermination', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('term_side', models.CharField(choices=[(b'A', b'A'), (b'Z', b'Z')], max_length=1, verbose_name='Termination')), + ('port_speed', models.PositiveIntegerField(verbose_name=b'Port speed (Kbps)')), + ('upstream_speed', models.PositiveIntegerField(blank=True, help_text=b'Upstream speed, if different from port speed', null=True, verbose_name=b'Upstream speed (Kbps)')), + ('xconnect_id', models.CharField(blank=True, max_length=50, verbose_name=b'Cross-connect ID')), + ('pp_info', models.CharField(blank=True, max_length=100, verbose_name=b'Patch panel/port(s)')), + ('circuit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='terminations', to='circuits.Circuit')), + ('interface', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='circuit_termination', to='dcim.Interface')), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='circuit_terminations', to='dcim.Site')), + ], + options={ + 'ordering': ['circuit', 'term_side'], + 'unique_together': {('circuit', 'term_side')}, + }, + ), + migrations.RunPython( + code=circuits_to_terms, + ), + migrations.RemoveField( + model_name='circuit', + name='interface', + ), + migrations.RemoveField( + model_name='circuit', + name='port_speed', + ), + migrations.RemoveField( + model_name='circuit', + name='pp_info', + ), + migrations.RemoveField( + model_name='circuit', + name='site', + ), + migrations.RemoveField( + model_name='circuit', + name='upstream_speed', + ), + migrations.RemoveField( + model_name='circuit', + name='xconnect_id', + ), + ] diff --git a/netbox/circuits/migrations/0007_circuit_add_description_squashed_0017_circuittype_description.py b/netbox/circuits/migrations/0007_circuit_add_description_squashed_0017_circuittype_description.py new file mode 100644 index 000000000..c33504f50 --- /dev/null +++ b/netbox/circuits/migrations/0007_circuit_add_description_squashed_0017_circuittype_description.py @@ -0,0 +1,253 @@ +import sys + +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + +import dcim.fields +from dcim.constants import CONNECTION_STATUS_CONNECTED + +CIRCUIT_STATUS_CHOICES = ( + (0, 'deprovisioning'), + (1, 'active'), + (2, 'planned'), + (3, 'provisioning'), + (4, 'offline'), + (5, 'decommissioned') +) + + +def circuit_terminations_to_cables(apps, schema_editor): + """ + Copy all existing CircuitTermination Interface associations as Cables + """ + ContentType = apps.get_model('contenttypes', 'ContentType') + CircuitTermination = apps.get_model('circuits', 'CircuitTermination') + Interface = apps.get_model('dcim', 'Interface') + Cable = apps.get_model('dcim', 'Cable') + + # Load content types + circuittermination_type = ContentType.objects.get_for_model(CircuitTermination) + interface_type = ContentType.objects.get_for_model(Interface) + + # Create a new Cable instance from each console connection + if 'test' not in sys.argv: + print("\n Adding circuit terminations... ", end='', flush=True) + for circuittermination in CircuitTermination.objects.filter(interface__isnull=False): + + # Create the new Cable + cable = Cable.objects.create( + termination_a_type=circuittermination_type, + termination_a_id=circuittermination.id, + termination_b_type=interface_type, + termination_b_id=circuittermination.interface_id, + status=CONNECTION_STATUS_CONNECTED + ) + + # Cache the Cable on its two termination points + CircuitTermination.objects.filter(pk=circuittermination.pk).update( + cable=cable, + connected_endpoint=circuittermination.interface, + connection_status=CONNECTION_STATUS_CONNECTED + ) + # Cache the connected Cable on the Interface + Interface.objects.filter(pk=circuittermination.interface_id).update( + cable=cable, + _connected_circuittermination=circuittermination, + connection_status=CONNECTION_STATUS_CONNECTED + ) + + cable_count = Cable.objects.filter(termination_a_type=circuittermination_type).count() + if 'test' not in sys.argv: + print("{} cables created".format(cable_count)) + + +def circuit_status_to_slug(apps, schema_editor): + Circuit = apps.get_model('circuits', 'Circuit') + for id, slug in CIRCUIT_STATUS_CHOICES: + Circuit.objects.filter(status=str(id)).update(status=slug) + + +class Migration(migrations.Migration): + + replaces = [('circuits', '0007_circuit_add_description'), ('circuits', '0008_circuittermination_interface_protect_on_delete'), ('circuits', '0009_unicode_literals'), ('circuits', '0010_circuit_status'), ('circuits', '0011_tags'), ('circuits', '0012_change_logging'), ('circuits', '0013_cables'), ('circuits', '0014_circuittermination_description'), ('circuits', '0015_custom_tag_models'), ('circuits', '0016_3569_circuit_fields'), ('circuits', '0017_circuittype_description')] + + dependencies = [ + ('circuits', '0006_terminations'), + ('extras', '0019_tag_taggeditem'), + ('taggit', '0002_auto_20150616_2121'), + ('dcim', '0066_cables'), + ] + + operations = [ + migrations.AddField( + model_name='circuit', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AlterField( + model_name='circuittermination', + name='interface', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='circuit_termination', to='dcim.Interface'), + ), + migrations.AlterField( + model_name='circuit', + name='cid', + field=models.CharField(max_length=50, verbose_name='Circuit ID'), + ), + migrations.AlterField( + model_name='circuit', + name='commit_rate', + field=models.PositiveIntegerField(blank=True, null=True, verbose_name='Commit rate (Kbps)'), + ), + migrations.AlterField( + model_name='circuit', + name='install_date', + field=models.DateField(blank=True, null=True, verbose_name='Date installed'), + ), + migrations.AlterField( + model_name='circuittermination', + name='port_speed', + field=models.PositiveIntegerField(verbose_name='Port speed (Kbps)'), + ), + migrations.AlterField( + model_name='circuittermination', + name='pp_info', + field=models.CharField(blank=True, max_length=100, verbose_name='Patch panel/port(s)'), + ), + migrations.AlterField( + model_name='circuittermination', + name='term_side', + field=models.CharField(choices=[('A', 'A'), ('Z', 'Z')], max_length=1, verbose_name='Termination'), + ), + migrations.AlterField( + model_name='circuittermination', + name='upstream_speed', + field=models.PositiveIntegerField(blank=True, help_text='Upstream speed, if different from port speed', null=True, verbose_name='Upstream speed (Kbps)'), + ), + migrations.AlterField( + model_name='circuittermination', + name='xconnect_id', + field=models.CharField(blank=True, max_length=50, verbose_name='Cross-connect ID'), + ), + migrations.AlterField( + model_name='provider', + name='account', + field=models.CharField(blank=True, max_length=30, verbose_name='Account number'), + ), + migrations.AlterField( + model_name='provider', + name='admin_contact', + field=models.TextField(blank=True, verbose_name='Admin contact'), + ), + migrations.AlterField( + model_name='provider', + name='asn', + field=dcim.fields.ASNField(blank=True, null=True, verbose_name='ASN'), + ), + migrations.AlterField( + model_name='provider', + name='noc_contact', + field=models.TextField(blank=True, verbose_name='NOC contact'), + ), + migrations.AlterField( + model_name='provider', + name='portal_url', + field=models.URLField(blank=True, verbose_name='Portal'), + ), + migrations.AddField( + model_name='circuit', + name='status', + field=models.PositiveSmallIntegerField(choices=[[2, 'Planned'], [3, 'Provisioning'], [1, 'Active'], [4, 'Offline'], [0, 'Deprovisioning'], [5, 'Decommissioned']], default=1), + ), + migrations.AddField( + model_name='circuit', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='provider', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='circuittype', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='circuittype', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='circuit', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='circuit', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='provider', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='provider', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='circuittermination', + name='connected_endpoint', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.Interface'), + ), + migrations.AddField( + model_name='circuittermination', + name='connection_status', + field=models.NullBooleanField(), + ), + migrations.AddField( + model_name='circuittermination', + name='cable', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.Cable'), + ), + migrations.RunPython( + code=circuit_terminations_to_cables, + ), + migrations.RemoveField( + model_name='circuittermination', + name='interface', + ), + migrations.AddField( + model_name='circuittermination', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AlterField( + model_name='circuit', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='provider', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='circuit', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=circuit_status_to_slug, + ), + migrations.AddField( + model_name='circuittype', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + ] diff --git a/netbox/dcim/migrations/0003_auto_20160628_1721_squashed_0010_devicebay_installed_device_set_null.py b/netbox/dcim/migrations/0003_auto_20160628_1721_squashed_0010_devicebay_installed_device_set_null.py new file mode 100644 index 000000000..a9f80f49b --- /dev/null +++ b/netbox/dcim/migrations/0003_auto_20160628_1721_squashed_0010_devicebay_installed_device_set_null.py @@ -0,0 +1,101 @@ +import django.db.models.deletion +from django.db import migrations, models + +import dcim.fields + + +def copy_primary_ip(apps, schema_editor): + Device = apps.get_model('dcim', 'Device') + for d in Device.objects.select_related('primary_ip'): + if not d.primary_ip: + continue + if d.primary_ip.family == 4: + d.primary_ip4 = d.primary_ip + elif d.primary_ip.family == 6: + d.primary_ip6 = d.primary_ip + d.save() + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0003_auto_20160628_1721'), ('dcim', '0004_auto_20160701_2049'), ('dcim', '0005_auto_20160706_1722'), ('dcim', '0006_add_device_primary_ip4_ip6'), ('dcim', '0007_device_copy_primary_ip'), ('dcim', '0008_device_remove_primary_ip'), ('dcim', '0009_site_32bit_asn_support'), ('dcim', '0010_devicebay_installed_device_set_null')] + + dependencies = [ + ('ipam', '0001_initial'), + ('dcim', '0002_auto_20160622_1821'), + ] + + operations = [ + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[0, b'Virtual'], [800, b'10/100M (100BASE-TX)'], [1000, b'1GE (1000BASE-T)'], [1100, b'1GE (SFP)'], [1150, b'10GE (10GBASE-T)'], [1200, b'10GE (SFP+)'], [1300, b'10GE (XFP)'], [1400, b'40GE (QSFP+)']], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[0, b'Virtual'], [800, b'10/100M (100BASE-TX)'], [1000, b'1GE (1000BASE-T)'], [1100, b'1GE (SFP)'], [1150, b'10GE (10GBASE-T)'], [1200, b'10GE (SFP+)'], [1300, b'10GE (XFP)'], [1400, b'40GE (QSFP+)']], default=1200), + ), + migrations.AddField( + model_name='devicetype', + name='subdevice_role', + field=models.NullBooleanField(choices=[(None, b'None'), (True, b'Parent'), (False, b'Child')], default=None, help_text=b'Parent devices house child devices in device bays. Select "None" if this device type is neither a parent nor a child.', verbose_name=b'Parent/child status'), + ), + migrations.CreateModel( + name='DeviceBayTemplate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=30)), + ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_bay_templates', to='dcim.DeviceType')), + ], + options={ + 'ordering': ['device_type', 'name'], + 'unique_together': {('device_type', 'name')}, + }, + ), + migrations.CreateModel( + name='DeviceBay', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, verbose_name=b'Name')), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='device_bays', to='dcim.Device')), + ('installed_device', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_bay', to='dcim.Device')), + ], + options={ + 'ordering': ['device', 'name'], + 'unique_together': {('device', 'name')}, + }, + ), + migrations.AddField( + model_name='interface', + name='mac_address', + field=dcim.fields.MACAddressField(blank=True, null=True, verbose_name=b'MAC Address'), + ), + migrations.AddField( + model_name='device', + name='primary_ip4', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip4_for', to='ipam.IPAddress', verbose_name=b'Primary IPv4'), + ), + migrations.AddField( + model_name='device', + name='primary_ip6', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip6_for', to='ipam.IPAddress', verbose_name=b'Primary IPv6'), + ), + migrations.RunPython( + code=copy_primary_ip, + ), + migrations.RemoveField( + model_name='device', + name='primary_ip', + ), + migrations.AlterField( + model_name='site', + name='asn', + field=dcim.fields.ASNField(blank=True, null=True, verbose_name=b'ASN'), + ), + migrations.AlterField( + model_name='devicebay', + name='installed_device', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parent_bay', to='dcim.Device'), + ), + ] diff --git a/netbox/dcim/migrations/0011_devicetype_part_number_squashed_0022_color_names_to_rgb.py b/netbox/dcim/migrations/0011_devicetype_part_number_squashed_0022_color_names_to_rgb.py new file mode 100644 index 000000000..dac983398 --- /dev/null +++ b/netbox/dcim/migrations/0011_devicetype_part_number_squashed_0022_color_names_to_rgb.py @@ -0,0 +1,154 @@ +import django.core.validators +import django.db.models.deletion +from django.db import migrations, models + +import utilities.fields + +COLOR_CONVERSION = { + 'teal': '009688', + 'green': '4caf50', + 'blue': '2196f3', + 'purple': '9c27b0', + 'yellow': 'ffeb3b', + 'orange': 'ff9800', + 'red': 'f44336', + 'light_gray': 'c0c0c0', + 'medium_gray': '9e9e9e', + 'dark_gray': '607d8b', +} + + +def color_names_to_rgb(apps, schema_editor): + RackRole = apps.get_model('dcim', 'RackRole') + DeviceRole = apps.get_model('dcim', 'DeviceRole') + for color_name, color_rgb in COLOR_CONVERSION.items(): + RackRole.objects.filter(color=color_name).update(color=color_rgb) + DeviceRole.objects.filter(color=color_name).update(color=color_rgb) + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0011_devicetype_part_number'), ('dcim', '0012_site_rack_device_add_tenant'), ('dcim', '0013_add_interface_form_factors'), ('dcim', '0014_rack_add_type_width'), ('dcim', '0015_rack_add_u_height_validator'), ('dcim', '0016_module_add_manufacturer'), ('dcim', '0017_rack_add_role'), ('dcim', '0018_device_add_asset_tag'), ('dcim', '0019_new_iface_form_factors'), ('dcim', '0020_rack_desc_units'), ('dcim', '0021_add_ff_flexstack'), ('dcim', '0022_color_names_to_rgb')] + + dependencies = [ + ('dcim', '0010_devicebay_installed_device_set_null'), + ('tenancy', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='devicetype', + name='part_number', + field=models.CharField(blank=True, help_text=b'Discrete part number (optional)', max_length=50), + ), + migrations.AddField( + model_name='device', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='tenancy.Tenant'), + ), + migrations.AddField( + model_name='rack', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='racks', to='tenancy.Tenant'), + ), + migrations.AddField( + model_name='site', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='sites', to='tenancy.Tenant'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet', [[800, b'100BASE-TX (10/100M)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Modular', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1300, b'XFP (10GE)'], [1200, b'SFP+ (10GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet', [[800, b'100BASE-TX (10/100M)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Modular', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1300, b'XFP (10GE)'], [1200, b'SFP+ (10GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus']]]], default=1200), + ), + migrations.AddField( + model_name='rack', + name='type', + field=models.PositiveSmallIntegerField(blank=True, choices=[(100, b'2-post frame'), (200, b'4-post frame'), (300, b'4-post cabinet'), (1000, b'Wall-mounted frame'), (1100, b'Wall-mounted cabinet')], null=True, verbose_name=b'Type'), + ), + migrations.AddField( + model_name='rack', + name='width', + field=models.PositiveSmallIntegerField(choices=[(19, b'19 inches'), (23, b'23 inches')], default=19, help_text=b'Rail-to-rail width', verbose_name=b'Width'), + ), + migrations.AlterField( + model_name='rack', + name='u_height', + field=models.PositiveSmallIntegerField(default=42, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name=b'Height (U)'), + ), + migrations.AddField( + model_name='module', + name='manufacturer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='modules', to='dcim.Manufacturer'), + ), + migrations.CreateModel( + name='RackRole', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('color', models.CharField(choices=[[b'teal', b'Teal'], [b'green', b'Green'], [b'blue', b'Blue'], [b'purple', b'Purple'], [b'yellow', b'Yellow'], [b'orange', b'Orange'], [b'red', b'Red'], [b'light_gray', b'Light Gray'], [b'medium_gray', b'Medium Gray'], [b'dark_gray', b'Dark Gray']], max_length=30)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='rack', + name='role', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='racks', to='dcim.RackRole'), + ), + migrations.AddField( + model_name='device', + name='asset_tag', + field=utilities.fields.NullableCharField(blank=True, help_text=b'A unique tag used to identify this device', max_length=50, null=True, unique=True, verbose_name=b'Asset tag'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AddField( + model_name='rack', + name='desc_units', + field=models.BooleanField(default=False, help_text=b'Units are numbered top-to-bottom', verbose_name=b'Descending units'), + ), + migrations.AlterField( + model_name='device', + name='position', + field=models.PositiveSmallIntegerField(blank=True, help_text=b'The lowest-numbered unit occupied by the device', null=True, validators=[django.core.validators.MinValueValidator(1)], verbose_name=b'Position (U)'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.RunPython( + code=color_names_to_rgb, + ), + migrations.AlterField( + model_name='devicerole', + name='color', + field=utilities.fields.ColorField(max_length=6), + ), + migrations.AlterField( + model_name='rackrole', + name='color', + field=utilities.fields.ColorField(max_length=6), + ), + ] diff --git a/netbox/dcim/migrations/0023_devicetype_comments_squashed_0043_device_component_name_lengths.py b/netbox/dcim/migrations/0023_devicetype_comments_squashed_0043_device_component_name_lengths.py new file mode 100644 index 000000000..064832e80 --- /dev/null +++ b/netbox/dcim/migrations/0023_devicetype_comments_squashed_0043_device_component_name_lengths.py @@ -0,0 +1,478 @@ +import django.contrib.postgres.fields +import django.core.validators +import django.db.models.deletion +import mptt.fields +from django.conf import settings +from django.db import migrations, models + +import dcim.fields +import utilities.fields + + +def copy_site_from_rack(apps, schema_editor): + Device = apps.get_model('dcim', 'Device') + for device in Device.objects.all(): + device.site = device.rack.site + device.save() + + +def rpc_client_to_napalm_driver(apps, schema_editor): + """ + Migrate legacy RPC clients to their respective NAPALM drivers + """ + Platform = apps.get_model('dcim', 'Platform') + + Platform.objects.filter(rpc_client='juniper-junos').update(napalm_driver='junos') + Platform.objects.filter(rpc_client='cisco-ios').update(napalm_driver='ios') + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0023_devicetype_comments'), ('dcim', '0024_site_add_contact_fields'), ('dcim', '0025_devicetype_add_interface_ordering'), ('dcim', '0026_add_rack_reservations'), ('dcim', '0027_device_add_site'), ('dcim', '0028_device_copy_rack_to_site'), ('dcim', '0029_allow_rackless_devices'), ('dcim', '0030_interface_add_lag'), ('dcim', '0031_regions'), ('dcim', '0032_device_increase_name_length'), ('dcim', '0033_rackreservation_rack_editable'), ('dcim', '0034_rename_module_to_inventoryitem'), ('dcim', '0035_device_expand_status_choices'), ('dcim', '0036_add_ff_juniper_vcp'), ('dcim', '0037_unicode_literals'), ('dcim', '0038_wireless_interfaces'), ('dcim', '0039_interface_add_enabled_mtu'), ('dcim', '0040_inventoryitem_add_asset_tag_description'), ('dcim', '0041_napalm_integration'), ('dcim', '0042_interface_ff_10ge_cx4'), ('dcim', '0043_device_component_name_lengths')] + + dependencies = [ + ('dcim', '0022_color_names_to_rgb'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.AddField( + model_name='devicetype', + name='comments', + field=models.TextField(blank=True), + ), + migrations.AddField( + model_name='site', + name='contact_email', + field=models.EmailField(blank=True, max_length=254, verbose_name=b'Contact E-mail'), + ), + migrations.AddField( + model_name='site', + name='contact_name', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='site', + name='contact_phone', + field=models.CharField(blank=True, max_length=20), + ), + migrations.AddField( + model_name='devicetype', + name='interface_ordering', + field=models.PositiveSmallIntegerField(choices=[[1, b'Slot/position'], [2, b'Name (alphabetically)']], default=1), + ), + migrations.CreateModel( + name='RackReservation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('units', django.contrib.postgres.fields.ArrayField(base_field=models.PositiveSmallIntegerField(), size=None)), + ('created', models.DateTimeField(auto_now_add=True)), + ('description', models.CharField(max_length=100)), + ('rack', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to='dcim.Rack')), + ('user', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['created'], + }, + ), + migrations.AddField( + model_name='device', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.Site'), + ), + migrations.RunPython( + code=copy_site_from_rack, + ), + migrations.AlterField( + model_name='device', + name='rack', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.Rack'), + ), + migrations.AlterField( + model_name='device', + name='site', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='devices', to='dcim.Site'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual'], [200, b'Link Aggregation Group (LAG)']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual'], [200, b'Link Aggregation Group (LAG)']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.CreateModel( + name='Region', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='dcim.Region')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='site', + name='region', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sites', to='dcim.Region'), + ), + migrations.AlterField( + model_name='device', + name='name', + field=utilities.fields.NullableCharField(blank=True, max_length=64, null=True, unique=True), + ), + migrations.AlterField( + model_name='rackreservation', + name='rack', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reservations', to='dcim.Rack'), + ), + migrations.RenameModel( + old_name='Module', + new_name='InventoryItem', + ), + migrations.AlterField( + model_name='inventoryitem', + name='device', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inventory_items', to='dcim.Device'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='parent', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.InventoryItem'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='manufacturer', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.Manufacturer'), + ), + migrations.AlterField( + model_name='device', + name='status', + field=models.PositiveIntegerField(choices=[[1, b'Active'], [0, b'Offline'], [2, b'Planned'], [3, b'Staged'], [4, b'Failed'], [5, b'Inventory']], default=1, verbose_name=b'Status'), + ), + migrations.AlterField( + model_name='device', + name='status', + field=models.PositiveSmallIntegerField(choices=[[1, b'Active'], [0, b'Offline'], [2, b'Planned'], [3, b'Staged'], [4, b'Failed'], [5, b'Inventory']], default=1, verbose_name=b'Status'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual'], [200, b'Link Aggregation Group (LAG)']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus'], [5200, b'Juniper VCP']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[[b'Virtual interfaces', [[0, b'Virtual'], [200, b'Link Aggregation Group (LAG)']]], [b'Ethernet (fixed)', [[800, b'100BASE-TX (10/100ME)'], [1000, b'1000BASE-T (1GE)'], [1150, b'10GBASE-T (10GE)']]], [b'Ethernet (modular)', [[1050, b'GBIC (1GE)'], [1100, b'SFP (1GE)'], [1200, b'SFP+ (10GE)'], [1300, b'XFP (10GE)'], [1310, b'XENPAK (10GE)'], [1320, b'X2 (10GE)'], [1350, b'SFP28 (25GE)'], [1400, b'QSFP+ (40GE)'], [1500, b'CFP (100GE)'], [1600, b'QSFP28 (100GE)']]], [b'FibreChannel', [[3010, b'SFP (1GFC)'], [3020, b'SFP (2GFC)'], [3040, b'SFP (4GFC)'], [3080, b'SFP+ (8GFC)'], [3160, b'SFP+ (16GFC)']]], [b'Serial', [[4000, b'T1 (1.544 Mbps)'], [4010, b'E1 (2.048 Mbps)'], [4040, b'T3 (45 Mbps)'], [4050, b'E3 (34 Mbps)'], [4050, b'E3 (34 Mbps)']]], [b'Stacking', [[5000, b'Cisco StackWise'], [5050, b'Cisco StackWise Plus'], [5100, b'Cisco FlexStack'], [5150, b'Cisco FlexStack Plus'], [5200, b'Juniper VCP']]], [b'Other', [[32767, b'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='consoleport', + name='connection_status', + field=models.NullBooleanField(choices=[[False, 'Planned'], [True, 'Connected']], default=True), + ), + migrations.AlterField( + model_name='consoleport', + name='cs_port', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connected_console', to='dcim.ConsoleServerPort', verbose_name='Console server port'), + ), + migrations.AlterField( + model_name='device', + name='asset_tag', + field=utilities.fields.NullableCharField(blank=True, help_text='A unique tag used to identify this device', max_length=50, null=True, unique=True, verbose_name='Asset tag'), + ), + migrations.AlterField( + model_name='device', + name='face', + field=models.PositiveSmallIntegerField(blank=True, choices=[[0, 'Front'], [1, 'Rear']], null=True, verbose_name='Rack face'), + ), + migrations.AlterField( + model_name='device', + name='position', + field=models.PositiveSmallIntegerField(blank=True, help_text='The lowest-numbered unit occupied by the device', null=True, validators=[django.core.validators.MinValueValidator(1)], verbose_name='Position (U)'), + ), + migrations.AlterField( + model_name='device', + name='primary_ip4', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip4_for', to='ipam.IPAddress', verbose_name='Primary IPv4'), + ), + migrations.AlterField( + model_name='device', + name='primary_ip6', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='primary_ip6_for', to='ipam.IPAddress', verbose_name='Primary IPv6'), + ), + migrations.AlterField( + model_name='device', + name='serial', + field=models.CharField(blank=True, max_length=50, verbose_name='Serial number'), + ), + migrations.AlterField( + model_name='device', + name='status', + field=models.PositiveSmallIntegerField(choices=[[1, 'Active'], [0, 'Offline'], [2, 'Planned'], [3, 'Staged'], [4, 'Failed'], [5, 'Inventory']], default=1, verbose_name='Status'), + ), + migrations.AlterField( + model_name='devicebay', + name='name', + field=models.CharField(max_length=50, verbose_name='Name'), + ), + migrations.AlterField( + model_name='devicetype', + name='interface_ordering', + field=models.PositiveSmallIntegerField(choices=[[1, 'Slot/position'], [2, 'Name (alphabetically)']], default=1), + ), + migrations.AlterField( + model_name='devicetype', + name='is_console_server', + field=models.BooleanField(default=False, help_text='This type of device has console server ports', verbose_name='Is a console server'), + ), + migrations.AlterField( + model_name='devicetype', + name='is_full_depth', + field=models.BooleanField(default=True, help_text='Device consumes both front and rear rack faces', verbose_name='Is full depth'), + ), + migrations.AlterField( + model_name='devicetype', + name='is_network_device', + field=models.BooleanField(default=True, help_text='This type of device has network interfaces', verbose_name='Is a network device'), + ), + migrations.AlterField( + model_name='devicetype', + name='is_pdu', + field=models.BooleanField(default=False, help_text='This type of device has power outlets', verbose_name='Is a PDU'), + ), + migrations.AlterField( + model_name='devicetype', + name='part_number', + field=models.CharField(blank=True, help_text='Discrete part number (optional)', max_length=50), + ), + migrations.AlterField( + model_name='devicetype', + name='subdevice_role', + field=models.NullBooleanField(choices=[(None, 'None'), (True, 'Parent'), (False, 'Child')], default=None, help_text='Parent devices house child devices in device bays. Select "None" if this device type is neither a parent nor a child.', verbose_name='Parent/child status'), + ), + migrations.AlterField( + model_name='devicetype', + name='u_height', + field=models.PositiveSmallIntegerField(default=1, verbose_name='Height (U)'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AddField( + model_name='interface', + name='lag', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='member_interfaces', to='dcim.Interface', verbose_name='Parent LAG'), + ), + migrations.AlterField( + model_name='interface', + name='mac_address', + field=dcim.fields.MACAddressField(blank=True, null=True, verbose_name='MAC Address'), + ), + migrations.AlterField( + model_name='interface', + name='mgmt_only', + field=models.BooleanField(default=False, help_text='This interface is used only for out-of-band management', verbose_name='OOB Management'), + ), + migrations.AlterField( + model_name='interfaceconnection', + name='connection_status', + field=models.BooleanField(choices=[[False, 'Planned'], [True, 'Connected']], default=True, verbose_name='Status'), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='mgmt_only', + field=models.BooleanField(default=False, verbose_name='Management only'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='discovered', + field=models.BooleanField(default=False, verbose_name='Discovered'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='name', + field=models.CharField(max_length=50, verbose_name='Name'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='part_id', + field=models.CharField(blank=True, max_length=50, verbose_name='Part ID'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='serial', + field=models.CharField(blank=True, max_length=50, verbose_name='Serial number'), + ), + migrations.AlterField( + model_name='platform', + name='rpc_client', + field=models.CharField(blank=True, choices=[['juniper-junos', 'Juniper Junos (NETCONF)'], ['cisco-ios', 'Cisco IOS (SSH)'], ['opengear', 'Opengear (SSH)']], max_length=30, verbose_name='RPC client'), + ), + migrations.AlterField( + model_name='powerport', + name='connection_status', + field=models.NullBooleanField(choices=[[False, 'Planned'], [True, 'Connected']], default=True), + ), + migrations.AlterField( + model_name='rack', + name='desc_units', + field=models.BooleanField(default=False, help_text='Units are numbered top-to-bottom', verbose_name='Descending units'), + ), + migrations.AlterField( + model_name='rack', + name='facility_id', + field=utilities.fields.NullableCharField(blank=True, max_length=30, null=True, verbose_name='Facility ID'), + ), + migrations.AlterField( + model_name='rack', + name='type', + field=models.PositiveSmallIntegerField(blank=True, choices=[(100, '2-post frame'), (200, '4-post frame'), (300, '4-post cabinet'), (1000, 'Wall-mounted frame'), (1100, 'Wall-mounted cabinet')], null=True, verbose_name='Type'), + ), + migrations.AlterField( + model_name='rack', + name='u_height', + field=models.PositiveSmallIntegerField(default=42, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Height (U)'), + ), + migrations.AlterField( + model_name='rack', + name='width', + field=models.PositiveSmallIntegerField(choices=[(19, '19 inches'), (23, '23 inches')], default=19, help_text='Rail-to-rail width', verbose_name='Width'), + ), + migrations.AlterField( + model_name='site', + name='asn', + field=dcim.fields.ASNField(blank=True, null=True, verbose_name='ASN'), + ), + migrations.AlterField( + model_name='site', + name='contact_email', + field=models.EmailField(blank=True, max_length=254, verbose_name='Contact E-mail'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AddField( + model_name='interface', + name='enabled', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='interface', + name='mtu', + field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='MTU'), + ), + migrations.AddField( + model_name='inventoryitem', + name='asset_tag', + field=utilities.fields.NullableCharField(blank=True, help_text='A unique tag used to identify this item', max_length=50, null=True, unique=True, verbose_name='Asset tag'), + ), + migrations.AddField( + model_name='inventoryitem', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AlterModelOptions( + name='device', + options={'ordering': ['name'], 'permissions': (('napalm_read', 'Read-only access to devices via NAPALM'), ('napalm_write', 'Read/write access to devices via NAPALM'))}, + ), + migrations.AddField( + model_name='platform', + name='napalm_driver', + field=models.CharField(blank=True, help_text='The name of the NAPALM driver to use when interacting with devices.', max_length=50, verbose_name='NAPALM driver'), + ), + migrations.AlterField( + model_name='platform', + name='rpc_client', + field=models.CharField(blank=True, choices=[['juniper-junos', 'Juniper Junos (NETCONF)'], ['cisco-ios', 'Cisco IOS (SSH)'], ['opengear', 'Opengear (SSH)']], max_length=30, verbose_name='Legacy RPC client'), + ), + migrations.RunPython( + code=rpc_client_to_napalm_driver, + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='consoleport', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='consoleporttemplate', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='consoleserverport', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='consoleserverporttemplate', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='devicebaytemplate', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='interface', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='poweroutlet', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='powerport', + name='name', + field=models.CharField(max_length=50), + ), + migrations.AlterField( + model_name='powerporttemplate', + name='name', + field=models.CharField(max_length=50), + ), + ] diff --git a/netbox/dcim/migrations/0044_virtualization_squashed_0061_platform_napalm_args.py b/netbox/dcim/migrations/0044_virtualization_squashed_0061_platform_napalm_args.py new file mode 100644 index 000000000..18ef39fe7 --- /dev/null +++ b/netbox/dcim/migrations/0044_virtualization_squashed_0061_platform_napalm_args.py @@ -0,0 +1,354 @@ +import django.contrib.postgres.fields.jsonb +import django.core.validators +import django.db.models.deletion +import taggit.managers +import timezone_field.fields +from django.conf import settings +from django.db import migrations, models + +import utilities.fields + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0044_virtualization'), ('dcim', '0045_devicerole_vm_role'), ('dcim', '0046_rack_lengthen_facility_id'), ('dcim', '0047_more_100ge_form_factors'), ('dcim', '0048_rack_serial'), ('dcim', '0049_rackreservation_change_user'), ('dcim', '0050_interface_vlan_tagging'), ('dcim', '0051_rackreservation_tenant'), ('dcim', '0052_virtual_chassis'), ('dcim', '0053_platform_manufacturer'), ('dcim', '0054_site_status_timezone_description'), ('dcim', '0055_virtualchassis_ordering'), ('dcim', '0056_django2'), ('dcim', '0057_tags'), ('dcim', '0058_relax_rack_naming_constraints'), ('dcim', '0059_site_latitude_longitude'), ('dcim', '0060_change_logging'), ('dcim', '0061_platform_napalm_args')] + + dependencies = [ + ('virtualization', '0001_virtualization'), + ('tenancy', '0003_unicode_literals'), + ('ipam', '0020_ipaddress_add_role_carp'), + ('dcim', '0043_device_component_name_lengths'), + ('taggit', '0002_auto_20150616_2121'), + ] + + operations = [ + migrations.AddField( + model_name='device', + name='cluster', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='devices', to='virtualization.Cluster'), + ), + migrations.AddField( + model_name='interface', + name='virtual_machine', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='virtualization.VirtualMachine'), + ), + migrations.AlterField( + model_name='interface', + name='device', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='interfaces', to='dcim.Device'), + ), + migrations.AddField( + model_name='devicerole', + name='vm_role', + field=models.BooleanField(default=True, help_text='Virtual machines may be assigned to this role', verbose_name='VM Role'), + ), + migrations.AlterField( + model_name='rack', + name='facility_id', + field=utilities.fields.NullableCharField(blank=True, max_length=50, null=True, verbose_name='Facility ID'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AddField( + model_name='rack', + name='serial', + field=models.CharField(blank=True, max_length=50, verbose_name='Serial number'), + ), + migrations.AlterField( + model_name='rackreservation', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='interface', + name='mode', + field=models.PositiveSmallIntegerField(blank=True, choices=[[100, 'Access'], [200, 'Tagged'], [300, 'Tagged All']], null=True), + ), + migrations.AddField( + model_name='interface', + name='tagged_vlans', + field=models.ManyToManyField(blank=True, related_name='interfaces_as_tagged', to='ipam.VLAN', verbose_name='Tagged VLANs'), + ), + migrations.AddField( + model_name='rackreservation', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='rackreservations', to='tenancy.Tenant'), + ), + migrations.CreateModel( + name='VirtualChassis', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('domain', models.CharField(blank=True, max_length=30)), + ('master', models.OneToOneField(default=1, on_delete=django.db.models.deletion.PROTECT, related_name='vc_master_for', to='dcim.Device')), + ], + options={ + 'ordering': ['master'], + 'verbose_name_plural': 'virtual chassis', + }, + ), + migrations.AddField( + model_name='device', + name='virtual_chassis', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='members', to='dcim.VirtualChassis'), + ), + migrations.AddField( + model_name='device', + name='vc_position', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)]), + ), + migrations.AddField( + model_name='device', + name='vc_priority', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(255)]), + ), + migrations.AlterUniqueTogether( + name='device', + unique_together={('rack', 'position', 'face'), ('virtual_chassis', 'vc_position')}, + ), + migrations.AlterField( + model_name='platform', + name='napalm_driver', + field=models.CharField(blank=True, help_text='The name of the NAPALM driver to use when interacting with devices', max_length=50, verbose_name='NAPALM driver'), + ), + migrations.AddField( + model_name='site', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='site', + name='status', + field=models.PositiveSmallIntegerField(choices=[[1, 'Active'], [2, 'Planned'], [4, 'Retired']], default=1), + ), + migrations.AddField( + model_name='site', + name='time_zone', + field=timezone_field.fields.TimeZoneField(blank=True), + ), + migrations.AlterField( + model_name='virtualchassis', + name='master', + field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='vc_master_for', to='dcim.Device'), + ), + migrations.AddField( + model_name='interface', + name='untagged_vlan', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='interfaces_as_untagged', to='ipam.VLAN', verbose_name='Untagged VLAN'), + ), + migrations.AddField( + model_name='platform', + name='manufacturer', + field=models.ForeignKey(blank=True, help_text='Optionally limit this platform to devices of a certain manufacturer', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='platforms', to='dcim.Manufacturer'), + ), + migrations.AddField( + model_name='device', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='devicetype', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='rack', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='site', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='consoleport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='consoleserverport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='devicebay', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='interface', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='inventoryitem', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='poweroutlet', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='powerport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='virtualchassis', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AlterModelOptions( + name='rack', + options={'ordering': ['site', 'group', 'name']}, + ), + migrations.AlterUniqueTogether( + name='rack', + unique_together={('group', 'name'), ('group', 'facility_id')}, + ), + migrations.AddField( + model_name='site', + name='latitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=8, null=True), + ), + migrations.AddField( + model_name='site', + name='longitude', + field=models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True), + ), + migrations.AddField( + model_name='devicerole', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='devicerole', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='devicetype', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='devicetype', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='manufacturer', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='manufacturer', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='platform', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='platform', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='rackgroup', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='rackgroup', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='rackreservation', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='rackrole', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='rackrole', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='region', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='region', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='virtualchassis', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='virtualchassis', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='device', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='device', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='rack', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='rack', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='rackreservation', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='site', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='site', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='platform', + name='napalm_args', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, help_text='Additional arguments to pass when initiating the NAPALM driver (JSON format)', null=True, verbose_name='NAPALM arguments'), + ), + ] diff --git a/netbox/dcim/migrations/0062_interface_mtu_squashed_0065_front_rear_ports.py b/netbox/dcim/migrations/0062_interface_mtu_squashed_0065_front_rear_ports.py new file mode 100644 index 000000000..71ce4191f --- /dev/null +++ b/netbox/dcim/migrations/0062_interface_mtu_squashed_0065_front_rear_ports.py @@ -0,0 +1,124 @@ +import django.contrib.postgres.fields.jsonb +import django.core.validators +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0062_interface_mtu'), ('dcim', '0063_device_local_context_data'), ('dcim', '0064_remove_platform_rpc_client'), ('dcim', '0065_front_rear_ports')] + + dependencies = [ + ('taggit', '0002_auto_20150616_2121'), + ('dcim', '0061_platform_napalm_args'), + ] + + operations = [ + migrations.AlterField( + model_name='interface', + name='mtu', + field=models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65536)], verbose_name='MTU'), + ), + migrations.AlterField( + model_name='interface', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['SONET', [[6100, 'OC-3/STM-1'], [6200, 'OC-12/STM-4'], [6300, 'OC-48/STM-16'], [6400, 'OC-192/STM-64'], [6500, 'OC-768/STM-256'], [6600, 'OC-1920/STM-640'], [6700, 'OC-3840/STM-1234']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)'], [3320, 'SFP28 (32GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP'], [5300, 'Extreme SummitStack'], [5310, 'Extreme SummitStack-128'], [5320, 'Extreme SummitStack-256'], [5330, 'Extreme SummitStack-512']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AlterField( + model_name='interfacetemplate', + name='form_factor', + field=models.PositiveSmallIntegerField(choices=[['Virtual interfaces', [[0, 'Virtual'], [200, 'Link Aggregation Group (LAG)']]], ['Ethernet (fixed)', [[800, '100BASE-TX (10/100ME)'], [1000, '1000BASE-T (1GE)'], [1150, '10GBASE-T (10GE)'], [1170, '10GBASE-CX4 (10GE)']]], ['Ethernet (modular)', [[1050, 'GBIC (1GE)'], [1100, 'SFP (1GE)'], [1200, 'SFP+ (10GE)'], [1300, 'XFP (10GE)'], [1310, 'XENPAK (10GE)'], [1320, 'X2 (10GE)'], [1350, 'SFP28 (25GE)'], [1400, 'QSFP+ (40GE)'], [1500, 'CFP (100GE)'], [1510, 'CFP2 (100GE)'], [1520, 'CFP4 (100GE)'], [1550, 'Cisco CPAK (100GE)'], [1600, 'QSFP28 (100GE)']]], ['Wireless', [[2600, 'IEEE 802.11a'], [2610, 'IEEE 802.11b/g'], [2620, 'IEEE 802.11n'], [2630, 'IEEE 802.11ac'], [2640, 'IEEE 802.11ad']]], ['SONET', [[6100, 'OC-3/STM-1'], [6200, 'OC-12/STM-4'], [6300, 'OC-48/STM-16'], [6400, 'OC-192/STM-64'], [6500, 'OC-768/STM-256'], [6600, 'OC-1920/STM-640'], [6700, 'OC-3840/STM-1234']]], ['FibreChannel', [[3010, 'SFP (1GFC)'], [3020, 'SFP (2GFC)'], [3040, 'SFP (4GFC)'], [3080, 'SFP+ (8GFC)'], [3160, 'SFP+ (16GFC)'], [3320, 'SFP28 (32GFC)']]], ['Serial', [[4000, 'T1 (1.544 Mbps)'], [4010, 'E1 (2.048 Mbps)'], [4040, 'T3 (45 Mbps)'], [4050, 'E3 (34 Mbps)']]], ['Stacking', [[5000, 'Cisco StackWise'], [5050, 'Cisco StackWise Plus'], [5100, 'Cisco FlexStack'], [5150, 'Cisco FlexStack Plus'], [5200, 'Juniper VCP'], [5300, 'Extreme SummitStack'], [5310, 'Extreme SummitStack-128'], [5320, 'Extreme SummitStack-256'], [5330, 'Extreme SummitStack-512']]], ['Other', [[32767, 'Other']]]], default=1200), + ), + migrations.AddField( + model_name='device', + name='local_context_data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), + ), + migrations.RemoveField( + model_name='platform', + name='rpc_client', + ), + migrations.CreateModel( + name='RearPort', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=64)), + ('type', models.PositiveSmallIntegerField()), + ('positions', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(64)])), + ('description', models.CharField(blank=True, max_length=100)), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rearports', to='dcim.Device')), + ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), + ], + options={ + 'ordering': ['device', 'name'], + 'unique_together': {('device', 'name')}, + }, + ), + migrations.CreateModel( + name='RearPortTemplate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=64)), + ('type', models.PositiveSmallIntegerField()), + ('positions', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(64)])), + ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rearport_templates', to='dcim.DeviceType')), + ], + options={ + 'ordering': ['device_type', 'name'], + 'unique_together': {('device_type', 'name')}, + }, + ), + migrations.CreateModel( + name='FrontPortTemplate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=64)), + ('type', models.PositiveSmallIntegerField()), + ('rear_port_position', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(64)])), + ('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontport_templates', to='dcim.DeviceType')), + ('rear_port', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontport_templates', to='dcim.RearPortTemplate')), + ], + options={ + 'ordering': ['device_type', 'name'], + 'unique_together': {('rear_port', 'rear_port_position'), ('device_type', 'name')}, + }, + ), + migrations.CreateModel( + name='FrontPort', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=64)), + ('type', models.PositiveSmallIntegerField()), + ('rear_port_position', models.PositiveSmallIntegerField(default=1, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(64)])), + ('description', models.CharField(blank=True, max_length=100)), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontports', to='dcim.Device')), + ('rear_port', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='frontports', to='dcim.RearPort')), + ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), + ], + options={ + 'ordering': ['device', 'name'], + 'unique_together': {('device', 'name'), ('rear_port', 'rear_port_position')}, + }, + ), + migrations.AlterField( + model_name='consoleporttemplate', + name='device_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consoleport_templates', to='dcim.DeviceType'), + ), + migrations.AlterField( + model_name='consoleserverporttemplate', + name='device_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='consoleserverport_templates', to='dcim.DeviceType'), + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='device_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='poweroutlet_templates', to='dcim.DeviceType'), + ), + migrations.AlterField( + model_name='powerporttemplate', + name='device_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='powerport_templates', to='dcim.DeviceType'), + ), + ] diff --git a/netbox/dcim/migrations/0067_device_type_remove_qualifiers_squashed_0070_custom_tag_models.py b/netbox/dcim/migrations/0067_device_type_remove_qualifiers_squashed_0070_custom_tag_models.py new file mode 100644 index 000000000..6fbf115d9 --- /dev/null +++ b/netbox/dcim/migrations/0067_device_type_remove_qualifiers_squashed_0070_custom_tag_models.py @@ -0,0 +1,146 @@ +import taggit.managers +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0067_device_type_remove_qualifiers'), ('dcim', '0068_rack_new_fields'), ('dcim', '0069_deprecate_nullablecharfield'), ('dcim', '0070_custom_tag_models')] + + dependencies = [ + ('extras', '0019_tag_taggeditem'), + ('dcim', '0066_cables'), + ] + + operations = [ + migrations.RemoveField( + model_name='devicetype', + name='is_console_server', + ), + migrations.RemoveField( + model_name='devicetype', + name='is_network_device', + ), + migrations.RemoveField( + model_name='devicetype', + name='is_pdu', + ), + migrations.RemoveField( + model_name='devicetype', + name='interface_ordering', + ), + migrations.AddField( + model_name='rack', + name='status', + field=models.PositiveSmallIntegerField(default=3), + ), + migrations.AddField( + model_name='rack', + name='outer_depth', + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='rack', + name='outer_unit', + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='rack', + name='outer_width', + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='device', + name='asset_tag', + field=models.CharField(blank=True, max_length=50, null=True, unique=True), + ), + migrations.AlterField( + model_name='device', + name='name', + field=models.CharField(blank=True, max_length=64, null=True, unique=True), + ), + migrations.AlterField( + model_name='inventoryitem', + name='asset_tag', + field=models.CharField(blank=True, max_length=50, null=True, unique=True), + ), + migrations.AddField( + model_name='rack', + name='asset_tag', + field=models.CharField(blank=True, max_length=50, null=True, unique=True), + ), + migrations.AlterField( + model_name='rack', + name='facility_id', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='consoleport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='consoleserverport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='device', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='devicebay', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='devicetype', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='frontport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='interface', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='inventoryitem', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='poweroutlet', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='powerport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='rack', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='rearport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='site', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AlterField( + model_name='virtualchassis', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + ] diff --git a/netbox/dcim/migrations/0071_device_components_add_description_squashed_0088_powerfeed_available_power.py b/netbox/dcim/migrations/0071_device_components_add_description_squashed_0088_powerfeed_available_power.py new file mode 100644 index 000000000..f74572c6f --- /dev/null +++ b/netbox/dcim/migrations/0071_device_components_add_description_squashed_0088_powerfeed_available_power.py @@ -0,0 +1,839 @@ +import sys + +import django.core.validators +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + +SITE_STATUS_CHOICES = ( + (1, 'active'), + (2, 'planned'), + (4, 'retired'), +) + +RACK_TYPE_CHOICES = ( + (100, '2-post-frame'), + (200, '4-post-frame'), + (300, '4-post-cabinet'), + (1000, 'wall-frame'), + (1100, 'wall-cabinet'), +) + +RACK_STATUS_CHOICES = ( + (0, 'reserved'), + (1, 'available'), + (2, 'planned'), + (3, 'active'), + (4, 'deprecated'), +) + +RACK_DIMENSION_CHOICES = ( + (1000, 'mm'), + (2000, 'in'), +) + +SUBDEVICE_ROLE_CHOICES = ( + ('true', 'parent'), + ('false', 'child'), +) + +DEVICE_FACE_CHOICES = ( + (0, 'front'), + (1, 'rear'), +) + +DEVICE_STATUS_CHOICES = ( + (0, 'offline'), + (1, 'active'), + (2, 'planned'), + (3, 'staged'), + (4, 'failed'), + (5, 'inventory'), + (6, 'decommissioning'), +) + +INTERFACE_TYPE_CHOICES = ( + (0, 'virtual'), + (200, 'lag'), + (800, '100base-tx'), + (1000, '1000base-t'), + (1050, '1000base-x-gbic'), + (1100, '1000base-x-sfp'), + (1120, '2.5gbase-t'), + (1130, '5gbase-t'), + (1150, '10gbase-t'), + (1170, '10gbase-cx4'), + (1200, '10gbase-x-sfpp'), + (1300, '10gbase-x-xfp'), + (1310, '10gbase-x-xenpak'), + (1320, '10gbase-x-x2'), + (1350, '25gbase-x-sfp28'), + (1400, '40gbase-x-qsfpp'), + (1420, '50gbase-x-sfp28'), + (1500, '100gbase-x-cfp'), + (1510, '100gbase-x-cfp2'), + (1520, '100gbase-x-cfp4'), + (1550, '100gbase-x-cpak'), + (1600, '100gbase-x-qsfp28'), + (1650, '200gbase-x-cfp2'), + (1700, '200gbase-x-qsfp56'), + (1750, '400gbase-x-qsfpdd'), + (1800, '400gbase-x-osfp'), + (2600, 'ieee802.11a'), + (2610, 'ieee802.11g'), + (2620, 'ieee802.11n'), + (2630, 'ieee802.11ac'), + (2640, 'ieee802.11ad'), + (2810, 'gsm'), + (2820, 'cdma'), + (2830, 'lte'), + (6100, 'sonet-oc3'), + (6200, 'sonet-oc12'), + (6300, 'sonet-oc48'), + (6400, 'sonet-oc192'), + (6500, 'sonet-oc768'), + (6600, 'sonet-oc1920'), + (6700, 'sonet-oc3840'), + (3010, '1gfc-sfp'), + (3020, '2gfc-sfp'), + (3040, '4gfc-sfp'), + (3080, '8gfc-sfpp'), + (3160, '16gfc-sfpp'), + (3320, '32gfc-sfp28'), + (3400, '128gfc-sfp28'), + (7010, 'inifiband-sdr'), + (7020, 'inifiband-ddr'), + (7030, 'inifiband-qdr'), + (7040, 'inifiband-fdr10'), + (7050, 'inifiband-fdr'), + (7060, 'inifiband-edr'), + (7070, 'inifiband-hdr'), + (7080, 'inifiband-ndr'), + (7090, 'inifiband-xdr'), + (4000, 't1'), + (4010, 'e1'), + (4040, 't3'), + (4050, 'e3'), + (5000, 'cisco-stackwise'), + (5050, 'cisco-stackwise-plus'), + (5100, 'cisco-flexstack'), + (5150, 'cisco-flexstack-plus'), + (5200, 'juniper-vcp'), + (5300, 'extreme-summitstack'), + (5310, 'extreme-summitstack-128'), + (5320, 'extreme-summitstack-256'), + (5330, 'extreme-summitstack-512'), +) + +INTERFACE_MODE_CHOICES = ( + (100, 'access'), + (200, 'tagged'), + (300, 'tagged-all'), +) + +PORT_TYPE_CHOICES = ( + (1000, '8p8c'), + (1100, '110-punch'), + (1200, 'bnc'), + (2000, 'st'), + (2100, 'sc'), + (2110, 'sc-apc'), + (2200, 'fc'), + (2300, 'lc'), + (2310, 'lc-apc'), + (2400, 'mtrj'), + (2500, 'mpo'), + (2600, 'lsh'), + (2610, 'lsh-apc'), +) + +CABLE_TYPE_CHOICES = ( + (1300, 'cat3'), + (1500, 'cat5'), + (1510, 'cat5e'), + (1600, 'cat6'), + (1610, 'cat6a'), + (1700, 'cat7'), + (1800, 'dac-active'), + (1810, 'dac-passive'), + (1900, 'coaxial'), + (3000, 'mmf'), + (3010, 'mmf-om1'), + (3020, 'mmf-om2'), + (3030, 'mmf-om3'), + (3040, 'mmf-om4'), + (3500, 'smf'), + (3510, 'smf-os1'), + (3520, 'smf-os2'), + (3800, 'aoc'), + (5000, 'power'), +) + +CABLE_STATUS_CHOICES = ( + ('true', 'connected'), + ('false', 'planned'), +) + +CABLE_LENGTH_UNIT_CHOICES = ( + (1200, 'm'), + (1100, 'cm'), + (2100, 'ft'), + (2000, 'in'), +) + +POWERFEED_STATUS_CHOICES = ( + (0, 'offline'), + (1, 'active'), + (2, 'planned'), + (4, 'failed'), +) + +POWERFEED_TYPE_CHOICES = ( + (1, 'primary'), + (2, 'redundant'), +) + +POWERFEED_SUPPLY_CHOICES = ( + (1, 'ac'), + (2, 'dc'), +) + +POWERFEED_PHASE_CHOICES = ( + (1, 'single-phase'), + (3, 'three-phase'), +) + +POWEROUTLET_FEED_LEG_CHOICES_CHOICES = ( + (1, 'A'), + (2, 'B'), + (3, 'C'), +) + + +def cache_cable_devices(apps, schema_editor): + Cable = apps.get_model('dcim', 'Cable') + + if 'test' not in sys.argv: + print("\nUpdating cable device terminations...") + cable_count = Cable.objects.count() + + # Cache A/B termination devices on all existing Cables. Note that the custom save() method on Cable is not + # available during a migration, so we replicate its logic here. + for i, cable in enumerate(Cable.objects.all(), start=1): + + if not i % 1000 and 'test' not in sys.argv: + print("[{}/{}]".format(i, cable_count)) + + termination_a_model = apps.get_model(cable.termination_a_type.app_label, cable.termination_a_type.model) + termination_a_device = None + if hasattr(termination_a_model, 'device'): + termination_a = termination_a_model.objects.get(pk=cable.termination_a_id) + termination_a_device = termination_a.device + + termination_b_model = apps.get_model(cable.termination_b_type.app_label, cable.termination_b_type.model) + termination_b_device = None + if hasattr(termination_b_model, 'device'): + termination_b = termination_b_model.objects.get(pk=cable.termination_b_id) + termination_b_device = termination_b.device + + Cable.objects.filter(pk=cable.pk).update( + _termination_a_device=termination_a_device, + _termination_b_device=termination_b_device + ) + + +def site_status_to_slug(apps, schema_editor): + Site = apps.get_model('dcim', 'Site') + for id, slug in SITE_STATUS_CHOICES: + Site.objects.filter(status=str(id)).update(status=slug) + + +def rack_type_to_slug(apps, schema_editor): + Rack = apps.get_model('dcim', 'Rack') + for id, slug in RACK_TYPE_CHOICES: + Rack.objects.filter(type=str(id)).update(type=slug) + + +def rack_status_to_slug(apps, schema_editor): + Rack = apps.get_model('dcim', 'Rack') + for id, slug in RACK_STATUS_CHOICES: + Rack.objects.filter(status=str(id)).update(status=slug) + + +def rack_outer_unit_to_slug(apps, schema_editor): + Rack = apps.get_model('dcim', 'Rack') + for id, slug in RACK_DIMENSION_CHOICES: + Rack.objects.filter(status=str(id)).update(status=slug) + + +def devicetype_subdevicerole_to_slug(apps, schema_editor): + DeviceType = apps.get_model('dcim', 'DeviceType') + for boolean, slug in SUBDEVICE_ROLE_CHOICES: + DeviceType.objects.filter(subdevice_role=boolean).update(subdevice_role=slug) + + +def device_face_to_slug(apps, schema_editor): + Device = apps.get_model('dcim', 'Device') + for id, slug in DEVICE_FACE_CHOICES: + Device.objects.filter(face=str(id)).update(face=slug) + + +def device_status_to_slug(apps, schema_editor): + Device = apps.get_model('dcim', 'Device') + for id, slug in DEVICE_STATUS_CHOICES: + Device.objects.filter(status=str(id)).update(status=slug) + + +def interfacetemplate_type_to_slug(apps, schema_editor): + InterfaceTemplate = apps.get_model('dcim', 'InterfaceTemplate') + for id, slug in INTERFACE_TYPE_CHOICES: + InterfaceTemplate.objects.filter(type=id).update(type=slug) + + +def interface_type_to_slug(apps, schema_editor): + Interface = apps.get_model('dcim', 'Interface') + for id, slug in INTERFACE_TYPE_CHOICES: + Interface.objects.filter(type=id).update(type=slug) + + +def interface_mode_to_slug(apps, schema_editor): + Interface = apps.get_model('dcim', 'Interface') + for id, slug in INTERFACE_MODE_CHOICES: + Interface.objects.filter(mode=id).update(mode=slug) + + +def frontporttemplate_type_to_slug(apps, schema_editor): + FrontPortTemplate = apps.get_model('dcim', 'FrontPortTemplate') + for id, slug in PORT_TYPE_CHOICES: + FrontPortTemplate.objects.filter(type=id).update(type=slug) + + +def rearporttemplate_type_to_slug(apps, schema_editor): + RearPortTemplate = apps.get_model('dcim', 'RearPortTemplate') + for id, slug in PORT_TYPE_CHOICES: + RearPortTemplate.objects.filter(type=id).update(type=slug) + + +def frontport_type_to_slug(apps, schema_editor): + FrontPort = apps.get_model('dcim', 'FrontPort') + for id, slug in PORT_TYPE_CHOICES: + FrontPort.objects.filter(type=id).update(type=slug) + + +def rearport_type_to_slug(apps, schema_editor): + RearPort = apps.get_model('dcim', 'RearPort') + for id, slug in PORT_TYPE_CHOICES: + RearPort.objects.filter(type=id).update(type=slug) + + +def cable_type_to_slug(apps, schema_editor): + Cable = apps.get_model('dcim', 'Cable') + for id, slug in CABLE_TYPE_CHOICES: + Cable.objects.filter(type=id).update(type=slug) + + +def cable_status_to_slug(apps, schema_editor): + Cable = apps.get_model('dcim', 'Cable') + for bool_str, slug in CABLE_STATUS_CHOICES: + Cable.objects.filter(status=bool_str).update(status=slug) + + +def cable_length_unit_to_slug(apps, schema_editor): + Cable = apps.get_model('dcim', 'Cable') + for id, slug in CABLE_LENGTH_UNIT_CHOICES: + Cable.objects.filter(length_unit=id).update(length_unit=slug) + + +def powerfeed_status_to_slug(apps, schema_editor): + PowerFeed = apps.get_model('dcim', 'PowerFeed') + for id, slug in POWERFEED_STATUS_CHOICES: + PowerFeed.objects.filter(status=id).update(status=slug) + + +def powerfeed_type_to_slug(apps, schema_editor): + PowerFeed = apps.get_model('dcim', 'PowerFeed') + for id, slug in POWERFEED_TYPE_CHOICES: + PowerFeed.objects.filter(type=id).update(type=slug) + + +def powerfeed_supply_to_slug(apps, schema_editor): + PowerFeed = apps.get_model('dcim', 'PowerFeed') + for id, slug in POWERFEED_SUPPLY_CHOICES: + PowerFeed.objects.filter(supply=id).update(supply=slug) + + +def powerfeed_phase_to_slug(apps, schema_editor): + PowerFeed = apps.get_model('dcim', 'PowerFeed') + for id, slug in POWERFEED_PHASE_CHOICES: + PowerFeed.objects.filter(phase=id).update(phase=slug) + + +def poweroutlettemplate_feed_leg_to_slug(apps, schema_editor): + PowerOutletTemplate = apps.get_model('dcim', 'PowerOutletTemplate') + for id, slug in POWEROUTLET_FEED_LEG_CHOICES_CHOICES: + PowerOutletTemplate.objects.filter(feed_leg=id).update(feed_leg=slug) + + +def poweroutlet_feed_leg_to_slug(apps, schema_editor): + PowerOutlet = apps.get_model('dcim', 'PowerOutlet') + for id, slug in POWEROUTLET_FEED_LEG_CHOICES_CHOICES: + PowerOutlet.objects.filter(feed_leg=id).update(feed_leg=slug) + + +class Migration(migrations.Migration): + + replaces = [('dcim', '0071_device_components_add_description'), ('dcim', '0072_powerfeeds'), ('dcim', '0073_interface_form_factor_to_type'), ('dcim', '0074_increase_field_length_platform_name_slug'), ('dcim', '0075_cable_devices'), ('dcim', '0076_console_port_types'), ('dcim', '0077_power_types'), ('dcim', '0078_3569_site_fields'), ('dcim', '0079_3569_rack_fields'), ('dcim', '0080_3569_devicetype_fields'), ('dcim', '0081_3569_device_fields'), ('dcim', '0082_3569_interface_fields'), ('dcim', '0082_3569_port_fields'), ('dcim', '0083_3569_cable_fields'), ('dcim', '0084_3569_powerfeed_fields'), ('dcim', '0085_3569_poweroutlet_fields'), ('dcim', '0086_device_name_nonunique'), ('dcim', '0087_role_descriptions'), ('dcim', '0088_powerfeed_available_power')] + + dependencies = [ + ('dcim', '0070_custom_tag_models'), + ('extras', '0021_add_color_comments_changelog_to_tag'), + ('tenancy', '0006_custom_tag_models'), + ] + + operations = [ + migrations.AddField( + model_name='consoleport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='consoleserverport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='devicebay', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='poweroutlet', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='powerport', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.CreateModel( + name='PowerPanel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('name', models.CharField(max_length=50)), + ('rack_group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.RackGroup')), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='dcim.Site')), + ], + options={ + 'ordering': ['site', 'name'], + 'unique_together': {('site', 'name')}, + }, + ), + migrations.CreateModel( + name='PowerFeed', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('name', models.CharField(max_length=50)), + ('status', models.PositiveSmallIntegerField(default=1)), + ('type', models.PositiveSmallIntegerField(default=1)), + ('supply', models.PositiveSmallIntegerField(default=1)), + ('phase', models.PositiveSmallIntegerField(default=1)), + ('voltage', models.PositiveSmallIntegerField(default=120, validators=[django.core.validators.MinValueValidator(1)])), + ('amperage', models.PositiveSmallIntegerField(default=20, validators=[django.core.validators.MinValueValidator(1)])), + ('max_utilization', models.PositiveSmallIntegerField(default=80, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)])), + ('available_power', models.PositiveSmallIntegerField(default=0, editable=False)), + ('comments', models.TextField(blank=True)), + ('cable', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.Cable')), + ('power_panel', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='powerfeeds', to='dcim.PowerPanel')), + ('rack', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='dcim.Rack')), + ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags')), + ('connected_endpoint', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.PowerPort')), + ('connection_status', models.NullBooleanField()), + ], + options={ + 'ordering': ['power_panel', 'name'], + 'unique_together': {('power_panel', 'name')}, + }, + ), + migrations.RenameField( + model_name='powerport', + old_name='connected_endpoint', + new_name='_connected_poweroutlet', + ), + migrations.AddField( + model_name='powerport', + name='_connected_powerfeed', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='dcim.PowerFeed'), + ), + migrations.AddField( + model_name='powerport', + name='allocated_draw', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + ), + migrations.AddField( + model_name='powerport', + name='maximum_draw', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + ), + migrations.AddField( + model_name='powerporttemplate', + name='allocated_draw', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + ), + migrations.AddField( + model_name='powerporttemplate', + name='maximum_draw', + field=models.PositiveSmallIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]), + ), + migrations.AddField( + model_name='poweroutlet', + name='feed_leg', + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='poweroutlet', + name='power_port', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='poweroutlets', to='dcim.PowerPort'), + ), + migrations.AddField( + model_name='poweroutlettemplate', + name='feed_leg', + field=models.PositiveSmallIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='poweroutlettemplate', + name='power_port', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='poweroutlet_templates', to='dcim.PowerPortTemplate'), + ), + migrations.RenameField( + model_name='interface', + old_name='form_factor', + new_name='type', + ), + migrations.RenameField( + model_name='interfacetemplate', + old_name='form_factor', + new_name='type', + ), + migrations.AlterField( + model_name='platform', + name='name', + field=models.CharField(max_length=100, unique=True), + ), + migrations.AlterField( + model_name='platform', + name='slug', + field=models.SlugField(max_length=100, unique=True), + ), + migrations.AddField( + model_name='cable', + name='_termination_a_device', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.Device'), + ), + migrations.AddField( + model_name='cable', + name='_termination_b_device', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.Device'), + ), + migrations.RunPython( + code=cache_cable_devices, + reverse_code=django.db.migrations.operations.special.RunPython.noop, + ), + migrations.AddField( + model_name='consoleport', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='consoleporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='consoleserverport', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='consoleserverporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='poweroutlet', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='poweroutlettemplate', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='powerport', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='powerporttemplate', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='site', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=site_status_to_slug, + ), + migrations.AlterField( + model_name='rack', + name='type', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=rack_type_to_slug, + ), + migrations.AlterField( + model_name='rack', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='rack', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=rack_status_to_slug, + ), + migrations.AlterField( + model_name='rack', + name='outer_unit', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=rack_outer_unit_to_slug, + ), + migrations.AlterField( + model_name='rack', + name='outer_unit', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='devicetype', + name='subdevice_role', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=devicetype_subdevicerole_to_slug, + ), + migrations.AlterField( + model_name='devicetype', + name='subdevice_role', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='device', + name='face', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=device_face_to_slug, + ), + migrations.AlterField( + model_name='device', + name='face', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='device', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=device_status_to_slug, + ), + migrations.AlterField( + model_name='interfacetemplate', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=interfacetemplate_type_to_slug, + ), + migrations.AlterField( + model_name='interface', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=interface_type_to_slug, + ), + migrations.AlterField( + model_name='interface', + name='mode', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=interface_mode_to_slug, + ), + migrations.AlterField( + model_name='interface', + name='mode', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='frontporttemplate', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=frontporttemplate_type_to_slug, + ), + migrations.AlterField( + model_name='rearporttemplate', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=rearporttemplate_type_to_slug, + ), + migrations.AlterField( + model_name='frontport', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=frontport_type_to_slug, + ), + migrations.AlterField( + model_name='rearport', + name='type', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=rearport_type_to_slug, + ), + migrations.AlterField( + model_name='cable', + name='type', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=cable_type_to_slug, + ), + migrations.AlterField( + model_name='cable', + name='type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='cable', + name='status', + field=models.CharField(default='connected', max_length=50), + ), + migrations.RunPython( + code=cable_status_to_slug, + ), + migrations.AlterField( + model_name='cable', + name='length_unit', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=cable_length_unit_to_slug, + ), + migrations.AlterField( + model_name='cable', + name='length_unit', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='powerfeed', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=powerfeed_status_to_slug, + ), + migrations.AlterField( + model_name='powerfeed', + name='type', + field=models.CharField(default='primary', max_length=50), + ), + migrations.RunPython( + code=powerfeed_type_to_slug, + ), + migrations.AlterField( + model_name='powerfeed', + name='supply', + field=models.CharField(default='ac', max_length=50), + ), + migrations.RunPython( + code=powerfeed_supply_to_slug, + ), + migrations.AlterField( + model_name='powerfeed', + name='phase', + field=models.CharField(default='single-phase', max_length=50), + ), + migrations.RunPython( + code=powerfeed_phase_to_slug, + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='feed_leg', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=poweroutlettemplate_feed_leg_to_slug, + ), + migrations.AlterField( + model_name='poweroutlettemplate', + name='feed_leg', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='poweroutlet', + name='feed_leg', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=poweroutlet_feed_leg_to_slug, + ), + migrations.AlterField( + model_name='poweroutlet', + name='feed_leg', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='device', + name='name', + field=models.CharField(blank=True, max_length=64, null=True), + ), + migrations.AlterUniqueTogether( + name='device', + unique_together={('rack', 'position', 'face'), ('site', 'tenant', 'name'), ('virtual_chassis', 'vc_position')}, + ), + migrations.AddField( + model_name='devicerole', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AddField( + model_name='rackrole', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AlterField( + model_name='powerfeed', + name='available_power', + field=models.PositiveIntegerField(default=0, editable=False), + ), + ] diff --git a/netbox/extras/migrations/0001_initial_squashed_0013_objectchange.py b/netbox/extras/migrations/0001_initial_squashed_0013_objectchange.py new file mode 100644 index 000000000..112a8c9af --- /dev/null +++ b/netbox/extras/migrations/0001_initial_squashed_0013_objectchange.py @@ -0,0 +1,265 @@ +import django.contrib.postgres.fields.jsonb +import django.db.models.deletion +from django.conf import settings +from django.db import connection, migrations, models +from django.db.utils import OperationalError + +import extras.models + + +def verify_postgresql_version(apps, schema_editor): + """ + Verify that PostgreSQL is version 9.4 or higher. + """ + # https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSERVERVERSION + DB_MINIMUM_VERSION = 90400 # 9.4.0 + + try: + pg_version = connection.pg_version + + if pg_version < DB_MINIMUM_VERSION: + raise Exception("PostgreSQL 9.4.0 ({}) or higher is required ({} found). Upgrade PostgreSQL and then run migrations again.".format(DB_MINIMUM_VERSION, pg_version)) + + # Skip if the database is missing (e.g. for CI testing) or misconfigured. + except OperationalError: + pass + + +def is_filterable_to_filter_logic(apps, schema_editor): + CustomField = apps.get_model('extras', 'CustomField') + CustomField.objects.filter(is_filterable=False).update(filter_logic=0) + CustomField.objects.filter(is_filterable=True).update(filter_logic=1) + # Select fields match on primary key only + CustomField.objects.filter(is_filterable=True, type=600).update(filter_logic=2) + + +class Migration(migrations.Migration): + + replaces = [('extras', '0001_initial'), ('extras', '0002_custom_fields'), ('extras', '0003_exporttemplate_add_description'), ('extras', '0004_topologymap_change_comma_to_semicolon'), ('extras', '0005_useraction_add_bulk_create'), ('extras', '0006_add_imageattachments'), ('extras', '0007_unicode_literals'), ('extras', '0008_reports'), ('extras', '0009_topologymap_type'), ('extras', '0010_customfield_filter_logic'), ('extras', '0011_django2'), ('extras', '0012_webhooks'), ('extras', '0013_objectchange')] + + dependencies = [ + ('dcim', '0002_auto_20160622_1821'), + ('contenttypes', '0002_remove_content_type_name'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='CustomField', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.PositiveSmallIntegerField(choices=[(100, 'Text'), (200, 'Integer'), (300, 'Boolean (true/false)'), (400, 'Date'), (500, 'URL'), (600, 'Selection')], default=100)), + ('name', models.CharField(max_length=50, unique=True)), + ('label', models.CharField(blank=True, help_text="Name of the field as displayed to users (if not provided, the field's name will be used)", max_length=50)), + ('description', models.CharField(blank=True, max_length=100)), + ('required', models.BooleanField(default=False, help_text='Determines whether this field is required when creating new objects or editing an existing object.')), + ('is_filterable', models.BooleanField(default=True, help_text='This field can be used to filter objects.')), + ('default', models.CharField(blank=True, help_text='Default value for the field. Use "true" or "false" for booleans.', max_length=100)), + ('weight', models.PositiveSmallIntegerField(default=100, help_text='Fields with higher weights appear lower in a form')), + ('obj_type', models.ManyToManyField(help_text='The object(s) to which this field applies.', related_name='custom_fields', to='contenttypes.ContentType', verbose_name='Object(s)')), + ], + options={ + 'ordering': ['weight', 'name'], + }, + ), + migrations.CreateModel( + name='CustomFieldValue', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('obj_id', models.PositiveIntegerField()), + ('serialized_value', models.CharField(max_length=255)), + ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='values', to='extras.CustomField')), + ('obj_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType')), + ], + options={ + 'ordering': ['obj_type', 'obj_id'], + 'unique_together': {('field', 'obj_type', 'obj_id')}, + }, + ), + migrations.CreateModel( + name='ExportTemplate', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100)), + ('template_code', models.TextField()), + ('mime_type', models.CharField(blank=True, max_length=15)), + ('file_extension', models.CharField(blank=True, max_length=15)), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ('description', models.CharField(blank=True, max_length=200)), + ], + options={ + 'ordering': ['content_type', 'name'], + 'unique_together': {('content_type', 'name')}, + }, + ), + migrations.CreateModel( + name='CustomFieldChoice', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('value', models.CharField(max_length=100)), + ('weight', models.PositiveSmallIntegerField(default=100, help_text='Higher weights appear lower in the list')), + ('field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='extras.CustomField')), + ], + options={ + 'ordering': ['field', 'weight', 'value'], + 'unique_together': {('field', 'value')}, + }, + ), + migrations.CreateModel( + name='Graph', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('type', models.PositiveSmallIntegerField(choices=[(100, 'Interface'), (200, 'Provider'), (300, 'Site')])), + ('weight', models.PositiveSmallIntegerField(default=1000)), + ('name', models.CharField(max_length=100, verbose_name='Name')), + ('source', models.CharField(max_length=500, verbose_name='Source URL')), + ('link', models.URLField(blank=True, verbose_name='Link URL')), + ], + options={ + 'ordering': ['type', 'weight', 'name'], + }, + ), + migrations.CreateModel( + name='ImageAttachment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('object_id', models.PositiveIntegerField()), + ('image', models.ImageField(height_field='image_height', upload_to=extras.models.image_upload, width_field='image_width')), + ('image_height', models.PositiveSmallIntegerField()), + ('image_width', models.PositiveSmallIntegerField()), + ('name', models.CharField(blank=True, max_length=50)), + ('created', models.DateTimeField(auto_now_add=True)), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='TopologyMap', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('device_patterns', models.TextField(help_text='Identify devices to include in the diagram using regular expressions, one per line. Each line will result in a new tier of the drawing. Separate multiple regexes within a line using semicolons. Devices will be rendered in the order they are defined.')), + ('description', models.CharField(blank=True, max_length=100)), + ('site', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='topology_maps', to='dcim.Site')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='UserAction', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('time', models.DateTimeField(auto_now_add=True)), + ('object_id', models.PositiveIntegerField(blank=True, null=True)), + ('action', models.PositiveSmallIntegerField(choices=[(1, 'created'), (7, 'bulk created'), (2, 'imported'), (3, 'modified'), (4, 'bulk edited'), (5, 'deleted'), (6, 'bulk deleted')])), + ('message', models.TextField(blank=True)), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='actions', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-time'], + }, + ), + migrations.RunPython( + code=verify_postgresql_version, + ), + migrations.CreateModel( + name='ReportResult', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('report', models.CharField(max_length=255, unique=True)), + ('created', models.DateTimeField(auto_now_add=True)), + ('failed', models.BooleanField()), + ('data', django.contrib.postgres.fields.jsonb.JSONField()), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['report'], + }, + ), + migrations.AddField( + model_name='topologymap', + name='type', + field=models.PositiveSmallIntegerField(choices=[(1, 'Network'), (2, 'Console'), (3, 'Power')], default=1), + ), + migrations.AddField( + model_name='customfield', + name='filter_logic', + field=models.PositiveSmallIntegerField(choices=[(0, 'Disabled'), (1, 'Loose'), (2, 'Exact')], default=1, help_text='Loose matches any instance of a given string; exact matches the entire field.'), + ), + migrations.AlterField( + model_name='customfield', + name='required', + field=models.BooleanField(default=False, help_text='If true, this field is required when creating new objects or editing an existing object.'), + ), + migrations.AlterField( + model_name='customfield', + name='weight', + field=models.PositiveSmallIntegerField(default=100, help_text='Fields with higher weights appear lower in a form.'), + ), + migrations.RunPython( + code=is_filterable_to_filter_logic, + ), + migrations.RemoveField( + model_name='customfield', + name='is_filterable', + ), + migrations.AlterField( + model_name='customfield', + name='obj_type', + field=models.ManyToManyField(help_text='The object(s) to which this field applies.', limit_choices_to={'model__in': ('provider', 'circuit', 'site', 'rack', 'devicetype', 'device', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'tenant', 'cluster', 'virtualmachine')}, related_name='custom_fields', to='contenttypes.ContentType', verbose_name='Object(s)'), + ), + migrations.AlterField( + model_name='customfieldchoice', + name='field', + field=models.ForeignKey(limit_choices_to={'type': 600}, on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='extras.CustomField'), + ), + migrations.AlterField( + model_name='exporttemplate', + name='content_type', + field=models.ForeignKey(limit_choices_to={'model__in': ['provider', 'circuit', 'site', 'region', 'rack', 'rackgroup', 'manufacturer', 'devicetype', 'device', 'consoleport', 'powerport', 'interfaceconnection', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'tenant', 'cluster', 'virtualmachine']}, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.CreateModel( + name='Webhook', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=150, unique=True)), + ('type_create', models.BooleanField(default=False, help_text='Call this webhook when a matching object is created.')), + ('type_update', models.BooleanField(default=False, help_text='Call this webhook when a matching object is updated.')), + ('type_delete', models.BooleanField(default=False, help_text='Call this webhook when a matching object is deleted.')), + ('payload_url', models.CharField(help_text='A POST will be sent to this URL when the webhook is called.', max_length=500, verbose_name='URL')), + ('http_content_type', models.PositiveSmallIntegerField(choices=[(1, 'application/json'), (2, 'application/x-www-form-urlencoded')], default=1, verbose_name='HTTP content type')), + ('secret', models.CharField(blank=True, help_text="When provided, the request will include a 'X-Hook-Signature' header containing a HMAC hex digest of the payload body using the secret as the key. The secret is not transmitted in the request.", max_length=255)), + ('enabled', models.BooleanField(default=True)), + ('ssl_verification', models.BooleanField(default=True, help_text='Enable SSL certificate verification. Disable with caution!', verbose_name='SSL verification')), + ('obj_type', models.ManyToManyField(help_text='The object(s) to which this Webhook applies.', related_name='webhooks', to='contenttypes.ContentType', verbose_name='Object types')), + ], + options={ + 'unique_together': {('payload_url', 'type_create', 'type_update', 'type_delete')}, + }, + ), + migrations.CreateModel( + name='ObjectChange', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('time', models.DateTimeField(auto_now_add=True)), + ('user_name', models.CharField(editable=False, max_length=150)), + ('request_id', models.UUIDField(editable=False)), + ('action', models.PositiveSmallIntegerField(choices=[(1, 'Created'), (2, 'Updated'), (3, 'Deleted')])), + ('changed_object_id', models.PositiveIntegerField()), + ('related_object_id', models.PositiveIntegerField(blank=True, null=True)), + ('object_repr', models.CharField(editable=False, max_length=200)), + ('object_data', django.contrib.postgres.fields.jsonb.JSONField(editable=False)), + ('changed_object_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType')), + ('related_object_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='contenttypes.ContentType')), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='changes', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['-time'], + }, + ), + ] diff --git a/netbox/extras/migrations/0014_configcontexts_squashed_0019_tag_taggeditem.py b/netbox/extras/migrations/0014_configcontexts_squashed_0019_tag_taggeditem.py new file mode 100644 index 000000000..6f8b63649 --- /dev/null +++ b/netbox/extras/migrations/0014_configcontexts_squashed_0019_tag_taggeditem.py @@ -0,0 +1,106 @@ +import django.contrib.postgres.fields.jsonb +import django.db.models.deletion +from django.db import migrations, models + + +def set_template_language(apps, schema_editor): + """ + Set the language for all existing ExportTemplates to Django (Jinja2 is the default for new ExportTemplates). + """ + ExportTemplate = apps.get_model('extras', 'ExportTemplate') + ExportTemplate.objects.update(template_language=10) + + +class Migration(migrations.Migration): + + replaces = [('extras', '0014_configcontexts'), ('extras', '0015_remove_useraction'), ('extras', '0016_exporttemplate_add_cable'), ('extras', '0017_exporttemplate_mime_type_length'), ('extras', '0018_exporttemplate_add_jinja2'), ('extras', '0019_tag_taggeditem')] + + dependencies = [ + ('extras', '0013_objectchange'), + ('tenancy', '0005_change_logging'), + ('dcim', '0061_platform_napalm_args'), + ('contenttypes', '0002_remove_content_type_name'), + ] + + operations = [ + migrations.CreateModel( + name='ConfigContext', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=100, unique=True)), + ('weight', models.PositiveSmallIntegerField(default=1000)), + ('description', models.CharField(blank=True, max_length=100)), + ('is_active', models.BooleanField(default=True)), + ('data', django.contrib.postgres.fields.jsonb.JSONField()), + ('platforms', models.ManyToManyField(blank=True, related_name='_configcontext_platforms_+', to='dcim.Platform')), + ('regions', models.ManyToManyField(blank=True, related_name='_configcontext_regions_+', to='dcim.Region')), + ('roles', models.ManyToManyField(blank=True, related_name='_configcontext_roles_+', to='dcim.DeviceRole')), + ('sites', models.ManyToManyField(blank=True, related_name='_configcontext_sites_+', to='dcim.Site')), + ('tenant_groups', models.ManyToManyField(blank=True, related_name='_configcontext_tenant_groups_+', to='tenancy.TenantGroup')), + ('tenants', models.ManyToManyField(blank=True, related_name='_configcontext_tenants_+', to='tenancy.Tenant')), + ], + options={ + 'ordering': ['weight', 'name'], + }, + ), + migrations.AlterField( + model_name='customfield', + name='obj_type', + field=models.ManyToManyField(help_text='The object(s) to which this field applies.', limit_choices_to={'model__in': ('provider', 'circuit', 'site', 'rack', 'devicetype', 'device', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service', 'secret', 'tenant', 'cluster', 'virtualmachine')}, related_name='custom_fields', to='contenttypes.ContentType', verbose_name='Object(s)'), + ), + migrations.AlterField( + model_name='exporttemplate', + name='content_type', + field=models.ForeignKey(limit_choices_to={'model__in': ['provider', 'circuit', 'site', 'region', 'rack', 'rackgroup', 'manufacturer', 'devicetype', 'device', 'consoleport', 'powerport', 'interfaceconnection', 'virtualchassis', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service', 'secret', 'tenant', 'cluster', 'virtualmachine']}, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AlterField( + model_name='webhook', + name='obj_type', + field=models.ManyToManyField(help_text='The object(s) to which this Webhook applies.', limit_choices_to={'model__in': ('provider', 'circuit', 'site', 'rack', 'devicetype', 'device', 'virtualchassis', 'consoleport', 'consoleserverport', 'powerport', 'poweroutlet', 'interface', 'devicebay', 'inventoryitem', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service', 'secret', 'tenant', 'cluster', 'virtualmachine')}, related_name='webhooks', to='contenttypes.ContentType', verbose_name='Object types'), + ), + migrations.DeleteModel( + name='UserAction', + ), + migrations.AlterField( + model_name='exporttemplate', + name='content_type', + field=models.ForeignKey(limit_choices_to={'model__in': ['provider', 'circuit', 'site', 'region', 'rack', 'rackgroup', 'manufacturer', 'devicetype', 'device', 'consoleport', 'powerport', 'interface', 'cable', 'virtualchassis', 'aggregate', 'prefix', 'ipaddress', 'vlan', 'vrf', 'service', 'secret', 'tenant', 'cluster', 'virtualmachine']}, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AlterField( + model_name='exporttemplate', + name='mime_type', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AddField( + model_name='exporttemplate', + name='template_language', + field=models.PositiveSmallIntegerField(default=20), + ), + migrations.RunPython( + code=set_template_language, + ), + migrations.CreateModel( + name='Tag', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100, unique=True)), + ('slug', models.SlugField(max_length=100, unique=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TaggedItem', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('object_id', models.IntegerField(db_index=True)), + ('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='extras_taggeditem_tagged_items', to='contenttypes.ContentType')), + ('tag', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='extras_taggeditem_items', to='extras.Tag')), + ], + options={ + 'abstract': False, + 'index_together': {('content_type', 'object_id')}, + }, + ), + ] diff --git a/netbox/extras/migrations/0020_tag_data_squashed_0021_add_color_comments_changelog_to_tag.py b/netbox/extras/migrations/0020_tag_data_squashed_0021_add_color_comments_changelog_to_tag.py new file mode 100644 index 000000000..a673bf880 --- /dev/null +++ b/netbox/extras/migrations/0020_tag_data_squashed_0021_add_color_comments_changelog_to_tag.py @@ -0,0 +1,93 @@ +from django.db import migrations, models + +import utilities.fields + + +def copy_tags(apps, schema_editor): + """ + Copy data from taggit_tag to extras_tag + """ + TaggitTag = apps.get_model('taggit', 'Tag') + ExtrasTag = apps.get_model('extras', 'Tag') + + tags_values = TaggitTag.objects.all().values('id', 'name', 'slug') + tags = [ExtrasTag(**tag) for tag in tags_values] + ExtrasTag.objects.bulk_create(tags) + + +def copy_taggeditems(apps, schema_editor): + """ + Copy data from taggit_taggeditem to extras_taggeditem + """ + TaggitTaggedItem = apps.get_model('taggit', 'TaggedItem') + ExtrasTaggedItem = apps.get_model('extras', 'TaggedItem') + + tagged_items_values = TaggitTaggedItem.objects.all().values('id', 'object_id', 'content_type_id', 'tag_id') + tagged_items = [ExtrasTaggedItem(**tagged_item) for tagged_item in tagged_items_values] + ExtrasTaggedItem.objects.bulk_create(tagged_items) + + +def delete_taggit_taggeditems(apps, schema_editor): + """ + Delete all TaggedItem instances from taggit_taggeditem + """ + TaggitTaggedItem = apps.get_model('taggit', 'TaggedItem') + TaggitTaggedItem.objects.all().delete() + + +def delete_taggit_tags(apps, schema_editor): + """ + Delete all Tag instances from taggit_tag + """ + TaggitTag = apps.get_model('taggit', 'Tag') + TaggitTag.objects.all().delete() + + +class Migration(migrations.Migration): + + replaces = [('extras', '0020_tag_data'), ('extras', '0021_add_color_comments_changelog_to_tag')] + + dependencies = [ + ('extras', '0019_tag_taggeditem'), + ('virtualization', '0009_custom_tag_models'), + ('tenancy', '0006_custom_tag_models'), + ('secrets', '0006_custom_tag_models'), + ('dcim', '0070_custom_tag_models'), + ('ipam', '0025_custom_tag_models'), + ('circuits', '0015_custom_tag_models'), + ] + + operations = [ + migrations.RunPython( + code=copy_tags, + ), + migrations.RunPython( + code=copy_taggeditems, + ), + migrations.RunPython( + code=delete_taggit_taggeditems, + ), + migrations.RunPython( + code=delete_taggit_tags, + ), + migrations.AddField( + model_name='tag', + name='color', + field=utilities.fields.ColorField(default='9e9e9e', max_length=6), + ), + migrations.AddField( + model_name='tag', + name='comments', + field=models.TextField(blank=True, default=''), + ), + migrations.AddField( + model_name='tag', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='tag', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + ] diff --git a/netbox/extras/migrations/0022_custom_links_squashed_0034_configcontext_tags.py b/netbox/extras/migrations/0022_custom_links_squashed_0034_configcontext_tags.py new file mode 100644 index 000000000..4a591efa0 --- /dev/null +++ b/netbox/extras/migrations/0022_custom_links_squashed_0034_configcontext_tags.py @@ -0,0 +1,227 @@ +import django.contrib.postgres.fields.jsonb +import django.db.models.deletion +from django.db import migrations, models + +import extras.models + +CUSTOMFIELD_TYPE_CHOICES = ( + (100, 'text'), + (200, 'integer'), + (300, 'boolean'), + (400, 'date'), + (500, 'url'), + (600, 'select') +) + +CUSTOMFIELD_FILTER_LOGIC_CHOICES = ( + (0, 'disabled'), + (1, 'integer'), + (2, 'exact'), +) + +OBJECTCHANGE_ACTION_CHOICES = ( + (1, 'create'), + (2, 'update'), + (3, 'delete'), +) + +EXPORTTEMPLATE_LANGUAGE_CHOICES = ( + (10, 'django'), + (20, 'jinja2'), +) + +WEBHOOK_CONTENTTYPE_CHOICES = ( + (1, 'application/json'), + (2, 'application/x-www-form-urlencoded'), +) + +GRAPH_TYPE_CHOICES = ( + (100, 'dcim', 'interface'), + (150, 'dcim', 'device'), + (200, 'circuits', 'provider'), + (300, 'dcim', 'site'), +) + + +def customfield_type_to_slug(apps, schema_editor): + CustomField = apps.get_model('extras', 'CustomField') + for id, slug in CUSTOMFIELD_TYPE_CHOICES: + CustomField.objects.filter(type=str(id)).update(type=slug) + + +def customfield_filter_logic_to_slug(apps, schema_editor): + CustomField = apps.get_model('extras', 'CustomField') + for id, slug in CUSTOMFIELD_FILTER_LOGIC_CHOICES: + CustomField.objects.filter(filter_logic=str(id)).update(filter_logic=slug) + + +def objectchange_action_to_slug(apps, schema_editor): + ObjectChange = apps.get_model('extras', 'ObjectChange') + for id, slug in OBJECTCHANGE_ACTION_CHOICES: + ObjectChange.objects.filter(action=str(id)).update(action=slug) + + +def exporttemplate_language_to_slug(apps, schema_editor): + ExportTemplate = apps.get_model('extras', 'ExportTemplate') + for id, slug in EXPORTTEMPLATE_LANGUAGE_CHOICES: + ExportTemplate.objects.filter(template_language=str(id)).update(template_language=slug) + + +def webhook_contenttype_to_slug(apps, schema_editor): + Webhook = apps.get_model('extras', 'Webhook') + for id, slug in WEBHOOK_CONTENTTYPE_CHOICES: + Webhook.objects.filter(http_content_type=str(id)).update(http_content_type=slug) + + +def graph_type_to_fk(apps, schema_editor): + Graph = apps.get_model('extras', 'Graph') + ContentType = apps.get_model('contenttypes', 'ContentType') + + # On a new installation (and during tests) content types might not yet exist. So, we only perform the bulk + # updates if a Graph has been created, which implies that we're working with a populated database. + if Graph.objects.exists(): + for id, app_label, model in GRAPH_TYPE_CHOICES: + content_type = ContentType.objects.get(app_label=app_label, model=model) + Graph.objects.filter(type=id).update(type=content_type.pk) + + +class Migration(migrations.Migration): + + replaces = [('extras', '0022_custom_links'), ('extras', '0023_fix_tag_sequences'), ('extras', '0024_scripts'), ('extras', '0025_objectchange_time_index'), ('extras', '0026_webhook_ca_file_path'), ('extras', '0027_webhook_additional_headers'), ('extras', '0028_remove_topology_maps'), ('extras', '0029_3569_customfield_fields'), ('extras', '0030_3569_objectchange_fields'), ('extras', '0031_3569_exporttemplate_fields'), ('extras', '0032_3569_webhook_fields'), ('extras', '0033_graph_type_template_language'), ('extras', '0034_configcontext_tags')] + + dependencies = [ + ('extras', '0021_add_color_comments_changelog_to_tag'), + ('contenttypes', '0002_remove_content_type_name'), + ] + + operations = [ + migrations.CreateModel( + name='CustomLink', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100, unique=True)), + ('text', models.CharField(max_length=500)), + ('url', models.CharField(max_length=500)), + ('weight', models.PositiveSmallIntegerField(default=100)), + ('group_name', models.CharField(blank=True, max_length=50)), + ('button_class', models.CharField(default='default', max_length=30)), + ('new_window', models.BooleanField()), + ('content_type', models.ForeignKey(limit_choices_to=extras.models.get_custom_link_models, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), + ], + options={ + 'ordering': ['group_name', 'weight', 'name'], + }, + ), + migrations.AlterField( + model_name='customfield', + name='obj_type', + field=models.ManyToManyField(limit_choices_to=extras.models.get_custom_field_models, related_name='custom_fields', to='contenttypes.ContentType'), + ), + migrations.AlterField( + model_name='exporttemplate', + name='content_type', + field=models.ForeignKey(limit_choices_to=extras.models.get_export_template_models, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AlterField( + model_name='webhook', + name='obj_type', + field=models.ManyToManyField(limit_choices_to=extras.models.get_webhook_models, related_name='webhooks', to='contenttypes.ContentType'), + ), + migrations.RunSQL( + sql="SELECT setval('extras_tag_id_seq', (SELECT id FROM extras_tag ORDER BY id DESC LIMIT 1) + 1)", + ), + migrations.RunSQL( + sql="SELECT setval('extras_taggeditem_id_seq', (SELECT id FROM extras_taggeditem ORDER BY id DESC LIMIT 1) + 1)", + ), + migrations.CreateModel( + name='Script', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False)), + ], + options={ + 'permissions': (('run_script', 'Can run script'),), + 'managed': False, + }, + ), + migrations.AlterField( + model_name='objectchange', + name='time', + field=models.DateTimeField(auto_now_add=True, db_index=True), + ), + migrations.AddField( + model_name='webhook', + name='ca_file_path', + field=models.CharField(blank=True, max_length=4096, null=True), + ), + migrations.AddField( + model_name='webhook', + name='additional_headers', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), + ), + migrations.DeleteModel( + name='TopologyMap', + ), + migrations.AlterField( + model_name='customfield', + name='type', + field=models.CharField(default='text', max_length=50), + ), + migrations.RunPython( + code=customfield_type_to_slug, + ), + migrations.AlterField( + model_name='customfieldchoice', + name='field', + field=models.ForeignKey(limit_choices_to={'type': 'select'}, on_delete=django.db.models.deletion.CASCADE, related_name='choices', to='extras.CustomField'), + ), + migrations.AlterField( + model_name='customfield', + name='filter_logic', + field=models.CharField(default='loose', max_length=50), + ), + migrations.RunPython( + code=customfield_filter_logic_to_slug, + ), + migrations.AlterField( + model_name='objectchange', + name='action', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=objectchange_action_to_slug, + ), + migrations.AlterField( + model_name='exporttemplate', + name='template_language', + field=models.CharField(default='jinja2', max_length=50), + ), + migrations.RunPython( + code=exporttemplate_language_to_slug, + ), + migrations.AlterField( + model_name='webhook', + name='http_content_type', + field=models.CharField(default='application/json', max_length=50), + ), + migrations.RunPython( + code=webhook_contenttype_to_slug, + ), + migrations.RunPython( + code=graph_type_to_fk, + ), + migrations.AlterField( + model_name='graph', + name='type', + field=models.ForeignKey(limit_choices_to={'model__in': ['provider', 'device', 'interface', 'site']}, on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType'), + ), + migrations.AddField( + model_name='graph', + name='template_language', + field=models.CharField(default='jinja2', max_length=50), + ), + migrations.AddField( + model_name='configcontext', + name='tags', + field=models.ManyToManyField(blank=True, related_name='_configcontext_tags_+', to='extras.Tag'), + ), + ] diff --git a/netbox/ipam/migrations/0003_ipam_add_vlangroups_squashed_0011_rir_add_is_private.py b/netbox/ipam/migrations/0003_ipam_add_vlangroups_squashed_0011_rir_add_is_private.py new file mode 100644 index 000000000..c3b86135c --- /dev/null +++ b/netbox/ipam/migrations/0003_ipam_add_vlangroups_squashed_0011_rir_add_is_private.py @@ -0,0 +1,100 @@ +import django.db.models.deletion +from django.db import migrations, models + +import ipam.fields + + +class Migration(migrations.Migration): + + replaces = [('ipam', '0003_ipam_add_vlangroups'), ('ipam', '0004_ipam_vlangroup_uniqueness'), ('ipam', '0005_auto_20160725_1842'), ('ipam', '0006_vrf_vlan_add_tenant'), ('ipam', '0007_prefix_ipaddress_add_tenant'), ('ipam', '0008_prefix_change_order'), ('ipam', '0009_ipaddress_add_status'), ('ipam', '0010_ipaddress_help_texts'), ('ipam', '0011_rir_add_is_private')] + + dependencies = [ + ('tenancy', '0001_initial'), + ('dcim', '0010_devicebay_installed_device_set_null'), + ('ipam', '0002_vrf_add_enforce_unique'), + ] + + operations = [ + migrations.CreateModel( + name='VLANGroup', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('slug', models.SlugField()), + ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='vlan_groups', to='dcim.Site')), + ], + options={ + 'ordering': ['site', 'name'], + 'unique_together': {('site', 'name'), ('site', 'slug')}, + 'verbose_name': 'VLAN group', + 'verbose_name_plural': 'VLAN groups', + }, + ), + migrations.AddField( + model_name='vlan', + name='group', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='ipam.VLANGroup'), + ), + migrations.AlterModelOptions( + name='vlan', + options={'ordering': ['site', 'group', 'vid'], 'verbose_name': 'VLAN', 'verbose_name_plural': 'VLANs'}, + ), + migrations.AlterUniqueTogether( + name='vlan', + unique_together={('group', 'vid'), ('group', 'name')}, + ), + migrations.AddField( + model_name='vlan', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + migrations.AlterField( + model_name='vlan', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AddField( + model_name='vlan', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='tenancy.Tenant'), + ), + migrations.AddField( + model_name='vrf', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vrfs', to='tenancy.Tenant'), + ), + migrations.AddField( + model_name='ipaddress', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_addresses', to='tenancy.Tenant'), + ), + migrations.AddField( + model_name='prefix', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='tenancy.Tenant'), + ), + migrations.AlterModelOptions( + name='prefix', + options={'ordering': ['vrf', 'family', 'prefix'], 'verbose_name_plural': 'prefixes'}, + ), + migrations.AddField( + model_name='ipaddress', + name='status', + field=models.PositiveSmallIntegerField(choices=[(1, b'Active'), (2, b'Reserved'), (5, b'DHCP')], default=1, verbose_name=b'Status'), + ), + migrations.AlterField( + model_name='ipaddress', + name='address', + field=ipam.fields.IPAddressField(help_text=b'IPv4 or IPv6 address (with mask)'), + ), + migrations.AlterField( + model_name='ipaddress', + name='nat_inside', + field=models.OneToOneField(blank=True, help_text=b'The IP for which this address is the "outside" IP', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nat_outside', to='ipam.IPAddress', verbose_name=b'NAT (Inside)'), + ), + migrations.AddField( + model_name='rir', + name='is_private', + field=models.BooleanField(default=False, help_text=b'IP space managed by this RIR is considered private', verbose_name=b'Private'), + ), + ] diff --git a/netbox/ipam/migrations/0012_services_squashed_0018_remove_service_uniqueness_constraint.py b/netbox/ipam/migrations/0012_services_squashed_0018_remove_service_uniqueness_constraint.py new file mode 100644 index 000000000..6bc5020d4 --- /dev/null +++ b/netbox/ipam/migrations/0012_services_squashed_0018_remove_service_uniqueness_constraint.py @@ -0,0 +1,171 @@ +import django.core.validators +import django.db.models.deletion +from django.db import migrations, models + +import ipam.fields + + +class Migration(migrations.Migration): + + replaces = [('ipam', '0012_services'), ('ipam', '0013_prefix_add_is_pool'), ('ipam', '0014_ipaddress_status_add_deprecated'), ('ipam', '0015_global_vlans'), ('ipam', '0016_unicode_literals'), ('ipam', '0017_ipaddress_roles'), ('ipam', '0018_remove_service_uniqueness_constraint')] + + dependencies = [ + ('dcim', '0022_color_names_to_rgb'), + ('ipam', '0011_rir_add_is_private'), + ] + + operations = [ + migrations.AlterField( + model_name='prefix', + name='prefix', + field=ipam.fields.IPNetworkField(help_text=b'IPv4 or IPv6 network with mask'), + ), + migrations.AlterField( + model_name='prefix', + name='role', + field=models.ForeignKey(blank=True, help_text=b'The primary function of this prefix', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prefixes', to='ipam.Role'), + ), + migrations.AlterField( + model_name='prefix', + name='status', + field=models.PositiveSmallIntegerField(choices=[(0, b'Container'), (1, b'Active'), (2, b'Reserved'), (3, b'Deprecated')], default=1, help_text=b'Operational status of this prefix', verbose_name=b'Status'), + ), + migrations.AlterField( + model_name='ipaddress', + name='status', + field=models.PositiveSmallIntegerField(choices=[(1, b'Active'), (2, b'Reserved'), (3, b'Deprecated'), (5, b'DHCP')], default=1, verbose_name=b'Status'), + ), + migrations.AlterField( + model_name='vlan', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlans', to='dcim.Site'), + ), + migrations.AlterField( + model_name='vlangroup', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlan_groups', to='dcim.Site'), + ), + migrations.AlterField( + model_name='aggregate', + name='family', + field=models.PositiveSmallIntegerField(choices=[(4, 'IPv4'), (6, 'IPv6')]), + ), + migrations.AlterField( + model_name='aggregate', + name='rir', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='aggregates', to='ipam.RIR', verbose_name='RIR'), + ), + migrations.AlterField( + model_name='ipaddress', + name='address', + field=ipam.fields.IPAddressField(help_text='IPv4 or IPv6 address (with mask)'), + ), + migrations.AlterField( + model_name='ipaddress', + name='family', + field=models.PositiveSmallIntegerField(choices=[(4, 'IPv4'), (6, 'IPv6')], editable=False), + ), + migrations.AlterField( + model_name='ipaddress', + name='nat_inside', + field=models.OneToOneField(blank=True, help_text='The IP for which this address is the "outside" IP', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='nat_outside', to='ipam.IPAddress', verbose_name='NAT (Inside)'), + ), + migrations.AlterField( + model_name='ipaddress', + name='status', + field=models.PositiveSmallIntegerField(choices=[(1, 'Active'), (2, 'Reserved'), (3, 'Deprecated'), (5, 'DHCP')], default=1, verbose_name='Status'), + ), + migrations.AlterField( + model_name='ipaddress', + name='vrf', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='ip_addresses', to='ipam.VRF', verbose_name='VRF'), + ), + migrations.AlterField( + model_name='prefix', + name='family', + field=models.PositiveSmallIntegerField(choices=[(4, 'IPv4'), (6, 'IPv6')], editable=False), + ), + migrations.AddField( + model_name='prefix', + name='is_pool', + field=models.BooleanField(default=False, help_text='All IP addresses within this prefix are considered usable', verbose_name='Is a pool'), + ), + migrations.AlterField( + model_name='prefix', + name='prefix', + field=ipam.fields.IPNetworkField(help_text='IPv4 or IPv6 network with mask'), + ), + migrations.AlterField( + model_name='prefix', + name='role', + field=models.ForeignKey(blank=True, help_text='The primary function of this prefix', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prefixes', to='ipam.Role'), + ), + migrations.AlterField( + model_name='prefix', + name='status', + field=models.PositiveSmallIntegerField(choices=[(0, 'Container'), (1, 'Active'), (2, 'Reserved'), (3, 'Deprecated')], default=1, help_text='Operational status of this prefix', verbose_name='Status'), + ), + migrations.AlterField( + model_name='prefix', + name='vlan', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='ipam.VLAN', verbose_name='VLAN'), + ), + migrations.AlterField( + model_name='prefix', + name='vrf', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='prefixes', to='ipam.VRF', verbose_name='VRF'), + ), + migrations.AlterField( + model_name='rir', + name='is_private', + field=models.BooleanField(default=False, help_text='IP space managed by this RIR is considered private', verbose_name='Private'), + ), + migrations.AlterField( + model_name='vlan', + name='status', + field=models.PositiveSmallIntegerField(choices=[(1, 'Active'), (2, 'Reserved'), (3, 'Deprecated')], default=1, verbose_name='Status'), + ), + migrations.AlterField( + model_name='vlan', + name='vid', + field=models.PositiveSmallIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(4094)], verbose_name='ID'), + ), + migrations.AlterField( + model_name='vrf', + name='enforce_unique', + field=models.BooleanField(default=True, help_text='Prevent duplicate prefixes/IP addresses within this VRF', verbose_name='Enforce unique space'), + ), + migrations.AlterField( + model_name='vrf', + name='rd', + field=models.CharField(max_length=21, unique=True, verbose_name='Route distinguisher'), + ), + migrations.AddField( + model_name='ipaddress', + name='role', + field=models.PositiveSmallIntegerField(blank=True, choices=[(10, 'Loopback'), (20, 'Secondary'), (30, 'Anycast'), (40, 'VIP'), (41, 'VRRP'), (42, 'HSRP'), (43, 'GLBP')], help_text='The functional role of this IP', null=True, verbose_name='Role'), + ), + migrations.AlterField( + model_name='ipaddress', + name='status', + field=models.PositiveSmallIntegerField(choices=[(1, 'Active'), (2, 'Reserved'), (3, 'Deprecated'), (5, 'DHCP')], default=1, help_text='The operational status of this IP', verbose_name='Status'), + ), + migrations.CreateModel( + name='Service', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True)), + ('last_updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=30)), + ('protocol', models.PositiveSmallIntegerField(choices=[(6, 'TCP'), (17, 'UDP')])), + ('port', models.PositiveIntegerField(validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(65535)], verbose_name='Port number')), + ('description', models.CharField(blank=True, max_length=100)), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='services', to='dcim.Device', verbose_name='device')), + ('ipaddresses', models.ManyToManyField(blank=True, related_name='services', to='ipam.IPAddress', verbose_name='IP addresses')), + ], + options={ + 'ordering': ['device', 'protocol', 'port'], + 'unique_together': set(), + }, + ), + ] diff --git a/netbox/ipam/migrations/0019_virtualization_squashed_0020_ipaddress_add_role_carp.py b/netbox/ipam/migrations/0019_virtualization_squashed_0020_ipaddress_add_role_carp.py new file mode 100644 index 000000000..c0b67464f --- /dev/null +++ b/netbox/ipam/migrations/0019_virtualization_squashed_0020_ipaddress_add_role_carp.py @@ -0,0 +1,34 @@ +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('ipam', '0019_virtualization'), ('ipam', '0020_ipaddress_add_role_carp')] + + dependencies = [ + ('ipam', '0018_remove_service_uniqueness_constraint'), + ('virtualization', '0001_virtualization'), + ] + + operations = [ + migrations.AlterModelOptions( + name='service', + options={'ordering': ['protocol', 'port']}, + ), + migrations.AddField( + model_name='service', + name='virtual_machine', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='services', to='virtualization.VirtualMachine'), + ), + migrations.AlterField( + model_name='service', + name='device', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='services', to='dcim.Device', verbose_name='device'), + ), + migrations.AlterField( + model_name='ipaddress', + name='role', + field=models.PositiveSmallIntegerField(blank=True, choices=[(10, 'Loopback'), (20, 'Secondary'), (30, 'Anycast'), (40, 'VIP'), (41, 'VRRP'), (42, 'HSRP'), (43, 'GLBP'), (44, 'CARP')], help_text='The functional role of this IP', null=True, verbose_name='Role'), + ), + ] diff --git a/netbox/ipam/migrations/0021_vrf_ordering_squashed_0025_custom_tag_models.py b/netbox/ipam/migrations/0021_vrf_ordering_squashed_0025_custom_tag_models.py new file mode 100644 index 000000000..f101f0dd0 --- /dev/null +++ b/netbox/ipam/migrations/0021_vrf_ordering_squashed_0025_custom_tag_models.py @@ -0,0 +1,145 @@ +import taggit.managers +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('ipam', '0021_vrf_ordering'), ('ipam', '0022_tags'), ('ipam', '0023_change_logging'), ('ipam', '0024_vrf_allow_null_rd'), ('ipam', '0025_custom_tag_models')] + + dependencies = [ + ('ipam', '0020_ipaddress_add_role_carp'), + ('taggit', '0002_auto_20150616_2121'), + ('extras', '0019_tag_taggeditem'), + ] + + operations = [ + migrations.AlterModelOptions( + name='vrf', + options={'ordering': ['name', 'rd'], 'verbose_name': 'VRF', 'verbose_name_plural': 'VRFs'}, + ), + migrations.AddField( + model_name='rir', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='rir', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='role', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='role', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='vlangroup', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='vlangroup', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='aggregate', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='aggregate', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='ipaddress', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='ipaddress', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='prefix', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='prefix', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='service', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='service', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='vlan', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vlan', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='vrf', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='vrf', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='vrf', + name='rd', + field=models.CharField(blank=True, max_length=21, null=True, unique=True), + ), + migrations.AddField( + model_name='aggregate', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='ipaddress', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='prefix', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='service', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='vlan', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='vrf', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + ] diff --git a/netbox/ipam/migrations/0026_prefix_ordering_vrf_nulls_first_squashed_0032_role_description.py b/netbox/ipam/migrations/0026_prefix_ordering_vrf_nulls_first_squashed_0032_role_description.py new file mode 100644 index 000000000..d5116039d --- /dev/null +++ b/netbox/ipam/migrations/0026_prefix_ordering_vrf_nulls_first_squashed_0032_role_description.py @@ -0,0 +1,140 @@ +import django.core.validators +from django.db import migrations, models +import django.db.models.expressions + +PREFIX_STATUS_CHOICES = ( + (0, 'container'), + (1, 'active'), + (2, 'reserved'), + (3, 'deprecated'), +) + +IPADDRESS_STATUS_CHOICES = ( + (0, 'container'), + (1, 'active'), + (2, 'reserved'), + (3, 'deprecated'), +) + +IPADDRESS_ROLE_CHOICES = ( + (10, 'loopback'), + (20, 'secondary'), + (30, 'anycast'), + (40, 'vip'), + (41, 'vrrp'), + (42, 'hsrp'), + (43, 'glbp'), + (44, 'carp'), +) + +VLAN_STATUS_CHOICES = ( + (1, 'active'), + (2, 'reserved'), + (3, 'deprecated'), +) + +SERVICE_PROTOCOL_CHOICES = ( + (6, 'tcp'), + (17, 'udp'), +) + + +def prefix_status_to_slug(apps, schema_editor): + Prefix = apps.get_model('ipam', 'Prefix') + for id, slug in PREFIX_STATUS_CHOICES: + Prefix.objects.filter(status=str(id)).update(status=slug) + + +def ipaddress_status_to_slug(apps, schema_editor): + IPAddress = apps.get_model('ipam', 'IPAddress') + for id, slug in IPADDRESS_STATUS_CHOICES: + IPAddress.objects.filter(status=str(id)).update(status=slug) + + +def ipaddress_role_to_slug(apps, schema_editor): + IPAddress = apps.get_model('ipam', 'IPAddress') + for id, slug in IPADDRESS_ROLE_CHOICES: + IPAddress.objects.filter(role=str(id)).update(role=slug) + + +def vlan_status_to_slug(apps, schema_editor): + VLAN = apps.get_model('ipam', 'VLAN') + for id, slug in VLAN_STATUS_CHOICES: + VLAN.objects.filter(status=str(id)).update(status=slug) + + +def service_protocol_to_slug(apps, schema_editor): + Service = apps.get_model('ipam', 'Service') + for id, slug in SERVICE_PROTOCOL_CHOICES: + Service.objects.filter(protocol=str(id)).update(protocol=slug) + + +class Migration(migrations.Migration): + + replaces = [('ipam', '0026_prefix_ordering_vrf_nulls_first'), ('ipam', '0027_ipaddress_add_dns_name'), ('ipam', '0028_3569_prefix_fields'), ('ipam', '0029_3569_ipaddress_fields'), ('ipam', '0030_3569_vlan_fields'), ('ipam', '0031_3569_service_fields'), ('ipam', '0032_role_description')] + + dependencies = [ + ('ipam', '0025_custom_tag_models'), + ] + + operations = [ + migrations.AlterModelOptions( + name='prefix', + options={'ordering': [django.db.models.expressions.OrderBy(django.db.models.expressions.F('vrf'), nulls_first=True), 'family', 'prefix'], 'verbose_name_plural': 'prefixes'}, + ), + migrations.AddField( + model_name='ipaddress', + name='dns_name', + field=models.CharField(blank=True, max_length=255, validators=[django.core.validators.RegexValidator(code='invalid', message='Only alphanumeric characters, hyphens, periods, and underscores are allowed in DNS names', regex='^[0-9A-Za-z._-]+$')]), + ), + migrations.AlterField( + model_name='prefix', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=prefix_status_to_slug, + ), + migrations.AlterField( + model_name='ipaddress', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=ipaddress_status_to_slug, + ), + migrations.AlterField( + model_name='ipaddress', + name='role', + field=models.CharField(blank=True, default='', max_length=50), + ), + migrations.RunPython( + code=ipaddress_role_to_slug, + ), + migrations.AlterField( + model_name='ipaddress', + name='role', + field=models.CharField(blank=True, max_length=50), + ), + migrations.AlterField( + model_name='vlan', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=vlan_status_to_slug, + ), + migrations.AlterField( + model_name='service', + name='protocol', + field=models.CharField(max_length=50), + ), + migrations.RunPython( + code=service_protocol_to_slug, + ), + migrations.AddField( + model_name='role', + name='description', + field=models.CharField(blank=True, max_length=100), + ), + ] diff --git a/netbox/secrets/migrations/0001_initial_squashed_0006_custom_tag_models.py b/netbox/secrets/migrations/0001_initial_squashed_0006_custom_tag_models.py new file mode 100644 index 000000000..2a5f2b740 --- /dev/null +++ b/netbox/secrets/migrations/0001_initial_squashed_0006_custom_tag_models.py @@ -0,0 +1,81 @@ +import django.db.models.deletion +import taggit.managers +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('secrets', '0001_initial'), ('secrets', '0002_userkey_add_session_key'), ('secrets', '0003_unicode_literals'), ('secrets', '0004_tags'), ('secrets', '0005_change_logging'), ('secrets', '0006_custom_tag_models')] + + dependencies = [ + ('dcim', '0002_auto_20160622_1821'), + ('extras', '0019_tag_taggeditem'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('taggit', '0002_auto_20150616_2121'), + ('auth', '0007_alter_validators_add_error_messages'), + ] + + operations = [ + migrations.CreateModel( + name='SecretRole', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('groups', models.ManyToManyField(blank=True, related_name='secretroles', to='auth.Group')), + ('users', models.ManyToManyField(blank=True, related_name='secretroles', to=settings.AUTH_USER_MODEL)), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='UserKey', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True)), + ('last_updated', models.DateTimeField(auto_now=True)), + ('public_key', models.TextField(verbose_name='RSA public key')), + ('master_key_cipher', models.BinaryField(blank=True, max_length=512, null=True)), + ('user', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='user_key', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'ordering': ['user__username'], + 'permissions': (('activate_userkey', 'Can activate user keys for decryption'),), + }, + ), + migrations.CreateModel( + name='SessionKey', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cipher', models.BinaryField(max_length=512)), + ('hash', models.CharField(editable=False, max_length=128)), + ('created', models.DateTimeField(auto_now_add=True)), + ('userkey', models.OneToOneField(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='session_key', to='secrets.UserKey')), + ], + options={ + 'ordering': ['userkey__user__username'], + }, + ), + migrations.CreateModel( + name='Secret', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('name', models.CharField(blank=True, max_length=100)), + ('ciphertext', models.BinaryField(max_length=65568)), + ('hash', models.CharField(editable=False, max_length=128)), + ('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='secrets', to='dcim.Device')), + ('role', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='secrets', to='secrets.SecretRole')), + ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags')), + ], + options={ + 'ordering': ['device', 'role', 'name'], + 'unique_together': {('device', 'role', 'name')}, + }, + ), + ] diff --git a/netbox/tenancy/migrations/0001_initial_squashed_0005_change_logging.py b/netbox/tenancy/migrations/0001_initial_squashed_0005_change_logging.py new file mode 100644 index 000000000..664ea5d1b --- /dev/null +++ b/netbox/tenancy/migrations/0001_initial_squashed_0005_change_logging.py @@ -0,0 +1,45 @@ +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('tenancy', '0001_initial'), ('tenancy', '0002_tenant_group_optional'), ('tenancy', '0003_unicode_literals'), ('tenancy', '0004_tags'), ('tenancy', '0005_change_logging')] + + dependencies = [ + ('taggit', '0002_auto_20150616_2121'), + ] + + operations = [ + migrations.CreateModel( + name='TenantGroup', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50, unique=True)), + ('slug', models.SlugField(unique=True)), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Tenant', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('name', models.CharField(max_length=30, unique=True)), + ('slug', models.SlugField(unique=True)), + ('description', models.CharField(blank=True, help_text='Long-form name (optional)', max_length=100)), + ('comments', models.TextField(blank=True)), + ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tenants', to='tenancy.TenantGroup')), + ('tags', taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags')), + ], + options={ + 'ordering': ['group', 'name'], + }, + ), + ] diff --git a/netbox/users/migrations/0001_api_tokens_squashed_0003_token_permissions.py b/netbox/users/migrations/0001_api_tokens_squashed_0003_token_permissions.py new file mode 100644 index 000000000..1053dcd7a --- /dev/null +++ b/netbox/users/migrations/0001_api_tokens_squashed_0003_token_permissions.py @@ -0,0 +1,35 @@ +import django.core.validators +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('users', '0001_api_tokens'), ('users', '0002_unicode_literals'), ('users', '0003_token_permissions')] + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Token', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('expires', models.DateTimeField(blank=True, null=True)), + ('key', models.CharField(max_length=40, unique=True, validators=[django.core.validators.MinLengthValidator(40)])), + ('write_enabled', models.BooleanField(default=True, help_text='Permit create/update/delete operations using this key')), + ('description', models.CharField(blank=True, max_length=100)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tokens', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'default_permissions': [], + }, + ), + migrations.AlterModelOptions( + name='token', + options={}, + ), + ] diff --git a/netbox/virtualization/migrations/0002_virtualmachine_add_status_squashed_0009_custom_tag_models.py b/netbox/virtualization/migrations/0002_virtualmachine_add_status_squashed_0009_custom_tag_models.py new file mode 100644 index 000000000..4a8fa4ea5 --- /dev/null +++ b/netbox/virtualization/migrations/0002_virtualmachine_add_status_squashed_0009_custom_tag_models.py @@ -0,0 +1,89 @@ +import django.contrib.postgres.fields.jsonb +import django.db.models.deletion +import taggit.managers +from django.db import migrations, models + + +class Migration(migrations.Migration): + + replaces = [('virtualization', '0002_virtualmachine_add_status'), ('virtualization', '0003_cluster_add_site'), ('virtualization', '0004_virtualmachine_add_role'), ('virtualization', '0005_django2'), ('virtualization', '0006_tags'), ('virtualization', '0007_change_logging'), ('virtualization', '0008_virtualmachine_local_context_data'), ('virtualization', '0009_custom_tag_models')] + + dependencies = [ + ('dcim', '0044_virtualization'), + ('virtualization', '0001_virtualization'), + ('extras', '0019_tag_taggeditem'), + ('taggit', '0002_auto_20150616_2121'), + ] + + operations = [ + migrations.AddField( + model_name='virtualmachine', + name='status', + field=models.PositiveSmallIntegerField(choices=[[1, 'Active'], [0, 'Offline'], [3, 'Staged']], default=1, verbose_name='Status'), + ), + migrations.AddField( + model_name='cluster', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='dcim.Site'), + ), + migrations.AddField( + model_name='virtualmachine', + name='role', + field=models.ForeignKey(blank=True, limit_choices_to={'vm_role': True}, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='virtual_machines', to='dcim.DeviceRole'), + ), + migrations.AddField( + model_name='clustergroup', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='clustergroup', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='clustertype', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AddField( + model_name='clustertype', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='cluster', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='cluster', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AlterField( + model_name='virtualmachine', + name='created', + field=models.DateField(auto_now_add=True, null=True), + ), + migrations.AlterField( + model_name='virtualmachine', + name='last_updated', + field=models.DateTimeField(auto_now=True, null=True), + ), + migrations.AddField( + model_name='virtualmachine', + name='local_context_data', + field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='cluster', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='virtualmachine', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='extras.TaggedItem', to='extras.Tag', verbose_name='Tags'), + ), + ] diff --git a/netbox/virtualization/migrations/0010_cluster_add_tenant_squashed_0012_vm_name_nonunique.py b/netbox/virtualization/migrations/0010_cluster_add_tenant_squashed_0012_vm_name_nonunique.py new file mode 100644 index 000000000..74f2dacd3 --- /dev/null +++ b/netbox/virtualization/migrations/0010_cluster_add_tenant_squashed_0012_vm_name_nonunique.py @@ -0,0 +1,50 @@ +from django.db import migrations, models +import django.db.models.deletion + +VIRTUALMACHINE_STATUS_CHOICES = ( + (0, 'offline'), + (1, 'active'), + (3, 'staged'), +) + + +def virtualmachine_status_to_slug(apps, schema_editor): + VirtualMachine = apps.get_model('virtualization', 'VirtualMachine') + for id, slug in VIRTUALMACHINE_STATUS_CHOICES: + VirtualMachine.objects.filter(status=str(id)).update(status=slug) + + +class Migration(migrations.Migration): + + replaces = [('virtualization', '0010_cluster_add_tenant'), ('virtualization', '0011_3569_virtualmachine_fields'), ('virtualization', '0012_vm_name_nonunique')] + + dependencies = [ + ('tenancy', '0001_initial'), + ('tenancy', '0006_custom_tag_models'), + ('virtualization', '0009_custom_tag_models'), + ] + + operations = [ + migrations.AddField( + model_name='cluster', + name='tenant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='clusters', to='tenancy.Tenant'), + ), + migrations.AlterField( + model_name='virtualmachine', + name='status', + field=models.CharField(default='active', max_length=50), + ), + migrations.RunPython( + code=virtualmachine_status_to_slug, + ), + migrations.AlterField( + model_name='virtualmachine', + name='name', + field=models.CharField(max_length=64), + ), + migrations.AlterUniqueTogether( + name='virtualmachine', + unique_together={('cluster', 'tenant', 'name')}, + ), + ]