nautobot 2.2.8__py3-none-any.whl → 2.3.0__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 +113 -0
- nautobot/cloud/filters.py +187 -0
- nautobot/cloud/forms.py +339 -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 +246 -0
- nautobot/cloud/navigation.py +85 -0
- nautobot/cloud/tables.py +157 -0
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +122 -0
- nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +111 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +69 -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 +125 -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 +110 -14
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +11 -3
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +28 -7
- nautobot/core/jobs/__init__.py +20 -3
- 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 +15 -19
- nautobot/core/settings.yaml +48 -13
- nautobot/core/settings_funcs.py +103 -0
- nautobot/core/tables.py +130 -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 +28 -8
- 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 +63 -14
- 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 +204 -2
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +12 -5
- nautobot/core/tests/test_templatetags_netutils.py +3 -3
- 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 +119 -67
- nautobot/core/views/mixins.py +105 -36
- nautobot/core/views/paginator.py +9 -3
- nautobot/core/views/renderers.py +121 -56
- nautobot/core/views/utils.py +81 -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 +252 -18
- nautobot/dcim/filters/__init__.py +373 -193
- nautobot/dcim/filters/mixins.py +274 -1
- nautobot/dcim/forms.py +834 -121
- 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 +862 -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 +282 -99
- nautobot/dcim/models/devices.py +472 -13
- nautobot/dcim/models/racks.py +0 -1
- nautobot/dcim/navigation.py +47 -0
- nautobot/dcim/signals.py +3 -3
- nautobot/dcim/tables/__init__.py +35 -23
- nautobot/dcim/tables/devices.py +248 -47
- 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 +14 -6
- 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 +6 -0
- 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 +159 -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 +693 -208
- nautobot/dcim/tests/test_filters.py +843 -217
- nautobot/dcim/tests/test_models.py +1103 -8
- nautobot/dcim/tests/test_views.py +1525 -343
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1109 -113
- 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 +73 -59
- 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 +460 -9
- nautobot/extras/filters/__init__.py +174 -3
- nautobot/extras/filters/mixins.py +46 -43
- nautobot/extras/forms/base.py +24 -5
- 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 +26 -3
- 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 +87 -3
- nautobot/extras/models/metadata.py +441 -0
- nautobot/extras/models/mixins.py +72 -62
- nautobot/extras/models/models.py +118 -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 +109 -101
- nautobot/extras/tables.py +201 -17
- 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 +11 -0
- 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 +509 -23
- 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 +6 -6
- nautobot/extras/tests/test_models.py +501 -4
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +586 -8
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +85 -16
- nautobot/extras/views.py +562 -122
- nautobot/ipam/__init__.py +0 -1
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/factory.py +17 -19
- nautobot/ipam/filters.py +13 -0
- nautobot/ipam/forms.py +8 -4
- 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 +20 -20
- nautobot/ipam/querysets.py +1 -1
- nautobot/ipam/signals.py +4 -2
- nautobot/ipam/tables.py +5 -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 +9 -2
- 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 +20 -34
- nautobot/project-static/css/base.css +21 -0
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +894 -90
- nautobot/project-static/docs/apps/index.html +894 -90
- nautobot/project-static/docs/apps/nautobot-apps.html +894 -90
- nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +921 -122
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +906 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1620 -905
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +937 -146
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +979 -190
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +903 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +899 -95
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +993 -195
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +976 -133
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1080 -274
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1244 -336
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1729 -877
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1166 -383
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2090 -1376
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2248 -1424
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +914 -113
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +965 -165
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1012 -225
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1915 -1279
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1848 -1104
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +906 -103
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2335 -1701
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1804 -1026
- nautobot/project-static/docs/development/apps/api/configuration-view.html +894 -90
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/global-search.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/graphql.html +894 -90
- nautobot/project-static/docs/development/apps/api/models/index.html +944 -92
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +894 -90
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +894 -90
- nautobot/project-static/docs/development/apps/api/prometheus.html +894 -90
- nautobot/project-static/docs/development/apps/api/setup.html +894 -90
- nautobot/project-static/docs/development/apps/api/testing.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +894 -90
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/base-template.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/index.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/notes.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +894 -90
- nautobot/project-static/docs/development/apps/api/views/urls.html +894 -90
- nautobot/project-static/docs/development/apps/index.html +894 -90
- nautobot/project-static/docs/development/apps/migration/code-updates.html +894 -90
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +894 -90
- nautobot/project-static/docs/development/apps/migration/from-v1.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +894 -90
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +894 -90
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +894 -90
- nautobot/project-static/docs/development/core/application-registry.html +894 -90
- nautobot/project-static/docs/development/core/best-practices.html +895 -90
- nautobot/project-static/docs/development/core/bootstrap-ui.html +894 -90
- nautobot/project-static/docs/development/core/caching.html +894 -90
- nautobot/project-static/docs/development/core/controllers.html +894 -90
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +894 -90
- nautobot/project-static/docs/development/core/generic-views.html +894 -90
- nautobot/project-static/docs/development/core/getting-started.html +894 -90
- nautobot/project-static/docs/development/core/homepage.html +894 -90
- nautobot/project-static/docs/development/core/index.html +905 -90
- nautobot/project-static/docs/development/core/model-checklist.html +903 -91
- nautobot/project-static/docs/development/core/model-features.html +894 -90
- nautobot/project-static/docs/development/core/natural-keys.html +894 -90
- nautobot/project-static/docs/development/core/navigation-menu.html +894 -90
- nautobot/project-static/docs/development/core/release-checklist.html +897 -93
- nautobot/project-static/docs/development/core/role-internals.html +894 -90
- nautobot/project-static/docs/development/core/settings.html +894 -90
- nautobot/project-static/docs/development/core/style-guide.html +895 -91
- nautobot/project-static/docs/development/core/templates.html +906 -91
- nautobot/project-static/docs/development/core/testing.html +894 -90
- nautobot/project-static/docs/development/core/user-preferences.html +894 -90
- nautobot/project-static/docs/development/index.html +894 -90
- nautobot/project-static/docs/development/jobs/index.html +1271 -453
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +894 -90
- nautobot/project-static/docs/index.html +9032 -13
- 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 +902 -91
- nautobot/project-static/docs/overview/design_philosophy.html +896 -92
- nautobot/project-static/docs/overview/index.html +13 -8228
- nautobot/project-static/docs/release-notes/index.html +1131 -94
- nautobot/project-static/docs/release-notes/version-1.0.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.1.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.2.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.3.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.4.html +894 -90
- nautobot/project-static/docs/release-notes/version-1.5.html +895 -91
- nautobot/project-static/docs/release-notes/version-1.6.html +895 -91
- nautobot/project-static/docs/release-notes/version-2.0.html +894 -90
- nautobot/project-static/docs/release-notes/version-2.1.html +894 -90
- nautobot/project-static/docs/release-notes/version-2.2.html +1137 -196
- nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
- nautobot/project-static/docs/requirements.txt +5 -5
- 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 +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +1025 -175
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +894 -90
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +902 -90
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +894 -90
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +946 -155
- nautobot/project-static/docs/user-guide/administration/installation/index.html +903 -95
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +936 -124
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +956 -159
- nautobot/project-static/docs/user-guide/administration/installation/services.html +915 -114
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +910 -101
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +894 -90
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +894 -90
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +894 -90
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +894 -90
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +977 -121
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +894 -90
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +895 -91
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +898 -90
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +897 -93
- 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 +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +920 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +925 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +915 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +922 -118
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +923 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +916 -107
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +938 -120
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +930 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +939 -121
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +930 -112
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +923 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +925 -117
- 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 +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +942 -85
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +945 -88
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +931 -127
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +908 -104
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +938 -90
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +899 -91
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +899 -91
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +903 -98
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +894 -90
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +899 -91
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +894 -90
- 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 +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +894 -90
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +894 -90
- nautobot/project-static/docs/user-guide/index.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1260 -787
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +898 -90
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +897 -93
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +952 -123
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +894 -90
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +894 -90
- 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 +24 -20
- 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/models.py +0 -2
- nautobot/virtualization/tables.py +12 -8
- 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.8.dist-info → nautobot-2.3.0.dist-info}/METADATA +21 -19
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/RECORD +684 -564
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
- 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.8.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
- {nautobot-2.2.8.dist-info → nautobot-2.3.0.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
|
|
|
@@ -439,7 +452,6 @@ class Platform(OrganizationalModel):
|
|
|
439
452
|
@extras_features(
|
|
440
453
|
"custom_links",
|
|
441
454
|
"custom_validators",
|
|
442
|
-
"dynamic_groups",
|
|
443
455
|
"export_templates",
|
|
444
456
|
"graphql",
|
|
445
457
|
"locations",
|
|
@@ -733,7 +745,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
733
745
|
pass
|
|
734
746
|
|
|
735
747
|
# Validate primary IP addresses
|
|
736
|
-
|
|
748
|
+
all_interfaces = self.all_interfaces.all()
|
|
737
749
|
for field in ["primary_ip4", "primary_ip6"]:
|
|
738
750
|
ip = getattr(self, field)
|
|
739
751
|
if ip is not None:
|
|
@@ -743,12 +755,14 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
743
755
|
else:
|
|
744
756
|
if ip.ip_version != 6:
|
|
745
757
|
raise ValidationError({f"{field}": f"{ip} is not an IPv6 address."})
|
|
746
|
-
if ipam_models.IPAddressToInterface.objects.filter(
|
|
758
|
+
if ipam_models.IPAddressToInterface.objects.filter(
|
|
759
|
+
ip_address=ip, interface__in=all_interfaces
|
|
760
|
+
).exists():
|
|
747
761
|
pass
|
|
748
762
|
elif (
|
|
749
763
|
ip.nat_inside is not None
|
|
750
764
|
and ipam_models.IPAddressToInterface.objects.filter(
|
|
751
|
-
ip_address=ip.nat_inside, interface__in=
|
|
765
|
+
ip_address=ip.nat_inside, interface__in=all_interfaces
|
|
752
766
|
).exists()
|
|
753
767
|
):
|
|
754
768
|
pass
|
|
@@ -847,7 +861,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
847
861
|
"""Create device components from the device type definition."""
|
|
848
862
|
# The order of these is significant as
|
|
849
863
|
# - PowerOutlet depends on PowerPort
|
|
850
|
-
# - FrontPort depends on
|
|
864
|
+
# - FrontPort depends on RearPort
|
|
851
865
|
component_models = [
|
|
852
866
|
(ConsolePort, self.device_type.console_port_templates.all()),
|
|
853
867
|
(ConsoleServerPort, self.device_type.console_server_port_templates.all()),
|
|
@@ -857,10 +871,11 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
857
871
|
(RearPort, self.device_type.rear_port_templates.all()),
|
|
858
872
|
(FrontPort, self.device_type.front_port_templates.all()),
|
|
859
873
|
(DeviceBay, self.device_type.device_bay_templates.all()),
|
|
874
|
+
(ModuleBay, self.device_type.module_bay_templates.all()),
|
|
860
875
|
]
|
|
861
876
|
instantiated_components = []
|
|
862
877
|
for model, templates in component_models:
|
|
863
|
-
model.objects.bulk_create([x.instantiate(self) for x in templates])
|
|
878
|
+
model.objects.bulk_create([x.instantiate(device=self) for x in templates])
|
|
864
879
|
return instantiated_components
|
|
865
880
|
|
|
866
881
|
@property
|
|
@@ -906,10 +921,11 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
906
921
|
Return a QuerySet matching all Interfaces assigned to this Device or, if this Device is a VC master, to another
|
|
907
922
|
Device belonging to the same VirtualChassis.
|
|
908
923
|
"""
|
|
909
|
-
|
|
924
|
+
qs = self.all_interfaces
|
|
910
925
|
if self.virtual_chassis and self.virtual_chassis.master == self:
|
|
911
|
-
|
|
912
|
-
|
|
926
|
+
for member in self.virtual_chassis.members.exclude(id=self.id):
|
|
927
|
+
qs |= member.all_interfaces.filter(mgmt_only=False)
|
|
928
|
+
return qs
|
|
913
929
|
|
|
914
930
|
@property
|
|
915
931
|
def common_vc_interfaces(self):
|
|
@@ -919,7 +935,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
919
935
|
"""
|
|
920
936
|
if self.virtual_chassis:
|
|
921
937
|
return self.virtual_chassis.member_interfaces
|
|
922
|
-
return self.
|
|
938
|
+
return self.all_interfaces
|
|
923
939
|
|
|
924
940
|
def get_cables(self, pk_list=False):
|
|
925
941
|
"""
|
|
@@ -950,6 +966,79 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
950
966
|
"""
|
|
951
967
|
return Device.objects.filter(parent_bay__device=self.pk)
|
|
952
968
|
|
|
969
|
+
@property
|
|
970
|
+
def all_modules(self):
|
|
971
|
+
"""
|
|
972
|
+
Return all child Modules installed in ModuleBays within this Device.
|
|
973
|
+
"""
|
|
974
|
+
# Supports Device->ModuleBay->Module->ModuleBay->Module->ModuleBay->Module->ModuleBay->Module
|
|
975
|
+
# This query looks for modules that are installed in a module_bay and attached to this device
|
|
976
|
+
# We artificially limit the recursion to 4 levels or we would be stuck in an infinite loop.
|
|
977
|
+
recursion_depth = MODULE_RECURSION_DEPTH_LIMIT
|
|
978
|
+
qs = Module.objects.all()
|
|
979
|
+
query = Q()
|
|
980
|
+
for level in range(recursion_depth):
|
|
981
|
+
recursive_query = "parent_module_bay__parent_module__" * level
|
|
982
|
+
query = query | Q(**{f"{recursive_query}parent_module_bay__parent_device": self})
|
|
983
|
+
return qs.filter(query)
|
|
984
|
+
|
|
985
|
+
@property
|
|
986
|
+
def all_console_ports(self):
|
|
987
|
+
"""
|
|
988
|
+
Return all Console Ports that are installed in the device or in modules that are installed in the device.
|
|
989
|
+
"""
|
|
990
|
+
# TODO: These could probably be optimized to reduce the number of joins
|
|
991
|
+
return ConsolePort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
992
|
+
|
|
993
|
+
@property
|
|
994
|
+
def all_console_server_ports(self):
|
|
995
|
+
"""
|
|
996
|
+
Return all Console Server Ports that are installed in the device or in modules that are installed in the device.
|
|
997
|
+
"""
|
|
998
|
+
return ConsoleServerPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
999
|
+
|
|
1000
|
+
@property
|
|
1001
|
+
def all_front_ports(self):
|
|
1002
|
+
"""
|
|
1003
|
+
Return all Front Ports that are installed in the device or in modules that are installed in the device.
|
|
1004
|
+
"""
|
|
1005
|
+
return FrontPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1006
|
+
|
|
1007
|
+
@property
|
|
1008
|
+
def all_interfaces(self):
|
|
1009
|
+
"""
|
|
1010
|
+
Return all Interfaces that are installed in the device or in modules that are installed in the device.
|
|
1011
|
+
"""
|
|
1012
|
+
return Interface.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1013
|
+
|
|
1014
|
+
@property
|
|
1015
|
+
def all_module_bays(self):
|
|
1016
|
+
"""
|
|
1017
|
+
Return all Module Bays that are installed in the device or in modules that are installed in the device.
|
|
1018
|
+
"""
|
|
1019
|
+
return ModuleBay.objects.filter(Q(parent_device=self) | Q(parent_module__in=self.all_modules))
|
|
1020
|
+
|
|
1021
|
+
@property
|
|
1022
|
+
def all_power_ports(self):
|
|
1023
|
+
"""
|
|
1024
|
+
Return all Power Ports that are installed in the device or in modules that are installed in the device.
|
|
1025
|
+
"""
|
|
1026
|
+
return PowerPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1027
|
+
|
|
1028
|
+
@property
|
|
1029
|
+
def all_power_outlets(self):
|
|
1030
|
+
"""
|
|
1031
|
+
Return all Power Outlets that are installed in the device or in modules that are installed in the device.
|
|
1032
|
+
"""
|
|
1033
|
+
return PowerOutlet.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1034
|
+
|
|
1035
|
+
@property
|
|
1036
|
+
def all_rear_ports(self):
|
|
1037
|
+
"""
|
|
1038
|
+
Return all Rear Ports that are installed in the device or in modules that are installed in the device.
|
|
1039
|
+
"""
|
|
1040
|
+
return RearPort.objects.filter(Q(device=self) | Q(module__in=self.all_modules))
|
|
1041
|
+
|
|
953
1042
|
|
|
954
1043
|
#
|
|
955
1044
|
# Virtual chassis
|
|
@@ -1019,7 +1108,6 @@ class VirtualChassis(PrimaryModel):
|
|
|
1019
1108
|
@extras_features(
|
|
1020
1109
|
"custom_links",
|
|
1021
1110
|
"custom_validators",
|
|
1022
|
-
"dynamic_groups",
|
|
1023
1111
|
"export_templates",
|
|
1024
1112
|
"graphql",
|
|
1025
1113
|
"statuses",
|
|
@@ -1065,6 +1153,10 @@ class DeviceRedundancyGroup(PrimaryModel):
|
|
|
1065
1153
|
def devices_sorted(self):
|
|
1066
1154
|
return self.devices.order_by("device_redundancy_group_priority")
|
|
1067
1155
|
|
|
1156
|
+
@property
|
|
1157
|
+
def controllers_sorted(self):
|
|
1158
|
+
return self.controllers.order_by("name")
|
|
1159
|
+
|
|
1068
1160
|
def __str__(self):
|
|
1069
1161
|
return self.name
|
|
1070
1162
|
|
|
@@ -1247,7 +1339,6 @@ class SoftwareVersion(PrimaryModel):
|
|
|
1247
1339
|
@extras_features(
|
|
1248
1340
|
"custom_links",
|
|
1249
1341
|
"custom_validators",
|
|
1250
|
-
"dynamic_groups",
|
|
1251
1342
|
"export_templates",
|
|
1252
1343
|
"graphql",
|
|
1253
1344
|
"locations",
|
|
@@ -1331,7 +1422,6 @@ class Controller(PrimaryModel):
|
|
|
1331
1422
|
@extras_features(
|
|
1332
1423
|
"custom_links",
|
|
1333
1424
|
"custom_validators",
|
|
1334
|
-
"dynamic_groups",
|
|
1335
1425
|
"export_templates",
|
|
1336
1426
|
"graphql",
|
|
1337
1427
|
"webhooks",
|
|
@@ -1382,3 +1472,372 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
|
|
|
1382
1472
|
raise ValidationError(
|
|
1383
1473
|
{"controller": "Controller device group must have the same controller as the parent group."}
|
|
1384
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
|
+
comments = models.TextField(blank=True)
|
|
1514
|
+
|
|
1515
|
+
clone_fields = [
|
|
1516
|
+
"manufacturer",
|
|
1517
|
+
]
|
|
1518
|
+
|
|
1519
|
+
class Meta:
|
|
1520
|
+
ordering = ("manufacturer", "model")
|
|
1521
|
+
unique_together = [
|
|
1522
|
+
("manufacturer", "model"),
|
|
1523
|
+
]
|
|
1524
|
+
|
|
1525
|
+
def __str__(self):
|
|
1526
|
+
return self.model
|
|
1527
|
+
|
|
1528
|
+
def to_yaml(self):
|
|
1529
|
+
data = OrderedDict(
|
|
1530
|
+
(
|
|
1531
|
+
("manufacturer", self.manufacturer.name),
|
|
1532
|
+
("model", self.model),
|
|
1533
|
+
("part_number", self.part_number),
|
|
1534
|
+
("comments", self.comments),
|
|
1535
|
+
)
|
|
1536
|
+
)
|
|
1537
|
+
|
|
1538
|
+
# Component templates
|
|
1539
|
+
if self.console_port_templates.exists():
|
|
1540
|
+
data["console-ports"] = [
|
|
1541
|
+
{
|
|
1542
|
+
"name": c.name,
|
|
1543
|
+
"type": c.type,
|
|
1544
|
+
}
|
|
1545
|
+
for c in self.console_port_templates.all()
|
|
1546
|
+
]
|
|
1547
|
+
if self.console_server_port_templates.exists():
|
|
1548
|
+
data["console-server-ports"] = [
|
|
1549
|
+
{
|
|
1550
|
+
"name": c.name,
|
|
1551
|
+
"type": c.type,
|
|
1552
|
+
}
|
|
1553
|
+
for c in self.console_server_port_templates.all()
|
|
1554
|
+
]
|
|
1555
|
+
if self.power_port_templates.exists():
|
|
1556
|
+
data["power-ports"] = [
|
|
1557
|
+
{
|
|
1558
|
+
"name": c.name,
|
|
1559
|
+
"type": c.type,
|
|
1560
|
+
"maximum_draw": c.maximum_draw,
|
|
1561
|
+
"allocated_draw": c.allocated_draw,
|
|
1562
|
+
}
|
|
1563
|
+
for c in self.power_port_templates.all()
|
|
1564
|
+
]
|
|
1565
|
+
if self.power_outlet_templates.exists():
|
|
1566
|
+
data["power-outlets"] = [
|
|
1567
|
+
{
|
|
1568
|
+
"name": c.name,
|
|
1569
|
+
"type": c.type,
|
|
1570
|
+
"power_port": c.power_port_template.name if c.power_port_template else None,
|
|
1571
|
+
"feed_leg": c.feed_leg,
|
|
1572
|
+
}
|
|
1573
|
+
for c in self.power_outlet_templates.all()
|
|
1574
|
+
]
|
|
1575
|
+
if self.interface_templates.exists():
|
|
1576
|
+
data["interfaces"] = [
|
|
1577
|
+
{
|
|
1578
|
+
"name": c.name,
|
|
1579
|
+
"type": c.type,
|
|
1580
|
+
"mgmt_only": c.mgmt_only,
|
|
1581
|
+
}
|
|
1582
|
+
for c in self.interface_templates.all()
|
|
1583
|
+
]
|
|
1584
|
+
if self.front_port_templates.exists():
|
|
1585
|
+
data["front-ports"] = [
|
|
1586
|
+
{
|
|
1587
|
+
"name": c.name,
|
|
1588
|
+
"type": c.type,
|
|
1589
|
+
"rear_port": c.rear_port_template.name,
|
|
1590
|
+
"rear_port_position": c.rear_port_position,
|
|
1591
|
+
}
|
|
1592
|
+
for c in self.front_port_templates.all()
|
|
1593
|
+
]
|
|
1594
|
+
if self.rear_port_templates.exists():
|
|
1595
|
+
data["rear-ports"] = [
|
|
1596
|
+
{
|
|
1597
|
+
"name": c.name,
|
|
1598
|
+
"type": c.type,
|
|
1599
|
+
"positions": c.positions,
|
|
1600
|
+
}
|
|
1601
|
+
for c in self.rear_port_templates.all()
|
|
1602
|
+
]
|
|
1603
|
+
if self.module_bay_templates.exists():
|
|
1604
|
+
data["module-bays"] = [
|
|
1605
|
+
{
|
|
1606
|
+
"name": c.name,
|
|
1607
|
+
"position": c.position,
|
|
1608
|
+
"label": c.label,
|
|
1609
|
+
"description": c.description,
|
|
1610
|
+
}
|
|
1611
|
+
for c in self.module_bay_templates.all()
|
|
1612
|
+
]
|
|
1613
|
+
|
|
1614
|
+
return yaml.dump(dict(data), sort_keys=False, allow_unicode=True)
|
|
1615
|
+
|
|
1616
|
+
@property
|
|
1617
|
+
def display(self):
|
|
1618
|
+
return f"{self.manufacturer.name} {self.model}"
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
@extras_features(
|
|
1622
|
+
"custom_links",
|
|
1623
|
+
"custom_validators",
|
|
1624
|
+
"export_templates",
|
|
1625
|
+
"graphql",
|
|
1626
|
+
"locations",
|
|
1627
|
+
"statuses",
|
|
1628
|
+
"webhooks",
|
|
1629
|
+
)
|
|
1630
|
+
class Module(PrimaryModel):
|
|
1631
|
+
"""
|
|
1632
|
+
A Module represents a line card, supervisor, or other interchangeable hardware component within a ModuleBay.
|
|
1633
|
+
Each Module is assigned a ModuleType and Status, and optionally a Role and/or Tenant.
|
|
1634
|
+
|
|
1635
|
+
Each Module must be assigned to either a ModuleBay or a Location, but not both.
|
|
1636
|
+
|
|
1637
|
+
When a new Module is created, console, power and interface components are created along with it as dictated
|
|
1638
|
+
by the component templates assigned to its ModuleType. Components can also be added, modified, or deleted after
|
|
1639
|
+
the creation of a Module.
|
|
1640
|
+
"""
|
|
1641
|
+
|
|
1642
|
+
module_type = models.ForeignKey(to="dcim.ModuleType", on_delete=models.PROTECT, related_name="modules")
|
|
1643
|
+
parent_module_bay = models.OneToOneField(
|
|
1644
|
+
to="dcim.ModuleBay",
|
|
1645
|
+
on_delete=models.CASCADE,
|
|
1646
|
+
related_name="installed_module",
|
|
1647
|
+
blank=True,
|
|
1648
|
+
null=True,
|
|
1649
|
+
)
|
|
1650
|
+
status = StatusField()
|
|
1651
|
+
role = RoleField(blank=True, null=True)
|
|
1652
|
+
tenant = models.ForeignKey(
|
|
1653
|
+
to="tenancy.Tenant",
|
|
1654
|
+
on_delete=models.PROTECT,
|
|
1655
|
+
related_name="modules",
|
|
1656
|
+
blank=True,
|
|
1657
|
+
null=True,
|
|
1658
|
+
)
|
|
1659
|
+
serial = models.CharField( # noqa: DJ001 # django-nullable-model-string-field -- intentional
|
|
1660
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1661
|
+
blank=True,
|
|
1662
|
+
null=True,
|
|
1663
|
+
verbose_name="Serial number",
|
|
1664
|
+
db_index=True,
|
|
1665
|
+
)
|
|
1666
|
+
asset_tag = models.CharField(
|
|
1667
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1668
|
+
blank=True,
|
|
1669
|
+
null=True,
|
|
1670
|
+
unique=True,
|
|
1671
|
+
verbose_name="Asset tag",
|
|
1672
|
+
help_text="A unique tag used to identify this module",
|
|
1673
|
+
)
|
|
1674
|
+
location = models.ForeignKey(
|
|
1675
|
+
to="dcim.Location",
|
|
1676
|
+
on_delete=models.PROTECT,
|
|
1677
|
+
related_name="modules",
|
|
1678
|
+
blank=True,
|
|
1679
|
+
null=True,
|
|
1680
|
+
)
|
|
1681
|
+
# TODO: add software support for Modules
|
|
1682
|
+
|
|
1683
|
+
clone_fields = [
|
|
1684
|
+
"module_type",
|
|
1685
|
+
"role",
|
|
1686
|
+
"tenant",
|
|
1687
|
+
"location",
|
|
1688
|
+
"status",
|
|
1689
|
+
]
|
|
1690
|
+
|
|
1691
|
+
# The recursive nature of this model combined with the fact that it can be a child of a
|
|
1692
|
+
# device or location makes our natural key implementation unusable, so just use the pk
|
|
1693
|
+
natural_key_field_names = ["pk"]
|
|
1694
|
+
|
|
1695
|
+
class Meta:
|
|
1696
|
+
ordering = ("parent_module_bay", "location", "module_type", "asset_tag", "serial")
|
|
1697
|
+
constraints = [
|
|
1698
|
+
models.UniqueConstraint(
|
|
1699
|
+
fields=["module_type", "serial"],
|
|
1700
|
+
name="dcim_module_module_type_serial_unique",
|
|
1701
|
+
),
|
|
1702
|
+
]
|
|
1703
|
+
|
|
1704
|
+
def __str__(self):
|
|
1705
|
+
serial = f" (Serial: {self.serial})" if self.serial else ""
|
|
1706
|
+
asset_tag = f" (Asset Tag: {self.asset_tag})" if self.asset_tag else ""
|
|
1707
|
+
return str(self.module_type) + serial + asset_tag
|
|
1708
|
+
|
|
1709
|
+
@property
|
|
1710
|
+
def display(self):
|
|
1711
|
+
if self.location:
|
|
1712
|
+
return f"{self!s} at location {self.location}"
|
|
1713
|
+
elif self.parent_module_bay.parent_device is not None:
|
|
1714
|
+
return f"{self.module_type!s} installed in {self.parent_module_bay.parent_device.display}"
|
|
1715
|
+
else:
|
|
1716
|
+
return f"{self.module_type!s} installed in {self.parent_module_bay.parent_module.display}"
|
|
1717
|
+
|
|
1718
|
+
@property
|
|
1719
|
+
def device(self):
|
|
1720
|
+
"""Walk up parent chain to find the Device that this Module is installed in, if one exists."""
|
|
1721
|
+
if self.parent_module_bay is None:
|
|
1722
|
+
return None
|
|
1723
|
+
return self.parent_module_bay.parent
|
|
1724
|
+
|
|
1725
|
+
def clean(self):
|
|
1726
|
+
super().clean()
|
|
1727
|
+
|
|
1728
|
+
# Validate that the Module is associated with a Location or a ModuleBay
|
|
1729
|
+
if self.parent_module_bay is None and self.location is None:
|
|
1730
|
+
raise ValidationError("One of location or parent_module_bay must be set")
|
|
1731
|
+
|
|
1732
|
+
# Validate location
|
|
1733
|
+
if self.location is not None:
|
|
1734
|
+
if self.parent_module_bay is not None:
|
|
1735
|
+
raise ValidationError("Only one of location or parent_module_bay must be set")
|
|
1736
|
+
|
|
1737
|
+
if ContentType.objects.get_for_model(self) not in self.location.location_type.content_types.all():
|
|
1738
|
+
raise ValidationError(
|
|
1739
|
+
{"location": f'Modules may not associate to locations of type "{self.location.location_type}".'}
|
|
1740
|
+
)
|
|
1741
|
+
|
|
1742
|
+
def save(self, *args, **kwargs):
|
|
1743
|
+
is_new = not self.present_in_database
|
|
1744
|
+
|
|
1745
|
+
if self.serial == "":
|
|
1746
|
+
self.serial = None
|
|
1747
|
+
if self.asset_tag == "":
|
|
1748
|
+
self.asset_tag = None
|
|
1749
|
+
|
|
1750
|
+
# Prevent creating a Module that is its own ancestor, creating an infinite loop
|
|
1751
|
+
parent_module = getattr(self.parent_module_bay, "parent_module", None)
|
|
1752
|
+
while parent_module is not None:
|
|
1753
|
+
if parent_module == self:
|
|
1754
|
+
raise ValidationError("Creating this instance would cause an infinite loop.")
|
|
1755
|
+
parent_module = getattr(parent_module.parent_module_bay, "parent_module", None)
|
|
1756
|
+
|
|
1757
|
+
# Keep track of whether the parent module bay has changed so we can update the component names
|
|
1758
|
+
parent_module_changed = (
|
|
1759
|
+
not is_new and not Module.objects.filter(pk=self.pk, parent_module_bay=self.parent_module_bay).exists()
|
|
1760
|
+
)
|
|
1761
|
+
|
|
1762
|
+
super().save(*args, **kwargs)
|
|
1763
|
+
|
|
1764
|
+
# If this is a new Module, instantiate all related components per the ModuleType definition
|
|
1765
|
+
if is_new:
|
|
1766
|
+
self.create_components()
|
|
1767
|
+
|
|
1768
|
+
# Render component names when this Module is first created or when the parent module bay has changed
|
|
1769
|
+
if is_new or parent_module_changed:
|
|
1770
|
+
self.render_component_names()
|
|
1771
|
+
|
|
1772
|
+
def create_components(self):
|
|
1773
|
+
"""Create module components from the module type definition."""
|
|
1774
|
+
# The order of these is significant as
|
|
1775
|
+
# - PowerOutlet depends on PowerPort
|
|
1776
|
+
# - FrontPort depends on RearPort
|
|
1777
|
+
component_models = [
|
|
1778
|
+
(ConsolePort, self.module_type.console_port_templates.all()),
|
|
1779
|
+
(ConsoleServerPort, self.module_type.console_server_port_templates.all()),
|
|
1780
|
+
(PowerPort, self.module_type.power_port_templates.all()),
|
|
1781
|
+
(PowerOutlet, self.module_type.power_outlet_templates.all()),
|
|
1782
|
+
(Interface, self.module_type.interface_templates.all()),
|
|
1783
|
+
(RearPort, self.module_type.rear_port_templates.all()),
|
|
1784
|
+
(FrontPort, self.module_type.front_port_templates.all()),
|
|
1785
|
+
(ModuleBay, self.module_type.module_bay_templates.all()),
|
|
1786
|
+
]
|
|
1787
|
+
instantiated_components = []
|
|
1788
|
+
for model, templates in component_models:
|
|
1789
|
+
model.objects.bulk_create([x.instantiate(device=None, module=self) for x in templates])
|
|
1790
|
+
return instantiated_components
|
|
1791
|
+
|
|
1792
|
+
def render_component_names(self):
|
|
1793
|
+
"""
|
|
1794
|
+
Replace the {module}, {module.parent}, {module.parent.parent}, etc. template variables in descendant
|
|
1795
|
+
component names with the correct parent module bay positions.
|
|
1796
|
+
"""
|
|
1797
|
+
|
|
1798
|
+
# disable sorting to improve performance, sorting isn't necessary here
|
|
1799
|
+
component_models = [
|
|
1800
|
+
self.console_ports.all().order_by(),
|
|
1801
|
+
self.console_server_ports.all().order_by(),
|
|
1802
|
+
self.power_ports.all().order_by(),
|
|
1803
|
+
self.power_outlets.all().order_by(),
|
|
1804
|
+
self.interfaces.all().order_by(),
|
|
1805
|
+
self.rear_ports.all().order_by(),
|
|
1806
|
+
self.front_ports.all().order_by(),
|
|
1807
|
+
]
|
|
1808
|
+
|
|
1809
|
+
for component_qs in component_models:
|
|
1810
|
+
for component in component_qs.only("name", "module"):
|
|
1811
|
+
component.render_name_template(save=True)
|
|
1812
|
+
|
|
1813
|
+
for child in self.get_children():
|
|
1814
|
+
child.render_component_names()
|
|
1815
|
+
|
|
1816
|
+
def get_cables(self, pk_list=False):
|
|
1817
|
+
"""
|
|
1818
|
+
Return a QuerySet or PK list matching all Cables connected to any component of this Module.
|
|
1819
|
+
"""
|
|
1820
|
+
from .cables import Cable
|
|
1821
|
+
|
|
1822
|
+
cable_pks = []
|
|
1823
|
+
for component_model in [
|
|
1824
|
+
ConsolePort,
|
|
1825
|
+
ConsoleServerPort,
|
|
1826
|
+
PowerPort,
|
|
1827
|
+
PowerOutlet,
|
|
1828
|
+
Interface,
|
|
1829
|
+
FrontPort,
|
|
1830
|
+
RearPort,
|
|
1831
|
+
]:
|
|
1832
|
+
cable_pks += component_model.objects.filter(module=self, cable__isnull=False).values_list(
|
|
1833
|
+
"cable", flat=True
|
|
1834
|
+
)
|
|
1835
|
+
if pk_list:
|
|
1836
|
+
return cable_pks
|
|
1837
|
+
return Cable.objects.filter(pk__in=cable_pks)
|
|
1838
|
+
|
|
1839
|
+
def get_children(self):
|
|
1840
|
+
"""
|
|
1841
|
+
Return the set of child Modules installed in ModuleBays within this Module.
|
|
1842
|
+
"""
|
|
1843
|
+
return Module.objects.filter(parent_module_bay__parent_module=self)
|
nautobot/dcim/models/racks.py
CHANGED
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
|