nautobot 2.4.13__py3-none-any.whl → 2.4.15__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/apps/choices.py +8 -0
- nautobot/apps/ui.py +14 -0
- nautobot/core/api/views.py +2 -0
- nautobot/core/choices.py +4 -0
- nautobot/core/filters.py +21 -41
- nautobot/core/graphql/generators.py +8 -0
- nautobot/core/graphql/schema.py +30 -30
- nautobot/core/management/commands/check_job_approval_status.py +47 -0
- nautobot/core/management/commands/generate_test_data.py +1 -1
- nautobot/core/management/commands/migrate.py +90 -1
- nautobot/core/models/tree_queries.py +17 -0
- nautobot/core/settings.py +2 -2
- nautobot/core/settings.yaml +3 -3
- nautobot/core/tables.py +29 -6
- nautobot/core/templates/base_django.html +1 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +1 -1
- nautobot/core/templates/generic/object_list.html +17 -20
- nautobot/core/templates/inc/breadcrumbs.html +14 -0
- nautobot/core/templatetags/buttons.py +2 -4
- nautobot/core/templatetags/helpers.py +29 -6
- nautobot/core/templatetags/ui_framework.py +21 -0
- nautobot/core/testing/api.py +7 -0
- nautobot/core/testing/filters.py +20 -3
- nautobot/core/testing/forms.py +1 -1
- nautobot/core/tests/integration/test_filters.py +2 -2
- nautobot/core/tests/test_breadcrumbs.py +366 -0
- nautobot/core/tests/test_commands.py +40 -0
- nautobot/core/tests/test_filters.py +51 -1
- nautobot/core/tests/test_forms.py +1 -1
- nautobot/core/tests/test_graphql.py +4 -4
- nautobot/core/tests/test_titles.py +183 -0
- nautobot/core/tests/test_tree_queries.py +30 -0
- nautobot/core/tests/test_views.py +2 -2
- nautobot/core/tests/test_views_utils.py +1 -1
- nautobot/core/ui/breadcrumbs.py +538 -0
- nautobot/core/ui/bulk_buttons.py +53 -0
- nautobot/core/ui/object_detail.py +31 -8
- nautobot/core/ui/titles.py +127 -0
- nautobot/core/ui/utils.py +25 -0
- nautobot/core/utils/migrations.py +1 -1
- nautobot/core/views/__init__.py +1 -1
- nautobot/core/views/mixins.py +26 -1
- nautobot/core/views/renderers.py +20 -2
- nautobot/core/views/utils.py +14 -13
- nautobot/dcim/api/serializers.py +9 -0
- nautobot/dcim/choices.py +55 -0
- nautobot/dcim/constants.py +0 -16
- nautobot/dcim/factory.py +1 -1
- nautobot/dcim/filters/__init__.py +15 -3
- nautobot/dcim/forms.py +120 -7
- nautobot/dcim/management/commands/trace_paths.py +1 -1
- nautobot/dcim/migrations/0072_alter_powerfeed_options_and_more.py +97 -0
- nautobot/dcim/models/device_component_templates.py +8 -0
- nautobot/dcim/models/device_components.py +31 -12
- nautobot/dcim/models/devices.py +1 -1
- nautobot/dcim/models/power.py +171 -10
- nautobot/dcim/models/racks.py +7 -4
- nautobot/dcim/tables/devices.py +2 -0
- nautobot/dcim/tables/devicetypes.py +1 -0
- nautobot/dcim/tables/power.py +30 -2
- nautobot/dcim/templates/dcim/device.html +2 -2
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -214
- nautobot/dcim/templates/dcim/location_retrieve.html +2 -2
- nautobot/dcim/templates/dcim/powerfeed_edit.html +8 -0
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/rack.html +2 -318
- nautobot/dcim/templates/dcim/rack_edit.html +2 -47
- nautobot/dcim/templates/dcim/rack_retrieve.html +318 -0
- nautobot/dcim/templates/dcim/rack_update.html +47 -0
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +61 -0
- nautobot/dcim/tests/test_api.py +24 -4
- nautobot/dcim/tests/test_filters.py +91 -13
- nautobot/dcim/tests/test_models.py +262 -0
- nautobot/dcim/tests/test_views.py +20 -12
- nautobot/dcim/urls.py +2 -27
- nautobot/dcim/utils.py +13 -30
- nautobot/dcim/views.py +428 -146
- nautobot/extras/choices.py +12 -4
- nautobot/extras/factory.py +19 -20
- nautobot/extras/filters/__init__.py +3 -2
- nautobot/extras/filters/mixins.py +23 -7
- nautobot/extras/forms/__init__.py +2 -1
- nautobot/extras/forms/forms.py +71 -0
- nautobot/extras/forms/mixins.py +4 -2
- nautobot/extras/managers.py +4 -1
- nautobot/extras/migrations/0062_collect_roles_from_related_apps_roles.py +30 -7
- nautobot/extras/migrations/0124_add_joblogentry_index.py +16 -0
- nautobot/extras/migrations/0125_jobresult_date_started.py +18 -0
- nautobot/extras/models/customfields.py +53 -5
- nautobot/extras/models/datasources.py +1 -2
- nautobot/extras/models/jobs.py +13 -3
- nautobot/extras/models/relationships.py +55 -6
- nautobot/extras/plugins/views.py +24 -1
- nautobot/extras/secrets/__init__.py +1 -1
- nautobot/extras/tables.py +9 -0
- nautobot/extras/templates/extras/customfield.html +2 -129
- nautobot/extras/templates/extras/customfield_edit.html +2 -108
- nautobot/extras/templates/extras/customfield_retrieve.html +129 -0
- nautobot/extras/templates/extras/customfield_update.html +108 -0
- nautobot/extras/templates/extras/graphqlquery.html +2 -97
- nautobot/extras/templates/extras/graphqlquery_list.html +1 -0
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +97 -0
- nautobot/extras/templates/extras/inc/jobresult.html +7 -3
- nautobot/extras/templates/extras/jobresult.html +2 -155
- nautobot/extras/templates/extras/jobresult_retrieve.html +155 -0
- nautobot/extras/templates/extras/marketplace.html +5 -6
- nautobot/extras/templates/extras/note.html +2 -53
- nautobot/extras/templates/extras/note_retrieve.html +53 -0
- nautobot/extras/templates/extras/plugins_list.html +5 -6
- nautobot/extras/templates/extras/secretsgroup.html +2 -29
- nautobot/extras/templates/extras/secretsgroup_edit.html +2 -82
- nautobot/extras/templates/extras/secretsgroup_retrieve.html +29 -0
- nautobot/extras/templates/extras/secretsgroup_update.html +82 -0
- nautobot/extras/templatetags/custom_links.py +2 -2
- nautobot/extras/templatetags/job_buttons.py +1 -1
- nautobot/extras/templatetags/plugins.py +1 -1
- nautobot/extras/tests/integration/test_computedfields.py +2 -2
- nautobot/extras/tests/integration/test_customfields.py +14 -11
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_notes.py +1 -1
- nautobot/extras/tests/integration/test_plugins.py +6 -6
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_customfields.py +115 -7
- nautobot/extras/tests/test_filters.py +9 -0
- nautobot/extras/tests/test_forms.py +2 -2
- nautobot/extras/tests/test_plugins.py +2 -3
- nautobot/extras/tests/test_relationships.py +14 -8
- nautobot/extras/tests/test_views.py +285 -2
- nautobot/extras/urls.py +5 -110
- nautobot/extras/utils.py +5 -2
- nautobot/extras/views.py +116 -311
- nautobot/ipam/api/views.py +69 -6
- nautobot/ipam/tables.py +8 -15
- nautobot/ipam/tests/migration/test_migrations.py +8 -8
- nautobot/ipam/tests/test_api.py +352 -2
- nautobot/ipam/tests/test_models.py +1 -1
- nautobot/project-static/docs/404.html +34 -34
- nautobot/project-static/docs/apps/index.html +34 -34
- nautobot/project-static/docs/apps/nautobot-apps.html +34 -34
- nautobot/project-static/docs/assets/_mkdocstrings.css +44 -6
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js → bundle.50899def.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.56ea9cef.min.js.map → bundle.50899def.min.js.map} +2 -2
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css → main.7e37652d.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.342714a4.min.css.map → main.7e37652d.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +39 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +139 -54
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +48 -38
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +50 -40
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +35 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +43 -39
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +52 -42
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +50 -41
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +54 -44
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +85 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +154 -62
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +54 -46
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +146 -87
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +240 -70
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +38 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +41 -35
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +173 -52
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +269 -85
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5987 -2643
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +36 -34
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +165 -89
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +161 -69
- nautobot/project-static/docs/development/apps/api/configuration-view.html +34 -34
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/global-search.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/graphql.html +34 -34
- nautobot/project-static/docs/development/apps/api/models/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +34 -34
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +34 -34
- nautobot/project-static/docs/development/apps/api/prometheus.html +34 -34
- nautobot/project-static/docs/development/apps/api/setup.html +34 -34
- nautobot/project-static/docs/development/apps/api/testing.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +34 -34
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/base-template.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/index.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +42 -36
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/notes.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +34 -34
- nautobot/project-static/docs/development/apps/api/views/urls.html +34 -34
- nautobot/project-static/docs/development/apps/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/code-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +34 -34
- nautobot/project-static/docs/development/apps/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +34 -34
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +37 -37
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +10544 -0
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +34 -34
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +34 -34
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +37 -37
- nautobot/project-static/docs/development/core/application-registry.html +162 -133
- nautobot/project-static/docs/development/core/best-practices.html +34 -34
- nautobot/project-static/docs/development/core/bootstrap-ui.html +34 -34
- nautobot/project-static/docs/development/core/caching.html +34 -34
- nautobot/project-static/docs/development/core/controllers.html +34 -34
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +34 -34
- nautobot/project-static/docs/development/core/generic-views.html +34 -34
- nautobot/project-static/docs/development/core/getting-started.html +34 -34
- nautobot/project-static/docs/development/core/homepage.html +34 -34
- nautobot/project-static/docs/development/core/index.html +34 -34
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +34 -34
- nautobot/project-static/docs/development/core/model-checklist.html +34 -34
- nautobot/project-static/docs/development/core/model-features.html +34 -34
- nautobot/project-static/docs/development/core/natural-keys.html +34 -34
- nautobot/project-static/docs/development/core/navigation-menu.html +34 -34
- nautobot/project-static/docs/development/core/release-checklist.html +34 -34
- nautobot/project-static/docs/development/core/role-internals.html +34 -34
- nautobot/project-static/docs/development/core/settings.html +34 -34
- nautobot/project-static/docs/development/core/style-guide.html +34 -34
- nautobot/project-static/docs/development/core/templates.html +34 -34
- nautobot/project-static/docs/development/core/testing.html +34 -34
- nautobot/project-static/docs/development/core/ui-component-framework.html +724 -289
- nautobot/project-static/docs/development/core/user-preferences.html +34 -34
- nautobot/project-static/docs/development/index.html +34 -34
- nautobot/project-static/docs/development/jobs/getting-started.html +34 -34
- nautobot/project-static/docs/development/jobs/index.html +34 -34
- nautobot/project-static/docs/development/jobs/installation.html +34 -34
- nautobot/project-static/docs/development/jobs/job-extensions.html +34 -34
- nautobot/project-static/docs/development/jobs/job-logging.html +34 -34
- nautobot/project-static/docs/development/jobs/job-patterns.html +34 -34
- nautobot/project-static/docs/development/jobs/job-structure.html +34 -34
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +34 -34
- nautobot/project-static/docs/development/jobs/testing.html +34 -34
- nautobot/project-static/docs/index.html +34 -34
- nautobot/project-static/docs/media/development/core/ui-component-framework/breadcrumbs-titles-data-flow.png +0 -0
- nautobot/project-static/docs/media/power_distribution.png +0 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +34 -34
- nautobot/project-static/docs/overview/design_philosophy.html +34 -34
- nautobot/project-static/docs/release-notes/index.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.4.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.5.html +34 -34
- nautobot/project-static/docs/release-notes/version-1.6.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.0.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.1.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.2.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.3.html +34 -34
- nautobot/project-static/docs/release-notes/version-2.4.html +402 -34
- nautobot/project-static/docs/requirements.txt +3 -3
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +303 -299
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +34 -34
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +37 -37
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +34 -34
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +34 -34
- nautobot/project-static/docs/user-guide/administration/installation/services.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +34 -34
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/security/notices.html +34 -34
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +296 -251
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +34 -34
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +42 -52
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +316 -39
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +35 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +147 -37
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +52 -35
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +51 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +34 -34
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +34 -34
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +34 -34
- nautobot/project-static/docs/user-guide/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +35 -35
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +34 -34
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +34 -34
- nautobot/tenancy/api/views.py +2 -1
- nautobot/users/tests/test_api.py +2 -2
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -252
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -75
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +252 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_update.html +75 -0
- nautobot/virtualization/urls.py +3 -61
- nautobot/virtualization/views.py +48 -72
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/METADATA +27 -27
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/RECORD +463 -439
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/NOTICE +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/WHEEL +0 -0
- {nautobot-2.4.13.dist-info → nautobot-2.4.15.dist-info}/entry_points.txt +0 -0
|
@@ -14,10 +14,12 @@ from nautobot.dcim.choices import (
|
|
|
14
14
|
InterfaceModeChoices,
|
|
15
15
|
InterfaceTypeChoices,
|
|
16
16
|
PortTypeChoices,
|
|
17
|
+
PowerFeedBreakerPoleChoices,
|
|
17
18
|
PowerFeedPhaseChoices,
|
|
18
19
|
PowerFeedSupplyChoices,
|
|
19
20
|
PowerFeedTypeChoices,
|
|
20
21
|
PowerOutletFeedLegChoices,
|
|
22
|
+
PowerPathChoices,
|
|
21
23
|
RackDimensionUnitChoices,
|
|
22
24
|
RackTypeChoices,
|
|
23
25
|
RackWidthChoices,
|
|
@@ -120,6 +122,7 @@ from nautobot.dcim.models import (
|
|
|
120
122
|
VirtualChassis,
|
|
121
123
|
VirtualDeviceContext,
|
|
122
124
|
)
|
|
125
|
+
from nautobot.extras.filters.mixins import RoleFilter, StatusFilter
|
|
123
126
|
from nautobot.extras.models import ExternalIntegration, Role, SecretsGroup, Status, Tag
|
|
124
127
|
from nautobot.ipam.models import IPAddress, Namespace, Prefix, Service, VLAN, VLANGroup
|
|
125
128
|
from nautobot.tenancy.models import Tenant
|
|
@@ -230,6 +233,7 @@ def common_test_data(cls):
|
|
|
230
233
|
PowerPanel.objects.create(name="Power Panel 1", location=loc0, rack_group=rack_groups[0]),
|
|
231
234
|
PowerPanel.objects.create(name="Power Panel 2", location=loc1, rack_group=rack_groups[1]),
|
|
232
235
|
PowerPanel.objects.create(name="Power Panel 3", location=loc1, rack_group=rack_groups[2]),
|
|
236
|
+
PowerPanel.objects.create(name="Power Panel 4", location=loc0),
|
|
233
237
|
)
|
|
234
238
|
power_panels[0].tags.set(Tag.objects.get_for_model(PowerPanel))
|
|
235
239
|
power_panels[1].tags.set(Tag.objects.get_for_model(PowerPanel)[:3])
|
|
@@ -350,7 +354,19 @@ def common_test_data(cls):
|
|
|
350
354
|
power_feeds = (
|
|
351
355
|
PowerFeed.objects.create(name="Power Feed 1", rack=racks[0], power_panel=power_panels[0], status=pf_status),
|
|
352
356
|
PowerFeed.objects.create(name="Power Feed 2", rack=racks[1], power_panel=power_panels[1], status=pf_status),
|
|
353
|
-
PowerFeed.objects.create(
|
|
357
|
+
PowerFeed.objects.create(
|
|
358
|
+
name="Power Feed 3",
|
|
359
|
+
rack=racks[2],
|
|
360
|
+
power_panel=power_panels[2],
|
|
361
|
+
status=pf_status,
|
|
362
|
+
destination_panel=power_panels[0],
|
|
363
|
+
),
|
|
364
|
+
PowerFeed.objects.create(
|
|
365
|
+
name="Power Feed 4",
|
|
366
|
+
power_panel=power_panels[1],
|
|
367
|
+
status=pf_status,
|
|
368
|
+
destination_panel=power_panels[3],
|
|
369
|
+
),
|
|
354
370
|
)
|
|
355
371
|
power_feeds[0].tags.set(Tag.objects.get_for_model(PowerFeed))
|
|
356
372
|
power_feeds[1].tags.set(Tag.objects.get_for_model(PowerFeed)[:3])
|
|
@@ -696,42 +712,42 @@ def common_test_data(cls):
|
|
|
696
712
|
# Create 3 of each component template on the first two module types
|
|
697
713
|
for i in range(6):
|
|
698
714
|
ConsolePortTemplate.objects.create(
|
|
699
|
-
name=f"Test Filters Module Console Port {i+1}",
|
|
715
|
+
name=f"Test Filters Module Console Port {i + 1}",
|
|
700
716
|
module_type=module_types[i % 2],
|
|
701
717
|
)
|
|
702
718
|
ConsoleServerPortTemplate.objects.create(
|
|
703
|
-
name=f"Test Filters Module Console Server Port {i+1}",
|
|
719
|
+
name=f"Test Filters Module Console Server Port {i + 1}",
|
|
704
720
|
module_type=module_types[i % 2],
|
|
705
721
|
)
|
|
706
722
|
ppt = PowerPortTemplate.objects.create(
|
|
707
|
-
name=f"Test Filters Module Power Port {i+1}",
|
|
723
|
+
name=f"Test Filters Module Power Port {i + 1}",
|
|
708
724
|
module_type=module_types[i % 2],
|
|
709
725
|
)
|
|
710
726
|
PowerOutletTemplate.objects.create(
|
|
711
|
-
name=f"Test Filters Module Power Outlet {i+1}",
|
|
727
|
+
name=f"Test Filters Module Power Outlet {i + 1}",
|
|
712
728
|
power_port_template=ppt,
|
|
713
729
|
module_type=module_types[i % 2],
|
|
714
730
|
)
|
|
715
731
|
InterfaceTemplate.objects.create(
|
|
716
|
-
name=f"Test Filters Module Interface {i+1}",
|
|
732
|
+
name=f"Test Filters Module Interface {i + 1}",
|
|
717
733
|
type=InterfaceTypeChoices.TYPE_1GE_FIXED,
|
|
718
734
|
module_type=module_types[i % 2],
|
|
719
735
|
)
|
|
720
736
|
rpt = RearPortTemplate.objects.create(
|
|
721
|
-
name=f"Test Filters Module Rear Port {i+1}",
|
|
737
|
+
name=f"Test Filters Module Rear Port {i + 1}",
|
|
722
738
|
module_type=module_types[i % 2],
|
|
723
739
|
type=PortTypeChoices.TYPE_8P8C,
|
|
724
740
|
positions=10,
|
|
725
741
|
)
|
|
726
742
|
FrontPortTemplate.objects.create(
|
|
727
|
-
name=f"Test Filters Module Front Port {i+1}",
|
|
743
|
+
name=f"Test Filters Module Front Port {i + 1}",
|
|
728
744
|
module_type=module_types[i % 2],
|
|
729
745
|
rear_port_template=rpt,
|
|
730
746
|
rear_port_position=i + 1,
|
|
731
747
|
type=PortTypeChoices.TYPE_8P8C,
|
|
732
748
|
)
|
|
733
749
|
ModuleBayTemplate.objects.create(
|
|
734
|
-
name=f"Test Filters Module Module Bay {i+1}",
|
|
750
|
+
name=f"Test Filters Module Module Bay {i + 1}",
|
|
735
751
|
position=i + 1,
|
|
736
752
|
module_type=module_types[i % 2],
|
|
737
753
|
requires_first_party_modules=(i % 2 == 0), # True for even indices, False for odd
|
|
@@ -1253,7 +1269,7 @@ class RackTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
|
|
|
1253
1269
|
|
|
1254
1270
|
rack_group = RackGroup.objects.get(name="Rack Group 3")
|
|
1255
1271
|
tenant = Tenant.objects.filter(tenant_group__isnull=False).first()
|
|
1256
|
-
rack_role = Role.objects.get_for_model(Rack).first()
|
|
1272
|
+
cls.rack_role = Role.objects.get_for_model(Rack).first()
|
|
1257
1273
|
|
|
1258
1274
|
Rack.objects.create(
|
|
1259
1275
|
name="Rack 4",
|
|
@@ -1262,7 +1278,7 @@ class RackTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
|
|
|
1262
1278
|
rack_group=rack_group,
|
|
1263
1279
|
tenant=tenant,
|
|
1264
1280
|
status=cls.rack_statuses[0],
|
|
1265
|
-
role=rack_role,
|
|
1281
|
+
role=cls.rack_role,
|
|
1266
1282
|
serial="ABCDEF",
|
|
1267
1283
|
asset_tag="1004",
|
|
1268
1284
|
type=RackTypeChoices.TYPE_2POST,
|
|
@@ -1291,6 +1307,34 @@ class RackTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilter
|
|
|
1291
1307
|
params = {"outer_unit": [RackDimensionUnitChoices.UNIT_MILLIMETER]}
|
|
1292
1308
|
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
|
|
1293
1309
|
|
|
1310
|
+
def test_role_status_negation(self):
|
|
1311
|
+
"""https://github.com/nautobot/nautobot/issues/6456"""
|
|
1312
|
+
self.assertIsInstance(self.filterset().filters["role"], RoleFilter)
|
|
1313
|
+
self.assertIsInstance(self.filterset().filters["role__n"], RoleFilter)
|
|
1314
|
+
with self.subTest("Negated role (id)"):
|
|
1315
|
+
params = {"role__n": [self.rack_role.pk]}
|
|
1316
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
1317
|
+
self.filterset(params, self.queryset).qs, Rack.objects.exclude(role=self.rack_role)
|
|
1318
|
+
)
|
|
1319
|
+
with self.subTest("Negated role (name)"):
|
|
1320
|
+
params = {"role__n": [self.rack_role.name]}
|
|
1321
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
1322
|
+
self.filterset(params, self.queryset).qs, Rack.objects.exclude(role=self.rack_role)
|
|
1323
|
+
)
|
|
1324
|
+
|
|
1325
|
+
self.assertIsInstance(self.filterset().filters["status"], StatusFilter)
|
|
1326
|
+
self.assertIsInstance(self.filterset().filters["status__n"], StatusFilter)
|
|
1327
|
+
with self.subTest("Negated status (id)"):
|
|
1328
|
+
params = {"status__n": [self.rack_statuses[0].pk]}
|
|
1329
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
1330
|
+
self.filterset(params, self.queryset).qs, Rack.objects.exclude(status=self.rack_statuses[0])
|
|
1331
|
+
)
|
|
1332
|
+
with self.subTest("Negated status (name)"):
|
|
1333
|
+
params = {"status__n": [self.rack_statuses[0].name]}
|
|
1334
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
1335
|
+
self.filterset(params, self.queryset).qs, Rack.objects.exclude(status=self.rack_statuses[0])
|
|
1336
|
+
)
|
|
1337
|
+
|
|
1294
1338
|
|
|
1295
1339
|
class RackReservationTestCase(FilterTestCases.FilterTestCase, FilterTestCases.TenancyFilterTestCaseMixin):
|
|
1296
1340
|
queryset = RackReservation.objects.all()
|
|
@@ -3559,8 +3603,6 @@ class PowerPanelTestCase(FilterTestCases.FilterTestCase):
|
|
|
3559
3603
|
def setUpTestData(cls):
|
|
3560
3604
|
common_test_data(cls)
|
|
3561
3605
|
|
|
3562
|
-
PowerPanel.objects.create(name="Power Panel 4", location=cls.loc1)
|
|
3563
|
-
|
|
3564
3606
|
|
|
3565
3607
|
class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCase):
|
|
3566
3608
|
queryset = PowerFeed.objects.all()
|
|
@@ -3568,8 +3610,12 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3568
3610
|
generic_filter_tests = [
|
|
3569
3611
|
("amperage",),
|
|
3570
3612
|
("available_power",),
|
|
3613
|
+
("breaker_pole_count",),
|
|
3614
|
+
("breaker_position",),
|
|
3571
3615
|
("cable", "cable__id"),
|
|
3572
3616
|
("comments",),
|
|
3617
|
+
("destination_panel", "destination_panel__id"),
|
|
3618
|
+
("destination_panel", "destination_panel__name"),
|
|
3573
3619
|
("max_utilization",),
|
|
3574
3620
|
("name",),
|
|
3575
3621
|
("power_panel", "power_panel__id"),
|
|
@@ -3589,6 +3635,7 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3589
3635
|
PowerFeed.objects.get(name="Power Feed 1"),
|
|
3590
3636
|
PowerFeed.objects.get(name="Power Feed 2"),
|
|
3591
3637
|
PowerFeed.objects.get(name="Power Feed 3"),
|
|
3638
|
+
PowerFeed.objects.get(name="Power Feed 4"),
|
|
3592
3639
|
)
|
|
3593
3640
|
|
|
3594
3641
|
pf_statuses = Status.objects.get_for_model(PowerFeed)
|
|
@@ -3602,6 +3649,9 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3602
3649
|
amperage=100,
|
|
3603
3650
|
max_utilization=10,
|
|
3604
3651
|
comments="PFA",
|
|
3652
|
+
power_path=PowerPathChoices.PATH_A,
|
|
3653
|
+
breaker_position=1,
|
|
3654
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_1,
|
|
3605
3655
|
)
|
|
3606
3656
|
PowerFeed.objects.filter(pk=power_feeds[1].pk).update(
|
|
3607
3657
|
status=pf_statuses[1],
|
|
@@ -3612,6 +3662,9 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3612
3662
|
amperage=200,
|
|
3613
3663
|
max_utilization=20,
|
|
3614
3664
|
comments="PFB",
|
|
3665
|
+
power_path=PowerPathChoices.PATH_B,
|
|
3666
|
+
breaker_position=4,
|
|
3667
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_2,
|
|
3615
3668
|
)
|
|
3616
3669
|
PowerFeed.objects.filter(pk=power_feeds[2].pk).update(
|
|
3617
3670
|
status=pf_statuses[2],
|
|
@@ -3622,14 +3675,32 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3622
3675
|
amperage=300,
|
|
3623
3676
|
max_utilization=30,
|
|
3624
3677
|
comments="PFC",
|
|
3678
|
+
power_path=PowerPathChoices.PATH_A,
|
|
3679
|
+
breaker_position=9,
|
|
3680
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_3,
|
|
3681
|
+
)
|
|
3682
|
+
PowerFeed.objects.filter(pk=power_feeds[3].pk).update(
|
|
3683
|
+
status=pf_statuses[0],
|
|
3684
|
+
type=PowerFeedTypeChoices.TYPE_REDUNDANT,
|
|
3685
|
+
supply=PowerFeedSupplyChoices.SUPPLY_AC,
|
|
3686
|
+
phase=PowerFeedPhaseChoices.PHASE_3PHASE,
|
|
3687
|
+
voltage=400,
|
|
3688
|
+
amperage=400,
|
|
3689
|
+
max_utilization=40,
|
|
3690
|
+
comments="PFD",
|
|
3691
|
+
power_path=PowerPathChoices.PATH_B,
|
|
3692
|
+
breaker_position=15,
|
|
3693
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_2,
|
|
3625
3694
|
)
|
|
3626
3695
|
|
|
3627
3696
|
power_feeds[0].refresh_from_db()
|
|
3628
3697
|
power_feeds[1].refresh_from_db()
|
|
3629
3698
|
power_feeds[2].refresh_from_db()
|
|
3699
|
+
power_feeds[3].refresh_from_db()
|
|
3630
3700
|
power_feeds[0].validated_save()
|
|
3631
3701
|
power_feeds[1].validated_save()
|
|
3632
3702
|
power_feeds[2].validated_save()
|
|
3703
|
+
power_feeds[3].validated_save()
|
|
3633
3704
|
|
|
3634
3705
|
power_ports = (
|
|
3635
3706
|
PowerPort.objects.get(name="Power Port 1"),
|
|
@@ -3674,6 +3745,13 @@ class PowerFeedTestCase(PathEndpointModelTestMixin, FilterTestCases.FilterTestCa
|
|
|
3674
3745
|
self.queryset.filter(phase=PowerFeedPhaseChoices.PHASE_3PHASE),
|
|
3675
3746
|
)
|
|
3676
3747
|
|
|
3748
|
+
def test_power_path(self):
|
|
3749
|
+
params = {"power_path": [PowerPathChoices.PATH_A]}
|
|
3750
|
+
self.assertQuerysetEqualAndNotEmpty(
|
|
3751
|
+
self.filterset(params, self.queryset).qs,
|
|
3752
|
+
self.queryset.filter(power_path=PowerPathChoices.PATH_A),
|
|
3753
|
+
)
|
|
3754
|
+
|
|
3677
3755
|
|
|
3678
3756
|
class DeviceRedundancyGroupTestCase(FilterTestCases.FilterTestCase):
|
|
3679
3757
|
queryset = DeviceRedundancyGroup.objects.all()
|
|
@@ -19,6 +19,10 @@ from nautobot.dcim.choices import (
|
|
|
19
19
|
InterfaceModeChoices,
|
|
20
20
|
InterfaceTypeChoices,
|
|
21
21
|
PortTypeChoices,
|
|
22
|
+
PowerFeedBreakerPoleChoices,
|
|
23
|
+
PowerFeedPhaseChoices,
|
|
24
|
+
PowerFeedSupplyChoices,
|
|
25
|
+
PowerFeedTypeChoices,
|
|
22
26
|
PowerOutletFeedLegChoices,
|
|
23
27
|
PowerOutletTypeChoices,
|
|
24
28
|
PowerPortTypeChoices,
|
|
@@ -53,6 +57,7 @@ from nautobot.dcim.models import (
|
|
|
53
57
|
ModuleFamily,
|
|
54
58
|
ModuleType,
|
|
55
59
|
Platform,
|
|
60
|
+
PowerFeed,
|
|
56
61
|
PowerOutlet,
|
|
57
62
|
PowerOutletTemplate,
|
|
58
63
|
PowerPanel,
|
|
@@ -2389,6 +2394,263 @@ class CableTestCase(ModelTestCases.BaseModelTestCase):
|
|
|
2389
2394
|
self.device1.delete()
|
|
2390
2395
|
|
|
2391
2396
|
|
|
2397
|
+
class PowerFeedTestCase(ModelTestCases.BaseModelTestCase):
|
|
2398
|
+
model = PowerFeed
|
|
2399
|
+
|
|
2400
|
+
@classmethod
|
|
2401
|
+
def setUpTestData(cls):
|
|
2402
|
+
cls.location = Location.objects.filter(location_type=LocationType.objects.get(name="Campus")).first()
|
|
2403
|
+
cls.status = Status.objects.get_for_model(PowerFeed).first()
|
|
2404
|
+
cls.rack_status = Status.objects.get_for_model(Rack).first()
|
|
2405
|
+
|
|
2406
|
+
cls.source_panel = PowerPanel.objects.create(location=cls.location, name="Source Panel 1")
|
|
2407
|
+
cls.destination_panel = PowerPanel.objects.create(location=cls.location, name="Destination Panel 1")
|
|
2408
|
+
|
|
2409
|
+
# Create location in different hierarchy for rack validation test
|
|
2410
|
+
cls.other_location = Location.objects.create(
|
|
2411
|
+
name="Other Location",
|
|
2412
|
+
location_type=LocationType.objects.get(name="Campus"),
|
|
2413
|
+
status=Status.objects.get_for_model(Location).first(),
|
|
2414
|
+
)
|
|
2415
|
+
|
|
2416
|
+
cls.rack = Rack.objects.create(location=cls.location, name="Test Rack", status=cls.rack_status)
|
|
2417
|
+
cls.other_rack = Rack.objects.create(location=cls.other_location, name="Other Rack", status=cls.rack_status)
|
|
2418
|
+
|
|
2419
|
+
PowerFeed.objects.create(
|
|
2420
|
+
name="Test Power Feed 1",
|
|
2421
|
+
power_panel=cls.source_panel,
|
|
2422
|
+
rack=cls.rack,
|
|
2423
|
+
status=cls.status,
|
|
2424
|
+
)
|
|
2425
|
+
PowerFeed.objects.create(
|
|
2426
|
+
name="Test Power Feed 2",
|
|
2427
|
+
power_panel=cls.source_panel,
|
|
2428
|
+
status=cls.status,
|
|
2429
|
+
)
|
|
2430
|
+
PowerFeed.objects.create(
|
|
2431
|
+
name="Test Power Feed 3",
|
|
2432
|
+
power_panel=cls.destination_panel,
|
|
2433
|
+
status=cls.status,
|
|
2434
|
+
)
|
|
2435
|
+
|
|
2436
|
+
def test_destination_panel_self_reference_validation(self):
|
|
2437
|
+
"""Test that a power feed cannot reference itself."""
|
|
2438
|
+
feed = PowerFeed(
|
|
2439
|
+
name="Self Reference",
|
|
2440
|
+
power_panel=self.source_panel,
|
|
2441
|
+
destination_panel=self.source_panel,
|
|
2442
|
+
status=self.status,
|
|
2443
|
+
)
|
|
2444
|
+
|
|
2445
|
+
with self.assertRaises(ValidationError) as cm:
|
|
2446
|
+
feed.full_clean()
|
|
2447
|
+
self.assertIn("destination_panel", cm.exception.message_dict)
|
|
2448
|
+
|
|
2449
|
+
def test_circuit_breaker_position_conflict_validation(self):
|
|
2450
|
+
"""Test that overlapping circuit breaker positions raise validation errors."""
|
|
2451
|
+
# Create first feed at position 1 with 2 poles (occupies 1,3)
|
|
2452
|
+
PowerFeed.objects.create(
|
|
2453
|
+
name="Feed 1",
|
|
2454
|
+
power_panel=self.source_panel,
|
|
2455
|
+
status=self.status,
|
|
2456
|
+
breaker_position=1,
|
|
2457
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_2,
|
|
2458
|
+
)
|
|
2459
|
+
|
|
2460
|
+
# Try to create conflicting feed at position 3
|
|
2461
|
+
conflicting_feed = PowerFeed(
|
|
2462
|
+
name="Feed 2",
|
|
2463
|
+
power_panel=self.source_panel,
|
|
2464
|
+
status=self.status,
|
|
2465
|
+
breaker_position=3,
|
|
2466
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_1,
|
|
2467
|
+
)
|
|
2468
|
+
|
|
2469
|
+
with self.assertRaises(ValidationError) as cm:
|
|
2470
|
+
conflicting_feed.full_clean()
|
|
2471
|
+
self.assertIn("breaker_position", cm.exception.message_dict)
|
|
2472
|
+
|
|
2473
|
+
def test_rack_location_hierarchy_validation(self):
|
|
2474
|
+
"""Test that rack must belong to same location hierarchy as power panel."""
|
|
2475
|
+
feed = PowerFeed(
|
|
2476
|
+
name="Invalid Rack Location",
|
|
2477
|
+
power_panel=self.source_panel,
|
|
2478
|
+
rack=self.other_rack, # Different location hierarchy
|
|
2479
|
+
status=self.status,
|
|
2480
|
+
)
|
|
2481
|
+
|
|
2482
|
+
with self.assertRaises(ValidationError) as cm:
|
|
2483
|
+
feed.full_clean()
|
|
2484
|
+
self.assertIn("rack", cm.exception.message_dict)
|
|
2485
|
+
|
|
2486
|
+
def test_ac_voltage_negative_validation(self):
|
|
2487
|
+
"""Test that AC supply cannot have negative voltage."""
|
|
2488
|
+
feed = PowerFeed(
|
|
2489
|
+
name="Negative Voltage",
|
|
2490
|
+
power_panel=self.source_panel,
|
|
2491
|
+
status=self.status,
|
|
2492
|
+
voltage=-120,
|
|
2493
|
+
supply=PowerFeedSupplyChoices.SUPPLY_AC,
|
|
2494
|
+
)
|
|
2495
|
+
|
|
2496
|
+
with self.assertRaises(ValidationError) as cm:
|
|
2497
|
+
feed.full_clean()
|
|
2498
|
+
self.assertIn("voltage", cm.exception.message_dict)
|
|
2499
|
+
|
|
2500
|
+
def test_phase_designation_single_pole(self):
|
|
2501
|
+
"""Test phase designation calculation for single-pole breakers."""
|
|
2502
|
+
# Pattern: positions 1,2=A, 3,4=B, 5,6=C, 7,8=A, etc.
|
|
2503
|
+
test_cases = [
|
|
2504
|
+
(1, "A"),
|
|
2505
|
+
(2, "A"),
|
|
2506
|
+
(3, "B"),
|
|
2507
|
+
(4, "B"),
|
|
2508
|
+
(5, "C"),
|
|
2509
|
+
(6, "C"),
|
|
2510
|
+
(7, "A"),
|
|
2511
|
+
(8, "A"),
|
|
2512
|
+
(9, "B"),
|
|
2513
|
+
(10, "B"),
|
|
2514
|
+
]
|
|
2515
|
+
|
|
2516
|
+
for position, expected_phase in test_cases:
|
|
2517
|
+
with self.subTest(position=position):
|
|
2518
|
+
feed = PowerFeed.objects.create(
|
|
2519
|
+
name=f"1P Test {position}",
|
|
2520
|
+
power_panel=self.source_panel,
|
|
2521
|
+
status=self.status,
|
|
2522
|
+
breaker_position=position,
|
|
2523
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_1,
|
|
2524
|
+
# phase defaults to PHASE_SINGLE which is correct for all single-pole feeds
|
|
2525
|
+
)
|
|
2526
|
+
self.assertEqual(feed.phase_designation, expected_phase)
|
|
2527
|
+
|
|
2528
|
+
def test_phase_designation_two_pole_single_phase(self):
|
|
2529
|
+
"""Test phase designation for 2-pole breakers delivering single-phase power."""
|
|
2530
|
+
# Common datacenter scenario: 2P breaker for 208V single-phase to rack PDU
|
|
2531
|
+
# Uses two phase conductors but delivers single-phase power
|
|
2532
|
+
test_cases = [
|
|
2533
|
+
(1, "A-B"), # occupies 1,3 → A,B → 208V single-phase
|
|
2534
|
+
(2, "A-B"), # occupies 2,4 → A,B → 208V single-phase
|
|
2535
|
+
(3, "B-C"), # occupies 3,5 → B,C → 208V single-phase
|
|
2536
|
+
(4, "B-C"), # occupies 4,6 → B,C → 208V single-phase
|
|
2537
|
+
(5, "A-C"), # occupies 5,7 → C,A → sorted to A-C → 208V single-phase
|
|
2538
|
+
(6, "A-C"), # occupies 6,8 → C,A → sorted to A-C → 208V single-phase
|
|
2539
|
+
(7, "A-B"), # occupies 7,9 → A,B → 208V single-phase (cycle continues)
|
|
2540
|
+
]
|
|
2541
|
+
|
|
2542
|
+
for position, expected_designation in test_cases:
|
|
2543
|
+
with self.subTest(position=position):
|
|
2544
|
+
feed = PowerFeed.objects.create(
|
|
2545
|
+
name=f"2P Single-Phase Test {position}",
|
|
2546
|
+
power_panel=self.source_panel,
|
|
2547
|
+
status=self.status,
|
|
2548
|
+
breaker_position=position,
|
|
2549
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_2,
|
|
2550
|
+
# phase defaults to PHASE_SINGLE - correct for 208V single-phase feeds
|
|
2551
|
+
)
|
|
2552
|
+
self.assertEqual(feed.phase_designation, expected_designation)
|
|
2553
|
+
# Verify it's still marked as single-phase power
|
|
2554
|
+
self.assertEqual(feed.phase, PowerFeedPhaseChoices.PHASE_SINGLE)
|
|
2555
|
+
|
|
2556
|
+
def test_phase_designation_three_pole_three_phase(self):
|
|
2557
|
+
"""Test phase designation for 3-pole breakers delivering three-phase power."""
|
|
2558
|
+
# True three-phase power using all three phases
|
|
2559
|
+
test_cases = [1, 2, 3, 4, 5]
|
|
2560
|
+
|
|
2561
|
+
for position in test_cases:
|
|
2562
|
+
with self.subTest(position=position):
|
|
2563
|
+
feed = PowerFeed.objects.create(
|
|
2564
|
+
name=f"3P Three-Phase Test {position}",
|
|
2565
|
+
power_panel=self.source_panel,
|
|
2566
|
+
status=self.status,
|
|
2567
|
+
breaker_position=position,
|
|
2568
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_3,
|
|
2569
|
+
phase=PowerFeedPhaseChoices.PHASE_3PHASE, # Explicitly set to three-phase
|
|
2570
|
+
)
|
|
2571
|
+
self.assertEqual(feed.phase_designation, "A-B-C")
|
|
2572
|
+
# Verify it's marked as three-phase power
|
|
2573
|
+
self.assertEqual(feed.phase, PowerFeedPhaseChoices.PHASE_3PHASE)
|
|
2574
|
+
|
|
2575
|
+
def test_phase_designation_edge_cases(self):
|
|
2576
|
+
"""Test phase designation calculation for edge cases and None values."""
|
|
2577
|
+
# Test missing breaker_position
|
|
2578
|
+
feed = PowerFeed.objects.create(
|
|
2579
|
+
name="No Position",
|
|
2580
|
+
power_panel=self.source_panel,
|
|
2581
|
+
status=self.status,
|
|
2582
|
+
breaker_position=None,
|
|
2583
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_1,
|
|
2584
|
+
)
|
|
2585
|
+
self.assertIsNone(feed.phase_designation)
|
|
2586
|
+
|
|
2587
|
+
# Test missing breaker_pole_count (should default to single pole)
|
|
2588
|
+
feed = PowerFeed.objects.create(
|
|
2589
|
+
name="No Pole Count",
|
|
2590
|
+
power_panel=self.source_panel,
|
|
2591
|
+
status=self.status,
|
|
2592
|
+
breaker_position=1,
|
|
2593
|
+
breaker_pole_count=None,
|
|
2594
|
+
)
|
|
2595
|
+
# Should default to single pole and have phase designation
|
|
2596
|
+
self.assertEqual(feed.breaker_pole_count, PowerFeedBreakerPoleChoices.POLE_1)
|
|
2597
|
+
self.assertEqual(feed.phase_designation, "A")
|
|
2598
|
+
|
|
2599
|
+
# Test both missing
|
|
2600
|
+
feed = PowerFeed.objects.create(
|
|
2601
|
+
name="No Position or Pole Count",
|
|
2602
|
+
power_panel=self.source_panel,
|
|
2603
|
+
status=self.status,
|
|
2604
|
+
breaker_position=None,
|
|
2605
|
+
breaker_pole_count=None,
|
|
2606
|
+
)
|
|
2607
|
+
self.assertIsNone(feed.phase_designation)
|
|
2608
|
+
|
|
2609
|
+
def test_phase_field_defaults(self):
|
|
2610
|
+
"""Test that phase field defaults correctly and type field defaults to primary."""
|
|
2611
|
+
feed = PowerFeed.objects.create(
|
|
2612
|
+
name="Default Fields Test",
|
|
2613
|
+
power_panel=self.source_panel,
|
|
2614
|
+
status=self.status,
|
|
2615
|
+
)
|
|
2616
|
+
|
|
2617
|
+
# Verify defaults
|
|
2618
|
+
self.assertEqual(feed.phase, PowerFeedPhaseChoices.PHASE_SINGLE)
|
|
2619
|
+
self.assertEqual(feed.type, PowerFeedTypeChoices.TYPE_PRIMARY)
|
|
2620
|
+
|
|
2621
|
+
def test_occupied_positions(self):
|
|
2622
|
+
"""Test occupied positions calculation."""
|
|
2623
|
+
feed = PowerFeed.objects.create(
|
|
2624
|
+
name="Test Feed",
|
|
2625
|
+
power_panel=self.source_panel,
|
|
2626
|
+
status=self.status,
|
|
2627
|
+
breaker_position=5,
|
|
2628
|
+
breaker_pole_count=PowerFeedBreakerPoleChoices.POLE_2,
|
|
2629
|
+
)
|
|
2630
|
+
|
|
2631
|
+
self.assertEqual(feed.get_occupied_positions(), {5, 7})
|
|
2632
|
+
self.assertEqual(feed.occupied_positions, "5, 7")
|
|
2633
|
+
|
|
2634
|
+
def test_breaker_pole_count_enforcement_in_save(self):
|
|
2635
|
+
"""Test that breaker_pole_count defaults to POLE_1 when breaker_position is set during save."""
|
|
2636
|
+
# Create feed with breaker_position but no breaker_pole_count
|
|
2637
|
+
feed = PowerFeed(
|
|
2638
|
+
name="Test Save Enforcement",
|
|
2639
|
+
power_panel=self.source_panel,
|
|
2640
|
+
status=self.status,
|
|
2641
|
+
breaker_position=10,
|
|
2642
|
+
)
|
|
2643
|
+
|
|
2644
|
+
# Verify breaker_pole_count is None before save
|
|
2645
|
+
self.assertIsNone(feed.breaker_pole_count)
|
|
2646
|
+
|
|
2647
|
+
# Save without calling clean() to bypass form validation
|
|
2648
|
+
feed.save()
|
|
2649
|
+
|
|
2650
|
+
# Verify breaker_pole_count was set to POLE_1 during save
|
|
2651
|
+
self.assertEqual(feed.breaker_pole_count, PowerFeedBreakerPoleChoices.POLE_1)
|
|
2652
|
+
|
|
2653
|
+
|
|
2392
2654
|
class PowerPanelTestCase(TestCase): # TODO: change to BaseModelTestCase once we have a PowerPanelFactory
|
|
2393
2655
|
def test_power_panel_validation(self):
|
|
2394
2656
|
status = Status.objects.get_for_model(Location).first()
|
|
@@ -715,32 +715,33 @@ class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
715
715
|
# Test the view
|
|
716
716
|
response = self.client.get(reverse("dcim:rack", args=[self.racks[0].pk]))
|
|
717
717
|
self.assertHttpStatus(response, 200)
|
|
718
|
+
|
|
718
719
|
# Validate Power Utilization for PowerFeed 11 is displaying correctly on Rack View.
|
|
719
720
|
power_feed_11_html = """
|
|
720
|
-
<td><div title="Used:
|
|
721
|
+
<td><div title="Used: 1263 Count: 3840" class="progress text-center">
|
|
721
722
|
<div class="progress-bar progress-bar-success"
|
|
722
|
-
role="progressbar" aria-valuenow="
|
|
723
|
-
|
|
723
|
+
role="progressbar" aria-valuenow="32" aria-valuemin="0" aria-valuemax="100" style="width: 32%">
|
|
724
|
+
32%
|
|
724
725
|
</div>
|
|
725
726
|
</div></td>
|
|
726
727
|
"""
|
|
727
728
|
self.assertContains(response, power_feed_11_html, html=True)
|
|
728
729
|
# Validate Power Utilization for PowerFeed12 is displaying correctly on Rack View.
|
|
729
730
|
power_feed_12_html = """
|
|
730
|
-
<td><div title="Used:
|
|
731
|
+
<td><div title="Used: 2526 Count: 3840" class="progress text-center">
|
|
731
732
|
<div class="progress-bar progress-bar-success"
|
|
732
|
-
role="progressbar" aria-valuenow="
|
|
733
|
-
|
|
733
|
+
role="progressbar" aria-valuenow="65" aria-valuemin="0" aria-valuemax="100" style="width: 65%">
|
|
734
|
+
65%
|
|
734
735
|
</div>
|
|
735
736
|
</div></td>
|
|
736
737
|
"""
|
|
737
738
|
self.assertContains(response, power_feed_12_html, html=True)
|
|
738
739
|
# Validate Rack Power Utilization for Combined powerfeeds is displaying correctly on the Rack View
|
|
739
740
|
total_utilization_html = """
|
|
740
|
-
<td><div title="Used:
|
|
741
|
+
<td><div title="Used: 3789 Count: 7680" class="progress text-center">
|
|
741
742
|
<div class="progress-bar progress-bar-success"
|
|
742
|
-
role="progressbar" aria-valuenow="
|
|
743
|
-
|
|
743
|
+
role="progressbar" aria-valuenow="49" aria-valuemin="0" aria-valuemax="100" style="width: 49%">
|
|
744
|
+
49%
|
|
744
745
|
</div>
|
|
745
746
|
</div></td>
|
|
746
747
|
"""
|
|
@@ -1656,6 +1657,7 @@ class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas
|
|
|
1656
1657
|
"type": PowerPortTypeChoices.TYPE_IEC_C14,
|
|
1657
1658
|
"maximum_draw": 100,
|
|
1658
1659
|
"allocated_draw": 50,
|
|
1660
|
+
"power_factor": Decimal("0.95"),
|
|
1659
1661
|
}
|
|
1660
1662
|
|
|
1661
1663
|
cls.bulk_create_data = {
|
|
@@ -1665,6 +1667,7 @@ class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas
|
|
|
1665
1667
|
"type": PowerPortTypeChoices.TYPE_IEC_C14,
|
|
1666
1668
|
"maximum_draw": 100,
|
|
1667
1669
|
"allocated_draw": 50,
|
|
1670
|
+
"power_factor": Decimal("0.95"),
|
|
1668
1671
|
}
|
|
1669
1672
|
|
|
1670
1673
|
cls.bulk_edit_data = {
|
|
@@ -1678,6 +1681,7 @@ class PowerPortTemplateTestCase(ViewTestCases.DeviceComponentTemplateViewTestCas
|
|
|
1678
1681
|
"name": test_instance.name,
|
|
1679
1682
|
"device_type": getattr(getattr(test_instance, "device_type", None), "pk", None),
|
|
1680
1683
|
"module_type": getattr(getattr(test_instance, "module_type", None), "pk", None),
|
|
1684
|
+
"power_factor": Decimal("0.95"),
|
|
1681
1685
|
"label": "new test label",
|
|
1682
1686
|
"description": "new test description",
|
|
1683
1687
|
}
|
|
@@ -2134,8 +2138,9 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
|
|
2134
2138
|
devicetypes[0].software_image_files.set(software_image_files[:2])
|
|
2135
2139
|
devicetypes[1].software_image_files.set(software_image_files[2:])
|
|
2136
2140
|
# Only valid software image files are those that belong to the device type or default images
|
|
2137
|
-
valid_software_image_files =
|
|
2138
|
-
|
|
2141
|
+
valid_software_image_files = [
|
|
2142
|
+
*software_image_files[2:],
|
|
2143
|
+
SoftwareImageFile.objects.filter(default_image=True).first(),
|
|
2139
2144
|
]
|
|
2140
2145
|
|
|
2141
2146
|
cls.custom_fields = (
|
|
@@ -2885,16 +2890,18 @@ class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
|
|
2885
2890
|
"type": PowerPortTypeChoices.TYPE_IEC_C14,
|
|
2886
2891
|
"maximum_draw": 100,
|
|
2887
2892
|
"allocated_draw": 50,
|
|
2893
|
+
"power_factor": Decimal("0.95"),
|
|
2888
2894
|
"description": "A power port",
|
|
2889
2895
|
"tags": [t.pk for t in Tag.objects.get_for_model(PowerPort)],
|
|
2890
2896
|
}
|
|
2891
2897
|
|
|
2892
2898
|
cls.bulk_create_data = {
|
|
2893
2899
|
"device": device.pk,
|
|
2894
|
-
"name_pattern": "Power Port [4-6]
|
|
2900
|
+
"name_pattern": "Power Port [4-6]",
|
|
2895
2901
|
"type": PowerPortTypeChoices.TYPE_IEC_C14,
|
|
2896
2902
|
"maximum_draw": 100,
|
|
2897
2903
|
"allocated_draw": 50,
|
|
2904
|
+
"power_factor": Decimal("0.95"),
|
|
2898
2905
|
"description": "A power port",
|
|
2899
2906
|
"tags": [t.pk for t in Tag.objects.get_for_model(PowerPort)],
|
|
2900
2907
|
}
|
|
@@ -2911,6 +2918,7 @@ class PowerPortTestCase(ViewTestCases.DeviceComponentViewTestCase):
|
|
|
2911
2918
|
"name": test_instance.name,
|
|
2912
2919
|
"device": getattr(getattr(test_instance, "device", None), "pk", None),
|
|
2913
2920
|
"module": getattr(getattr(test_instance, "module", None), "pk", None),
|
|
2921
|
+
"power_factor": Decimal("0.95"),
|
|
2914
2922
|
"label": "new test label",
|
|
2915
2923
|
"description": "new test description",
|
|
2916
2924
|
}
|