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
nautobot/dcim/models/devices.py
CHANGED
|
@@ -24,6 +24,7 @@ from nautobot.dcim.choices import (
|
|
|
24
24
|
SoftwareImageFileHashingAlgorithmChoices,
|
|
25
25
|
SubdeviceRoleChoices,
|
|
26
26
|
)
|
|
27
|
+
from nautobot.dcim.constants import MODULE_RECURSION_DEPTH_LIMIT
|
|
27
28
|
from nautobot.dcim.utils import get_all_network_driver_mappings
|
|
28
29
|
from nautobot.extras.models import ChangeLoggedModel, ConfigContextModel, RoleField, StatusField
|
|
29
30
|
from nautobot.extras.querysets import ConfigContextModelQuerySet
|
|
@@ -36,6 +37,7 @@ from .device_components import (
|
|
|
36
37
|
FrontPort,
|
|
37
38
|
Interface,
|
|
38
39
|
InventoryItem,
|
|
40
|
+
ModuleBay,
|
|
39
41
|
PowerOutlet,
|
|
40
42
|
PowerPort,
|
|
41
43
|
RearPort,
|
|
@@ -110,6 +112,7 @@ class DeviceTypeToSoftwareImageFile(BaseModel, ChangeLoggedModel):
|
|
|
110
112
|
software_image_file = models.ForeignKey(
|
|
111
113
|
"dcim.SoftwareImageFile", on_delete=models.PROTECT, related_name="device_type_mappings"
|
|
112
114
|
)
|
|
115
|
+
is_metadata_associable_model = False
|
|
113
116
|
|
|
114
117
|
class Meta:
|
|
115
118
|
unique_together = [
|
|
@@ -296,6 +299,16 @@ class DeviceType(PrimaryModel):
|
|
|
296
299
|
}
|
|
297
300
|
for c in self.device_bay_templates.all()
|
|
298
301
|
]
|
|
302
|
+
if self.module_bay_templates.exists():
|
|
303
|
+
data["module-bays"] = [
|
|
304
|
+
{
|
|
305
|
+
"name": c.name,
|
|
306
|
+
"position": c.position,
|
|
307
|
+
"label": c.label,
|
|
308
|
+
"description": c.description,
|
|
309
|
+
}
|
|
310
|
+
for c in self.module_bay_templates.all()
|
|
311
|
+
]
|
|
299
312
|
|
|
300
313
|
return yaml.dump(dict(data), sort_keys=False, allow_unicode=True)
|
|
301
314
|
|
|
@@ -733,7 +746,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
733
746
|
pass
|
|
734
747
|
|
|
735
748
|
# Validate primary IP addresses
|
|
736
|
-
|
|
749
|
+
all_interfaces = self.all_interfaces.all()
|
|
737
750
|
for field in ["primary_ip4", "primary_ip6"]:
|
|
738
751
|
ip = getattr(self, field)
|
|
739
752
|
if ip is not None:
|
|
@@ -743,12 +756,14 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
743
756
|
else:
|
|
744
757
|
if ip.ip_version != 6:
|
|
745
758
|
raise ValidationError({f"{field}": f"{ip} is not an IPv6 address."})
|
|
746
|
-
if ipam_models.IPAddressToInterface.objects.filter(
|
|
759
|
+
if ipam_models.IPAddressToInterface.objects.filter(
|
|
760
|
+
ip_address=ip, interface__in=all_interfaces
|
|
761
|
+
).exists():
|
|
747
762
|
pass
|
|
748
763
|
elif (
|
|
749
764
|
ip.nat_inside is not None
|
|
750
765
|
and ipam_models.IPAddressToInterface.objects.filter(
|
|
751
|
-
ip_address=ip.nat_inside, interface__in=
|
|
766
|
+
ip_address=ip.nat_inside, interface__in=all_interfaces
|
|
752
767
|
).exists()
|
|
753
768
|
):
|
|
754
769
|
pass
|
|
@@ -847,7 +862,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
847
862
|
"""Create device components from the device type definition."""
|
|
848
863
|
# The order of these is significant as
|
|
849
864
|
# - PowerOutlet depends on PowerPort
|
|
850
|
-
# - FrontPort depends on
|
|
865
|
+
# - FrontPort depends on RearPort
|
|
851
866
|
component_models = [
|
|
852
867
|
(ConsolePort, self.device_type.console_port_templates.all()),
|
|
853
868
|
(ConsoleServerPort, self.device_type.console_server_port_templates.all()),
|
|
@@ -857,10 +872,11 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
857
872
|
(RearPort, self.device_type.rear_port_templates.all()),
|
|
858
873
|
(FrontPort, self.device_type.front_port_templates.all()),
|
|
859
874
|
(DeviceBay, self.device_type.device_bay_templates.all()),
|
|
875
|
+
(ModuleBay, self.device_type.module_bay_templates.all()),
|
|
860
876
|
]
|
|
861
877
|
instantiated_components = []
|
|
862
878
|
for model, templates in component_models:
|
|
863
|
-
model.objects.bulk_create([x.instantiate(self) for x in templates])
|
|
879
|
+
model.objects.bulk_create([x.instantiate(device=self) for x in templates])
|
|
864
880
|
return instantiated_components
|
|
865
881
|
|
|
866
882
|
@property
|
|
@@ -906,10 +922,11 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
906
922
|
Return a QuerySet matching all Interfaces assigned to this Device or, if this Device is a VC master, to another
|
|
907
923
|
Device belonging to the same VirtualChassis.
|
|
908
924
|
"""
|
|
909
|
-
|
|
925
|
+
qs = self.all_interfaces
|
|
910
926
|
if self.virtual_chassis and self.virtual_chassis.master == self:
|
|
911
|
-
|
|
912
|
-
|
|
927
|
+
for member in self.virtual_chassis.members.exclude(id=self.id):
|
|
928
|
+
qs |= member.all_interfaces.filter(mgmt_only=False)
|
|
929
|
+
return qs
|
|
913
930
|
|
|
914
931
|
@property
|
|
915
932
|
def common_vc_interfaces(self):
|
|
@@ -919,7 +936,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
919
936
|
"""
|
|
920
937
|
if self.virtual_chassis:
|
|
921
938
|
return self.virtual_chassis.member_interfaces
|
|
922
|
-
return self.
|
|
939
|
+
return self.all_interfaces
|
|
923
940
|
|
|
924
941
|
def get_cables(self, pk_list=False):
|
|
925
942
|
"""
|
|
@@ -950,6 +967,79 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
950
967
|
"""
|
|
951
968
|
return Device.objects.filter(parent_bay__device=self.pk)
|
|
952
969
|
|
|
970
|
+
@property
|
|
971
|
+
def all_modules(self):
|
|
972
|
+
"""
|
|
973
|
+
Return all child Modules installed in ModuleBays within this Device.
|
|
974
|
+
"""
|
|
975
|
+
# Supports Device->ModuleBay->Module->ModuleBay->Module->ModuleBay->Module->ModuleBay->Module
|
|
976
|
+
# This query looks for modules that are installed in a module_bay and attached to this device
|
|
977
|
+
# We artificially limit the recursion to 4 levels or we would be stuck in an infinite loop.
|
|
978
|
+
recursion_depth = MODULE_RECURSION_DEPTH_LIMIT
|
|
979
|
+
qs = Module.objects.all()
|
|
980
|
+
query = Q()
|
|
981
|
+
for level in range(recursion_depth):
|
|
982
|
+
recursive_query = "parent_module_bay__parent_module__" * level
|
|
983
|
+
query = query | Q(**{f"{recursive_query}parent_module_bay__parent_device": self})
|
|
984
|
+
return qs.filter(query)
|
|
985
|
+
|
|
986
|
+
@property
|
|
987
|
+
def all_console_ports(self):
|
|
988
|
+
"""
|
|
989
|
+
Return all Console Ports that are installed in the device or in modules that are installed in the device.
|
|
990
|
+
"""
|
|
991
|
+
# TODO: These could probably be optimized to reduce the number of joins
|
|
992
|
+
return ConsolePort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
993
|
+
|
|
994
|
+
@property
|
|
995
|
+
def all_console_server_ports(self):
|
|
996
|
+
"""
|
|
997
|
+
Return all Console Server Ports that are installed in the device or in modules that are installed in the device.
|
|
998
|
+
"""
|
|
999
|
+
return ConsoleServerPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1000
|
+
|
|
1001
|
+
@property
|
|
1002
|
+
def all_front_ports(self):
|
|
1003
|
+
"""
|
|
1004
|
+
Return all Front Ports that are installed in the device or in modules that are installed in the device.
|
|
1005
|
+
"""
|
|
1006
|
+
return FrontPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1007
|
+
|
|
1008
|
+
@property
|
|
1009
|
+
def all_interfaces(self):
|
|
1010
|
+
"""
|
|
1011
|
+
Return all Interfaces that are installed in the device or in modules that are installed in the device.
|
|
1012
|
+
"""
|
|
1013
|
+
return Interface.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1014
|
+
|
|
1015
|
+
@property
|
|
1016
|
+
def all_module_bays(self):
|
|
1017
|
+
"""
|
|
1018
|
+
Return all Module Bays that are installed in the device or in modules that are installed in the device.
|
|
1019
|
+
"""
|
|
1020
|
+
return ModuleBay.objects.filter(Q(parent_device=self) | Q(parent_module__in=self.all_modules))
|
|
1021
|
+
|
|
1022
|
+
@property
|
|
1023
|
+
def all_power_ports(self):
|
|
1024
|
+
"""
|
|
1025
|
+
Return all Power Ports that are installed in the device or in modules that are installed in the device.
|
|
1026
|
+
"""
|
|
1027
|
+
return PowerPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1028
|
+
|
|
1029
|
+
@property
|
|
1030
|
+
def all_power_outlets(self):
|
|
1031
|
+
"""
|
|
1032
|
+
Return all Power Outlets that are installed in the device or in modules that are installed in the device.
|
|
1033
|
+
"""
|
|
1034
|
+
return PowerOutlet.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1035
|
+
|
|
1036
|
+
@property
|
|
1037
|
+
def all_rear_ports(self):
|
|
1038
|
+
"""
|
|
1039
|
+
Return all Rear Ports that are installed in the device or in modules that are installed in the device.
|
|
1040
|
+
"""
|
|
1041
|
+
return RearPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1042
|
+
|
|
953
1043
|
|
|
954
1044
|
#
|
|
955
1045
|
# Virtual chassis
|
|
@@ -1065,10 +1155,6 @@ class DeviceRedundancyGroup(PrimaryModel):
|
|
|
1065
1155
|
def devices_sorted(self):
|
|
1066
1156
|
return self.devices.order_by("device_redundancy_group_priority")
|
|
1067
1157
|
|
|
1068
|
-
@property
|
|
1069
|
-
def controllers_sorted(self):
|
|
1070
|
-
return self.controllers.order_by("name")
|
|
1071
|
-
|
|
1072
1158
|
def __str__(self):
|
|
1073
1159
|
return self.name
|
|
1074
1160
|
|
|
@@ -1386,3 +1472,370 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
|
|
|
1386
1472
|
raise ValidationError(
|
|
1387
1473
|
{"controller": "Controller device group must have the same controller as the parent group."}
|
|
1388
1474
|
)
|
|
1475
|
+
|
|
1476
|
+
|
|
1477
|
+
#
|
|
1478
|
+
# Modules
|
|
1479
|
+
#
|
|
1480
|
+
|
|
1481
|
+
|
|
1482
|
+
# TODO: 5840 - Translate comments field from devicetype library, Nautobot doesn't use that field for ModuleType
|
|
1483
|
+
@extras_features(
|
|
1484
|
+
"custom_links",
|
|
1485
|
+
"custom_validators",
|
|
1486
|
+
"export_templates",
|
|
1487
|
+
"graphql",
|
|
1488
|
+
"webhooks",
|
|
1489
|
+
)
|
|
1490
|
+
class ModuleType(PrimaryModel):
|
|
1491
|
+
"""
|
|
1492
|
+
A ModuleType represents a particular make (Manufacturer) and model of Module. A Module can represent
|
|
1493
|
+
a line card, supervisor, or other interchangeable hardware component within a ModuleBay.
|
|
1494
|
+
|
|
1495
|
+
ModuleType implements a subset of the features of DeviceType.
|
|
1496
|
+
|
|
1497
|
+
Each ModuleType can have an arbitrary number of component templates assigned to it,
|
|
1498
|
+
which define console, power, and interface objects. For example, a Cisco WS-SUP720-3B
|
|
1499
|
+
ModuleType would have:
|
|
1500
|
+
|
|
1501
|
+
* 1 ConsolePortTemplate
|
|
1502
|
+
* 2 InterfaceTemplates
|
|
1503
|
+
|
|
1504
|
+
When a new Module of this type is created, the appropriate console, power, and interface
|
|
1505
|
+
objects (as defined by the ModuleType) are automatically created as well.
|
|
1506
|
+
"""
|
|
1507
|
+
|
|
1508
|
+
manufacturer = models.ForeignKey(to="dcim.Manufacturer", on_delete=models.PROTECT, related_name="module_types")
|
|
1509
|
+
model = models.CharField(max_length=CHARFIELD_MAX_LENGTH)
|
|
1510
|
+
part_number = models.CharField(
|
|
1511
|
+
max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Discrete part number (optional)"
|
|
1512
|
+
)
|
|
1513
|
+
|
|
1514
|
+
clone_fields = [
|
|
1515
|
+
"manufacturer",
|
|
1516
|
+
]
|
|
1517
|
+
|
|
1518
|
+
class Meta:
|
|
1519
|
+
ordering = ("manufacturer", "model")
|
|
1520
|
+
unique_together = [
|
|
1521
|
+
("manufacturer", "model"),
|
|
1522
|
+
]
|
|
1523
|
+
|
|
1524
|
+
def __str__(self):
|
|
1525
|
+
return self.model
|
|
1526
|
+
|
|
1527
|
+
def to_yaml(self):
|
|
1528
|
+
data = OrderedDict(
|
|
1529
|
+
(
|
|
1530
|
+
("manufacturer", self.manufacturer.name),
|
|
1531
|
+
("model", self.model),
|
|
1532
|
+
("part_number", self.part_number),
|
|
1533
|
+
)
|
|
1534
|
+
)
|
|
1535
|
+
|
|
1536
|
+
# Component templates
|
|
1537
|
+
if self.console_port_templates.exists():
|
|
1538
|
+
data["console-ports"] = [
|
|
1539
|
+
{
|
|
1540
|
+
"name": c.name,
|
|
1541
|
+
"type": c.type,
|
|
1542
|
+
}
|
|
1543
|
+
for c in self.console_port_templates.all()
|
|
1544
|
+
]
|
|
1545
|
+
if self.console_server_port_templates.exists():
|
|
1546
|
+
data["console-server-ports"] = [
|
|
1547
|
+
{
|
|
1548
|
+
"name": c.name,
|
|
1549
|
+
"type": c.type,
|
|
1550
|
+
}
|
|
1551
|
+
for c in self.console_server_port_templates.all()
|
|
1552
|
+
]
|
|
1553
|
+
if self.power_port_templates.exists():
|
|
1554
|
+
data["power-ports"] = [
|
|
1555
|
+
{
|
|
1556
|
+
"name": c.name,
|
|
1557
|
+
"type": c.type,
|
|
1558
|
+
"maximum_draw": c.maximum_draw,
|
|
1559
|
+
"allocated_draw": c.allocated_draw,
|
|
1560
|
+
}
|
|
1561
|
+
for c in self.power_port_templates.all()
|
|
1562
|
+
]
|
|
1563
|
+
if self.power_outlet_templates.exists():
|
|
1564
|
+
data["power-outlets"] = [
|
|
1565
|
+
{
|
|
1566
|
+
"name": c.name,
|
|
1567
|
+
"type": c.type,
|
|
1568
|
+
"power_port": c.power_port_template.name if c.power_port_template else None,
|
|
1569
|
+
"feed_leg": c.feed_leg,
|
|
1570
|
+
}
|
|
1571
|
+
for c in self.power_outlet_templates.all()
|
|
1572
|
+
]
|
|
1573
|
+
if self.interface_templates.exists():
|
|
1574
|
+
data["interfaces"] = [
|
|
1575
|
+
{
|
|
1576
|
+
"name": c.name,
|
|
1577
|
+
"type": c.type,
|
|
1578
|
+
"mgmt_only": c.mgmt_only,
|
|
1579
|
+
}
|
|
1580
|
+
for c in self.interface_templates.all()
|
|
1581
|
+
]
|
|
1582
|
+
if self.front_port_templates.exists():
|
|
1583
|
+
data["front-ports"] = [
|
|
1584
|
+
{
|
|
1585
|
+
"name": c.name,
|
|
1586
|
+
"type": c.type,
|
|
1587
|
+
"rear_port": c.rear_port_template.name,
|
|
1588
|
+
"rear_port_position": c.rear_port_position,
|
|
1589
|
+
}
|
|
1590
|
+
for c in self.front_port_templates.all()
|
|
1591
|
+
]
|
|
1592
|
+
if self.rear_port_templates.exists():
|
|
1593
|
+
data["rear-ports"] = [
|
|
1594
|
+
{
|
|
1595
|
+
"name": c.name,
|
|
1596
|
+
"type": c.type,
|
|
1597
|
+
"positions": c.positions,
|
|
1598
|
+
}
|
|
1599
|
+
for c in self.rear_port_templates.all()
|
|
1600
|
+
]
|
|
1601
|
+
if self.module_bay_templates.exists():
|
|
1602
|
+
data["module-bays"] = [
|
|
1603
|
+
{
|
|
1604
|
+
"name": c.name,
|
|
1605
|
+
"position": c.position,
|
|
1606
|
+
"label": c.label,
|
|
1607
|
+
"description": c.description,
|
|
1608
|
+
}
|
|
1609
|
+
for c in self.module_bay_templates.all()
|
|
1610
|
+
]
|
|
1611
|
+
|
|
1612
|
+
return yaml.dump(dict(data), sort_keys=False, allow_unicode=True)
|
|
1613
|
+
|
|
1614
|
+
@property
|
|
1615
|
+
def display(self):
|
|
1616
|
+
return f"{self.manufacturer.name} {self.model}"
|
|
1617
|
+
|
|
1618
|
+
|
|
1619
|
+
@extras_features(
|
|
1620
|
+
"custom_links",
|
|
1621
|
+
"custom_validators",
|
|
1622
|
+
"export_templates",
|
|
1623
|
+
"graphql",
|
|
1624
|
+
"locations",
|
|
1625
|
+
"statuses",
|
|
1626
|
+
"webhooks",
|
|
1627
|
+
)
|
|
1628
|
+
class Module(PrimaryModel):
|
|
1629
|
+
"""
|
|
1630
|
+
A Module represents a line card, supervisor, or other interchangeable hardware component within a ModuleBay.
|
|
1631
|
+
Each Module is assigned a ModuleType and Status, and optionally a Role and/or Tenant.
|
|
1632
|
+
|
|
1633
|
+
Each Module must be assigned to either a ModuleBay or a Location, but not both.
|
|
1634
|
+
|
|
1635
|
+
When a new Module is created, console, power and interface components are created along with it as dictated
|
|
1636
|
+
by the component templates assigned to its ModuleType. Components can also be added, modified, or deleted after
|
|
1637
|
+
the creation of a Module.
|
|
1638
|
+
"""
|
|
1639
|
+
|
|
1640
|
+
module_type = models.ForeignKey(to="dcim.ModuleType", on_delete=models.PROTECT, related_name="modules")
|
|
1641
|
+
parent_module_bay = models.OneToOneField(
|
|
1642
|
+
to="dcim.ModuleBay",
|
|
1643
|
+
on_delete=models.CASCADE,
|
|
1644
|
+
related_name="installed_module",
|
|
1645
|
+
blank=True,
|
|
1646
|
+
null=True,
|
|
1647
|
+
)
|
|
1648
|
+
status = StatusField()
|
|
1649
|
+
role = RoleField(blank=True, null=True)
|
|
1650
|
+
tenant = models.ForeignKey(
|
|
1651
|
+
to="tenancy.Tenant",
|
|
1652
|
+
on_delete=models.PROTECT,
|
|
1653
|
+
related_name="modules",
|
|
1654
|
+
blank=True,
|
|
1655
|
+
null=True,
|
|
1656
|
+
)
|
|
1657
|
+
serial = models.CharField( # noqa: DJ001 # django-nullable-model-string-field -- intentional
|
|
1658
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1659
|
+
blank=True,
|
|
1660
|
+
null=True,
|
|
1661
|
+
verbose_name="Serial number",
|
|
1662
|
+
db_index=True,
|
|
1663
|
+
)
|
|
1664
|
+
asset_tag = models.CharField(
|
|
1665
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1666
|
+
blank=True,
|
|
1667
|
+
null=True,
|
|
1668
|
+
unique=True,
|
|
1669
|
+
verbose_name="Asset tag",
|
|
1670
|
+
help_text="A unique tag used to identify this module",
|
|
1671
|
+
)
|
|
1672
|
+
location = models.ForeignKey(
|
|
1673
|
+
to="dcim.Location",
|
|
1674
|
+
on_delete=models.PROTECT,
|
|
1675
|
+
related_name="modules",
|
|
1676
|
+
blank=True,
|
|
1677
|
+
null=True,
|
|
1678
|
+
)
|
|
1679
|
+
# TODO: add software support for Modules
|
|
1680
|
+
|
|
1681
|
+
clone_fields = [
|
|
1682
|
+
"module_type",
|
|
1683
|
+
"role",
|
|
1684
|
+
"tenant",
|
|
1685
|
+
"location",
|
|
1686
|
+
"status",
|
|
1687
|
+
]
|
|
1688
|
+
|
|
1689
|
+
# The recursive nature of this model combined with the fact that it can be a child of a
|
|
1690
|
+
# device or location makes our natural key implementation unusable, so just use the pk
|
|
1691
|
+
natural_key_field_names = ["pk"]
|
|
1692
|
+
|
|
1693
|
+
class Meta:
|
|
1694
|
+
ordering = ("parent_module_bay", "location", "module_type", "asset_tag", "serial")
|
|
1695
|
+
constraints = [
|
|
1696
|
+
models.UniqueConstraint(
|
|
1697
|
+
fields=["module_type", "serial"],
|
|
1698
|
+
name="dcim_module_module_type_serial_unique",
|
|
1699
|
+
),
|
|
1700
|
+
]
|
|
1701
|
+
|
|
1702
|
+
def __str__(self):
|
|
1703
|
+
serial = f" (Serial: {self.serial})" if self.serial else ""
|
|
1704
|
+
asset_tag = f" (Asset Tag: {self.asset_tag})" if self.asset_tag else ""
|
|
1705
|
+
return str(self.module_type) + serial + asset_tag
|
|
1706
|
+
|
|
1707
|
+
@property
|
|
1708
|
+
def display(self):
|
|
1709
|
+
if self.location:
|
|
1710
|
+
return f"{self!s} at location {self.location}"
|
|
1711
|
+
elif self.parent_module_bay.parent_device is not None:
|
|
1712
|
+
return f"{self.module_type!s} installed in {self.parent_module_bay.parent_device.display}"
|
|
1713
|
+
else:
|
|
1714
|
+
return f"{self.module_type!s} installed in {self.parent_module_bay.parent_module.display}"
|
|
1715
|
+
|
|
1716
|
+
@property
|
|
1717
|
+
def device(self):
|
|
1718
|
+
"""Walk up parent chain to find the Device that this Module is installed in, if one exists."""
|
|
1719
|
+
if self.parent_module_bay is None:
|
|
1720
|
+
return None
|
|
1721
|
+
return self.parent_module_bay.parent
|
|
1722
|
+
|
|
1723
|
+
def clean(self):
|
|
1724
|
+
super().clean()
|
|
1725
|
+
|
|
1726
|
+
# Validate that the Module is associated with a Location or a ModuleBay
|
|
1727
|
+
if self.parent_module_bay is None and self.location is None:
|
|
1728
|
+
raise ValidationError("One of location or parent_module_bay must be set")
|
|
1729
|
+
|
|
1730
|
+
# Validate location
|
|
1731
|
+
if self.location is not None:
|
|
1732
|
+
if self.parent_module_bay is not None:
|
|
1733
|
+
raise ValidationError("Only one of location or parent_module_bay must be set")
|
|
1734
|
+
|
|
1735
|
+
if ContentType.objects.get_for_model(self) not in self.location.location_type.content_types.all():
|
|
1736
|
+
raise ValidationError(
|
|
1737
|
+
{"location": f'Modules may not associate to locations of type "{self.location.location_type}".'}
|
|
1738
|
+
)
|
|
1739
|
+
|
|
1740
|
+
def save(self, *args, **kwargs):
|
|
1741
|
+
is_new = not self.present_in_database
|
|
1742
|
+
|
|
1743
|
+
if self.serial == "":
|
|
1744
|
+
self.serial = None
|
|
1745
|
+
if self.asset_tag == "":
|
|
1746
|
+
self.asset_tag = None
|
|
1747
|
+
|
|
1748
|
+
# Prevent creating a Module that is its own ancestor, creating an infinite loop
|
|
1749
|
+
parent_module = getattr(self.parent_module_bay, "parent_module", None)
|
|
1750
|
+
while parent_module is not None:
|
|
1751
|
+
if parent_module == self:
|
|
1752
|
+
raise ValidationError("Creating this instance would cause an infinite loop.")
|
|
1753
|
+
parent_module = getattr(parent_module.parent_module_bay, "parent_module", None)
|
|
1754
|
+
|
|
1755
|
+
# Keep track of whether the parent module bay has changed so we can update the component names
|
|
1756
|
+
parent_module_changed = (
|
|
1757
|
+
not is_new and not Module.objects.filter(pk=self.pk, parent_module_bay=self.parent_module_bay).exists()
|
|
1758
|
+
)
|
|
1759
|
+
|
|
1760
|
+
super().save(*args, **kwargs)
|
|
1761
|
+
|
|
1762
|
+
# If this is a new Module, instantiate all related components per the ModuleType definition
|
|
1763
|
+
if is_new:
|
|
1764
|
+
self.create_components()
|
|
1765
|
+
|
|
1766
|
+
# Render component names when this Module is first created or when the parent module bay has changed
|
|
1767
|
+
if is_new or parent_module_changed:
|
|
1768
|
+
self.render_component_names()
|
|
1769
|
+
|
|
1770
|
+
def create_components(self):
|
|
1771
|
+
"""Create module components from the module type definition."""
|
|
1772
|
+
# The order of these is significant as
|
|
1773
|
+
# - PowerOutlet depends on PowerPort
|
|
1774
|
+
# - FrontPort depends on RearPort
|
|
1775
|
+
component_models = [
|
|
1776
|
+
(ConsolePort, self.module_type.console_port_templates.all()),
|
|
1777
|
+
(ConsoleServerPort, self.module_type.console_server_port_templates.all()),
|
|
1778
|
+
(PowerPort, self.module_type.power_port_templates.all()),
|
|
1779
|
+
(PowerOutlet, self.module_type.power_outlet_templates.all()),
|
|
1780
|
+
(Interface, self.module_type.interface_templates.all()),
|
|
1781
|
+
(RearPort, self.module_type.rear_port_templates.all()),
|
|
1782
|
+
(FrontPort, self.module_type.front_port_templates.all()),
|
|
1783
|
+
(ModuleBay, self.module_type.module_bay_templates.all()),
|
|
1784
|
+
]
|
|
1785
|
+
instantiated_components = []
|
|
1786
|
+
for model, templates in component_models:
|
|
1787
|
+
model.objects.bulk_create([x.instantiate(device=None, module=self) for x in templates])
|
|
1788
|
+
return instantiated_components
|
|
1789
|
+
|
|
1790
|
+
def render_component_names(self):
|
|
1791
|
+
"""
|
|
1792
|
+
Replace the {module}, {module.parent}, {module.parent.parent}, etc. template variables in descendant
|
|
1793
|
+
component names with the correct parent module bay positions.
|
|
1794
|
+
"""
|
|
1795
|
+
|
|
1796
|
+
# disable sorting to improve performance, sorting isn't necessary here
|
|
1797
|
+
component_models = [
|
|
1798
|
+
self.console_ports.all().order_by(),
|
|
1799
|
+
self.console_server_ports.all().order_by(),
|
|
1800
|
+
self.power_ports.all().order_by(),
|
|
1801
|
+
self.power_outlets.all().order_by(),
|
|
1802
|
+
self.interfaces.all().order_by(),
|
|
1803
|
+
self.rear_ports.all().order_by(),
|
|
1804
|
+
self.front_ports.all().order_by(),
|
|
1805
|
+
]
|
|
1806
|
+
|
|
1807
|
+
for component_qs in component_models:
|
|
1808
|
+
for component in component_qs.only("name", "module"):
|
|
1809
|
+
component.render_name_template(save=True)
|
|
1810
|
+
|
|
1811
|
+
for child in self.get_children():
|
|
1812
|
+
child.render_component_names()
|
|
1813
|
+
|
|
1814
|
+
def get_cables(self, pk_list=False):
|
|
1815
|
+
"""
|
|
1816
|
+
Return a QuerySet or PK list matching all Cables connected to any component of this Module.
|
|
1817
|
+
"""
|
|
1818
|
+
from .cables import Cable
|
|
1819
|
+
|
|
1820
|
+
cable_pks = []
|
|
1821
|
+
for component_model in [
|
|
1822
|
+
ConsolePort,
|
|
1823
|
+
ConsoleServerPort,
|
|
1824
|
+
PowerPort,
|
|
1825
|
+
PowerOutlet,
|
|
1826
|
+
Interface,
|
|
1827
|
+
FrontPort,
|
|
1828
|
+
RearPort,
|
|
1829
|
+
]:
|
|
1830
|
+
cable_pks += component_model.objects.filter(module=self, cable__isnull=False).values_list(
|
|
1831
|
+
"cable", flat=True
|
|
1832
|
+
)
|
|
1833
|
+
if pk_list:
|
|
1834
|
+
return cable_pks
|
|
1835
|
+
return Cable.objects.filter(pk__in=cable_pks)
|
|
1836
|
+
|
|
1837
|
+
def get_children(self):
|
|
1838
|
+
"""
|
|
1839
|
+
Return the set of child Modules installed in ModuleBays within this Module.
|
|
1840
|
+
"""
|
|
1841
|
+
return Module.objects.filter(parent_module_bay__parent_module=self)
|
nautobot/dcim/navigation.py
CHANGED
|
@@ -244,6 +244,44 @@ menu_items = (
|
|
|
244
244
|
),
|
|
245
245
|
),
|
|
246
246
|
),
|
|
247
|
+
NavMenuGroup(
|
|
248
|
+
name="Modules",
|
|
249
|
+
weight=250,
|
|
250
|
+
items=(
|
|
251
|
+
NavMenuItem(
|
|
252
|
+
link="dcim:module_list",
|
|
253
|
+
name="Modules",
|
|
254
|
+
weight=100,
|
|
255
|
+
permissions=[
|
|
256
|
+
"dcim.view_module",
|
|
257
|
+
],
|
|
258
|
+
buttons=(
|
|
259
|
+
NavMenuAddButton(
|
|
260
|
+
link="dcim:module_add",
|
|
261
|
+
permissions=[
|
|
262
|
+
"dcim.add_module",
|
|
263
|
+
],
|
|
264
|
+
),
|
|
265
|
+
),
|
|
266
|
+
),
|
|
267
|
+
NavMenuItem(
|
|
268
|
+
link="dcim:moduletype_list",
|
|
269
|
+
name="Module Types",
|
|
270
|
+
weight=200,
|
|
271
|
+
permissions=[
|
|
272
|
+
"dcim.view_moduletype",
|
|
273
|
+
],
|
|
274
|
+
buttons=(
|
|
275
|
+
NavMenuAddButton(
|
|
276
|
+
link="dcim:moduletype_add",
|
|
277
|
+
permissions=[
|
|
278
|
+
"dcim.add_moduletype",
|
|
279
|
+
],
|
|
280
|
+
),
|
|
281
|
+
),
|
|
282
|
+
),
|
|
283
|
+
),
|
|
284
|
+
),
|
|
247
285
|
NavMenuGroup(
|
|
248
286
|
name="Software",
|
|
249
287
|
weight=300,
|
|
@@ -448,6 +486,15 @@ menu_items = (
|
|
|
448
486
|
],
|
|
449
487
|
buttons=(),
|
|
450
488
|
),
|
|
489
|
+
NavMenuItem(
|
|
490
|
+
link="dcim:modulebay_list",
|
|
491
|
+
name="Module Bays",
|
|
492
|
+
weight=850,
|
|
493
|
+
permissions=[
|
|
494
|
+
"dcim.view_modulebay",
|
|
495
|
+
],
|
|
496
|
+
buttons=(),
|
|
497
|
+
),
|
|
451
498
|
NavMenuItem(
|
|
452
499
|
link="dcim:inventoryitem_list",
|
|
453
500
|
name="Inventory Items",
|
nautobot/dcim/signals.py
CHANGED
|
@@ -297,15 +297,15 @@ def prevent_adding_tagged_vlans_with_incorrect_mode_or_site(sender, instance, ac
|
|
|
297
297
|
@receiver(post_save, sender=ControllerManagedDeviceGroup)
|
|
298
298
|
def handle_controller_managed_device_group_controller_change(instance, raw=False, **_):
|
|
299
299
|
"""Update descendants when the top level `ControllerManagedDeviceGroup.controller` changes."""
|
|
300
|
-
if instance.parent or instance._original_controller == instance.controller:
|
|
301
|
-
return
|
|
302
|
-
|
|
303
300
|
logger = logging.getLogger(__name__ + ".ControllerManagedDeviceGroup")
|
|
304
301
|
|
|
305
302
|
if raw:
|
|
306
303
|
logger.debug("Skipping controller update for imported controller device group %s", instance)
|
|
307
304
|
return
|
|
308
305
|
|
|
306
|
+
if instance.parent or instance._original_controller == instance.controller:
|
|
307
|
+
return
|
|
308
|
+
|
|
309
309
|
with transaction.atomic():
|
|
310
310
|
for group in instance.descendants(include_self=False):
|
|
311
311
|
group.controller = instance.controller
|