nautobot 2.4.9__py3-none-any.whl → 2.4.11__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/cloud/tests/test_views.py +13 -1
- nautobot/cloud/views.py +39 -9
- nautobot/core/api/parsers.py +56 -2
- nautobot/core/celery/__init__.py +21 -0
- nautobot/core/celery/encoders.py +3 -0
- nautobot/core/forms/forms.py +4 -1
- nautobot/core/jobs/bulk_actions.py +8 -8
- nautobot/core/jobs/cleanup.py +11 -0
- nautobot/core/management/commands/generate_test_data.py +2 -1
- nautobot/core/models/__init__.py +2 -0
- nautobot/core/templates/generic/object_retrieve.html +1 -1
- nautobot/core/testing/mixins.py +19 -1
- nautobot/core/testing/views.py +104 -8
- nautobot/core/tests/test_csv.py +92 -1
- nautobot/core/tests/test_jinja_filters.py +59 -0
- nautobot/core/tests/test_jobs.py +20 -4
- nautobot/core/tests/test_utils.py +193 -0
- nautobot/core/tests/test_views.py +73 -0
- nautobot/core/tests/test_views_utils.py +53 -2
- nautobot/core/ui/object_detail.py +4 -0
- nautobot/core/urls.py +2 -2
- nautobot/core/utils/lookup.py +4 -2
- nautobot/core/utils/module_loading.py +86 -58
- nautobot/core/views/__init__.py +21 -0
- nautobot/core/views/generic.py +2 -12
- nautobot/core/views/mixins.py +19 -1
- nautobot/core/views/renderers.py +4 -13
- nautobot/core/views/utils.py +16 -0
- nautobot/dcim/api/serializers.py +13 -0
- nautobot/dcim/api/urls.py +1 -0
- nautobot/dcim/api/views.py +20 -0
- nautobot/dcim/apps.py +1 -0
- nautobot/dcim/factory.py +11 -0
- nautobot/dcim/filters/__init__.py +110 -0
- nautobot/dcim/forms.py +205 -19
- nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
- nautobot/dcim/models/__init__.py +2 -0
- nautobot/dcim/models/device_component_templates.py +18 -0
- nautobot/dcim/models/device_components.py +25 -1
- nautobot/dcim/models/devices.py +68 -0
- nautobot/dcim/navigation.py +16 -0
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +48 -0
- nautobot/dcim/tables/devicetypes.py +35 -1
- nautobot/dcim/tables/template_code.py +2 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
- nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
- nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
- nautobot/dcim/templates/dcim/location.html +2 -249
- nautobot/dcim/templates/dcim/location_edit.html +2 -38
- nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
- nautobot/dcim/templates/dcim/location_update.html +38 -0
- nautobot/dcim/templates/dcim/module_update.html +1 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
- nautobot/dcim/tests/test_api.py +35 -0
- nautobot/dcim/tests/test_filters.py +102 -3
- nautobot/dcim/tests/test_models.py +146 -0
- nautobot/dcim/tests/test_views.py +70 -97
- nautobot/dcim/urls.py +4 -22
- nautobot/dcim/views.py +439 -153
- nautobot/extras/api/views.py +9 -2
- nautobot/extras/context_managers.py +2 -2
- nautobot/extras/datasources/git.py +11 -3
- nautobot/extras/forms/forms.py +9 -5
- nautobot/extras/jobs.py +4 -2
- nautobot/extras/models/customfields.py +2 -0
- nautobot/extras/models/datasources.py +13 -8
- nautobot/extras/models/groups.py +18 -0
- nautobot/extras/models/jobs.py +19 -0
- nautobot/extras/models/metadata.py +2 -0
- nautobot/extras/models/models.py +4 -0
- nautobot/extras/models/secrets.py +7 -0
- nautobot/extras/plugins/__init__.py +3 -0
- nautobot/extras/secrets/__init__.py +14 -0
- nautobot/extras/tables.py +40 -3
- nautobot/extras/templates/extras/configcontext.html +2 -220
- nautobot/extras/templates/extras/configcontext_edit.html +2 -50
- nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
- nautobot/extras/templates/extras/configcontext_update.html +50 -0
- nautobot/extras/templates/extras/configcontextschema.html +2 -48
- nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
- nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
- nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
- nautobot/extras/templates/extras/inc/json_data.html +1 -1
- nautobot/extras/templates/extras/inc/json_format.html +2 -2
- nautobot/extras/templates/extras/job_edit.html +12 -6
- nautobot/extras/templates/extras/tag.html +2 -52
- nautobot/extras/templates/extras/tag_edit.html +2 -15
- nautobot/extras/templates/extras/tag_retrieve.html +52 -0
- nautobot/extras/templates/extras/tag_update.html +15 -0
- nautobot/extras/templates/extras/team_retrieve.html +2 -2
- nautobot/extras/tests/test_api.py +15 -15
- nautobot/extras/tests/test_context_managers.py +20 -0
- nautobot/extras/tests/test_filters.py +4 -4
- nautobot/extras/tests/test_jobs.py +23 -10
- nautobot/extras/tests/test_models.py +45 -8
- nautobot/extras/tests/test_plugins.py +6 -3
- nautobot/extras/tests/test_views.py +66 -11
- nautobot/extras/urls.py +4 -134
- nautobot/extras/views.py +113 -158
- nautobot/ipam/models.py +51 -4
- nautobot/ipam/tables.py +19 -0
- nautobot/ipam/templates/ipam/vlan.html +2 -84
- nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
- nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
- nautobot/ipam/templates/ipam/vlan_update.html +24 -0
- nautobot/ipam/tests/test_views.py +5 -0
- nautobot/ipam/urls.py +1 -21
- nautobot/ipam/views.py +45 -70
- nautobot/project-static/docs/404.html +31 -8
- nautobot/project-static/docs/apps/index.html +31 -8
- nautobot/project-static/docs/apps/nautobot-apps.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +120 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +31 -8
- nautobot/project-static/docs/development/apps/api/configuration-view.html +31 -8
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/global-search.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/graphql.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +40 -8
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +70 -46
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +31 -8
- nautobot/project-static/docs/development/apps/api/prometheus.html +31 -8
- nautobot/project-static/docs/development/apps/api/setup.html +31 -8
- nautobot/project-static/docs/development/apps/api/testing.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/base-template.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/notes.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/urls.html +31 -8
- nautobot/project-static/docs/development/apps/index.html +31 -8
- nautobot/project-static/docs/development/apps/migration/code-updates.html +31 -8
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +31 -8
- nautobot/project-static/docs/development/apps/migration/from-v1.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +31 -8
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +31 -8
- nautobot/project-static/docs/development/core/application-registry.html +31 -8
- nautobot/project-static/docs/development/core/best-practices.html +31 -8
- nautobot/project-static/docs/development/core/bootstrap-ui.html +31 -8
- nautobot/project-static/docs/development/core/caching.html +31 -8
- nautobot/project-static/docs/development/core/controllers.html +31 -8
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +31 -8
- nautobot/project-static/docs/development/core/generic-views.html +31 -8
- nautobot/project-static/docs/development/core/getting-started.html +31 -8
- nautobot/project-static/docs/development/core/homepage.html +31 -8
- nautobot/project-static/docs/development/core/index.html +31 -8
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +31 -8
- nautobot/project-static/docs/development/core/model-checklist.html +31 -8
- nautobot/project-static/docs/development/core/model-features.html +31 -8
- nautobot/project-static/docs/development/core/natural-keys.html +31 -8
- nautobot/project-static/docs/development/core/navigation-menu.html +31 -8
- nautobot/project-static/docs/development/core/release-checklist.html +31 -8
- nautobot/project-static/docs/development/core/role-internals.html +31 -8
- nautobot/project-static/docs/development/core/settings.html +31 -8
- nautobot/project-static/docs/development/core/style-guide.html +31 -8
- nautobot/project-static/docs/development/core/templates.html +31 -8
- nautobot/project-static/docs/development/core/testing.html +31 -8
- nautobot/project-static/docs/development/core/ui-component-framework.html +31 -8
- nautobot/project-static/docs/development/core/user-preferences.html +31 -8
- nautobot/project-static/docs/development/index.html +31 -8
- nautobot/project-static/docs/development/jobs/getting-started.html +35 -8
- nautobot/project-static/docs/development/jobs/index.html +31 -8
- nautobot/project-static/docs/development/jobs/installation.html +31 -8
- nautobot/project-static/docs/development/jobs/job-extensions.html +31 -8
- nautobot/project-static/docs/development/jobs/job-logging.html +31 -8
- nautobot/project-static/docs/development/jobs/job-patterns.html +31 -8
- nautobot/project-static/docs/development/jobs/job-structure.html +31 -8
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +31 -8
- nautobot/project-static/docs/development/jobs/testing.html +31 -8
- nautobot/project-static/docs/index.html +31 -8
- nautobot/project-static/docs/insert-analytics.sh +36 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +31 -8
- nautobot/project-static/docs/overview/design_philosophy.html +31 -8
- nautobot/project-static/docs/release-notes/index.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.0.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.1.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.2.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.3.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.4.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.5.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.6.html +328 -8
- nautobot/project-static/docs/release-notes/version-2.0.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.1.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.2.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.3.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.4.html +353 -8
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +302 -298
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/services.html +31 -8
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +31 -8
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +31 -8
- nautobot/project-static/docs/user-guide/administration/security/index.html +31 -9
- nautobot/project-static/docs/user-guide/administration/security/notices.html +144 -9
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +31 -8
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +43 -20
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +41 -15
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +31 -8
- nautobot/project-static/docs/user-guide/index.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +37 -9
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +31 -8
- nautobot/tenancy/tables.py +2 -0
- nautobot/users/models.py +4 -0
- nautobot/virtualization/models.py +4 -0
- nautobot/virtualization/tests/test_views.py +1 -1
- nautobot/wireless/forms.py +0 -1
- nautobot/wireless/models.py +1 -1
- nautobot/wireless/tables.py +7 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/METADATA +4 -4
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/RECORD +433 -418
- /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
- /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/NOTICE +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/WHEEL +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/entry_points.txt +0 -0
nautobot/extras/views.py
CHANGED
|
@@ -2,6 +2,7 @@ import logging
|
|
|
2
2
|
from typing import Optional
|
|
3
3
|
from urllib.parse import parse_qs
|
|
4
4
|
|
|
5
|
+
from django.conf import settings
|
|
5
6
|
from django.contrib import messages
|
|
6
7
|
from django.contrib.contenttypes.models import ContentType
|
|
7
8
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
@@ -15,7 +16,7 @@ from django.urls import reverse
|
|
|
15
16
|
from django.urls.exceptions import NoReverseMatch
|
|
16
17
|
from django.utils import timezone
|
|
17
18
|
from django.utils.encoding import iri_to_uri
|
|
18
|
-
from django.utils.html import format_html
|
|
19
|
+
from django.utils.html import format_html, format_html_join
|
|
19
20
|
from django.utils.http import url_has_allowed_host_and_scheme
|
|
20
21
|
from django.utils.timezone import get_current_timezone
|
|
21
22
|
from django.views.generic import View
|
|
@@ -86,7 +87,6 @@ from .choices import (
|
|
|
86
87
|
JobExecutionType,
|
|
87
88
|
JobQueueTypeChoices,
|
|
88
89
|
JobResultStatusChoices,
|
|
89
|
-
LogLevelChoices,
|
|
90
90
|
)
|
|
91
91
|
from .datasources import (
|
|
92
92
|
enqueue_git_repository_diff_origin_and_local,
|
|
@@ -111,7 +111,6 @@ from .models import (
|
|
|
111
111
|
Job as JobModel,
|
|
112
112
|
JobButton,
|
|
113
113
|
JobHook,
|
|
114
|
-
JobLogEntry,
|
|
115
114
|
JobQueue,
|
|
116
115
|
JobResult,
|
|
117
116
|
MetadataType,
|
|
@@ -180,55 +179,89 @@ class ComputedFieldUIViewSet(NautobotUIViewSet):
|
|
|
180
179
|
# have an associated owner, such as a Git repository
|
|
181
180
|
|
|
182
181
|
|
|
183
|
-
class
|
|
182
|
+
class ConfigContextUIViewSet(NautobotUIViewSet):
|
|
183
|
+
bulk_update_form_class = forms.ConfigContextBulkEditForm
|
|
184
|
+
filterset_class = filters.ConfigContextFilterSet
|
|
185
|
+
filterset_form_class = forms.ConfigContextFilterForm
|
|
186
|
+
form_class = forms.ConfigContextForm
|
|
184
187
|
queryset = ConfigContext.objects.all()
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
table = tables.ConfigContextTable
|
|
188
|
-
action_buttons = ("add",)
|
|
188
|
+
serializer_class = serializers.ConfigContextSerializer
|
|
189
|
+
table_class = tables.ConfigContextTable
|
|
189
190
|
|
|
191
|
+
class AssignmentObjectFieldsPanel(object_detail.ObjectFieldsPanel):
|
|
192
|
+
def render_value(self, key, value, context):
|
|
193
|
+
if key == "dynamic_groups" and not settings.CONFIG_CONTEXT_DYNAMIC_GROUPS_ENABLED:
|
|
194
|
+
return None
|
|
195
|
+
if not value:
|
|
196
|
+
return helpers.HTML_NONE
|
|
190
197
|
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
items = []
|
|
199
|
+
for val in value.all():
|
|
200
|
+
rendered_val = helpers.hyperlinked_object(val)
|
|
201
|
+
items.append(rendered_val)
|
|
202
|
+
|
|
203
|
+
if not items:
|
|
204
|
+
return helpers.HTML_NONE
|
|
205
|
+
|
|
206
|
+
return format_html("<ul>{}</ul>", format_html_join("", "<li>{}</li>", ((item,) for item in items)))
|
|
207
|
+
|
|
208
|
+
object_detail_content = object_detail.ObjectDetailContent(
|
|
209
|
+
panels=(
|
|
210
|
+
object_detail.ObjectFieldsPanel(
|
|
211
|
+
weight=100,
|
|
212
|
+
section=SectionChoices.LEFT_HALF,
|
|
213
|
+
fields="__all__",
|
|
214
|
+
exclude_fields=[
|
|
215
|
+
"data",
|
|
216
|
+
"owner_content_type",
|
|
217
|
+
"owner_object_id",
|
|
218
|
+
],
|
|
219
|
+
hide_if_unset=[
|
|
220
|
+
"owner",
|
|
221
|
+
],
|
|
222
|
+
),
|
|
223
|
+
object_detail.Panel(
|
|
224
|
+
weight=100,
|
|
225
|
+
section=SectionChoices.FULL_WIDTH,
|
|
226
|
+
label="Data",
|
|
227
|
+
header_extra_content_template_path="extras/inc/json_format.html",
|
|
228
|
+
body_content_template_path="extras/inc/configcontext_data.html",
|
|
229
|
+
),
|
|
230
|
+
AssignmentObjectFieldsPanel(
|
|
231
|
+
weight=200,
|
|
232
|
+
section=SectionChoices.RIGHT_HALF,
|
|
233
|
+
label="Assignment",
|
|
234
|
+
fields=[
|
|
235
|
+
"locations",
|
|
236
|
+
"roles",
|
|
237
|
+
"device_types",
|
|
238
|
+
"platforms",
|
|
239
|
+
"cluster_groups",
|
|
240
|
+
"clusters",
|
|
241
|
+
"tenant_groups",
|
|
242
|
+
"tenants",
|
|
243
|
+
"device_redundancy_groups",
|
|
244
|
+
"dynamic_groups",
|
|
245
|
+
],
|
|
246
|
+
),
|
|
247
|
+
)
|
|
248
|
+
)
|
|
193
249
|
|
|
194
250
|
def get_extra_context(self, request, instance):
|
|
195
251
|
context = super().get_extra_context(request, instance)
|
|
196
252
|
# Determine user's preferred output format
|
|
197
|
-
if request.GET.get("
|
|
198
|
-
context["
|
|
253
|
+
if request.GET.get("data_format") in ["json", "yaml"]:
|
|
254
|
+
context["data_format"] = request.GET.get("data_format")
|
|
199
255
|
if request.user.is_authenticated:
|
|
200
|
-
request.user.set_config("extras.configcontext.format", context["
|
|
256
|
+
request.user.set_config("extras.configcontext.format", context["data_format"], commit=True)
|
|
201
257
|
elif request.user.is_authenticated:
|
|
202
|
-
context["
|
|
258
|
+
context["data_format"] = request.user.get_config("extras.configcontext.format", "json")
|
|
203
259
|
else:
|
|
204
|
-
context["
|
|
260
|
+
context["data_format"] = "json"
|
|
205
261
|
|
|
206
262
|
return context
|
|
207
263
|
|
|
208
264
|
|
|
209
|
-
class ConfigContextEditView(generic.ObjectEditView):
|
|
210
|
-
queryset = ConfigContext.objects.all()
|
|
211
|
-
model_form = forms.ConfigContextForm
|
|
212
|
-
template_name = "extras/configcontext_edit.html"
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
class ConfigContextBulkEditView(generic.BulkEditView):
|
|
216
|
-
queryset = ConfigContext.objects.all()
|
|
217
|
-
filterset = filters.ConfigContextFilterSet
|
|
218
|
-
table = tables.ConfigContextTable
|
|
219
|
-
form = forms.ConfigContextBulkEditForm
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
class ConfigContextDeleteView(generic.ObjectDeleteView):
|
|
223
|
-
queryset = ConfigContext.objects.all()
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
class ConfigContextBulkDeleteView(generic.BulkDeleteView):
|
|
227
|
-
queryset = ConfigContext.objects.all()
|
|
228
|
-
table = tables.ConfigContextTable
|
|
229
|
-
filterset = filters.ConfigContextFilterSet
|
|
230
|
-
|
|
231
|
-
|
|
232
265
|
class ObjectConfigContextView(generic.ObjectView):
|
|
233
266
|
base_template = None
|
|
234
267
|
template_name = "extras/object_configcontext.html"
|
|
@@ -263,28 +296,26 @@ class ObjectConfigContextView(generic.ObjectView):
|
|
|
263
296
|
# have an associated owner, such as a Git repository
|
|
264
297
|
|
|
265
298
|
|
|
266
|
-
class
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
action_buttons = ("add",)
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
class ConfigContextSchemaView(generic.ObjectView):
|
|
299
|
+
class ConfigContextSchemaUIViewSet(NautobotUIViewSet):
|
|
300
|
+
bulk_update_form_class = forms.ConfigContextSchemaBulkEditForm
|
|
301
|
+
filterset_class = filters.ConfigContextSchemaFilterSet
|
|
302
|
+
filterset_form_class = forms.ConfigContextSchemaFilterForm
|
|
303
|
+
form_class = forms.ConfigContextSchemaForm
|
|
275
304
|
queryset = ConfigContextSchema.objects.all()
|
|
305
|
+
serializer_class = serializers.ConfigContextSchemaSerializer
|
|
306
|
+
table_class = tables.ConfigContextSchemaTable
|
|
276
307
|
|
|
277
308
|
def get_extra_context(self, request, instance):
|
|
278
309
|
context = super().get_extra_context(request, instance)
|
|
279
310
|
# Determine user's preferred output format
|
|
280
|
-
if request.GET.get("
|
|
281
|
-
context["
|
|
311
|
+
if request.GET.get("data_format") in ["json", "yaml"]:
|
|
312
|
+
context["data_format"] = request.GET.get("data_format")
|
|
282
313
|
if request.user.is_authenticated:
|
|
283
|
-
request.user.set_config("extras.configcontextschema.format", context["
|
|
314
|
+
request.user.set_config("extras.configcontextschema.format", context["data_format"], commit=True)
|
|
284
315
|
elif request.user.is_authenticated:
|
|
285
|
-
context["
|
|
316
|
+
context["data_format"] = request.user.get_config("extras.configcontextschema.format", "json")
|
|
286
317
|
else:
|
|
287
|
-
context["
|
|
318
|
+
context["data_format"] = "json"
|
|
288
319
|
|
|
289
320
|
return context
|
|
290
321
|
|
|
@@ -372,29 +403,6 @@ class ConfigContextSchemaObjectValidationView(generic.ObjectView):
|
|
|
372
403
|
}
|
|
373
404
|
|
|
374
405
|
|
|
375
|
-
class ConfigContextSchemaEditView(generic.ObjectEditView):
|
|
376
|
-
queryset = ConfigContextSchema.objects.all()
|
|
377
|
-
model_form = forms.ConfigContextSchemaForm
|
|
378
|
-
template_name = "extras/configcontextschema_edit.html"
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
class ConfigContextSchemaBulkEditView(generic.BulkEditView):
|
|
382
|
-
queryset = ConfigContextSchema.objects.all()
|
|
383
|
-
filterset = filters.ConfigContextSchemaFilterSet
|
|
384
|
-
table = tables.ConfigContextSchemaTable
|
|
385
|
-
form = forms.ConfigContextSchemaBulkEditForm
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
class ConfigContextSchemaDeleteView(generic.ObjectDeleteView):
|
|
389
|
-
queryset = ConfigContextSchema.objects.all()
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
class ConfigContextSchemaBulkDeleteView(generic.BulkDeleteView):
|
|
393
|
-
queryset = ConfigContextSchema.objects.all()
|
|
394
|
-
table = tables.ConfigContextSchemaTable
|
|
395
|
-
filterset = filters.ConfigContextSchemaFilterSet
|
|
396
|
-
|
|
397
|
-
|
|
398
406
|
#
|
|
399
407
|
# Contacts
|
|
400
408
|
#
|
|
@@ -1553,6 +1561,11 @@ class JobEditView(generic.ObjectEditView):
|
|
|
1553
1561
|
model_form = forms.JobEditForm
|
|
1554
1562
|
template_name = "extras/job_edit.html"
|
|
1555
1563
|
|
|
1564
|
+
def alter_obj(self, obj, request, url_args, url_kwargs):
|
|
1565
|
+
# Reload the job class to ensure we have the latest version
|
|
1566
|
+
get_job(obj.class_path, reload=True)
|
|
1567
|
+
return obj
|
|
1568
|
+
|
|
1556
1569
|
|
|
1557
1570
|
class JobBulkEditView(generic.BulkEditView):
|
|
1558
1571
|
queryset = JobModel.objects.all()
|
|
@@ -2077,44 +2090,12 @@ class JobHookUIViewSet(NautobotUIViewSet):
|
|
|
2077
2090
|
#
|
|
2078
2091
|
|
|
2079
2092
|
|
|
2080
|
-
def get_annotated_jobresult_queryset():
|
|
2081
|
-
return (
|
|
2082
|
-
JobResult.objects.defer("result")
|
|
2083
|
-
.select_related("job_model", "user")
|
|
2084
|
-
.annotate(
|
|
2085
|
-
debug_log_count=count_related(
|
|
2086
|
-
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_DEBUG}
|
|
2087
|
-
),
|
|
2088
|
-
success_log_count=count_related(
|
|
2089
|
-
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_SUCCESS}
|
|
2090
|
-
),
|
|
2091
|
-
info_log_count=count_related(
|
|
2092
|
-
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_INFO}
|
|
2093
|
-
),
|
|
2094
|
-
warning_log_count=count_related(
|
|
2095
|
-
JobLogEntry, "job_result", filter_dict={"log_level": LogLevelChoices.LOG_WARNING}
|
|
2096
|
-
),
|
|
2097
|
-
error_log_count=count_related(
|
|
2098
|
-
JobLogEntry,
|
|
2099
|
-
"job_result",
|
|
2100
|
-
filter_dict={
|
|
2101
|
-
"log_level__in": [
|
|
2102
|
-
LogLevelChoices.LOG_FAILURE,
|
|
2103
|
-
LogLevelChoices.LOG_ERROR,
|
|
2104
|
-
LogLevelChoices.LOG_CRITICAL,
|
|
2105
|
-
],
|
|
2106
|
-
},
|
|
2107
|
-
),
|
|
2108
|
-
)
|
|
2109
|
-
)
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
2093
|
class JobResultListView(generic.ObjectListView):
|
|
2113
2094
|
"""
|
|
2114
2095
|
List JobResults
|
|
2115
2096
|
"""
|
|
2116
2097
|
|
|
2117
|
-
queryset =
|
|
2098
|
+
queryset = JobResult.objects.defer("result").select_related("job_model", "user")
|
|
2118
2099
|
filterset = filters.JobResultFilterSet
|
|
2119
2100
|
filterset_form = forms.JobResultFilterForm
|
|
2120
2101
|
table = tables.JobResultTable
|
|
@@ -2126,7 +2107,7 @@ class JobResultDeleteView(generic.ObjectDeleteView):
|
|
|
2126
2107
|
|
|
2127
2108
|
|
|
2128
2109
|
class JobResultBulkDeleteView(generic.BulkDeleteView):
|
|
2129
|
-
queryset =
|
|
2110
|
+
queryset = JobResult.objects.defer("result").select_related("job_model", "user")
|
|
2130
2111
|
table = tables.JobResultTable
|
|
2131
2112
|
filterset = filters.JobResultFilterSet
|
|
2132
2113
|
|
|
@@ -2519,24 +2500,15 @@ class RelationshipUIViewSet(NautobotUIViewSet):
|
|
|
2519
2500
|
)
|
|
2520
2501
|
|
|
2521
2502
|
|
|
2522
|
-
class
|
|
2503
|
+
class RelationshipAssociationUIViewSet(ObjectListViewMixin, ObjectDestroyViewMixin, ObjectBulkDestroyViewMixin):
|
|
2504
|
+
filterset_class = filters.RelationshipAssociationFilterSet
|
|
2505
|
+
filterset_form_class = forms.RelationshipAssociationFilterForm
|
|
2506
|
+
serializer_class = serializers.RelationshipAssociationSerializer
|
|
2507
|
+
table_class = tables.RelationshipAssociationTable
|
|
2523
2508
|
queryset = RelationshipAssociation.objects.all()
|
|
2524
|
-
filterset = filters.RelationshipAssociationFilterSet
|
|
2525
|
-
filterset_form = forms.RelationshipAssociationFilterForm
|
|
2526
|
-
table = tables.RelationshipAssociationTable
|
|
2527
2509
|
action_buttons = ()
|
|
2528
2510
|
|
|
2529
2511
|
|
|
2530
|
-
class RelationshipAssociationBulkDeleteView(generic.BulkDeleteView):
|
|
2531
|
-
queryset = RelationshipAssociation.objects.all()
|
|
2532
|
-
table = tables.RelationshipAssociationTable
|
|
2533
|
-
filterset = filters.RelationshipAssociationFilterSet
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
class RelationshipAssociationDeleteView(generic.ObjectDeleteView):
|
|
2537
|
-
queryset = RelationshipAssociation.objects.all()
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
2512
|
#
|
|
2541
2513
|
# Roles
|
|
2542
2514
|
#
|
|
@@ -3005,17 +2977,28 @@ class StatusUIViewSet(NautobotUIViewSet):
|
|
|
3005
2977
|
#
|
|
3006
2978
|
|
|
3007
2979
|
|
|
3008
|
-
class
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
2980
|
+
class TagUIViewSet(NautobotUIViewSet):
|
|
2981
|
+
bulk_update_form_class = forms.TagBulkEditForm
|
|
2982
|
+
filterset_class = filters.TagFilterSet
|
|
2983
|
+
filterset_form_class = forms.TagFilterForm
|
|
2984
|
+
form_class = forms.TagForm
|
|
2985
|
+
queryset = Tag.objects.all()
|
|
2986
|
+
serializer_class = serializers.TagSerializer
|
|
2987
|
+
table_class = tables.TagTable
|
|
2988
|
+
|
|
2989
|
+
def alter_queryset(self, request):
|
|
2990
|
+
queryset = super().alter_queryset(request)
|
|
3013
2991
|
|
|
2992
|
+
# Only annotate for list, bulk_edit, bulk_delete views
|
|
2993
|
+
if self.action in ["list", "bulk_update", "bulk_destroy"]:
|
|
2994
|
+
queryset = queryset.annotate(items=count_related(TaggedItem, "tag"))
|
|
3014
2995
|
|
|
3015
|
-
|
|
3016
|
-
queryset = Tag.objects.all()
|
|
2996
|
+
return queryset
|
|
3017
2997
|
|
|
3018
2998
|
def get_extra_context(self, request, instance):
|
|
2999
|
+
# Only run this logic when retrieving a single object
|
|
3000
|
+
if instance is None or self.action != "retrieve":
|
|
3001
|
+
return super().get_extra_context(request, instance)
|
|
3019
3002
|
tagged_items = (
|
|
3020
3003
|
TaggedItem.objects.filter(tag=instance).select_related("content_type").prefetch_related("content_object")
|
|
3021
3004
|
)
|
|
@@ -3036,34 +3019,6 @@ class TagView(generic.ObjectView):
|
|
|
3036
3019
|
}
|
|
3037
3020
|
|
|
3038
3021
|
|
|
3039
|
-
class TagEditView(generic.ObjectEditView):
|
|
3040
|
-
queryset = Tag.objects.all()
|
|
3041
|
-
model_form = forms.TagForm
|
|
3042
|
-
template_name = "extras/tag_edit.html"
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
class TagDeleteView(generic.ObjectDeleteView):
|
|
3046
|
-
queryset = Tag.objects.all()
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
class TagBulkImportView(generic.BulkImportView): # 3.0 TODO: remove, unused
|
|
3050
|
-
queryset = Tag.objects.all()
|
|
3051
|
-
table = tables.TagTable
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
class TagBulkEditView(generic.BulkEditView):
|
|
3055
|
-
queryset = Tag.objects.annotate(items=count_related(TaggedItem, "tag"))
|
|
3056
|
-
table = tables.TagTable
|
|
3057
|
-
form = forms.TagBulkEditForm
|
|
3058
|
-
filterset = filters.TagFilterSet
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
class TagBulkDeleteView(generic.BulkDeleteView):
|
|
3062
|
-
queryset = Tag.objects.annotate(items=count_related(TaggedItem, "tag"))
|
|
3063
|
-
table = tables.TagTable
|
|
3064
|
-
filterset = filters.TagFilterSet
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
3022
|
#
|
|
3068
3023
|
# Teams
|
|
3069
3024
|
#
|
nautobot/ipam/models.py
CHANGED
|
@@ -200,6 +200,8 @@ class VRF(PrimaryModel):
|
|
|
200
200
|
instance.validated_save()
|
|
201
201
|
return instance
|
|
202
202
|
|
|
203
|
+
add_device.alters_data = True
|
|
204
|
+
|
|
203
205
|
def remove_device(self, device):
|
|
204
206
|
"""
|
|
205
207
|
Remove a `device` from this VRF.
|
|
@@ -213,6 +215,8 @@ class VRF(PrimaryModel):
|
|
|
213
215
|
instance = self.devices.through.objects.get(vrf=self, device=device)
|
|
214
216
|
return instance.delete()
|
|
215
217
|
|
|
218
|
+
remove_device.alters_data = True
|
|
219
|
+
|
|
216
220
|
def add_virtual_machine(self, virtual_machine, rd="", name=""):
|
|
217
221
|
"""
|
|
218
222
|
Add a `virtual_machine` to this VRF, optionally overloading `rd` and `name`.
|
|
@@ -231,6 +235,8 @@ class VRF(PrimaryModel):
|
|
|
231
235
|
instance.validated_save()
|
|
232
236
|
return instance
|
|
233
237
|
|
|
238
|
+
add_virtual_machine.alters_data = True
|
|
239
|
+
|
|
234
240
|
def remove_virtual_machine(self, virtual_machine):
|
|
235
241
|
"""
|
|
236
242
|
Remove a `virtual_machine` from this VRF.
|
|
@@ -244,6 +250,8 @@ class VRF(PrimaryModel):
|
|
|
244
250
|
instance = self.virtual_machines.through.objects.get(vrf=self, virtual_machine=virtual_machine)
|
|
245
251
|
return instance.delete()
|
|
246
252
|
|
|
253
|
+
remove_virtual_machine.alters_data = True
|
|
254
|
+
|
|
247
255
|
def add_virtual_device_context(self, virtual_device_context, rd="", name=""):
|
|
248
256
|
"""
|
|
249
257
|
Add a `virtual_device_context` to this VRF, optionally overloading `rd` and `name`.
|
|
@@ -264,6 +272,8 @@ class VRF(PrimaryModel):
|
|
|
264
272
|
instance.validated_save()
|
|
265
273
|
return instance
|
|
266
274
|
|
|
275
|
+
add_virtual_device_context.alters_data = True
|
|
276
|
+
|
|
267
277
|
def remove_virtual_device_context(self, virtual_device_context):
|
|
268
278
|
"""
|
|
269
279
|
Remove a `virtual_device_context` from this VRF.
|
|
@@ -279,6 +289,8 @@ class VRF(PrimaryModel):
|
|
|
279
289
|
)
|
|
280
290
|
return instance.delete()
|
|
281
291
|
|
|
292
|
+
remove_virtual_device_context.alters_data = True
|
|
293
|
+
|
|
282
294
|
def add_prefix(self, prefix):
|
|
283
295
|
"""
|
|
284
296
|
Add a `prefix` to this VRF. Each object must be in the same Namespace.
|
|
@@ -293,6 +305,8 @@ class VRF(PrimaryModel):
|
|
|
293
305
|
instance.validated_save()
|
|
294
306
|
return instance
|
|
295
307
|
|
|
308
|
+
add_prefix.alters_data = True
|
|
309
|
+
|
|
296
310
|
def remove_prefix(self, prefix):
|
|
297
311
|
"""
|
|
298
312
|
Remove a `prefix` from this VRF.
|
|
@@ -306,6 +320,8 @@ class VRF(PrimaryModel):
|
|
|
306
320
|
instance = self.prefixes.through.objects.get(vrf=self, prefix=prefix)
|
|
307
321
|
return instance.delete()
|
|
308
322
|
|
|
323
|
+
remove_prefix.alters_data = True
|
|
324
|
+
|
|
309
325
|
|
|
310
326
|
@extras_features("graphql")
|
|
311
327
|
class VRFDeviceAssignment(BaseModel):
|
|
@@ -374,6 +390,8 @@ class VRFDeviceAssignment(BaseModel):
|
|
|
374
390
|
"A VRFDeviceAssignment entry must be associated with a device, a virtual machine, or a virtual device context."
|
|
375
391
|
)
|
|
376
392
|
|
|
393
|
+
clean.alters_data = True
|
|
394
|
+
|
|
377
395
|
|
|
378
396
|
@extras_features("graphql")
|
|
379
397
|
class VRFPrefixAssignment(BaseModel):
|
|
@@ -640,6 +658,8 @@ class Prefix(PrimaryModel):
|
|
|
640
658
|
self.prefix_length = prefix.prefixlen
|
|
641
659
|
self.ip_version = prefix.version
|
|
642
660
|
|
|
661
|
+
_deconstruct_prefix.alters_data = True
|
|
662
|
+
|
|
643
663
|
def delete(self, *args, **kwargs):
|
|
644
664
|
"""
|
|
645
665
|
A Prefix with children will be impossible to delete and raise a `ProtectedError`.
|
|
@@ -705,6 +725,8 @@ class Prefix(PrimaryModel):
|
|
|
705
725
|
return parent
|
|
706
726
|
return None
|
|
707
727
|
|
|
728
|
+
get_parent.alters_data = True
|
|
729
|
+
|
|
708
730
|
def clean(self):
|
|
709
731
|
if self.prefix is not None: # missing network/prefix_length will be caught by super().clean()
|
|
710
732
|
# Clear host bits from prefix
|
|
@@ -716,6 +738,8 @@ class Prefix(PrimaryModel):
|
|
|
716
738
|
|
|
717
739
|
super().clean()
|
|
718
740
|
|
|
741
|
+
clean.alters_data = True
|
|
742
|
+
|
|
719
743
|
def save(self, *args, **kwargs):
|
|
720
744
|
self.clean()
|
|
721
745
|
|
|
@@ -821,6 +845,8 @@ class Prefix(PrimaryModel):
|
|
|
821
845
|
|
|
822
846
|
return query.update(parent=self)
|
|
823
847
|
|
|
848
|
+
reparent_subnets.alters_data = True
|
|
849
|
+
|
|
824
850
|
def reparent_ips(self):
|
|
825
851
|
"""Determine the list of child IPAddresses and set the parent to self."""
|
|
826
852
|
query = IPAddress.objects.select_for_update().filter(
|
|
@@ -832,6 +858,8 @@ class Prefix(PrimaryModel):
|
|
|
832
858
|
|
|
833
859
|
return query.update(parent=self)
|
|
834
860
|
|
|
861
|
+
reparent_ips.alters_data = True
|
|
862
|
+
|
|
835
863
|
def supernets(self, direct=False, include_self=False, for_update=False):
|
|
836
864
|
"""
|
|
837
865
|
Return supernets of this Prefix.
|
|
@@ -861,7 +889,7 @@ class Prefix(PrimaryModel):
|
|
|
861
889
|
prefix_length__lte=self.prefix_length,
|
|
862
890
|
network__lte=self.network,
|
|
863
891
|
broadcast__gte=self.broadcast,
|
|
864
|
-
|
|
892
|
+
namespace_id=self.namespace_id,
|
|
865
893
|
)
|
|
866
894
|
|
|
867
895
|
return supernets
|
|
@@ -893,7 +921,7 @@ class Prefix(PrimaryModel):
|
|
|
893
921
|
ip_version=self.ip_version,
|
|
894
922
|
network__gte=self.network,
|
|
895
923
|
broadcast__lte=self.broadcast,
|
|
896
|
-
|
|
924
|
+
namespace_id=self.namespace_id,
|
|
897
925
|
)
|
|
898
926
|
|
|
899
927
|
def is_child_node(self):
|
|
@@ -1065,6 +1093,17 @@ class Prefix(PrimaryModel):
|
|
|
1065
1093
|
For prefixes containing IP addresses and/or pools, pools are considered fully utilized while
|
|
1066
1094
|
only IP addresses that are not contained within pools are added to the utilization.
|
|
1067
1095
|
|
|
1096
|
+
It is recommended that when using this method you add the following prefetch to the queryset when dealing with
|
|
1097
|
+
multiple prefixes to ensure good performance:
|
|
1098
|
+
|
|
1099
|
+
```
|
|
1100
|
+
prefetch_related(
|
|
1101
|
+
Prefetch(
|
|
1102
|
+
"children", queryset=Prefix.objects.only("network", "prefix_length", "parent_id").order_by()
|
|
1103
|
+
)
|
|
1104
|
+
)
|
|
1105
|
+
```
|
|
1106
|
+
|
|
1068
1107
|
Returns:
|
|
1069
1108
|
UtilizationData (namedtuple): (numerator, denominator)
|
|
1070
1109
|
"""
|
|
@@ -1077,7 +1116,7 @@ class Prefix(PrimaryModel):
|
|
|
1077
1116
|
# change this when that is the case, see #3873 for historical context.
|
|
1078
1117
|
if self.type != choices.PrefixTypeChoices.TYPE_CONTAINER:
|
|
1079
1118
|
pool_ips = IPAddress.objects.filter(
|
|
1080
|
-
|
|
1119
|
+
parent__namespace_id=self.namespace_id,
|
|
1081
1120
|
ip_version=self.ip_version,
|
|
1082
1121
|
host__gte=self.network,
|
|
1083
1122
|
host__lte=self.broadcast,
|
|
@@ -1085,7 +1124,11 @@ class Prefix(PrimaryModel):
|
|
|
1085
1124
|
child_ips = netaddr.IPSet(pool_ips)
|
|
1086
1125
|
|
|
1087
1126
|
if self.type != choices.PrefixTypeChoices.TYPE_POOL:
|
|
1088
|
-
|
|
1127
|
+
# Using self.children.all over self.children.iterator (with chunk_size given or not) consistently shaves
|
|
1128
|
+
# off around 200 extra SQL queries and shows better performance.
|
|
1129
|
+
# Also note that this is meant to be used in conjunction with a Prefetch on an only query. This query is
|
|
1130
|
+
# performed in nautobot.ipam.tables.PrefixDetailTable.
|
|
1131
|
+
child_prefixes = netaddr.IPSet(p.prefix for p in self.children.all())
|
|
1089
1132
|
|
|
1090
1133
|
numerator_set = child_ips | child_prefixes
|
|
1091
1134
|
|
|
@@ -1228,6 +1271,8 @@ class IPAddress(PrimaryModel):
|
|
|
1228
1271
|
self.mask_length = address.prefixlen
|
|
1229
1272
|
self.ip_version = address.version
|
|
1230
1273
|
|
|
1274
|
+
_deconstruct_address.alters_data = True
|
|
1275
|
+
|
|
1231
1276
|
natural_key_field_names = ["parent__namespace", "host"]
|
|
1232
1277
|
|
|
1233
1278
|
def _get_closest_parent(self):
|
|
@@ -1289,6 +1334,8 @@ class IPAddress(PrimaryModel):
|
|
|
1289
1334
|
|
|
1290
1335
|
super().clean()
|
|
1291
1336
|
|
|
1337
|
+
clean.alters_data = True
|
|
1338
|
+
|
|
1292
1339
|
def save(self, *args, **kwargs):
|
|
1293
1340
|
self.clean() # MUST do data fixup as above
|
|
1294
1341
|
|
nautobot/ipam/tables.py
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
from django.db.models import Prefetch, QuerySet
|
|
1
2
|
from django.utils.safestring import mark_safe
|
|
2
3
|
import django_tables2 as tables
|
|
4
|
+
from django_tables2.data import TableData
|
|
5
|
+
from django_tables2.rows import BoundRows
|
|
3
6
|
from django_tables2.utils import Accessor
|
|
4
7
|
|
|
5
8
|
from nautobot.core.tables import (
|
|
@@ -47,7 +50,9 @@ UTILIZATION_GRAPH = """
|
|
|
47
50
|
# object: the base ancestor Prefix, in the case of PrefixDetailTable, else None
|
|
48
51
|
PREFIX_COPY_LINK = """
|
|
49
52
|
{% load helpers %}
|
|
53
|
+
{% if not table.hide_hierarchy_ui %}
|
|
50
54
|
{% tree_hierarchy_ui_representation record.ancestors.count|as_range table.hide_hierarchy_ui base_tree_depth|default:0 %}
|
|
55
|
+
{% endif %}
|
|
51
56
|
<span class="hover_copy">
|
|
52
57
|
<a href="\
|
|
53
58
|
{% if record.present_in_database %}\
|
|
@@ -418,6 +423,20 @@ class PrefixDetailTable(PrefixTable):
|
|
|
418
423
|
tenant = TenantColumn()
|
|
419
424
|
tags = TagColumn(url_name="ipam:prefix_list")
|
|
420
425
|
|
|
426
|
+
def __init__(self, *args, **kwargs):
|
|
427
|
+
super().__init__(*args, **kwargs)
|
|
428
|
+
# Conditionally prefetch children for the utilization calculation if that column is visible.
|
|
429
|
+
if self.columns["utilization"].visible and isinstance(self.data.data, QuerySet):
|
|
430
|
+
self.data = TableData.from_data(
|
|
431
|
+
self.data.data.prefetch_related(
|
|
432
|
+
Prefetch(
|
|
433
|
+
"children", queryset=Prefix.objects.only("network", "prefix_length", "parent_id").order_by()
|
|
434
|
+
)
|
|
435
|
+
)
|
|
436
|
+
)
|
|
437
|
+
self.data.set_table(self)
|
|
438
|
+
self.rows = BoundRows(data=self.data, table=self, pinned_data=self.pinned_data)
|
|
439
|
+
|
|
421
440
|
class Meta(PrefixTable.Meta):
|
|
422
441
|
fields = (
|
|
423
442
|
"pk",
|