nautobot 2.4.0b1__py3-none-any.whl → 2.4.2__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/__init__.py +1 -1
- nautobot/apps/api.py +8 -8
- nautobot/apps/change_logging.py +2 -2
- nautobot/apps/choices.py +4 -4
- nautobot/apps/events.py +3 -3
- nautobot/apps/factory.py +2 -2
- nautobot/apps/filters.py +1 -1
- nautobot/apps/forms.py +20 -20
- nautobot/apps/graphql.py +2 -2
- nautobot/apps/jobs.py +8 -8
- nautobot/apps/models.py +19 -19
- nautobot/apps/tables.py +1 -1
- nautobot/apps/testing.py +10 -10
- nautobot/apps/ui.py +2 -2
- nautobot/apps/utils.py +7 -7
- nautobot/apps/views.py +7 -7
- nautobot/circuits/api/serializers.py +1 -0
- nautobot/circuits/api/views.py +4 -8
- nautobot/circuits/tables.py +2 -1
- nautobot/circuits/templates/circuits/circuit_create.html +1 -7
- nautobot/circuits/tests/integration/test_circuits_bulk_operations.py +43 -0
- nautobot/circuits/tests/integration/test_relationships.py +1 -1
- nautobot/circuits/views.py +3 -3
- nautobot/cloud/api/views.py +6 -10
- nautobot/cloud/models.py +1 -1
- nautobot/cloud/views.py +0 -16
- nautobot/core/api/constants.py +11 -0
- nautobot/core/api/fields.py +5 -5
- nautobot/core/api/filter_backends.py +3 -9
- nautobot/core/api/schema.py +13 -2
- nautobot/core/api/serializers.py +40 -34
- nautobot/core/api/views.py +56 -4
- nautobot/core/apps/__init__.py +0 -5
- nautobot/core/celery/log.py +4 -4
- nautobot/core/celery/schedulers.py +2 -2
- nautobot/core/choices.py +2 -2
- nautobot/core/events/__init__.py +3 -3
- nautobot/core/filters.py +67 -35
- nautobot/core/forms/__init__.py +19 -19
- nautobot/core/forms/fields.py +14 -11
- nautobot/core/forms/forms.py +33 -2
- nautobot/core/graphql/types.py +1 -1
- nautobot/core/jobs/__init__.py +28 -7
- nautobot/core/jobs/bulk_actions.py +285 -0
- nautobot/core/jobs/cleanup.py +48 -12
- nautobot/core/jobs/groups.py +1 -1
- nautobot/core/management/commands/validate_models.py +1 -1
- nautobot/core/models/__init__.py +3 -1
- nautobot/core/models/query_functions.py +2 -2
- nautobot/core/models/tree_queries.py +6 -3
- nautobot/core/settings.py +29 -2
- nautobot/core/settings.yaml +21 -0
- nautobot/core/tables.py +79 -61
- nautobot/core/templates/about.html +67 -0
- nautobot/core/templates/generic/object_bulk_destroy.html +1 -1
- nautobot/core/templates/inc/media.html +3 -0
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
- nautobot/core/templates/inc/tenant_table_row.html +11 -0
- nautobot/core/templates/nautobot_config.py.j2 +13 -0
- nautobot/core/templates/search.html +7 -0
- nautobot/core/templates/utilities/render_jinja2.html +1 -1
- nautobot/core/templates/utilities/templatetags/tag.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +7 -0
- nautobot/core/templatetags/helpers.py +11 -2
- nautobot/core/testing/__init__.py +8 -8
- nautobot/core/testing/api.py +170 -15
- nautobot/core/testing/filters.py +45 -10
- nautobot/core/testing/forms.py +2 -0
- nautobot/core/testing/integration.py +514 -5
- nautobot/core/testing/mixins.py +7 -2
- nautobot/core/testing/views.py +44 -29
- nautobot/core/tests/integration/test_app_home.py +0 -1
- nautobot/core/tests/integration/test_app_navbar.py +0 -1
- nautobot/core/tests/integration/test_filters.py +0 -2
- nautobot/core/tests/integration/test_home.py +0 -1
- nautobot/core/tests/integration/test_navbar.py +0 -1
- nautobot/core/tests/integration/test_view_authentication.py +1 -0
- nautobot/core/tests/runner.py +1 -1
- nautobot/core/tests/test_api.py +98 -1
- nautobot/core/tests/test_csv.py +25 -3
- nautobot/core/tests/test_filters.py +209 -246
- nautobot/core/tests/test_forms.py +1 -0
- nautobot/core/tests/test_jobs.py +492 -1
- nautobot/core/tests/test_models.py +9 -0
- nautobot/core/tests/test_settings_schema.py +7 -0
- nautobot/core/tests/test_tables.py +100 -0
- nautobot/core/tests/test_utils.py +63 -1
- nautobot/core/tests/test_views.py +30 -3
- nautobot/core/ui/nav.py +1 -0
- nautobot/core/ui/object_detail.py +15 -1
- nautobot/core/urls.py +11 -0
- nautobot/core/utils/git.py +7 -2
- nautobot/core/utils/lookup.py +11 -8
- nautobot/core/utils/querysets.py +64 -0
- nautobot/core/utils/requests.py +24 -9
- nautobot/core/views/__init__.py +42 -0
- nautobot/core/views/generic.py +131 -197
- nautobot/core/views/mixins.py +136 -41
- nautobot/core/views/renderers.py +6 -6
- nautobot/core/views/utils.py +2 -2
- nautobot/dcim/api/serializers.py +56 -64
- nautobot/dcim/api/views.py +47 -113
- nautobot/dcim/constants.py +6 -13
- nautobot/dcim/factory.py +6 -1
- nautobot/dcim/filters/__init__.py +31 -2
- nautobot/dcim/forms.py +48 -17
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
- nautobot/dcim/models/__init__.py +1 -1
- nautobot/dcim/models/device_component_templates.py +2 -2
- nautobot/dcim/models/device_components.py +22 -20
- nautobot/dcim/models/devices.py +10 -1
- nautobot/dcim/models/locations.py +3 -3
- nautobot/dcim/models/power.py +6 -5
- nautobot/dcim/models/racks.py +4 -4
- nautobot/dcim/tables/__init__.py +3 -3
- nautobot/dcim/tables/devices.py +9 -6
- nautobot/dcim/tables/devicetypes.py +2 -2
- nautobot/dcim/tables/racks.py +1 -1
- nautobot/dcim/templates/dcim/cable.html +1 -1
- nautobot/dcim/templates/dcim/controller_create.html +1 -7
- nautobot/dcim/templates/dcim/controller_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +2 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +5 -0
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device.html +3 -11
- nautobot/dcim/templates/dcim/device_component.html +1 -1
- nautobot/dcim/templates/dcim/device_edit.html +36 -37
- nautobot/dcim/templates/dcim/devicetype.html +1 -1
- nautobot/dcim/templates/dcim/location.html +2 -10
- nautobot/dcim/templates/dcim/location_edit.html +1 -7
- nautobot/dcim/templates/dcim/locationtype.html +1 -1
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/manufacturer.html +1 -1
- nautobot/dcim/templates/dcim/platform.html +1 -1
- nautobot/dcim/templates/dcim/powerfeed.html +1 -1
- nautobot/dcim/templates/dcim/powerpanel.html +1 -1
- nautobot/dcim/templates/dcim/rack.html +2 -10
- nautobot/dcim/templates/dcim/rack_edit.html +1 -7
- nautobot/dcim/templates/dcim/rackgroup.html +1 -1
- nautobot/dcim/templates/dcim/rackreservation.html +3 -11
- nautobot/dcim/templates/dcim/virtualchassis.html +1 -1
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -9
- nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +1 -7
- nautobot/dcim/tests/integration/test_controller.py +62 -0
- nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +30 -0
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +43 -0
- nautobot/dcim/tests/test_api.py +16 -5
- nautobot/dcim/tests/test_filters.py +33 -0
- nautobot/dcim/tests/test_forms.py +51 -2
- nautobot/dcim/tests/test_graphql.py +52 -0
- nautobot/dcim/tests/test_jobs.py +118 -0
- nautobot/dcim/tests/test_models.py +52 -9
- nautobot/dcim/tests/test_views.py +30 -84
- nautobot/dcim/views.py +13 -28
- nautobot/extras/api/customfields.py +2 -2
- nautobot/extras/api/serializers.py +123 -85
- nautobot/extras/api/views.py +33 -30
- nautobot/extras/constants.py +3 -0
- nautobot/extras/datasources/git.py +125 -0
- nautobot/extras/filters/__init__.py +8 -6
- nautobot/extras/forms/base.py +2 -2
- nautobot/extras/forms/forms.py +139 -31
- nautobot/extras/forms/mixins.py +14 -6
- nautobot/extras/group_sync.py +3 -3
- nautobot/extras/health_checks.py +1 -2
- nautobot/extras/jobs.py +85 -18
- nautobot/extras/managers.py +3 -1
- nautobot/extras/migrations/0018_joblog_data_migration.py +7 -9
- nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
- nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
- nautobot/extras/migrations/0122_add_graphqlquery_owner_content_type.py +34 -0
- nautobot/extras/models/__init__.py +1 -1
- nautobot/extras/models/contacts.py +1 -1
- nautobot/extras/models/customfields.py +41 -23
- nautobot/extras/models/datasources.py +85 -0
- nautobot/extras/models/groups.py +11 -9
- nautobot/extras/models/jobs.py +23 -4
- nautobot/extras/models/models.py +17 -2
- nautobot/extras/models/relationships.py +17 -5
- nautobot/extras/plugins/__init__.py +13 -2
- nautobot/extras/plugins/marketplace_manifest.yml +84 -79
- nautobot/extras/plugins/tables.py +16 -14
- nautobot/extras/plugins/views.py +65 -69
- nautobot/extras/registry.py +1 -1
- nautobot/extras/secrets/__init__.py +2 -2
- nautobot/extras/signals.py +15 -1
- nautobot/extras/tables.py +7 -5
- nautobot/extras/templates/extras/computedfield.html +1 -1
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +1 -1
- nautobot/extras/templates/extras/customfield.html +1 -1
- nautobot/extras/templates/extras/customlink.html +1 -1
- nautobot/extras/templates/extras/dynamicgroup.html +2 -10
- nautobot/extras/templates/extras/exporttemplate.html +1 -1
- nautobot/extras/templates/extras/gitrepository.html +1 -1
- nautobot/extras/templates/extras/graphqlquery.html +1 -1
- nautobot/extras/templates/extras/job_detail.html +17 -1
- nautobot/extras/templates/extras/job_edit.html +1 -0
- nautobot/extras/templates/extras/jobbutton_retrieve.html +1 -1
- nautobot/extras/templates/extras/jobhook.html +1 -1
- nautobot/extras/templates/extras/jobqueue_retrieve.html +1 -9
- nautobot/extras/templates/extras/jobresult.html +1 -1
- nautobot/extras/templates/extras/marketplace.html +29 -11
- nautobot/extras/templates/extras/objectchange.html +1 -1
- nautobot/extras/templates/extras/plugin_detail.html +33 -16
- nautobot/extras/templates/extras/plugins_tiles.html +21 -10
- nautobot/extras/templates/extras/relationship.html +1 -63
- nautobot/extras/templates/extras/role_retrieve.html +1 -1
- nautobot/extras/templates/extras/scheduledjob.html +1 -1
- nautobot/extras/templates/extras/secret.html +1 -1
- nautobot/extras/templates/extras/secretsgroup.html +1 -1
- nautobot/extras/templates/extras/status.html +1 -1
- nautobot/extras/templates/extras/tag.html +1 -1
- nautobot/extras/templates/extras/webhook.html +1 -1
- nautobot/extras/templatetags/job_buttons.py +4 -4
- nautobot/extras/test_jobs/api_test_job.py +1 -1
- nautobot/extras/test_jobs/atomic_transaction.py +2 -2
- nautobot/extras/test_jobs/dry_run.py +1 -1
- nautobot/extras/test_jobs/fail.py +5 -5
- nautobot/extras/test_jobs/file_output.py +1 -1
- nautobot/extras/test_jobs/file_upload_fail.py +1 -1
- nautobot/extras/test_jobs/file_upload_pass.py +1 -1
- nautobot/extras/test_jobs/ipaddress_vars.py +3 -1
- nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
- nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
- nautobot/extras/test_jobs/log_redaction.py +1 -1
- nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
- nautobot/extras/test_jobs/modify_db.py +1 -1
- nautobot/extras/test_jobs/object_var_optional.py +1 -1
- nautobot/extras/test_jobs/object_var_required.py +1 -1
- nautobot/extras/test_jobs/object_vars.py +1 -1
- nautobot/extras/test_jobs/pass.py +3 -3
- nautobot/extras/test_jobs/profiling.py +1 -1
- nautobot/extras/test_jobs/relative_import.py +3 -3
- nautobot/extras/test_jobs/singleton.py +16 -0
- nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
- nautobot/extras/test_jobs/task_queues.py +1 -1
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_interfaces.gql +8 -0
- nautobot/extras/tests/git_data/01-valid-files/graphql_queries/device_names.gql +5 -0
- nautobot/extras/tests/git_data/02-invalid-files/graphql_queries/bad_device_names.gql +5 -0
- nautobot/extras/tests/git_helper.py +9 -1
- nautobot/extras/tests/integration/__init__.py +29 -16
- nautobot/extras/tests/integration/test_plugin_banner.py +0 -2
- nautobot/extras/tests/test_api.py +19 -13
- nautobot/extras/tests/test_customfields.py +50 -52
- nautobot/extras/tests/test_datasources.py +29 -1
- nautobot/extras/tests/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/test_filters.py +6 -6
- nautobot/extras/tests/test_forms.py +33 -1
- nautobot/extras/tests/test_jobs.py +178 -32
- nautobot/extras/tests/test_models.py +299 -10
- nautobot/extras/tests/test_plugins.py +62 -9
- nautobot/extras/tests/test_relationships.py +120 -9
- nautobot/extras/tests/test_utils.py +22 -1
- nautobot/extras/tests/test_views.py +56 -194
- nautobot/extras/utils.py +20 -10
- nautobot/extras/views.py +85 -110
- nautobot/ipam/api/fields.py +3 -3
- nautobot/ipam/api/serializers.py +41 -33
- nautobot/ipam/api/views.py +68 -117
- nautobot/ipam/factory.py +1 -1
- nautobot/ipam/filters.py +3 -2
- nautobot/ipam/lookups.py +101 -62
- nautobot/ipam/models.py +74 -18
- nautobot/ipam/querysets.py +2 -2
- nautobot/ipam/tables.py +25 -9
- nautobot/ipam/templates/ipam/ipaddress.html +2 -10
- nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
- nautobot/ipam/templates/ipam/prefix.html +2 -10
- nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
- nautobot/ipam/templates/ipam/rir.html +1 -1
- nautobot/ipam/templates/ipam/routetarget.html +1 -1
- nautobot/ipam/templates/ipam/service.html +1 -1
- nautobot/ipam/templates/ipam/vlan.html +2 -10
- nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
- nautobot/ipam/templates/ipam/vlangroup.html +1 -1
- nautobot/ipam/templates/ipam/vrf.html +1 -1
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
- nautobot/ipam/tests/test_api.py +436 -3
- nautobot/ipam/tests/test_forms.py +49 -47
- nautobot/ipam/tests/test_migrations.py +30 -30
- nautobot/ipam/tests/test_models.py +119 -34
- nautobot/ipam/tests/test_querysets.py +63 -1
- nautobot/ipam/tests/test_utils.py +41 -2
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/utils/__init__.py +54 -17
- nautobot/ipam/views.py +61 -87
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
- nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
- nautobot/project-static/docs/404.html +131 -14
- nautobot/project-static/docs/apps/index.html +131 -14
- nautobot/project-static/docs/apps/nautobot-apps.html +132 -16
- nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js → bundle.60a45f97.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.83f73b43.min.js.map → bundle.60a45f97.min.js.map} +2 -2
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js → search.f8cc74c7.min.js} +1 -1
- nautobot/project-static/docs/assets/javascripts/workers/{search.6ce7567c.min.js.map → search.f8cc74c7.min.js.map} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css → main.a40c8224.min.css} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +147 -20
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +144 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +459 -132
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +175 -28
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +180 -31
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +138 -16
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +137 -15
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +164 -27
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +187 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +193 -31
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +216 -48
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +324 -75
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +666 -175
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +194 -46
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +538 -177
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +578 -221
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +145 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +156 -25
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +492 -65
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +705 -215
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +943 -422
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +144 -17
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +619 -200
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +474 -159
- nautobot/project-static/docs/development/apps/api/configuration-view.html +131 -14
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/global-search.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/graphql.html +131 -14
- nautobot/project-static/docs/development/apps/api/models/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +131 -14
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +153 -17
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +131 -14
- nautobot/project-static/docs/development/apps/api/prometheus.html +131 -14
- nautobot/project-static/docs/development/apps/api/setup.html +131 -14
- nautobot/project-static/docs/development/apps/api/testing.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +131 -14
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/base-template.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/index.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/notes.html +131 -14
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +137 -16
- nautobot/project-static/docs/development/apps/api/views/urls.html +131 -14
- nautobot/project-static/docs/development/apps/index.html +131 -14
- nautobot/project-static/docs/development/apps/migration/code-updates.html +131 -14
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +131 -14
- nautobot/project-static/docs/development/apps/migration/from-v1.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +131 -14
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +131 -14
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +135 -18
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +131 -14
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +297 -25
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +131 -14
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +131 -14
- nautobot/project-static/docs/development/core/application-registry.html +131 -14
- nautobot/project-static/docs/development/core/best-practices.html +131 -14
- nautobot/project-static/docs/development/core/bootstrap-ui.html +131 -14
- nautobot/project-static/docs/development/core/caching.html +131 -14
- nautobot/project-static/docs/development/core/controllers.html +131 -14
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +158 -84
- nautobot/project-static/docs/development/core/generic-views.html +131 -14
- nautobot/project-static/docs/development/core/getting-started.html +334 -234
- nautobot/project-static/docs/development/core/homepage.html +134 -17
- nautobot/project-static/docs/development/core/index.html +131 -14
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9829 -0
- nautobot/project-static/docs/development/core/model-checklist.html +141 -22
- nautobot/project-static/docs/development/core/model-features.html +131 -14
- nautobot/project-static/docs/development/core/natural-keys.html +131 -14
- nautobot/project-static/docs/development/core/navigation-menu.html +131 -14
- nautobot/project-static/docs/development/core/release-checklist.html +134 -17
- nautobot/project-static/docs/development/core/role-internals.html +131 -14
- nautobot/project-static/docs/development/core/settings.html +131 -14
- nautobot/project-static/docs/development/core/style-guide.html +134 -17
- nautobot/project-static/docs/development/core/templates.html +132 -15
- nautobot/project-static/docs/development/core/testing.html +131 -14
- nautobot/project-static/docs/development/core/ui-component-framework.html +454 -283
- nautobot/project-static/docs/development/core/user-preferences.html +131 -14
- nautobot/project-static/docs/development/index.html +131 -14
- nautobot/project-static/docs/development/jobs/index.html +301 -132
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +131 -14
- nautobot/project-static/docs/index.html +139 -33
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
- nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
- nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +132 -17
- nautobot/project-static/docs/overview/design_philosophy.html +131 -14
- nautobot/project-static/docs/release-notes/index.html +137 -22
- nautobot/project-static/docs/release-notes/version-1.0.html +319 -203
- nautobot/project-static/docs/release-notes/version-1.1.html +316 -200
- nautobot/project-static/docs/release-notes/version-1.2.html +391 -275
- nautobot/project-static/docs/release-notes/version-1.3.html +417 -301
- nautobot/project-static/docs/release-notes/version-1.4.html +502 -387
- nautobot/project-static/docs/release-notes/version-1.5.html +690 -576
- nautobot/project-static/docs/release-notes/version-1.6.html +989 -457
- nautobot/project-static/docs/release-notes/version-2.0.html +613 -499
- nautobot/project-static/docs/release-notes/version-2.1.html +448 -334
- nautobot/project-static/docs/release-notes/version-2.2.html +441 -327
- nautobot/project-static/docs/release-notes/version-2.3.html +1171 -451
- nautobot/project-static/docs/release-notes/version-2.4.html +800 -111
- nautobot/project-static/docs/requirements.txt +2 -2
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -287
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +133 -16
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +131 -14
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +195 -18
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +134 -17
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +131 -14
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +133 -16
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +151 -18
- nautobot/project-static/docs/user-guide/administration/installation/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +132 -15
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +131 -14
- nautobot/project-static/docs/user-guide/administration/installation/services.html +131 -14
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +131 -14
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +131 -14
- nautobot/project-static/docs/user-guide/administration/security/index.html +9420 -0
- nautobot/project-static/docs/user-guide/administration/security/notices.html +9843 -0
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +131 -14
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +134 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +131 -14
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +135 -22
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +134 -17
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +131 -14
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +134 -17
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +236 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +131 -14
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +134 -17
- nautobot/project-static/docs/{development/core/local-k8s.html → user-guide/feature-guides/wireless-networks-and-controllers.html} +632 -566
- nautobot/project-static/docs/user-guide/index.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +135 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +451 -16
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +135 -17
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +134 -17
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9797 -0
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +132 -15
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +179 -35
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +159 -15
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +131 -14
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +131 -14
- nautobot/project-static/js/forms.js +1 -1
- nautobot/tenancy/api/views.py +9 -13
- nautobot/tenancy/templates/tenancy/tenant.html +1 -2
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/views.py +4 -2
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +5 -4
- nautobot/users/api/views.py +3 -3
- nautobot/virtualization/api/serializers.py +4 -4
- nautobot/virtualization/api/views.py +5 -24
- nautobot/virtualization/filters.py +20 -3
- nautobot/virtualization/models.py +1 -1
- nautobot/virtualization/tables.py +2 -2
- nautobot/virtualization/templates/virtualization/cluster.html +1 -1
- nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
- nautobot/virtualization/templates/virtualization/clustergroup.html +1 -1
- nautobot/virtualization/templates/virtualization/clustertype.html +1 -1
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -10
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
- nautobot/virtualization/templates/virtualization/vminterface.html +1 -1
- nautobot/virtualization/tests/test_filters.py +17 -0
- nautobot/wireless/filters.py +2 -2
- nautobot/wireless/forms.py +1 -1
- nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +1 -9
- nautobot/wireless/tests/integration/__init__.py +0 -0
- nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
- nautobot/wireless/tests/test_filters.py +29 -1
- nautobot/wireless/tests/test_views.py +22 -1
- nautobot/wireless/views.py +0 -10
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/METADATA +9 -9
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/RECORD +667 -610
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/WHEEL +1 -1
- nautobot/core/fixtures/user-data.json +0 -59
- /nautobot/project-static/docs/assets/stylesheets/{main.6f8fc17f.min.css.map → main.a40c8224.min.css.map} +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/NOTICE +0 -0
- {nautobot-2.4.0b1.dist-info → nautobot-2.4.2.dist-info}/entry_points.txt +0 -0
nautobot/dcim/constants.py
CHANGED
|
@@ -27,19 +27,12 @@ REARPORT_POSITIONS_MAX = 1024
|
|
|
27
27
|
INTERFACE_MTU_MIN = 1
|
|
28
28
|
INTERFACE_MTU_MAX = 32767 # Max value of a signed 16-bit integer
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
WIRELESS_IFACE_TYPES = [
|
|
37
|
-
InterfaceTypeChoices.TYPE_80211A,
|
|
38
|
-
InterfaceTypeChoices.TYPE_80211G,
|
|
39
|
-
InterfaceTypeChoices.TYPE_80211N,
|
|
40
|
-
InterfaceTypeChoices.TYPE_80211AC,
|
|
41
|
-
InterfaceTypeChoices.TYPE_80211AD,
|
|
42
|
-
]
|
|
30
|
+
interface_type_by_category = {}
|
|
31
|
+
for category_name, category_item_tuples in InterfaceTypeChoices.CHOICES:
|
|
32
|
+
interface_type_by_category[category_name] = [item_tuple[0] for item_tuple in category_item_tuples]
|
|
33
|
+
|
|
34
|
+
WIRELESS_IFACE_TYPES = interface_type_by_category["Wireless"]
|
|
35
|
+
VIRTUAL_IFACE_TYPES = interface_type_by_category["Virtual interfaces"]
|
|
43
36
|
|
|
44
37
|
NONCONNECTABLE_IFACE_TYPES = VIRTUAL_IFACE_TYPES + WIRELESS_IFACE_TYPES
|
|
45
38
|
|
nautobot/dcim/factory.py
CHANGED
|
@@ -201,7 +201,12 @@ class DeviceFactory(PrimaryModelFactory):
|
|
|
201
201
|
if extracted:
|
|
202
202
|
self.software_image_files.set(extracted)
|
|
203
203
|
else:
|
|
204
|
-
self.software_image_files.set(
|
|
204
|
+
self.software_image_files.set(
|
|
205
|
+
get_random_instances(
|
|
206
|
+
SoftwareImageFile.objects.filter(default_image=True)
|
|
207
|
+
| SoftwareImageFile.objects.filter(device_types=self.device_type)
|
|
208
|
+
)
|
|
209
|
+
)
|
|
205
210
|
|
|
206
211
|
# TODO to be done after these model factories are done.
|
|
207
212
|
# has_cluster = NautobotBoolIterator()
|
|
@@ -128,8 +128,8 @@ __all__ = (
|
|
|
128
128
|
"FrontPortTemplateFilterSet",
|
|
129
129
|
"InterfaceConnectionFilterSet",
|
|
130
130
|
"InterfaceFilterSet",
|
|
131
|
-
"InterfaceRedundancyGroupFilterSet",
|
|
132
131
|
"InterfaceRedundancyGroupAssociationFilterSet",
|
|
132
|
+
"InterfaceRedundancyGroupFilterSet",
|
|
133
133
|
"InterfaceTemplateFilterSet",
|
|
134
134
|
"InventoryItemFilterSet",
|
|
135
135
|
"LocationFilterSet",
|
|
@@ -907,6 +907,12 @@ class DeviceFilterSet(
|
|
|
907
907
|
to_field_name="version",
|
|
908
908
|
label="Software version (version or ID)",
|
|
909
909
|
)
|
|
910
|
+
ip_addresses = MultiValueCharFilter(
|
|
911
|
+
method="filter_ip_addresses",
|
|
912
|
+
label="IP addresses (address or ID)",
|
|
913
|
+
distinct=True,
|
|
914
|
+
)
|
|
915
|
+
has_ip_addresses = RelatedMembershipBooleanFilter(field_name="interfaces__ip_addresses", label="Has IP addresses")
|
|
910
916
|
radio_profiles = NaturalKeyOrPKMultipleChoiceFilter(
|
|
911
917
|
field_name="controller_managed_device_group__radio_profiles",
|
|
912
918
|
queryset=RadioProfile.objects.all(),
|
|
@@ -928,6 +934,13 @@ class DeviceFilterSet(
|
|
|
928
934
|
label="Has wireless networks",
|
|
929
935
|
)
|
|
930
936
|
|
|
937
|
+
def filter_ip_addresses(self, queryset, name, value):
|
|
938
|
+
pk_values = set(item for item in value if is_uuid(item))
|
|
939
|
+
addresses = set(item for item in value if item not in pk_values)
|
|
940
|
+
|
|
941
|
+
ip_queryset = IPAddress.objects.filter_address_or_pk_in(addresses, pk_values)
|
|
942
|
+
return queryset.filter(interfaces__ip_addresses__in=ip_queryset).distinct()
|
|
943
|
+
|
|
931
944
|
class Meta:
|
|
932
945
|
model = Device
|
|
933
946
|
fields = [
|
|
@@ -1154,6 +1167,12 @@ class InterfaceFilterSet(
|
|
|
1154
1167
|
queryset=InterfaceRedundancyGroup.objects.all(),
|
|
1155
1168
|
to_field_name="name",
|
|
1156
1169
|
)
|
|
1170
|
+
ip_addresses = MultiValueCharFilter(
|
|
1171
|
+
method="filter_ip_addresses",
|
|
1172
|
+
label="IP addresses (address or ID)",
|
|
1173
|
+
distinct=True,
|
|
1174
|
+
)
|
|
1175
|
+
has_ip_addresses = RelatedMembershipBooleanFilter(field_name="ip_addresses", label="Has IP addresses")
|
|
1157
1176
|
virtual_device_contexts = NaturalKeyOrPKMultipleChoiceFilter(
|
|
1158
1177
|
queryset=VirtualDeviceContext.objects.all(),
|
|
1159
1178
|
to_field_name="name",
|
|
@@ -1164,6 +1183,13 @@ class InterfaceFilterSet(
|
|
|
1164
1183
|
label="Has Virtual Device Context",
|
|
1165
1184
|
)
|
|
1166
1185
|
|
|
1186
|
+
def filter_ip_addresses(self, queryset, name, value):
|
|
1187
|
+
pk_values = set(item for item in value if is_uuid(item))
|
|
1188
|
+
addresses = set(item for item in value if item not in pk_values)
|
|
1189
|
+
|
|
1190
|
+
ip_queryset = IPAddress.objects.filter_address_or_pk_in(addresses, pk_values)
|
|
1191
|
+
return queryset.filter(ip_addresses__in=ip_queryset).distinct()
|
|
1192
|
+
|
|
1167
1193
|
class Meta:
|
|
1168
1194
|
model = Interface
|
|
1169
1195
|
fields = [
|
|
@@ -1884,7 +1910,10 @@ class ControllerFilterSet(
|
|
|
1884
1910
|
fields = "__all__"
|
|
1885
1911
|
|
|
1886
1912
|
|
|
1887
|
-
class ControllerManagedDeviceGroupFilterSet(
|
|
1913
|
+
class ControllerManagedDeviceGroupFilterSet(
|
|
1914
|
+
NautobotFilterSet,
|
|
1915
|
+
TenancyModelFilterSetMixin,
|
|
1916
|
+
):
|
|
1888
1917
|
"""Filters for ControllerManagedDeviceGroup model."""
|
|
1889
1918
|
|
|
1890
1919
|
q = SearchFilter(
|
nautobot/dcim/forms.py
CHANGED
|
@@ -307,6 +307,17 @@ class LocationTypeFilterForm(NautobotFilterForm):
|
|
|
307
307
|
content_types = MultipleContentTypeField(feature="locations", choices_as_strings=True, required=False)
|
|
308
308
|
|
|
309
309
|
|
|
310
|
+
class LocationTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
311
|
+
pk = forms.ModelMultipleChoiceField(queryset=LocationType.objects.all(), widget=forms.MultipleHiddenInput())
|
|
312
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
313
|
+
nestable = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect)
|
|
314
|
+
add_content_types = MultipleContentTypeField(feature="locations", required=False)
|
|
315
|
+
remove_content_types = MultipleContentTypeField(feature="locations", required=False)
|
|
316
|
+
|
|
317
|
+
class Meta:
|
|
318
|
+
nullable_fields = []
|
|
319
|
+
|
|
320
|
+
|
|
310
321
|
#
|
|
311
322
|
# Locations
|
|
312
323
|
#
|
|
@@ -588,7 +599,7 @@ class RackBulkEditForm(
|
|
|
588
599
|
required=False,
|
|
589
600
|
widget=StaticSelect2(),
|
|
590
601
|
)
|
|
591
|
-
u_height = forms.IntegerField(required=False, label="Height (U)")
|
|
602
|
+
u_height = forms.IntegerField(required=False, label="Height (U)", min_value=1, max_value=100)
|
|
592
603
|
desc_units = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect, label="Descending units")
|
|
593
604
|
outer_width = forms.IntegerField(required=False, min_value=1)
|
|
594
605
|
outer_depth = forms.IntegerField(required=False, min_value=1)
|
|
@@ -784,6 +795,7 @@ class DeviceFamilyForm(NautobotModelForm):
|
|
|
784
795
|
fields = [
|
|
785
796
|
"name",
|
|
786
797
|
"description",
|
|
798
|
+
"tags",
|
|
787
799
|
]
|
|
788
800
|
|
|
789
801
|
|
|
@@ -796,7 +808,7 @@ class DeviceFamilyFilterForm(NautobotFilterForm):
|
|
|
796
808
|
tags = TagFilterField(model)
|
|
797
809
|
|
|
798
810
|
|
|
799
|
-
class DeviceFamilyBulkEditForm(
|
|
811
|
+
class DeviceFamilyBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
800
812
|
pk = forms.ModelMultipleChoiceField(queryset=DeviceFamily.objects.all(), widget=forms.MultipleHiddenInput())
|
|
801
813
|
description = forms.CharField(required=False)
|
|
802
814
|
|
|
@@ -878,7 +890,7 @@ class DeviceTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
|
878
890
|
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
|
879
891
|
device_family = DynamicModelChoiceField(queryset=DeviceFamily.objects.all(), required=False)
|
|
880
892
|
software_image_files = DynamicModelMultipleChoiceField(queryset=SoftwareImageFile.objects.all(), required=False)
|
|
881
|
-
u_height = forms.IntegerField(required=False)
|
|
893
|
+
u_height = forms.IntegerField(required=False, min_value=0)
|
|
882
894
|
is_full_depth = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect(), label="Is full depth")
|
|
883
895
|
comments = CommentField(label="Comments", required=False)
|
|
884
896
|
|
|
@@ -1655,6 +1667,8 @@ class ComponentTemplateImportForm(BootstrapMixin, CustomFieldModelCSVForm):
|
|
|
1655
1667
|
netbox-community/devicetype-library repository.
|
|
1656
1668
|
"""
|
|
1657
1669
|
|
|
1670
|
+
Meta: type # to be defined by concrete subclasses
|
|
1671
|
+
|
|
1658
1672
|
def __init__(self, data=None, *args, **kwargs):
|
|
1659
1673
|
super().__init__(data, *args, **kwargs)
|
|
1660
1674
|
|
|
@@ -2127,6 +2141,8 @@ class DeviceBulkEditForm(
|
|
|
2127
2141
|
rack_group = DynamicModelChoiceField(
|
|
2128
2142
|
queryset=RackGroup.objects.all(), required=False, query_params={"location": "$location"}
|
|
2129
2143
|
)
|
|
2144
|
+
cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False)
|
|
2145
|
+
comments = CommentField(widget=SmallTextarea, label="Comments")
|
|
2130
2146
|
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
2131
2147
|
platform = DynamicModelChoiceField(queryset=Platform.objects.all(), required=False)
|
|
2132
2148
|
serial = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False, label="Serial Number")
|
|
@@ -2150,6 +2166,8 @@ class DeviceBulkEditForm(
|
|
|
2150
2166
|
"position",
|
|
2151
2167
|
"face",
|
|
2152
2168
|
"rack_group",
|
|
2169
|
+
"cluster",
|
|
2170
|
+
"comments",
|
|
2153
2171
|
"secrets_group",
|
|
2154
2172
|
"device_redundancy_group",
|
|
2155
2173
|
"device_redundancy_group_priority",
|
|
@@ -3214,9 +3232,6 @@ class InterfaceBulkEditForm(
|
|
|
3214
3232
|
untagged_vlan = DynamicModelChoiceField(
|
|
3215
3233
|
queryset=VLAN.objects.all(),
|
|
3216
3234
|
required=False,
|
|
3217
|
-
query_params={
|
|
3218
|
-
"locations": "null",
|
|
3219
|
-
},
|
|
3220
3235
|
)
|
|
3221
3236
|
tagged_vlans = DynamicModelMultipleChoiceField(
|
|
3222
3237
|
queryset=VLAN.objects.all(),
|
|
@@ -3266,8 +3281,12 @@ class InterfaceBulkEditForm(
|
|
|
3266
3281
|
# Limit VLAN choices by Location
|
|
3267
3282
|
if locations.count() == 1:
|
|
3268
3283
|
location = locations.first()
|
|
3269
|
-
|
|
3284
|
+
# In the case of a single location, use the available_on_device query param to limit untagged VLAN choices
|
|
3285
|
+
# to those available on the devices in that location and in the ancestors of the location.
|
|
3286
|
+
self.fields["untagged_vlan"].widget.add_query_param("available_on_device", device.pk)
|
|
3270
3287
|
self.fields["tagged_vlans"].widget.add_query_param("locations", location.pk)
|
|
3288
|
+
else:
|
|
3289
|
+
self.fields["tagged_vlans"].widget.add_query_param("locations", "null")
|
|
3271
3290
|
|
|
3272
3291
|
# Restrict parent/bridge/LAG interface assignment by device (or VC master)
|
|
3273
3292
|
if device_count == 1:
|
|
@@ -4982,10 +5001,6 @@ class ControllerForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm):
|
|
|
4982
5001
|
queryset=Platform.objects.all(),
|
|
4983
5002
|
required=False,
|
|
4984
5003
|
)
|
|
4985
|
-
tenant = DynamicModelChoiceField(
|
|
4986
|
-
queryset=Tenant.objects.all(),
|
|
4987
|
-
required=False,
|
|
4988
|
-
)
|
|
4989
5004
|
external_integration = DynamicModelChoiceField(
|
|
4990
5005
|
queryset=ExternalIntegration.objects.all(),
|
|
4991
5006
|
required=False,
|
|
@@ -5007,6 +5022,7 @@ class ControllerForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm):
|
|
|
5007
5022
|
"role",
|
|
5008
5023
|
"description",
|
|
5009
5024
|
"platform",
|
|
5025
|
+
"tenant_group",
|
|
5010
5026
|
"tenant",
|
|
5011
5027
|
"location",
|
|
5012
5028
|
"capabilities",
|
|
@@ -5059,6 +5075,7 @@ class ControllerFilterForm(
|
|
|
5059
5075
|
"description",
|
|
5060
5076
|
"location",
|
|
5061
5077
|
"platform",
|
|
5078
|
+
"tenant_group",
|
|
5062
5079
|
"tenant",
|
|
5063
5080
|
"external_integration",
|
|
5064
5081
|
"controller_device",
|
|
@@ -5085,7 +5102,7 @@ class ControllerBulkEditForm(
|
|
|
5085
5102
|
required=False,
|
|
5086
5103
|
)
|
|
5087
5104
|
capabilities = JSONArrayFormField(
|
|
5088
|
-
choices=
|
|
5105
|
+
choices=ControllerCapabilitiesChoices,
|
|
5089
5106
|
base_field=forms.CharField(),
|
|
5090
5107
|
required=False,
|
|
5091
5108
|
)
|
|
@@ -5114,15 +5131,18 @@ class ControllerBulkEditForm(
|
|
|
5114
5131
|
"description",
|
|
5115
5132
|
"location",
|
|
5116
5133
|
"platform",
|
|
5117
|
-
"tenant",
|
|
5118
5134
|
"external_integration",
|
|
5119
5135
|
"controller_device",
|
|
5120
5136
|
"controller_device_redundancy_group",
|
|
5121
5137
|
"tags",
|
|
5122
5138
|
)
|
|
5139
|
+
nullable_fields = (
|
|
5140
|
+
"tenant",
|
|
5141
|
+
"capabilities",
|
|
5142
|
+
)
|
|
5123
5143
|
|
|
5124
5144
|
|
|
5125
|
-
class ControllerManagedDeviceGroupForm(NautobotModelForm):
|
|
5145
|
+
class ControllerManagedDeviceGroupForm(NautobotModelForm, TenancyForm):
|
|
5126
5146
|
"""ControllerManagedDeviceGroup create/edit form."""
|
|
5127
5147
|
|
|
5128
5148
|
controller = DynamicModelChoiceField(queryset=Controller.objects.all(), required=True)
|
|
@@ -5139,12 +5159,15 @@ class ControllerManagedDeviceGroupForm(NautobotModelForm):
|
|
|
5139
5159
|
fields = (
|
|
5140
5160
|
"controller",
|
|
5141
5161
|
"name",
|
|
5162
|
+
"description",
|
|
5142
5163
|
"devices",
|
|
5143
5164
|
"parent",
|
|
5144
5165
|
"capabilities",
|
|
5145
5166
|
"weight",
|
|
5146
5167
|
"radio_profiles",
|
|
5147
5168
|
"tags",
|
|
5169
|
+
"tenant_group",
|
|
5170
|
+
"tenant",
|
|
5148
5171
|
)
|
|
5149
5172
|
|
|
5150
5173
|
def __init__(self, *args, **kwargs):
|
|
@@ -5159,12 +5182,13 @@ class ControllerManagedDeviceGroupForm(NautobotModelForm):
|
|
|
5159
5182
|
return instance
|
|
5160
5183
|
|
|
5161
5184
|
|
|
5162
|
-
class ControllerManagedDeviceGroupFilterForm(NautobotFilterForm):
|
|
5185
|
+
class ControllerManagedDeviceGroupFilterForm(NautobotFilterForm, TenancyFilterForm):
|
|
5163
5186
|
"""ControllerManagedDeviceGroup basic filter form."""
|
|
5164
5187
|
|
|
5165
5188
|
model = ControllerManagedDeviceGroup
|
|
5166
5189
|
q = forms.CharField(required=False, label="Search")
|
|
5167
5190
|
name = forms.CharField(required=False, label="Name")
|
|
5191
|
+
description = forms.CharField(required=False, label="Description")
|
|
5168
5192
|
controller = DynamicModelChoiceField(
|
|
5169
5193
|
queryset=Controller.objects.all(),
|
|
5170
5194
|
required=False,
|
|
@@ -5185,11 +5209,14 @@ class ControllerManagedDeviceGroupFilterForm(NautobotFilterForm):
|
|
|
5185
5209
|
field_order = (
|
|
5186
5210
|
"q",
|
|
5187
5211
|
"name",
|
|
5212
|
+
"description",
|
|
5188
5213
|
"controller",
|
|
5189
5214
|
"parent",
|
|
5190
5215
|
"weight",
|
|
5191
5216
|
"subtree",
|
|
5192
5217
|
"tags",
|
|
5218
|
+
"tenant",
|
|
5219
|
+
"tenant_group",
|
|
5193
5220
|
)
|
|
5194
5221
|
|
|
5195
5222
|
|
|
@@ -5214,10 +5241,11 @@ class ControllerManagedDeviceGroupBulkEditForm(TagsBulkEditFormMixin, NautobotBu
|
|
|
5214
5241
|
label="Remove Radio Profiles",
|
|
5215
5242
|
)
|
|
5216
5243
|
capabilities = JSONArrayFormField(
|
|
5217
|
-
choices=
|
|
5244
|
+
choices=ControllerCapabilitiesChoices,
|
|
5218
5245
|
base_field=forms.CharField(),
|
|
5219
5246
|
required=False,
|
|
5220
5247
|
)
|
|
5248
|
+
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
5221
5249
|
|
|
5222
5250
|
class Meta:
|
|
5223
5251
|
model = ControllerManagedDeviceGroup
|
|
@@ -5225,9 +5253,12 @@ class ControllerManagedDeviceGroupBulkEditForm(TagsBulkEditFormMixin, NautobotBu
|
|
|
5225
5253
|
"controller",
|
|
5226
5254
|
"parent",
|
|
5227
5255
|
"weight",
|
|
5228
|
-
"capabilities",
|
|
5229
5256
|
"tags",
|
|
5230
5257
|
)
|
|
5258
|
+
nullable_fields = (
|
|
5259
|
+
"tenant",
|
|
5260
|
+
"capabilities",
|
|
5261
|
+
)
|
|
5231
5262
|
|
|
5232
5263
|
|
|
5233
5264
|
#
|
nautobot/dcim/graphql/types.py
CHANGED
|
@@ -98,13 +98,13 @@ class CableType(OptimizedNautobotObjectType):
|
|
|
98
98
|
|
|
99
99
|
def resolve_termination_a_type(self, args):
|
|
100
100
|
if self.termination_a_type:
|
|
101
|
-
model = self.termination_a_type.model_class()
|
|
101
|
+
model = self.termination_a_type.model_class() # pylint: disable=no-member
|
|
102
102
|
return f"{model._meta.app_label}.{model._meta.model_name}"
|
|
103
103
|
return None
|
|
104
104
|
|
|
105
105
|
def resolve_termination_b_type(self, args):
|
|
106
106
|
if self.termination_b_type:
|
|
107
|
-
model = self.termination_b_type.model_class()
|
|
107
|
+
model = self.termination_b_type.model_class() # pylint: disable=no-member
|
|
108
108
|
return f"{model._meta.app_label}.{model._meta.model_name}"
|
|
109
109
|
return None
|
|
110
110
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Generated by Django 4.2.16 on 2024-11-21 12:35
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
import django.db.models.deletion
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
dependencies = [
|
|
9
|
+
("tenancy", "0009_update_all_charfields_max_length_to_255"),
|
|
10
|
+
("dcim", "0066_controllermanageddevicegroup_radio_profiles_and_more"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name="controllermanageddevicegroup",
|
|
16
|
+
name="tenant",
|
|
17
|
+
field=models.ForeignKey(
|
|
18
|
+
blank=True,
|
|
19
|
+
null=True,
|
|
20
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
21
|
+
related_name="controller_managed_device_groups",
|
|
22
|
+
to="tenancy.tenant",
|
|
23
|
+
),
|
|
24
|
+
),
|
|
25
|
+
]
|
nautobot/dcim/models/__init__.py
CHANGED
|
@@ -63,12 +63,12 @@ __all__ = (
|
|
|
63
63
|
"Device",
|
|
64
64
|
"DeviceBay",
|
|
65
65
|
"DeviceBayTemplate",
|
|
66
|
+
"DeviceFamily",
|
|
66
67
|
"DeviceRedundancyGroup",
|
|
67
68
|
"DeviceType",
|
|
68
69
|
"DeviceTypeToSoftwareImageFile",
|
|
69
70
|
"FrontPort",
|
|
70
71
|
"FrontPortTemplate",
|
|
71
|
-
"DeviceFamily",
|
|
72
72
|
"Interface",
|
|
73
73
|
"InterfaceRedundancyGroup",
|
|
74
74
|
"InterfaceRedundancyGroupAssociation",
|
|
@@ -100,7 +100,7 @@ class ComponentTemplateModel(
|
|
|
100
100
|
def get_absolute_url(self, api=False):
|
|
101
101
|
# TODO: in the new UI, this should be able to link directly to the object, instead of the device-type.
|
|
102
102
|
if not api:
|
|
103
|
-
return self.device_type.get_absolute_url(api=api)
|
|
103
|
+
return self.device_type.get_absolute_url(api=api) # pylint: disable=no-member
|
|
104
104
|
return super().get_absolute_url(api=api)
|
|
105
105
|
|
|
106
106
|
def instantiate_model(self, model, device, **kwargs):
|
|
@@ -460,7 +460,7 @@ class DeviceBayTemplate(ComponentTemplateModel):
|
|
|
460
460
|
return self.instantiate_model(model=DeviceBay, device=device)
|
|
461
461
|
|
|
462
462
|
def clean(self):
|
|
463
|
-
if self.device_type and self.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT:
|
|
463
|
+
if self.device_type and self.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_PARENT: # pylint: disable=no-member
|
|
464
464
|
raise ValidationError(
|
|
465
465
|
f'Subdevice role of device type ({self.device_type}) must be set to "parent" to allow device bays.'
|
|
466
466
|
)
|
|
@@ -138,7 +138,7 @@ class ModularComponentModel(ComponentModel):
|
|
|
138
138
|
@property
|
|
139
139
|
def parent(self):
|
|
140
140
|
"""Device that this component belongs to, walking up module inheritance if necessary."""
|
|
141
|
-
return self.module.device if self.module else self.device
|
|
141
|
+
return self.module.device if self.module else self.device # pylint: disable=no-member
|
|
142
142
|
|
|
143
143
|
def render_name_template(self, save=False):
|
|
144
144
|
"""
|
|
@@ -161,9 +161,9 @@ class ModularComponentModel(ComponentModel):
|
|
|
161
161
|
|
|
162
162
|
The deeply nested interface would be named "A{module.parent}" after calling this method.
|
|
163
163
|
"""
|
|
164
|
-
if self.module and self.module.parent_module_bay and "{module" in self.name:
|
|
164
|
+
if self.module and self.module.parent_module_bay and "{module" in self.name: # pylint: disable=no-member
|
|
165
165
|
name = ""
|
|
166
|
-
module_bay = self.module.parent_module_bay
|
|
166
|
+
module_bay = self.module.parent_module_bay # pylint: disable=no-member
|
|
167
167
|
positions = []
|
|
168
168
|
while module_bay is not None:
|
|
169
169
|
position = getattr(module_bay, "position", None)
|
|
@@ -291,11 +291,11 @@ class PathEndpoint(models.Model):
|
|
|
291
291
|
return []
|
|
292
292
|
|
|
293
293
|
# Construct the complete path
|
|
294
|
-
path = [self, *self._path.get_path()]
|
|
294
|
+
path = [self, *self._path.get_path()] # pylint: disable=no-member
|
|
295
295
|
while (len(path) + 1) % 3:
|
|
296
296
|
# Pad to ensure we have complete three-tuples (e.g. for paths that end at a RearPort)
|
|
297
297
|
path.append(None)
|
|
298
|
-
path.append(self._path.destination)
|
|
298
|
+
path.append(self._path.destination) # pylint: disable=no-member
|
|
299
299
|
|
|
300
300
|
# Return the path as a list of three-tuples (A termination, cable, B termination)
|
|
301
301
|
return list(zip(*[iter(path)] * 3))
|
|
@@ -555,7 +555,7 @@ class BaseInterface(RelationshipModel):
|
|
|
555
555
|
|
|
556
556
|
def clean(self):
|
|
557
557
|
# Remove untagged VLAN assignment for non-802.1Q interfaces
|
|
558
|
-
if not self.mode and self.untagged_vlan is not None:
|
|
558
|
+
if not self.mode and self.untagged_vlan is not None: # pylint: disable=no-member # Intf/VMIntf both have untagged_vlan
|
|
559
559
|
raise ValidationError({"untagged_vlan": "Mode must be set when specifying untagged_vlan"})
|
|
560
560
|
|
|
561
561
|
def save(self, *args, **kwargs):
|
|
@@ -569,8 +569,8 @@ class BaseInterface(RelationshipModel):
|
|
|
569
569
|
self.status = status
|
|
570
570
|
|
|
571
571
|
# Only "tagged" interfaces may have tagged VLANs assigned. ("tagged all" implies all VLANs are assigned.)
|
|
572
|
-
if self.present_in_database and self.mode != InterfaceModeChoices.MODE_TAGGED:
|
|
573
|
-
self.tagged_vlans.clear()
|
|
572
|
+
if self.present_in_database and self.mode != InterfaceModeChoices.MODE_TAGGED: # pylint: disable=no-member
|
|
573
|
+
self.tagged_vlans.clear() # pylint: disable=no-member # Intf/VMIntf both have tagged_vlans
|
|
574
574
|
|
|
575
575
|
return super().save(*args, **kwargs)
|
|
576
576
|
|
|
@@ -710,18 +710,19 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
|
|
|
710
710
|
)
|
|
711
711
|
|
|
712
712
|
# An interface's parent must belong to the same device or virtual chassis
|
|
713
|
-
if self.parent and self.parent_interface.parent != self.parent:
|
|
713
|
+
if self.parent and self.parent_interface.parent != self.parent: # pylint: disable=no-member
|
|
714
714
|
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
715
715
|
raise ValidationError(
|
|
716
|
-
{
|
|
717
|
-
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs
|
|
718
|
-
f"({self.parent_interface.parent})."
|
|
716
|
+
{ # pylint: disable=no-member # false positive on parent_interface.parent
|
|
717
|
+
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs "
|
|
718
|
+
f"to a different device ({self.parent_interface.parent})."
|
|
719
719
|
}
|
|
720
720
|
)
|
|
721
|
-
elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis:
|
|
721
|
+
elif self.parent_interface.parent.virtual_chassis != self.parent.virtual_chassis: # pylint: disable=no-member
|
|
722
722
|
raise ValidationError(
|
|
723
|
-
{
|
|
724
|
-
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs
|
|
723
|
+
{ # pylint: disable=no-member # false positive on parent_interface.parent
|
|
724
|
+
"parent_interface": f"The selected parent interface ({self.parent_interface}) belongs "
|
|
725
|
+
f"to {self.parent_interface.parent}, which "
|
|
725
726
|
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
726
727
|
}
|
|
727
728
|
)
|
|
@@ -754,21 +755,22 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
|
|
|
754
755
|
raise ValidationError({"bridge": "An interface cannot be bridged to itself."})
|
|
755
756
|
|
|
756
757
|
# A bridged interface belong to the same device or virtual chassis
|
|
757
|
-
if self.parent and self.bridge.parent != self.parent:
|
|
758
|
+
if self.parent and self.bridge.parent != self.parent: # pylint: disable=no-member
|
|
758
759
|
if getattr(self.parent, "virtual_chassis", None) is None:
|
|
759
760
|
raise ValidationError(
|
|
760
761
|
{
|
|
761
762
|
"bridge": (
|
|
763
|
+
# pylint: disable=no-member # false positive on bridge.parent
|
|
762
764
|
f"The selected bridge interface ({self.bridge}) belongs to a different device "
|
|
763
765
|
f"({self.bridge.parent})."
|
|
764
766
|
)
|
|
765
767
|
}
|
|
766
768
|
)
|
|
767
|
-
elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id:
|
|
769
|
+
elif self.bridge.parent.virtual_chassis_id != self.parent.virtual_chassis_id: # pylint: disable=no-member
|
|
768
770
|
raise ValidationError(
|
|
769
771
|
{
|
|
770
772
|
"bridge": (
|
|
771
|
-
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which "
|
|
773
|
+
f"The selected bridge interface ({self.bridge}) belongs to {self.bridge.parent}, which " # pylint: disable=no-member
|
|
772
774
|
f"is not part of virtual chassis {self.parent.virtual_chassis}."
|
|
773
775
|
)
|
|
774
776
|
}
|
|
@@ -1084,8 +1086,8 @@ class DeviceBay(ComponentModel):
|
|
|
1084
1086
|
super().clean()
|
|
1085
1087
|
|
|
1086
1088
|
# Validate that the parent Device can have DeviceBays
|
|
1087
|
-
if not self.device.device_type.is_parent_device:
|
|
1088
|
-
raise ValidationError(f"This type of device ({self.device.device_type}) does not support device bays.")
|
|
1089
|
+
if not self.device.device_type.is_parent_device: # pylint: disable=no-member
|
|
1090
|
+
raise ValidationError(f"This type of device ({self.device.device_type}) does not support device bays.") # pylint: disable=no-member
|
|
1089
1091
|
|
|
1090
1092
|
# Cannot install a device into itself, obviously
|
|
1091
1093
|
if self.device == self.installed_device:
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -48,6 +48,7 @@ __all__ = (
|
|
|
48
48
|
"Controller",
|
|
49
49
|
"ControllerManagedDeviceGroup",
|
|
50
50
|
"Device",
|
|
51
|
+
"DeviceFamily",
|
|
51
52
|
"DeviceRedundancyGroup",
|
|
52
53
|
"DeviceType",
|
|
53
54
|
"InterfaceVDCAssignment",
|
|
@@ -823,6 +824,7 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
823
824
|
|
|
824
825
|
# If any software image file is specified, validate that
|
|
825
826
|
# each of the software image files belongs to the device's device type or is a default image
|
|
827
|
+
# TODO: this is incorrect as we cannot validate a ManyToMany during clean() - nautobot/nautobot#6344
|
|
826
828
|
for image_file in self.software_image_files.all():
|
|
827
829
|
if not image_file.default_image and self.device_type not in image_file.device_types.all():
|
|
828
830
|
raise ValidationError(
|
|
@@ -1481,6 +1483,13 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
|
|
|
1481
1483
|
null=True,
|
|
1482
1484
|
help_text="List of capabilities supported by the controller device group, these capabilities are used to enhance views in Nautobot.",
|
|
1483
1485
|
)
|
|
1486
|
+
tenant = models.ForeignKey(
|
|
1487
|
+
to="tenancy.Tenant",
|
|
1488
|
+
on_delete=models.PROTECT,
|
|
1489
|
+
related_name="controller_managed_device_groups",
|
|
1490
|
+
blank=True,
|
|
1491
|
+
null=True,
|
|
1492
|
+
)
|
|
1484
1493
|
|
|
1485
1494
|
class Meta:
|
|
1486
1495
|
ordering = ("weight",)
|
|
@@ -1500,7 +1509,7 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
|
|
|
1500
1509
|
if self.controller == self._original_controller and self.parent == self._original_parent:
|
|
1501
1510
|
return
|
|
1502
1511
|
|
|
1503
|
-
if self.parent and self.controller and self.controller != self.parent.controller:
|
|
1512
|
+
if self.parent and self.controller and self.controller != self.parent.controller: # pylint: disable=no-member
|
|
1504
1513
|
raise ValidationError(
|
|
1505
1514
|
{"controller": "Controller device group must have the same controller as the parent group."}
|
|
1506
1515
|
)
|
|
@@ -283,7 +283,7 @@ class Location(TreeModel, PrimaryModel):
|
|
|
283
283
|
# We shouldn't have a parent, *unless* our own location type is permitted to be nested.
|
|
284
284
|
if self.parent is not None:
|
|
285
285
|
if self.location_type.nestable:
|
|
286
|
-
if self.parent.location_type != self.location_type:
|
|
286
|
+
if self.parent.location_type != self.location_type: # pylint: disable=no-member
|
|
287
287
|
raise ValidationError(
|
|
288
288
|
{
|
|
289
289
|
"parent": f"A Location of type {self.location_type} may only have "
|
|
@@ -304,7 +304,7 @@ class Location(TreeModel, PrimaryModel):
|
|
|
304
304
|
|
|
305
305
|
# Is the parent location of a correct type?
|
|
306
306
|
if self.location_type.nestable:
|
|
307
|
-
if self.parent.location_type not in (self.location_type, self.location_type.parent):
|
|
307
|
+
if self.parent.location_type not in (self.location_type, self.location_type.parent): # pylint: disable=no-member
|
|
308
308
|
raise ValidationError(
|
|
309
309
|
{
|
|
310
310
|
"parent": f"A Location of type {self.location_type} can only have a Location "
|
|
@@ -312,7 +312,7 @@ class Location(TreeModel, PrimaryModel):
|
|
|
312
312
|
}
|
|
313
313
|
)
|
|
314
314
|
else:
|
|
315
|
-
if self.parent.location_type != self.location_type.parent:
|
|
315
|
+
if self.parent.location_type != self.location_type.parent: # pylint: disable=no-member
|
|
316
316
|
raise ValidationError(
|
|
317
317
|
{
|
|
318
318
|
"parent": f"A Location of type {self.location_type} can only have a Location "
|
nautobot/dcim/models/power.py
CHANGED
|
@@ -73,11 +73,11 @@ class PowerPanel(PrimaryModel):
|
|
|
73
73
|
if self.rack_group:
|
|
74
74
|
if (
|
|
75
75
|
self.location is not None
|
|
76
|
-
and self.rack_group.location is not None
|
|
77
|
-
and self.rack_group.location not in self.location.ancestors(include_self=True)
|
|
76
|
+
and self.rack_group.location is not None # pylint: disable=no-member
|
|
77
|
+
and self.rack_group.location not in self.location.ancestors(include_self=True) # pylint: disable=no-member
|
|
78
78
|
):
|
|
79
79
|
raise ValidationError(
|
|
80
|
-
{
|
|
80
|
+
{ # pylint: disable=no-member # false positive on rack_group.location
|
|
81
81
|
"rack_group": f'Rack group "{self.rack_group}" belongs to a location '
|
|
82
82
|
f'("{self.rack_group.location}") that does not contain "{self.location}".'
|
|
83
83
|
}
|
|
@@ -151,9 +151,10 @@ class PowerFeed(PrimaryModel, PathEndpoint, CableTermination):
|
|
|
151
151
|
super().clean()
|
|
152
152
|
|
|
153
153
|
# Rack must belong to same Location as PowerPanel
|
|
154
|
-
if self.rack and self.rack.location != self.power_panel.location:
|
|
154
|
+
if self.rack and self.rack.location != self.power_panel.location: # pylint: disable=no-member
|
|
155
155
|
raise ValidationError(
|
|
156
|
-
f"Rack {self.rack} ({self.rack.location}) and
|
|
156
|
+
f"Rack {self.rack} ({self.rack.location}) and " # pylint: disable=no-member
|
|
157
|
+
f"power panel {self.power_panel} ({self.power_panel.location}) are in different locations"
|
|
157
158
|
)
|
|
158
159
|
|
|
159
160
|
# AC voltage cannot be negative
|
nautobot/dcim/models/racks.py
CHANGED
|
@@ -77,11 +77,11 @@ class RackGroup(TreeModel, OrganizationalModel):
|
|
|
77
77
|
# Parent RackGroup (if any) must belong to the same or ancestor Location
|
|
78
78
|
if (
|
|
79
79
|
self.parent is not None
|
|
80
|
-
and self.parent.location is not None
|
|
81
|
-
and self.parent.location not in self.location.ancestors(include_self=True)
|
|
80
|
+
and self.parent.location is not None # pylint: disable=no-member
|
|
81
|
+
and self.parent.location not in self.location.ancestors(include_self=True) # pylint: disable=no-member
|
|
82
82
|
):
|
|
83
83
|
raise ValidationError(
|
|
84
|
-
{
|
|
84
|
+
{ # pylint: disable=no-member # false positive on parent.location
|
|
85
85
|
"location": f'Location "{self.location}" is not descended from '
|
|
86
86
|
f'parent rack group "{self.parent}" location "{self.parent.location}".'
|
|
87
87
|
}
|
|
@@ -296,7 +296,7 @@ class Rack(PrimaryModel):
|
|
|
296
296
|
# Determine which devices the user has permission to view
|
|
297
297
|
permitted_device_ids = []
|
|
298
298
|
if user is not None:
|
|
299
|
-
permitted_device_ids = self.devices.restrict(user, "view").values_list("pk", flat=True)
|
|
299
|
+
permitted_device_ids = self.devices.restrict(user, "view").values_list("pk", flat=True) # pylint: disable=no-member
|
|
300
300
|
|
|
301
301
|
for device in queryset:
|
|
302
302
|
if expand_devices:
|