nautobot 2.4.9__py3-none-any.whl → 2.4.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/cloud/tests/test_views.py +13 -1
- nautobot/cloud/views.py +39 -9
- nautobot/core/api/parsers.py +56 -2
- nautobot/core/celery/__init__.py +21 -0
- nautobot/core/celery/encoders.py +3 -0
- nautobot/core/forms/forms.py +4 -1
- nautobot/core/jobs/bulk_actions.py +8 -8
- nautobot/core/jobs/cleanup.py +11 -0
- nautobot/core/management/commands/generate_test_data.py +2 -1
- nautobot/core/models/__init__.py +2 -0
- nautobot/core/templates/generic/object_retrieve.html +1 -1
- nautobot/core/testing/mixins.py +19 -1
- nautobot/core/testing/views.py +104 -8
- nautobot/core/tests/test_csv.py +92 -1
- nautobot/core/tests/test_jinja_filters.py +59 -0
- nautobot/core/tests/test_jobs.py +20 -4
- nautobot/core/tests/test_utils.py +193 -0
- nautobot/core/tests/test_views.py +73 -0
- nautobot/core/tests/test_views_utils.py +53 -2
- nautobot/core/ui/object_detail.py +4 -0
- nautobot/core/urls.py +2 -2
- nautobot/core/utils/lookup.py +4 -2
- nautobot/core/utils/module_loading.py +86 -58
- nautobot/core/views/__init__.py +21 -0
- nautobot/core/views/generic.py +2 -12
- nautobot/core/views/mixins.py +19 -1
- nautobot/core/views/renderers.py +4 -13
- nautobot/core/views/utils.py +16 -0
- nautobot/dcim/api/serializers.py +13 -0
- nautobot/dcim/api/urls.py +1 -0
- nautobot/dcim/api/views.py +20 -0
- nautobot/dcim/apps.py +1 -0
- nautobot/dcim/factory.py +11 -0
- nautobot/dcim/filters/__init__.py +110 -0
- nautobot/dcim/forms.py +205 -19
- nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
- nautobot/dcim/models/__init__.py +2 -0
- nautobot/dcim/models/device_component_templates.py +18 -0
- nautobot/dcim/models/device_components.py +25 -1
- nautobot/dcim/models/devices.py +68 -0
- nautobot/dcim/navigation.py +16 -0
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +48 -0
- nautobot/dcim/tables/devicetypes.py +35 -1
- nautobot/dcim/tables/template_code.py +2 -0
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
- nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
- nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
- nautobot/dcim/templates/dcim/location.html +2 -249
- nautobot/dcim/templates/dcim/location_edit.html +2 -38
- nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
- nautobot/dcim/templates/dcim/location_update.html +38 -0
- nautobot/dcim/templates/dcim/module_update.html +1 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
- nautobot/dcim/tests/test_api.py +35 -0
- nautobot/dcim/tests/test_filters.py +102 -3
- nautobot/dcim/tests/test_models.py +146 -0
- nautobot/dcim/tests/test_views.py +70 -97
- nautobot/dcim/urls.py +4 -22
- nautobot/dcim/views.py +439 -153
- nautobot/extras/api/views.py +9 -2
- nautobot/extras/context_managers.py +2 -2
- nautobot/extras/datasources/git.py +11 -3
- nautobot/extras/forms/forms.py +9 -5
- nautobot/extras/jobs.py +4 -2
- nautobot/extras/models/customfields.py +2 -0
- nautobot/extras/models/datasources.py +13 -8
- nautobot/extras/models/groups.py +18 -0
- nautobot/extras/models/jobs.py +19 -0
- nautobot/extras/models/metadata.py +2 -0
- nautobot/extras/models/models.py +4 -0
- nautobot/extras/models/secrets.py +7 -0
- nautobot/extras/plugins/__init__.py +3 -0
- nautobot/extras/secrets/__init__.py +14 -0
- nautobot/extras/tables.py +40 -3
- nautobot/extras/templates/extras/configcontext.html +2 -220
- nautobot/extras/templates/extras/configcontext_edit.html +2 -50
- nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
- nautobot/extras/templates/extras/configcontext_update.html +50 -0
- nautobot/extras/templates/extras/configcontextschema.html +2 -48
- nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
- nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
- nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
- nautobot/extras/templates/extras/inc/json_data.html +1 -1
- nautobot/extras/templates/extras/inc/json_format.html +2 -2
- nautobot/extras/templates/extras/job_edit.html +12 -6
- nautobot/extras/templates/extras/tag.html +2 -52
- nautobot/extras/templates/extras/tag_edit.html +2 -15
- nautobot/extras/templates/extras/tag_retrieve.html +52 -0
- nautobot/extras/templates/extras/tag_update.html +15 -0
- nautobot/extras/templates/extras/team_retrieve.html +2 -2
- nautobot/extras/tests/test_api.py +15 -15
- nautobot/extras/tests/test_context_managers.py +20 -0
- nautobot/extras/tests/test_filters.py +4 -4
- nautobot/extras/tests/test_jobs.py +23 -10
- nautobot/extras/tests/test_models.py +45 -8
- nautobot/extras/tests/test_plugins.py +6 -3
- nautobot/extras/tests/test_views.py +66 -11
- nautobot/extras/urls.py +4 -134
- nautobot/extras/views.py +113 -158
- nautobot/ipam/models.py +51 -4
- nautobot/ipam/tables.py +19 -0
- nautobot/ipam/templates/ipam/vlan.html +2 -84
- nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
- nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
- nautobot/ipam/templates/ipam/vlan_update.html +24 -0
- nautobot/ipam/tests/test_views.py +5 -0
- nautobot/ipam/urls.py +1 -21
- nautobot/ipam/views.py +45 -70
- nautobot/project-static/docs/404.html +31 -8
- nautobot/project-static/docs/apps/index.html +31 -8
- nautobot/project-static/docs/apps/nautobot-apps.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +120 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +31 -8
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +31 -8
- nautobot/project-static/docs/development/apps/api/configuration-view.html +31 -8
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/global-search.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/graphql.html +31 -8
- nautobot/project-static/docs/development/apps/api/models/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +40 -8
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +70 -46
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +31 -8
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +31 -8
- nautobot/project-static/docs/development/apps/api/prometheus.html +31 -8
- nautobot/project-static/docs/development/apps/api/setup.html +31 -8
- nautobot/project-static/docs/development/apps/api/testing.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +31 -8
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/base-template.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/index.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/notes.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +31 -8
- nautobot/project-static/docs/development/apps/api/views/urls.html +31 -8
- nautobot/project-static/docs/development/apps/index.html +31 -8
- nautobot/project-static/docs/development/apps/migration/code-updates.html +31 -8
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +31 -8
- nautobot/project-static/docs/development/apps/migration/from-v1.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +31 -8
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +31 -8
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +31 -8
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +31 -8
- nautobot/project-static/docs/development/core/application-registry.html +31 -8
- nautobot/project-static/docs/development/core/best-practices.html +31 -8
- nautobot/project-static/docs/development/core/bootstrap-ui.html +31 -8
- nautobot/project-static/docs/development/core/caching.html +31 -8
- nautobot/project-static/docs/development/core/controllers.html +31 -8
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +31 -8
- nautobot/project-static/docs/development/core/generic-views.html +31 -8
- nautobot/project-static/docs/development/core/getting-started.html +31 -8
- nautobot/project-static/docs/development/core/homepage.html +31 -8
- nautobot/project-static/docs/development/core/index.html +31 -8
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +31 -8
- nautobot/project-static/docs/development/core/model-checklist.html +31 -8
- nautobot/project-static/docs/development/core/model-features.html +31 -8
- nautobot/project-static/docs/development/core/natural-keys.html +31 -8
- nautobot/project-static/docs/development/core/navigation-menu.html +31 -8
- nautobot/project-static/docs/development/core/release-checklist.html +31 -8
- nautobot/project-static/docs/development/core/role-internals.html +31 -8
- nautobot/project-static/docs/development/core/settings.html +31 -8
- nautobot/project-static/docs/development/core/style-guide.html +31 -8
- nautobot/project-static/docs/development/core/templates.html +31 -8
- nautobot/project-static/docs/development/core/testing.html +31 -8
- nautobot/project-static/docs/development/core/ui-component-framework.html +31 -8
- nautobot/project-static/docs/development/core/user-preferences.html +31 -8
- nautobot/project-static/docs/development/index.html +31 -8
- nautobot/project-static/docs/development/jobs/getting-started.html +35 -8
- nautobot/project-static/docs/development/jobs/index.html +31 -8
- nautobot/project-static/docs/development/jobs/installation.html +31 -8
- nautobot/project-static/docs/development/jobs/job-extensions.html +31 -8
- nautobot/project-static/docs/development/jobs/job-logging.html +31 -8
- nautobot/project-static/docs/development/jobs/job-patterns.html +31 -8
- nautobot/project-static/docs/development/jobs/job-structure.html +31 -8
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +31 -8
- nautobot/project-static/docs/development/jobs/testing.html +31 -8
- nautobot/project-static/docs/index.html +31 -8
- nautobot/project-static/docs/insert-analytics.sh +36 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +31 -8
- nautobot/project-static/docs/overview/design_philosophy.html +31 -8
- nautobot/project-static/docs/release-notes/index.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.0.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.1.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.2.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.3.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.4.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.5.html +31 -8
- nautobot/project-static/docs/release-notes/version-1.6.html +328 -8
- nautobot/project-static/docs/release-notes/version-2.0.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.1.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.2.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.3.html +31 -8
- nautobot/project-static/docs/release-notes/version-2.4.html +353 -8
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +302 -298
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +31 -8
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +31 -8
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +31 -8
- nautobot/project-static/docs/user-guide/administration/installation/services.html +31 -8
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +31 -8
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +31 -8
- nautobot/project-static/docs/user-guide/administration/security/index.html +31 -9
- nautobot/project-static/docs/user-guide/administration/security/notices.html +144 -9
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +31 -8
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +31 -8
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +43 -20
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +35 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +31 -8
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +41 -15
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +31 -8
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +31 -8
- nautobot/project-static/docs/user-guide/index.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +37 -9
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +31 -8
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +31 -8
- nautobot/tenancy/tables.py +2 -0
- nautobot/users/models.py +4 -0
- nautobot/virtualization/models.py +4 -0
- nautobot/virtualization/tests/test_views.py +1 -1
- nautobot/wireless/forms.py +0 -1
- nautobot/wireless/models.py +1 -1
- nautobot/wireless/tables.py +7 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/METADATA +4 -4
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/RECORD +433 -418
- /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
- /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/NOTICE +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/WHEEL +0 -0
- {nautobot-2.4.9.dist-info → nautobot-2.4.11.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Generated by Django 4.2.19 on 2025-03-18 17:22
|
|
2
|
+
|
|
3
|
+
import uuid
|
|
4
|
+
|
|
5
|
+
import django.core.serializers.json
|
|
6
|
+
from django.db import migrations, models
|
|
7
|
+
import django.db.models.deletion
|
|
8
|
+
|
|
9
|
+
import nautobot.core.models.fields
|
|
10
|
+
import nautobot.extras.models.mixins
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Migration(migrations.Migration):
|
|
14
|
+
dependencies = [
|
|
15
|
+
("extras", "0122_add_graphqlquery_owner_content_type"),
|
|
16
|
+
("dcim", "0069_softwareimagefile_external_integration"),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
operations = [
|
|
20
|
+
migrations.AddField(
|
|
21
|
+
model_name="modulebay",
|
|
22
|
+
name="requires_first_party_modules",
|
|
23
|
+
field=models.BooleanField(default=False),
|
|
24
|
+
),
|
|
25
|
+
migrations.AddField(
|
|
26
|
+
model_name="modulebaytemplate",
|
|
27
|
+
name="requires_first_party_modules",
|
|
28
|
+
field=models.BooleanField(default=False),
|
|
29
|
+
),
|
|
30
|
+
migrations.CreateModel(
|
|
31
|
+
name="ModuleFamily",
|
|
32
|
+
fields=[
|
|
33
|
+
(
|
|
34
|
+
"id",
|
|
35
|
+
models.UUIDField(
|
|
36
|
+
default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
("created", models.DateTimeField(auto_now_add=True, null=True)),
|
|
40
|
+
("last_updated", models.DateTimeField(auto_now=True, null=True)),
|
|
41
|
+
(
|
|
42
|
+
"_custom_field_data",
|
|
43
|
+
models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder),
|
|
44
|
+
),
|
|
45
|
+
("name", models.CharField(max_length=255, unique=True)),
|
|
46
|
+
("description", models.CharField(blank=True, max_length=255)),
|
|
47
|
+
("tags", nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag")),
|
|
48
|
+
],
|
|
49
|
+
options={
|
|
50
|
+
"verbose_name_plural": "module families",
|
|
51
|
+
"ordering": ["name"],
|
|
52
|
+
},
|
|
53
|
+
bases=(
|
|
54
|
+
nautobot.extras.models.mixins.DynamicGroupMixin,
|
|
55
|
+
nautobot.extras.models.mixins.NotesMixin,
|
|
56
|
+
models.Model,
|
|
57
|
+
),
|
|
58
|
+
),
|
|
59
|
+
migrations.AddField(
|
|
60
|
+
model_name="modulebay",
|
|
61
|
+
name="module_family",
|
|
62
|
+
field=models.ForeignKey(
|
|
63
|
+
blank=True,
|
|
64
|
+
null=True,
|
|
65
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
66
|
+
related_name="module_bays",
|
|
67
|
+
to="dcim.modulefamily",
|
|
68
|
+
),
|
|
69
|
+
),
|
|
70
|
+
migrations.AddField(
|
|
71
|
+
model_name="modulebaytemplate",
|
|
72
|
+
name="module_family",
|
|
73
|
+
field=models.ForeignKey(
|
|
74
|
+
blank=True,
|
|
75
|
+
null=True,
|
|
76
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
77
|
+
related_name="module_bay_templates",
|
|
78
|
+
to="dcim.modulefamily",
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
migrations.AddField(
|
|
82
|
+
model_name="moduletype",
|
|
83
|
+
name="module_family",
|
|
84
|
+
field=models.ForeignKey(
|
|
85
|
+
blank=True,
|
|
86
|
+
null=True,
|
|
87
|
+
on_delete=django.db.models.deletion.PROTECT,
|
|
88
|
+
related_name="module_types",
|
|
89
|
+
to="dcim.modulefamily",
|
|
90
|
+
),
|
|
91
|
+
),
|
|
92
|
+
]
|
nautobot/dcim/models/__init__.py
CHANGED
|
@@ -38,6 +38,7 @@ from .devices import (
|
|
|
38
38
|
InterfaceVDCAssignment,
|
|
39
39
|
Manufacturer,
|
|
40
40
|
Module,
|
|
41
|
+
ModuleFamily,
|
|
41
42
|
ModuleType,
|
|
42
43
|
Platform,
|
|
43
44
|
SoftwareImageFile,
|
|
@@ -81,6 +82,7 @@ __all__ = (
|
|
|
81
82
|
"Module",
|
|
82
83
|
"ModuleBay",
|
|
83
84
|
"ModuleBayTemplate",
|
|
85
|
+
"ModuleFamily",
|
|
84
86
|
"ModuleType",
|
|
85
87
|
"PathEndpoint",
|
|
86
88
|
"Platform",
|
|
@@ -82,6 +82,8 @@ class ComponentTemplateModel(
|
|
|
82
82
|
"""
|
|
83
83
|
raise NotImplementedError()
|
|
84
84
|
|
|
85
|
+
instantiate.alters_data = True
|
|
86
|
+
|
|
85
87
|
def to_objectchange(self, action, **kwargs):
|
|
86
88
|
"""
|
|
87
89
|
Return a new ObjectChange with the `related_object` pinned to the `device_type` by default.
|
|
@@ -122,6 +124,8 @@ class ComponentTemplateModel(
|
|
|
122
124
|
**kwargs,
|
|
123
125
|
)
|
|
124
126
|
|
|
127
|
+
instantiate_model.alters_data = True
|
|
128
|
+
|
|
125
129
|
|
|
126
130
|
class ModularComponentTemplateModel(ComponentTemplateModel):
|
|
127
131
|
"""Component Template that supports assignment to a DeviceType or a ModuleType."""
|
|
@@ -477,6 +481,18 @@ class ModuleBayTemplate(ModularComponentTemplateModel):
|
|
|
477
481
|
)
|
|
478
482
|
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
479
483
|
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
484
|
+
module_family = models.ForeignKey(
|
|
485
|
+
to="dcim.ModuleFamily",
|
|
486
|
+
on_delete=models.PROTECT,
|
|
487
|
+
related_name="module_bay_templates",
|
|
488
|
+
blank=True,
|
|
489
|
+
null=True,
|
|
490
|
+
help_text="Module family that can be installed in this bay. Leave blank for no restriction.",
|
|
491
|
+
)
|
|
492
|
+
requires_first_party_modules = models.BooleanField(
|
|
493
|
+
default=False,
|
|
494
|
+
help_text="This bay will only accept modules from the same manufacturer as the parent device or module",
|
|
495
|
+
)
|
|
480
496
|
|
|
481
497
|
natural_key_field_names = ["device_type", "module_type", "name"]
|
|
482
498
|
|
|
@@ -501,6 +517,8 @@ class ModuleBayTemplate(ModularComponentTemplateModel):
|
|
|
501
517
|
position=self.position,
|
|
502
518
|
label=self.label,
|
|
503
519
|
description=self.description,
|
|
520
|
+
module_family=self.module_family,
|
|
521
|
+
requires_first_party_modules=self.requires_first_party_modules,
|
|
504
522
|
_custom_field_data=custom_field_data,
|
|
505
523
|
)
|
|
506
524
|
|
|
@@ -182,6 +182,8 @@ class ModularComponentModel(ComponentModel):
|
|
|
182
182
|
if save:
|
|
183
183
|
self.save(update_fields=["_name", "name"])
|
|
184
184
|
|
|
185
|
+
render_name_template.alters_data = True
|
|
186
|
+
|
|
185
187
|
def to_objectchange(self, action, **kwargs):
|
|
186
188
|
"""
|
|
187
189
|
Return a new ObjectChange with the `related_object` pinned to the parent `device` or `module`.
|
|
@@ -820,6 +822,8 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
|
|
|
820
822
|
instance.validated_save()
|
|
821
823
|
return len(ip_addresses)
|
|
822
824
|
|
|
825
|
+
add_ip_addresses.alters_data = True
|
|
826
|
+
|
|
823
827
|
def remove_ip_addresses(self, ip_addresses):
|
|
824
828
|
"""Remove one or more IPAddress instances from this interface's `ip_addresses` many-to-many relationship.
|
|
825
829
|
|
|
@@ -839,6 +843,8 @@ class Interface(ModularComponentModel, CableTermination, PathEndpoint, BaseInter
|
|
|
839
843
|
count += deleted_count
|
|
840
844
|
return count
|
|
841
845
|
|
|
846
|
+
remove_ip_addresses.alters_data = True
|
|
847
|
+
|
|
842
848
|
@property
|
|
843
849
|
def is_connectable(self):
|
|
844
850
|
return self.type not in NONCONNECTABLE_IFACE_TYPES
|
|
@@ -939,6 +945,8 @@ class InterfaceRedundancyGroup(PrimaryModel): # pylint: disable=too-many-ancest
|
|
|
939
945
|
)
|
|
940
946
|
return instance.validated_save()
|
|
941
947
|
|
|
948
|
+
add_interface.alters_data = True
|
|
949
|
+
|
|
942
950
|
def remove_interface(self, interface):
|
|
943
951
|
"""
|
|
944
952
|
Remove an interface.
|
|
@@ -952,6 +960,8 @@ class InterfaceRedundancyGroup(PrimaryModel): # pylint: disable=too-many-ancest
|
|
|
952
960
|
)
|
|
953
961
|
return instance.delete()
|
|
954
962
|
|
|
963
|
+
remove_interface.alters_data = True
|
|
964
|
+
|
|
955
965
|
|
|
956
966
|
@extras_features("graphql")
|
|
957
967
|
class InterfaceRedundancyGroupAssociation(BaseModel, ChangeLoggedModel):
|
|
@@ -1208,6 +1218,18 @@ class ModuleBay(PrimaryModel):
|
|
|
1208
1218
|
blank=True,
|
|
1209
1219
|
null=True,
|
|
1210
1220
|
)
|
|
1221
|
+
module_family = models.ForeignKey(
|
|
1222
|
+
to="dcim.ModuleFamily",
|
|
1223
|
+
on_delete=models.PROTECT,
|
|
1224
|
+
related_name="module_bays",
|
|
1225
|
+
blank=True,
|
|
1226
|
+
null=True,
|
|
1227
|
+
help_text="Module family that can be installed in this bay",
|
|
1228
|
+
)
|
|
1229
|
+
requires_first_party_modules = models.BooleanField(
|
|
1230
|
+
default=False,
|
|
1231
|
+
help_text="This bay will only accept modules from the same manufacturer as the parent device or module",
|
|
1232
|
+
)
|
|
1211
1233
|
name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, db_index=True)
|
|
1212
1234
|
_name = NaturalOrderingField(target_field="name", max_length=CHARFIELD_MAX_LENGTH, blank=True, db_index=True)
|
|
1213
1235
|
position = models.CharField(
|
|
@@ -1218,7 +1240,7 @@ class ModuleBay(PrimaryModel):
|
|
|
1218
1240
|
label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
|
|
1219
1241
|
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
1220
1242
|
|
|
1221
|
-
clone_fields = ["parent_device", "parent_module"]
|
|
1243
|
+
clone_fields = ["parent_device", "parent_module", "module_family", "requires_first_party_modules"]
|
|
1222
1244
|
|
|
1223
1245
|
# The recursive nature of this model combined with the fact that it can be a child of a
|
|
1224
1246
|
# device or location makes our natural key implementation unusable, so just use the pk
|
|
@@ -1287,3 +1309,5 @@ class ModuleBay(PrimaryModel):
|
|
|
1287
1309
|
|
|
1288
1310
|
if not self.position:
|
|
1289
1311
|
self.position = self.name
|
|
1312
|
+
|
|
1313
|
+
clean.alters_data = True
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -897,6 +897,8 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
897
897
|
model.objects.bulk_create([x.instantiate(device=self) for x in templates])
|
|
898
898
|
return instantiated_components
|
|
899
899
|
|
|
900
|
+
create_components.alters_data = True
|
|
901
|
+
|
|
900
902
|
@property
|
|
901
903
|
def display(self):
|
|
902
904
|
if self.name:
|
|
@@ -1548,6 +1550,30 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
|
|
|
1548
1550
|
#
|
|
1549
1551
|
|
|
1550
1552
|
|
|
1553
|
+
@extras_features(
|
|
1554
|
+
"custom_links",
|
|
1555
|
+
"custom_validators",
|
|
1556
|
+
"export_templates",
|
|
1557
|
+
"graphql",
|
|
1558
|
+
"webhooks",
|
|
1559
|
+
)
|
|
1560
|
+
class ModuleFamily(PrimaryModel):
|
|
1561
|
+
"""
|
|
1562
|
+
A ModuleFamily represents a classification of ModuleTypes.
|
|
1563
|
+
It is used to enforce compatibility between ModuleBays and Modules.
|
|
1564
|
+
"""
|
|
1565
|
+
|
|
1566
|
+
name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, unique=True)
|
|
1567
|
+
description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
|
|
1568
|
+
|
|
1569
|
+
class Meta:
|
|
1570
|
+
ordering = ["name"]
|
|
1571
|
+
verbose_name_plural = "module families"
|
|
1572
|
+
|
|
1573
|
+
def __str__(self):
|
|
1574
|
+
return self.name
|
|
1575
|
+
|
|
1576
|
+
|
|
1551
1577
|
# TODO: 5840 - Translate comments field from devicetype library, Nautobot doesn't use that field for ModuleType
|
|
1552
1578
|
@extras_features(
|
|
1553
1579
|
"custom_links",
|
|
@@ -1575,6 +1601,13 @@ class ModuleType(PrimaryModel):
|
|
|
1575
1601
|
"""
|
|
1576
1602
|
|
|
1577
1603
|
manufacturer = models.ForeignKey(to="dcim.Manufacturer", on_delete=models.PROTECT, related_name="module_types")
|
|
1604
|
+
module_family = models.ForeignKey(
|
|
1605
|
+
to="dcim.ModuleFamily",
|
|
1606
|
+
on_delete=models.PROTECT,
|
|
1607
|
+
related_name="module_types",
|
|
1608
|
+
blank=True,
|
|
1609
|
+
null=True,
|
|
1610
|
+
)
|
|
1578
1611
|
model = models.CharField(max_length=CHARFIELD_MAX_LENGTH)
|
|
1579
1612
|
part_number = models.CharField(
|
|
1580
1613
|
max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Discrete part number (optional)"
|
|
@@ -1583,6 +1616,7 @@ class ModuleType(PrimaryModel):
|
|
|
1583
1616
|
|
|
1584
1617
|
clone_fields = [
|
|
1585
1618
|
"manufacturer",
|
|
1619
|
+
"module_family",
|
|
1586
1620
|
]
|
|
1587
1621
|
|
|
1588
1622
|
class Meta:
|
|
@@ -1808,6 +1842,36 @@ class Module(PrimaryModel):
|
|
|
1808
1842
|
{"location": f'Modules may not associate to locations of type "{self.location.location_type}".'}
|
|
1809
1843
|
)
|
|
1810
1844
|
|
|
1845
|
+
# Validate module family compatibility
|
|
1846
|
+
if self.parent_module_bay and self.parent_module_bay.module_family:
|
|
1847
|
+
if self.module_type.module_family != self.parent_module_bay.module_family:
|
|
1848
|
+
module_family_name = self.parent_module_bay.module_family.name
|
|
1849
|
+
if self.module_type.module_family is None:
|
|
1850
|
+
module_type_family = "not assigned to a family"
|
|
1851
|
+
else:
|
|
1852
|
+
module_type_family = f"in the family {self.module_type.module_family.name}"
|
|
1853
|
+
raise ValidationError(
|
|
1854
|
+
{
|
|
1855
|
+
"module_type": f"The selected module bay requires a module type in the family {module_family_name}, "
|
|
1856
|
+
f"but the selected module type is {module_type_family}."
|
|
1857
|
+
}
|
|
1858
|
+
)
|
|
1859
|
+
|
|
1860
|
+
# Validate module manufacturer constraint
|
|
1861
|
+
if self.parent_module_bay and self.parent_module_bay.requires_first_party_modules:
|
|
1862
|
+
if self.parent_module_bay.parent_device:
|
|
1863
|
+
parent_mfr = self.parent_module_bay.parent_device.device_type.manufacturer
|
|
1864
|
+
elif self.parent_module_bay.parent_module:
|
|
1865
|
+
parent_mfr = self.parent_module_bay.parent_module.module_type.manufacturer
|
|
1866
|
+
else:
|
|
1867
|
+
parent_mfr = None
|
|
1868
|
+
if parent_mfr and self.module_type.manufacturer != parent_mfr:
|
|
1869
|
+
raise ValidationError(
|
|
1870
|
+
{
|
|
1871
|
+
"module_type": "The selected module bay requires a module type from the same manufacturer as the parent device or module"
|
|
1872
|
+
}
|
|
1873
|
+
)
|
|
1874
|
+
|
|
1811
1875
|
def save(self, *args, **kwargs):
|
|
1812
1876
|
is_new = not self.present_in_database
|
|
1813
1877
|
|
|
@@ -1858,6 +1922,8 @@ class Module(PrimaryModel):
|
|
|
1858
1922
|
model.objects.bulk_create([x.instantiate(device=None, module=self) for x in templates])
|
|
1859
1923
|
return instantiated_components
|
|
1860
1924
|
|
|
1925
|
+
create_components.alters_data = True
|
|
1926
|
+
|
|
1861
1927
|
def render_component_names(self):
|
|
1862
1928
|
"""
|
|
1863
1929
|
Replace the {module}, {module.parent}, {module.parent.parent}, etc. template variables in descendant
|
|
@@ -1882,6 +1948,8 @@ class Module(PrimaryModel):
|
|
|
1882
1948
|
for child in self.get_children():
|
|
1883
1949
|
child.render_component_names()
|
|
1884
1950
|
|
|
1951
|
+
render_component_names.alters_data = True
|
|
1952
|
+
|
|
1885
1953
|
def get_cables(self, pk_list=False):
|
|
1886
1954
|
"""
|
|
1887
1955
|
Return a QuerySet or PK list matching all Cables connected to any component of this Module.
|
nautobot/dcim/navigation.py
CHANGED
|
@@ -293,6 +293,22 @@ menu_items = (
|
|
|
293
293
|
),
|
|
294
294
|
),
|
|
295
295
|
),
|
|
296
|
+
NavMenuItem(
|
|
297
|
+
link="dcim:modulefamily_list",
|
|
298
|
+
name="Module Families",
|
|
299
|
+
weight=300,
|
|
300
|
+
permissions=[
|
|
301
|
+
"dcim.view_modulefamily",
|
|
302
|
+
],
|
|
303
|
+
buttons=(
|
|
304
|
+
NavMenuAddButton(
|
|
305
|
+
link="dcim:modulefamily_add",
|
|
306
|
+
permissions=[
|
|
307
|
+
"dcim.add_modulefamily",
|
|
308
|
+
],
|
|
309
|
+
),
|
|
310
|
+
),
|
|
311
|
+
),
|
|
296
312
|
),
|
|
297
313
|
),
|
|
298
314
|
NavMenuGroup(
|
nautobot/dcim/tables/__init__.py
CHANGED
|
@@ -30,6 +30,7 @@ from .devices import (
|
|
|
30
30
|
InterfaceTable,
|
|
31
31
|
InventoryItemTable,
|
|
32
32
|
ModuleBayTable,
|
|
33
|
+
ModuleFamilyTable,
|
|
33
34
|
ModuleModuleBayTable,
|
|
34
35
|
ModuleTable,
|
|
35
36
|
PlatformTable,
|
|
@@ -104,6 +105,7 @@ __all__ = (
|
|
|
104
105
|
"ManufacturerTable",
|
|
105
106
|
"ModuleBayTable",
|
|
106
107
|
"ModuleBayTemplateTable",
|
|
108
|
+
"ModuleFamilyTable",
|
|
107
109
|
"ModuleModuleBayTable",
|
|
108
110
|
"ModuleTable",
|
|
109
111
|
"ModuleTypeTable",
|
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -26,6 +26,7 @@ from nautobot.dcim.models import (
|
|
|
26
26
|
InventoryItem,
|
|
27
27
|
Module,
|
|
28
28
|
ModuleBay,
|
|
29
|
+
ModuleFamily,
|
|
29
30
|
Platform,
|
|
30
31
|
PowerOutlet,
|
|
31
32
|
PowerPort,
|
|
@@ -86,6 +87,7 @@ __all__ = (
|
|
|
86
87
|
"InterfaceTable",
|
|
87
88
|
"InventoryItemTable",
|
|
88
89
|
"ModuleBayTable",
|
|
90
|
+
"ModuleFamilyTable",
|
|
89
91
|
"ModuleModuleBayTable",
|
|
90
92
|
"ModuleTable",
|
|
91
93
|
"PlatformTable",
|
|
@@ -275,6 +277,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
275
277
|
)
|
|
276
278
|
location = tables.Column(linkify=True)
|
|
277
279
|
tenant = TenantColumn()
|
|
280
|
+
module_type__module_family = tables.Column(linkify=True, verbose_name="Family")
|
|
278
281
|
tags = TagColumn(url_name="dcim:module_list")
|
|
279
282
|
actions = ButtonsColumn(Module, prepend_template=MODULE_BUTTONS)
|
|
280
283
|
|
|
@@ -283,6 +286,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
283
286
|
fields = (
|
|
284
287
|
"pk",
|
|
285
288
|
"module_type",
|
|
289
|
+
"module_family",
|
|
286
290
|
"parent_module_bay",
|
|
287
291
|
"location",
|
|
288
292
|
"serial",
|
|
@@ -296,6 +300,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
296
300
|
default_columns = (
|
|
297
301
|
"pk",
|
|
298
302
|
"module_type",
|
|
303
|
+
"module_family",
|
|
299
304
|
"parent_module_bay",
|
|
300
305
|
"location",
|
|
301
306
|
"serial",
|
|
@@ -307,6 +312,40 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
307
312
|
)
|
|
308
313
|
|
|
309
314
|
|
|
315
|
+
class ModuleFamilyTable(BaseTable):
|
|
316
|
+
pk = ToggleColumn()
|
|
317
|
+
name = tables.Column(linkify=True)
|
|
318
|
+
module_type_count = LinkedCountColumn(
|
|
319
|
+
viewname="dcim:moduletype_list", url_params={"module_family": "pk"}, verbose_name="Module Types"
|
|
320
|
+
)
|
|
321
|
+
module_bay_count = LinkedCountColumn(
|
|
322
|
+
viewname="dcim:modulebay_list", url_params={"module_family": "pk"}, verbose_name="Module Bays"
|
|
323
|
+
)
|
|
324
|
+
tags = TagColumn()
|
|
325
|
+
actions = ButtonsColumn(ModuleFamily)
|
|
326
|
+
|
|
327
|
+
class Meta(BaseTable.Meta):
|
|
328
|
+
model = ModuleFamily
|
|
329
|
+
fields = (
|
|
330
|
+
"pk",
|
|
331
|
+
"name",
|
|
332
|
+
"description",
|
|
333
|
+
"module_type_count",
|
|
334
|
+
"module_bay_count",
|
|
335
|
+
"tags",
|
|
336
|
+
"created",
|
|
337
|
+
"last_updated",
|
|
338
|
+
"actions",
|
|
339
|
+
)
|
|
340
|
+
default_columns = (
|
|
341
|
+
"name",
|
|
342
|
+
"description",
|
|
343
|
+
"module_type_count",
|
|
344
|
+
"module_bay_count",
|
|
345
|
+
"actions",
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
|
|
310
349
|
#
|
|
311
350
|
# Device components
|
|
312
351
|
#
|
|
@@ -943,6 +982,7 @@ class ModuleBayTable(BaseTable):
|
|
|
943
982
|
installed_module = tables.Column(linkify=True, verbose_name="Installed Module")
|
|
944
983
|
installed_module__status = ColoredLabelColumn()
|
|
945
984
|
tags = TagColumn(url_name="dcim:devicebay_list")
|
|
985
|
+
module_family = tables.Column(linkify=True, verbose_name="Family")
|
|
946
986
|
|
|
947
987
|
class Meta(BaseTable.Meta):
|
|
948
988
|
model = ModuleBay
|
|
@@ -953,6 +993,7 @@ class ModuleBayTable(BaseTable):
|
|
|
953
993
|
"name",
|
|
954
994
|
"position",
|
|
955
995
|
"label",
|
|
996
|
+
"module_family",
|
|
956
997
|
"description",
|
|
957
998
|
"installed_module",
|
|
958
999
|
"installed_module__status",
|
|
@@ -965,6 +1006,7 @@ class ModuleBayTable(BaseTable):
|
|
|
965
1006
|
"name",
|
|
966
1007
|
"position",
|
|
967
1008
|
"label",
|
|
1009
|
+
"module_family",
|
|
968
1010
|
"description",
|
|
969
1011
|
"installed_module",
|
|
970
1012
|
"installed_module__status",
|
|
@@ -1008,8 +1050,10 @@ class DeviceModuleBayTable(ModuleBayTable):
|
|
|
1008
1050
|
'"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
|
|
1009
1051
|
attrs={"td": {"class": "text-nowrap"}},
|
|
1010
1052
|
)
|
|
1053
|
+
module_family = tables.Column(linkify=True, verbose_name="Family")
|
|
1011
1054
|
installed_module = tables.Column(linkify=True, verbose_name="Installed Module")
|
|
1012
1055
|
installed_module__status = ColoredLabelColumn(verbose_name="Installed Module Status")
|
|
1056
|
+
requires_first_party_modules = BooleanColumn(verbose_name="First-Party Only")
|
|
1013
1057
|
actions = ButtonsColumn(model=ModuleBay, buttons=("edit", "delete"), prepend_template=MODULEBAY_BUTTONS)
|
|
1014
1058
|
|
|
1015
1059
|
class Meta(ModularDeviceComponentTable.Meta):
|
|
@@ -1018,6 +1062,8 @@ class DeviceModuleBayTable(ModuleBayTable):
|
|
|
1018
1062
|
"pk",
|
|
1019
1063
|
"name",
|
|
1020
1064
|
"position",
|
|
1065
|
+
"module_family",
|
|
1066
|
+
"requires_first_party_modules",
|
|
1021
1067
|
"installed_module",
|
|
1022
1068
|
"installed_module__status",
|
|
1023
1069
|
"label",
|
|
@@ -1029,6 +1075,8 @@ class DeviceModuleBayTable(ModuleBayTable):
|
|
|
1029
1075
|
"pk",
|
|
1030
1076
|
"name",
|
|
1031
1077
|
"position",
|
|
1078
|
+
"module_family",
|
|
1079
|
+
"requires_first_party_modules",
|
|
1032
1080
|
"installed_module",
|
|
1033
1081
|
"installed_module__status",
|
|
1034
1082
|
"actions",
|
|
@@ -158,6 +158,7 @@ class ModuleTypeTable(BaseTable):
|
|
|
158
158
|
pk = ToggleColumn()
|
|
159
159
|
manufacturer = tables.Column(linkify=True)
|
|
160
160
|
model = tables.Column(linkify=True, verbose_name="Module Type")
|
|
161
|
+
module_family = tables.Column(linkify=True, verbose_name="Family")
|
|
161
162
|
module_count = LinkedCountColumn(
|
|
162
163
|
viewname="dcim:module_list",
|
|
163
164
|
url_params={"module_type": "pk"},
|
|
@@ -172,6 +173,7 @@ class ModuleTypeTable(BaseTable):
|
|
|
172
173
|
"model",
|
|
173
174
|
"manufacturer",
|
|
174
175
|
"part_number",
|
|
176
|
+
"module_family",
|
|
175
177
|
"module_count",
|
|
176
178
|
"tags",
|
|
177
179
|
)
|
|
@@ -180,6 +182,7 @@ class ModuleTypeTable(BaseTable):
|
|
|
180
182
|
"model",
|
|
181
183
|
"manufacturer",
|
|
182
184
|
"part_number",
|
|
185
|
+
"module_family",
|
|
183
186
|
"module_count",
|
|
184
187
|
)
|
|
185
188
|
|
|
@@ -333,8 +336,39 @@ class ModuleBayTemplateTable(ComponentTemplateTable):
|
|
|
333
336
|
buttons=("edit", "delete"),
|
|
334
337
|
return_url_extra=r"%3Ftab=modulebays",
|
|
335
338
|
)
|
|
339
|
+
module_family = tables.Column(verbose_name="Family", linkify=True)
|
|
340
|
+
requires_first_party_modules = BooleanColumn(verbose_name="Requires First-Party Modules")
|
|
336
341
|
|
|
337
342
|
class Meta(BaseTable.Meta):
|
|
338
343
|
model = ModuleBayTemplate
|
|
339
|
-
fields = (
|
|
344
|
+
fields = (
|
|
345
|
+
"pk",
|
|
346
|
+
"name",
|
|
347
|
+
"position",
|
|
348
|
+
"module_family",
|
|
349
|
+
"label",
|
|
350
|
+
"requires_first_party_modules",
|
|
351
|
+
"description",
|
|
352
|
+
"actions",
|
|
353
|
+
)
|
|
354
|
+
default_columns = (
|
|
355
|
+
"pk",
|
|
356
|
+
"name",
|
|
357
|
+
"position",
|
|
358
|
+
"module_family",
|
|
359
|
+
"label",
|
|
360
|
+
"requires_first_party_modules",
|
|
361
|
+
"description",
|
|
362
|
+
"actions",
|
|
363
|
+
)
|
|
364
|
+
field_order = (
|
|
365
|
+
"pk",
|
|
366
|
+
"name",
|
|
367
|
+
"position",
|
|
368
|
+
"module_family",
|
|
369
|
+
"label",
|
|
370
|
+
"requires_first_party_modules",
|
|
371
|
+
"description",
|
|
372
|
+
"actions",
|
|
373
|
+
)
|
|
340
374
|
empty_text = "None"
|
|
@@ -93,7 +93,9 @@ LINKED_RECORD_COUNT = """
|
|
|
93
93
|
|
|
94
94
|
TREE_LINK = """
|
|
95
95
|
{% load helpers %}
|
|
96
|
+
{% if not table.hide_hierarchy_ui %}
|
|
96
97
|
{% tree_hierarchy_ui_representation record.tree_depth|as_range table.hide_hierarchy_ui %}
|
|
98
|
+
{% endif %}
|
|
97
99
|
<a href="{{ record.get_absolute_url }}">{{ record.name }}</a>
|
|
98
100
|
"""
|
|
99
101
|
|
|
@@ -1,91 +1,2 @@
|
|
|
1
1
|
{% extends 'generic/object_retrieve.html' %}
|
|
2
|
-
{%
|
|
3
|
-
|
|
4
|
-
{% block extra_nav_tabs %}
|
|
5
|
-
{% if wireless_networks_count %}
|
|
6
|
-
<li role="presentation"{% if request.GET.tab == 'wireless_networks' %} class="active"{% endif %}>
|
|
7
|
-
<a href="{{ object.get_absolute_url }}#wireless_networks" onclick="switch_tab(this.href, reload=false)" aria-controls="wireless_networks" role="tab" data-toggle="tab">
|
|
8
|
-
Wireless Networks {% badge wireless_networks_count %}
|
|
9
|
-
</a>
|
|
10
|
-
</li>
|
|
11
|
-
{% endif %}
|
|
12
|
-
{% if radio_profiles_count %}
|
|
13
|
-
<li role="presentation"{% if request.GET.tab == 'radio_profiles' %} class="active"{% endif %}>
|
|
14
|
-
<a href="{{ object.get_absolute_url }}#radio_profiles" onclick="switch_tab(this.href, reload=false)" aria-controls="radio_profiles" role="tab" data-toggle="tab">
|
|
15
|
-
Radio Profiles {% badge radio_profiles_count %}
|
|
16
|
-
</a>
|
|
17
|
-
</li>
|
|
18
|
-
{% endif %}
|
|
19
|
-
{% endblock extra_nav_tabs %}
|
|
20
|
-
|
|
21
|
-
{% block extra_tab_content %}
|
|
22
|
-
{% if wireless_networks_count %}
|
|
23
|
-
<div id="wireless_networks" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "wireless_networks" %}active{% else %}fade{% endif %}">
|
|
24
|
-
<div class="panel panel-default">
|
|
25
|
-
<div class="panel-heading">
|
|
26
|
-
<strong>Wireless Networks</strong>
|
|
27
|
-
</div>
|
|
28
|
-
{% include 'inc/table.html' with table=wireless_networks_table %}
|
|
29
|
-
</div>
|
|
30
|
-
{% include 'inc/paginator.html' with paginator=wireless_networks_table.paginator page=wireless_networks_table.page %}
|
|
31
|
-
</div>
|
|
32
|
-
{% endif %}
|
|
33
|
-
{% if radio_profiles_count %}
|
|
34
|
-
<div id="radio_profiles" role="tabpanel" class="tab-pane {% if not active_tab and not request.GET.tab or request.GET.tab == "radio_profiles" %}active{% else %}fade{% endif %}">
|
|
35
|
-
<div class="panel panel-default">
|
|
36
|
-
<div class="panel-heading">
|
|
37
|
-
<strong>Radio Profiles</strong>
|
|
38
|
-
</div>
|
|
39
|
-
{% include 'panel_table.html' with table=radio_profiles_table %}
|
|
40
|
-
</div>
|
|
41
|
-
{% include 'inc/paginator.html' with paginator=radio_profiles_table.paginator page=radio_profiles_table.page %}
|
|
42
|
-
</div>
|
|
43
|
-
{% endif %}
|
|
44
|
-
{% endblock extra_tab_content %}
|
|
45
|
-
|
|
46
|
-
{% block content_left_page %}
|
|
47
|
-
<div class="panel panel-default">
|
|
48
|
-
<div class="panel-heading">
|
|
49
|
-
<strong>Controller</strong>
|
|
50
|
-
</div>
|
|
51
|
-
<div class="table-responsive">
|
|
52
|
-
<table class="table table-hover panel-body attr-table">
|
|
53
|
-
<tr>
|
|
54
|
-
<td>Name</td>
|
|
55
|
-
<td>{{ object.name|placeholder }}</td>
|
|
56
|
-
</tr>
|
|
57
|
-
<tr>
|
|
58
|
-
<td>Controller</td>
|
|
59
|
-
<td>{{ object.controller|hyperlinked_object }}</td>
|
|
60
|
-
</tr>
|
|
61
|
-
<tr>
|
|
62
|
-
<td>Parent</td>
|
|
63
|
-
<td>{{ object.parent|hyperlinked_object }}</td>
|
|
64
|
-
</tr>
|
|
65
|
-
<tr>
|
|
66
|
-
<td>Capabilities</td>
|
|
67
|
-
<td>{{ object.get_capabilities_display }}</td>
|
|
68
|
-
</tr>
|
|
69
|
-
<tr>
|
|
70
|
-
<td>Weight</td>
|
|
71
|
-
<td>{{ object.weight }}</td>
|
|
72
|
-
</tr>
|
|
73
|
-
{% include 'inc/tenant_table_row.html' %}
|
|
74
|
-
<tr>
|
|
75
|
-
<td>Description</td>
|
|
76
|
-
<td>{{ object.description|placeholder }}</td>
|
|
77
|
-
</tr>
|
|
78
|
-
</table>
|
|
79
|
-
</div>
|
|
80
|
-
</div>
|
|
81
|
-
{% endblock content_left_page %}
|
|
82
|
-
|
|
83
|
-
{% block content_full_width_page %}
|
|
84
|
-
<div class="panel panel-default">
|
|
85
|
-
<div class="panel-heading">
|
|
86
|
-
<strong>Devices</strong>
|
|
87
|
-
</div>
|
|
88
|
-
{% include 'responsive_table.html' with table=devices_table %}
|
|
89
|
-
</div>
|
|
90
|
-
{% include 'inc/paginator.html' with paginator=devices_table.paginator page=devices_table.page %}
|
|
91
|
-
{% endblock content_full_width_page %}
|
|
2
|
+
{% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
|