nautobot 2.4.11__py3-none-any.whl → 2.4.13__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/core/jobs/cleanup.py +4 -4
- 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 +1 -0
- nautobot/core/templates/inc/footer.html +4 -4
- nautobot/core/tests/test_utils.py +1 -177
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/ui/object_detail.py +1 -1
- nautobot/core/utils/module_loading.py +58 -63
- nautobot/dcim/filters/__init__.py +6 -0
- nautobot/dcim/filters/mixins.py +2 -1
- nautobot/dcim/migrations/0071_alter_consoleport_options_and_more.py +42 -0
- nautobot/dcim/models/device_components.py +10 -2
- nautobot/dcim/models/devices.py +28 -0
- nautobot/dcim/tables/devices.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/device.html +1 -34
- nautobot/dcim/templates/dcim/rack_elevation_list.html +4 -1
- 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_models.py +1 -0
- nautobot/dcim/urls.py +2 -59
- nautobot/dcim/views.py +180 -191
- nautobot/extras/datasources/git.py +2 -2
- nautobot/extras/jobs_ui.py +208 -0
- nautobot/extras/models/tags.py +4 -0
- nautobot/extras/tables.py +1 -1
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +2 -2
- nautobot/extras/templates/extras/inc/configcontext_data.html +1 -1
- nautobot/extras/templates/extras/inc/configcontext_format.html +6 -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_detail.html +1 -326
- nautobot/extras/templates/extras/tag_retrieve.html +1 -51
- nautobot/extras/views.py +83 -29
- nautobot/ipam/migrations/0052_alter_ipaddress_index_together_and_more.py +28 -0
- nautobot/ipam/models.py +13 -1
- nautobot/ipam/tests/test_api.py +1 -3
- nautobot/ipam/utils/testing.py +76 -29
- nautobot/project-static/docs/404.html +2 -2
- nautobot/project-static/docs/apps/index.html +2 -2
- nautobot/project-static/docs/apps/nautobot-apps.html +2 -2
- 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 +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2 -2
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +4 -2
- nautobot/project-static/docs/development/apps/api/configuration-view.html +2 -2
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/global-search.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/graphql.html +2 -2
- nautobot/project-static/docs/development/apps/api/models/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +2 -2
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +2 -2
- nautobot/project-static/docs/development/apps/api/prometheus.html +2 -2
- nautobot/project-static/docs/development/apps/api/setup.html +2 -2
- nautobot/project-static/docs/development/apps/api/testing.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +2 -2
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/base-template.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/index.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/notes.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +2 -2
- nautobot/project-static/docs/development/apps/api/views/urls.html +2 -2
- nautobot/project-static/docs/development/apps/index.html +2 -2
- nautobot/project-static/docs/development/apps/migration/code-updates.html +2 -2
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +2 -2
- nautobot/project-static/docs/development/apps/migration/from-v1.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +2 -2
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +2 -2
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +2 -2
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +2 -2
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +2 -2
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +2 -2
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +2 -2
- nautobot/project-static/docs/development/core/application-registry.html +2 -2
- nautobot/project-static/docs/development/core/best-practices.html +2 -2
- nautobot/project-static/docs/development/core/bootstrap-ui.html +2 -2
- nautobot/project-static/docs/development/core/caching.html +2 -2
- nautobot/project-static/docs/development/core/controllers.html +2 -2
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +2 -2
- nautobot/project-static/docs/development/core/generic-views.html +2 -2
- nautobot/project-static/docs/development/core/getting-started.html +2 -2
- nautobot/project-static/docs/development/core/homepage.html +2 -2
- nautobot/project-static/docs/development/core/index.html +2 -2
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +2 -2
- nautobot/project-static/docs/development/core/model-checklist.html +2 -2
- nautobot/project-static/docs/development/core/model-features.html +2 -2
- nautobot/project-static/docs/development/core/natural-keys.html +2 -2
- nautobot/project-static/docs/development/core/navigation-menu.html +2 -2
- nautobot/project-static/docs/development/core/release-checklist.html +2 -2
- nautobot/project-static/docs/development/core/role-internals.html +2 -2
- nautobot/project-static/docs/development/core/settings.html +2 -2
- nautobot/project-static/docs/development/core/style-guide.html +2 -2
- nautobot/project-static/docs/development/core/templates.html +2 -2
- nautobot/project-static/docs/development/core/testing.html +2 -2
- nautobot/project-static/docs/development/core/ui-component-framework.html +2 -2
- nautobot/project-static/docs/development/core/user-preferences.html +2 -2
- nautobot/project-static/docs/development/index.html +2 -2
- nautobot/project-static/docs/development/jobs/getting-started.html +2 -6
- nautobot/project-static/docs/development/jobs/index.html +2 -2
- nautobot/project-static/docs/development/jobs/installation.html +2 -2
- nautobot/project-static/docs/development/jobs/job-extensions.html +2 -2
- nautobot/project-static/docs/development/jobs/job-logging.html +2 -2
- nautobot/project-static/docs/development/jobs/job-patterns.html +2 -2
- nautobot/project-static/docs/development/jobs/job-structure.html +2 -2
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +2 -2
- nautobot/project-static/docs/development/jobs/testing.html +2 -2
- nautobot/project-static/docs/index.html +2 -2
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +2 -2
- nautobot/project-static/docs/overview/design_philosophy.html +2 -2
- nautobot/project-static/docs/release-notes/index.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.0.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.1.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.2.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.3.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.4.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.5.html +2 -2
- nautobot/project-static/docs/release-notes/version-1.6.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.0.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.1.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.2.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.3.html +2 -2
- nautobot/project-static/docs/release-notes/version-2.4.html +211 -2
- nautobot/project-static/docs/requirements.txt +1 -1
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +299 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +2 -2
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +2 -2
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +2 -2
- nautobot/project-static/docs/user-guide/administration/installation/services.html +2 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +2 -2
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +2 -2
- nautobot/project-static/docs/user-guide/administration/security/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/security/notices.html +2 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +2 -2
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +2 -2
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +2 -2
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +3 -3
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +2 -2
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +2 -2
- nautobot/project-static/docs/user-guide/index.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +2 -2
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +2 -2
- nautobot/wireless/navigation.py +1 -1
- nautobot/wireless/tables.py +13 -5
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/METADATA +1 -1
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/RECORD +364 -357
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/NOTICE +0 -0
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/WHEEL +0 -0
- {nautobot-2.4.11.dist-info → nautobot-2.4.13.dist-info}/entry_points.txt +0 -0
|
@@ -1,13 +1,30 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
1
|
+
from contextlib import contextmanager
|
|
2
|
+
import importlib
|
|
3
|
+
from importlib.util import find_spec, module_from_spec
|
|
3
4
|
from keyword import iskeyword
|
|
4
5
|
import logging
|
|
6
|
+
import os
|
|
5
7
|
import pkgutil
|
|
6
8
|
import sys
|
|
7
9
|
|
|
8
10
|
logger = logging.getLogger(__name__)
|
|
9
11
|
|
|
10
12
|
|
|
13
|
+
@contextmanager
|
|
14
|
+
def _temporarily_add_to_sys_path(path):
|
|
15
|
+
"""
|
|
16
|
+
Allow loading of modules and packages from within the provided directory by temporarily modifying `sys.path`.
|
|
17
|
+
|
|
18
|
+
On exit, it restores the original `sys.path` value.
|
|
19
|
+
"""
|
|
20
|
+
old_sys_path = sys.path.copy()
|
|
21
|
+
sys.path.insert(0, path)
|
|
22
|
+
try:
|
|
23
|
+
yield
|
|
24
|
+
finally:
|
|
25
|
+
sys.path = old_sys_path
|
|
26
|
+
|
|
27
|
+
|
|
11
28
|
def clear_module_from_sys_modules(module_name):
|
|
12
29
|
"""
|
|
13
30
|
Remove the module and all its submodules from sys.modules.
|
|
@@ -39,7 +56,7 @@ def check_name_safe_to_import_privately(name: str) -> tuple[bool, str]:
|
|
|
39
56
|
return True, "a valid and non-conflicting module name"
|
|
40
57
|
|
|
41
58
|
|
|
42
|
-
def import_modules_privately(path, module_path=None,
|
|
59
|
+
def import_modules_privately(path, module_path=None, ignore_import_errors=True):
|
|
43
60
|
"""
|
|
44
61
|
Import modules from the filesystem without adding the path permanently to `sys.path`.
|
|
45
62
|
|
|
@@ -55,71 +72,49 @@ def import_modules_privately(path, module_path=None, module_prefix="", ignore_im
|
|
|
55
72
|
ignore_import_errors (bool): Exceptions raised while importing modules will be caught and logged.
|
|
56
73
|
If this is set as False, they will then be re-raised to be handled by the caller of this function.
|
|
57
74
|
"""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
# whether or not we actually want to do so. So instead, for the case where a module_path is provided, we need to
|
|
62
|
-
# iteratively import each submodule ourselves.
|
|
63
|
-
if module_path:
|
|
64
|
-
# Git repository case - e.g. import_modules_privately(settings.GIT_ROOT, module_path=[repository_slug, "jobs"])
|
|
65
|
-
# Here we want to ONLY auto-load the module sequence identified by module_path.
|
|
66
|
-
permitted, reason = check_name_safe_to_import_privately(module_path[0])
|
|
67
|
-
if not permitted:
|
|
68
|
-
logger.error("Unable to load module %r from %s as it is %s", module_path[0], path, reason)
|
|
69
|
-
else:
|
|
70
|
-
module = None
|
|
71
|
-
module_name = module_path.pop(0)
|
|
72
|
-
submodule_name = module_name
|
|
73
|
-
try:
|
|
74
|
-
while True:
|
|
75
|
-
finder = FileFinder(path, (SourceFileLoader, SOURCE_SUFFIXES))
|
|
76
|
-
finder.invalidate_caches()
|
|
77
|
-
spec = finder.find_spec(module_name)
|
|
78
|
-
if spec is None or spec.loader is None:
|
|
79
|
-
logger.error("Unable to find module spec and/or loader for %r", submodule_name)
|
|
80
|
-
break
|
|
81
|
-
spec.name = submodule_name
|
|
82
|
-
spec.loader.name = submodule_name
|
|
83
|
-
submodule = module_from_spec(spec)
|
|
84
|
-
sys.modules[submodule_name] = submodule
|
|
85
|
-
spec.loader.exec_module(submodule)
|
|
86
|
-
if module is not None:
|
|
87
|
-
setattr(module, module_name, submodule)
|
|
88
|
-
module = submodule
|
|
89
|
-
loaded_modules.append(module)
|
|
90
|
-
if module_path:
|
|
91
|
-
submodule_name = f"{module_name}.{module_path[0]}"
|
|
92
|
-
module_name = module_path.pop(0)
|
|
93
|
-
path = module.__path__[0]
|
|
94
|
-
else:
|
|
95
|
-
break
|
|
96
|
-
except Exception as exc:
|
|
97
|
-
logger.error("Unable to load module %s from %s: %s", module_name, path, exc)
|
|
98
|
-
if not ignore_import_errors:
|
|
99
|
-
raise
|
|
75
|
+
if module_path is None:
|
|
76
|
+
module_path = []
|
|
77
|
+
module_prefix = None
|
|
100
78
|
else:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
for finder, discovered_module_name,
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
79
|
+
module_prefix = ".".join(module_path)
|
|
80
|
+
with _temporarily_add_to_sys_path(path):
|
|
81
|
+
for finder, discovered_module_name, is_package in pkgutil.walk_packages([path], onerror=logger.error):
|
|
82
|
+
if module_prefix and not (
|
|
83
|
+
module_prefix.startswith(f"{discovered_module_name}.") # my_repo/__init__.py
|
|
84
|
+
or discovered_module_name == module_prefix # my_repo/jobs.py
|
|
85
|
+
or discovered_module_name.startswith(f"{module_prefix}.") # my_repo/jobs/foobar.py
|
|
86
|
+
):
|
|
107
87
|
continue
|
|
108
|
-
module_name = discovered_module_name
|
|
109
|
-
if module_name in sys.modules:
|
|
110
|
-
clear_module_from_sys_modules(module_name)
|
|
111
|
-
|
|
112
88
|
try:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
89
|
+
existing_module = find_spec(discovered_module_name)
|
|
90
|
+
except (ModuleNotFoundError, ValueError):
|
|
91
|
+
existing_module = None
|
|
92
|
+
if existing_module is not None:
|
|
93
|
+
existing_module_path = os.path.realpath(existing_module.origin)
|
|
94
|
+
if not existing_module_path.startswith(path):
|
|
95
|
+
logger.error(
|
|
96
|
+
"Unable to load module %s from %s as it conflicts with existing module %s",
|
|
97
|
+
discovered_module_name,
|
|
98
|
+
path,
|
|
99
|
+
existing_module_path,
|
|
100
|
+
)
|
|
116
101
|
continue
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
102
|
+
|
|
103
|
+
if discovered_module_name in sys.modules:
|
|
104
|
+
clear_module_from_sys_modules(discovered_module_name)
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
if not is_package:
|
|
108
|
+
spec = finder.find_spec(discovered_module_name)
|
|
109
|
+
if spec is None:
|
|
110
|
+
raise ValueError("Unable to find module spec")
|
|
111
|
+
module = module_from_spec(spec)
|
|
112
|
+
sys.modules[discovered_module_name] = module
|
|
113
|
+
spec.loader.exec_module(module)
|
|
114
|
+
else:
|
|
115
|
+
module = importlib.import_module(discovered_module_name)
|
|
116
|
+
importlib.reload(module)
|
|
121
117
|
except Exception as exc:
|
|
122
118
|
logger.error("Unable to load module %s from %s: %s", discovered_module_name, path, exc)
|
|
123
119
|
if not ignore_import_errors:
|
|
124
120
|
raise
|
|
125
|
-
return loaded_modules
|
|
@@ -961,6 +961,12 @@ class DeviceFilterSet(
|
|
|
961
961
|
field_name="controller_managed_device_group__wireless_networks",
|
|
962
962
|
label="Has wireless networks",
|
|
963
963
|
)
|
|
964
|
+
controller = NaturalKeyOrPKMultipleChoiceFilter(
|
|
965
|
+
field_name="controller_managed_device_group__controller",
|
|
966
|
+
queryset=Controller.objects.all(),
|
|
967
|
+
to_field_name="name",
|
|
968
|
+
label="Controller (name or ID)",
|
|
969
|
+
)
|
|
964
970
|
|
|
965
971
|
def filter_ip_addresses(self, queryset, name, value):
|
|
966
972
|
pk_values = set(item for item in value if is_uuid(item))
|
nautobot/dcim/filters/mixins.py
CHANGED
|
@@ -39,6 +39,7 @@ from nautobot.dcim.models import (
|
|
|
39
39
|
RearPortTemplate,
|
|
40
40
|
)
|
|
41
41
|
from nautobot.extras.filters import CustomFieldModelFilterSetMixin
|
|
42
|
+
from nautobot.extras.filters.mixins import RelationshipModelFilterSetMixin
|
|
42
43
|
|
|
43
44
|
|
|
44
45
|
class CableTerminationModelFilterSetMixin(django_filters.FilterSet):
|
|
@@ -101,7 +102,7 @@ class DeviceComponentModelFilterSetMixin(CustomFieldModelFilterSetMixin):
|
|
|
101
102
|
)
|
|
102
103
|
|
|
103
104
|
|
|
104
|
-
class ModularDeviceComponentModelFilterSetMixin(DeviceComponentModelFilterSetMixin):
|
|
105
|
+
class ModularDeviceComponentModelFilterSetMixin(DeviceComponentModelFilterSetMixin, RelationshipModelFilterSetMixin):
|
|
105
106
|
module = NaturalKeyOrPKMultipleChoiceFilter(
|
|
106
107
|
queryset=Module.objects.all(),
|
|
107
108
|
to_field_name="module_type__model",
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Generated by Django 4.2.20 on 2025-07-17 20:24
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
import nautobot.core.models.query_functions
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Migration(migrations.Migration):
|
|
9
|
+
dependencies = [
|
|
10
|
+
("dcim", "0070_modulefamily_models"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AlterModelOptions(
|
|
15
|
+
name="consoleport",
|
|
16
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
17
|
+
),
|
|
18
|
+
migrations.AlterModelOptions(
|
|
19
|
+
name="consoleserverport",
|
|
20
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
21
|
+
),
|
|
22
|
+
migrations.AlterModelOptions(
|
|
23
|
+
name="frontport",
|
|
24
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
25
|
+
),
|
|
26
|
+
migrations.AlterModelOptions(
|
|
27
|
+
name="interface",
|
|
28
|
+
options={"ordering": ("device", "module__id", nautobot.core.models.query_functions.CollateAsChar("_name"))},
|
|
29
|
+
),
|
|
30
|
+
migrations.AlterModelOptions(
|
|
31
|
+
name="poweroutlet",
|
|
32
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
33
|
+
),
|
|
34
|
+
migrations.AlterModelOptions(
|
|
35
|
+
name="powerport",
|
|
36
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
37
|
+
),
|
|
38
|
+
migrations.AlterModelOptions(
|
|
39
|
+
name="rearport",
|
|
40
|
+
options={"ordering": ("device", "module__id", "_name")},
|
|
41
|
+
),
|
|
42
|
+
]
|
|
@@ -2,6 +2,7 @@ import re
|
|
|
2
2
|
|
|
3
3
|
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
|
+
from django.core.cache import cache
|
|
5
6
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
6
7
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
7
8
|
from django.db import models, transaction
|
|
@@ -123,7 +124,7 @@ class ModularComponentModel(ComponentModel):
|
|
|
123
124
|
|
|
124
125
|
class Meta:
|
|
125
126
|
abstract = True
|
|
126
|
-
ordering = ("device", "
|
|
127
|
+
ordering = ("device", "module__id", "_name") # Module.ordering is complex/expensive so don't order by module
|
|
127
128
|
constraints = [
|
|
128
129
|
models.UniqueConstraint(
|
|
129
130
|
fields=("device", "name"),
|
|
@@ -646,7 +647,7 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
|
|
|
646
647
|
)
|
|
647
648
|
|
|
648
649
|
class Meta(ModularComponentModel.Meta):
|
|
649
|
-
ordering = ("device", "
|
|
650
|
+
ordering = ("device", "module__id", CollateAsChar("_name")) # Module.ordering is complex; don't order by module
|
|
650
651
|
|
|
651
652
|
def clean(self):
|
|
652
653
|
super().clean()
|
|
@@ -1311,3 +1312,10 @@ class ModuleBay(PrimaryModel):
|
|
|
1311
1312
|
self.position = self.name
|
|
1312
1313
|
|
|
1313
1314
|
clean.alters_data = True
|
|
1315
|
+
|
|
1316
|
+
def save(self, *args, **kwargs):
|
|
1317
|
+
super().save(*args, **kwargs)
|
|
1318
|
+
|
|
1319
|
+
if self.parent_device is not None:
|
|
1320
|
+
# Set the has_module_bays cache key on the parent device - see Device.has_module_bays()
|
|
1321
|
+
cache.set(f"nautobot.dcim.device.{self.parent_device.pk}.has_module_bays", True, timeout=5)
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -2,6 +2,7 @@ from collections import OrderedDict
|
|
|
2
2
|
|
|
3
3
|
from django.contrib.contenttypes.fields import GenericRelation
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
|
+
from django.core.cache import cache
|
|
5
6
|
from django.core.exceptions import ValidationError
|
|
6
7
|
from django.core.serializers.json import DjangoJSONEncoder
|
|
7
8
|
from django.core.validators import MaxValueValidator, MinValueValidator
|
|
@@ -30,6 +31,7 @@ from nautobot.dcim.utils import get_all_network_driver_mappings, get_network_dri
|
|
|
30
31
|
from nautobot.extras.models import ChangeLoggedModel, ConfigContextModel, RoleField, StatusField
|
|
31
32
|
from nautobot.extras.querysets import ConfigContextModelQuerySet
|
|
32
33
|
from nautobot.extras.utils import extras_features
|
|
34
|
+
from nautobot.wireless.models import ControllerManagedDeviceGroupWirelessNetworkAssignment
|
|
33
35
|
|
|
34
36
|
from .device_components import (
|
|
35
37
|
ConsolePort,
|
|
@@ -895,6 +897,8 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
895
897
|
instantiated_components = []
|
|
896
898
|
for model, templates in component_models:
|
|
897
899
|
model.objects.bulk_create([x.instantiate(device=self) for x in templates])
|
|
900
|
+
cache_key = f"nautobot.dcim.device.{self.pk}.has_module_bays"
|
|
901
|
+
cache.delete(cache_key)
|
|
898
902
|
return instantiated_components
|
|
899
903
|
|
|
900
904
|
create_components.alters_data = True
|
|
@@ -987,6 +991,18 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
987
991
|
"""
|
|
988
992
|
return Device.objects.filter(parent_bay__device=self.pk)
|
|
989
993
|
|
|
994
|
+
@property
|
|
995
|
+
def has_module_bays(self) -> bool:
|
|
996
|
+
"""
|
|
997
|
+
Cacheable property for determining whether this Device has any ModuleBays, and therefore may contain Modules.
|
|
998
|
+
"""
|
|
999
|
+
cache_key = f"nautobot.dcim.device.{self.pk}.has_module_bays"
|
|
1000
|
+
module_bays_exists = cache.get(cache_key)
|
|
1001
|
+
if module_bays_exists is None:
|
|
1002
|
+
module_bays_exists = self.module_bays.exists()
|
|
1003
|
+
cache.set(cache_key, module_bays_exists, timeout=5)
|
|
1004
|
+
return module_bays_exists
|
|
1005
|
+
|
|
990
1006
|
@property
|
|
991
1007
|
def all_modules(self):
|
|
992
1008
|
"""
|
|
@@ -997,6 +1013,9 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
997
1013
|
# We artificially limit the recursion to 4 levels or we would be stuck in an infinite loop.
|
|
998
1014
|
recursion_depth = MODULE_RECURSION_DEPTH_LIMIT
|
|
999
1015
|
qs = Module.objects.all()
|
|
1016
|
+
if not self.has_module_bays:
|
|
1017
|
+
# Short-circuit to avoid an expensive nested query
|
|
1018
|
+
return qs.none()
|
|
1000
1019
|
query = Q()
|
|
1001
1020
|
for level in range(recursion_depth):
|
|
1002
1021
|
recursive_query = "parent_module_bay__parent_module__" * level
|
|
@@ -1456,6 +1475,15 @@ class Controller(PrimaryModel):
|
|
|
1456
1475
|
return format_html('<span class="text-muted">—</span>')
|
|
1457
1476
|
return format_html_join(" ", '<span class="label label-default">{}</span>', ((v,) for v in self.capabilities))
|
|
1458
1477
|
|
|
1478
|
+
@property
|
|
1479
|
+
def wireless_network_assignments(self):
|
|
1480
|
+
"""
|
|
1481
|
+
Returns all Controller Managed Device Group Wireless Network Assignment linked to this controller.
|
|
1482
|
+
"""
|
|
1483
|
+
return ControllerManagedDeviceGroupWirelessNetworkAssignment.objects.filter(
|
|
1484
|
+
controller_managed_device_group__controller=self
|
|
1485
|
+
)
|
|
1486
|
+
|
|
1459
1487
|
|
|
1460
1488
|
@extras_features(
|
|
1461
1489
|
"custom_links",
|
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -181,6 +181,7 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
181
181
|
software_version = tables.Column(linkify=True, verbose_name="Software Version")
|
|
182
182
|
secrets_group = tables.Column(linkify=True)
|
|
183
183
|
capabilities = tables.Column(orderable=False, accessor="controller_managed_device_group.capabilities")
|
|
184
|
+
manufacturer = tables.Column(orderable=False, accessor="device_type.manufacturer")
|
|
184
185
|
tags = TagColumn(url_name="dcim:device_list")
|
|
185
186
|
actions = ButtonsColumn(Device)
|
|
186
187
|
|
|
@@ -213,6 +214,7 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
213
214
|
"controller_managed_device_group",
|
|
214
215
|
"secrets_group",
|
|
215
216
|
"capabilities",
|
|
217
|
+
"manufacturer",
|
|
216
218
|
"tags",
|
|
217
219
|
"actions",
|
|
218
220
|
)
|
|
@@ -1,10 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block extra_nav_tabs %}
|
|
5
|
-
{% if 'wireless' in object.capabilities %}
|
|
6
|
-
<li role="presentation" {% if active_tab == 'wireless-networks' %} class="active"{% endif %}>
|
|
7
|
-
<a href="{% url 'dcim:controller_wirelessnetworks' pk=object.pk %}">Wireless Networks</a>
|
|
8
|
-
</li>
|
|
9
|
-
{% endif %}
|
|
10
|
-
{% endblock extra_nav_tabs %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -1,83 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Controller</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<div class="table-responsive">
|
|
10
|
-
<table class="table table-hover panel-body attr-table">
|
|
11
|
-
<tr>
|
|
12
|
-
<td>Name</td>
|
|
13
|
-
<td>{{ object.name|placeholder }}</td>
|
|
14
|
-
</tr>
|
|
15
|
-
<tr>
|
|
16
|
-
<td>Status</td>
|
|
17
|
-
<td>
|
|
18
|
-
{{ object.status|hyperlinked_object_with_color }}
|
|
19
|
-
</td>
|
|
20
|
-
</tr>
|
|
21
|
-
<tr>
|
|
22
|
-
<td>Role</td>
|
|
23
|
-
<td>{{ object.role|hyperlinked_object_with_color }}</td>
|
|
24
|
-
</tr>
|
|
25
|
-
<tr>
|
|
26
|
-
<td>Capabilities</td>
|
|
27
|
-
<td>{{ object.get_capabilities_display }}</td>
|
|
28
|
-
</tr>
|
|
29
|
-
<tr>
|
|
30
|
-
<td>Location</td>
|
|
31
|
-
<td>{{ object.location|hyperlinked_object }}</td>
|
|
32
|
-
</tr>
|
|
33
|
-
<tr>
|
|
34
|
-
<td>Platform</td>
|
|
35
|
-
<td>{{ object.platform|hyperlinked_object }}</td>
|
|
36
|
-
</tr>
|
|
37
|
-
{% include 'inc/tenant_table_row.html' %}
|
|
38
|
-
<tr>
|
|
39
|
-
<td>Description</td>
|
|
40
|
-
<td>{{ object.description|placeholder }}</td>
|
|
41
|
-
</tr>
|
|
42
|
-
</table>
|
|
43
|
-
</div>
|
|
44
|
-
</div>
|
|
45
|
-
{% endblock content_left_page %}
|
|
46
|
-
|
|
47
|
-
{% block content_right_page %}
|
|
48
|
-
<div class="panel panel-default">
|
|
49
|
-
<div class="panel-heading">
|
|
50
|
-
<strong>Integration</strong>
|
|
51
|
-
</div>
|
|
52
|
-
<div class="table-responsive">
|
|
53
|
-
<table class="table table-hover panel-body attr-table">
|
|
54
|
-
<tr>
|
|
55
|
-
<td>External Integration</td>
|
|
56
|
-
<td>{{ object.external_integration|hyperlinked_object }}</td>
|
|
57
|
-
</tr>
|
|
58
|
-
{% if object.controller_device %}
|
|
59
|
-
<tr>
|
|
60
|
-
<td>Controller Device</td>
|
|
61
|
-
<td>{{ object.controller_device|hyperlinked_object }}</td>
|
|
62
|
-
</tr>
|
|
63
|
-
{% endif %}
|
|
64
|
-
{% if object.controller_device_redundancy_group %}
|
|
65
|
-
<tr>
|
|
66
|
-
<td>Controller Device Redundancy Group</td>
|
|
67
|
-
<td>{{ object.controller_device_redundancy_group|hyperlinked_object }}</td>
|
|
68
|
-
</tr>
|
|
69
|
-
{% endif %}
|
|
70
|
-
</table>
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
{% endblock content_right_page %}
|
|
74
|
-
|
|
75
|
-
{% block content_full_width_page %}
|
|
76
|
-
<div class="panel panel-default">
|
|
77
|
-
<div class="panel-heading">
|
|
78
|
-
<strong>Managed Devices</strong>
|
|
79
|
-
</div>
|
|
80
|
-
{% include 'responsive_table.html' with table=devices_table %}
|
|
81
|
-
</div>
|
|
82
|
-
{% include 'inc/paginator.html' with paginator=devices_table.paginator page=devices_table.page %}
|
|
83
|
-
{% endblock content_full_width_page %}
|
|
1
|
+
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -1,25 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content %}
|
|
5
|
-
<form method="post">
|
|
6
|
-
{% csrf_token %}
|
|
7
|
-
<div class="panel panel-default">
|
|
8
|
-
<div class="panel-heading">
|
|
9
|
-
<strong>Wireless Networks</strong>
|
|
10
|
-
<div class="pull-right noprint">
|
|
11
|
-
{% if request.user.is_authenticated %}
|
|
12
|
-
{% table_config_button_small wireless_networks_table %}
|
|
13
|
-
{% endif %}
|
|
14
|
-
</div>
|
|
15
|
-
</div>
|
|
16
|
-
{% include 'responsive_table.html' with table=wireless_networks_table %}
|
|
17
|
-
</div>
|
|
18
|
-
</form>
|
|
19
|
-
{% table_config_form wireless_networks_table %}
|
|
20
|
-
{% endblock content %}
|
|
21
|
-
|
|
22
|
-
{% block javascript %}
|
|
23
|
-
{{ block.super }}
|
|
24
|
-
<script src="{% versioned_static 'js/tableconfig.js' %}"></script>
|
|
25
|
-
{% endblock javascript %}
|
|
1
|
+
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -398,40 +398,7 @@
|
|
|
398
398
|
</div>
|
|
399
399
|
</div>
|
|
400
400
|
{% endif %}
|
|
401
|
-
{%
|
|
402
|
-
<div id="dynamic_groups" role="tabpanel" class="tab-pane {% if request.GET.tab == 'dynamic_groups' %}active{% else %}fade{% endif %}">
|
|
403
|
-
<div class="row">
|
|
404
|
-
<div class="col-md-12">
|
|
405
|
-
<div class="alert alert-warning">
|
|
406
|
-
Dynamic group membership is cached for performance reasons,
|
|
407
|
-
therefore this table may not always be up-to-date.
|
|
408
|
-
<br>You can refresh the membership of any specific group by navigating to it from the list below
|
|
409
|
-
or from the <a href="{% url 'extras:dynamicgroup_list' %}">Dynamic Groups list view</a>.
|
|
410
|
-
<br>You can also refresh the membership of all groups by running the
|
|
411
|
-
<a href="{% url 'extras:job_run_by_class_path' class_path='nautobot.core.jobs.groups.RefreshDynamicGroupCaches' %}">Refresh Dynamic Group Caches job</a>.
|
|
412
|
-
</div>
|
|
413
|
-
</div>
|
|
414
|
-
</div>
|
|
415
|
-
<div class="row">
|
|
416
|
-
<div class="col-md-12">
|
|
417
|
-
<form method="post">
|
|
418
|
-
{% csrf_token %}
|
|
419
|
-
<div class="panel panel-default">
|
|
420
|
-
<div class="panel-heading">
|
|
421
|
-
<strong>Dynamic Groups</strong>
|
|
422
|
-
<div class="pull-right noprint">
|
|
423
|
-
<!-- Insert table config button here -->
|
|
424
|
-
</div>
|
|
425
|
-
</div>
|
|
426
|
-
<div class="table-responsive">
|
|
427
|
-
{% render_table associated_dynamic_groups_table 'inc/table.html' %}
|
|
428
|
-
</div>
|
|
429
|
-
</div>
|
|
430
|
-
</form>
|
|
431
|
-
</div>
|
|
432
|
-
</div>
|
|
433
|
-
</div>
|
|
434
|
-
{% endif %}
|
|
401
|
+
{% comment %}The dynamic_groups tab is intentionally omitted here for performance reasons.{% endcomment %}
|
|
435
402
|
{% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
|
|
436
403
|
<div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
|
|
437
404
|
<div class="row">
|
|
@@ -3,8 +3,11 @@
|
|
|
3
3
|
{% load static %}
|
|
4
4
|
|
|
5
5
|
{% block buttons %}
|
|
6
|
+
<button class="btn btn-default toggle-fullname" selected="selected">
|
|
7
|
+
<span class="mdi mdi-checkbox-marked-circle-outline" aria-hidden="true"></span> Show Device Full Name
|
|
8
|
+
</button>
|
|
6
9
|
<button class="btn btn-default toggle-images" selected="selected">
|
|
7
|
-
<span class="mdi mdi
|
|
10
|
+
<span class="mdi mdi-checkbox-marked-circle-outline" aria-hidden="true"></span> Show Images
|
|
8
11
|
</button>
|
|
9
12
|
<div class="btn-group" role="group">
|
|
10
13
|
<a href="{% url 'dcim:rack_elevation_list' %}{% querystring request face='front' %}" class="btn btn-default{% if rack_face == 'front' %} active{% endif %}">Front</a>
|
|
@@ -1,51 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block content_left_page %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading">
|
|
7
|
-
<strong>Virtual Chassis</strong>
|
|
8
|
-
</div>
|
|
9
|
-
<table class="table table-hover panel-body attr-table">
|
|
10
|
-
<tr>
|
|
11
|
-
<td>Domain</td>
|
|
12
|
-
<td>{{ object.domain|placeholder }}</td>
|
|
13
|
-
</tr>
|
|
14
|
-
<tr>
|
|
15
|
-
<td>Master</td>
|
|
16
|
-
<td>{{ object.master|hyperlinked_object }}</td>
|
|
17
|
-
</tr>
|
|
18
|
-
</table>
|
|
19
|
-
</div>
|
|
20
|
-
{% endblock content_left_page %}
|
|
21
|
-
|
|
22
|
-
{% block content_right_page %}
|
|
23
|
-
<div class="panel panel-default">
|
|
24
|
-
<div class="panel-heading">
|
|
25
|
-
<strong>Members</strong>
|
|
26
|
-
</div>
|
|
27
|
-
<table class="table table-hover panel-body attr-table">
|
|
28
|
-
<tr>
|
|
29
|
-
<th>Device</th>
|
|
30
|
-
<th>Position</th>
|
|
31
|
-
<th>Master</th>
|
|
32
|
-
<th>Priority</th>
|
|
33
|
-
</tr>
|
|
34
|
-
{% for vc_member in members %}
|
|
35
|
-
<tr{% if vc_member == device %} class="info"{% endif %}>
|
|
36
|
-
<td>{{ vc_member|hyperlinked_object }}</td>
|
|
37
|
-
<td><span class="badge badge-default">{{ vc_member.vc_position }}</span></td>
|
|
38
|
-
<td>{% if object.master == vc_member %}{{ True | render_boolean }}{% endif %}</td>
|
|
39
|
-
<td>{{ vc_member.vc_priority|placeholder }}</td>
|
|
40
|
-
</tr>
|
|
41
|
-
{% endfor %}
|
|
42
|
-
</table>
|
|
43
|
-
{% if perms.dcim.change_virtualchassis %}
|
|
44
|
-
<div class="panel-footer text-right noprint">
|
|
45
|
-
<a href="{% url 'dcim:virtualchassis_add_member' pk=object.pk %}?location={{ object.master.location.pk }}&rack={{ object.master.rack.pk }}" class="btn btn-primary btn-xs">
|
|
46
|
-
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Member
|
|
47
|
-
</a>
|
|
48
|
-
</div>
|
|
49
|
-
{% endif %}
|
|
50
|
-
</div>
|
|
51
|
-
{% endblock content_right_page %}
|
|
1
|
+
{% extends 'dcim/virtualchassis_retrieve.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -1,22 +1,2 @@
|
|
|
1
|
-
{% extends '
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block form %}
|
|
5
|
-
<div class="panel panel-default">
|
|
6
|
-
<div class="panel-heading"><strong>Virtual Chassis</strong></div>
|
|
7
|
-
<div class="panel-body">
|
|
8
|
-
{% render_field form.name %}
|
|
9
|
-
{% render_field form.domain %}
|
|
10
|
-
</div>
|
|
11
|
-
</div>
|
|
12
|
-
<div class="panel panel-default">
|
|
13
|
-
<div class="panel-heading"><strong>Member Devices</strong></div>
|
|
14
|
-
<div class="panel-body">
|
|
15
|
-
{% render_field form.location %}
|
|
16
|
-
{% render_field form.rack %}
|
|
17
|
-
{% render_field form.members %}
|
|
18
|
-
{% render_field form.initial_position %}
|
|
19
|
-
</div>
|
|
20
|
-
</div>
|
|
21
|
-
{% include 'inc/extras_features_edit_form_fields.html' %}
|
|
22
|
-
{% endblock %}
|
|
1
|
+
{% extends 'dcim/virtualchassis_create.html' %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{% extends 'generic/object_create.html' %}
|
|
2
|
+
{% load form_helpers %}
|
|
3
|
+
|
|
4
|
+
{% block form %}
|
|
5
|
+
<div class="panel panel-default">
|
|
6
|
+
<div class="panel-heading"><strong>Virtual Chassis</strong></div>
|
|
7
|
+
<div class="panel-body">
|
|
8
|
+
{% render_field form.name %}
|
|
9
|
+
{% render_field form.domain %}
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="panel panel-default">
|
|
13
|
+
<div class="panel-heading"><strong>Member Devices</strong></div>
|
|
14
|
+
<div class="panel-body">
|
|
15
|
+
{% render_field form.location %}
|
|
16
|
+
{% render_field form.rack %}
|
|
17
|
+
{% render_field form.members %}
|
|
18
|
+
{% render_field form.initial_position %}
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
{% include 'inc/extras_features_edit_form_fields.html' %}
|
|
22
|
+
{% endblock %}
|