nautobot 2.2.9__py3-none-any.whl → 2.3.0b1__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.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/forms.py +4 -0
- nautobot/apps/models.py +10 -1
- nautobot/circuits/__init__.py +0 -1
- nautobot/circuits/apps.py +1 -0
- nautobot/circuits/factory.py +15 -3
- nautobot/circuits/filters.py +13 -0
- nautobot/circuits/forms.py +13 -0
- nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
- nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
- nautobot/circuits/models.py +16 -3
- nautobot/circuits/tables.py +16 -2
- nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
- nautobot/circuits/tests/test_api.py +7 -5
- nautobot/circuits/tests/test_filters.py +12 -5
- nautobot/circuits/tests/test_models.py +33 -2
- nautobot/circuits/views.py +2 -3
- nautobot/cloud/__init__.py +0 -0
- nautobot/cloud/api/__init__.py +0 -0
- nautobot/cloud/api/serializers.py +54 -0
- nautobot/cloud/api/urls.py +16 -0
- nautobot/cloud/api/views.py +48 -0
- nautobot/cloud/apps.py +13 -0
- nautobot/cloud/factory.py +111 -0
- nautobot/cloud/filters.py +184 -0
- nautobot/cloud/forms.py +333 -0
- nautobot/cloud/homepage.py +43 -0
- nautobot/cloud/migrations/0001_initial.py +304 -0
- nautobot/cloud/migrations/__init__.py +0 -0
- nautobot/cloud/models.py +247 -0
- nautobot/cloud/navigation.py +85 -0
- nautobot/cloud/tables.py +173 -0
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +128 -0
- nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +100 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +65 -0
- nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
- nautobot/cloud/tests/__init__.py +0 -0
- nautobot/cloud/tests/test_api.py +248 -0
- nautobot/cloud/tests/test_filters.py +113 -0
- nautobot/cloud/tests/test_models.py +43 -0
- nautobot/cloud/tests/test_views.py +153 -0
- nautobot/cloud/urls.py +14 -0
- nautobot/cloud/views.py +181 -0
- nautobot/core/__init__.py +0 -3
- nautobot/core/api/metadata.py +1 -0
- nautobot/core/api/parsers.py +7 -1
- nautobot/core/api/urls.py +1 -0
- nautobot/core/api/utils.py +1 -0
- nautobot/core/api/views.py +4 -0
- nautobot/core/apps/__init__.py +6 -3
- nautobot/core/constants.py +8 -0
- nautobot/core/factory.py +32 -1
- nautobot/core/filters.py +96 -28
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +1 -1
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +34 -4
- nautobot/core/jobs/__init__.py +17 -6
- nautobot/core/jobs/cleanup.py +100 -0
- nautobot/core/jobs/groups.py +38 -0
- nautobot/core/management/commands/generate_test_data.py +116 -3
- nautobot/core/models/__init__.py +34 -9
- nautobot/core/models/generics.py +19 -3
- nautobot/core/models/name_color_content_types.py +7 -28
- nautobot/core/models/querysets.py +4 -3
- nautobot/core/models/tree_queries.py +1 -1
- nautobot/core/models/utils.py +21 -5
- nautobot/core/settings.py +4 -30
- nautobot/core/settings.yaml +34 -27
- nautobot/core/settings_funcs.py +103 -0
- nautobot/core/tables.py +127 -56
- nautobot/core/templates/admin/search_form.html +1 -1
- nautobot/core/templates/buttons/add.html +11 -3
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
- nautobot/core/templates/buttons/export.html +101 -53
- nautobot/core/templates/buttons/job_import.html +11 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
- nautobot/core/templates/generic/object_bulk_update.html +3 -1
- nautobot/core/templates/generic/object_changelog.html +0 -9
- nautobot/core/templates/generic/object_list.html +156 -17
- nautobot/core/templates/generic/object_retrieve.html +80 -16
- nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
- nautobot/core/templates/inc/javascript.html +2 -0
- nautobot/core/templates/inc/media.html +2 -2
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/paginator.html +7 -7
- nautobot/core/templates/inc/search_panel.html +2 -2
- nautobot/core/templates/inc/table.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +13 -23
- nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
- nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
- nautobot/core/templates/utilities/theme_preview.html +25 -8
- nautobot/core/templates/utilities/worker_status.html +152 -0
- nautobot/core/templatetags/buttons.py +335 -38
- nautobot/core/templatetags/form_helpers.py +1 -1
- nautobot/core/templatetags/helpers.py +181 -11
- nautobot/core/testing/api.py +5 -4
- nautobot/core/testing/filters.py +51 -13
- nautobot/core/testing/mixins.py +46 -0
- nautobot/core/testing/models.py +22 -0
- nautobot/core/testing/schema.py +4 -8
- nautobot/core/testing/views.py +31 -14
- nautobot/core/tests/integration/test_general_functionality.py +1 -1
- nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
- nautobot/core/tests/integration/test_swagger.py +1 -1
- nautobot/core/tests/nautobot_config.py +0 -1
- nautobot/core/tests/runner.py +2 -2
- nautobot/core/tests/test_api.py +1 -0
- nautobot/core/tests/test_authentication.py +7 -2
- nautobot/core/tests/test_filters.py +11 -9
- nautobot/core/tests/test_forms.py +9 -0
- nautobot/core/tests/test_graphql.py +27 -16
- nautobot/core/tests/test_jobs.py +123 -74
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +12 -5
- nautobot/core/tests/test_utils.py +31 -20
- nautobot/core/tests/test_views.py +6 -6
- nautobot/core/urls.py +8 -3
- nautobot/core/utils/deprecation.py +29 -0
- nautobot/core/utils/filtering.py +12 -9
- nautobot/core/utils/lookup.py +37 -2
- nautobot/core/utils/requests.py +4 -1
- nautobot/core/views/__init__.py +137 -24
- nautobot/core/views/generic.py +118 -66
- nautobot/core/views/mixins.py +104 -35
- nautobot/core/views/paginator.py +9 -3
- nautobot/core/views/renderers.py +121 -56
- nautobot/core/views/utils.py +79 -1
- nautobot/dcim/__init__.py +0 -1
- nautobot/dcim/api/serializers.py +180 -44
- nautobot/dcim/api/urls.py +7 -3
- nautobot/dcim/api/views.py +53 -7
- nautobot/dcim/apps.py +3 -0
- nautobot/dcim/choices.py +25 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/factory.py +249 -18
- nautobot/dcim/filters/__init__.py +369 -193
- nautobot/dcim/filters/mixins.py +274 -1
- nautobot/dcim/forms.py +817 -109
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/homepage.py +1 -1
- nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
- nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
- nautobot/dcim/migrations/0061_module_models.py +861 -0
- nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
- nautobot/dcim/models/__init__.py +8 -0
- nautobot/dcim/models/cables.py +15 -0
- nautobot/dcim/models/device_component_templates.py +207 -53
- nautobot/dcim/models/device_components.py +275 -106
- nautobot/dcim/models/devices.py +466 -13
- nautobot/dcim/navigation.py +47 -0
- nautobot/dcim/signals.py +3 -3
- nautobot/dcim/tables/__init__.py +35 -23
- nautobot/dcim/tables/devices.py +231 -59
- nautobot/dcim/tables/devicetypes.py +65 -9
- nautobot/dcim/tables/racks.py +5 -1
- nautobot/dcim/tables/template_code.py +46 -26
- nautobot/dcim/templates/dcim/cable_connect.html +76 -3
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/device/base.html +15 -7
- nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
- nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
- nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
- nautobot/dcim/templates/dcim/device/frontports.html +2 -3
- nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
- nautobot/dcim/templates/dcim/device/inventory.html +2 -3
- nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
- nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
- nautobot/dcim/templates/dcim/device/powerports.html +2 -3
- nautobot/dcim/templates/dcim/device/rearports.html +2 -3
- nautobot/dcim/templates/dcim/device.html +45 -1
- nautobot/dcim/templates/dcim/device_component.html +13 -5
- nautobot/dcim/templates/dcim/device_list.html +2 -1
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -6
- nautobot/dcim/templates/dcim/devicetype.html +99 -98
- nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
- nautobot/dcim/templates/dcim/interface.html +17 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/manufacturer.html +24 -0
- nautobot/dcim/templates/dcim/module/base.html +97 -0
- nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
- nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
- nautobot/dcim/templates/dcim/module_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_frontports.html +53 -0
- nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
- nautobot/dcim/templates/dcim/module_list.html +20 -0
- nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
- nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
- nautobot/dcim/templates/dcim/module_powerports.html +53 -0
- nautobot/dcim/templates/dcim/module_rearports.html +53 -0
- nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
- nautobot/dcim/templates/dcim/module_update.html +71 -0
- nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
- nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +142 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +691 -208
- nautobot/dcim/tests/test_filters.py +836 -217
- nautobot/dcim/tests/test_models.py +1072 -39
- nautobot/dcim/tests/test_views.py +1488 -358
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1107 -120
- nautobot/extras/__init__.py +0 -1
- nautobot/extras/api/serializers.py +115 -3
- nautobot/extras/api/urls.py +12 -0
- nautobot/extras/api/views.py +125 -7
- nautobot/extras/apps.py +2 -2
- nautobot/extras/choices.py +43 -0
- nautobot/extras/context_managers.py +13 -8
- nautobot/extras/datasources/git.py +2 -0
- nautobot/extras/factory.py +422 -9
- nautobot/extras/filters/__init__.py +174 -3
- nautobot/extras/filters/mixins.py +46 -43
- nautobot/extras/forms/base.py +17 -4
- nautobot/extras/forms/forms.py +227 -8
- nautobot/extras/forms/mixins.py +93 -0
- nautobot/extras/graphql/types.py +23 -10
- nautobot/extras/homepage.py +16 -13
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
- nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
- nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
- nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
- nautobot/extras/migrations/0111_metadata.py +162 -0
- nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
- nautobot/extras/migrations/0113_saved_views.py +77 -0
- nautobot/extras/models/__init__.py +15 -1
- nautobot/extras/models/change_logging.py +3 -3
- nautobot/extras/models/contacts.py +4 -0
- nautobot/extras/models/customfields.py +18 -3
- nautobot/extras/models/groups.py +389 -225
- nautobot/extras/models/jobs.py +4 -84
- nautobot/extras/models/metadata.py +441 -0
- nautobot/extras/models/mixins.py +72 -62
- nautobot/extras/models/models.py +116 -9
- nautobot/extras/models/relationships.py +9 -2
- nautobot/extras/models/tags.py +13 -2
- nautobot/extras/navigation.py +57 -0
- nautobot/extras/plugins/__init__.py +3 -1
- nautobot/extras/querysets.py +30 -66
- nautobot/extras/signals.py +96 -114
- nautobot/extras/tables.py +171 -47
- nautobot/extras/templates/extras/dynamicgroup.html +44 -15
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
- nautobot/extras/templates/extras/job.html +1 -1
- nautobot/extras/templates/extras/job_detail.html +0 -11
- nautobot/extras/templates/extras/jobresult.html +61 -74
- nautobot/extras/templates/extras/metadatatype_create.html +89 -0
- nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
- nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
- nautobot/extras/templates/extras/objectchange_list.html +0 -12
- nautobot/extras/templates/extras/plugins_list.html +1 -3
- nautobot/extras/templates/extras/role_retrieve.html +48 -0
- nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
- nautobot/extras/tests/integration/test_customfields.py +1 -0
- nautobot/extras/tests/test_api.py +501 -22
- nautobot/extras/tests/test_changelog.py +20 -9
- nautobot/extras/tests/test_context_managers.py +22 -15
- nautobot/extras/tests/test_datasources.py +13 -1
- nautobot/extras/tests/test_dynamicgroups.py +201 -171
- nautobot/extras/tests/test_filters.py +211 -12
- nautobot/extras/tests/test_jobs.py +4 -4
- nautobot/extras/tests/test_models.py +499 -4
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +565 -28
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +56 -45
- nautobot/extras/views.py +585 -96
- nautobot/ipam/__init__.py +0 -1
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/factory.py +17 -19
- nautobot/ipam/filters.py +14 -1
- nautobot/ipam/forms.py +9 -5
- nautobot/ipam/graphql/types.py +2 -2
- nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
- nautobot/ipam/models.py +23 -9
- nautobot/ipam/querysets.py +1 -1
- nautobot/ipam/signals.py +4 -2
- nautobot/ipam/tables.py +1 -0
- nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +1 -0
- nautobot/ipam/tests/test_api.py +37 -18
- nautobot/ipam/tests/test_filters.py +26 -2
- nautobot/ipam/tests/test_models.py +8 -3
- nautobot/ipam/tests/test_querysets.py +1 -1
- nautobot/ipam/tests/test_views.py +3 -2
- nautobot/ipam/urls.py +2 -2
- nautobot/ipam/views.py +25 -28
- nautobot/project-static/css/base.css +20 -1
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +884 -80
- nautobot/project-static/docs/apps/index.html +884 -80
- nautobot/project-static/docs/apps/nautobot-apps.html +884 -80
- nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +911 -112
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +896 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1457 -790
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +927 -136
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +969 -180
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +893 -91
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +889 -85
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +983 -185
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +938 -143
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1064 -274
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1190 -346
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1663 -865
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1156 -373
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2200 -1502
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2229 -1421
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +904 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +955 -155
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1002 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1911 -1275
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1835 -1091
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +896 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2323 -1693
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1785 -1023
- nautobot/project-static/docs/development/apps/api/configuration-view.html +884 -80
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/global-search.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/graphql.html +884 -80
- nautobot/project-static/docs/development/apps/api/models/index.html +922 -81
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +884 -80
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +884 -80
- nautobot/project-static/docs/development/apps/api/prometheus.html +884 -80
- nautobot/project-static/docs/development/apps/api/setup.html +884 -80
- nautobot/project-static/docs/development/apps/api/testing.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +884 -80
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/base-template.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/index.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/notes.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +884 -80
- nautobot/project-static/docs/development/apps/api/views/urls.html +884 -80
- nautobot/project-static/docs/development/apps/index.html +884 -80
- nautobot/project-static/docs/development/apps/migration/code-updates.html +884 -80
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +884 -80
- nautobot/project-static/docs/development/apps/migration/from-v1.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +884 -80
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +884 -80
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +884 -80
- nautobot/project-static/docs/development/core/application-registry.html +884 -80
- nautobot/project-static/docs/development/core/best-practices.html +885 -80
- nautobot/project-static/docs/development/core/bootstrap-ui.html +884 -80
- nautobot/project-static/docs/development/core/caching.html +884 -80
- nautobot/project-static/docs/development/core/controllers.html +884 -80
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +884 -80
- nautobot/project-static/docs/development/core/generic-views.html +884 -80
- nautobot/project-static/docs/development/core/getting-started.html +884 -80
- nautobot/project-static/docs/development/core/homepage.html +884 -80
- nautobot/project-static/docs/development/core/index.html +884 -91
- nautobot/project-static/docs/development/core/model-checklist.html +887 -81
- nautobot/project-static/docs/development/core/model-features.html +884 -80
- nautobot/project-static/docs/development/core/natural-keys.html +884 -80
- nautobot/project-static/docs/development/core/navigation-menu.html +884 -80
- nautobot/project-static/docs/development/core/release-checklist.html +887 -83
- nautobot/project-static/docs/development/core/role-internals.html +884 -80
- nautobot/project-static/docs/development/core/settings.html +884 -80
- nautobot/project-static/docs/development/core/style-guide.html +885 -81
- nautobot/project-static/docs/development/core/templates.html +896 -81
- nautobot/project-static/docs/development/core/testing.html +884 -80
- nautobot/project-static/docs/development/core/user-preferences.html +884 -80
- nautobot/project-static/docs/development/index.html +884 -80
- nautobot/project-static/docs/development/jobs/index.html +1247 -457
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +884 -80
- nautobot/project-static/docs/index.html +13 -8228
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
- nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
- nautobot/project-static/docs/models/dcim/module.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
- nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
- nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
- nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
- nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
- nautobot/project-static/docs/models/extras/role.html +15 -0
- nautobot/project-static/docs/models/extras/savedview.html +15 -0
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
- nautobot/project-static/docs/models/extras/status.html +15 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +892 -81
- nautobot/project-static/docs/overview/design_philosophy.html +886 -82
- nautobot/project-static/docs/overview/index.html +9032 -13
- nautobot/project-static/docs/release-notes/index.html +887 -83
- nautobot/project-static/docs/release-notes/version-1.0.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.1.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.2.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.3.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.4.html +884 -80
- nautobot/project-static/docs/release-notes/version-1.5.html +885 -81
- nautobot/project-static/docs/release-notes/version-1.6.html +885 -81
- nautobot/project-static/docs/release-notes/version-2.0.html +884 -80
- nautobot/project-static/docs/release-notes/version-2.1.html +884 -80
- nautobot/project-static/docs/release-notes/version-2.2.html +990 -323
- nautobot/project-static/docs/release-notes/version-2.3.html +9524 -0
- nautobot/project-static/docs/requirements.txt +4 -4
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +335 -260
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +983 -197
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +884 -80
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +888 -84
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +884 -80
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/index.html +888 -80
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation/services.html +888 -80
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +900 -91
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +884 -80
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +884 -80
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +884 -80
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +884 -80
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +915 -163
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +884 -80
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +885 -81
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +888 -80
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +887 -83
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +910 -92
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +915 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +905 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +912 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +913 -109
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +906 -97
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +918 -100
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +920 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +929 -111
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +920 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +913 -109
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +914 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +932 -75
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +916 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +935 -78
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +913 -95
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +910 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +914 -96
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +916 -98
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +898 -94
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +889 -81
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +889 -81
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +893 -88
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +884 -80
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +889 -81
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +884 -80
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +884 -80
- nautobot/project-static/docs/user-guide/index.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1250 -777
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +888 -80
- nautobot/project-static/docs/user-guide/platform-functionality/metadata.html +8948 -0
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +887 -83
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +942 -113
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +884 -80
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +884 -80
- nautobot/project-static/js/forms.js +71 -0
- nautobot/project-static/js/table_sorting_indicator.js +46 -0
- nautobot/project-static/js/tableconfig.js +6 -1
- nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/tenancy/__init__.py +0 -1
- nautobot/tenancy/apps.py +1 -0
- nautobot/tenancy/factory.py +3 -2
- nautobot/tenancy/filters/__init__.py +1 -0
- nautobot/tenancy/forms.py +1 -1
- nautobot/tenancy/templates/tenancy/tenant.html +22 -18
- nautobot/tenancy/views.py +11 -10
- nautobot/users/__init__.py +0 -1
- nautobot/users/api/serializers.py +1 -1
- nautobot/users/api/views.py +4 -2
- nautobot/users/apps.py +3 -2
- nautobot/users/factory.py +3 -3
- nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
- nautobot/users/models.py +12 -0
- nautobot/users/tests/test_filters.py +6 -3
- nautobot/users/urls.py +8 -0
- nautobot/virtualization/__init__.py +0 -1
- nautobot/virtualization/apps.py +1 -0
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/forms.py +11 -3
- nautobot/virtualization/graphql/types.py +2 -2
- nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
- nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
- nautobot/virtualization/tables.py +15 -5
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
- nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
- nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
- nautobot/virtualization/tests/test_api.py +9 -4
- nautobot/virtualization/tests/test_filters.py +22 -0
- nautobot/virtualization/tests/test_models.py +7 -3
- nautobot/virtualization/tests/test_views.py +19 -3
- nautobot/virtualization/urls.py +2 -2
- nautobot/virtualization/views.py +10 -32
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/METADATA +21 -19
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/RECORD +679 -559
- nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
- nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
- nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
- nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
- nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
- nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
- nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
- /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/NOTICE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/WHEEL +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/entry_points.txt +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
1
3
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
|
2
4
|
from django.contrib.contenttypes.models import ContentType
|
|
3
5
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
@@ -24,7 +26,6 @@ from nautobot.dcim.choices import (
|
|
|
24
26
|
PowerOutletFeedLegChoices,
|
|
25
27
|
PowerOutletTypeChoices,
|
|
26
28
|
PowerPortTypeChoices,
|
|
27
|
-
SubdeviceRoleChoices,
|
|
28
29
|
)
|
|
29
30
|
from nautobot.dcim.constants import (
|
|
30
31
|
NONCONNECTABLE_IFACE_TYPES,
|
|
@@ -36,6 +37,7 @@ from nautobot.dcim.constants import (
|
|
|
36
37
|
from nautobot.extras.models import (
|
|
37
38
|
ChangeLoggedModel,
|
|
38
39
|
RelationshipModel,
|
|
40
|
+
RoleField,
|
|
39
41
|
Status,
|
|
40
42
|
StatusField,
|
|
41
43
|
)
|
|
@@ -52,6 +54,7 @@ __all__ = (
|
|
|
52
54
|
"InterfaceRedundancyGroup",
|
|
53
55
|
"InterfaceRedundancyGroupAssociation",
|
|
54
56
|
"InventoryItem",
|
|
57
|
+
"ModuleBay",
|
|
55
58
|
"PathEndpoint",
|
|
56
59
|
"PowerOutlet",
|
|
57
60
|
"PowerPort",
|
|
@@ -70,7 +73,7 @@ class ComponentModel(PrimaryModel):
|
|
|
70
73
|
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
71
74
|
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
72
75
|
|
|
73
|
-
natural_key_field_names = ["
|
|
76
|
+
natural_key_field_names = ["device", "name"]
|
|
74
77
|
|
|
75
78
|
class Meta:
|
|
76
79
|
abstract = True
|
|
@@ -84,6 +87,9 @@ class ComponentModel(PrimaryModel):
|
|
|
84
87
|
"""
|
|
85
88
|
Return a new ObjectChange with the `related_object` pinned to the `device` by default.
|
|
86
89
|
"""
|
|
90
|
+
if "related_object" in kwargs:
|
|
91
|
+
return super().to_objectchange(action, **kwargs)
|
|
92
|
+
|
|
87
93
|
# Annotate the parent Device
|
|
88
94
|
try:
|
|
89
95
|
device = self.device
|
|
@@ -93,6 +99,114 @@ class ComponentModel(PrimaryModel):
|
|
|
93
99
|
|
|
94
100
|
return super().to_objectchange(action, related_object=device, **kwargs)
|
|
95
101
|
|
|
102
|
+
@property
|
|
103
|
+
def parent(self):
|
|
104
|
+
return self.device
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class ModularComponentModel(ComponentModel):
|
|
108
|
+
device = ForeignKeyWithAutoRelatedName(
|
|
109
|
+
to="dcim.Device",
|
|
110
|
+
on_delete=models.CASCADE,
|
|
111
|
+
blank=True,
|
|
112
|
+
null=True,
|
|
113
|
+
)
|
|
114
|
+
module = ForeignKeyWithAutoRelatedName(
|
|
115
|
+
to="dcim.Module",
|
|
116
|
+
on_delete=models.CASCADE,
|
|
117
|
+
blank=True,
|
|
118
|
+
null=True,
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
natural_key_field_names = ["device", "module", "name"]
|
|
122
|
+
|
|
123
|
+
class Meta:
|
|
124
|
+
abstract = True
|
|
125
|
+
ordering = ("device", "module", "_name")
|
|
126
|
+
constraints = [
|
|
127
|
+
models.UniqueConstraint(
|
|
128
|
+
fields=("device", "name"),
|
|
129
|
+
name="%(app_label)s_%(class)s_device_name_unique",
|
|
130
|
+
),
|
|
131
|
+
models.UniqueConstraint(
|
|
132
|
+
fields=("module", "name"),
|
|
133
|
+
name="%(app_label)s_%(class)s_module_name_unique",
|
|
134
|
+
),
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def parent(self):
|
|
139
|
+
"""Device that this component belongs to, walking up module inheritance if necessary."""
|
|
140
|
+
return self.module.device if self.module else self.device
|
|
141
|
+
|
|
142
|
+
def render_name_template(self, save=False):
|
|
143
|
+
"""
|
|
144
|
+
Replace the {module}, {module.parent}, {module.parent.parent}, etc. variables in the name
|
|
145
|
+
field with the actual module bay positions.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
save (bool, optional): If True, save the object after updating the name field. Defaults to False.
|
|
149
|
+
|
|
150
|
+
If a module bay position is blank, it will be skipped and the parents will be checked until a non-blank
|
|
151
|
+
position is found. If all parent module bays are exhausted, the variable is left as-is.
|
|
152
|
+
|
|
153
|
+
Example:
|
|
154
|
+
- Device (name="Device 1")
|
|
155
|
+
- ModuleBay (position="A")
|
|
156
|
+
- Module
|
|
157
|
+
- ModuleBay (position="")
|
|
158
|
+
- Module
|
|
159
|
+
- Interface (name="{module}{module.parent}")
|
|
160
|
+
|
|
161
|
+
The deeply nested interface would be named "A{module.parent}" after calling this method.
|
|
162
|
+
"""
|
|
163
|
+
if self.module and self.module.parent_module_bay and "{module" in self.name:
|
|
164
|
+
name = ""
|
|
165
|
+
module_bay = self.module.parent_module_bay
|
|
166
|
+
positions = []
|
|
167
|
+
while module_bay is not None:
|
|
168
|
+
position = getattr(module_bay, "position", None)
|
|
169
|
+
if position:
|
|
170
|
+
positions.append(position)
|
|
171
|
+
module_bay = getattr(getattr(module_bay, "parent_module", None), "parent_module_bay", None)
|
|
172
|
+
for part in re.split(r"({module(?:\.parent)*})", self.name):
|
|
173
|
+
if re.fullmatch(r"{module(\.parent)*}", part):
|
|
174
|
+
depth = part.count(".parent")
|
|
175
|
+
if depth < len(positions):
|
|
176
|
+
name += positions[depth]
|
|
177
|
+
continue
|
|
178
|
+
name += part
|
|
179
|
+
if self.name != name:
|
|
180
|
+
self.name = name
|
|
181
|
+
if save:
|
|
182
|
+
self.save(update_fields=["_name", "name"])
|
|
183
|
+
|
|
184
|
+
def to_objectchange(self, action, **kwargs):
|
|
185
|
+
"""
|
|
186
|
+
Return a new ObjectChange with the `related_object` pinned to the parent `device` or `module`.
|
|
187
|
+
"""
|
|
188
|
+
if "related_object" in kwargs:
|
|
189
|
+
return super().to_objectchange(action, **kwargs)
|
|
190
|
+
|
|
191
|
+
# Annotate the parent
|
|
192
|
+
try:
|
|
193
|
+
parent = self.device if self.device else self.module
|
|
194
|
+
except ObjectDoesNotExist:
|
|
195
|
+
# The parent may have already been deleted
|
|
196
|
+
parent = None
|
|
197
|
+
|
|
198
|
+
return super().to_objectchange(action, related_object=parent, **kwargs)
|
|
199
|
+
|
|
200
|
+
def clean(self):
|
|
201
|
+
super().clean()
|
|
202
|
+
|
|
203
|
+
# Validate that a Device or Module is set, but not both
|
|
204
|
+
if self.device and self.module:
|
|
205
|
+
raise ValidationError("Only one of device or module must be set")
|
|
206
|
+
|
|
207
|
+
if not (self.device or self.module):
|
|
208
|
+
raise ValidationError("Either device or module must be set")
|
|
209
|
+
|
|
96
210
|
|
|
97
211
|
class CableTermination(models.Model):
|
|
98
212
|
"""
|
|
@@ -212,9 +326,9 @@ class PathEndpoint(models.Model):
|
|
|
212
326
|
"graphql",
|
|
213
327
|
"webhooks",
|
|
214
328
|
)
|
|
215
|
-
class ConsolePort(CableTermination, PathEndpoint
|
|
329
|
+
class ConsolePort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
216
330
|
"""
|
|
217
|
-
A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts.
|
|
331
|
+
A physical console port within a Device or Module. ConsolePorts connect to ConsoleServerPorts.
|
|
218
332
|
"""
|
|
219
333
|
|
|
220
334
|
type = models.CharField(
|
|
@@ -224,14 +338,6 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
224
338
|
help_text="Physical port type",
|
|
225
339
|
)
|
|
226
340
|
|
|
227
|
-
class Meta:
|
|
228
|
-
ordering = ("device", "_name")
|
|
229
|
-
unique_together = ("device", "name")
|
|
230
|
-
|
|
231
|
-
@property
|
|
232
|
-
def parent(self):
|
|
233
|
-
return self.device
|
|
234
|
-
|
|
235
341
|
|
|
236
342
|
#
|
|
237
343
|
# Console server ports
|
|
@@ -239,9 +345,9 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
239
345
|
|
|
240
346
|
|
|
241
347
|
@extras_features("custom_links", "cable_terminations", "custom_validators", "graphql", "webhooks")
|
|
242
|
-
class ConsoleServerPort(CableTermination, PathEndpoint
|
|
348
|
+
class ConsoleServerPort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
243
349
|
"""
|
|
244
|
-
A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
|
|
350
|
+
A physical port within a Device or Module (typically a designated console server) which provides access to ConsolePorts.
|
|
245
351
|
"""
|
|
246
352
|
|
|
247
353
|
type = models.CharField(
|
|
@@ -251,14 +357,6 @@ class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
251
357
|
help_text="Physical port type",
|
|
252
358
|
)
|
|
253
359
|
|
|
254
|
-
class Meta:
|
|
255
|
-
ordering = ("device", "_name")
|
|
256
|
-
unique_together = ("device", "name")
|
|
257
|
-
|
|
258
|
-
@property
|
|
259
|
-
def parent(self):
|
|
260
|
-
return self.device
|
|
261
|
-
|
|
262
360
|
|
|
263
361
|
#
|
|
264
362
|
# Power ports
|
|
@@ -273,9 +371,9 @@ class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
273
371
|
"graphql",
|
|
274
372
|
"webhooks",
|
|
275
373
|
)
|
|
276
|
-
class PowerPort(CableTermination, PathEndpoint
|
|
374
|
+
class PowerPort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
277
375
|
"""
|
|
278
|
-
A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets.
|
|
376
|
+
A physical power supply (intake) port within a Device or Module. PowerPorts connect to PowerOutlets.
|
|
279
377
|
"""
|
|
280
378
|
|
|
281
379
|
type = models.CharField(
|
|
@@ -297,14 +395,6 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
297
395
|
help_text="Allocated power draw (watts)",
|
|
298
396
|
)
|
|
299
397
|
|
|
300
|
-
class Meta:
|
|
301
|
-
ordering = ("device", "_name")
|
|
302
|
-
unique_together = ("device", "name")
|
|
303
|
-
|
|
304
|
-
@property
|
|
305
|
-
def parent(self):
|
|
306
|
-
return self.device
|
|
307
|
-
|
|
308
398
|
def clean(self):
|
|
309
399
|
super().clean()
|
|
310
400
|
|
|
@@ -384,9 +474,9 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
384
474
|
|
|
385
475
|
|
|
386
476
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
387
|
-
class PowerOutlet(CableTermination, PathEndpoint
|
|
477
|
+
class PowerOutlet(ModularComponentModel, CableTermination, PathEndpoint):
|
|
388
478
|
"""
|
|
389
|
-
A physical power outlet (output) within a Device which provides power to a PowerPort.
|
|
479
|
+
A physical power outlet (output) within a Device or Module which provides power to a PowerPort.
|
|
390
480
|
"""
|
|
391
481
|
|
|
392
482
|
type = models.CharField(
|
|
@@ -410,19 +500,11 @@ class PowerOutlet(CableTermination, PathEndpoint, ComponentModel):
|
|
|
410
500
|
help_text="Phase (for three-phase feeds)",
|
|
411
501
|
)
|
|
412
502
|
|
|
413
|
-
class Meta:
|
|
414
|
-
ordering = ("device", "_name")
|
|
415
|
-
unique_together = ("device", "name")
|
|
416
|
-
|
|
417
|
-
@property
|
|
418
|
-
def parent(self):
|
|
419
|
-
return self.device
|
|
420
|
-
|
|
421
503
|
def clean(self):
|
|
422
504
|
super().clean()
|
|
423
505
|
|
|
424
506
|
# Validate power port assignment
|
|
425
|
-
if self.power_port and self.power_port.
|
|
507
|
+
if self.power_port and self.parent and self.power_port.parent != self.parent:
|
|
426
508
|
raise ValidationError(f"Parent power port ({self.power_port}) must belong to the same device")
|
|
427
509
|
|
|
428
510
|
|
|
@@ -446,6 +528,7 @@ class BaseInterface(RelationshipModel):
|
|
|
446
528
|
validators=[MinValueValidator(1), MaxValueValidator(65536)],
|
|
447
529
|
verbose_name="MTU",
|
|
448
530
|
)
|
|
531
|
+
role = RoleField(blank=True, null=True)
|
|
449
532
|
mode = models.CharField(max_length=50, choices=InterfaceModeChoices, blank=True)
|
|
450
533
|
parent_interface = models.ForeignKey(
|
|
451
534
|
to="self",
|
|
@@ -500,9 +583,9 @@ class BaseInterface(RelationshipModel):
|
|
|
500
583
|
"statuses",
|
|
501
584
|
"webhooks",
|
|
502
585
|
)
|
|
503
|
-
class Interface(CableTermination, PathEndpoint,
|
|
586
|
+
class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInterface):
|
|
504
587
|
"""
|
|
505
|
-
A network interface within a Device. A physical Interface can connect to exactly one other Interface.
|
|
588
|
+
A network interface within a Device or Module. A physical Interface can connect to exactly one other Interface.
|
|
506
589
|
"""
|
|
507
590
|
|
|
508
591
|
# Override ComponentModel._name to specify naturalize_interface function
|
|
@@ -559,15 +642,14 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
559
642
|
verbose_name="IP Addresses",
|
|
560
643
|
)
|
|
561
644
|
|
|
562
|
-
class Meta:
|
|
563
|
-
ordering = ("device", CollateAsChar("_name"))
|
|
564
|
-
unique_together = ("device", "name")
|
|
645
|
+
class Meta(ModularComponentModel.Meta):
|
|
646
|
+
ordering = ("device", "module", CollateAsChar("_name"))
|
|
565
647
|
|
|
566
648
|
def clean(self):
|
|
567
649
|
super().clean()
|
|
568
650
|
|
|
569
651
|
# VRF validation
|
|
570
|
-
if self.vrf and self.vrf not in self.
|
|
652
|
+
if self.vrf and self.parent and self.vrf not in self.parent.vrfs.all():
|
|
571
653
|
# TODO(jathan): Or maybe we automatically add the VRF to the device?
|
|
572
654
|
raise ValidationError({"vrf": "VRF must be assigned to same Device."})
|
|
573
655
|
|
|
@@ -578,19 +660,23 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
578
660
|
raise ValidationError({"lag": "A LAG interface cannot be its own parent."})
|
|
579
661
|
|
|
580
662
|
# An interface's LAG must belong to the same device or virtual chassis
|
|
581
|
-
if self.lag.
|
|
582
|
-
if self.
|
|
663
|
+
if self.parent and self.lag.parent != self.parent:
|
|
664
|
+
if self.lag.parent is None:
|
|
665
|
+
raise ValidationError(
|
|
666
|
+
{"lag": f"The selected LAG interface ({self.lag}) does not belong to a device."}
|
|
667
|
+
)
|
|
668
|
+
elif self.parent.virtual_chassis is None:
|
|
583
669
|
raise ValidationError(
|
|
584
670
|
{
|
|
585
|
-
"lag": f"The selected LAG interface ({self.lag}) belongs to a different device ({self.lag.
|
|
671
|
+
"lag": f"The selected LAG interface ({self.lag}) belongs to a different device ({self.lag.parent})."
|
|
586
672
|
}
|
|
587
673
|
)
|
|
588
|
-
elif self.lag.
|
|
674
|
+
elif self.lag.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
|
|
589
675
|
raise ValidationError(
|
|
590
676
|
{
|
|
591
677
|
"lag": (
|
|
592
|
-
f"The selected LAG interface ({self.lag}) belongs to {self.lag.
|
|
593
|
-
f"of virtual chassis {self.
|
|
678
|
+
f"The selected LAG interface ({self.lag}) belongs to {self.lag.parent}, which is not part "
|
|
679
|
+
f"of virtual chassis {self.parent.virtual_chassis}."
|
|
594
680
|
)
|
|
595
681
|
}
|
|
596
682
|
)
|
|
@@ -623,19 +709,19 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
623
709
|
)
|
|
624
710
|
|
|
625
711
|
# An interface's parent must belong to the same device or virtual chassis
|
|
626
|
-
if self.parent_interface.
|
|
627
|
-
if getattr(self.
|
|
712
|
+
if self.parent and self.parent_interface.parent != self.parent:
|
|
713
|
+
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
628
714
|
raise ValidationError(
|
|
629
715
|
{
|
|
630
716
|
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to a different device "
|
|
631
|
-
f"({self.parent_interface.
|
|
717
|
+
f"({self.parent_interface.parent})."
|
|
632
718
|
}
|
|
633
719
|
)
|
|
634
|
-
elif self.parent_interface.
|
|
720
|
+
elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis:
|
|
635
721
|
raise ValidationError(
|
|
636
722
|
{
|
|
637
|
-
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to {self.parent_interface.
|
|
638
|
-
f"is not part of virtual chassis {self.
|
|
723
|
+
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to {self.parent_interface.parent}, which "
|
|
724
|
+
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
639
725
|
}
|
|
640
726
|
)
|
|
641
727
|
|
|
@@ -645,7 +731,8 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
645
731
|
if (
|
|
646
732
|
self.untagged_vlan
|
|
647
733
|
and self.untagged_vlan.locations.exists()
|
|
648
|
-
and
|
|
734
|
+
and self.parent
|
|
735
|
+
and not self.untagged_vlan.locations.filter(id=self.parent.location_id).exists()
|
|
649
736
|
):
|
|
650
737
|
raise ValidationError(
|
|
651
738
|
{
|
|
@@ -663,22 +750,22 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
663
750
|
raise ValidationError({"bridge": "An interface cannot be bridged to itself."})
|
|
664
751
|
|
|
665
752
|
# A bridged interface belong to the same device or virtual chassis
|
|
666
|
-
if self.bridge.
|
|
667
|
-
if getattr(self.
|
|
753
|
+
if self.parent and self.bridge.parent != self.parent:
|
|
754
|
+
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
668
755
|
raise ValidationError(
|
|
669
756
|
{
|
|
670
757
|
"bridge": (
|
|
671
758
|
f"The selected bridge interface ({self.bridge}) belongs to a different device "
|
|
672
|
-
f"({self.bridge.
|
|
759
|
+
f"({self.bridge.parent})."
|
|
673
760
|
)
|
|
674
761
|
}
|
|
675
762
|
)
|
|
676
|
-
elif self.bridge.
|
|
763
|
+
elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
|
|
677
764
|
raise ValidationError(
|
|
678
765
|
{
|
|
679
766
|
"bridge": (
|
|
680
|
-
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.
|
|
681
|
-
f"is not part of virtual chassis {self.
|
|
767
|
+
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which "
|
|
768
|
+
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
682
769
|
)
|
|
683
770
|
}
|
|
684
771
|
)
|
|
@@ -766,10 +853,6 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
766
853
|
def ip_address_count(self):
|
|
767
854
|
return self.ip_addresses.count()
|
|
768
855
|
|
|
769
|
-
@property
|
|
770
|
-
def parent(self):
|
|
771
|
-
return self.device
|
|
772
|
-
|
|
773
856
|
|
|
774
857
|
@extras_features(
|
|
775
858
|
"custom_fields",
|
|
@@ -879,6 +962,7 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
879
962
|
related_name="interface_redundancy_group_associations",
|
|
880
963
|
)
|
|
881
964
|
priority = models.PositiveSmallIntegerField()
|
|
965
|
+
is_metadata_associable_model = False
|
|
882
966
|
|
|
883
967
|
class Meta:
|
|
884
968
|
"""Meta class."""
|
|
@@ -888,7 +972,7 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
888
972
|
|
|
889
973
|
def __str__(self):
|
|
890
974
|
"""Return a string representation of the instance."""
|
|
891
|
-
return f"{self.interface_redundancy_group}: {self.interface.device} {self.interface}: {self.priority}"
|
|
975
|
+
return f"{self.interface_redundancy_group}: {self.interface.device or self.interface.module} {self.interface}: {self.priority}"
|
|
892
976
|
|
|
893
977
|
|
|
894
978
|
#
|
|
@@ -897,9 +981,9 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
897
981
|
|
|
898
982
|
|
|
899
983
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
900
|
-
class FrontPort(
|
|
984
|
+
class FrontPort(ModularComponentModel, CableTermination):
|
|
901
985
|
"""
|
|
902
|
-
A pass-through port on the front of a Device.
|
|
986
|
+
A pass-through port on the front of a Device or Module.
|
|
903
987
|
"""
|
|
904
988
|
|
|
905
989
|
type = models.CharField(max_length=50, choices=PortTypeChoices)
|
|
@@ -912,22 +996,22 @@ class FrontPort(CableTermination, ComponentModel):
|
|
|
912
996
|
],
|
|
913
997
|
)
|
|
914
998
|
|
|
915
|
-
|
|
916
|
-
ordering = ("device", "_name")
|
|
917
|
-
unique_together = (
|
|
918
|
-
("device", "name"),
|
|
919
|
-
("rear_port", "rear_port_position"),
|
|
920
|
-
)
|
|
999
|
+
natural_key_field_names = ["device", "module", "name", "rear_port", "rear_port_position"]
|
|
921
1000
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1001
|
+
class Meta(ModularComponentModel.Meta):
|
|
1002
|
+
constraints = [
|
|
1003
|
+
*ModularComponentModel.Meta.constraints,
|
|
1004
|
+
models.UniqueConstraint(
|
|
1005
|
+
fields=("rear_port", "rear_port_position"),
|
|
1006
|
+
name="dcim_frontport_rear_port_position_unique",
|
|
1007
|
+
),
|
|
1008
|
+
]
|
|
925
1009
|
|
|
926
1010
|
def clean(self):
|
|
927
1011
|
super().clean()
|
|
928
1012
|
|
|
929
1013
|
# Validate rear port assignment
|
|
930
|
-
if self.rear_port.
|
|
1014
|
+
if self.parent and self.rear_port.parent != self.parent:
|
|
931
1015
|
raise ValidationError({"rear_port": f"Rear port ({self.rear_port}) must belong to the same device"})
|
|
932
1016
|
|
|
933
1017
|
# Validate rear port position assignment
|
|
@@ -941,9 +1025,9 @@ class FrontPort(CableTermination, ComponentModel):
|
|
|
941
1025
|
|
|
942
1026
|
|
|
943
1027
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
944
|
-
class RearPort(
|
|
1028
|
+
class RearPort(ModularComponentModel, CableTermination):
|
|
945
1029
|
"""
|
|
946
|
-
A pass-through port on the rear of a Device.
|
|
1030
|
+
A pass-through port on the rear of a Device or Module.
|
|
947
1031
|
"""
|
|
948
1032
|
|
|
949
1033
|
type = models.CharField(max_length=50, choices=PortTypeChoices)
|
|
@@ -955,10 +1039,6 @@ class RearPort(CableTermination, ComponentModel):
|
|
|
955
1039
|
],
|
|
956
1040
|
)
|
|
957
1041
|
|
|
958
|
-
class Meta:
|
|
959
|
-
ordering = ("device", "_name")
|
|
960
|
-
unique_together = ("device", "name")
|
|
961
|
-
|
|
962
1042
|
def clean(self):
|
|
963
1043
|
super().clean()
|
|
964
1044
|
|
|
@@ -972,10 +1052,6 @@ class RearPort(CableTermination, ComponentModel):
|
|
|
972
1052
|
}
|
|
973
1053
|
)
|
|
974
1054
|
|
|
975
|
-
@property
|
|
976
|
-
def parent(self):
|
|
977
|
-
return self.device
|
|
978
|
-
|
|
979
1055
|
|
|
980
1056
|
#
|
|
981
1057
|
# Device bays
|
|
@@ -1020,16 +1096,6 @@ class DeviceBay(ComponentModel):
|
|
|
1020
1096
|
"installed_device": f"Cannot install the specified device; device is already installed in {current_bay}"
|
|
1021
1097
|
}
|
|
1022
1098
|
)
|
|
1023
|
-
if self.installed_device.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_CHILD:
|
|
1024
|
-
raise ValidationError(
|
|
1025
|
-
{
|
|
1026
|
-
"installed_device": f'Cannot install device "{self.installed_device}"; device-type "{self.installed_device.device_type}" subdevice_role is not "child".'
|
|
1027
|
-
}
|
|
1028
|
-
)
|
|
1029
|
-
|
|
1030
|
-
@property
|
|
1031
|
-
def parent(self):
|
|
1032
|
-
return self.device
|
|
1033
1099
|
|
|
1034
1100
|
|
|
1035
1101
|
#
|
|
@@ -1079,7 +1145,8 @@ class InventoryItem(TreeModel, ComponentModel):
|
|
|
1079
1145
|
related_name="inventory_items",
|
|
1080
1146
|
blank=True,
|
|
1081
1147
|
null=True,
|
|
1082
|
-
verbose_name="
|
|
1148
|
+
verbose_name="Software Version",
|
|
1149
|
+
help_text="The software version installed on this inventory item",
|
|
1083
1150
|
)
|
|
1084
1151
|
software_image_files = models.ManyToManyField(
|
|
1085
1152
|
to="dcim.SoftwareImageFile",
|
|
@@ -1101,3 +1168,105 @@ class InventoryItem(TreeModel, ComponentModel):
|
|
|
1101
1168
|
For the time being we just use the PK as a natural key.
|
|
1102
1169
|
"""
|
|
1103
1170
|
return ["pk"]
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
@extras_features(
|
|
1174
|
+
"custom_links",
|
|
1175
|
+
"custom_validators",
|
|
1176
|
+
"export_templates",
|
|
1177
|
+
"graphql",
|
|
1178
|
+
"webhooks",
|
|
1179
|
+
)
|
|
1180
|
+
class ModuleBay(PrimaryModel):
|
|
1181
|
+
"""
|
|
1182
|
+
A slot in a Device or Module which can contain Modules.
|
|
1183
|
+
"""
|
|
1184
|
+
|
|
1185
|
+
parent_device = models.ForeignKey(
|
|
1186
|
+
to="dcim.Device",
|
|
1187
|
+
on_delete=models.CASCADE,
|
|
1188
|
+
related_name="module_bays",
|
|
1189
|
+
blank=True,
|
|
1190
|
+
null=True,
|
|
1191
|
+
)
|
|
1192
|
+
parent_module = models.ForeignKey(
|
|
1193
|
+
to="dcim.Module",
|
|
1194
|
+
on_delete=models.CASCADE,
|
|
1195
|
+
related_name="module_bays",
|
|
1196
|
+
blank=True,
|
|
1197
|
+
null=True,
|
|
1198
|
+
)
|
|
1199
|
+
name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, db_index=True)
|
|
1200
|
+
_name = NaturalOrderingField(target_field="name", max_length=CHARFIELD_MAX_LENGTH, blank=True, db_index=True)
|
|
1201
|
+
position = models.CharField(
|
|
1202
|
+
blank=True,
|
|
1203
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1204
|
+
help_text="The position of the module bay within the parent device/module",
|
|
1205
|
+
)
|
|
1206
|
+
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
1207
|
+
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
1208
|
+
|
|
1209
|
+
clone_fields = ["parent_device", "parent_module"]
|
|
1210
|
+
|
|
1211
|
+
# The recursive nature of this model combined with the fact that it can be a child of a
|
|
1212
|
+
# device or location makes our natural key implementation unusable, so just use the pk
|
|
1213
|
+
natural_key_field_names = ["pk"]
|
|
1214
|
+
|
|
1215
|
+
class Meta:
|
|
1216
|
+
# TODO: Ordering by parent_module.id is not correct but prevents an infinite loop
|
|
1217
|
+
ordering = (
|
|
1218
|
+
"parent_device",
|
|
1219
|
+
"parent_module__id",
|
|
1220
|
+
"_name",
|
|
1221
|
+
)
|
|
1222
|
+
constraints = [
|
|
1223
|
+
models.UniqueConstraint(
|
|
1224
|
+
fields=["parent_device", "name"],
|
|
1225
|
+
name="dcim_modulebay_parent_device_name_unique",
|
|
1226
|
+
),
|
|
1227
|
+
models.UniqueConstraint(
|
|
1228
|
+
fields=["parent_module", "name"],
|
|
1229
|
+
name="dcim_modulebay_parent_module_name_unique",
|
|
1230
|
+
),
|
|
1231
|
+
]
|
|
1232
|
+
|
|
1233
|
+
@property
|
|
1234
|
+
def parent(self):
|
|
1235
|
+
"""Walk up parent chain to find the Device that this ModuleBay is installed in, if one exists."""
|
|
1236
|
+
return self.parent_module.device if self.parent_module else self.parent_device
|
|
1237
|
+
|
|
1238
|
+
def __str__(self):
|
|
1239
|
+
if self.parent_device is not None:
|
|
1240
|
+
return f"{self.parent_device} ({self.name})"
|
|
1241
|
+
else:
|
|
1242
|
+
return f"{self.parent_module} ({self.name})"
|
|
1243
|
+
|
|
1244
|
+
@property
|
|
1245
|
+
def display(self):
|
|
1246
|
+
if self.parent_device is not None:
|
|
1247
|
+
return f"{self.parent_device.display} ({self.name})"
|
|
1248
|
+
else:
|
|
1249
|
+
return f"{self.parent_module.display} ({self.name})"
|
|
1250
|
+
|
|
1251
|
+
def to_objectchange(self, action, **kwargs):
|
|
1252
|
+
"""
|
|
1253
|
+
Return a new ObjectChange with the `related_object` pinned to the parent `device` or `module`.
|
|
1254
|
+
"""
|
|
1255
|
+
# Annotate the parent
|
|
1256
|
+
try:
|
|
1257
|
+
parent = self.parent
|
|
1258
|
+
except ObjectDoesNotExist:
|
|
1259
|
+
# The parent has already been deleted
|
|
1260
|
+
parent = None
|
|
1261
|
+
|
|
1262
|
+
return super().to_objectchange(action, related_object=parent, **kwargs)
|
|
1263
|
+
|
|
1264
|
+
def clean(self):
|
|
1265
|
+
super().clean()
|
|
1266
|
+
|
|
1267
|
+
# Validate that a Device or Module is set, but not both
|
|
1268
|
+
if self.parent_device and self.parent_module:
|
|
1269
|
+
raise ValidationError("Only one of parent_device or parent_module must be set")
|
|
1270
|
+
|
|
1271
|
+
if not (self.parent_device or self.parent_module):
|
|
1272
|
+
raise ValidationError("Either parent_device or parent_module must be set")
|