nautobot 3.0.0a2__py3-none-any.whl → 3.0.0rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nautobot/apps/choices.py +4 -2
- nautobot/apps/filters.py +7 -9
- nautobot/apps/models.py +2 -2
- nautobot/apps/ui.py +13 -1
- nautobot/apps/utils.py +8 -0
- nautobot/circuits/filters.py +3 -2
- nautobot/circuits/navigation.py +3 -2
- nautobot/circuits/templates/circuits/circuit_create.html +3 -3
- nautobot/circuits/templates/circuits/circuittermination_create.html +9 -24
- nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +6 -6
- nautobot/circuits/templates/circuits/inc/speed_widget.html +12 -12
- nautobot/circuits/tests/integration/test_circuit.py +10 -13
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +0 -3
- nautobot/circuits/views.py +6 -2
- nautobot/cloud/filters.py +1 -1
- nautobot/cloud/navigation.py +3 -2
- nautobot/core/api/schema.py +1 -1
- nautobot/core/api/serializers.py +6 -1
- nautobot/core/api/urls.py +2 -0
- nautobot/core/api/views.py +12 -0
- nautobot/core/apps/__init__.py +11 -10
- nautobot/core/celery/__init__.py +3 -5
- nautobot/core/checks.py +46 -0
- nautobot/core/choices.py +1 -1
- nautobot/core/cli/bootstrap_v3_to_v5.py +105 -13
- nautobot/core/cli/migrate_deprecated_templates.py +227 -0
- nautobot/core/constants.py +3 -0
- nautobot/core/context_processors.py +9 -1
- nautobot/core/filters.py +4 -0
- nautobot/core/forms/__init__.py +2 -0
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/forms/widgets.py +21 -2
- nautobot/core/jobs/__init__.py +62 -3
- nautobot/core/jobs/groups.py +31 -1
- nautobot/core/management/commands/generate_test_data.py +28 -9
- nautobot/core/models/__init__.py +11 -0
- nautobot/core/models/generics.py +9 -1
- nautobot/core/models/tree_queries.py +10 -5
- nautobot/core/models/utils.py +1 -1
- nautobot/core/settings.py +35 -19
- nautobot/core/settings.yaml +17 -33
- nautobot/core/signals.py +12 -1
- nautobot/core/tables.py +13 -6
- nautobot/core/templates/40x.html +1 -1
- nautobot/core/templates/500.html +2 -2
- nautobot/core/templates/admin/base.html +1 -2
- nautobot/core/templates/admin/change_list.html +9 -12
- nautobot/core/templates/admin/config/config.html +12 -12
- nautobot/core/templates/admin/index.html +3 -3
- nautobot/core/templates/base_django.html +1 -2
- nautobot/core/templates/buttons/export.html +1 -1
- nautobot/core/templates/components/button/dropdown.html +5 -3
- nautobot/core/templates/components/panel/body_wrapper_generic_table.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/components/panel/panel.html +3 -3
- nautobot/core/templates/components/tab/content_wrapper.html +6 -7
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +1 -1
- nautobot/core/templates/echarts/echarts.html +22 -9
- nautobot/core/templates/generic/object_bulk_add_component.html +2 -1
- nautobot/core/templates/generic/object_bulk_create.html +6 -5
- nautobot/core/templates/generic/object_bulk_delete.html +1 -1
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -3
- nautobot/core/templates/generic/object_bulk_edit.html +1 -1
- nautobot/core/templates/generic/object_bulk_import.html +1 -1
- nautobot/core/templates/generic/object_bulk_remove.html +2 -2
- nautobot/core/templates/generic/object_bulk_update.html +5 -4
- nautobot/core/templates/generic/object_create.html +5 -4
- nautobot/core/templates/generic/object_delete.html +1 -1
- nautobot/core/templates/generic/object_detail.html +1 -1
- nautobot/core/templates/generic/object_edit.html +1 -1
- nautobot/core/templates/generic/object_import.html +2 -1
- nautobot/core/templates/generic/object_list.html +12 -4
- nautobot/core/templates/generic/object_notes.html +5 -3
- nautobot/core/templates/generic/object_retrieve.html +4 -5
- nautobot/core/templates/graphene/graphiql.html +7 -8
- nautobot/core/templates/home.html +1 -1
- nautobot/core/templates/import_success.html +2 -1
- nautobot/core/templates/inc/computed_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/created_updated.html +7 -3
- nautobot/core/templates/inc/custom_fields/panel_data.html +1 -1
- nautobot/core/templates/inc/footer.html +3 -1
- nautobot/core/templates/inc/form_static_field.html +6 -0
- nautobot/core/templates/inc/header.html +11 -1
- nautobot/core/templates/inc/image_attachments.html +2 -1
- nautobot/core/templates/inc/media.html +14 -0
- nautobot/core/templates/inc/nav_menu.html +3 -9
- nautobot/core/templates/inc/object_details_advanced_panel.html +2 -2
- nautobot/core/templates/inc/search_panel.html +4 -4
- nautobot/core/templates/login.html +4 -2
- nautobot/core/templates/nautobot_config.py.j2 +6 -11
- nautobot/core/templates/redoc_ui.html +7 -0
- nautobot/core/templates/rest_framework/api.html +103 -2
- nautobot/core/templates/search.html +1 -1
- nautobot/core/templates/swagger_ui.html +17 -3
- nautobot/core/templates/system_jobs/import_objects.html +1 -2
- nautobot/core/templates/utilities/confirmation_form.html +2 -2
- nautobot/core/templates/utilities/obj_table.html +10 -2
- nautobot/core/templates/utilities/render_field.html +7 -7
- nautobot/core/templates/utilities/render_jinja2.html +2 -2
- nautobot/core/templates/utilities/templatetags/filter_form_drawer.html +37 -4
- nautobot/core/templates/utilities/theme_preview.html +19 -3
- nautobot/core/templates/widgets/number_input_with_choices.html +44 -0
- nautobot/core/templates/widgets/selectwithdisabled_option.html +3 -1
- nautobot/core/templatetags/helpers.py +76 -18
- nautobot/core/testing/api.py +68 -9
- nautobot/core/testing/filters.py +0 -23
- nautobot/core/testing/integration.py +41 -17
- nautobot/core/testing/mixins.py +2 -0
- nautobot/core/testing/utils.py +18 -4
- nautobot/core/testing/views.py +104 -13
- nautobot/core/tests/integration/test_app_home.py +34 -30
- nautobot/core/tests/integration/test_app_navbar.py +3 -0
- nautobot/core/tests/integration/test_filters.py +48 -11
- nautobot/core/tests/integration/test_theme.py +22 -21
- nautobot/core/tests/nautobot_config.py +3 -0
- nautobot/core/tests/nautobot_config_without_example_apps.py +4 -0
- nautobot/core/tests/runner.py +8 -1
- nautobot/core/tests/test_api.py +5 -3
- nautobot/core/tests/test_breadcrumbs.py +27 -28
- nautobot/core/tests/test_checks.py +28 -0
- nautobot/core/tests/test_cli.py +40 -0
- nautobot/core/tests/test_config.py +2 -1
- nautobot/core/tests/test_forms.py +55 -13
- nautobot/core/tests/test_jobs.py +144 -3
- nautobot/core/tests/test_nautobot_server.py +2 -0
- nautobot/core/tests/test_navigations.py +76 -1
- nautobot/core/tests/test_patch_social_django.py +42 -0
- nautobot/core/tests/test_renderers.py +59 -0
- nautobot/core/tests/test_settings_schema.py +1 -0
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +62 -13
- nautobot/core/tests/test_templatetags_ui_framework.py +4 -4
- nautobot/core/tests/test_titles.py +0 -16
- nautobot/core/tests/test_tree_queries.py +14 -1
- nautobot/core/tests/test_ui.py +123 -4
- nautobot/core/tests/test_utils.py +72 -5
- nautobot/core/tests/test_views.py +159 -31
- nautobot/core/ui/breadcrumbs.py +70 -29
- nautobot/core/ui/bulk_buttons.py +1 -1
- nautobot/core/ui/choices.py +143 -27
- nautobot/core/ui/constants.py +76 -12
- nautobot/core/ui/echarts.py +15 -20
- nautobot/core/ui/object_detail.py +143 -55
- nautobot/core/ui/titles.py +3 -6
- nautobot/core/urls.py +20 -9
- nautobot/core/utils/cache.py +2 -1
- nautobot/core/utils/filtering.py +28 -18
- nautobot/core/utils/lookup.py +49 -8
- nautobot/core/utils/module_loading.py +21 -0
- nautobot/core/utils/patch_social_django.py +128 -0
- nautobot/core/views/__init__.py +38 -1
- nautobot/core/views/generic.py +3 -3
- nautobot/core/views/mixins.py +45 -22
- nautobot/core/views/renderers.py +4 -3
- nautobot/core/views/viewsets.py +2 -1
- nautobot/data_validation/apps.py +1 -5
- nautobot/data_validation/custom_validators.py +4 -4
- nautobot/data_validation/filters.py +1 -1
- nautobot/data_validation/forms.py +40 -0
- nautobot/data_validation/migrations/0001_initial.py +0 -7
- nautobot/data_validation/migrations/0002_data_migration_from_app.py +3 -14
- nautobot/data_validation/models.py +16 -7
- nautobot/data_validation/navigation.py +8 -1
- nautobot/data_validation/tables.py +12 -5
- nautobot/data_validation/templates/data_validation/datacompliance_tab.html +1 -0
- nautobot/data_validation/templates/data_validation/device_constraints.html +61 -0
- nautobot/data_validation/tests/__init__.py +2 -2
- nautobot/data_validation/tests/migrations/test_migrations.py +83 -3
- nautobot/data_validation/tests/test_data_compliance_rules.py +12 -7
- nautobot/data_validation/tests/test_filters.py +8 -6
- nautobot/data_validation/tests/test_models.py +15 -0
- nautobot/data_validation/tests/test_views.py +190 -32
- nautobot/data_validation/urls.py +2 -5
- nautobot/data_validation/views.py +73 -40
- nautobot/dcim/api/serializers.py +3 -13
- nautobot/dcim/apps.py +4 -0
- nautobot/dcim/choices.py +65 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/custom_validators.py +84 -0
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filter_mixins.py +353 -4
- nautobot/dcim/{filters/__init__.py → filters.py} +15 -36
- nautobot/dcim/forms.py +90 -4
- nautobot/dcim/migrations/0075_interface_duplex_interface_speed_and_more.py +32 -0
- nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py} +1 -1
- nautobot/dcim/migrations/{0076_device_cluster_to_clusters_data_migration.py → 0077_device_cluster_to_clusters_data_migration.py} +1 -1
- nautobot/dcim/migrations/{0077_remove_device_cluster.py → 0078_remove_device_cluster.py} +1 -1
- nautobot/dcim/migrations/0079_remove_device_location_tenant_name_uniqueness.py +16 -0
- nautobot/dcim/migrations/0080_device_name_data_migration.py +59 -0
- nautobot/dcim/migrations/0081_alter_device_device_redundancy_group_priority_and_more.py +25 -0
- nautobot/dcim/models/device_component_templates.py +33 -1
- nautobot/dcim/models/device_components.py +98 -64
- nautobot/dcim/models/devices.py +30 -20
- nautobot/dcim/navigation.py +7 -6
- nautobot/dcim/tables/devices.py +18 -0
- nautobot/dcim/tables/devicetypes.py +8 -1
- nautobot/dcim/tables/racks.py +0 -2
- nautobot/dcim/tables/template_code.py +15 -15
- nautobot/dcim/templates/dcim/cable_connect.html +28 -112
- nautobot/dcim/templates/dcim/cable_trace.html +0 -4
- nautobot/dcim/templates/dcim/{cable_edit.html → cable_update.html} +1 -1
- nautobot/dcim/templates/dcim/consoleport.html +7 -6
- nautobot/dcim/templates/dcim/consoleserverport.html +7 -6
- nautobot/dcim/templates/dcim/device/config.html +2 -2
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +1 -1
- nautobot/dcim/templates/dcim/device/status.html +8 -8
- nautobot/dcim/templates/dcim/device.html +1 -1
- nautobot/dcim/templates/dcim/device_component_add.html +2 -2
- nautobot/dcim/templates/dcim/device_create.html +5 -3
- nautobot/dcim/templates/dcim/device_interface_delete.html +1 -1
- nautobot/dcim/templates/dcim/device_list.html +73 -10
- nautobot/dcim/templates/dcim/devicebay.html +1 -1
- nautobot/dcim/templates/dcim/devicebay_populate.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_component_add.html +2 -2
- nautobot/dcim/templates/dcim/footer_convert_to_contact_or_team_record.html +14 -0
- nautobot/dcim/templates/dcim/frontport.html +10 -9
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/edit_form_softwareversion_js.html +2 -2
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/rack_elevation.html +1 -1
- nautobot/dcim/templates/dcim/interface.html +35 -7
- nautobot/dcim/templates/dcim/interface_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/interface_edit.html +2 -0
- nautobot/dcim/templates/dcim/inventoryitem.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_add.html +3 -1
- nautobot/dcim/templates/dcim/inventoryitem_bulk_delete.html +1 -1
- nautobot/dcim/templates/dcim/inventoryitem_edit.html +3 -1
- nautobot/dcim/templates/dcim/module/base.html +49 -9
- nautobot/dcim/templates/dcim/module_consoleports.html +1 -1
- nautobot/dcim/templates/dcim/module_consoleserverports.html +1 -1
- nautobot/dcim/templates/dcim/module_frontports.html +1 -1
- nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
- nautobot/dcim/templates/dcim/module_list.html +57 -8
- nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
- nautobot/dcim/templates/dcim/module_poweroutlets.html +1 -1
- nautobot/dcim/templates/dcim/module_powerports.html +1 -1
- nautobot/dcim/templates/dcim/module_rearports.html +1 -1
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_list.html +2 -2
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +49 -9
- nautobot/dcim/templates/dcim/platform_create.html +1 -1
- nautobot/dcim/templates/dcim/poweroutlet.html +1 -1
- nautobot/dcim/templates/dcim/powerport.html +6 -5
- nautobot/dcim/templates/dcim/rack_elevation_list.html +17 -5
- nautobot/dcim/templates/dcim/rack_retrieve.html +22 -15
- nautobot/dcim/templates/dcim/rearport.html +8 -7
- nautobot/dcim/templates/dcim/trace/cable.html +1 -1
- nautobot/dcim/templates/dcim/virtualchassis_add_member.html +16 -14
- nautobot/dcim/templates/dcim/virtualchassis_update.html +15 -7
- nautobot/dcim/tests/integration/test_controller.py +4 -6
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +1 -5
- nautobot/dcim/tests/integration/test_create_device.py +0 -2
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +1 -3
- nautobot/dcim/tests/integration/test_fileinputpicker.py +6 -10
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +0 -2
- nautobot/dcim/tests/integration/test_module_bay_position.py +3 -4
- nautobot/dcim/tests/test_api.py +194 -6
- nautobot/dcim/tests/test_custom_validators.py +229 -0
- nautobot/dcim/tests/test_filters.py +55 -7
- nautobot/dcim/tests/test_forms.py +110 -8
- nautobot/dcim/tests/test_graphql.py +44 -1
- nautobot/dcim/tests/test_models.py +328 -4
- nautobot/dcim/tests/test_tables.py +160 -0
- nautobot/dcim/tests/test_views.py +132 -29
- nautobot/dcim/urls.py +64 -21
- nautobot/dcim/utils.py +3 -3
- nautobot/dcim/views.py +777 -397
- nautobot/extras/api/views.py +60 -45
- nautobot/extras/choices.py +2 -13
- nautobot/extras/datasources/git.py +3 -1
- nautobot/extras/{filters/mixins.py → filter_mixins.py} +1 -1
- nautobot/extras/{filters/customfields.py → filter_mixins_customfields.py} +42 -6
- nautobot/extras/{filters/__init__.py → filters.py} +33 -48
- nautobot/extras/forms/forms.py +14 -15
- nautobot/extras/forms/mixins.py +0 -41
- nautobot/extras/jobs.py +2 -0
- nautobot/extras/jobs_ui.py +4 -3
- nautobot/extras/management/__init__.py +11 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +4 -1
- nautobot/extras/migrations/0127_approval_workflow_models.py +6 -6
- nautobot/extras/migrations/0129_jobresult_debug_log_count_jobresult_error_log_count_and_more.py +37 -0
- nautobot/extras/migrations/0130_jobresult_generate_log_entry_counts.py +42 -0
- nautobot/extras/migrations/0131_configcontext_device_families.py +18 -0
- nautobot/extras/models/__init__.py +1 -2
- nautobot/extras/models/approvals.py +33 -14
- nautobot/extras/models/change_logging.py +4 -0
- nautobot/extras/models/contacts.py +2 -0
- nautobot/extras/models/groups.py +44 -5
- nautobot/extras/models/jobs.py +60 -4
- nautobot/extras/models/mixins.py +28 -0
- nautobot/extras/models/models.py +23 -2
- nautobot/extras/models/secrets.py +1 -0
- nautobot/extras/models/statuses.py +0 -15
- nautobot/extras/navigation.py +13 -9
- nautobot/extras/plugins/__init__.py +33 -55
- nautobot/extras/plugins/marketplace_manifest.yml +49 -1
- nautobot/extras/plugins/tables.py +3 -3
- nautobot/extras/plugins/urls.py +2 -21
- nautobot/extras/plugins/utils.py +1 -33
- nautobot/extras/plugins/views.py +0 -9
- nautobot/extras/querysets.py +8 -0
- nautobot/extras/signals.py +20 -19
- nautobot/extras/tables.py +64 -68
- nautobot/extras/templates/django_ajax_tables/ajax_wrapper.html +2 -0
- nautobot/extras/templates/extras/approval_dashboard.html +7 -5
- nautobot/extras/templates/extras/approvalworkflowdefinition_update.html +4 -2
- nautobot/extras/templates/extras/approvalworkflowstage_retrieve.html +20 -12
- nautobot/extras/templates/extras/configcontext_update.html +1 -0
- nautobot/extras/templates/extras/configcontextschema_validation.html +2 -2
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +11 -5
- nautobot/extras/templates/extras/dynamicgroup_update.html +1 -1
- nautobot/extras/templates/extras/gitrepository_result.html +0 -2
- nautobot/extras/templates/extras/inc/approval_buttons_column.html +20 -6
- nautobot/extras/templates/extras/inc/bulk_edit_overridable_field.html +8 -7
- nautobot/extras/templates/extras/inc/configcontext_format.html +10 -3
- nautobot/extras/templates/extras/inc/graphqlquery_execute.html +71 -0
- nautobot/extras/templates/extras/inc/job_tiles.html +15 -3
- nautobot/extras/templates/extras/inc/json_format.html +10 -3
- nautobot/extras/templates/extras/inc/overridable_field.html +13 -12
- nautobot/extras/templates/extras/job.html +29 -12
- nautobot/extras/templates/extras/job_bulk_edit.html +18 -0
- nautobot/extras/templates/extras/job_edit.html +52 -46
- nautobot/extras/templates/extras/job_list.html +29 -25
- nautobot/extras/templates/extras/marketplace.html +5 -9
- nautobot/extras/templates/extras/object_configcontext.html +1 -1
- nautobot/extras/templates/extras/object_dynamicgroups.html +2 -2
- nautobot/extras/templates/extras/objectchange_retrieve.html +19 -39
- nautobot/extras/templates/extras/plugin_detail.html +29 -24
- nautobot/extras/templates/extras/plugins_list.html +16 -26
- nautobot/extras/templates/extras/role_retrieve.html +64 -0
- nautobot/extras/templates/extras/scheduledjob.html +4 -2
- nautobot/extras/templates/extras/secret_create.html +1 -1
- nautobot/extras/templatetags/custom_links.py +12 -12
- nautobot/extras/templatetags/job_buttons.py +14 -12
- nautobot/extras/test_jobs/invalid_import.py +9 -0
- nautobot/extras/test_jobs/log_counts_by_level.py +23 -0
- nautobot/extras/test_jobs/missing_import.py +11 -0
- nautobot/extras/tests/integration/test_computedfields.py +8 -9
- nautobot/extras/tests/integration/test_configcontextschema.py +27 -26
- nautobot/extras/tests/integration/test_customfields.py +9 -10
- nautobot/extras/tests/integration/test_dynamicgroups.py +12 -9
- nautobot/extras/tests/integration/test_plugin_banner.py +3 -0
- nautobot/extras/tests/integration/test_plugins.py +18 -6
- nautobot/extras/tests/integration/test_relationships.py +0 -2
- nautobot/extras/tests/test_api.py +90 -18
- nautobot/extras/tests/test_approvals.py +38 -38
- nautobot/extras/tests/test_changelog.py +59 -5
- nautobot/extras/tests/test_customfields.py +22 -13
- nautobot/extras/tests/test_customfields_filters.py +479 -0
- nautobot/extras/tests/test_dynamicgroups.py +39 -1
- nautobot/extras/tests/test_filters.py +57 -22
- nautobot/extras/tests/test_forms.py +18 -21
- nautobot/extras/tests/test_jobs.py +25 -4
- nautobot/extras/tests/test_migrations.py +1 -0
- nautobot/extras/tests/test_models.py +51 -33
- nautobot/extras/tests/test_plugins.py +36 -10
- nautobot/extras/tests/test_utils.py +3 -4
- nautobot/extras/tests/test_views.py +52 -112
- nautobot/extras/urls.py +0 -14
- nautobot/extras/views.py +164 -71
- nautobot/ipam/factory.py +7 -0
- nautobot/ipam/filter_mixins.py +38 -0
- nautobot/ipam/filters.py +53 -38
- nautobot/ipam/formfields.py +1 -1
- nautobot/ipam/forms.py +6 -3
- nautobot/ipam/migrations/0030_ipam__namespaces.py +13 -0
- nautobot/ipam/migrations/0031_ipam___data_migrations.py +4 -1
- nautobot/ipam/migrations/0054_namespace_tenant.py +25 -0
- nautobot/ipam/models.py +29 -2
- nautobot/ipam/navigation.py +3 -2
- nautobot/ipam/signals.py +71 -0
- nautobot/ipam/tables.py +19 -6
- nautobot/ipam/templates/ipam/inc/toggle_available.html +10 -10
- nautobot/ipam/templates/ipam/inc/vlangroup_header.html +1 -0
- nautobot/ipam/templates/ipam/ipaddress.html +14 -0
- nautobot/ipam/templates/ipam/ipaddress_merge.html +3 -3
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +1 -0
- nautobot/ipam/templates/ipam/namespace_ip_addresses.html +1 -1
- nautobot/ipam/templates/ipam/namespace_prefixes.html +1 -1
- nautobot/ipam/templates/ipam/namespace_update.html +15 -0
- nautobot/ipam/templates/ipam/namespace_vrfs.html +1 -1
- nautobot/ipam/templates/ipam/prefix_delete.html +1 -1
- nautobot/ipam/templates/ipam/prefix_list.html +14 -13
- nautobot/ipam/templates/ipam/vlan_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/vlan_vminterfaces.html +1 -1
- nautobot/ipam/tests/migration/test_migrations.py +89 -0
- nautobot/ipam/tests/test_api.py +13 -6
- nautobot/ipam/tests/test_filters.py +36 -1
- nautobot/ipam/tests/test_forms.py +1 -1
- nautobot/ipam/tests/test_models.py +44 -2
- nautobot/ipam/tests/test_tables.py +1 -2
- nautobot/ipam/tests/test_utils.py +1 -1
- nautobot/ipam/tests/test_views.py +13 -14
- nautobot/ipam/ui.py +0 -17
- nautobot/ipam/utils/migrations.py +16 -2
- nautobot/ipam/utils/testing.py +9 -3
- nautobot/ipam/views.py +53 -11
- nautobot/load_balancers/__init__.py +0 -0
- nautobot/load_balancers/api/__init__.py +1 -0
- nautobot/load_balancers/api/serializers.py +75 -0
- nautobot/load_balancers/api/urls.py +23 -0
- nautobot/load_balancers/api/views.py +61 -0
- nautobot/load_balancers/apps.py +17 -0
- nautobot/load_balancers/choices.py +167 -0
- nautobot/load_balancers/filters.py +225 -0
- nautobot/load_balancers/forms.py +532 -0
- nautobot/load_balancers/management/commands/__init__.py +0 -0
- nautobot/load_balancers/management/commands/generate_load_balancer_models_test_data.py +38 -0
- nautobot/load_balancers/migrations/0001_initial.py +465 -0
- nautobot/load_balancers/migrations/0002_create_default_statuses_pool_members.py +31 -0
- nautobot/load_balancers/migrations/__init__.py +0 -0
- nautobot/load_balancers/models.py +423 -0
- nautobot/load_balancers/navigation.py +80 -0
- nautobot/load_balancers/tables.py +255 -0
- nautobot/load_balancers/tests/__init__.py +474 -0
- nautobot/load_balancers/tests/test_api.py +353 -0
- nautobot/load_balancers/tests/test_filters.py +134 -0
- nautobot/load_balancers/tests/test_forms.py +266 -0
- nautobot/load_balancers/tests/test_models.py +195 -0
- nautobot/load_balancers/tests/test_views.py +229 -0
- nautobot/load_balancers/urls.py +17 -0
- nautobot/load_balancers/views.py +248 -0
- nautobot/project-static/dist/css/github-dark.min.css +10 -0
- nautobot/project-static/dist/css/github.min.css +10 -0
- nautobot/project-static/dist/css/nautobot.css +1 -11
- nautobot/project-static/dist/css/nautobot.css.map +1 -1
- nautobot/project-static/dist/js/libraries.js +1 -1
- nautobot/project-static/dist/js/libraries.js.map +1 -1
- nautobot/project-static/dist/js/nautobot.js +1 -1
- nautobot/project-static/dist/js/nautobot.js.map +1 -1
- nautobot/project-static/js/cabletrace.js +1 -1
- nautobot/project-static/js/forms.js +13 -0
- nautobot/project-static/js/interface_filtering.js +20 -16
- nautobot/project-static/nautobot-icons/battery-3.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-globe.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield-check.svg +3 -0
- nautobot/project-static/nautobot-icons/bus-shield.svg +3 -0
- nautobot/project-static/nautobot-icons/cloud.svg +1 -1
- nautobot/project-static/nautobot-icons/control-panel.svg +1 -1
- nautobot/project-static/nautobot-icons/device-lifecycle.svg +1 -1
- nautobot/project-static/nautobot-icons/elements.svg +1 -1
- nautobot/project-static/nautobot-icons/extensibility.svg +3 -0
- nautobot/project-static/nautobot-icons/hammer.svg +1 -1
- nautobot/project-static/nautobot-icons/organization.svg +3 -0
- nautobot/project-static/nautobot-icons/secrets.svg +1 -1
- nautobot/project-static/nautobot-icons/security.svg +3 -0
- nautobot/project-static/nautobot-icons/server.svg +1 -1
- nautobot/project-static/nautobot-icons/star-filled.svg +1 -1
- nautobot/project-static/nautobot-icons/star.svg +1 -1
- nautobot/tenancy/api/serializers.py +1 -0
- nautobot/tenancy/api/views.py +2 -1
- nautobot/tenancy/{filters/__init__.py → filters.py} +2 -10
- nautobot/tenancy/navigation.py +3 -1
- nautobot/tenancy/tests/test_filters.py +0 -2
- nautobot/tenancy/views.py +2 -1
- nautobot/ui/package-lock.json +87 -4
- nautobot/ui/package.json +2 -1
- nautobot/ui/src/js/collapse.js +3 -3
- nautobot/ui/src/js/nautobot.js +16 -1
- nautobot/ui/src/js/select2.js +53 -2
- nautobot/ui/src/scss/colors.scss +1 -1
- nautobot/ui/src/scss/nautobot.scss +112 -30
- nautobot/ui/webpack.config.js +13 -0
- nautobot/users/templates/users/preferences.html +11 -2
- nautobot/users/templates/users/profile.html +45 -12
- nautobot/users/templates/users/sessionkey_delete.html +1 -1
- nautobot/users/tests/test_api.py +4 -0
- nautobot/users/views.py +4 -2
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/models.py +1 -68
- nautobot/virtualization/navigation.py +3 -2
- nautobot/virtualization/templates/virtualization/virtual_machine_vminterface_delete.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_list.html +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +3 -1
- nautobot/virtualization/tests/test_api.py +3 -0
- nautobot/virtualization/tests/test_filters.py +10 -1
- nautobot/virtualization/tests/test_models.py +45 -4
- nautobot/virtualization/views.py +4 -1
- nautobot/vpn/__init__.py +0 -0
- nautobot/vpn/api/serializers.py +113 -0
- nautobot/vpn/api/urls.py +19 -0
- nautobot/vpn/api/views.py +70 -0
- nautobot/vpn/apps.py +8 -0
- nautobot/vpn/choices.py +171 -0
- nautobot/vpn/factory.py +219 -0
- nautobot/vpn/filters.py +234 -0
- nautobot/vpn/forms.py +487 -0
- nautobot/vpn/homepage.py +19 -0
- nautobot/vpn/migrations/0001_initial.py +541 -0
- nautobot/vpn/migrations/0002_populate_defaults.py +199 -0
- nautobot/vpn/migrations/__init__.py +0 -0
- nautobot/vpn/models.py +535 -0
- nautobot/vpn/navigation.py +98 -0
- nautobot/vpn/tables.py +383 -0
- nautobot/vpn/templates/vpn/vpnprofile_create.html +150 -0
- nautobot/vpn/tests/__init__.py +0 -0
- nautobot/vpn/tests/test_api.py +336 -0
- nautobot/vpn/tests/test_filters.py +139 -0
- nautobot/vpn/tests/test_forms.py +293 -0
- nautobot/vpn/tests/test_models.py +147 -0
- nautobot/vpn/tests/test_views.py +300 -0
- nautobot/vpn/urls.py +16 -0
- nautobot/vpn/views.py +495 -0
- nautobot/wireless/navigation.py +3 -2
- nautobot/wireless/tests/integration/test_radio_profile.py +1 -5
- nautobot/wireless/tests/test_api.py +1 -1
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/METADATA +15 -15
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/RECORD +514 -572
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/entry_points.txt +1 -0
- nautobot/circuits/templates/circuits/circuit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuit_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittermination.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_edit.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/circuittermination_update.html +0 -1
- nautobot/circuits/templates/circuits/circuittype.html +0 -2
- nautobot/circuits/templates/circuits/circuittype_retrieve.html +0 -2
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +0 -85
- nautobot/circuits/templates/circuits/provider.html +0 -2
- nautobot/circuits/templates/circuits/provider_edit.html +0 -2
- nautobot/circuits/templates/circuits/provider_retrieve.html +0 -1
- nautobot/circuits/templates/circuits/provider_update.html +0 -1
- nautobot/circuits/templates/circuits/providernetwork.html +0 -2
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -2
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -2
- nautobot/core/templates/buttons/import.html +0 -9
- nautobot/data_validation/template_content.py +0 -42
- nautobot/data_validation/templates/data_validation/datacompliance_retrieve.html +0 -1
- nautobot/dcim/filters/mixins.py +0 -354
- nautobot/dcim/templates/dcim/controller/base.html +0 -2
- nautobot/dcim/templates/dcim/controller_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +0 -2
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/device/base.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleports.html +0 -2
- nautobot/dcim/templates/dcim/device/consoleserverports.html +0 -2
- nautobot/dcim/templates/dcim/device/devicebays.html +0 -2
- nautobot/dcim/templates/dcim/device/frontports.html +0 -2
- nautobot/dcim/templates/dcim/device/interfaces.html +0 -2
- nautobot/dcim/templates/dcim/device/inventory.html +0 -2
- nautobot/dcim/templates/dcim/device/modulebays.html +0 -2
- nautobot/dcim/templates/dcim/device/poweroutlets.html +0 -2
- nautobot/dcim/templates/dcim/device/powerports.html +0 -2
- nautobot/dcim/templates/dcim/device/rearports.html +0 -2
- nautobot/dcim/templates/dcim/device/wireless.html +0 -2
- nautobot/dcim/templates/dcim/device_component.html +0 -2
- nautobot/dcim/templates/dcim/device_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicefamily_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/devicetype.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_edit.html +0 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +0 -1
- nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/location.html +0 -2
- nautobot/dcim/templates/dcim/location_edit.html +0 -2
- nautobot/dcim/templates/dcim/location_retrieve.html +0 -243
- nautobot/dcim/templates/dcim/locationtype.html +0 -2
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/manufacturer.html +0 -2
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +0 -1
- nautobot/dcim/templates/dcim/platform.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed.html +0 -2
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_edit.html +0 -2
- nautobot/dcim/templates/dcim/powerpanel_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/rack.html +0 -2
- nautobot/dcim/templates/dcim/rack_edit.html +0 -2
- nautobot/dcim/templates/dcim/rackgroup.html +0 -2
- nautobot/dcim/templates/dcim/rackreservation.html +0 -2
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/softwareversion_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_add.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_edit.html +0 -2
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +0 -2
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +0 -2
- nautobot/dcim/ui.py +0 -29
- nautobot/extras/templates/extras/computedfield.html +0 -2
- nautobot/extras/templates/extras/computedfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontext.html +0 -2
- nautobot/extras/templates/extras/configcontext_edit.html +0 -2
- nautobot/extras/templates/extras/configcontext_retrieve.html +0 -2
- nautobot/extras/templates/extras/configcontextschema.html +0 -2
- nautobot/extras/templates/extras/configcontextschema_edit.html +0 -2
- nautobot/extras/templates/extras/contact_retrieve.html +0 -2
- nautobot/extras/templates/extras/customfield.html +0 -2
- nautobot/extras/templates/extras/customfield_edit.html +0 -2
- nautobot/extras/templates/extras/customfield_retrieve.html +0 -2
- nautobot/extras/templates/extras/customlink.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup.html +0 -2
- nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -2
- nautobot/extras/templates/extras/exporttemplate.html +0 -2
- nautobot/extras/templates/extras/gitrepository.html +0 -2
- nautobot/extras/templates/extras/gitrepository_object_edit.html +0 -2
- nautobot/extras/templates/extras/graphqlquery.html +0 -2
- nautobot/extras/templates/extras/graphqlquery_list.html +0 -1
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +0 -97
- nautobot/extras/templates/extras/job_detail.html +0 -2
- nautobot/extras/templates/extras/jobbutton_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobhook.html +0 -2
- nautobot/extras/templates/extras/jobqueue_retrieve.html +0 -2
- nautobot/extras/templates/extras/jobresult.html +0 -2
- nautobot/extras/templates/extras/metadatatype_retrieve.html +0 -2
- nautobot/extras/templates/extras/note.html +0 -2
- nautobot/extras/templates/extras/note_retrieve.html +0 -1
- nautobot/extras/templates/extras/object_changelog.html +0 -2
- nautobot/extras/templates/extras/object_notes.html +0 -2
- nautobot/extras/templates/extras/objectchange.html +0 -2
- nautobot/extras/templates/extras/objectchange_list.html +0 -3
- nautobot/extras/templates/extras/relationship.html +0 -1
- nautobot/extras/templates/extras/secret.html +0 -1
- nautobot/extras/templates/extras/secret_edit.html +0 -1
- nautobot/extras/templates/extras/secretsgroup.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_edit.html +0 -2
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +0 -2
- nautobot/extras/templates/extras/status.html +0 -2
- nautobot/extras/templates/extras/tag.html +0 -2
- nautobot/extras/templates/extras/tag_edit.html +0 -2
- nautobot/extras/templates/extras/tag_retrieve.html +0 -2
- nautobot/extras/templates/extras/team_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +0 -4
- nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -1
- nautobot/ipam/templates/ipam/prefix.html +0 -2
- nautobot/ipam/templates/ipam/prefix_edit.html +0 -1
- nautobot/ipam/templates/ipam/prefix_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/rir.html +0 -2
- nautobot/ipam/templates/ipam/routetarget.html +0 -1
- nautobot/ipam/templates/ipam/service.html +0 -2
- nautobot/ipam/templates/ipam/service_edit.html +0 -2
- nautobot/ipam/templates/ipam/service_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlan.html +0 -2
- nautobot/ipam/templates/ipam/vlan_edit.html +0 -2
- nautobot/ipam/templates/ipam/vlan_retrieve.html +0 -2
- nautobot/ipam/templates/ipam/vlangroup.html +0 -2
- nautobot/ipam/templates/ipam/vrf.html +0 -1
- nautobot/tenancy/templates/tenancy/tenant.html +0 -2
- nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup.html +0 -2
- nautobot/tenancy/templates/tenancy/tenantgroup_retrieve.html +0 -1
- nautobot/virtualization/templates/virtualization/clustergroup.html +0 -2
- nautobot/virtualization/templates/virtualization/clustertype.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +0 -2
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/radioprofile_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +0 -2
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +0 -2
- /nautobot/dcim/templates/dcim/{cable.html → cable_retrieve.html} +0 -0
- /nautobot/tenancy/{filters/mixins.py → filter_mixins.py} +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/LICENSE.txt +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/NOTICE +0 -0
- {nautobot-3.0.0a2.dist-info → nautobot-3.0.0rc1.dist-info}/WHEEL +0 -0
nautobot/dcim/forms.py
CHANGED
|
@@ -27,7 +27,9 @@ from nautobot.core.forms import (
|
|
|
27
27
|
form_from_model,
|
|
28
28
|
JSONArrayFormField,
|
|
29
29
|
MultipleContentTypeField,
|
|
30
|
+
MultiValueCharInput,
|
|
30
31
|
NullableDateField,
|
|
32
|
+
NumberWithSelect,
|
|
31
33
|
NumericArrayField,
|
|
32
34
|
SelectWithPK,
|
|
33
35
|
SmallTextarea,
|
|
@@ -37,7 +39,8 @@ from nautobot.core.forms import (
|
|
|
37
39
|
)
|
|
38
40
|
from nautobot.core.forms.constants import BOOLEAN_WITH_BLANK_CHOICES
|
|
39
41
|
from nautobot.core.forms.fields import LaxURLField
|
|
40
|
-
from nautobot.
|
|
42
|
+
from nautobot.core.utils.config import get_settings_or_config
|
|
43
|
+
from nautobot.dcim.constants import RACK_U_HEIGHT_DEFAULT, RACK_U_HEIGHT_MAXIMUM
|
|
41
44
|
from nautobot.dcim.form_mixins import (
|
|
42
45
|
LocatableModelBulkEditFormMixin,
|
|
43
46
|
LocatableModelFilterFormMixin,
|
|
@@ -84,8 +87,10 @@ from .choices import (
|
|
|
84
87
|
ControllerCapabilitiesChoices,
|
|
85
88
|
DeviceFaceChoices,
|
|
86
89
|
DeviceRedundancyGroupFailoverStrategyChoices,
|
|
90
|
+
InterfaceDuplexChoices,
|
|
87
91
|
InterfaceModeChoices,
|
|
88
92
|
InterfaceRedundancyGroupProtocolChoices,
|
|
93
|
+
InterfaceSpeedChoices,
|
|
89
94
|
InterfaceTypeChoices,
|
|
90
95
|
LocationDataToContactActionChoices,
|
|
91
96
|
PortTypeChoices,
|
|
@@ -527,6 +532,17 @@ class RackForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm):
|
|
|
527
532
|
)
|
|
528
533
|
comments = CommentField()
|
|
529
534
|
|
|
535
|
+
def __init__(self, *args, **kwargs):
|
|
536
|
+
super().__init__(*args, **kwargs)
|
|
537
|
+
# Set initial value for u_height from Constance config when creating a new rack
|
|
538
|
+
if not self.instance.present_in_database and not kwargs.get("data"):
|
|
539
|
+
# Only set initial if this is a new form (not submitted data)
|
|
540
|
+
config_default = get_settings_or_config("RACK_DEFAULT_U_HEIGHT", fallback=RACK_U_HEIGHT_DEFAULT)
|
|
541
|
+
self.fields["u_height"].initial = config_default
|
|
542
|
+
# Override the form's initial dict to ensure it displays the Constance config value
|
|
543
|
+
# (unconditionally set it, even if already present from model default)
|
|
544
|
+
self.initial["u_height"] = config_default
|
|
545
|
+
|
|
530
546
|
class Meta:
|
|
531
547
|
model = Rack
|
|
532
548
|
fields = [
|
|
@@ -1460,16 +1476,29 @@ class InterfaceTemplateForm(ModularComponentTemplateForm):
|
|
|
1460
1476
|
"label",
|
|
1461
1477
|
"type",
|
|
1462
1478
|
"mgmt_only",
|
|
1479
|
+
"speed",
|
|
1480
|
+
"duplex",
|
|
1463
1481
|
"description",
|
|
1464
1482
|
]
|
|
1465
1483
|
widgets = {
|
|
1466
1484
|
"type": StaticSelect2(),
|
|
1485
|
+
"speed": NumberWithSelect(choices=InterfaceSpeedChoices),
|
|
1486
|
+
"duplex": StaticSelect2(),
|
|
1487
|
+
}
|
|
1488
|
+
labels = {
|
|
1489
|
+
"speed": "Speed (Kbps)",
|
|
1467
1490
|
}
|
|
1468
1491
|
|
|
1469
1492
|
|
|
1470
1493
|
class InterfaceTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1471
1494
|
type = forms.ChoiceField(choices=InterfaceTypeChoices, widget=StaticSelect2())
|
|
1472
1495
|
mgmt_only = forms.BooleanField(required=False, label="Management only")
|
|
1496
|
+
speed = forms.IntegerField(
|
|
1497
|
+
required=False, min_value=0, label="Speed (Kbps)", widget=NumberWithSelect(choices=InterfaceSpeedChoices)
|
|
1498
|
+
)
|
|
1499
|
+
duplex = forms.ChoiceField(
|
|
1500
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
1501
|
+
)
|
|
1473
1502
|
field_order = (
|
|
1474
1503
|
"device_type",
|
|
1475
1504
|
"module_family",
|
|
@@ -1478,6 +1507,8 @@ class InterfaceTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
|
1478
1507
|
"label_pattern",
|
|
1479
1508
|
"type",
|
|
1480
1509
|
"mgmt_only",
|
|
1510
|
+
"speed",
|
|
1511
|
+
"duplex",
|
|
1481
1512
|
"description",
|
|
1482
1513
|
)
|
|
1483
1514
|
|
|
@@ -1491,10 +1522,16 @@ class InterfaceTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1491
1522
|
widget=StaticSelect2(),
|
|
1492
1523
|
)
|
|
1493
1524
|
mgmt_only = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label="Management only")
|
|
1525
|
+
speed = forms.IntegerField(
|
|
1526
|
+
required=False, min_value=0, label="Speed (Kbps)", widget=NumberWithSelect(choices=InterfaceSpeedChoices)
|
|
1527
|
+
)
|
|
1528
|
+
duplex = forms.ChoiceField(
|
|
1529
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
1530
|
+
)
|
|
1494
1531
|
description = forms.CharField(required=False)
|
|
1495
1532
|
|
|
1496
1533
|
class Meta:
|
|
1497
|
-
nullable_fields = ["label", "description"]
|
|
1534
|
+
nullable_fields = ["label", "speed", "duplex", "description"]
|
|
1498
1535
|
|
|
1499
1536
|
|
|
1500
1537
|
class FrontPortTemplateForm(ModularComponentTemplateForm):
|
|
@@ -1965,6 +2002,8 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1965
2002
|
"label",
|
|
1966
2003
|
"type",
|
|
1967
2004
|
"mgmt_only",
|
|
2005
|
+
"speed",
|
|
2006
|
+
"duplex",
|
|
1968
2007
|
]
|
|
1969
2008
|
|
|
1970
2009
|
|
|
@@ -3137,6 +3176,7 @@ class PowerOutletBulkEditForm(
|
|
|
3137
3176
|
class InterfaceFilterForm(ModularDeviceComponentFilterForm, RoleModelFilterFormMixin, StatusModelFilterFormMixin):
|
|
3138
3177
|
model = Interface
|
|
3139
3178
|
type = forms.MultipleChoiceField(choices=InterfaceTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
3179
|
+
speed = forms.MultipleChoiceField(choices=InterfaceSpeedChoices, required=False, widget=MultiValueCharInput)
|
|
3140
3180
|
enabled = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
|
|
3141
3181
|
mgmt_only = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
|
|
3142
3182
|
mac_address = forms.CharField(required=False, label="MAC address")
|
|
@@ -3221,6 +3261,8 @@ class InterfaceForm(InterfaceCommonForm, ModularComponentEditForm):
|
|
|
3221
3261
|
"bridge",
|
|
3222
3262
|
"lag",
|
|
3223
3263
|
"mac_address",
|
|
3264
|
+
"speed",
|
|
3265
|
+
"duplex",
|
|
3224
3266
|
"ip_addresses",
|
|
3225
3267
|
"virtual_device_contexts",
|
|
3226
3268
|
"mtu",
|
|
@@ -3236,9 +3278,12 @@ class InterfaceForm(InterfaceCommonForm, ModularComponentEditForm):
|
|
|
3236
3278
|
widgets = {
|
|
3237
3279
|
"type": StaticSelect2(),
|
|
3238
3280
|
"mode": StaticSelect2(),
|
|
3281
|
+
"speed": NumberWithSelect(choices=InterfaceSpeedChoices),
|
|
3282
|
+
"duplex": StaticSelect2(),
|
|
3239
3283
|
}
|
|
3240
3284
|
labels = {
|
|
3241
3285
|
"mode": "802.1Q Mode",
|
|
3286
|
+
"speed": "Speed (Kbps)",
|
|
3242
3287
|
}
|
|
3243
3288
|
help_texts = {
|
|
3244
3289
|
"mode": INTERFACE_MODE_HELP_TEXT,
|
|
@@ -3311,6 +3356,12 @@ class InterfaceCreateForm(ModularComponentCreateForm, InterfaceCommonForm, RoleN
|
|
|
3311
3356
|
},
|
|
3312
3357
|
)
|
|
3313
3358
|
mac_address = forms.CharField(required=False, label="MAC Address")
|
|
3359
|
+
speed = forms.IntegerField(
|
|
3360
|
+
required=False, min_value=0, label="Speed (Kbps)", widget=NumberWithSelect(choices=InterfaceSpeedChoices)
|
|
3361
|
+
)
|
|
3362
|
+
duplex = forms.ChoiceField(
|
|
3363
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
3364
|
+
)
|
|
3314
3365
|
mgmt_only = forms.BooleanField(
|
|
3315
3366
|
required=False,
|
|
3316
3367
|
label="Management only",
|
|
@@ -3357,6 +3408,8 @@ class InterfaceCreateForm(ModularComponentCreateForm, InterfaceCommonForm, RoleN
|
|
|
3357
3408
|
"status",
|
|
3358
3409
|
"role",
|
|
3359
3410
|
"type",
|
|
3411
|
+
"speed",
|
|
3412
|
+
"duplex",
|
|
3360
3413
|
"enabled",
|
|
3361
3414
|
"parent_interface",
|
|
3362
3415
|
"bridge",
|
|
@@ -3390,6 +3443,10 @@ class InterfaceBulkCreateForm(
|
|
|
3390
3443
|
queryset=Status.objects.all(),
|
|
3391
3444
|
query_params={"content_types": Interface._meta.label_lower},
|
|
3392
3445
|
)
|
|
3446
|
+
speed = forms.IntegerField(required=False, min_value=0, label="Speed (Kbps)")
|
|
3447
|
+
duplex = forms.ChoiceField(
|
|
3448
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
3449
|
+
)
|
|
3393
3450
|
|
|
3394
3451
|
field_order = (
|
|
3395
3452
|
"name_pattern",
|
|
@@ -3403,6 +3460,8 @@ class InterfaceBulkCreateForm(
|
|
|
3403
3460
|
"mgmt_only",
|
|
3404
3461
|
"description",
|
|
3405
3462
|
"mode",
|
|
3463
|
+
"speed",
|
|
3464
|
+
"duplex",
|
|
3406
3465
|
"tags",
|
|
3407
3466
|
)
|
|
3408
3467
|
|
|
@@ -3422,6 +3481,10 @@ class ModuleInterfaceBulkCreateForm(
|
|
|
3422
3481
|
queryset=Status.objects.all(),
|
|
3423
3482
|
query_params={"content_types": Interface._meta.label_lower},
|
|
3424
3483
|
)
|
|
3484
|
+
speed = forms.IntegerField(required=False, min_value=0, label="Speed (Kbps)")
|
|
3485
|
+
duplex = forms.ChoiceField(
|
|
3486
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
3487
|
+
)
|
|
3425
3488
|
|
|
3426
3489
|
field_order = (
|
|
3427
3490
|
"name_pattern",
|
|
@@ -3435,13 +3498,28 @@ class ModuleInterfaceBulkCreateForm(
|
|
|
3435
3498
|
"mgmt_only",
|
|
3436
3499
|
"description",
|
|
3437
3500
|
"mode",
|
|
3501
|
+
"speed",
|
|
3502
|
+
"duplex",
|
|
3438
3503
|
"tags",
|
|
3439
3504
|
)
|
|
3440
3505
|
|
|
3441
3506
|
|
|
3442
3507
|
class InterfaceBulkEditForm(
|
|
3443
3508
|
form_from_model(
|
|
3444
|
-
Interface,
|
|
3509
|
+
Interface,
|
|
3510
|
+
[
|
|
3511
|
+
"label",
|
|
3512
|
+
"type",
|
|
3513
|
+
"parent_interface",
|
|
3514
|
+
"bridge",
|
|
3515
|
+
"lag",
|
|
3516
|
+
"mac_address",
|
|
3517
|
+
"mtu",
|
|
3518
|
+
"description",
|
|
3519
|
+
"mode",
|
|
3520
|
+
"speed",
|
|
3521
|
+
"duplex",
|
|
3522
|
+
],
|
|
3445
3523
|
),
|
|
3446
3524
|
TagsBulkEditFormMixin,
|
|
3447
3525
|
StatusModelBulkEditFormMixin,
|
|
@@ -3485,6 +3563,12 @@ class InterfaceBulkEditForm(
|
|
|
3485
3563
|
label="VRF",
|
|
3486
3564
|
required=False,
|
|
3487
3565
|
)
|
|
3566
|
+
speed = forms.IntegerField(
|
|
3567
|
+
required=False, min_value=0, label="Speed (Kbps)", widget=NumberWithSelect(choices=InterfaceSpeedChoices)
|
|
3568
|
+
)
|
|
3569
|
+
duplex = forms.ChoiceField(
|
|
3570
|
+
choices=add_blank_choice(InterfaceDuplexChoices), required=False, widget=StaticSelect2(), label="Duplex"
|
|
3571
|
+
)
|
|
3488
3572
|
|
|
3489
3573
|
class Meta:
|
|
3490
3574
|
nullable_fields = [
|
|
@@ -3496,6 +3580,8 @@ class InterfaceBulkEditForm(
|
|
|
3496
3580
|
"mtu",
|
|
3497
3581
|
"description",
|
|
3498
3582
|
"mode",
|
|
3583
|
+
"speed",
|
|
3584
|
+
"duplex",
|
|
3499
3585
|
"untagged_vlan",
|
|
3500
3586
|
"tagged_vlans",
|
|
3501
3587
|
"vrf",
|
|
@@ -4577,7 +4663,7 @@ class BaseVCMemberFormSet(forms.BaseModelFormSet):
|
|
|
4577
4663
|
vc_position_list.append(vc_position)
|
|
4578
4664
|
|
|
4579
4665
|
|
|
4580
|
-
class DeviceVCMembershipForm(forms.ModelForm):
|
|
4666
|
+
class DeviceVCMembershipForm(BootstrapMixin, forms.ModelForm):
|
|
4581
4667
|
class Meta:
|
|
4582
4668
|
model = Device
|
|
4583
4669
|
fields = [
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by Django 4.2.25 on 2025-11-01 22:09
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("dcim", "0074_alter_rack_u_height"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.AddField(
|
|
13
|
+
model_name="interface",
|
|
14
|
+
name="duplex",
|
|
15
|
+
field=models.CharField(blank=True, default="", max_length=10),
|
|
16
|
+
),
|
|
17
|
+
migrations.AddField(
|
|
18
|
+
model_name="interface",
|
|
19
|
+
name="speed",
|
|
20
|
+
field=models.PositiveIntegerField(blank=True, null=True),
|
|
21
|
+
),
|
|
22
|
+
migrations.AddField(
|
|
23
|
+
model_name="interfacetemplate",
|
|
24
|
+
name="duplex",
|
|
25
|
+
field=models.CharField(blank=True, default="", max_length=10),
|
|
26
|
+
),
|
|
27
|
+
migrations.AddField(
|
|
28
|
+
model_name="interfacetemplate",
|
|
29
|
+
name="speed",
|
|
30
|
+
field=models.PositiveIntegerField(blank=True, null=True),
|
|
31
|
+
),
|
|
32
|
+
]
|
nautobot/dcim/migrations/{0075_add_deviceclusterassignment.py → 0076_add_deviceclusterassignment.py}
RENAMED
|
@@ -6,7 +6,7 @@ import django.db.models.deletion
|
|
|
6
6
|
|
|
7
7
|
class Migration(migrations.Migration):
|
|
8
8
|
dependencies = [
|
|
9
|
-
("dcim", "
|
|
9
|
+
("dcim", "0075_interface_duplex_interface_speed_and_more"),
|
|
10
10
|
("virtualization", "0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more"),
|
|
11
11
|
]
|
|
12
12
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Generated by Django 4.2.24 on 2025-10-07 07:18
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
dependencies = [
|
|
8
|
+
("dcim", "0078_remove_device_cluster"),
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
operations = [
|
|
12
|
+
migrations.AlterUniqueTogether(
|
|
13
|
+
name="device",
|
|
14
|
+
unique_together={("rack", "position", "face"), ("virtual_chassis", "vc_position")},
|
|
15
|
+
),
|
|
16
|
+
]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Generated by Django 4.2.24 on 2025-10-07 07:18
|
|
2
|
+
|
|
3
|
+
from constance.models import Constance
|
|
4
|
+
from django.db import migrations
|
|
5
|
+
|
|
6
|
+
from nautobot.core.utils.config import get_settings_or_config
|
|
7
|
+
from nautobot.dcim.choices import DeviceUniquenessChoices
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def migrate_device_uniqueness_setting(apps, schema_editor):
|
|
11
|
+
"""
|
|
12
|
+
Migrate deprecated DEVICE_NAME_AS_NATURAL_KEY setting to DEVICE_UNIQUENESS and DEVICE_NAME_REQUIRED.
|
|
13
|
+
"""
|
|
14
|
+
try:
|
|
15
|
+
old_value = get_settings_or_config("DEVICE_NAME_AS_NATURAL_KEY")
|
|
16
|
+
except AttributeError:
|
|
17
|
+
old_value = False
|
|
18
|
+
new_value = DeviceUniquenessChoices.NAME if old_value else DeviceUniquenessChoices.LOCATION_TENANT_NAME
|
|
19
|
+
|
|
20
|
+
# Update or create DEVICE_UNIQUENESS in Constance
|
|
21
|
+
Constance.objects.update_or_create(
|
|
22
|
+
key="DEVICE_UNIQUENESS",
|
|
23
|
+
defaults={"value": new_value},
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# cleanup: remove deprecated setting entry if it exists
|
|
27
|
+
Constance.objects.filter(key="DEVICE_NAME_AS_NATURAL_KEY").delete()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def reverse_migrate_device_uniqueness_setting(apps, schema_editor):
|
|
31
|
+
"""
|
|
32
|
+
Reverse migration set DEVICE_NAME_AS_NATURAL_KEY based on DEVICE_UNIQUENESS.
|
|
33
|
+
"""
|
|
34
|
+
try:
|
|
35
|
+
device_uniqueness = Constance.objects.get(key="DEVICE_UNIQUENESS").value
|
|
36
|
+
except Constance.DoesNotExist:
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
if device_uniqueness == DeviceUniquenessChoices.NAME:
|
|
40
|
+
Constance.objects.update_or_create(key="DEVICE_NAME_AS_NATURAL_KEY", defaults={"value": True})
|
|
41
|
+
else:
|
|
42
|
+
Constance.objects.update_or_create(key="DEVICE_NAME_AS_NATURAL_KEY", defaults={"value": False})
|
|
43
|
+
|
|
44
|
+
# cleanup: remove DEVICE_UNIQUENESS setting entry if it exists
|
|
45
|
+
Constance.objects.filter(key="DEVICE_UNIQUENESS").delete()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Migration(migrations.Migration):
|
|
49
|
+
dependencies = [
|
|
50
|
+
("dcim", "0079_remove_device_location_tenant_name_uniqueness"),
|
|
51
|
+
("constance", "0003_drop_pickle"),
|
|
52
|
+
]
|
|
53
|
+
|
|
54
|
+
operations = [
|
|
55
|
+
migrations.RunPython(
|
|
56
|
+
migrate_device_uniqueness_setting,
|
|
57
|
+
reverse_migrate_device_uniqueness_setting,
|
|
58
|
+
),
|
|
59
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Generated by Django 4.2.25 on 2025-11-05 19:42
|
|
2
|
+
|
|
3
|
+
import django.core.validators
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
dependencies = [
|
|
9
|
+
("dcim", "0080_device_name_data_migration"),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AlterField(
|
|
14
|
+
model_name="device",
|
|
15
|
+
name="device_redundancy_group_priority",
|
|
16
|
+
field=models.PositiveIntegerField(
|
|
17
|
+
blank=True, null=True, validators=[django.core.validators.MinValueValidator(1)]
|
|
18
|
+
),
|
|
19
|
+
),
|
|
20
|
+
migrations.AlterField(
|
|
21
|
+
model_name="interfaceredundancygroupassociation",
|
|
22
|
+
name="priority",
|
|
23
|
+
field=models.PositiveIntegerField(),
|
|
24
|
+
),
|
|
25
|
+
]
|
|
@@ -11,6 +11,7 @@ from nautobot.core.models.fields import ForeignKeyWithAutoRelatedName, NaturalOr
|
|
|
11
11
|
from nautobot.core.models.ordering import naturalize_interface
|
|
12
12
|
from nautobot.dcim.choices import (
|
|
13
13
|
ConsolePortTypeChoices,
|
|
14
|
+
InterfaceDuplexChoices,
|
|
14
15
|
InterfaceTypeChoices,
|
|
15
16
|
PortTypeChoices,
|
|
16
17
|
PowerOutletFeedLegChoices,
|
|
@@ -18,7 +19,13 @@ from nautobot.dcim.choices import (
|
|
|
18
19
|
PowerPortTypeChoices,
|
|
19
20
|
SubdeviceRoleChoices,
|
|
20
21
|
)
|
|
21
|
-
from nautobot.dcim.constants import
|
|
22
|
+
from nautobot.dcim.constants import (
|
|
23
|
+
COPPER_TWISTED_PAIR_IFACE_TYPES,
|
|
24
|
+
REARPORT_POSITIONS_MAX,
|
|
25
|
+
REARPORT_POSITIONS_MIN,
|
|
26
|
+
VIRTUAL_IFACE_TYPES,
|
|
27
|
+
WIRELESS_IFACE_TYPES,
|
|
28
|
+
)
|
|
22
29
|
from nautobot.extras.models import (
|
|
23
30
|
ChangeLoggedModel,
|
|
24
31
|
ContactMixin,
|
|
@@ -349,6 +356,29 @@ class InterfaceTemplate(ModularComponentTemplateModel):
|
|
|
349
356
|
)
|
|
350
357
|
type = models.CharField(max_length=50, choices=InterfaceTypeChoices)
|
|
351
358
|
mgmt_only = models.BooleanField(default=False, verbose_name="Management only")
|
|
359
|
+
speed = models.PositiveIntegerField(null=True, blank=True)
|
|
360
|
+
duplex = models.CharField(max_length=10, choices=InterfaceDuplexChoices, blank=True, default="")
|
|
361
|
+
|
|
362
|
+
def clean(self):
|
|
363
|
+
super().clean()
|
|
364
|
+
self._validate_speed_and_duplex()
|
|
365
|
+
|
|
366
|
+
def _validate_speed_and_duplex(self):
|
|
367
|
+
"""Validate speed (Kbps) and duplex based on interface type."""
|
|
368
|
+
|
|
369
|
+
is_lag = self.type == InterfaceTypeChoices.TYPE_LAG
|
|
370
|
+
is_virtual = self.type in VIRTUAL_IFACE_TYPES
|
|
371
|
+
is_wireless = self.type in WIRELESS_IFACE_TYPES
|
|
372
|
+
|
|
373
|
+
# Check settings by interface type
|
|
374
|
+
if self.speed and any([is_lag, is_virtual, is_wireless]):
|
|
375
|
+
raise ValidationError({"speed": "Speed is not applicable to this interface type."})
|
|
376
|
+
|
|
377
|
+
if self.duplex and any([is_lag, is_virtual, is_wireless]):
|
|
378
|
+
raise ValidationError({"duplex": "Duplex is not applicable to this interface type."})
|
|
379
|
+
|
|
380
|
+
if self.duplex and self.type not in COPPER_TWISTED_PAIR_IFACE_TYPES:
|
|
381
|
+
raise ValidationError({"duplex": "Duplex is only applicable to copper twisted-pair interfaces."})
|
|
352
382
|
|
|
353
383
|
def instantiate(self, device, module=None):
|
|
354
384
|
try:
|
|
@@ -361,6 +391,8 @@ class InterfaceTemplate(ModularComponentTemplateModel):
|
|
|
361
391
|
module=module,
|
|
362
392
|
type=self.type,
|
|
363
393
|
mgmt_only=self.mgmt_only,
|
|
394
|
+
speed=self.speed,
|
|
395
|
+
duplex=self.duplex,
|
|
364
396
|
status=status,
|
|
365
397
|
)
|
|
366
398
|
|