nautobot 2.3.0b1__py3-none-any.whl → 2.3.1__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/factory.py +2 -0
- nautobot/cloud/filters.py +3 -0
- nautobot/cloud/forms.py +8 -2
- nautobot/cloud/migrations/0001_initial.py +1 -1
- nautobot/cloud/models.py +1 -2
- nautobot/cloud/tables.py +1 -17
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +11 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +4 -0
- nautobot/cloud/tests/test_filters.py +12 -0
- nautobot/cloud/tests/test_views.py +17 -0
- nautobot/cloud/views.py +1 -1
- nautobot/core/celery/__init__.py +5 -2
- nautobot/core/filters.py +15 -1
- nautobot/core/forms/forms.py +10 -2
- nautobot/core/graphql/generators.py +2 -2
- nautobot/core/graphql/schema.py +6 -14
- nautobot/core/jobs/__init__.py +4 -1
- nautobot/core/management/commands/generate_test_data.py +2 -2
- nautobot/core/models/__init__.py +2 -2
- nautobot/core/settings.py +13 -2
- nautobot/core/settings.yaml +16 -2
- nautobot/core/tables.py +3 -0
- nautobot/core/templates/generic/object_retrieve.html +6 -6
- nautobot/core/templates/inc/computed_fields/panel_data.html +36 -24
- nautobot/core/templates/inc/object_details_advanced_panel.html +1 -1
- nautobot/core/templates/nautobot_config.py.j2 +15 -0
- nautobot/core/testing/filters.py +12 -1
- nautobot/core/tests/integration/test_general_functionality.py +1 -1
- nautobot/core/tests/test_jobs.py +74 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/generic.py +1 -1
- nautobot/core/views/mixins.py +1 -1
- nautobot/core/views/utils.py +8 -6
- nautobot/dcim/factory.py +4 -1
- nautobot/dcim/filters/__init__.py +4 -0
- nautobot/dcim/forms.py +24 -0
- nautobot/dcim/migrations/0061_module_models.py +1 -0
- nautobot/dcim/models/device_components.py +7 -0
- nautobot/dcim/models/devices.py +18 -19
- nautobot/dcim/models/racks.py +0 -1
- nautobot/dcim/tables/devices.py +17 -3
- nautobot/dcim/tables/devicetypes.py +1 -1
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device.html +3 -3
- nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +6 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +17 -0
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +3 -3
- nautobot/dcim/tests/test_api.py +2 -0
- nautobot/dcim/tests/test_filters.py +14 -7
- nautobot/dcim/tests/test_forms.py +54 -0
- nautobot/dcim/tests/test_models.py +40 -1
- nautobot/dcim/tests/test_views.py +45 -2
- nautobot/dcim/views.py +4 -1
- nautobot/extras/api/serializers.py +0 -1
- nautobot/extras/api/views.py +7 -59
- nautobot/extras/factory.py +50 -12
- nautobot/extras/filters/__init__.py +4 -1
- nautobot/extras/forms/base.py +10 -4
- nautobot/extras/forms/forms.py +1 -0
- nautobot/extras/homepage.py +12 -2
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/migrations/0111_metadata.py +4 -4
- nautobot/extras/migrations/0114_computedfield_grouping.py +17 -0
- nautobot/extras/models/customfields.py +54 -0
- nautobot/extras/models/jobs.py +83 -0
- nautobot/extras/models/metadata.py +18 -18
- nautobot/extras/models/models.py +2 -0
- nautobot/extras/signals.py +14 -1
- nautobot/extras/tables.py +43 -14
- nautobot/extras/templates/extras/computedfield.html +4 -0
- nautobot/extras/templates/extras/job_detail.html +11 -0
- nautobot/extras/tests/test_api.py +16 -9
- nautobot/extras/tests/test_jobs.py +2 -2
- nautobot/extras/tests/test_models.py +20 -18
- nautobot/extras/tests/test_views.py +23 -3
- nautobot/extras/utils.py +35 -6
- nautobot/extras/views.py +28 -51
- nautobot/ipam/filters.py +1 -1
- nautobot/ipam/forms.py +1 -1
- nautobot/ipam/models.py +9 -20
- nautobot/ipam/querysets.py +26 -0
- nautobot/ipam/tables.py +4 -0
- nautobot/ipam/tests/test_models.py +89 -2
- nautobot/ipam/views.py +10 -15
- nautobot/project-static/css/base.css +1 -0
- nautobot/project-static/docs/404.html +18 -18
- nautobot/project-static/docs/apps/index.html +18 -18
- nautobot/project-static/docs/apps/nautobot-apps.html +18 -18
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +66 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +66 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +34 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +82 -63
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +75 -111
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +34 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +161 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +18 -18
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +21 -19
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +34 -18
- nautobot/project-static/docs/development/apps/api/configuration-view.html +18 -18
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/global-search.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -18
- nautobot/project-static/docs/development/apps/api/models/index.html +33 -22
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +18 -18
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +18 -18
- nautobot/project-static/docs/development/apps/api/prometheus.html +18 -18
- nautobot/project-static/docs/development/apps/api/setup.html +18 -18
- nautobot/project-static/docs/development/apps/api/testing.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +18 -18
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/base-template.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/index.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/notes.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +18 -18
- nautobot/project-static/docs/development/apps/api/views/urls.html +18 -18
- nautobot/project-static/docs/development/apps/index.html +18 -18
- nautobot/project-static/docs/development/apps/migration/code-updates.html +18 -18
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +18 -18
- nautobot/project-static/docs/development/apps/migration/from-v1.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +18 -18
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +18 -18
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +18 -18
- nautobot/project-static/docs/development/core/application-registry.html +18 -18
- nautobot/project-static/docs/development/core/best-practices.html +18 -18
- nautobot/project-static/docs/development/core/bootstrap-ui.html +18 -18
- nautobot/project-static/docs/development/core/caching.html +18 -18
- nautobot/project-static/docs/development/core/controllers.html +18 -18
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +18 -18
- nautobot/project-static/docs/development/core/generic-views.html +18 -18
- nautobot/project-static/docs/development/core/getting-started.html +18 -18
- nautobot/project-static/docs/development/core/homepage.html +18 -18
- nautobot/project-static/docs/development/core/index.html +29 -18
- nautobot/project-static/docs/development/core/model-checklist.html +26 -20
- nautobot/project-static/docs/development/core/model-features.html +18 -18
- nautobot/project-static/docs/development/core/natural-keys.html +18 -18
- nautobot/project-static/docs/development/core/navigation-menu.html +18 -18
- nautobot/project-static/docs/development/core/release-checklist.html +18 -18
- nautobot/project-static/docs/development/core/role-internals.html +18 -18
- nautobot/project-static/docs/development/core/settings.html +18 -18
- nautobot/project-static/docs/development/core/style-guide.html +19 -19
- nautobot/project-static/docs/development/core/templates.html +18 -18
- nautobot/project-static/docs/development/core/testing.html +18 -18
- nautobot/project-static/docs/development/core/user-preferences.html +18 -18
- nautobot/project-static/docs/development/index.html +18 -18
- nautobot/project-static/docs/development/jobs/index.html +393 -379
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +18 -18
- nautobot/project-static/docs/index.html +9032 -13
- nautobot/project-static/docs/models/extras/metadatachoice.html +3 -3
- nautobot/project-static/docs/models/extras/metadatatype.html +3 -3
- nautobot/project-static/docs/models/extras/objectmetadata.html +3 -3
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +18 -18
- nautobot/project-static/docs/overview/design_philosophy.html +20 -20
- nautobot/project-static/docs/overview/index.html +13 -9032
- nautobot/project-static/docs/release-notes/index.html +252 -19
- nautobot/project-static/docs/release-notes/version-1.0.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.1.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.2.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.3.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.4.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.5.html +18 -18
- nautobot/project-static/docs/release-notes/version-1.6.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.0.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.1.html +18 -18
- nautobot/project-static/docs/release-notes/version-2.2.html +248 -111
- nautobot/project-static/docs/release-notes/version-2.3.html +644 -90
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +278 -278
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +52 -20
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +18 -18
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +22 -18
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +18 -18
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +69 -82
- nautobot/project-static/docs/user-guide/administration/installation/index.html +24 -24
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +60 -52
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +80 -87
- nautobot/project-static/docs/user-guide/administration/installation/services.html +37 -44
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +18 -18
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +18 -18
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +18 -18
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +18 -18
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +76 -24
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +18 -18
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +19 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +19 -19
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +62 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +18 -18
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +18 -18
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +18 -18
- nautobot/project-static/docs/user-guide/index.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +21 -21
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +36 -36
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -33
- nautobot/project-static/docs/user-guide/platform-functionality/{metadata.html → objectmetadata.html} +197 -84
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +21 -21
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +18 -18
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +18 -18
- nautobot/tenancy/templates/tenancy/tenant.html +4 -4
- nautobot/virtualization/models.py +0 -2
- nautobot/virtualization/tables.py +2 -5
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/METADATA +3 -3
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/RECORD +378 -377
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/NOTICE +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/WHEEL +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.1.dist-info}/entry_points.txt +0 -0
|
@@ -295,6 +295,15 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
|
|
|
295
295
|
# CELERY_TASK_SOFT_TIME_LIMIT = int(os.getenv("NAUTOBOT_CELERY_TASK_SOFT_TIME_LIMIT", str(5 * 60)))
|
|
296
296
|
# CELERY_TASK_TIME_LIMIT = int(os.getenv("NAUTOBOT_CELERY_TASK_TIME_LIMIT", str(10 * 60)))
|
|
297
297
|
|
|
298
|
+
# How many tasks a worker is allowed to reserve for its own consumption and execution.
|
|
299
|
+
# If set to zero (not recommended) a single worker can reserve all tasks even if other workers are free.
|
|
300
|
+
# For short running tasks (such as webhooks) you may want to set this to a larger number to increase throughput.
|
|
301
|
+
# Conversely, for long running tasks (such as SSoT or Golden-Config Jobs at scale) you may want to set this to 1
|
|
302
|
+
# so that a worker executing a long-running task will not prefetch other tasks, which would block their execution
|
|
303
|
+
# until the long-running task completes.
|
|
304
|
+
# https://docs.celeryq.dev/en/stable/userguide/optimizing.html#prefetch-limits
|
|
305
|
+
# CELERY_WORKER_PREFETCH_MULTIPLIER = int(os.getenv("NAUTOBOT_CELERY_WORKER_PREFETCH_MULTIPLIER", "4"))
|
|
306
|
+
|
|
298
307
|
# Ports for prometheus metric HTTP server running on the celery worker.
|
|
299
308
|
# Normally this should be set to a single port, unless you have multiple workers running on a single machine, i.e.
|
|
300
309
|
# sharing the same available ports. In that case you need to specify a range of ports greater than or equal to the
|
|
@@ -307,6 +316,12 @@ SECRET_KEY = os.getenv("NAUTOBOT_SECRET_KEY", "{{ secret_key }}")
|
|
|
307
316
|
# int(value) for value in os.getenv("NAUTOBOT_CELERY_WORKER_PROMETHEUS_PORTS").split(",")
|
|
308
317
|
# ]
|
|
309
318
|
|
|
319
|
+
# If enabled stdout and stderr of running jobs will be redirected to the task logger.
|
|
320
|
+
# CELERY_WORKER_REDIRECT_STDOUTS = is_truthy(os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS", "True"))
|
|
321
|
+
|
|
322
|
+
# The log level of log messages generated by redirected job stdout and stderr.
|
|
323
|
+
# Can be one of `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`.
|
|
324
|
+
# CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = os.getenv("NAUTOBOT_CELERY_WORKER_REDIRECT_STDOUTS_LEVEL", "WARNING")
|
|
310
325
|
|
|
311
326
|
# Number of days to retain changelog entries. Set to 0 to retain changes indefinitely. Defaults to 90 if not set here.
|
|
312
327
|
#
|
nautobot/core/testing/filters.py
CHANGED
|
@@ -132,6 +132,17 @@ class FilterTestCases:
|
|
|
132
132
|
if generic_filter_test not in self.generic_filter_tests:
|
|
133
133
|
self.generic_filter_tests = (*self.generic_filter_tests, generic_filter_test)
|
|
134
134
|
|
|
135
|
+
# Make sure we have at least 3 contacts and 3 teams in the database
|
|
136
|
+
if Contact.objects.count() < 3:
|
|
137
|
+
Contact.objects.create(name="Generic Filter Test Contact 1")
|
|
138
|
+
Contact.objects.create(name="Generic Filter Test Contact 2")
|
|
139
|
+
Contact.objects.create(name="Generic Filter Test Contact 3")
|
|
140
|
+
|
|
141
|
+
if Team.objects.count() < 3:
|
|
142
|
+
Team.objects.create(name="Generic Filter Test Team 1")
|
|
143
|
+
Team.objects.create(name="Generic Filter Test Team 2")
|
|
144
|
+
Team.objects.create(name="Generic Filter Test Team 3")
|
|
145
|
+
|
|
135
146
|
# Make sure we have some valid contact-associations:
|
|
136
147
|
for contact, team, instance in zip(Contact.objects.all()[:3], Team.objects.all()[:3], self.queryset):
|
|
137
148
|
ContactAssociation.objects.create(
|
|
@@ -272,7 +283,7 @@ class FilterTestCases:
|
|
|
272
283
|
# if lookup_method is iexact use the full updated attr
|
|
273
284
|
if lookup_method == "iexact":
|
|
274
285
|
lookup = randomized_attr_value.upper()
|
|
275
|
-
model_queryset = self.queryset.filter(**{f"{filter_field_name}": lookup})
|
|
286
|
+
model_queryset = self.queryset.filter(**{f"{filter_field_name}__iexact": lookup})
|
|
276
287
|
else:
|
|
277
288
|
lookup = randomized_attr_value[1:].upper()
|
|
278
289
|
model_queryset = self.queryset.filter(**{f"{filter_field_name}__icontains": lookup})
|
nautobot/core/tests/test_jobs.py
CHANGED
|
@@ -3,24 +3,27 @@ from pathlib import Path
|
|
|
3
3
|
|
|
4
4
|
from django.contrib.contenttypes.models import ContentType
|
|
5
5
|
from django.core.cache import cache
|
|
6
|
+
from django.core.files.base import ContentFile
|
|
6
7
|
from django.utils import timezone
|
|
7
8
|
import yaml
|
|
8
9
|
|
|
9
10
|
from nautobot.core.jobs.cleanup import CleanupTypes
|
|
10
11
|
from nautobot.core.testing import create_job_result_and_run_job, TransactionTestCase
|
|
11
|
-
from nautobot.dcim.models import DeviceType, Location, LocationType, Manufacturer
|
|
12
|
+
from nautobot.dcim.models import Device, DeviceType, Location, LocationType, Manufacturer
|
|
12
13
|
from nautobot.extras.choices import JobResultStatusChoices, LogLevelChoices
|
|
13
14
|
from nautobot.extras.factory import JobResultFactory, ObjectChangeFactory
|
|
14
15
|
from nautobot.extras.models import (
|
|
15
16
|
Contact,
|
|
16
17
|
ContactAssociation,
|
|
17
18
|
ExportTemplate,
|
|
19
|
+
FileProxy,
|
|
18
20
|
JobLogEntry,
|
|
19
21
|
JobResult,
|
|
20
22
|
ObjectChange,
|
|
21
23
|
Role,
|
|
22
24
|
Status,
|
|
23
25
|
)
|
|
26
|
+
from nautobot.ipam.models import Prefix
|
|
24
27
|
from nautobot.users.models import ObjectPermission
|
|
25
28
|
|
|
26
29
|
|
|
@@ -218,6 +221,76 @@ class ImportObjectsTestCase(TransactionTestCase):
|
|
|
218
221
|
)
|
|
219
222
|
self.assertEqual(4, Status.objects.filter(name__startswith="test_status").count())
|
|
220
223
|
|
|
224
|
+
def test_csv_import_with_utf_8_with_bom_encoding(self):
|
|
225
|
+
"""
|
|
226
|
+
A superuser running the job with a .csv file with utf_8 with bom encoding should successfully create all specified objects.
|
|
227
|
+
Test for bug fix https://github.com/nautobot/nautobot/issues/5812 and https://github.com/nautobot/nautobot/issues/5985
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
status = Status.objects.get(name="Active").pk
|
|
231
|
+
content = f"prefix,status\n192.168.1.1/32,{status}"
|
|
232
|
+
content = content.encode("utf-8-sig")
|
|
233
|
+
filename = "test.csv"
|
|
234
|
+
csv_file = FileProxy.objects.create(name=filename, file=ContentFile(content, name=filename))
|
|
235
|
+
job_result = create_job_result_and_run_job(
|
|
236
|
+
"nautobot.core.jobs",
|
|
237
|
+
"ImportObjects",
|
|
238
|
+
content_type=ContentType.objects.get_for_model(Prefix).pk,
|
|
239
|
+
csv_file=csv_file.id,
|
|
240
|
+
)
|
|
241
|
+
self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
|
|
242
|
+
self.assertFalse(
|
|
243
|
+
JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_WARNING).exists()
|
|
244
|
+
)
|
|
245
|
+
self.assertFalse(
|
|
246
|
+
JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR).exists()
|
|
247
|
+
)
|
|
248
|
+
self.assertEqual(
|
|
249
|
+
1, Prefix.objects.filter(status=Status.objects.get(name="Active"), prefix="192.168.1.1/32").count()
|
|
250
|
+
)
|
|
251
|
+
mfr = Manufacturer.objects.create(name="Test Cisco Manufacturer")
|
|
252
|
+
device_type = DeviceType.objects.create(
|
|
253
|
+
manufacturer=mfr,
|
|
254
|
+
model="Cisco CSR1000v",
|
|
255
|
+
u_height=0,
|
|
256
|
+
)
|
|
257
|
+
location_type = LocationType.objects.create(name="Test Location Type")
|
|
258
|
+
location_type.content_types.set([ContentType.objects.get_for_model(Device)])
|
|
259
|
+
location = Location.objects.create(
|
|
260
|
+
name="Device Location",
|
|
261
|
+
location_type=location_type,
|
|
262
|
+
status=Status.objects.get_for_model(Location).first(),
|
|
263
|
+
)
|
|
264
|
+
role = Role.objects.create(name="Device Status")
|
|
265
|
+
role.content_types.set([ContentType.objects.get_for_model(Device)])
|
|
266
|
+
content = "\n".join(
|
|
267
|
+
[
|
|
268
|
+
"serial,asset_tag,device_type,location,status,name,role",
|
|
269
|
+
f"1021C4,CA211,{device_type.pk},{location.pk},{status},Test-AC-01,{role}",
|
|
270
|
+
f"1021C5,CA212,{device_type.pk},{location.pk},{status},Test-AC-02,{role}",
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
content = content.encode("utf-8-sig")
|
|
274
|
+
filename = "test.csv"
|
|
275
|
+
csv_file = FileProxy.objects.create(name=filename, file=ContentFile(content, name=filename))
|
|
276
|
+
job_result = create_job_result_and_run_job(
|
|
277
|
+
"nautobot.core.jobs",
|
|
278
|
+
"ImportObjects",
|
|
279
|
+
content_type=ContentType.objects.get_for_model(Device).pk,
|
|
280
|
+
csv_file=csv_file.id,
|
|
281
|
+
)
|
|
282
|
+
self.assertEqual(job_result.status, JobResultStatusChoices.STATUS_SUCCESS)
|
|
283
|
+
self.assertFalse(
|
|
284
|
+
JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_WARNING).exists()
|
|
285
|
+
)
|
|
286
|
+
self.assertFalse(
|
|
287
|
+
JobLogEntry.objects.filter(job_result=job_result, log_level=LogLevelChoices.LOG_ERROR).exists()
|
|
288
|
+
)
|
|
289
|
+
device_1 = Device.objects.get(name="Test-AC-01")
|
|
290
|
+
device_2 = Device.objects.get(name="Test-AC-02")
|
|
291
|
+
self.assertEqual(device_1.serial, "1021C4")
|
|
292
|
+
self.assertEqual(device_2.serial, "1021C5")
|
|
293
|
+
|
|
221
294
|
def test_csv_import_bad_row(self):
|
|
222
295
|
"""A row of incorrect data should fail validation for that object but import all others successfully if `roll_back_if_error` is False."""
|
|
223
296
|
csv_data = self.csv_data.split("\n")
|
nautobot/core/views/__init__.py
CHANGED
|
@@ -299,7 +299,7 @@ class SearchView(AccessMixin, View):
|
|
|
299
299
|
|
|
300
300
|
# Construct the results table for this object type
|
|
301
301
|
filtered_queryset = filterset({"q": form.cleaned_data["q"]}, queryset=queryset).qs
|
|
302
|
-
table = table(filtered_queryset, orderable=False)
|
|
302
|
+
table = table(filtered_queryset, hide_hierarchy_ui=True, orderable=False)
|
|
303
303
|
table.paginate(per_page=SEARCH_MAX_RESULTS)
|
|
304
304
|
|
|
305
305
|
if table.page:
|
nautobot/core/views/generic.py
CHANGED
|
@@ -586,6 +586,7 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
586
586
|
|
|
587
587
|
if form.is_valid():
|
|
588
588
|
logger.debug("Form validation was successful")
|
|
589
|
+
msg = f"Deleted {self.queryset.model._meta.verbose_name} {obj}"
|
|
589
590
|
|
|
590
591
|
try:
|
|
591
592
|
obj.delete()
|
|
@@ -594,7 +595,6 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
594
595
|
handle_protectederror([obj], request, e)
|
|
595
596
|
return redirect(obj.get_absolute_url())
|
|
596
597
|
|
|
597
|
-
msg = f"Deleted {self.queryset.model._meta.verbose_name} {obj}"
|
|
598
598
|
logger.info(msg)
|
|
599
599
|
messages.success(request, msg)
|
|
600
600
|
|
nautobot/core/views/mixins.py
CHANGED
|
@@ -745,8 +745,8 @@ class ObjectDestroyViewMixin(NautobotViewSetMixin, mixins.DestroyModelMixin):
|
|
|
745
745
|
queryset = self.get_queryset()
|
|
746
746
|
try:
|
|
747
747
|
with transaction.atomic():
|
|
748
|
-
obj.delete()
|
|
749
748
|
msg = f"Deleted {queryset.model._meta.verbose_name} {obj}"
|
|
749
|
+
obj.delete()
|
|
750
750
|
self.logger.info(msg)
|
|
751
751
|
messages.success(request, msg)
|
|
752
752
|
self.success_url = self.get_return_url(request, obj)
|
nautobot/core/views/utils.py
CHANGED
|
@@ -360,12 +360,14 @@ def common_detail_view_context(request, instance):
|
|
|
360
360
|
|
|
361
361
|
if instance.is_metadata_associable_model:
|
|
362
362
|
paginate = {"paginator_class": EnhancedPaginator, "per_page": get_paginate_count(request)}
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
363
|
+
object_metadata = instance.associated_object_metadata.restrict(request.user, "view").order_by(
|
|
364
|
+
"metadata_type", "scoped_fields"
|
|
365
|
+
)
|
|
366
|
+
object_metadata_table = ObjectMetadataTable(object_metadata, orderable=False)
|
|
367
|
+
object_metadata_table.columns.hide("assigned_object")
|
|
368
|
+
RequestConfig(request, paginate).configure(object_metadata_table)
|
|
369
|
+
context["associated_object_metadata_table"] = object_metadata_table
|
|
368
370
|
else:
|
|
369
|
-
context["
|
|
371
|
+
context["associated_object_metadata_table"] = None
|
|
370
372
|
|
|
371
373
|
return context
|
nautobot/dcim/factory.py
CHANGED
|
@@ -760,13 +760,16 @@ module_types = (
|
|
|
760
760
|
class ModuleTypeFactory(PrimaryModelFactory):
|
|
761
761
|
class Meta:
|
|
762
762
|
model = ModuleType
|
|
763
|
-
exclude = ("has_part_number",)
|
|
763
|
+
exclude = ("has_part_number", "has_comments")
|
|
764
764
|
|
|
765
765
|
manufacturer = random_instance(Manufacturer, allow_null=False)
|
|
766
766
|
|
|
767
767
|
has_part_number = NautobotBoolIterator()
|
|
768
768
|
part_number = factory.Maybe("has_part_number", factory.Faker("ean", length=8), "")
|
|
769
769
|
|
|
770
|
+
has_comments = NautobotBoolIterator()
|
|
771
|
+
comments = factory.Maybe("has_comments", factory.Faker("bs"))
|
|
772
|
+
|
|
770
773
|
@factory.lazy_attribute
|
|
771
774
|
def model(self):
|
|
772
775
|
"""
|
|
@@ -1999,6 +1999,10 @@ class ModuleTypeFilterSet(DeviceTypeModuleTypeCommonFiltersMixin, NautobotFilter
|
|
|
1999
1999
|
"lookup_expr": "icontains",
|
|
2000
2000
|
"preprocessor": str.strip,
|
|
2001
2001
|
},
|
|
2002
|
+
"comments": {
|
|
2003
|
+
"lookup_expr": "icontains",
|
|
2004
|
+
"preprocessor": str.strip,
|
|
2005
|
+
},
|
|
2002
2006
|
},
|
|
2003
2007
|
)
|
|
2004
2008
|
has_modules = RelatedMembershipBooleanFilter(
|
nautobot/dcim/forms.py
CHANGED
|
@@ -886,6 +886,7 @@ class DeviceTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
|
886
886
|
software_image_files = DynamicModelMultipleChoiceField(queryset=SoftwareImageFile.objects.all(), required=False)
|
|
887
887
|
u_height = forms.IntegerField(required=False)
|
|
888
888
|
is_full_depth = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect(), label="Is full depth")
|
|
889
|
+
comments = CommentField(label="Comments", required=False)
|
|
889
890
|
|
|
890
891
|
class Meta:
|
|
891
892
|
nullable_fields = ["device_family", "software_image_files"]
|
|
@@ -946,6 +947,7 @@ class DeviceTypeFilterForm(NautobotFilterForm):
|
|
|
946
947
|
|
|
947
948
|
class ModuleTypeForm(NautobotModelForm):
|
|
948
949
|
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all())
|
|
950
|
+
comments = CommentField(label="Comments")
|
|
949
951
|
|
|
950
952
|
class Meta:
|
|
951
953
|
model = ModuleType
|
|
@@ -953,6 +955,7 @@ class ModuleTypeForm(NautobotModelForm):
|
|
|
953
955
|
"manufacturer",
|
|
954
956
|
"model",
|
|
955
957
|
"part_number",
|
|
958
|
+
"comments",
|
|
956
959
|
"tags",
|
|
957
960
|
]
|
|
958
961
|
|
|
@@ -974,6 +977,7 @@ class ModuleTypeImportForm(BootstrapMixin, forms.ModelForm):
|
|
|
974
977
|
"manufacturer",
|
|
975
978
|
"model",
|
|
976
979
|
"part_number",
|
|
980
|
+
"comments",
|
|
977
981
|
]
|
|
978
982
|
|
|
979
983
|
|
|
@@ -981,6 +985,7 @@ class ModuleTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
|
981
985
|
pk = forms.ModelMultipleChoiceField(queryset=ModuleType.objects.all(), widget=forms.MultipleHiddenInput())
|
|
982
986
|
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
|
983
987
|
part_number = forms.CharField(required=False)
|
|
988
|
+
comments = CommentField(label="Comments", required=False)
|
|
984
989
|
|
|
985
990
|
class Meta:
|
|
986
991
|
nullable_fields = []
|
|
@@ -2059,6 +2064,25 @@ class DeviceForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm, LocalC
|
|
|
2059
2064
|
if position:
|
|
2060
2065
|
self.fields["position"].widget.choices = [(position, f"U{position}")]
|
|
2061
2066
|
|
|
2067
|
+
def clean(self):
|
|
2068
|
+
super().clean()
|
|
2069
|
+
|
|
2070
|
+
device_type = self.cleaned_data["device_type"]
|
|
2071
|
+
software_image_files = self.cleaned_data["software_image_files"]
|
|
2072
|
+
|
|
2073
|
+
# If any software image file is specified, validate that
|
|
2074
|
+
# each of the software image files belongs to the device's device type or is a default image
|
|
2075
|
+
for image_file in software_image_files:
|
|
2076
|
+
if not image_file.default_image and device_type not in image_file.device_types.all():
|
|
2077
|
+
raise ValidationError(
|
|
2078
|
+
{
|
|
2079
|
+
"software_image_files": (
|
|
2080
|
+
f"Software image file {image_file} for version '{image_file.software_version}' is not "
|
|
2081
|
+
f"valid for device type {device_type}."
|
|
2082
|
+
)
|
|
2083
|
+
}
|
|
2084
|
+
)
|
|
2085
|
+
|
|
2062
2086
|
def save(self, *args, **kwargs):
|
|
2063
2087
|
instance = super().save(*args, **kwargs)
|
|
2064
2088
|
instance.vrfs.set(self.cleaned_data["vrfs"])
|
|
@@ -138,6 +138,7 @@ class Migration(migrations.Migration):
|
|
|
138
138
|
),
|
|
139
139
|
("model", models.CharField(max_length=255)),
|
|
140
140
|
("part_number", models.CharField(blank=True, max_length=255)),
|
|
141
|
+
("comments", models.TextField(blank=True)),
|
|
141
142
|
],
|
|
142
143
|
options={
|
|
143
144
|
"ordering": ("manufacturer", "model"),
|
|
@@ -26,6 +26,7 @@ from nautobot.dcim.choices import (
|
|
|
26
26
|
PowerOutletFeedLegChoices,
|
|
27
27
|
PowerOutletTypeChoices,
|
|
28
28
|
PowerPortTypeChoices,
|
|
29
|
+
SubdeviceRoleChoices,
|
|
29
30
|
)
|
|
30
31
|
from nautobot.dcim.constants import (
|
|
31
32
|
NONCONNECTABLE_IFACE_TYPES,
|
|
@@ -1096,6 +1097,12 @@ class DeviceBay(ComponentModel):
|
|
|
1096
1097
|
"installed_device": f"Cannot install the specified device; device is already installed in {current_bay}"
|
|
1097
1098
|
}
|
|
1098
1099
|
)
|
|
1100
|
+
if self.installed_device.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_CHILD:
|
|
1101
|
+
raise ValidationError(
|
|
1102
|
+
{
|
|
1103
|
+
"installed_device": f'Cannot install device "{self.installed_device}"; device-type "{self.installed_device.device_type}" subdevice_role is not "child".'
|
|
1104
|
+
}
|
|
1105
|
+
)
|
|
1099
1106
|
|
|
1100
1107
|
|
|
1101
1108
|
#
|
nautobot/dcim/models/devices.py
CHANGED
|
@@ -452,7 +452,6 @@ class Platform(OrganizationalModel):
|
|
|
452
452
|
@extras_features(
|
|
453
453
|
"custom_links",
|
|
454
454
|
"custom_validators",
|
|
455
|
-
"dynamic_groups",
|
|
456
455
|
"export_templates",
|
|
457
456
|
"graphql",
|
|
458
457
|
"locations",
|
|
@@ -819,21 +818,18 @@ class Device(PrimaryModel, ConfigContextModel):
|
|
|
819
818
|
}
|
|
820
819
|
)
|
|
821
820
|
|
|
822
|
-
#
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
)
|
|
835
|
-
}
|
|
836
|
-
)
|
|
821
|
+
# If any software image file is specified, validate that
|
|
822
|
+
# each of the software image files belongs to the device's device type or is a default image
|
|
823
|
+
for image_file in self.software_image_files.all():
|
|
824
|
+
if not image_file.default_image and self.device_type not in image_file.device_types.all():
|
|
825
|
+
raise ValidationError(
|
|
826
|
+
{
|
|
827
|
+
"software_image_files": (
|
|
828
|
+
f"Software image file {image_file} for version '{image_file.software_version}' is not "
|
|
829
|
+
f"valid for device type {self.device_type}."
|
|
830
|
+
)
|
|
831
|
+
}
|
|
832
|
+
)
|
|
837
833
|
|
|
838
834
|
def save(self, *args, **kwargs):
|
|
839
835
|
is_new = not self.present_in_database
|
|
@@ -1109,7 +1105,6 @@ class VirtualChassis(PrimaryModel):
|
|
|
1109
1105
|
@extras_features(
|
|
1110
1106
|
"custom_links",
|
|
1111
1107
|
"custom_validators",
|
|
1112
|
-
"dynamic_groups",
|
|
1113
1108
|
"export_templates",
|
|
1114
1109
|
"graphql",
|
|
1115
1110
|
"statuses",
|
|
@@ -1155,6 +1150,10 @@ class DeviceRedundancyGroup(PrimaryModel):
|
|
|
1155
1150
|
def devices_sorted(self):
|
|
1156
1151
|
return self.devices.order_by("device_redundancy_group_priority")
|
|
1157
1152
|
|
|
1153
|
+
@property
|
|
1154
|
+
def controllers_sorted(self):
|
|
1155
|
+
return self.controllers.order_by("name")
|
|
1156
|
+
|
|
1158
1157
|
def __str__(self):
|
|
1159
1158
|
return self.name
|
|
1160
1159
|
|
|
@@ -1337,7 +1336,6 @@ class SoftwareVersion(PrimaryModel):
|
|
|
1337
1336
|
@extras_features(
|
|
1338
1337
|
"custom_links",
|
|
1339
1338
|
"custom_validators",
|
|
1340
|
-
"dynamic_groups",
|
|
1341
1339
|
"export_templates",
|
|
1342
1340
|
"graphql",
|
|
1343
1341
|
"locations",
|
|
@@ -1421,7 +1419,6 @@ class Controller(PrimaryModel):
|
|
|
1421
1419
|
@extras_features(
|
|
1422
1420
|
"custom_links",
|
|
1423
1421
|
"custom_validators",
|
|
1424
|
-
"dynamic_groups",
|
|
1425
1422
|
"export_templates",
|
|
1426
1423
|
"graphql",
|
|
1427
1424
|
"webhooks",
|
|
@@ -1510,6 +1507,7 @@ class ModuleType(PrimaryModel):
|
|
|
1510
1507
|
part_number = models.CharField(
|
|
1511
1508
|
max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Discrete part number (optional)"
|
|
1512
1509
|
)
|
|
1510
|
+
comments = models.TextField(blank=True)
|
|
1513
1511
|
|
|
1514
1512
|
clone_fields = [
|
|
1515
1513
|
"manufacturer",
|
|
@@ -1530,6 +1528,7 @@ class ModuleType(PrimaryModel):
|
|
|
1530
1528
|
("manufacturer", self.manufacturer.name),
|
|
1531
1529
|
("model", self.model),
|
|
1532
1530
|
("part_number", self.part_number),
|
|
1531
|
+
("comments", self.comments),
|
|
1533
1532
|
)
|
|
1534
1533
|
)
|
|
1535
1534
|
|
nautobot/dcim/models/racks.py
CHANGED
nautobot/dcim/tables/devices.py
CHANGED
|
@@ -261,7 +261,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
|
|
|
261
261
|
)
|
|
262
262
|
location = tables.Column(linkify=True)
|
|
263
263
|
tenant = TenantColumn()
|
|
264
|
-
tags = TagColumn(url_name="dcim:
|
|
264
|
+
tags = TagColumn(url_name="dcim:module_list")
|
|
265
265
|
actions = ButtonsColumn(Module, prepend_template=MODULE_BUTTONS)
|
|
266
266
|
|
|
267
267
|
class Meta(BaseTable.Meta):
|
|
@@ -1125,13 +1125,27 @@ class DeviceRedundancyGroupTable(BaseTable):
|
|
|
1125
1125
|
url_params={"device_redundancy_group": "pk"},
|
|
1126
1126
|
verbose_name="Devices",
|
|
1127
1127
|
)
|
|
1128
|
+
controller_count = LinkedCountColumn(
|
|
1129
|
+
viewname="dcim:controller_list",
|
|
1130
|
+
url_params={"controller_device_redundancy_group": "pk"},
|
|
1131
|
+
verbose_name="Controllers",
|
|
1132
|
+
)
|
|
1128
1133
|
secrets_group = tables.Column(linkify=True)
|
|
1129
1134
|
tags = TagColumn(url_name="dcim:deviceredundancygroup_list")
|
|
1130
1135
|
|
|
1131
1136
|
class Meta(BaseTable.Meta):
|
|
1132
1137
|
model = DeviceRedundancyGroup
|
|
1133
|
-
fields = (
|
|
1134
|
-
|
|
1138
|
+
fields = (
|
|
1139
|
+
"pk",
|
|
1140
|
+
"name",
|
|
1141
|
+
"status",
|
|
1142
|
+
"failover_strategy",
|
|
1143
|
+
"controller_count",
|
|
1144
|
+
"device_count",
|
|
1145
|
+
"secrets_group",
|
|
1146
|
+
"tags",
|
|
1147
|
+
)
|
|
1148
|
+
default_columns = ("pk", "name", "status", "failover_strategy", "controller_count", "device_count")
|
|
1135
1149
|
|
|
1136
1150
|
|
|
1137
1151
|
#
|
|
@@ -160,7 +160,7 @@ class ModuleTypeTable(BaseTable):
|
|
|
160
160
|
url_params={"module_type": "pk"},
|
|
161
161
|
verbose_name="Modules",
|
|
162
162
|
)
|
|
163
|
-
tags = TagColumn(url_name="dcim:
|
|
163
|
+
tags = TagColumn(url_name="dcim:moduletype_list")
|
|
164
164
|
|
|
165
165
|
class Meta(BaseTable.Meta):
|
|
166
166
|
model = ModuleType
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
<a href="{% url 'dcim:device_modulebays' pk=object.pk %}">Modules {% badge module_count %}</a>
|
|
72
72
|
</li>
|
|
73
73
|
{% endif %}
|
|
74
|
-
{% with interface_count=object.
|
|
74
|
+
{% with interface_count=object.vc_interfaces.count %}
|
|
75
75
|
{% if interface_count %}
|
|
76
76
|
<li role="presentation" {% if active_tab == 'interfaces' %} class="active"{% endif %}>
|
|
77
77
|
<a href="{% url 'dcim:device_interfaces' pk=object.pk %}">Interfaces {% badge interface_count %}</a>
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
{% include 'dcim/inc/detail_softwareversion_softwareimagefile_rows.html' %}
|
|
234
234
|
</table>
|
|
235
235
|
</div>
|
|
236
|
-
{% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic computed_fields_advanced_ui=False %}
|
|
236
|
+
{% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic computed_fields=object.get_computed_fields_grouping_basic computed_fields_advanced_ui=False %}
|
|
237
237
|
{% include 'inc/relationships/panel_override.html' with relationships_fields_override=object.get_relationships_data_basic_fields %}
|
|
238
238
|
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:device_list' %}
|
|
239
239
|
<div class="panel panel-default">
|
|
@@ -427,7 +427,7 @@
|
|
|
427
427
|
</div>
|
|
428
428
|
{% endif %}
|
|
429
429
|
{% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
|
|
430
|
-
<div id="
|
|
430
|
+
<div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
|
|
431
431
|
<div class="row">
|
|
432
432
|
<div class="col-md-12">
|
|
433
433
|
<form method="post">
|
|
@@ -440,7 +440,7 @@
|
|
|
440
440
|
</div>
|
|
441
441
|
</div>
|
|
442
442
|
<div class="table-responsive">
|
|
443
|
-
{% render_table
|
|
443
|
+
{% render_table associated_object_metadata_table 'inc/table.html' %}
|
|
444
444
|
</div>
|
|
445
445
|
</div>
|
|
446
446
|
</form>
|
|
@@ -45,6 +45,12 @@
|
|
|
45
45
|
{% endblock content_right_page %}
|
|
46
46
|
|
|
47
47
|
{% block content_full_width_page %}
|
|
48
|
+
<div class="panel panel-default">
|
|
49
|
+
<div class="panel-heading">
|
|
50
|
+
<strong>Controllers</strong>
|
|
51
|
+
</div>
|
|
52
|
+
{% include 'responsive_table.html' with table=controllers_table %}
|
|
53
|
+
</div>
|
|
48
54
|
<div class="panel panel-default">
|
|
49
55
|
<div class="panel-heading">
|
|
50
56
|
<strong>Devices</strong>
|
|
@@ -113,6 +113,23 @@
|
|
|
113
113
|
</div>
|
|
114
114
|
{% endblock content_left_page %}
|
|
115
115
|
|
|
116
|
+
{% block content_right_page %}
|
|
117
|
+
<div class="panel panel-default">
|
|
118
|
+
<div class="panel-heading">
|
|
119
|
+
<strong>Comments</strong>
|
|
120
|
+
</div>
|
|
121
|
+
<div class="panel-body rendered-markdown">
|
|
122
|
+
{% if object.comments %}
|
|
123
|
+
{{ object.comments|render_markdown }}
|
|
124
|
+
{% else %}
|
|
125
|
+
<span class="text-muted">None</span>
|
|
126
|
+
{% endif %}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
{% endblock content_right_page %}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
116
133
|
{% block extra_tab_content %}
|
|
117
134
|
<div role="tabpanel" class="tab-pane {% if request.GET.tab == 'interfaces' %}active{% else %}fade{% endif %}" id="interfaces">
|
|
118
135
|
{% include 'dcim/inc/moduletype_component_table.html' with table=interface_table title='Interfaces' tab='interfaces' %}
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
</div>
|
|
145
145
|
<div class="row">
|
|
146
146
|
<div class="col-md-6">
|
|
147
|
-
{% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic computed_fields_advanced_ui=False %}
|
|
147
|
+
{% include 'inc/custom_fields/panel.html' with custom_fields=object.get_custom_field_groupings_basic computed_fields=object.get_computed_fields_grouping_basic computed_fields_advanced_ui=False %}
|
|
148
148
|
{% include 'inc/relationships_panel.html' %}
|
|
149
149
|
{% include 'extras/inc/tags_panel.html' %}
|
|
150
150
|
{% plugin_left_page object %}
|
|
@@ -236,7 +236,7 @@
|
|
|
236
236
|
</div>
|
|
237
237
|
{% endif %}
|
|
238
238
|
{% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
|
|
239
|
-
<div id="
|
|
239
|
+
<div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
|
|
240
240
|
<div class="row">
|
|
241
241
|
<div class="col-md-12">
|
|
242
242
|
<form method="post">
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
</div>
|
|
250
250
|
</div>
|
|
251
251
|
<div class="table-responsive">
|
|
252
|
-
{% render_table
|
|
252
|
+
{% render_table associated_object_metadata_table 'inc/table.html' %}
|
|
253
253
|
</div>
|
|
254
254
|
</div>
|
|
255
255
|
</form>
|
nautobot/dcim/tests/test_api.py
CHANGED
|
@@ -1022,6 +1022,7 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase):
|
|
|
1022
1022
|
model = ModuleType
|
|
1023
1023
|
bulk_update_data = {
|
|
1024
1024
|
"part_number": "ABC123",
|
|
1025
|
+
"comments": "changed comment",
|
|
1025
1026
|
}
|
|
1026
1027
|
|
|
1027
1028
|
@classmethod
|
|
@@ -1033,6 +1034,7 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase):
|
|
|
1033
1034
|
"manufacturer": manufacturer_id,
|
|
1034
1035
|
"model": "Module Type 1",
|
|
1035
1036
|
"part_number": "123456",
|
|
1037
|
+
"comments": "test comment",
|
|
1036
1038
|
},
|
|
1037
1039
|
{
|
|
1038
1040
|
"manufacturer": manufacturer_id,
|