nautobot 2.4.10__py3-none-any.whl → 2.4.12__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/circuits/templates/circuits/circuittermination_retrieve.html +1 -114
- nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +1 -1
- nautobot/circuits/views.py +76 -6
- nautobot/cloud/navigation.py +1 -1
- nautobot/cloud/tests/test_views.py +13 -1
- nautobot/cloud/views.py +39 -9
- 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/templates/components/panel/header_extra_content_table.html +12 -1
- nautobot/core/templates/components/panel/panel.html +4 -0
- nautobot/core/templates/generic/object_retrieve.html +2 -1
- nautobot/core/testing/mixins.py +19 -1
- nautobot/core/testing/views.py +104 -8
- nautobot/core/tests/test_jobs.py +20 -4
- nautobot/core/tests/test_utils.py +17 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +53 -2
- nautobot/core/ui/object_detail.py +5 -1
- nautobot/core/utils/lookup.py +4 -2
- nautobot/core/utils/module_loading.py +23 -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 +116 -0
- nautobot/dcim/filters/mixins.py +2 -1
- 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 +14 -0
- nautobot/dcim/models/device_components.py +13 -1
- nautobot/dcim/models/devices.py +72 -0
- nautobot/dcim/navigation.py +16 -0
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +50 -0
- nautobot/dcim/tables/devicetypes.py +35 -1
- nautobot/dcim/tables/template_code.py +2 -0
- nautobot/dcim/templates/dcim/controller/base.html +1 -9
- nautobot/dcim/templates/dcim/controller_retrieve.html +2 -83
- nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +2 -25
- 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/templates/dcim/virtualchassis.html +2 -51
- nautobot/dcim/templates/dcim/virtualchassis_add.html +2 -22
- nautobot/dcim/templates/dcim/virtualchassis_create.html +22 -0
- nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -93
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +51 -0
- nautobot/dcim/templates/dcim/virtualchassis_update.html +93 -0
- 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 +5 -80
- nautobot/dcim/views.py +584 -342
- nautobot/extras/api/views.py +9 -2
- nautobot/extras/datasources/git.py +9 -1
- nautobot/extras/forms/forms.py +9 -5
- nautobot/extras/jobs.py +4 -2
- nautobot/extras/jobs_ui.py +208 -0
- nautobot/extras/models/datasources.py +5 -8
- nautobot/extras/models/jobs.py +5 -0
- nautobot/extras/models/tags.py +4 -0
- nautobot/extras/plugins/__init__.py +3 -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/configcontext_format.html +6 -0
- nautobot/extras/templates/extras/job_detail.html +1 -326
- 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 +2 -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_filters.py +4 -4
- nautobot/extras/tests/test_jobs.py +23 -10
- nautobot/extras/tests/test_models.py +19 -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 +186 -178
- nautobot/ipam/models.py +19 -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 +33 -10
- nautobot/project-static/docs/apps/index.html +33 -10
- nautobot/project-static/docs/apps/nautobot-apps.html +33 -10
- nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js → bundle.56ea9cef.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js.map → bundle.56ea9cef.min.js.map} +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +122 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +33 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +33 -10
- nautobot/project-static/docs/development/apps/api/configuration-view.html +33 -10
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +33 -10
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +33 -10
- nautobot/project-static/docs/development/apps/api/models/global-search.html +33 -10
- nautobot/project-static/docs/development/apps/api/models/graphql.html +33 -10
- nautobot/project-static/docs/development/apps/api/models/index.html +33 -10
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +42 -10
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -11
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +33 -10
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +33 -10
- nautobot/project-static/docs/development/apps/api/prometheus.html +33 -10
- nautobot/project-static/docs/development/apps/api/setup.html +33 -10
- nautobot/project-static/docs/development/apps/api/testing.html +33 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +33 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +33 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +33 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +33 -10
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/base-template.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/index.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/notes.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +33 -10
- nautobot/project-static/docs/development/apps/api/views/urls.html +33 -10
- nautobot/project-static/docs/development/apps/index.html +33 -10
- nautobot/project-static/docs/development/apps/migration/code-updates.html +33 -10
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +33 -10
- nautobot/project-static/docs/development/apps/migration/from-v1.html +33 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +33 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +33 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +33 -10
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +33 -10
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +33 -10
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +33 -10
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +33 -10
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +33 -10
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +33 -10
- nautobot/project-static/docs/development/core/application-registry.html +33 -10
- nautobot/project-static/docs/development/core/best-practices.html +33 -10
- nautobot/project-static/docs/development/core/bootstrap-ui.html +33 -10
- nautobot/project-static/docs/development/core/caching.html +33 -10
- nautobot/project-static/docs/development/core/controllers.html +33 -10
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +33 -10
- nautobot/project-static/docs/development/core/generic-views.html +33 -10
- nautobot/project-static/docs/development/core/getting-started.html +33 -10
- nautobot/project-static/docs/development/core/homepage.html +33 -10
- nautobot/project-static/docs/development/core/index.html +33 -10
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +33 -10
- nautobot/project-static/docs/development/core/model-checklist.html +33 -10
- nautobot/project-static/docs/development/core/model-features.html +33 -10
- nautobot/project-static/docs/development/core/natural-keys.html +33 -10
- nautobot/project-static/docs/development/core/navigation-menu.html +33 -10
- nautobot/project-static/docs/development/core/release-checklist.html +33 -10
- nautobot/project-static/docs/development/core/role-internals.html +33 -10
- nautobot/project-static/docs/development/core/settings.html +33 -10
- nautobot/project-static/docs/development/core/style-guide.html +33 -10
- nautobot/project-static/docs/development/core/templates.html +33 -10
- nautobot/project-static/docs/development/core/testing.html +33 -10
- nautobot/project-static/docs/development/core/ui-component-framework.html +33 -10
- nautobot/project-static/docs/development/core/user-preferences.html +33 -10
- nautobot/project-static/docs/development/index.html +33 -10
- nautobot/project-static/docs/development/jobs/getting-started.html +33 -10
- nautobot/project-static/docs/development/jobs/index.html +33 -10
- nautobot/project-static/docs/development/jobs/installation.html +33 -10
- nautobot/project-static/docs/development/jobs/job-extensions.html +33 -10
- nautobot/project-static/docs/development/jobs/job-logging.html +33 -10
- nautobot/project-static/docs/development/jobs/job-patterns.html +33 -10
- nautobot/project-static/docs/development/jobs/job-structure.html +33 -10
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +33 -10
- nautobot/project-static/docs/development/jobs/testing.html +33 -10
- nautobot/project-static/docs/index.html +33 -10
- 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 +33 -10
- nautobot/project-static/docs/overview/design_philosophy.html +33 -10
- nautobot/project-static/docs/release-notes/index.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.0.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +33 -10
- nautobot/project-static/docs/release-notes/version-1.6.html +33 -10
- nautobot/project-static/docs/release-notes/version-2.0.html +33 -10
- nautobot/project-static/docs/release-notes/version-2.1.html +33 -10
- nautobot/project-static/docs/release-notes/version-2.2.html +33 -10
- nautobot/project-static/docs/release-notes/version-2.3.html +33 -10
- nautobot/project-static/docs/release-notes/version-2.4.html +363 -10
- nautobot/project-static/docs/requirements.txt +1 -1
- 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 +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +33 -10
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +33 -10
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/index.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +33 -10
- nautobot/project-static/docs/user-guide/administration/installation/services.html +33 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +33 -10
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +33 -10
- nautobot/project-static/docs/user-guide/administration/security/index.html +33 -10
- nautobot/project-static/docs/user-guide/administration/security/notices.html +33 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +33 -10
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +33 -10
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +45 -22
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +37 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +37 -10
- 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 +36 -13
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +33 -10
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -18
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +33 -10
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +33 -10
- nautobot/project-static/docs/user-guide/index.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +39 -11
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +33 -10
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +33 -10
- nautobot/tenancy/tables.py +2 -0
- nautobot/virtualization/tests/test_views.py +1 -1
- nautobot/wireless/forms.py +0 -1
- nautobot/wireless/models.py +1 -1
- nautobot/wireless/navigation.py +1 -1
- nautobot/wireless/tables.py +18 -3
- {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/METADATA +4 -4
- {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/RECORD +439 -419
- /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.10.dist-info → nautobot-2.4.12.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/NOTICE +0 -0
- {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/WHEEL +0 -0
- {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/entry_points.txt +0 -0
|
@@ -6,117 +6,4 @@
|
|
|
6
6
|
<li><a href="{% url 'circuits:circuit_list' %}?provider={{ object.circuit.provider.pk }}">{{ object.circuit.provider }}</a></li>
|
|
7
7
|
<li>{{ object.circuit|hyperlinked_object }}</li>
|
|
8
8
|
<li>{{ object|hyperlinked_object }}</li>
|
|
9
|
-
{% endblock breadcrumbs %}
|
|
10
|
-
|
|
11
|
-
{% block content_left_page %}
|
|
12
|
-
<div class="panel panel-default">
|
|
13
|
-
<table class="table table-hover panel-body attr-table">
|
|
14
|
-
<tr>
|
|
15
|
-
{% if object.location %}
|
|
16
|
-
<tr>
|
|
17
|
-
<td>Location</td>
|
|
18
|
-
<td>{% include 'dcim/inc/location_hierarchy.html' with location=object.location %}</td>
|
|
19
|
-
</tr>
|
|
20
|
-
{% endif %}
|
|
21
|
-
{% if object.provider_network %}
|
|
22
|
-
<td>Provider Network</td>
|
|
23
|
-
<td>
|
|
24
|
-
{{ object.provider_network|hyperlinked_object }}
|
|
25
|
-
</td>
|
|
26
|
-
{% endif %}
|
|
27
|
-
{% if object.cloud_network %}
|
|
28
|
-
<td>Cloud Network</td>
|
|
29
|
-
<td>
|
|
30
|
-
{{ object.cloud_network|hyperlinked_object }}
|
|
31
|
-
</td>
|
|
32
|
-
{% endif %}
|
|
33
|
-
</tr>
|
|
34
|
-
{% if object.location %}
|
|
35
|
-
<tr>
|
|
36
|
-
<td>Cable</td>
|
|
37
|
-
<td>
|
|
38
|
-
{% if object.cable %}
|
|
39
|
-
{% if perms.dcim.delete_cable %}
|
|
40
|
-
<div class="pull-right">
|
|
41
|
-
<a href="{% url 'dcim:cable_delete' pk=object.cable.pk %}?return_url={{ object.circuit.get_absolute_url }}" title="Remove cable" class="btn btn-danger btn-xs">
|
|
42
|
-
<i class="mdi mdi-ethernet-cable-off" aria-hidden="true"></i> Disconnect
|
|
43
|
-
</a>
|
|
44
|
-
</div>
|
|
45
|
-
{% endif %}
|
|
46
|
-
{{ object.cable|hyperlinked_object }}
|
|
47
|
-
<a href="{% url 'circuits:circuittermination_trace' pk=object.pk %}" class="btn btn-primary btn-xs" title="Trace">
|
|
48
|
-
<i class="mdi mdi-transit-connection-variant" aria-hidden="true"></i>
|
|
49
|
-
</a>
|
|
50
|
-
{% with peer=object.get_cable_peer %}
|
|
51
|
-
to
|
|
52
|
-
{% if peer.device %}
|
|
53
|
-
{{ peer.device|hyperlinked_object }}
|
|
54
|
-
{% elif peer.circuit %}
|
|
55
|
-
{{ peer.circuit|hyperlinked_object }}
|
|
56
|
-
{% endif %}
|
|
57
|
-
({{ peer }})
|
|
58
|
-
{% endwith %}
|
|
59
|
-
{% else %}
|
|
60
|
-
{% if perms.dcim.add_cable %}
|
|
61
|
-
<div class="pull-right">
|
|
62
|
-
<span class="dropdown">
|
|
63
|
-
<button type="button" class="btn btn-success btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
64
|
-
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
|
|
65
|
-
</button>
|
|
66
|
-
<ul class="dropdown-menu dropdown-menu-right">
|
|
67
|
-
<li><a href="{% url 'circuits:circuittermination_connect' termination_a_id=object.pk termination_b_type='interface' %}?termination_b_location={{ object.location.pk }}&return_url={{ object.get_absolute_url }}">Interface</a></li>
|
|
68
|
-
<li><a href="{% url 'circuits:circuittermination_connect' termination_a_id=object.pk termination_b_type='front-port' %}?termination_b_location={{ object.location.pk }}&return_url={{ object.get_absolute_url }}">Front Port</a></li>
|
|
69
|
-
<li><a href="{% url 'circuits:circuittermination_connect' termination_a_id=object.pk termination_b_type='rear-port' %}?termination_b_location={{ object.location.pk }}&return_url={{ object.get_absolute_url }}">Rear Port</a></li>
|
|
70
|
-
<li><a href="{% url 'circuits:circuittermination_connect' termination_a_id=object.pk termination_b_type='circuit-termination' %}?termination_b_location={{ object.location.pk }}&return_url={{ object.get_absolute_url }}">Circuit Termination</a></li>
|
|
71
|
-
</ul>
|
|
72
|
-
</span>
|
|
73
|
-
</div>
|
|
74
|
-
{% endif %}
|
|
75
|
-
<span class="text-muted">Not defined</span>
|
|
76
|
-
{% endif %}
|
|
77
|
-
</td>
|
|
78
|
-
</tr>
|
|
79
|
-
{% endif %}
|
|
80
|
-
<tr>
|
|
81
|
-
<td>Speed</td>
|
|
82
|
-
<td>
|
|
83
|
-
{% if object.port_speed and object.upstream_speed %}
|
|
84
|
-
<i class="mdi mdi-arrow-down-bold" title="Downstream"></i> {{ object.port_speed|humanize_speed }}
|
|
85
|
-
<i class="mdi mdi-arrow-up-bold" title="Upstream"></i> {{ object.upstream_speed|humanize_speed }}
|
|
86
|
-
{% elif object.port_speed %}
|
|
87
|
-
{{ object.port_speed|humanize_speed }}
|
|
88
|
-
{% else %}
|
|
89
|
-
<span class="text-muted">—</span>
|
|
90
|
-
{% endif %}
|
|
91
|
-
</td>
|
|
92
|
-
</tr>
|
|
93
|
-
<tr>
|
|
94
|
-
<td>IP Addressing</td>
|
|
95
|
-
<td>
|
|
96
|
-
{% if object.connected_endpoint %}
|
|
97
|
-
{% for ip in object.ip_addresses %}
|
|
98
|
-
{% if not forloop.first %}<br />{% endif %}
|
|
99
|
-
{{ ip|hyperlinked_object }} ({{ ip.vrf|default:"Global" }})
|
|
100
|
-
{% empty %}
|
|
101
|
-
<span class="text-muted">None</span>
|
|
102
|
-
{% endfor %}
|
|
103
|
-
{% else %}
|
|
104
|
-
<span class="text-muted">—</span>
|
|
105
|
-
{% endif %}
|
|
106
|
-
</td>
|
|
107
|
-
</tr>
|
|
108
|
-
<tr>
|
|
109
|
-
<td>Cross-Connect</td>
|
|
110
|
-
<td>{{ object.xconnect_id|placeholder }}</td>
|
|
111
|
-
</tr>
|
|
112
|
-
<tr>
|
|
113
|
-
<td>Patch Panel/Port</td>
|
|
114
|
-
<td>{{ object.pp_info|placeholder }}</td>
|
|
115
|
-
</tr>
|
|
116
|
-
<tr>
|
|
117
|
-
<td>Description</td>
|
|
118
|
-
<td>{{ object.description|placeholder }}</td>
|
|
119
|
-
</tr>
|
|
120
|
-
</table>
|
|
121
|
-
</div>
|
|
122
|
-
{% endblock content_left_page %}
|
|
9
|
+
{% endblock breadcrumbs %}
|
nautobot/circuits/views.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from django.contrib import messages
|
|
2
2
|
from django.db import transaction
|
|
3
3
|
from django.shortcuts import get_object_or_404, redirect, render
|
|
4
|
-
from django.utils.html import format_html
|
|
4
|
+
from django.utils.html import format_html, format_html_join
|
|
5
5
|
|
|
6
6
|
from nautobot.core.forms import ConfirmationForm
|
|
7
|
-
from nautobot.core.templatetags
|
|
7
|
+
from nautobot.core.templatetags import helpers
|
|
8
8
|
from nautobot.core.ui.choices import SectionChoices
|
|
9
9
|
from nautobot.core.ui.object_detail import (
|
|
10
10
|
ObjectDetailContent,
|
|
@@ -13,6 +13,7 @@ from nautobot.core.ui.object_detail import (
|
|
|
13
13
|
)
|
|
14
14
|
from nautobot.core.ui.utils import render_component_template
|
|
15
15
|
from nautobot.core.views import generic
|
|
16
|
+
from nautobot.core.views.utils import get_obj_from_context
|
|
16
17
|
from nautobot.core.views.viewsets import NautobotUIViewSet
|
|
17
18
|
|
|
18
19
|
from . import filters, forms, tables
|
|
@@ -50,6 +51,38 @@ class CircuitTypeUIViewSet(NautobotUIViewSet):
|
|
|
50
51
|
)
|
|
51
52
|
|
|
52
53
|
|
|
54
|
+
class CircuitTerminationObjectFieldsPanel(ObjectFieldsPanel):
|
|
55
|
+
def get_extra_context(self, context):
|
|
56
|
+
return {"termination": context["object"]}
|
|
57
|
+
|
|
58
|
+
def render_key(self, key, value, context):
|
|
59
|
+
if key == "connected_endpoint":
|
|
60
|
+
return "IP Addressing"
|
|
61
|
+
return super().render_key(key, value, context)
|
|
62
|
+
|
|
63
|
+
def render_value(self, key, value, context):
|
|
64
|
+
instance = get_obj_from_context(context, self.context_object_key)
|
|
65
|
+
location = getattr(instance, "location", None)
|
|
66
|
+
|
|
67
|
+
# Cable column is hidden if the location is unset
|
|
68
|
+
if not location and key == "cable":
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
if location and key == "cable":
|
|
72
|
+
return render_component_template("circuits/inc/circuit_termination_cable_fragment.html", context)
|
|
73
|
+
|
|
74
|
+
if key == "connected_endpoint":
|
|
75
|
+
ip_addresses = getattr(value, "ip_addresses", None)
|
|
76
|
+
if not ip_addresses or not ip_addresses.exists():
|
|
77
|
+
return helpers.HTML_NONE
|
|
78
|
+
return format_html_join(
|
|
79
|
+
", ",
|
|
80
|
+
"{} ({})",
|
|
81
|
+
((helpers.hyperlinked_object(ip), getattr(ip, "vrf", None) or "Global") for ip in ip_addresses.all()),
|
|
82
|
+
)
|
|
83
|
+
return super().render_value(key, value, context)
|
|
84
|
+
|
|
85
|
+
|
|
53
86
|
class CircuitTerminationUIViewSet(NautobotUIViewSet):
|
|
54
87
|
action_buttons = ("import", "export")
|
|
55
88
|
bulk_update_form_class = forms.CircuitTerminationBulkEditForm
|
|
@@ -60,6 +93,41 @@ class CircuitTerminationUIViewSet(NautobotUIViewSet):
|
|
|
60
93
|
serializer_class = serializers.CircuitTerminationSerializer
|
|
61
94
|
table_class = tables.CircuitTerminationTable
|
|
62
95
|
|
|
96
|
+
object_detail_content = ObjectDetailContent(
|
|
97
|
+
panels=(
|
|
98
|
+
CircuitTerminationObjectFieldsPanel(
|
|
99
|
+
section=SectionChoices.LEFT_HALF,
|
|
100
|
+
weight=100,
|
|
101
|
+
fields=[
|
|
102
|
+
"location",
|
|
103
|
+
"provider_network",
|
|
104
|
+
"cloud_network",
|
|
105
|
+
"cable",
|
|
106
|
+
"port_speed",
|
|
107
|
+
"upstream_speed",
|
|
108
|
+
"connected_endpoint",
|
|
109
|
+
"xconnect_id",
|
|
110
|
+
"pp_info",
|
|
111
|
+
"description",
|
|
112
|
+
],
|
|
113
|
+
hide_if_unset=[
|
|
114
|
+
"location",
|
|
115
|
+
"provider_network",
|
|
116
|
+
"cloud_network",
|
|
117
|
+
"port_speed",
|
|
118
|
+
"upstream_speed",
|
|
119
|
+
],
|
|
120
|
+
exclude_fields=[
|
|
121
|
+
"circuit",
|
|
122
|
+
],
|
|
123
|
+
value_transforms={
|
|
124
|
+
"port_speed": [helpers.humanize_speed],
|
|
125
|
+
"upstream_speed": [helpers.humanize_speed],
|
|
126
|
+
},
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
|
|
63
131
|
def get_object(self):
|
|
64
132
|
obj = super().get_object()
|
|
65
133
|
if self.action in ["create", "update"] and "circuit" in self.kwargs:
|
|
@@ -127,8 +195,8 @@ class CircuitUIViewSet(NautobotUIViewSet):
|
|
|
127
195
|
"description",
|
|
128
196
|
),
|
|
129
197
|
value_transforms={
|
|
130
|
-
"port_speed": [humanize_speed, placeholder],
|
|
131
|
-
"upstream_speed": [humanize_speed],
|
|
198
|
+
"port_speed": [helpers.humanize_speed, helpers.placeholder],
|
|
199
|
+
"upstream_speed": [helpers.humanize_speed],
|
|
132
200
|
},
|
|
133
201
|
hide_if_unset=("location", "provider_network", "cloud_network", "upstream_speed"),
|
|
134
202
|
ignore_nonexistent_fields=True, # ip_addresses may be undefined
|
|
@@ -173,8 +241,10 @@ class CircuitUIViewSet(NautobotUIViewSet):
|
|
|
173
241
|
'<span title="{} ({})">{}</span>',
|
|
174
242
|
relationship.label,
|
|
175
243
|
relationship.key,
|
|
176
|
-
bettertitle(relationship.get_label(side)),
|
|
244
|
+
helpers.bettertitle(relationship.get_label(side)),
|
|
177
245
|
)
|
|
246
|
+
if key == "ip_addresses":
|
|
247
|
+
return "IP Addressing"
|
|
178
248
|
return super().render_key(key, value, context)
|
|
179
249
|
|
|
180
250
|
def render_value(self, key, value, context):
|
|
@@ -209,7 +279,7 @@ class CircuitUIViewSet(NautobotUIViewSet):
|
|
|
209
279
|
weight=100,
|
|
210
280
|
fields="__all__",
|
|
211
281
|
exclude_fields=["comments", "circuit_termination_a", "circuit_termination_z"],
|
|
212
|
-
value_transforms={"commit_rate": [humanize_speed, placeholder]},
|
|
282
|
+
value_transforms={"commit_rate": [helpers.humanize_speed, helpers.placeholder]},
|
|
213
283
|
),
|
|
214
284
|
CircuitTerminationPanel(
|
|
215
285
|
label="Termination - A Side",
|
nautobot/cloud/navigation.py
CHANGED
|
@@ -34,7 +34,6 @@ class CloudAccountTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
34
34
|
"provider": providers[1].pk,
|
|
35
35
|
"secrets_group": secrets_groups[1].pk,
|
|
36
36
|
"description": "New description",
|
|
37
|
-
"comments": "New comments",
|
|
38
37
|
}
|
|
39
38
|
|
|
40
39
|
def test_post_without_secrets_group(self):
|
|
@@ -56,6 +55,12 @@ class CloudAccountTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
56
55
|
|
|
57
56
|
class CloudNetworkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
58
57
|
model = CloudNetwork
|
|
58
|
+
custom_action_required_permissions = {
|
|
59
|
+
"cloud:cloudnetwork_children": ["cloud.view_cloudnetwork"],
|
|
60
|
+
"cloud:cloudnetwork_prefixes": ["cloud.view_cloudnetwork", "ipam.view_prefix"],
|
|
61
|
+
"cloud:cloudnetwork_circuits": ["cloud.view_cloudnetwork", "circuits.view_circuit"],
|
|
62
|
+
"cloud:cloudnetwork_cloud_services": ["cloud.view_cloudnetwork", "cloud.view_cloudservice"],
|
|
63
|
+
}
|
|
59
64
|
|
|
60
65
|
@classmethod
|
|
61
66
|
def setUpTestData(cls):
|
|
@@ -104,6 +109,10 @@ class CloudNetworkTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
104
109
|
|
|
105
110
|
class CloudResourceTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
106
111
|
model = CloudResourceType
|
|
112
|
+
custom_action_required_permissions = {
|
|
113
|
+
"cloud:cloudresourcetype_services": ["cloud.view_cloudresourcetype", "cloud.view_cloudservice"],
|
|
114
|
+
"cloud:cloudresourcetype_networks": ["cloud.view_cloudresourcetype", "cloud.view_cloudnetwork"],
|
|
115
|
+
}
|
|
107
116
|
|
|
108
117
|
@classmethod
|
|
109
118
|
def setUpTestData(cls):
|
|
@@ -133,6 +142,9 @@ class CloudResourceTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
133
142
|
|
|
134
143
|
class CloudServiceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
135
144
|
model = CloudService
|
|
145
|
+
custom_action_required_permissions = {
|
|
146
|
+
"cloud:cloudservice_cloud_networks": ["cloud.view_cloudservice", "cloud.view_cloudnetwork"],
|
|
147
|
+
}
|
|
136
148
|
|
|
137
149
|
@classmethod
|
|
138
150
|
def setUpTestData(cls):
|
nautobot/cloud/views.py
CHANGED
|
@@ -64,7 +64,6 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
|
|
|
64
64
|
table_class = CloudNetworkTable
|
|
65
65
|
form_class = CloudNetworkForm
|
|
66
66
|
bulk_update_form_class = CloudNetworkBulkEditForm
|
|
67
|
-
|
|
68
67
|
object_detail_content = object_detail.ObjectDetailContent(
|
|
69
68
|
panels=(
|
|
70
69
|
object_detail.ObjectFieldsPanel(
|
|
@@ -153,19 +152,35 @@ class CloudNetworkUIViewSet(NautobotUIViewSet):
|
|
|
153
152
|
),
|
|
154
153
|
)
|
|
155
154
|
|
|
156
|
-
@action(detail=True, url_path="children")
|
|
155
|
+
@action(detail=True, url_path="children", custom_view_base_action="view")
|
|
157
156
|
def children(self, request, *args, **kwargs):
|
|
158
157
|
return Response({})
|
|
159
158
|
|
|
160
|
-
@action(
|
|
159
|
+
@action(
|
|
160
|
+
detail=True,
|
|
161
|
+
url_path="prefixes",
|
|
162
|
+
custom_view_base_action="view",
|
|
163
|
+
custom_view_additional_permissions=["ipam.view_prefix"],
|
|
164
|
+
)
|
|
161
165
|
def prefixes(self, request, *args, **kwargs):
|
|
162
166
|
return Response({})
|
|
163
167
|
|
|
164
|
-
@action(
|
|
168
|
+
@action(
|
|
169
|
+
detail=True,
|
|
170
|
+
url_path="circuits",
|
|
171
|
+
custom_view_base_action="view",
|
|
172
|
+
custom_view_additional_permissions=["circuits.view_circuit"],
|
|
173
|
+
)
|
|
165
174
|
def circuits(self, request, *args, **kwargs):
|
|
166
175
|
return Response({})
|
|
167
176
|
|
|
168
|
-
@action(
|
|
177
|
+
@action(
|
|
178
|
+
detail=True,
|
|
179
|
+
url_path="cloud-services",
|
|
180
|
+
url_name="cloud_services",
|
|
181
|
+
custom_view_base_action="view",
|
|
182
|
+
custom_view_additional_permissions=["cloud.view_cloudservice"],
|
|
183
|
+
)
|
|
169
184
|
def cloud_services(self, request, *args, **kwargs):
|
|
170
185
|
return Response({})
|
|
171
186
|
|
|
@@ -178,7 +193,6 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
|
|
|
178
193
|
table_class = CloudResourceTypeTable
|
|
179
194
|
form_class = CloudResourceTypeForm
|
|
180
195
|
bulk_update_form_class = CloudResourceTypeBulkEditForm
|
|
181
|
-
|
|
182
196
|
object_detail_content = object_detail.ObjectDetailContent(
|
|
183
197
|
panels=(
|
|
184
198
|
object_detail.ObjectFieldsPanel(
|
|
@@ -230,11 +244,21 @@ class CloudResourceTypeUIViewSet(NautobotUIViewSet):
|
|
|
230
244
|
),
|
|
231
245
|
)
|
|
232
246
|
|
|
233
|
-
@action(
|
|
247
|
+
@action(
|
|
248
|
+
detail=True,
|
|
249
|
+
url_path="networks",
|
|
250
|
+
custom_view_base_action="view",
|
|
251
|
+
custom_view_additional_permissions=["cloud.view_cloudnetwork"],
|
|
252
|
+
)
|
|
234
253
|
def networks(self, request, *args, **kwargs):
|
|
235
254
|
return Response({})
|
|
236
255
|
|
|
237
|
-
@action(
|
|
256
|
+
@action(
|
|
257
|
+
detail=True,
|
|
258
|
+
url_path="services",
|
|
259
|
+
custom_view_base_action="view",
|
|
260
|
+
custom_view_additional_permissions=["cloud.view_cloudservice"],
|
|
261
|
+
)
|
|
238
262
|
def services(self, request, *args, **kwargs):
|
|
239
263
|
return Response({})
|
|
240
264
|
|
|
@@ -284,6 +308,12 @@ class CloudServiceUIViewSet(NautobotUIViewSet):
|
|
|
284
308
|
),
|
|
285
309
|
)
|
|
286
310
|
|
|
287
|
-
@action(
|
|
311
|
+
@action(
|
|
312
|
+
detail=True,
|
|
313
|
+
url_path="cloud-networks",
|
|
314
|
+
url_name="cloud_networks",
|
|
315
|
+
custom_view_base_action="view",
|
|
316
|
+
custom_view_additional_permissions=["cloud.view_cloudnetwork"],
|
|
317
|
+
)
|
|
288
318
|
def cloud_networks(self, request, *args, **kwargs):
|
|
289
319
|
return Response({})
|
nautobot/core/celery/__init__.py
CHANGED
|
@@ -3,10 +3,12 @@ import logging
|
|
|
3
3
|
import os
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import shutil
|
|
6
|
+
import sys
|
|
6
7
|
|
|
7
8
|
from celery import Celery, shared_task, signals
|
|
8
9
|
from celery.app.log import TaskFormatter
|
|
9
10
|
from celery.utils.log import get_logger
|
|
11
|
+
from django.apps import apps
|
|
10
12
|
from django.conf import settings
|
|
11
13
|
from django.db.utils import OperationalError, ProgrammingError
|
|
12
14
|
from django.utils.functional import SimpleLazyObject
|
|
@@ -19,6 +21,7 @@ from nautobot.core.celery.control import discard_git_repository, refresh_git_rep
|
|
|
19
21
|
from nautobot.core.celery.encoders import NautobotKombuJSONEncoder
|
|
20
22
|
from nautobot.core.celery.log import NautobotDatabaseHandler
|
|
21
23
|
from nautobot.core.utils.module_loading import import_modules_privately
|
|
24
|
+
from nautobot.extras.plugins.utils import import_object
|
|
22
25
|
from nautobot.extras.registry import registry
|
|
23
26
|
|
|
24
27
|
logger = logging.getLogger(__name__)
|
|
@@ -47,12 +50,14 @@ app.autodiscover_tasks()
|
|
|
47
50
|
def import_jobs(sender=None, **kwargs):
|
|
48
51
|
"""
|
|
49
52
|
Import system Jobs into Nautobot as well as Jobs from JOBS_ROOT and GIT_ROOT.
|
|
53
|
+
Import app-provided jobs if the app provides dynamic jobs.
|
|
50
54
|
|
|
51
55
|
Note that app-provided jobs are automatically imported at startup time via NautobotAppConfig.ready()
|
|
52
56
|
"""
|
|
53
57
|
import nautobot.core.jobs # noqa: F401
|
|
54
58
|
|
|
55
59
|
_import_jobs_from_jobs_root()
|
|
60
|
+
_import_dynamic_jobs_from_apps()
|
|
56
61
|
|
|
57
62
|
try:
|
|
58
63
|
_import_jobs_from_git_repositories()
|
|
@@ -120,6 +125,22 @@ def _import_jobs_from_git_repositories():
|
|
|
120
125
|
refresh_git_repository(state=None, repository_pk=repo.pk, head=repo.current_head)
|
|
121
126
|
|
|
122
127
|
|
|
128
|
+
def _import_dynamic_jobs_from_apps():
|
|
129
|
+
for app_name in settings.PLUGINS:
|
|
130
|
+
app_config = apps.get_app_config(app_name)
|
|
131
|
+
if not getattr(app_config, "provides_dynamic_jobs", False):
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
# Unload job modules from sys.modules if they were previously loaded
|
|
135
|
+
app_jobs = getattr(app_config, "features", {}).get("jobs", [])
|
|
136
|
+
for job in app_jobs:
|
|
137
|
+
if job.__module__ in sys.modules:
|
|
138
|
+
del sys.modules[job.__module__]
|
|
139
|
+
|
|
140
|
+
# Load app jobs
|
|
141
|
+
app_config.features["jobs"] = import_object(f"{app_config.__module__}.{app_config.jobs}")
|
|
142
|
+
|
|
143
|
+
|
|
123
144
|
def add_nautobot_log_handler(logger_instance, log_format=None):
|
|
124
145
|
"""Add NautobotDatabaseHandler to logger and update logger level filtering to send all log levels to our handler."""
|
|
125
146
|
if any(isinstance(h, NautobotDatabaseHandler) for h in logger_instance.handlers):
|
nautobot/core/celery/encoders.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
from zoneinfo import ZoneInfo
|
|
2
3
|
|
|
3
4
|
from django.db import models
|
|
4
5
|
from rest_framework.utils.encoders import JSONEncoder
|
|
@@ -52,5 +53,7 @@ class NautobotKombuJSONEncoder(JSONEncoder):
|
|
|
52
53
|
# JobResult.result uses NautobotKombuJSONEncoder as an encoder and expects a JSONSerializable object,
|
|
53
54
|
# although an exception, such as a RuntimeException, can be supplied as the obj.
|
|
54
55
|
return f"{obj.__class__.__name__}: {obj}"
|
|
56
|
+
elif isinstance(obj, ZoneInfo):
|
|
57
|
+
return obj.key
|
|
55
58
|
else:
|
|
56
59
|
return super().default(obj)
|
nautobot/core/forms/forms.py
CHANGED
|
@@ -138,7 +138,10 @@ class BulkEditForm(forms.Form):
|
|
|
138
138
|
# Handle M2M Save
|
|
139
139
|
for key in self.cleaned_data.keys():
|
|
140
140
|
if key.startswith(("add_", "remove_")):
|
|
141
|
-
|
|
141
|
+
if key.startswith("add_"):
|
|
142
|
+
field_name = key.lstrip("add_")
|
|
143
|
+
else:
|
|
144
|
+
field_name = key.lstrip("remove_")
|
|
142
145
|
if field_name in m2m_field_names:
|
|
143
146
|
continue
|
|
144
147
|
with contextlib.suppress(FieldDoesNotExist):
|
|
@@ -96,12 +96,11 @@ class BulkEditObjects(Job):
|
|
|
96
96
|
model_field = None
|
|
97
97
|
|
|
98
98
|
# Handle nullification
|
|
99
|
-
if nullified_fields:
|
|
100
|
-
if
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
else
|
|
104
|
-
setattr(obj, field_name, None if model_field is not None and model_field.null else "")
|
|
99
|
+
if nullified_fields and field_name in nullified_fields and field_name in form.nullable_fields:
|
|
100
|
+
if isinstance(model_field, ManyToManyField):
|
|
101
|
+
getattr(obj, field_name).set([])
|
|
102
|
+
else:
|
|
103
|
+
setattr(obj, field_name, None if model_field is not None and model_field.null else "")
|
|
105
104
|
|
|
106
105
|
# ManyToManyFields
|
|
107
106
|
elif isinstance(model_field, ManyToManyField):
|
|
@@ -109,7 +108,8 @@ class BulkEditObjects(Job):
|
|
|
109
108
|
getattr(obj, field_name).set(form.cleaned_data[field_name])
|
|
110
109
|
# Normal fields
|
|
111
110
|
elif form.cleaned_data[field_name] not in (None, "", []):
|
|
112
|
-
|
|
111
|
+
if hasattr(obj, field_name):
|
|
112
|
+
setattr(obj, field_name, form.cleaned_data[field_name])
|
|
113
113
|
|
|
114
114
|
# Update custom fields
|
|
115
115
|
for field_name in form_custom_fields:
|
|
@@ -121,7 +121,7 @@ class BulkEditObjects(Job):
|
|
|
121
121
|
obj.full_clean()
|
|
122
122
|
obj.save()
|
|
123
123
|
updated_objects_pk.append(obj.pk)
|
|
124
|
-
form.post_save(obj)
|
|
124
|
+
form.post_save(obj) # handles M2M add_* and remove_* form fields
|
|
125
125
|
|
|
126
126
|
if hasattr(form, "save_relationships") and callable(form.save_relationships):
|
|
127
127
|
# Add/remove relationship associations
|
nautobot/core/jobs/cleanup.py
CHANGED
|
@@ -65,6 +65,17 @@ class LogsCleanup(Job):
|
|
|
65
65
|
related_model = related_object.related_model
|
|
66
66
|
related_field_name = related_object.field.name
|
|
67
67
|
cascade_queryset = related_model.objects.filter(**{f"{related_field_name}__id__in": queryset})
|
|
68
|
+
if cascade_queryset.exists():
|
|
69
|
+
self.recursive_delete_with_cascade(cascade_queryset, deletion_summary)
|
|
70
|
+
|
|
71
|
+
genericrelation_related_fields = [
|
|
72
|
+
field for field in queryset.model._meta.private_fields if hasattr(field, "bulk_related_objects")
|
|
73
|
+
]
|
|
74
|
+
for gr_related_field in genericrelation_related_fields:
|
|
75
|
+
related_model = gr_related_field.related_model
|
|
76
|
+
related_field_name = gr_related_field.related_query_name()
|
|
77
|
+
cascade_queryset = related_model.objects.filter(**{f"{related_field_name}__id__in": queryset})
|
|
78
|
+
if cascade_queryset.exists():
|
|
68
79
|
self.recursive_delete_with_cascade(cascade_queryset, deletion_summary)
|
|
69
80
|
|
|
70
81
|
deleted_count = queryset._raw_delete(using="default")
|
|
@@ -225,7 +225,8 @@ class Command(BaseCommand):
|
|
|
225
225
|
_create_batch(InterfaceTemplateFactory, 30)
|
|
226
226
|
_create_batch(PowerPortTemplateFactory, 30)
|
|
227
227
|
_create_batch(PowerOutletTemplateFactory, 30)
|
|
228
|
-
_create_batch(ModuleBayTemplateFactory,
|
|
228
|
+
_create_batch(ModuleBayTemplateFactory, 60, description="without module families", has_module_family=False)
|
|
229
|
+
_create_batch(ModuleBayTemplateFactory, 30, description="with module families", has_module_family=True)
|
|
229
230
|
_create_batch(ManufacturerFactory, 2, description="without Platforms or DeviceTypes") # Last 2 hard-coded
|
|
230
231
|
_create_batch(DeviceRedundancyGroupFactory, 20)
|
|
231
232
|
_create_batch(DeviceFactory, 20)
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
{% load helpers %}
|
|
2
2
|
|
|
3
|
-
<strong>{{ body_content_table_verbose_name_plural|bettertitle }}</strong>
|
|
3
|
+
<strong>{{ body_content_table_verbose_name_plural|bettertitle }}</strong>
|
|
4
|
+
{% if body_content_table_list_url %}
|
|
5
|
+
<a href="{{ body_content_table_list_url }}" class="badge badge-primary">{% if badge_count_override %}{{ badge_count_override }}{% else %}{{ body_content_table.rows|length }}{% endif %}</a>
|
|
6
|
+
{% endif %}
|
|
7
|
+
|
|
8
|
+
<div class="pull-right noprint">
|
|
9
|
+
{% if request.user.is_authenticated %}
|
|
10
|
+
{% table_config_button_small body_content_table %}
|
|
11
|
+
{% endif %}
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
{% table_config_form body_content_table %}
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<div class="col-md-6">
|
|
145
145
|
{% block content_left_page %}{% endblock content_left_page %}
|
|
146
146
|
{% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic custom_fields_advanced_ui=False computed_fields=object.get_computed_fields_grouping_basic computed_fields_advanced_ui=False %}
|
|
147
|
-
{% include 'inc/
|
|
147
|
+
{% include 'inc/relationships/panel_override.html' with relationships_fields_override=object.get_relationships_data_basic_fields %}
|
|
148
148
|
{% include 'extras/inc/tags_panel.html' %}
|
|
149
149
|
{% plugin_left_page object %}
|
|
150
150
|
</div>
|
|
@@ -363,4 +363,5 @@
|
|
|
363
363
|
}
|
|
364
364
|
});
|
|
365
365
|
</script>
|
|
366
|
+
<script src="{% versioned_static 'js/tableconfig.js' %}"></script>
|
|
366
367
|
{% endblock javascript %}
|
nautobot/core/testing/mixins.py
CHANGED
|
@@ -5,7 +5,7 @@ from django.apps import apps
|
|
|
5
5
|
from django.contrib.auth import get_user_model
|
|
6
6
|
from django.contrib.contenttypes.models import ContentType
|
|
7
7
|
from django.core.cache import cache
|
|
8
|
-
from django.core.exceptions import FieldDoesNotExist
|
|
8
|
+
from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
|
|
9
9
|
from django.db import connections, DEFAULT_DB_ALIAS
|
|
10
10
|
from django.db.models import JSONField, ManyToManyField, ManyToManyRel
|
|
11
11
|
from django.forms.models import model_to_dict
|
|
@@ -161,6 +161,24 @@ class NautobotTestCaseMixin:
|
|
|
161
161
|
obj_perm.users.add(self.user)
|
|
162
162
|
obj_perm.object_types.add(ct)
|
|
163
163
|
|
|
164
|
+
def remove_permissions(self, *names, **kwargs):
|
|
165
|
+
"""
|
|
166
|
+
Remove a set of permissions. Accepts permission names in the form <app>.<action>_<model>.
|
|
167
|
+
Additional keyword arguments will be passed to the ObjectPermission constructor to allow creating more detailed permissions.
|
|
168
|
+
|
|
169
|
+
Examples:
|
|
170
|
+
>>> remove_permissions("ipam.add_vlangroup", "ipam.view_vlangroup")
|
|
171
|
+
>>> remove_permissions("ipam.add_vlangroup", "ipam.view_vlangroup", constraints={"pk": "uuid-1234"})
|
|
172
|
+
"""
|
|
173
|
+
for name in names:
|
|
174
|
+
_, action, _ = permissions.resolve_permission(name)
|
|
175
|
+
try:
|
|
176
|
+
obj_perm = users_models.ObjectPermission.objects.get(name=name, actions=[action], **kwargs)
|
|
177
|
+
obj_perm.delete()
|
|
178
|
+
except ObjectDoesNotExist:
|
|
179
|
+
# Permission does not exist, so nothing to remove
|
|
180
|
+
pass
|
|
181
|
+
|
|
164
182
|
#
|
|
165
183
|
# Custom assertions
|
|
166
184
|
#
|