nautobot 2.3.0b1__py3-none-any.whl → 2.3.2__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/celery/schedulers.py +18 -0
- 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 +19 -5
- nautobot/core/tables.py +4 -1
- nautobot/core/templates/generic/object_retrieve.html +6 -6
- nautobot/core/templates/home.html +4 -3
- 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/templatetags/buttons.py +1 -1
- 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 +11 -9
- nautobot/dcim/factory.py +7 -4
- 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 +24 -10
- nautobot/dcim/tables/devicetypes.py +1 -1
- nautobot/dcim/templates/dcim/device/base.html +1 -1
- nautobot/dcim/templates/dcim/device.html +15 -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 +15 -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/utils.py +9 -6
- nautobot/dcim/views.py +4 -1
- nautobot/extras/api/serializers.py +2 -1
- nautobot/extras/api/views.py +7 -59
- nautobot/extras/factory.py +50 -12
- nautobot/extras/filters/__init__.py +18 -3
- nautobot/extras/forms/base.py +10 -4
- nautobot/extras/forms/forms.py +7 -0
- nautobot/extras/forms/mixins.py +2 -2
- nautobot/extras/homepage.py +12 -2
- nautobot/extras/jobs.py +2 -2
- nautobot/extras/management/__init__.py +3 -0
- nautobot/extras/migrations/0111_metadata.py +4 -4
- nautobot/extras/migrations/0114_computedfield_grouping.py +17 -0
- nautobot/extras/migrations/0115_scheduledjob_time_zone.py +23 -0
- nautobot/extras/models/customfields.py +54 -0
- nautobot/extras/models/jobs.py +105 -9
- nautobot/extras/models/metadata.py +18 -18
- nautobot/extras/models/models.py +2 -0
- nautobot/extras/signals.py +14 -1
- nautobot/extras/tables.py +77 -18
- nautobot/extras/templates/extras/computedfield.html +4 -0
- nautobot/extras/templates/extras/job_detail.html +11 -0
- nautobot/extras/templates/extras/scheduledjob.html +13 -2
- nautobot/extras/tests/test_api.py +33 -27
- nautobot/extras/tests/test_filters.py +57 -1
- nautobot/extras/tests/test_jobs.py +2 -2
- nautobot/extras/tests/test_models.py +319 -19
- nautobot/extras/tests/test_views.py +26 -5
- nautobot/extras/utils.py +35 -6
- nautobot/extras/views.py +35 -51
- nautobot/ipam/api/views.py +9 -2
- nautobot/ipam/choices.py +17 -0
- nautobot/ipam/factory.py +6 -0
- nautobot/ipam/filters.py +2 -2
- nautobot/ipam/forms.py +6 -4
- nautobot/ipam/migrations/0048_vrf_status.py +23 -0
- nautobot/ipam/migrations/0049_vrf_data_migration.py +25 -0
- nautobot/ipam/models.py +11 -20
- nautobot/ipam/querysets.py +26 -0
- nautobot/ipam/tables.py +7 -2
- nautobot/ipam/templates/ipam/vrf.html +4 -0
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -0
- nautobot/ipam/tests/test_api.py +33 -3
- nautobot/ipam/tests/test_models.py +89 -2
- nautobot/ipam/tests/test_views.py +3 -0
- nautobot/ipam/views.py +10 -15
- nautobot/project-static/css/base.css +7 -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 +775 -91
- 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 +55 -23
- 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/project-static/js/homepage_layout.js +3 -0
- 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.2.dist-info}/METADATA +3 -3
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/RECORD +397 -393
- 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.2.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/NOTICE +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/WHEEL +0 -0
- {nautobot-2.3.0b1.dist-info → nautobot-2.3.2.dist-info}/entry_points.txt +0 -0
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):
|
|
@@ -396,7 +396,7 @@ class DeviceModuleConsolePortTable(ConsolePortTable):
|
|
|
396
396
|
"actions",
|
|
397
397
|
)
|
|
398
398
|
row_attrs = {
|
|
399
|
-
"
|
|
399
|
+
"class": cable_status_color_css,
|
|
400
400
|
}
|
|
401
401
|
|
|
402
402
|
|
|
@@ -460,7 +460,7 @@ class DeviceModuleConsoleServerPortTable(ConsoleServerPortTable):
|
|
|
460
460
|
"actions",
|
|
461
461
|
)
|
|
462
462
|
row_attrs = {
|
|
463
|
-
"
|
|
463
|
+
"class": cable_status_color_css,
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
|
|
@@ -535,7 +535,7 @@ class DeviceModulePowerPortTable(PowerPortTable):
|
|
|
535
535
|
"connection",
|
|
536
536
|
"actions",
|
|
537
537
|
)
|
|
538
|
-
row_attrs = {"
|
|
538
|
+
row_attrs = {"class": cable_status_color_css}
|
|
539
539
|
|
|
540
540
|
|
|
541
541
|
class PowerOutletTable(ModularDeviceComponentTable, PathEndpointTable):
|
|
@@ -613,7 +613,7 @@ class DeviceModulePowerOutletTable(PowerOutletTable):
|
|
|
613
613
|
"connection",
|
|
614
614
|
"actions",
|
|
615
615
|
)
|
|
616
|
-
row_attrs = {"
|
|
616
|
+
row_attrs = {"class": cable_status_color_css}
|
|
617
617
|
|
|
618
618
|
|
|
619
619
|
class BaseInterfaceTable(BaseTable):
|
|
@@ -739,7 +739,7 @@ class DeviceModuleInterfaceTable(InterfaceTable):
|
|
|
739
739
|
"actions",
|
|
740
740
|
]
|
|
741
741
|
row_attrs = {
|
|
742
|
-
"
|
|
742
|
+
"class": cable_status_color_css,
|
|
743
743
|
"data-name": lambda record: record.name,
|
|
744
744
|
}
|
|
745
745
|
|
|
@@ -815,7 +815,7 @@ class DeviceModuleFrontPortTable(FrontPortTable):
|
|
|
815
815
|
"cable_peer",
|
|
816
816
|
"actions",
|
|
817
817
|
)
|
|
818
|
-
row_attrs = {"
|
|
818
|
+
row_attrs = {"class": cable_status_color_css}
|
|
819
819
|
|
|
820
820
|
|
|
821
821
|
class RearPortTable(ModularDeviceComponentTable, CableTerminationTable):
|
|
@@ -874,7 +874,7 @@ class DeviceModuleRearPortTable(RearPortTable):
|
|
|
874
874
|
"cable_peer",
|
|
875
875
|
"actions",
|
|
876
876
|
)
|
|
877
|
-
row_attrs = {"
|
|
877
|
+
row_attrs = {"class": cable_status_color_css}
|
|
878
878
|
|
|
879
879
|
|
|
880
880
|
class DeviceBayTable(DeviceComponentTable):
|
|
@@ -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">
|
|
@@ -406,6 +406,18 @@
|
|
|
406
406
|
{% endif %}
|
|
407
407
|
{% if object.is_dynamic_group_associable_model and perms.extras.view_dynamicgroup %}
|
|
408
408
|
<div id="dynamic_groups" role="tabpanel" class="tab-pane {% if request.GET.tab == 'dynamic_groups' %}active{% else %}fade{% endif %}">
|
|
409
|
+
<div class="row">
|
|
410
|
+
<div class="col-md-12">
|
|
411
|
+
<div class="alert alert-warning">
|
|
412
|
+
Dynamic group membership is cached for performance reasons,
|
|
413
|
+
therefore this table may not always be up-to-date.
|
|
414
|
+
<br>You can refresh the membership of any specific group by navigating to it from the list below
|
|
415
|
+
or from the <a href="{% url 'extras:dynamicgroup_list' %}">Dynamic Groups list view</a>.
|
|
416
|
+
<br>You can also refresh the membership of all groups by running the
|
|
417
|
+
<a href="{% url 'extras:job_run_by_class_path' class_path='nautobot.core.jobs.groups.RefreshDynamicGroupCaches' %}">Refresh Dynamic Group Caches job</a>.
|
|
418
|
+
</div>
|
|
419
|
+
</div>
|
|
420
|
+
</div>
|
|
409
421
|
<div class="row">
|
|
410
422
|
<div class="col-md-12">
|
|
411
423
|
<form method="post">
|
|
@@ -427,7 +439,7 @@
|
|
|
427
439
|
</div>
|
|
428
440
|
{% endif %}
|
|
429
441
|
{% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
|
|
430
|
-
<div id="
|
|
442
|
+
<div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
|
|
431
443
|
<div class="row">
|
|
432
444
|
<div class="col-md-12">
|
|
433
445
|
<form method="post">
|
|
@@ -440,7 +452,7 @@
|
|
|
440
452
|
</div>
|
|
441
453
|
</div>
|
|
442
454
|
<div class="table-responsive">
|
|
443
|
-
{% render_table
|
|
455
|
+
{% render_table associated_object_metadata_table 'inc/table.html' %}
|
|
444
456
|
</div>
|
|
445
457
|
</div>
|
|
446
458
|
</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 %}
|
|
@@ -215,6 +215,18 @@
|
|
|
215
215
|
{% endif %}
|
|
216
216
|
{% if object.is_dynamic_group_associable_model and perms.extras.view_dynamicgroup %}
|
|
217
217
|
<div id="dynamic_groups" role="tabpanel" class="tab-pane {% if request.GET.tab == 'dynamic_groups' %}active{% else %}fade{% endif %}">
|
|
218
|
+
<div class="row">
|
|
219
|
+
<div class="col-md-12">
|
|
220
|
+
<div class="alert alert-warning">
|
|
221
|
+
Dynamic group membership is cached for performance reasons,
|
|
222
|
+
therefore this table may not always be up-to-date.
|
|
223
|
+
<br>You can refresh the membership of any specific group by navigating to it from the list below
|
|
224
|
+
or from the <a href="{% url 'extras:dynamicgroup_list' %}">Dynamic Groups list view</a>.
|
|
225
|
+
<br>You can also refresh the membership of all groups by running the
|
|
226
|
+
<a href="{% url 'extras:job_run_by_class_path' class_path='nautobot.core.jobs.groups.RefreshDynamicGroupCaches' %}">Refresh Dynamic Group Caches job</a>.
|
|
227
|
+
</div>
|
|
228
|
+
</div>
|
|
229
|
+
</div>
|
|
218
230
|
<div class="row">
|
|
219
231
|
<div class="col-md-12">
|
|
220
232
|
<form method="post">
|
|
@@ -236,7 +248,7 @@
|
|
|
236
248
|
</div>
|
|
237
249
|
{% endif %}
|
|
238
250
|
{% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
|
|
239
|
-
<div id="
|
|
251
|
+
<div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
|
|
240
252
|
<div class="row">
|
|
241
253
|
<div class="col-md-12">
|
|
242
254
|
<form method="post">
|
|
@@ -249,7 +261,7 @@
|
|
|
249
261
|
</div>
|
|
250
262
|
</div>
|
|
251
263
|
<div class="table-responsive">
|
|
252
|
-
{% render_table
|
|
264
|
+
{% render_table associated_object_metadata_table 'inc/table.html' %}
|
|
253
265
|
</div>
|
|
254
266
|
</div>
|
|
255
267
|
</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,
|
|
@@ -656,9 +656,15 @@ def common_test_data(cls):
|
|
|
656
656
|
device_redundancy_groups = iter(DeviceRedundancyGroup.objects.all())
|
|
657
657
|
|
|
658
658
|
module_types = (
|
|
659
|
-
ModuleType.objects.create(
|
|
660
|
-
|
|
661
|
-
|
|
659
|
+
ModuleType.objects.create(
|
|
660
|
+
manufacturer=cls.manufacturers[0], model="Filter Test Module Type 1", comments="Module Type 1"
|
|
661
|
+
),
|
|
662
|
+
ModuleType.objects.create(
|
|
663
|
+
manufacturer=cls.manufacturers[1], model="Filter Test Module Type 2", comments="Module Type 2"
|
|
664
|
+
),
|
|
665
|
+
ModuleType.objects.create(
|
|
666
|
+
manufacturer=cls.manufacturers[2], model="Filter Test Module Type 3", comments="Module Type 3"
|
|
667
|
+
),
|
|
662
668
|
)
|
|
663
669
|
|
|
664
670
|
# Create 3 of each component template on the first two module types
|
|
@@ -898,7 +904,7 @@ class ModularDeviceComponentTestMixin(DeviceComponentTestMixin):
|
|
|
898
904
|
)
|
|
899
905
|
parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
|
|
900
906
|
module_type = ModuleType.objects.create(
|
|
901
|
-
manufacturer=manufacturer, model=f"Test Device Filter for {model} Module Type"
|
|
907
|
+
manufacturer=manufacturer, model=f"Test Device Filter for {model} Module Type", comments="Module Type test"
|
|
902
908
|
)
|
|
903
909
|
module = Module.objects.create(
|
|
904
910
|
module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
|
|
@@ -2526,7 +2532,7 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
|
|
|
2526
2532
|
name="Parent module bay", position="1", parent_device=device_vc_master
|
|
2527
2533
|
)
|
|
2528
2534
|
module_type = ModuleType.objects.create(
|
|
2529
|
-
manufacturer=manufacturer, model="Test Device Filter for Interface Module Type"
|
|
2535
|
+
manufacturer=manufacturer, model="Test Device Filter for Interface Module Type", comments="Module Type test"
|
|
2530
2536
|
)
|
|
2531
2537
|
module = Module.objects.create(
|
|
2532
2538
|
module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
|
|
@@ -2772,7 +2778,7 @@ class FrontPortTestCase(ModularDeviceComponentTestMixin, FilterTestCases.FilterT
|
|
|
2772
2778
|
)
|
|
2773
2779
|
parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
|
|
2774
2780
|
module_type = ModuleType.objects.create(
|
|
2775
|
-
manufacturer=manufacturer, model="Test Device Filter for FrontPort Module Type"
|
|
2781
|
+
manufacturer=manufacturer, model="Test Device Filter for FrontPort Module Type", comments="Module Type test"
|
|
2776
2782
|
)
|
|
2777
2783
|
module = Module.objects.create(
|
|
2778
2784
|
module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
|
|
@@ -3357,7 +3363,7 @@ class CableTestCase(FilterTestCases.FilterTestCase):
|
|
|
3357
3363
|
)
|
|
3358
3364
|
parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
|
|
3359
3365
|
module_type = ModuleType.objects.create(
|
|
3360
|
-
manufacturer=manufacturer, model="Test Device Filter for Cable Module Type"
|
|
3366
|
+
manufacturer=manufacturer, model="Test Device Filter for Cable Module Type", comments="Module Type test"
|
|
3361
3367
|
)
|
|
3362
3368
|
module = Module.objects.create(
|
|
3363
3369
|
module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
|
|
@@ -4012,6 +4018,7 @@ class ModuleTypeTestCase(FilterTestCases.FilterTestCase):
|
|
|
4012
4018
|
queryset = ModuleType.objects.all()
|
|
4013
4019
|
filterset = ModuleTypeFilterSet
|
|
4014
4020
|
generic_filter_tests = [
|
|
4021
|
+
("comments",),
|
|
4015
4022
|
("manufacturer", "manufacturer__id"),
|
|
4016
4023
|
("manufacturer", "manufacturer__name"),
|
|
4017
4024
|
("model",),
|
|
@@ -12,6 +12,8 @@ from nautobot.dcim.models import (
|
|
|
12
12
|
Manufacturer,
|
|
13
13
|
Platform,
|
|
14
14
|
Rack,
|
|
15
|
+
SoftwareImageFile,
|
|
16
|
+
SoftwareVersion,
|
|
15
17
|
)
|
|
16
18
|
from nautobot.extras.models import Role, SecretsGroup, Status
|
|
17
19
|
from nautobot.ipam.models import VLAN
|
|
@@ -43,6 +45,15 @@ class DeviceTestCase(FormTestCases.BaseFormTestCase):
|
|
|
43
45
|
cls.manufacturer = cls.device_type.manufacturer
|
|
44
46
|
cls.platform = Platform.objects.filter(manufacturer=cls.device_type.manufacturer).first()
|
|
45
47
|
cls.device_role = Role.objects.get_for_model(Device).first()
|
|
48
|
+
cls.software_version_contains_no_valid_image_for_device_type = SoftwareVersion.objects.create(
|
|
49
|
+
platform=cls.platform,
|
|
50
|
+
version="New version 1.0.0",
|
|
51
|
+
status=Status.objects.get_for_model(SoftwareVersion).first(),
|
|
52
|
+
)
|
|
53
|
+
cls.software_version = SoftwareVersion.objects.first()
|
|
54
|
+
cls.software_image_files = SoftwareImageFile.objects.exclude(software_version=cls.software_version).exclude(
|
|
55
|
+
default_image=True
|
|
56
|
+
)
|
|
46
57
|
|
|
47
58
|
Device.objects.create(
|
|
48
59
|
name="Device 1",
|
|
@@ -134,6 +145,49 @@ class DeviceTestCase(FormTestCases.BaseFormTestCase):
|
|
|
134
145
|
self.assertFalse(form.is_valid())
|
|
135
146
|
self.assertIn("face", form.errors)
|
|
136
147
|
|
|
148
|
+
def test_no_software_image_file_specified_is_valid(self):
|
|
149
|
+
form = DeviceForm(
|
|
150
|
+
data={
|
|
151
|
+
"name": "New Device",
|
|
152
|
+
"role": self.device_role.pk,
|
|
153
|
+
"tenant": None,
|
|
154
|
+
"manufacturer": self.manufacturer.pk,
|
|
155
|
+
"device_type": self.device_type.pk,
|
|
156
|
+
"location": self.location.pk,
|
|
157
|
+
"rack": None,
|
|
158
|
+
"face": None,
|
|
159
|
+
"position": None,
|
|
160
|
+
"platform": self.platform.pk,
|
|
161
|
+
"status": self.device_status.pk,
|
|
162
|
+
"secrets_group": SecretsGroup.objects.first().pk,
|
|
163
|
+
"software_version": self.software_version_contains_no_valid_image_for_device_type.pk,
|
|
164
|
+
"software_image_files": [],
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
self.assertTrue(form.is_valid())
|
|
168
|
+
|
|
169
|
+
def test_invalid_software_image_file_specified(self):
|
|
170
|
+
form = DeviceForm(
|
|
171
|
+
data={
|
|
172
|
+
"name": "New Device",
|
|
173
|
+
"role": self.device_role.pk,
|
|
174
|
+
"tenant": None,
|
|
175
|
+
"manufacturer": self.manufacturer.pk,
|
|
176
|
+
"device_type": self.device_type.pk,
|
|
177
|
+
"location": self.location.pk,
|
|
178
|
+
"rack": None,
|
|
179
|
+
"face": None,
|
|
180
|
+
"position": None,
|
|
181
|
+
"platform": self.platform.pk,
|
|
182
|
+
"status": self.device_status.pk,
|
|
183
|
+
"secrets_group": SecretsGroup.objects.first().pk,
|
|
184
|
+
"software_version": self.software_version.pk,
|
|
185
|
+
"software_image_files": list(self.software_image_files.values_list("pk", flat=True)),
|
|
186
|
+
}
|
|
187
|
+
)
|
|
188
|
+
self.assertFalse(form.is_valid())
|
|
189
|
+
self.assertIn("software_image_files", form.errors)
|
|
190
|
+
|
|
137
191
|
def test_non_racked_device_with_position(self):
|
|
138
192
|
form = DeviceForm(
|
|
139
193
|
data={
|
|
@@ -1723,11 +1723,19 @@ class DeviceTestCase(ModelTestCases.BaseModelTestCase):
|
|
|
1723
1723
|
software_version.software_image_files.all().update(default_image=False)
|
|
1724
1724
|
self.device_type.software_image_files.set([])
|
|
1725
1725
|
self.device.software_version = software_version
|
|
1726
|
+
invalid_software_image_file = SoftwareImageFile.objects.filter(default_image=False).first()
|
|
1727
|
+
invalid_software_image_file.device_types.set([])
|
|
1728
|
+
self.device.software_image_files.set([invalid_software_image_file])
|
|
1726
1729
|
|
|
1727
|
-
#
|
|
1730
|
+
# There is an invalid non-default software_image_file specified for the software version
|
|
1731
|
+
# It is not a default image and it does not match any device type
|
|
1728
1732
|
with self.assertRaises(ValidationError):
|
|
1729
1733
|
self.device.validated_save()
|
|
1730
1734
|
|
|
1735
|
+
# user should be able to specify any software version without specifying software_image_files
|
|
1736
|
+
self.device.software_image_files.set([])
|
|
1737
|
+
self.device.validated_save()
|
|
1738
|
+
|
|
1731
1739
|
# Default image matches
|
|
1732
1740
|
software_image_file = software_version.software_image_files.first()
|
|
1733
1741
|
software_image_file.default_image = True
|
|
@@ -1903,6 +1911,37 @@ class DeviceTestCase(ModelTestCases.BaseModelTestCase):
|
|
|
1903
1911
|
self.assertNotEqual(child_mtime_after_parent_rack_update_save, child_mtime_after_parent_site_update_save)
|
|
1904
1912
|
|
|
1905
1913
|
|
|
1914
|
+
class DeviceBayTestCase(ModelTestCases.BaseModelTestCase):
|
|
1915
|
+
model = DeviceBay
|
|
1916
|
+
|
|
1917
|
+
def setUp(self):
|
|
1918
|
+
self.devices = Device.objects.filter(device_type__subdevice_role=SubdeviceRoleChoices.ROLE_PARENT)
|
|
1919
|
+
devicetype = DeviceType.objects.create(
|
|
1920
|
+
manufacturer=self.devices[0].device_type.manufacturer,
|
|
1921
|
+
model="TestDeviceType1",
|
|
1922
|
+
u_height=0,
|
|
1923
|
+
subdevice_role=SubdeviceRoleChoices.ROLE_CHILD,
|
|
1924
|
+
)
|
|
1925
|
+
child_device = Device.objects.create(
|
|
1926
|
+
device_type=devicetype,
|
|
1927
|
+
role=self.devices[0].role,
|
|
1928
|
+
name="TestDevice1",
|
|
1929
|
+
status=self.devices[0].status,
|
|
1930
|
+
location=self.devices[0].location,
|
|
1931
|
+
)
|
|
1932
|
+
DeviceBay.objects.create(device=self.devices[0], name="Device Bay 1", installed_device=child_device)
|
|
1933
|
+
|
|
1934
|
+
def test_assigning_installed_device(self):
|
|
1935
|
+
server = Device.objects.exclude(device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD).last()
|
|
1936
|
+
bay = DeviceBay(device=self.devices[1], name="Device Bay Err", installed_device=server)
|
|
1937
|
+
with self.assertRaises(ValidationError) as err:
|
|
1938
|
+
bay.validated_save()
|
|
1939
|
+
self.assertIn(
|
|
1940
|
+
f'Cannot install device "{server}"; device-type "{server.device_type}" subdevice_role is not "child".',
|
|
1941
|
+
str(err.exception),
|
|
1942
|
+
)
|
|
1943
|
+
|
|
1944
|
+
|
|
1906
1945
|
class DeviceTypeToSoftwareImageFileTestCase(ModelTestCases.BaseModelTestCase):
|
|
1907
1946
|
model = DeviceTypeToSoftwareImageFile
|
|
1908
1947
|
|
|
@@ -817,6 +817,7 @@ class DeviceTypeTestCase(
|
|
|
817
817
|
cls.bulk_edit_data = {
|
|
818
818
|
"u_height": 0,
|
|
819
819
|
"is_full_depth": False,
|
|
820
|
+
"comments": "changed comment",
|
|
820
821
|
}
|
|
821
822
|
|
|
822
823
|
def test_list_has_correct_links(self):
|
|
@@ -1196,6 +1197,7 @@ class ModuleTypeTestCase(
|
|
|
1196
1197
|
ModuleType.objects.create(
|
|
1197
1198
|
model="Test Module Type 1",
|
|
1198
1199
|
manufacturer=manufacturers[0],
|
|
1200
|
+
comments="test comment",
|
|
1199
1201
|
)
|
|
1200
1202
|
ModuleType.objects.create(
|
|
1201
1203
|
model="Test Module Type 2",
|
|
@@ -1215,10 +1217,12 @@ class ModuleTypeTestCase(
|
|
|
1215
1217
|
"model": "Test Module Type X",
|
|
1216
1218
|
"part_number": "123ABC",
|
|
1217
1219
|
"tags": [t.pk for t in Tag.objects.get_for_model(ModuleType)],
|
|
1220
|
+
"comments": "test comment",
|
|
1218
1221
|
}
|
|
1219
1222
|
|
|
1220
1223
|
cls.bulk_edit_data = {
|
|
1221
1224
|
"manufacturer": manufacturers[1].pk,
|
|
1225
|
+
"comments": "changed comment",
|
|
1222
1226
|
}
|
|
1223
1227
|
|
|
1224
1228
|
def test_list_has_correct_links(self):
|
|
@@ -2080,7 +2084,7 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2080
2084
|
status_active = statuses[0]
|
|
2081
2085
|
|
|
2082
2086
|
# We want unique sets of software image files for each device type
|
|
2083
|
-
software_image_files = list(SoftwareImageFile.objects.
|
|
2087
|
+
software_image_files = list(SoftwareImageFile.objects.filter(default_image=False)[:4])
|
|
2084
2088
|
software_versions = list(SoftwareVersion.objects.filter(software_image_files__isnull=False)[:2])
|
|
2085
2089
|
software_image_files[0].software_version = software_versions[0]
|
|
2086
2090
|
software_image_files[1].software_version = software_versions[0]
|
|
@@ -2090,6 +2094,10 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2090
2094
|
software_image_file.save()
|
|
2091
2095
|
devicetypes[0].software_image_files.set(software_image_files[:2])
|
|
2092
2096
|
devicetypes[1].software_image_files.set(software_image_files[2:])
|
|
2097
|
+
# Only valid software image files are those that belong to the device type or default images
|
|
2098
|
+
valid_software_image_files = software_image_files[2:] + [
|
|
2099
|
+
SoftwareImageFile.objects.filter(default_image=True).first()
|
|
2100
|
+
]
|
|
2093
2101
|
|
|
2094
2102
|
cls.custom_fields = (
|
|
2095
2103
|
CustomField.objects.create(
|
|
@@ -2201,7 +2209,7 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2201
2209
|
"cf_crash_counter": -1,
|
|
2202
2210
|
"cr_router-id": None,
|
|
2203
2211
|
"software_version": software_versions[1].pk,
|
|
2204
|
-
"software_image_files": [f.pk for f in
|
|
2212
|
+
"software_image_files": [f.pk for f in valid_software_image_files],
|
|
2205
2213
|
}
|
|
2206
2214
|
|
|
2207
2215
|
cls.bulk_edit_data = {
|
|
@@ -2359,6 +2367,19 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2359
2367
|
sorted(interface_ips),
|
|
2360
2368
|
)
|
|
2361
2369
|
|
|
2370
|
+
with self.subTest("Assert Assigning IPAddress Without Selecting Any IPAddress Raises Exception"):
|
|
2371
|
+
assign_ip_form_data["pk"] = []
|
|
2372
|
+
assign_ip_request = {
|
|
2373
|
+
"path": reverse("ipam:ipaddress_assign")
|
|
2374
|
+
+ f"?interface={self.interfaces[1].id}&return_url={device_list_url}",
|
|
2375
|
+
"data": post_data(assign_ip_form_data),
|
|
2376
|
+
}
|
|
2377
|
+
response = self.client.post(**assign_ip_request, follow=True)
|
|
2378
|
+
self.assertHttpStatus(response, 200)
|
|
2379
|
+
self.assertIn(
|
|
2380
|
+
"Please select at least one IP Address from the table.", response.content.decode(response.charset)
|
|
2381
|
+
)
|
|
2382
|
+
|
|
2362
2383
|
@override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
|
|
2363
2384
|
def test_device_rearports(self):
|
|
2364
2385
|
device = Device.objects.first()
|
|
@@ -4172,6 +4193,28 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
4172
4193
|
"domain": "domain-x",
|
|
4173
4194
|
}
|
|
4174
4195
|
|
|
4196
|
+
def test_device_interfaces_count_correct(self):
|
|
4197
|
+
"""
|
|
4198
|
+
This checks whether the other memebers' interfaces are included in the
|
|
4199
|
+
interfaces tab of the master device and whether the interface count on the tab header is
|
|
4200
|
+
rendered correctly.
|
|
4201
|
+
"""
|
|
4202
|
+
self.user.is_superuser = True
|
|
4203
|
+
self.user.save()
|
|
4204
|
+
interface_status = Status.objects.get_for_model(Interface).first()
|
|
4205
|
+
Interface.objects.create(device=self.devices[0], name="eth0", status=interface_status)
|
|
4206
|
+
Interface.objects.create(device=self.devices[0], name="eth1", status=interface_status)
|
|
4207
|
+
Interface.objects.create(device=self.devices[1], name="device 1 interface 1", status=interface_status)
|
|
4208
|
+
Interface.objects.create(device=self.devices[1], name="device 1 interface 2", status=interface_status)
|
|
4209
|
+
Interface.objects.create(device=self.devices[2], name="device 2 interface 1", status=interface_status)
|
|
4210
|
+
Interface.objects.create(device=self.devices[2], name="device 2 interface 2", status=interface_status)
|
|
4211
|
+
response = self.client.get(reverse("dcim:device_interfaces", kwargs={"pk": self.devices[0].pk}))
|
|
4212
|
+
self.assertIn('Interfaces <span class="badge">6</span>', str(response.content))
|
|
4213
|
+
self.assertIn("device 1 interface 1", str(response.content))
|
|
4214
|
+
self.assertIn("device 1 interface 2", str(response.content))
|
|
4215
|
+
self.assertIn("device 2 interface 1", str(response.content))
|
|
4216
|
+
self.assertIn("device 2 interface 2", str(response.content))
|
|
4217
|
+
|
|
4175
4218
|
def test_device_column_visible(self):
|
|
4176
4219
|
"""
|
|
4177
4220
|
This checks whether the device column on a device's interfaces
|
nautobot/dcim/utils.py
CHANGED
|
@@ -14,7 +14,7 @@ from netutils.lib_mapper import (
|
|
|
14
14
|
SCRAPLI_LIB_MAPPER_REVERSE,
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
from nautobot.core.
|
|
17
|
+
from nautobot.core.choices import ColorChoices
|
|
18
18
|
from nautobot.core.utils.config import get_settings_or_config
|
|
19
19
|
from nautobot.dcim.choices import InterfaceModeChoices
|
|
20
20
|
from nautobot.dcim.constants import NETUTILS_NETWORK_DRIVER_MAPPING_NAMES
|
|
@@ -55,11 +55,14 @@ def cable_status_color_css(record):
|
|
|
55
55
|
"""
|
|
56
56
|
if not record.cable:
|
|
57
57
|
return ""
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
else:
|
|
59
|
+
CABLE_STATUS_TO_CSS_CLASS = {
|
|
60
|
+
ColorChoices.COLOR_GREEN: "success",
|
|
61
|
+
ColorChoices.COLOR_AMBER: "warning",
|
|
62
|
+
ColorChoices.COLOR_CYAN: "info",
|
|
63
|
+
}
|
|
64
|
+
status_color = record.cable.get_status_color().strip("#")
|
|
65
|
+
return CABLE_STATUS_TO_CSS_CLASS.get(status_color, "")
|
|
63
66
|
|
|
64
67
|
|
|
65
68
|
def get_network_driver_mapping_tool_names():
|
nautobot/dcim/views.py
CHANGED
|
@@ -1923,7 +1923,7 @@ class DeviceInterfacesView(DeviceComponentTabView):
|
|
|
1923
1923
|
|
|
1924
1924
|
def get_extra_context(self, request, instance):
|
|
1925
1925
|
interfaces = (
|
|
1926
|
-
instance.
|
|
1926
|
+
instance.vc_interfaces.restrict(request.user, "view")
|
|
1927
1927
|
.prefetch_related(
|
|
1928
1928
|
Prefetch("ip_addresses", queryset=IPAddress.objects.restrict(request.user)),
|
|
1929
1929
|
Prefetch("member_interfaces", queryset=Interface.objects.restrict(request.user)),
|
|
@@ -4049,6 +4049,9 @@ class DeviceRedundancyGroupUIViewSet(NautobotUIViewSet):
|
|
|
4049
4049
|
devices_table = tables.DeviceTable(devices)
|
|
4050
4050
|
devices_table.columns.show("device_redundancy_group_priority")
|
|
4051
4051
|
context["devices_table"] = devices_table
|
|
4052
|
+
controllers = instance.controllers_sorted.restrict(request.user)
|
|
4053
|
+
controllers_table = tables.ControllerTable(controllers)
|
|
4054
|
+
context["controllers_table"] = controllers_table
|
|
4052
4055
|
return context
|
|
4053
4056
|
|
|
4054
4057
|
|
|
@@ -6,6 +6,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
|
|
6
6
|
from drf_spectacular.utils import extend_schema_field
|
|
7
7
|
from rest_framework import serializers
|
|
8
8
|
from rest_framework.validators import UniqueTogetherValidator
|
|
9
|
+
from timezone_field.rest_framework import TimeZoneSerializerField
|
|
9
10
|
|
|
10
11
|
from nautobot.core.api import (
|
|
11
12
|
BaseModelSerializer,
|
|
@@ -228,7 +229,6 @@ class ContactAssociationSerializer(NautobotModelSerializer):
|
|
|
228
229
|
fields = "__all__"
|
|
229
230
|
validators = []
|
|
230
231
|
extra_kwargs = {
|
|
231
|
-
"role": {"required": False},
|
|
232
232
|
"contact": {"required": False},
|
|
233
233
|
"team": {"required": False},
|
|
234
234
|
}
|
|
@@ -582,6 +582,7 @@ class JobVariableSerializer(serializers.Serializer):
|
|
|
582
582
|
|
|
583
583
|
class ScheduledJobSerializer(BaseModelSerializer):
|
|
584
584
|
# start_time = serializers.DateTimeField(format=None, required=False)
|
|
585
|
+
time_zone = TimeZoneSerializerField(required=False)
|
|
585
586
|
|
|
586
587
|
class Meta:
|
|
587
588
|
model = ScheduledJob
|