nautobot 2.2.9__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 +95 -13
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +11 -3
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/schema.py +26 -4
- nautobot/core/jobs/__init__.py +16 -2
- 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 +2 -17
- nautobot/core/settings.yaml +34 -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 +13 -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_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 +122 -0
- 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 +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 +275 -99
- nautobot/dcim/models/devices.py +468 -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 +229 -43
- 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/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 +1072 -8
- nautobot/dcim/tests/test_views.py +1510 -341
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1106 -116
- 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 +66 -0
- 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 +14 -1
- 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 +6 -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 +95 -100
- nautobot/extras/tables.py +165 -12
- 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/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 +565 -8
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +51 -11
- nautobot/extras/views.py +542 -76
- 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 +11 -8
- 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 +6 -0
- 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 +18 -26
- nautobot/project-static/css/base.css +20 -0
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +892 -88
- nautobot/project-static/docs/apps/index.html +892 -88
- nautobot/project-static/docs/apps/nautobot-apps.html +892 -88
- 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 +919 -120
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +904 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1618 -903
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +935 -144
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +977 -188
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +901 -99
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +897 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +991 -193
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +974 -131
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1078 -272
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1242 -334
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1727 -875
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1164 -381
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2088 -1374
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2246 -1422
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +912 -111
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +963 -163
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1010 -223
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1913 -1277
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1846 -1102
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +904 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2331 -1699
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1802 -1024
- nautobot/project-static/docs/development/apps/api/configuration-view.html +892 -88
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/global-search.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/graphql.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/index.html +942 -90
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +892 -88
- nautobot/project-static/docs/development/apps/api/prometheus.html +892 -88
- nautobot/project-static/docs/development/apps/api/setup.html +892 -88
- nautobot/project-static/docs/development/apps/api/testing.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/base-template.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/notes.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/urls.html +892 -88
- nautobot/project-static/docs/development/apps/index.html +892 -88
- nautobot/project-static/docs/development/apps/migration/code-updates.html +892 -88
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +892 -88
- nautobot/project-static/docs/development/apps/migration/from-v1.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +892 -88
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +892 -88
- nautobot/project-static/docs/development/core/application-registry.html +892 -88
- nautobot/project-static/docs/development/core/best-practices.html +893 -88
- nautobot/project-static/docs/development/core/bootstrap-ui.html +892 -88
- nautobot/project-static/docs/development/core/caching.html +892 -88
- nautobot/project-static/docs/development/core/controllers.html +892 -88
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +892 -88
- nautobot/project-static/docs/development/core/generic-views.html +892 -88
- nautobot/project-static/docs/development/core/getting-started.html +892 -88
- nautobot/project-static/docs/development/core/homepage.html +892 -88
- nautobot/project-static/docs/development/core/index.html +892 -88
- nautobot/project-static/docs/development/core/model-checklist.html +901 -89
- nautobot/project-static/docs/development/core/model-features.html +892 -88
- nautobot/project-static/docs/development/core/natural-keys.html +892 -88
- nautobot/project-static/docs/development/core/navigation-menu.html +892 -88
- nautobot/project-static/docs/development/core/release-checklist.html +895 -91
- nautobot/project-static/docs/development/core/role-internals.html +892 -88
- nautobot/project-static/docs/development/core/settings.html +892 -88
- nautobot/project-static/docs/development/core/style-guide.html +893 -89
- nautobot/project-static/docs/development/core/templates.html +904 -89
- nautobot/project-static/docs/development/core/testing.html +892 -88
- nautobot/project-static/docs/development/core/user-preferences.html +892 -88
- nautobot/project-static/docs/development/index.html +892 -88
- nautobot/project-static/docs/development/jobs/index.html +893 -89
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +892 -88
- nautobot/project-static/docs/index.html +892 -88
- 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 +900 -89
- nautobot/project-static/docs/overview/design_philosophy.html +892 -88
- nautobot/project-static/docs/release-notes/index.html +1129 -92
- nautobot/project-static/docs/release-notes/version-1.0.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.1.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.2.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.3.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.4.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.5.html +893 -89
- nautobot/project-static/docs/release-notes/version-1.6.html +893 -89
- nautobot/project-static/docs/release-notes/version-2.0.html +892 -88
- nautobot/project-static/docs/release-notes/version-2.1.html +892 -88
- nautobot/project-static/docs/release-notes/version-2.2.html +895 -91
- 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 +331 -256
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +992 -174
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +896 -88
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +944 -153
- nautobot/project-static/docs/user-guide/administration/installation/index.html +901 -93
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +934 -122
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +954 -157
- nautobot/project-static/docs/user-guide/administration/installation/services.html +913 -112
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +908 -99
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +892 -88
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +892 -88
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +892 -88
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +893 -89
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +893 -89
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +896 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +895 -91
- 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 +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +918 -100
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +913 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +914 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +936 -118
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +928 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +937 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +923 -115
- 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 +916 -112
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +940 -83
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +943 -86
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +921 -103
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +929 -125
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +922 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +936 -88
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +897 -89
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +897 -89
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +901 -96
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +897 -89
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +892 -88
- 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 +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +892 -88
- nautobot/project-static/docs/user-guide/index.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1258 -785
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +896 -88
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +950 -121
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +892 -88
- 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 +10 -3
- 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.0.dist-info}/METADATA +20 -18
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/RECORD +677 -557
- 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.9.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
1
3
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
|
2
4
|
from django.contrib.contenttypes.models import ContentType
|
|
3
5
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
@@ -36,6 +38,7 @@ from nautobot.dcim.constants import (
|
|
|
36
38
|
from nautobot.extras.models import (
|
|
37
39
|
ChangeLoggedModel,
|
|
38
40
|
RelationshipModel,
|
|
41
|
+
RoleField,
|
|
39
42
|
Status,
|
|
40
43
|
StatusField,
|
|
41
44
|
)
|
|
@@ -52,6 +55,7 @@ __all__ = (
|
|
|
52
55
|
"InterfaceRedundancyGroup",
|
|
53
56
|
"InterfaceRedundancyGroupAssociation",
|
|
54
57
|
"InventoryItem",
|
|
58
|
+
"ModuleBay",
|
|
55
59
|
"PathEndpoint",
|
|
56
60
|
"PowerOutlet",
|
|
57
61
|
"PowerPort",
|
|
@@ -70,7 +74,7 @@ class ComponentModel(PrimaryModel):
|
|
|
70
74
|
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
71
75
|
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
72
76
|
|
|
73
|
-
natural_key_field_names = ["
|
|
77
|
+
natural_key_field_names = ["device", "name"]
|
|
74
78
|
|
|
75
79
|
class Meta:
|
|
76
80
|
abstract = True
|
|
@@ -84,6 +88,9 @@ class ComponentModel(PrimaryModel):
|
|
|
84
88
|
"""
|
|
85
89
|
Return a new ObjectChange with the `related_object` pinned to the `device` by default.
|
|
86
90
|
"""
|
|
91
|
+
if "related_object" in kwargs:
|
|
92
|
+
return super().to_objectchange(action, **kwargs)
|
|
93
|
+
|
|
87
94
|
# Annotate the parent Device
|
|
88
95
|
try:
|
|
89
96
|
device = self.device
|
|
@@ -93,6 +100,114 @@ class ComponentModel(PrimaryModel):
|
|
|
93
100
|
|
|
94
101
|
return super().to_objectchange(action, related_object=device, **kwargs)
|
|
95
102
|
|
|
103
|
+
@property
|
|
104
|
+
def parent(self):
|
|
105
|
+
return self.device
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class ModularComponentModel(ComponentModel):
|
|
109
|
+
device = ForeignKeyWithAutoRelatedName(
|
|
110
|
+
to="dcim.Device",
|
|
111
|
+
on_delete=models.CASCADE,
|
|
112
|
+
blank=True,
|
|
113
|
+
null=True,
|
|
114
|
+
)
|
|
115
|
+
module = ForeignKeyWithAutoRelatedName(
|
|
116
|
+
to="dcim.Module",
|
|
117
|
+
on_delete=models.CASCADE,
|
|
118
|
+
blank=True,
|
|
119
|
+
null=True,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
natural_key_field_names = ["device", "module", "name"]
|
|
123
|
+
|
|
124
|
+
class Meta:
|
|
125
|
+
abstract = True
|
|
126
|
+
ordering = ("device", "module", "_name")
|
|
127
|
+
constraints = [
|
|
128
|
+
models.UniqueConstraint(
|
|
129
|
+
fields=("device", "name"),
|
|
130
|
+
name="%(app_label)s_%(class)s_device_name_unique",
|
|
131
|
+
),
|
|
132
|
+
models.UniqueConstraint(
|
|
133
|
+
fields=("module", "name"),
|
|
134
|
+
name="%(app_label)s_%(class)s_module_name_unique",
|
|
135
|
+
),
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
@property
|
|
139
|
+
def parent(self):
|
|
140
|
+
"""Device that this component belongs to, walking up module inheritance if necessary."""
|
|
141
|
+
return self.module.device if self.module else self.device
|
|
142
|
+
|
|
143
|
+
def render_name_template(self, save=False):
|
|
144
|
+
"""
|
|
145
|
+
Replace the {module}, {module.parent}, {module.parent.parent}, etc. variables in the name
|
|
146
|
+
field with the actual module bay positions.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
save (bool, optional): If True, save the object after updating the name field. Defaults to False.
|
|
150
|
+
|
|
151
|
+
If a module bay position is blank, it will be skipped and the parents will be checked until a non-blank
|
|
152
|
+
position is found. If all parent module bays are exhausted, the variable is left as-is.
|
|
153
|
+
|
|
154
|
+
Example:
|
|
155
|
+
- Device (name="Device 1")
|
|
156
|
+
- ModuleBay (position="A")
|
|
157
|
+
- Module
|
|
158
|
+
- ModuleBay (position="")
|
|
159
|
+
- Module
|
|
160
|
+
- Interface (name="{module}{module.parent}")
|
|
161
|
+
|
|
162
|
+
The deeply nested interface would be named "A{module.parent}" after calling this method.
|
|
163
|
+
"""
|
|
164
|
+
if self.module and self.module.parent_module_bay and "{module" in self.name:
|
|
165
|
+
name = ""
|
|
166
|
+
module_bay = self.module.parent_module_bay
|
|
167
|
+
positions = []
|
|
168
|
+
while module_bay is not None:
|
|
169
|
+
position = getattr(module_bay, "position", None)
|
|
170
|
+
if position:
|
|
171
|
+
positions.append(position)
|
|
172
|
+
module_bay = getattr(getattr(module_bay, "parent_module", None), "parent_module_bay", None)
|
|
173
|
+
for part in re.split(r"({module(?:\.parent)*})", self.name):
|
|
174
|
+
if re.fullmatch(r"{module(\.parent)*}", part):
|
|
175
|
+
depth = part.count(".parent")
|
|
176
|
+
if depth < len(positions):
|
|
177
|
+
name += positions[depth]
|
|
178
|
+
continue
|
|
179
|
+
name += part
|
|
180
|
+
if self.name != name:
|
|
181
|
+
self.name = name
|
|
182
|
+
if save:
|
|
183
|
+
self.save(update_fields=["_name", "name"])
|
|
184
|
+
|
|
185
|
+
def to_objectchange(self, action, **kwargs):
|
|
186
|
+
"""
|
|
187
|
+
Return a new ObjectChange with the `related_object` pinned to the parent `device` or `module`.
|
|
188
|
+
"""
|
|
189
|
+
if "related_object" in kwargs:
|
|
190
|
+
return super().to_objectchange(action, **kwargs)
|
|
191
|
+
|
|
192
|
+
# Annotate the parent
|
|
193
|
+
try:
|
|
194
|
+
parent = self.device if self.device else self.module
|
|
195
|
+
except ObjectDoesNotExist:
|
|
196
|
+
# The parent may have already been deleted
|
|
197
|
+
parent = None
|
|
198
|
+
|
|
199
|
+
return super().to_objectchange(action, related_object=parent, **kwargs)
|
|
200
|
+
|
|
201
|
+
def clean(self):
|
|
202
|
+
super().clean()
|
|
203
|
+
|
|
204
|
+
# Validate that a Device or Module is set, but not both
|
|
205
|
+
if self.device and self.module:
|
|
206
|
+
raise ValidationError("Only one of device or module must be set")
|
|
207
|
+
|
|
208
|
+
if not (self.device or self.module):
|
|
209
|
+
raise ValidationError("Either device or module must be set")
|
|
210
|
+
|
|
96
211
|
|
|
97
212
|
class CableTermination(models.Model):
|
|
98
213
|
"""
|
|
@@ -212,9 +327,9 @@ class PathEndpoint(models.Model):
|
|
|
212
327
|
"graphql",
|
|
213
328
|
"webhooks",
|
|
214
329
|
)
|
|
215
|
-
class ConsolePort(CableTermination, PathEndpoint
|
|
330
|
+
class ConsolePort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
216
331
|
"""
|
|
217
|
-
A physical console port within a Device. ConsolePorts connect to ConsoleServerPorts.
|
|
332
|
+
A physical console port within a Device or Module. ConsolePorts connect to ConsoleServerPorts.
|
|
218
333
|
"""
|
|
219
334
|
|
|
220
335
|
type = models.CharField(
|
|
@@ -224,14 +339,6 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
224
339
|
help_text="Physical port type",
|
|
225
340
|
)
|
|
226
341
|
|
|
227
|
-
class Meta:
|
|
228
|
-
ordering = ("device", "_name")
|
|
229
|
-
unique_together = ("device", "name")
|
|
230
|
-
|
|
231
|
-
@property
|
|
232
|
-
def parent(self):
|
|
233
|
-
return self.device
|
|
234
|
-
|
|
235
342
|
|
|
236
343
|
#
|
|
237
344
|
# Console server ports
|
|
@@ -239,9 +346,9 @@ class ConsolePort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
239
346
|
|
|
240
347
|
|
|
241
348
|
@extras_features("custom_links", "cable_terminations", "custom_validators", "graphql", "webhooks")
|
|
242
|
-
class ConsoleServerPort(CableTermination, PathEndpoint
|
|
349
|
+
class ConsoleServerPort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
243
350
|
"""
|
|
244
|
-
A physical port within a Device (typically a designated console server) which provides access to ConsolePorts.
|
|
351
|
+
A physical port within a Device or Module (typically a designated console server) which provides access to ConsolePorts.
|
|
245
352
|
"""
|
|
246
353
|
|
|
247
354
|
type = models.CharField(
|
|
@@ -251,14 +358,6 @@ class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
251
358
|
help_text="Physical port type",
|
|
252
359
|
)
|
|
253
360
|
|
|
254
|
-
class Meta:
|
|
255
|
-
ordering = ("device", "_name")
|
|
256
|
-
unique_together = ("device", "name")
|
|
257
|
-
|
|
258
|
-
@property
|
|
259
|
-
def parent(self):
|
|
260
|
-
return self.device
|
|
261
|
-
|
|
262
361
|
|
|
263
362
|
#
|
|
264
363
|
# Power ports
|
|
@@ -273,9 +372,9 @@ class ConsoleServerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
273
372
|
"graphql",
|
|
274
373
|
"webhooks",
|
|
275
374
|
)
|
|
276
|
-
class PowerPort(CableTermination, PathEndpoint
|
|
375
|
+
class PowerPort(ModularComponentModel, CableTermination, PathEndpoint):
|
|
277
376
|
"""
|
|
278
|
-
A physical power supply (intake) port within a Device. PowerPorts connect to PowerOutlets.
|
|
377
|
+
A physical power supply (intake) port within a Device or Module. PowerPorts connect to PowerOutlets.
|
|
279
378
|
"""
|
|
280
379
|
|
|
281
380
|
type = models.CharField(
|
|
@@ -297,14 +396,6 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
297
396
|
help_text="Allocated power draw (watts)",
|
|
298
397
|
)
|
|
299
398
|
|
|
300
|
-
class Meta:
|
|
301
|
-
ordering = ("device", "_name")
|
|
302
|
-
unique_together = ("device", "name")
|
|
303
|
-
|
|
304
|
-
@property
|
|
305
|
-
def parent(self):
|
|
306
|
-
return self.device
|
|
307
|
-
|
|
308
399
|
def clean(self):
|
|
309
400
|
super().clean()
|
|
310
401
|
|
|
@@ -384,9 +475,9 @@ class PowerPort(CableTermination, PathEndpoint, ComponentModel):
|
|
|
384
475
|
|
|
385
476
|
|
|
386
477
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
387
|
-
class PowerOutlet(CableTermination, PathEndpoint
|
|
478
|
+
class PowerOutlet(ModularComponentModel, CableTermination, PathEndpoint):
|
|
388
479
|
"""
|
|
389
|
-
A physical power outlet (output) within a Device which provides power to a PowerPort.
|
|
480
|
+
A physical power outlet (output) within a Device or Module which provides power to a PowerPort.
|
|
390
481
|
"""
|
|
391
482
|
|
|
392
483
|
type = models.CharField(
|
|
@@ -410,19 +501,11 @@ class PowerOutlet(CableTermination, PathEndpoint, ComponentModel):
|
|
|
410
501
|
help_text="Phase (for three-phase feeds)",
|
|
411
502
|
)
|
|
412
503
|
|
|
413
|
-
class Meta:
|
|
414
|
-
ordering = ("device", "_name")
|
|
415
|
-
unique_together = ("device", "name")
|
|
416
|
-
|
|
417
|
-
@property
|
|
418
|
-
def parent(self):
|
|
419
|
-
return self.device
|
|
420
|
-
|
|
421
504
|
def clean(self):
|
|
422
505
|
super().clean()
|
|
423
506
|
|
|
424
507
|
# Validate power port assignment
|
|
425
|
-
if self.power_port and self.power_port.
|
|
508
|
+
if self.power_port and self.parent and self.power_port.parent != self.parent:
|
|
426
509
|
raise ValidationError(f"Parent power port ({self.power_port}) must belong to the same device")
|
|
427
510
|
|
|
428
511
|
|
|
@@ -446,6 +529,7 @@ class BaseInterface(RelationshipModel):
|
|
|
446
529
|
validators=[MinValueValidator(1), MaxValueValidator(65536)],
|
|
447
530
|
verbose_name="MTU",
|
|
448
531
|
)
|
|
532
|
+
role = RoleField(blank=True, null=True)
|
|
449
533
|
mode = models.CharField(max_length=50, choices=InterfaceModeChoices, blank=True)
|
|
450
534
|
parent_interface = models.ForeignKey(
|
|
451
535
|
to="self",
|
|
@@ -500,9 +584,9 @@ class BaseInterface(RelationshipModel):
|
|
|
500
584
|
"statuses",
|
|
501
585
|
"webhooks",
|
|
502
586
|
)
|
|
503
|
-
class Interface(CableTermination, PathEndpoint,
|
|
587
|
+
class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInterface):
|
|
504
588
|
"""
|
|
505
|
-
A network interface within a Device. A physical Interface can connect to exactly one other Interface.
|
|
589
|
+
A network interface within a Device or Module. A physical Interface can connect to exactly one other Interface.
|
|
506
590
|
"""
|
|
507
591
|
|
|
508
592
|
# Override ComponentModel._name to specify naturalize_interface function
|
|
@@ -559,15 +643,14 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
559
643
|
verbose_name="IP Addresses",
|
|
560
644
|
)
|
|
561
645
|
|
|
562
|
-
class Meta:
|
|
563
|
-
ordering = ("device", CollateAsChar("_name"))
|
|
564
|
-
unique_together = ("device", "name")
|
|
646
|
+
class Meta(ModularComponentModel.Meta):
|
|
647
|
+
ordering = ("device", "module", CollateAsChar("_name"))
|
|
565
648
|
|
|
566
649
|
def clean(self):
|
|
567
650
|
super().clean()
|
|
568
651
|
|
|
569
652
|
# VRF validation
|
|
570
|
-
if self.vrf and self.vrf not in self.
|
|
653
|
+
if self.vrf and self.parent and self.vrf not in self.parent.vrfs.all():
|
|
571
654
|
# TODO(jathan): Or maybe we automatically add the VRF to the device?
|
|
572
655
|
raise ValidationError({"vrf": "VRF must be assigned to same Device."})
|
|
573
656
|
|
|
@@ -578,19 +661,23 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
578
661
|
raise ValidationError({"lag": "A LAG interface cannot be its own parent."})
|
|
579
662
|
|
|
580
663
|
# An interface's LAG must belong to the same device or virtual chassis
|
|
581
|
-
if self.lag.
|
|
582
|
-
if self.
|
|
664
|
+
if self.parent and self.lag.parent != self.parent:
|
|
665
|
+
if self.lag.parent is None:
|
|
666
|
+
raise ValidationError(
|
|
667
|
+
{"lag": f"The selected LAG interface ({self.lag}) does not belong to a device."}
|
|
668
|
+
)
|
|
669
|
+
elif self.parent.virtual_chassis is None:
|
|
583
670
|
raise ValidationError(
|
|
584
671
|
{
|
|
585
|
-
"lag": f"The selected LAG interface ({self.lag}) belongs to a different device ({self.lag.
|
|
672
|
+
"lag": f"The selected LAG interface ({self.lag}) belongs to a different device ({self.lag.parent})."
|
|
586
673
|
}
|
|
587
674
|
)
|
|
588
|
-
elif self.lag.
|
|
675
|
+
elif self.lag.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
|
|
589
676
|
raise ValidationError(
|
|
590
677
|
{
|
|
591
678
|
"lag": (
|
|
592
|
-
f"The selected LAG interface ({self.lag}) belongs to {self.lag.
|
|
593
|
-
f"of virtual chassis {self.
|
|
679
|
+
f"The selected LAG interface ({self.lag}) belongs to {self.lag.parent}, which is not part "
|
|
680
|
+
f"of virtual chassis {self.parent.virtual_chassis}."
|
|
594
681
|
)
|
|
595
682
|
}
|
|
596
683
|
)
|
|
@@ -623,19 +710,19 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
623
710
|
)
|
|
624
711
|
|
|
625
712
|
# An interface's parent must belong to the same device or virtual chassis
|
|
626
|
-
if self.parent_interface.
|
|
627
|
-
if getattr(self.
|
|
713
|
+
if self.parent and self.parent_interface.parent != self.parent:
|
|
714
|
+
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
628
715
|
raise ValidationError(
|
|
629
716
|
{
|
|
630
717
|
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to a different device "
|
|
631
|
-
f"({self.parent_interface.
|
|
718
|
+
f"({self.parent_interface.parent})."
|
|
632
719
|
}
|
|
633
720
|
)
|
|
634
|
-
elif self.parent_interface.
|
|
721
|
+
elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis:
|
|
635
722
|
raise ValidationError(
|
|
636
723
|
{
|
|
637
|
-
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to {self.parent_interface.
|
|
638
|
-
f"is not part of virtual chassis {self.
|
|
724
|
+
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs to {self.parent_interface.parent}, which "
|
|
725
|
+
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
639
726
|
}
|
|
640
727
|
)
|
|
641
728
|
|
|
@@ -645,7 +732,8 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
645
732
|
if (
|
|
646
733
|
self.untagged_vlan
|
|
647
734
|
and self.untagged_vlan.locations.exists()
|
|
648
|
-
and
|
|
735
|
+
and self.parent
|
|
736
|
+
and not self.untagged_vlan.locations.filter(id=self.parent.location_id).exists()
|
|
649
737
|
):
|
|
650
738
|
raise ValidationError(
|
|
651
739
|
{
|
|
@@ -663,22 +751,22 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
663
751
|
raise ValidationError({"bridge": "An interface cannot be bridged to itself."})
|
|
664
752
|
|
|
665
753
|
# A bridged interface belong to the same device or virtual chassis
|
|
666
|
-
if self.bridge.
|
|
667
|
-
if getattr(self.
|
|
754
|
+
if self.parent and self.bridge.parent != self.parent:
|
|
755
|
+
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
668
756
|
raise ValidationError(
|
|
669
757
|
{
|
|
670
758
|
"bridge": (
|
|
671
759
|
f"The selected bridge interface ({self.bridge}) belongs to a different device "
|
|
672
|
-
f"({self.bridge.
|
|
760
|
+
f"({self.bridge.parent})."
|
|
673
761
|
)
|
|
674
762
|
}
|
|
675
763
|
)
|
|
676
|
-
elif self.bridge.
|
|
764
|
+
elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
|
|
677
765
|
raise ValidationError(
|
|
678
766
|
{
|
|
679
767
|
"bridge": (
|
|
680
|
-
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.
|
|
681
|
-
f"is not part of virtual chassis {self.
|
|
768
|
+
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which "
|
|
769
|
+
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
682
770
|
)
|
|
683
771
|
}
|
|
684
772
|
)
|
|
@@ -766,10 +854,6 @@ class Interface(CableTermination, PathEndpoint, ComponentModel, BaseInterface):
|
|
|
766
854
|
def ip_address_count(self):
|
|
767
855
|
return self.ip_addresses.count()
|
|
768
856
|
|
|
769
|
-
@property
|
|
770
|
-
def parent(self):
|
|
771
|
-
return self.device
|
|
772
|
-
|
|
773
857
|
|
|
774
858
|
@extras_features(
|
|
775
859
|
"custom_fields",
|
|
@@ -879,6 +963,7 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
879
963
|
related_name="interface_redundancy_group_associations",
|
|
880
964
|
)
|
|
881
965
|
priority = models.PositiveSmallIntegerField()
|
|
966
|
+
is_metadata_associable_model = False
|
|
882
967
|
|
|
883
968
|
class Meta:
|
|
884
969
|
"""Meta class."""
|
|
@@ -888,7 +973,7 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
888
973
|
|
|
889
974
|
def __str__(self):
|
|
890
975
|
"""Return a string representation of the instance."""
|
|
891
|
-
return f"{self.interface_redundancy_group}: {self.interface.device} {self.interface}: {self.priority}"
|
|
976
|
+
return f"{self.interface_redundancy_group}: {self.interface.device or self.interface.module} {self.interface}: {self.priority}"
|
|
892
977
|
|
|
893
978
|
|
|
894
979
|
#
|
|
@@ -897,9 +982,9 @@ class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
|
897
982
|
|
|
898
983
|
|
|
899
984
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
900
|
-
class FrontPort(
|
|
985
|
+
class FrontPort(ModularComponentModel, CableTermination):
|
|
901
986
|
"""
|
|
902
|
-
A pass-through port on the front of a Device.
|
|
987
|
+
A pass-through port on the front of a Device or Module.
|
|
903
988
|
"""
|
|
904
989
|
|
|
905
990
|
type = models.CharField(max_length=50, choices=PortTypeChoices)
|
|
@@ -912,22 +997,22 @@ class FrontPort(CableTermination, ComponentModel):
|
|
|
912
997
|
],
|
|
913
998
|
)
|
|
914
999
|
|
|
915
|
-
|
|
916
|
-
ordering = ("device", "_name")
|
|
917
|
-
unique_together = (
|
|
918
|
-
("device", "name"),
|
|
919
|
-
("rear_port", "rear_port_position"),
|
|
920
|
-
)
|
|
1000
|
+
natural_key_field_names = ["device", "module", "name", "rear_port", "rear_port_position"]
|
|
921
1001
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1002
|
+
class Meta(ModularComponentModel.Meta):
|
|
1003
|
+
constraints = [
|
|
1004
|
+
*ModularComponentModel.Meta.constraints,
|
|
1005
|
+
models.UniqueConstraint(
|
|
1006
|
+
fields=("rear_port", "rear_port_position"),
|
|
1007
|
+
name="dcim_frontport_rear_port_position_unique",
|
|
1008
|
+
),
|
|
1009
|
+
]
|
|
925
1010
|
|
|
926
1011
|
def clean(self):
|
|
927
1012
|
super().clean()
|
|
928
1013
|
|
|
929
1014
|
# Validate rear port assignment
|
|
930
|
-
if self.rear_port.
|
|
1015
|
+
if self.parent and self.rear_port.parent != self.parent:
|
|
931
1016
|
raise ValidationError({"rear_port": f"Rear port ({self.rear_port}) must belong to the same device"})
|
|
932
1017
|
|
|
933
1018
|
# Validate rear port position assignment
|
|
@@ -941,9 +1026,9 @@ class FrontPort(CableTermination, ComponentModel):
|
|
|
941
1026
|
|
|
942
1027
|
|
|
943
1028
|
@extras_features("cable_terminations", "custom_links", "custom_validators", "graphql", "webhooks")
|
|
944
|
-
class RearPort(
|
|
1029
|
+
class RearPort(ModularComponentModel, CableTermination):
|
|
945
1030
|
"""
|
|
946
|
-
A pass-through port on the rear of a Device.
|
|
1031
|
+
A pass-through port on the rear of a Device or Module.
|
|
947
1032
|
"""
|
|
948
1033
|
|
|
949
1034
|
type = models.CharField(max_length=50, choices=PortTypeChoices)
|
|
@@ -955,10 +1040,6 @@ class RearPort(CableTermination, ComponentModel):
|
|
|
955
1040
|
],
|
|
956
1041
|
)
|
|
957
1042
|
|
|
958
|
-
class Meta:
|
|
959
|
-
ordering = ("device", "_name")
|
|
960
|
-
unique_together = ("device", "name")
|
|
961
|
-
|
|
962
1043
|
def clean(self):
|
|
963
1044
|
super().clean()
|
|
964
1045
|
|
|
@@ -972,10 +1053,6 @@ class RearPort(CableTermination, ComponentModel):
|
|
|
972
1053
|
}
|
|
973
1054
|
)
|
|
974
1055
|
|
|
975
|
-
@property
|
|
976
|
-
def parent(self):
|
|
977
|
-
return self.device
|
|
978
|
-
|
|
979
1056
|
|
|
980
1057
|
#
|
|
981
1058
|
# Device bays
|
|
@@ -1027,10 +1104,6 @@ class DeviceBay(ComponentModel):
|
|
|
1027
1104
|
}
|
|
1028
1105
|
)
|
|
1029
1106
|
|
|
1030
|
-
@property
|
|
1031
|
-
def parent(self):
|
|
1032
|
-
return self.device
|
|
1033
|
-
|
|
1034
1107
|
|
|
1035
1108
|
#
|
|
1036
1109
|
# Inventory items
|
|
@@ -1079,7 +1152,8 @@ class InventoryItem(TreeModel, ComponentModel):
|
|
|
1079
1152
|
related_name="inventory_items",
|
|
1080
1153
|
blank=True,
|
|
1081
1154
|
null=True,
|
|
1082
|
-
verbose_name="
|
|
1155
|
+
verbose_name="Software Version",
|
|
1156
|
+
help_text="The software version installed on this inventory item",
|
|
1083
1157
|
)
|
|
1084
1158
|
software_image_files = models.ManyToManyField(
|
|
1085
1159
|
to="dcim.SoftwareImageFile",
|
|
@@ -1101,3 +1175,105 @@ class InventoryItem(TreeModel, ComponentModel):
|
|
|
1101
1175
|
For the time being we just use the PK as a natural key.
|
|
1102
1176
|
"""
|
|
1103
1177
|
return ["pk"]
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
@extras_features(
|
|
1181
|
+
"custom_links",
|
|
1182
|
+
"custom_validators",
|
|
1183
|
+
"export_templates",
|
|
1184
|
+
"graphql",
|
|
1185
|
+
"webhooks",
|
|
1186
|
+
)
|
|
1187
|
+
class ModuleBay(PrimaryModel):
|
|
1188
|
+
"""
|
|
1189
|
+
A slot in a Device or Module which can contain Modules.
|
|
1190
|
+
"""
|
|
1191
|
+
|
|
1192
|
+
parent_device = models.ForeignKey(
|
|
1193
|
+
to="dcim.Device",
|
|
1194
|
+
on_delete=models.CASCADE,
|
|
1195
|
+
related_name="module_bays",
|
|
1196
|
+
blank=True,
|
|
1197
|
+
null=True,
|
|
1198
|
+
)
|
|
1199
|
+
parent_module = models.ForeignKey(
|
|
1200
|
+
to="dcim.Module",
|
|
1201
|
+
on_delete=models.CASCADE,
|
|
1202
|
+
related_name="module_bays",
|
|
1203
|
+
blank=True,
|
|
1204
|
+
null=True,
|
|
1205
|
+
)
|
|
1206
|
+
name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, db_index=True)
|
|
1207
|
+
_name = NaturalOrderingField(target_field="name", max_length=CHARFIELD_MAX_LENGTH, blank=True, db_index=True)
|
|
1208
|
+
position = models.CharField(
|
|
1209
|
+
blank=True,
|
|
1210
|
+
max_length=CHARFIELD_MAX_LENGTH,
|
|
1211
|
+
help_text="The position of the module bay within the parent device/module",
|
|
1212
|
+
)
|
|
1213
|
+
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
1214
|
+
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
1215
|
+
|
|
1216
|
+
clone_fields = ["parent_device", "parent_module"]
|
|
1217
|
+
|
|
1218
|
+
# The recursive nature of this model combined with the fact that it can be a child of a
|
|
1219
|
+
# device or location makes our natural key implementation unusable, so just use the pk
|
|
1220
|
+
natural_key_field_names = ["pk"]
|
|
1221
|
+
|
|
1222
|
+
class Meta:
|
|
1223
|
+
# TODO: Ordering by parent_module.id is not correct but prevents an infinite loop
|
|
1224
|
+
ordering = (
|
|
1225
|
+
"parent_device",
|
|
1226
|
+
"parent_module__id",
|
|
1227
|
+
"_name",
|
|
1228
|
+
)
|
|
1229
|
+
constraints = [
|
|
1230
|
+
models.UniqueConstraint(
|
|
1231
|
+
fields=["parent_device", "name"],
|
|
1232
|
+
name="dcim_modulebay_parent_device_name_unique",
|
|
1233
|
+
),
|
|
1234
|
+
models.UniqueConstraint(
|
|
1235
|
+
fields=["parent_module", "name"],
|
|
1236
|
+
name="dcim_modulebay_parent_module_name_unique",
|
|
1237
|
+
),
|
|
1238
|
+
]
|
|
1239
|
+
|
|
1240
|
+
@property
|
|
1241
|
+
def parent(self):
|
|
1242
|
+
"""Walk up parent chain to find the Device that this ModuleBay is installed in, if one exists."""
|
|
1243
|
+
return self.parent_module.device if self.parent_module else self.parent_device
|
|
1244
|
+
|
|
1245
|
+
def __str__(self):
|
|
1246
|
+
if self.parent_device is not None:
|
|
1247
|
+
return f"{self.parent_device} ({self.name})"
|
|
1248
|
+
else:
|
|
1249
|
+
return f"{self.parent_module} ({self.name})"
|
|
1250
|
+
|
|
1251
|
+
@property
|
|
1252
|
+
def display(self):
|
|
1253
|
+
if self.parent_device is not None:
|
|
1254
|
+
return f"{self.parent_device.display} ({self.name})"
|
|
1255
|
+
else:
|
|
1256
|
+
return f"{self.parent_module.display} ({self.name})"
|
|
1257
|
+
|
|
1258
|
+
def to_objectchange(self, action, **kwargs):
|
|
1259
|
+
"""
|
|
1260
|
+
Return a new ObjectChange with the `related_object` pinned to the parent `device` or `module`.
|
|
1261
|
+
"""
|
|
1262
|
+
# Annotate the parent
|
|
1263
|
+
try:
|
|
1264
|
+
parent = self.parent
|
|
1265
|
+
except ObjectDoesNotExist:
|
|
1266
|
+
# The parent has already been deleted
|
|
1267
|
+
parent = None
|
|
1268
|
+
|
|
1269
|
+
return super().to_objectchange(action, related_object=parent, **kwargs)
|
|
1270
|
+
|
|
1271
|
+
def clean(self):
|
|
1272
|
+
super().clean()
|
|
1273
|
+
|
|
1274
|
+
# Validate that a Device or Module is set, but not both
|
|
1275
|
+
if self.parent_device and self.parent_module:
|
|
1276
|
+
raise ValidationError("Only one of parent_device or parent_module must be set")
|
|
1277
|
+
|
|
1278
|
+
if not (self.parent_device or self.parent_module):
|
|
1279
|
+
raise ValidationError("Either parent_device or parent_module must be set")
|