nautobot 2.0.0a3__py3-none-any.whl → 2.0.0b1__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.
- nautobot/apps/api.py +6 -8
- nautobot/apps/forms.py +0 -2
- nautobot/apps/ui.py +0 -8
- nautobot/circuits/api/serializers.py +9 -117
- nautobot/circuits/api/urls.py +1 -1
- nautobot/circuits/api/views.py +0 -1
- nautobot/circuits/forms.py +0 -65
- nautobot/circuits/migrations/0014_related_name_changes.py +1 -1
- nautobot/circuits/migrations/0016_tagsfield.py +34 -0
- nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
- nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
- nautobot/circuits/models.py +3 -87
- nautobot/circuits/navigation.py +14 -69
- nautobot/circuits/signals.py +0 -2
- nautobot/circuits/tables.py +39 -1
- nautobot/circuits/tests/integration/test_relationships.py +9 -9
- nautobot/circuits/tests/test_api.py +4 -8
- nautobot/circuits/tests/test_filters.py +10 -4
- nautobot/circuits/tests/test_models.py +5 -1
- nautobot/circuits/tests/test_views.py +27 -5
- nautobot/circuits/views.py +18 -10
- nautobot/core/api/__init__.py +8 -2
- nautobot/core/api/fields.py +15 -6
- nautobot/core/api/filter_backends.py +3 -2
- nautobot/core/api/metadata.py +237 -30
- nautobot/core/api/mixins.py +94 -0
- nautobot/core/api/pagination.py +4 -0
- nautobot/core/api/parsers.py +154 -0
- nautobot/core/api/renderers.py +153 -2
- nautobot/core/api/schema.py +46 -2
- nautobot/core/api/serializers.py +377 -35
- nautobot/core/api/urls.py +11 -3
- nautobot/core/api/utils.py +174 -2
- nautobot/core/api/versioning.py +32 -10
- nautobot/core/api/views.py +266 -72
- nautobot/core/apps/__init__.py +138 -220
- nautobot/core/celery/__init__.py +112 -41
- nautobot/core/celery/backends.py +19 -12
- nautobot/core/celery/control.py +46 -0
- nautobot/core/celery/encoders.py +53 -0
- nautobot/core/celery/log.py +38 -0
- nautobot/core/celery/schedulers.py +23 -4
- nautobot/core/celery/task.py +1 -16
- nautobot/core/checks.py +0 -27
- nautobot/core/choices.py +0 -113
- nautobot/core/{cli.py → cli/__init__.py} +1 -1
- nautobot/core/cli/__main__.py +3 -0
- nautobot/core/constants.py +0 -24
- nautobot/core/context_processors.py +12 -0
- nautobot/core/filters.py +2 -2
- nautobot/core/forms/__init__.py +0 -4
- nautobot/core/forms/fields.py +38 -65
- nautobot/core/forms/forms.py +4 -1
- nautobot/core/forms/utils.py +0 -52
- nautobot/core/graphql/schema.py +4 -27
- nautobot/core/jobs/__init__.py +75 -0
- nautobot/core/management/commands/build_ui.py +255 -0
- nautobot/core/management/commands/generate_test_data.py +3 -2
- nautobot/core/management/commands/post_upgrade.py +24 -24
- nautobot/core/models/__init__.py +26 -1
- nautobot/core/models/fields.py +24 -5
- nautobot/core/models/generics.py +2 -42
- nautobot/core/models/managers.py +5 -0
- nautobot/core/models/name_color_content_types.py +0 -14
- nautobot/core/models/tree_queries.py +14 -4
- nautobot/core/models/utils.py +5 -6
- nautobot/core/models/validators.py +17 -8
- nautobot/core/releases.py +8 -10
- nautobot/core/settings.py +80 -42
- nautobot/core/tables.py +5 -5
- nautobot/core/tasks.py +4 -7
- nautobot/core/templates/base.html +1 -49
- nautobot/core/templates/base_django.html +49 -0
- nautobot/core/templates/base_react.html +55 -0
- nautobot/core/templates/buttons/export.html +6 -4
- nautobot/core/templates/generic/object_bulk_create.html +10 -21
- nautobot/core/templates/generic/object_list.html +3 -1
- nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
- nautobot/core/templates/inc/footer.html +1 -0
- nautobot/core/templates/inc/javascript.html +0 -14
- nautobot/core/templates/inc/nav_menu.html +28 -33
- nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
- nautobot/core/templates/inc/relationships_table_rows.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +8 -20
- nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
- nautobot/core/templates/rest_framework/api.html +8 -0
- nautobot/core/templatetags/buttons.py +32 -28
- nautobot/core/testing/__init__.py +47 -44
- nautobot/core/testing/api.py +362 -47
- nautobot/core/testing/filters.py +1 -1
- nautobot/core/testing/migrations.py +2 -0
- nautobot/core/testing/mixins.py +22 -9
- nautobot/core/testing/schema.py +2 -1
- nautobot/core/testing/views.py +21 -46
- nautobot/core/tests/integration/test_filters.py +17 -8
- nautobot/core/tests/integration/test_navbar.py +11 -34
- nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
- nautobot/core/tests/nautobot_config.py +2 -3
- nautobot/core/tests/test_api.py +290 -21
- nautobot/core/tests/test_checks.py +0 -7
- nautobot/core/tests/test_filters.py +107 -59
- nautobot/core/tests/test_forms.py +26 -92
- nautobot/core/tests/test_graphql.py +110 -77
- nautobot/core/tests/test_logging.py +4 -0
- nautobot/core/tests/test_managers.py +3 -1
- nautobot/core/tests/test_models.py +2 -0
- nautobot/core/tests/test_paginator.py +3 -1
- nautobot/core/tests/test_releases.py +12 -12
- nautobot/core/tests/test_templatetags_helpers.py +4 -4
- nautobot/core/tests/test_utils.py +32 -68
- nautobot/core/tests/test_views.py +12 -15
- nautobot/core/utils/data.py +17 -0
- nautobot/core/utils/deprecation.py +9 -6
- nautobot/core/utils/filtering.py +8 -3
- nautobot/core/utils/git.py +12 -4
- nautobot/core/utils/lookup.py +3 -1
- nautobot/core/utils/requests.py +1 -104
- nautobot/core/views/__init__.py +1 -0
- nautobot/core/views/generic.py +75 -110
- nautobot/core/views/mixins.py +52 -61
- nautobot/core/views/renderers.py +6 -7
- nautobot/core/views/utils.py +80 -0
- nautobot/dcim/api/serializers.py +160 -667
- nautobot/dcim/api/urls.py +1 -1
- nautobot/dcim/api/views.py +7 -44
- nautobot/dcim/choices.py +2 -0
- nautobot/dcim/filters/__init__.py +21 -0
- nautobot/dcim/form_mixins.py +1 -27
- nautobot/dcim/forms.py +19 -765
- nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -1
- nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -13
- nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -1
- nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -1
- nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
- nautobot/dcim/migrations/0035_related_name_changes.py +1 -1
- nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -1
- nautobot/dcim/migrations/0040_tagsfield.py +109 -0
- nautobot/dcim/migrations/{0040_ipam__namespaces.py → 0041_ipam__namespaces.py} +1 -1
- nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
- nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
- nautobot/dcim/models/cables.py +3 -33
- nautobot/dcim/models/device_component_templates.py +6 -0
- nautobot/dcim/models/device_components.py +12 -198
- nautobot/dcim/models/devices.py +30 -143
- nautobot/dcim/models/locations.py +3 -64
- nautobot/dcim/models/power.py +3 -50
- nautobot/dcim/models/racks.py +7 -84
- nautobot/dcim/navigation.py +141 -467
- nautobot/dcim/signals.py +0 -2
- nautobot/dcim/tables/locations.py +2 -2
- nautobot/dcim/tables/power.py +1 -2
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/devicetype.html +2 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/location.html +16 -1
- nautobot/dcim/templates/dcim/locationtype.html +15 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
- nautobot/dcim/templates/dcim/rackgroup.html +0 -12
- nautobot/dcim/tests/test_api.py +166 -81
- nautobot/dcim/tests/test_cablepaths.py +41 -35
- nautobot/dcim/tests/test_filters.py +67 -23
- nautobot/dcim/tests/test_forms.py +5 -205
- nautobot/dcim/tests/test_graphql.py +7 -2
- nautobot/dcim/tests/test_migrations.py +6 -11
- nautobot/dcim/tests/test_models.py +182 -110
- nautobot/dcim/tests/test_natural_ordering.py +11 -8
- nautobot/dcim/tests/test_signals.py +6 -3
- nautobot/dcim/tests/test_views.py +197 -175
- nautobot/dcim/urls.py +11 -16
- nautobot/dcim/views.py +7 -134
- nautobot/docs/additional-features/caching.md +6 -87
- nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
- nautobot/docs/additional-features/jobs.md +177 -195
- nautobot/docs/administration/nautobot-server.md +6 -21
- nautobot/docs/administration/replicating-nautobot.md +0 -10
- nautobot/docs/configuration/optional-settings.md +32 -41
- nautobot/docs/configuration/required-settings.md +11 -52
- nautobot/docs/development/application-registry.md +2 -13
- nautobot/docs/development/extending-models.md +15 -17
- nautobot/docs/development/generic-views.md +0 -2
- nautobot/docs/development/getting-started.md +55 -5
- nautobot/docs/development/navigation-menu.md +22 -93
- nautobot/docs/development/react-ui.md +105 -0
- nautobot/docs/development/role-internals.md +1 -3
- nautobot/docs/development/style-guide.md +6 -4
- nautobot/docs/index.md +3 -2
- nautobot/docs/installation/migrating-from-netbox.md +11 -42
- nautobot/docs/installation/nautobot.md +1 -1
- nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/docs/installation/upgrading-from-nautobot-v1.md +170 -747
- nautobot/docs/models/dcim/device.md +3 -0
- nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
- nautobot/docs/models/extras/computedfield.md +4 -4
- nautobot/docs/models/extras/gitrepository.md +3 -0
- nautobot/docs/models/extras/job.md +1 -0
- nautobot/docs/models/extras/jobbutton.md +18 -13
- nautobot/docs/models/extras/jobhook.md +7 -4
- nautobot/docs/models/extras/jobresult.md +6 -2
- nautobot/docs/models/extras/relationship.md +2 -2
- nautobot/docs/models/extras/status.md +6 -19
- nautobot/docs/models/ipam/ipaddress.md +3 -0
- nautobot/docs/models/virtualization/virtualmachine.md +3 -0
- nautobot/docs/plugins/development.md +83 -21
- nautobot/docs/release-notes/version-1.5.md +53 -0
- nautobot/docs/release-notes/version-2.0.md +180 -0
- nautobot/docs/requirements.txt +1 -0
- nautobot/docs/rest-api/overview.md +384 -215
- nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
- nautobot/extras/admin.py +3 -5
- nautobot/extras/api/customfields.py +15 -39
- nautobot/extras/api/fields.py +0 -11
- nautobot/extras/api/mixins.py +45 -0
- nautobot/extras/api/relationships.py +63 -158
- nautobot/extras/api/serializers.py +165 -700
- nautobot/extras/api/urls.py +1 -1
- nautobot/extras/api/views.py +294 -280
- nautobot/extras/apps.py +4 -7
- nautobot/extras/choices.py +11 -9
- nautobot/extras/constants.py +9 -3
- nautobot/extras/datasources/__init__.py +2 -0
- nautobot/extras/datasources/git.py +135 -186
- nautobot/extras/datasources/registry.py +25 -35
- nautobot/extras/filters/__init__.py +20 -19
- nautobot/extras/filters/mixins.py +4 -4
- nautobot/extras/forms/forms.py +63 -127
- nautobot/extras/forms/mixins.py +23 -51
- nautobot/extras/health_checks.py +0 -33
- nautobot/extras/jobs.py +387 -565
- nautobot/extras/management/commands/runjob.py +24 -62
- nautobot/extras/managers.py +30 -7
- nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
- nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -1
- nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -1
- nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -7
- nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -32
- nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -1
- nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -1
- nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
- nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -1
- nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -2
- nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -1
- nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -1
- nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
- nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -1
- nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
- nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -9
- nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -1
- nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
- nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
- nautobot/extras/migrations/{0076_remove_name_field_and_make_label_field_non_nullable.py → 0077_remove_name_field_and_make_label_field_non_nullable.py} +1 -1
- nautobot/extras/migrations/{0077_remove_slug.py → 0078_remove_slug.py} +1 -5
- nautobot/extras/migrations/0079_tagsfield.py +28 -0
- nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
- nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
- nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
- nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
- nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
- nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
- nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
- nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
- nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
- nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
- nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
- nautobot/extras/models/__init__.py +2 -3
- nautobot/extras/models/change_logging.py +0 -36
- nautobot/extras/models/customfields.py +39 -33
- nautobot/extras/models/datasources.py +48 -50
- nautobot/extras/models/groups.py +5 -6
- nautobot/extras/models/jobs.py +189 -321
- nautobot/extras/models/mixins.py +0 -71
- nautobot/extras/models/models.py +0 -19
- nautobot/extras/models/relationships.py +19 -13
- nautobot/extras/models/roles.py +0 -34
- nautobot/extras/models/secrets.py +2 -26
- nautobot/extras/models/statuses.py +6 -5
- nautobot/extras/models/tags.py +2 -17
- nautobot/extras/navigation.py +89 -307
- nautobot/extras/plugins/__init__.py +3 -120
- nautobot/extras/plugins/utils.py +0 -3
- nautobot/extras/plugins/validators.py +5 -4
- nautobot/extras/plugins/views.py +16 -3
- nautobot/extras/querysets.py +1 -7
- nautobot/extras/registry.py +3 -0
- nautobot/extras/signals.py +26 -60
- nautobot/extras/tables.py +34 -40
- nautobot/extras/tasks.py +0 -12
- nautobot/extras/templates/extras/configcontext.html +1 -1
- nautobot/extras/templates/extras/configcontextschema.html +16 -1
- nautobot/extras/templates/extras/customfield.html +0 -13
- nautobot/extras/templates/extras/gitrepository.html +3 -3
- nautobot/extras/templates/extras/inc/jobresult.html +10 -0
- nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
- nautobot/extras/templates/extras/job.html +35 -25
- nautobot/extras/templates/extras/job_approval_request.html +15 -30
- nautobot/extras/templates/extras/job_detail.html +13 -31
- nautobot/extras/templates/extras/job_edit.html +15 -17
- nautobot/extras/templates/extras/jobresult.html +24 -6
- nautobot/extras/templates/extras/scheduledjob.html +2 -2
- nautobot/extras/templates/extras/secret.html +28 -0
- nautobot/extras/templatetags/job_buttons.py +1 -0
- nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
- nautobot/extras/test_jobs/atomic_transaction.py +53 -0
- nautobot/extras/test_jobs/dry_run.py +29 -0
- nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
- nautobot/extras/test_jobs/duplicate_name2.py +9 -0
- nautobot/extras/test_jobs/fail.py +23 -0
- nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
- nautobot/extras/test_jobs/file_upload_pass.py +25 -0
- nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
- nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
- nautobot/extras/test_jobs/job_button_receiver.py +28 -0
- nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
- nautobot/extras/test_jobs/job_variables.py +88 -0
- nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
- nautobot/extras/test_jobs/log_redaction.py +20 -0
- nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
- nautobot/extras/test_jobs/modify_db.py +25 -0
- nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
- nautobot/extras/test_jobs/object_var_optional.py +21 -0
- nautobot/extras/test_jobs/object_var_required.py +21 -0
- nautobot/extras/test_jobs/object_vars.py +26 -0
- nautobot/extras/test_jobs/pass.py +25 -0
- nautobot/extras/test_jobs/profiling.py +32 -0
- nautobot/extras/test_jobs/read_only_job.py +15 -0
- nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
- nautobot/extras/{tests/example_jobs/test_soft_time_limit_greater_than_time_limit.py → test_jobs/soft_time_limit_greater_than_time_limit.py} +5 -1
- nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
- nautobot/extras/tests/integration/test_computedfields.py +1 -1
- nautobot/extras/tests/integration/test_configcontextschema.py +5 -3
- nautobot/extras/tests/integration/test_customfields.py +4 -2
- nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
- nautobot/extras/tests/integration/test_jobs.py +25 -27
- nautobot/extras/tests/integration/test_notes.py +8 -4
- nautobot/extras/tests/integration/test_relationships.py +2 -2
- nautobot/extras/tests/test_api.py +649 -642
- nautobot/extras/tests/test_changelog.py +3 -3
- nautobot/extras/tests/test_context_managers.py +5 -3
- nautobot/extras/tests/test_customfields.py +92 -50
- nautobot/extras/tests/test_datasources.py +189 -112
- nautobot/extras/tests/test_dynamicgroups.py +7 -8
- nautobot/extras/tests/test_filters.py +137 -89
- nautobot/extras/tests/test_forms.py +73 -75
- nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
- nautobot/extras/tests/test_jobs.py +262 -263
- nautobot/extras/tests/test_migrations.py +4 -3
- nautobot/extras/tests/test_models.py +116 -161
- nautobot/extras/tests/test_plugins.py +38 -60
- nautobot/extras/tests/test_relationships.py +167 -120
- nautobot/extras/tests/test_tags.py +6 -11
- nautobot/extras/tests/test_utils.py +31 -1
- nautobot/extras/tests/test_views.py +201 -145
- nautobot/extras/tests/test_webhooks.py +6 -2
- nautobot/extras/urls.py +42 -42
- nautobot/extras/utils.py +137 -163
- nautobot/extras/views.py +78 -152
- nautobot/ipam/api/fields.py +17 -0
- nautobot/ipam/api/serializers.py +58 -164
- nautobot/ipam/api/urls.py +1 -1
- nautobot/ipam/api/views.py +3 -2
- nautobot/ipam/apps.py +1 -2
- nautobot/ipam/filters.py +1 -10
- nautobot/ipam/forms.py +4 -177
- nautobot/ipam/lookups.py +1 -0
- nautobot/ipam/management/commands/__init__.py +0 -0
- nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
- nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -1
- nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -38
- nautobot/ipam/migrations/0020_related_name_changes.py +1 -1
- nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +2 -2
- nautobot/ipam/migrations/0028_tagsfield.py +44 -0
- nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
- nautobot/ipam/migrations/{0028_ipam__namespaces.py → 0030_ipam__namespaces.py} +77 -28
- nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
- nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
- nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
- nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
- nautobot/ipam/models.py +100 -236
- nautobot/ipam/navigation.py +36 -181
- nautobot/ipam/querysets.py +20 -25
- nautobot/ipam/signals.py +49 -6
- nautobot/ipam/tables.py +10 -3
- nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
- nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
- nautobot/ipam/templates/ipam/namespace_retrieve.html +17 -4
- nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
- nautobot/ipam/templates/ipam/prefix.html +1 -1
- nautobot/ipam/templates/ipam/vlangroup.html +0 -13
- nautobot/ipam/templates/ipam/vrf_edit.html +6 -0
- nautobot/ipam/tests/integration/test_prefixes.py +3 -26
- nautobot/ipam/tests/test_api.py +22 -19
- nautobot/ipam/tests/test_filters.py +59 -23
- nautobot/ipam/tests/test_migrations.py +6 -10
- nautobot/ipam/tests/test_models.py +323 -198
- nautobot/ipam/tests/test_ordering.py +2 -2
- nautobot/ipam/tests/test_querysets.py +44 -24
- nautobot/ipam/tests/test_views.py +73 -26
- nautobot/ipam/urls.py +16 -0
- nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
- nautobot/ipam/utils/migrations.py +713 -0
- nautobot/ipam/views.py +137 -20
- nautobot/project-static/docs/404.html +1178 -10
- nautobot/project-static/docs/additional-features/caching.html +1224 -159
- nautobot/project-static/docs/additional-features/change-logging.html +1180 -12
- nautobot/project-static/docs/additional-features/config-contexts.html +1180 -12
- nautobot/project-static/docs/additional-features/graphql.html +1179 -11
- nautobot/project-static/docs/additional-features/healthcheck.html +1180 -12
- nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1184 -12
- nautobot/project-static/docs/additional-features/jobs.html +1514 -328
- nautobot/project-static/docs/additional-features/napalm.html +1180 -12
- nautobot/project-static/docs/additional-features/prometheus-metrics.html +1180 -12
- nautobot/project-static/docs/additional-features/template-filters.html +1180 -12
- nautobot/project-static/docs/administration/celery-queues.html +1178 -10
- nautobot/project-static/docs/administration/nautobot-server.html +1451 -304
- nautobot/project-static/docs/administration/nautobot-shell.html +1178 -10
- nautobot/project-static/docs/administration/permissions.html +1178 -10
- nautobot/project-static/docs/administration/replicating-nautobot.html +1262 -113
- nautobot/project-static/docs/apps/index.html +1178 -10
- nautobot/project-static/docs/apps/nautobot-apps.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1580 -426
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3481 -1838
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1185 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1719 -551
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2062 -930
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +1946 -659
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1180 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1189 -21
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +9283 -6218
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2734 -2122
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1178 -10
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2337 -1300
- nautobot/project-static/docs/configuration/authentication/ldap.html +1178 -10
- nautobot/project-static/docs/configuration/authentication/remote.html +1178 -10
- nautobot/project-static/docs/configuration/authentication/sso.html +1178 -10
- nautobot/project-static/docs/configuration/index.html +1178 -10
- nautobot/project-static/docs/configuration/optional-settings.html +1311 -160
- nautobot/project-static/docs/configuration/required-settings.html +1312 -211
- nautobot/project-static/docs/core-functionality/circuits.html +1178 -10
- nautobot/project-static/docs/core-functionality/device-types.html +1178 -10
- nautobot/project-static/docs/core-functionality/devices.html +1182 -10
- nautobot/project-static/docs/core-functionality/ipam.html +1182 -10
- nautobot/project-static/docs/core-functionality/power.html +1178 -10
- nautobot/project-static/docs/core-functionality/secrets.html +1178 -10
- nautobot/project-static/docs/core-functionality/services.html +1178 -10
- nautobot/project-static/docs/core-functionality/sites-and-racks.html +1178 -10
- nautobot/project-static/docs/core-functionality/tenancy.html +1178 -10
- nautobot/project-static/docs/core-functionality/virtualization.html +1182 -10
- nautobot/project-static/docs/core-functionality/vlans.html +1179 -11
- nautobot/project-static/docs/development/application-registry.html +1190 -42
- nautobot/project-static/docs/development/best-practices.html +1178 -10
- nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1178 -10
- nautobot/project-static/docs/development/extending-models.html +1238 -83
- nautobot/project-static/docs/development/generic-views.html +1180 -14
- nautobot/project-static/docs/development/getting-started.html +1365 -90
- nautobot/project-static/docs/development/homepage.html +1178 -10
- nautobot/project-static/docs/development/index.html +1178 -10
- nautobot/project-static/docs/development/model-features.html +1178 -10
- nautobot/project-static/docs/development/natural-keys.html +1178 -10
- nautobot/project-static/docs/development/navigation-menu.html +1215 -125
- nautobot/project-static/docs/development/react-ui.html +4199 -0
- nautobot/project-static/docs/development/release-checklist.html +1178 -10
- nautobot/project-static/docs/development/role-internals.html +1179 -12
- nautobot/project-static/docs/development/style-guide.html +1188 -19
- nautobot/project-static/docs/development/templates.html +1178 -10
- nautobot/project-static/docs/development/testing.html +1178 -10
- nautobot/project-static/docs/development/user-preferences.html +1178 -10
- nautobot/project-static/docs/docker/index.html +1178 -10
- nautobot/project-static/docs/index.html +1183 -12
- nautobot/project-static/docs/installation/centos.html +1178 -10
- nautobot/project-static/docs/installation/external-authentication.html +1178 -10
- nautobot/project-static/docs/installation/http-server.html +1178 -10
- nautobot/project-static/docs/installation/index.html +1178 -10
- nautobot/project-static/docs/installation/migrating-from-netbox.html +1305 -189
- nautobot/project-static/docs/installation/migrating-from-postgresql.html +1178 -10
- nautobot/project-static/docs/installation/nautobot.html +1179 -11
- nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1178 -10
- nautobot/project-static/docs/installation/selinux-troubleshooting.html +1178 -10
- nautobot/project-static/docs/installation/services.html +1178 -10
- nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
- nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
- nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
- nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
- nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
- nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
- nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
- nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
- nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
- nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
- nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
- nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
- nautobot/project-static/docs/installation/ubuntu.html +1178 -10
- nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +3823 -2152
- nautobot/project-static/docs/installation/upgrading.html +1178 -10
- nautobot/project-static/docs/models/circuits/circuit.html +1293 -103
- nautobot/project-static/docs/models/circuits/circuittermination.html +1293 -103
- nautobot/project-static/docs/models/circuits/circuittype.html +1293 -103
- nautobot/project-static/docs/models/circuits/provider.html +1293 -103
- nautobot/project-static/docs/models/circuits/providernetwork.html +1293 -103
- nautobot/project-static/docs/models/dcim/cable.html +1324 -103
- nautobot/project-static/docs/models/dcim/consoleport.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleserverport.html +1293 -103
- nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/device.html +1326 -132
- nautobot/project-static/docs/models/dcim/devicebay.html +1293 -103
- nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1379 -97
- nautobot/project-static/docs/models/dcim/devicetype.html +1293 -103
- nautobot/project-static/docs/models/dcim/frontport.html +1293 -103
- nautobot/project-static/docs/models/dcim/frontporttemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/interface.html +1293 -103
- nautobot/project-static/docs/models/dcim/interfacetemplate.html +1293 -103
- nautobot/project-static/docs/models/dcim/inventoryitem.html +1293 -103
- nautobot/project-static/docs/models/dcim/location.html +1293 -103
- nautobot/project-static/docs/models/dcim/locationtype.html +1293 -103
- nautobot/project-static/docs/models/dcim/manufacturer.html +1292 -102
- nautobot/project-static/docs/models/dcim/platform.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerfeed.html +1270 -80
- nautobot/project-static/docs/models/dcim/poweroutlet.html +1272 -82
- nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerpanel.html +1270 -80
- nautobot/project-static/docs/models/dcim/powerport.html +1272 -82
- nautobot/project-static/docs/models/dcim/powerporttemplate.html +1272 -82
- nautobot/project-static/docs/models/dcim/rack.html +1272 -82
- nautobot/project-static/docs/models/dcim/rackgroup.html +1272 -82
- nautobot/project-static/docs/models/dcim/rackreservation.html +1272 -82
- nautobot/project-static/docs/models/dcim/rearport.html +1286 -96
- nautobot/project-static/docs/models/dcim/rearporttemplate.html +1286 -96
- nautobot/project-static/docs/models/dcim/region.html +1178 -10
- nautobot/project-static/docs/models/dcim/site.html +1178 -10
- nautobot/project-static/docs/models/dcim/virtualchassis.html +1284 -94
- nautobot/project-static/docs/models/extras/computedfield.html +1184 -16
- nautobot/project-static/docs/models/extras/configcontext.html +1314 -86
- nautobot/project-static/docs/models/extras/configcontextschema.html +1276 -86
- nautobot/project-static/docs/models/extras/customfield.html +1180 -12
- nautobot/project-static/docs/models/extras/customlink.html +1180 -12
- nautobot/project-static/docs/models/extras/dynamicgroup.html +1180 -12
- nautobot/project-static/docs/models/extras/exporttemplate.html +1180 -12
- nautobot/project-static/docs/models/extras/gitrepository.html +1184 -12
- nautobot/project-static/docs/models/extras/graphqlquery.html +1321 -86
- nautobot/project-static/docs/models/extras/imageattachment.html +1276 -86
- nautobot/project-static/docs/models/extras/job.html +1277 -86
- nautobot/project-static/docs/models/extras/jobbutton.html +1201 -29
- nautobot/project-static/docs/models/extras/jobhook.html +1188 -16
- nautobot/project-static/docs/models/extras/joblogentry.html +1274 -84
- nautobot/project-static/docs/models/extras/jobresult.html +1364 -169
- nautobot/project-static/docs/models/extras/note.html +1180 -12
- nautobot/project-static/docs/models/extras/relationship.html +1182 -14
- nautobot/project-static/docs/models/extras/role.html +1320 -86
- nautobot/project-static/docs/models/extras/secret.html +1314 -86
- nautobot/project-static/docs/models/extras/secretsgroup.html +1276 -86
- nautobot/project-static/docs/models/extras/status.html +1188 -59
- nautobot/project-static/docs/models/extras/tag.html +1180 -12
- nautobot/project-static/docs/models/extras/webhook.html +1180 -12
- nautobot/project-static/docs/models/ipam/ipaddress.html +1327 -102
- nautobot/project-static/docs/models/ipam/prefix.html +1276 -86
- nautobot/project-static/docs/models/ipam/rir.html +1276 -86
- nautobot/project-static/docs/models/ipam/routetarget.html +1276 -86
- nautobot/project-static/docs/models/ipam/service.html +1276 -86
- nautobot/project-static/docs/models/ipam/vlan.html +1276 -86
- nautobot/project-static/docs/models/ipam/vlangroup.html +1276 -86
- nautobot/project-static/docs/models/ipam/vrf.html +1276 -86
- nautobot/project-static/docs/models/tenancy/tenant.html +1276 -86
- nautobot/project-static/docs/models/tenancy/tenantgroup.html +1276 -86
- nautobot/project-static/docs/models/users/objectpermission.html +1314 -86
- nautobot/project-static/docs/models/users/token.html +1276 -86
- nautobot/project-static/docs/models/virtualization/cluster.html +1276 -86
- nautobot/project-static/docs/models/virtualization/clustergroup.html +1276 -86
- nautobot/project-static/docs/models/virtualization/clustertype.html +1276 -86
- nautobot/project-static/docs/models/virtualization/virtualmachine.html +1321 -127
- nautobot/project-static/docs/models/virtualization/vminterface.html +1276 -86
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/plugins/development.html +1726 -495
- nautobot/project-static/docs/plugins/index.html +1178 -10
- nautobot/project-static/docs/plugins/porting-from-netbox.html +1178 -10
- nautobot/project-static/docs/release-notes/index.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.0.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.1.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.2.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.3.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.4.html +1178 -10
- nautobot/project-static/docs/release-notes/version-1.5.html +1608 -225
- nautobot/project-static/docs/release-notes/version-2.0.html +1547 -47
- nautobot/project-static/docs/requirements.txt +1 -0
- nautobot/project-static/docs/rest-api/authentication.html +1179 -11
- nautobot/project-static/docs/rest-api/filtering.html +1178 -10
- nautobot/project-static/docs/rest-api/overview.html +1841 -446
- nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +197 -187
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guides/custom-fields.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/index.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/ipam.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/platforms.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/regions.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/tenants.html +1178 -10
- nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1178 -10
- nautobot/project-static/docs/user-guides/git-data-source.html +1178 -10
- nautobot/project-static/docs/user-guides/graphql.html +1178 -10
- nautobot/project-static/docs/user-guides/relationships.html +1178 -10
- nautobot/project-static/docs/user-guides/s3-django-storage.html +1178 -10
- nautobot/project-static/js/forms.js +16 -9
- nautobot/project-static/js/theme.js +5 -0
- nautobot/tenancy/api/serializers.py +4 -32
- nautobot/tenancy/api/urls.py +1 -1
- nautobot/tenancy/forms.py +0 -28
- nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
- nautobot/tenancy/models.py +0 -25
- nautobot/tenancy/navigation.py +6 -39
- nautobot/tenancy/templates/tenancy/tenant.html +12 -12
- nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
- nautobot/tenancy/tests/test_api.py +1 -3
- nautobot/tenancy/tests/test_filters.py +10 -5
- nautobot/tenancy/views.py +0 -2
- nautobot/ui/.eslintignore +6 -0
- nautobot/ui/.gitignore +10 -0
- nautobot/ui/.prettierignore +9 -0
- nautobot/ui/.prettierrc +4 -0
- nautobot/ui/README.md +33 -0
- nautobot/ui/app_imports.js.j2 +7 -0
- nautobot/ui/craco.config.js +46 -0
- nautobot/ui/jsconfig-base.json +11 -0
- nautobot/ui/jsconfig.json +5 -0
- nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
- nautobot/ui/package-lock.json +21451 -0
- nautobot/ui/package.json +70 -0
- nautobot/ui/public/index.html +47 -0
- nautobot/ui/public/logo192.png +0 -0
- nautobot/ui/public/logo512.png +0 -0
- nautobot/ui/public/manifest.json +25 -0
- nautobot/ui/public/nautobot_logo.svg +131 -0
- nautobot/ui/public/robots.txt +3 -0
- nautobot/ui/src/App.js +71 -0
- nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
- nautobot/ui/src/components/AppTab.js +40 -0
- nautobot/ui/src/components/Apps.js +60 -0
- nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
- nautobot/ui/src/components/HomePanel.js +58 -0
- nautobot/ui/src/components/JobHistoryTable.js +78 -0
- nautobot/ui/src/components/Layout.js +53 -0
- nautobot/ui/src/components/LoadingWidget.js +25 -0
- nautobot/ui/src/components/Navbar.js +116 -0
- nautobot/ui/src/components/NotificationPopover.js +27 -0
- nautobot/ui/src/components/ObjectListTable.js +209 -0
- nautobot/ui/src/components/ReferenceDataTag.js +35 -0
- nautobot/ui/src/components/RouterButton.js +10 -0
- nautobot/ui/src/components/RouterLink.js +10 -0
- nautobot/ui/src/components/SidebarNav.js +147 -0
- nautobot/ui/src/components/Table.js +48 -0
- nautobot/ui/src/components/TableItem.js +71 -0
- nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
- nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
- nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
- nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
- nautobot/ui/src/components/__tests__/Table.test.js +36 -0
- nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
- nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
- nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
- nautobot/ui/src/components/pagination.js +93 -0
- nautobot/ui/src/components/paginator.js +79 -0
- nautobot/ui/src/components/paginator_form.js +43 -0
- nautobot/ui/src/components/usePagination.js +57 -0
- nautobot/ui/src/constants/apiPath.js +10 -0
- nautobot/ui/src/constants/icons.js +15 -0
- nautobot/ui/src/constants/size.js +15 -0
- nautobot/ui/src/index.js +65 -0
- nautobot/ui/src/reportWebVitals.js +15 -0
- nautobot/ui/src/router.js +77 -0
- nautobot/ui/src/utils/api.js +131 -0
- nautobot/ui/src/utils/app-import.js +15 -0
- nautobot/ui/src/utils/color.js +15 -0
- nautobot/ui/src/utils/date.js +14 -0
- nautobot/ui/src/utils/index.js +15 -0
- nautobot/ui/src/utils/navigation.js +32 -0
- nautobot/ui/src/utils/session.js +64 -0
- nautobot/ui/src/utils/store.js +242 -0
- nautobot/ui/src/utils/string.js +6 -0
- nautobot/ui/src/utils/url.js +4 -0
- nautobot/ui/src/views/Home.js +138 -0
- nautobot/ui/src/views/InstalledApps.js +80 -0
- nautobot/ui/src/views/Login.js +48 -0
- nautobot/ui/src/views/Logout.js +20 -0
- nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
- nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
- nautobot/ui/src/views/__tests__/Login.test.js +15 -0
- nautobot/ui/src/views/generic/GenericView.js +142 -0
- nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
- nautobot/ui/src/views/generic/ObjectList.js +127 -0
- nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
- nautobot/users/admin.py +1 -1
- nautobot/users/api/serializers.py +51 -61
- nautobot/users/api/urls.py +1 -1
- nautobot/users/api/views.py +53 -2
- nautobot/users/tests/test_api.py +110 -25
- nautobot/virtualization/api/serializers.py +18 -130
- nautobot/virtualization/api/urls.py +1 -1
- nautobot/virtualization/api/views.py +1 -22
- nautobot/virtualization/forms.py +13 -99
- nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -1
- nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -11
- nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -1
- nautobot/virtualization/migrations/0018_related_name_changes.py +1 -1
- nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
- nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
- nautobot/virtualization/migrations/{0021_ipam__namespaces.py → 0023_ipam__namespaces.py} +2 -2
- nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
- nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
- nautobot/virtualization/models.py +31 -123
- nautobot/virtualization/navigation.py +18 -99
- nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -1
- nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
- nautobot/virtualization/tests/test_api.py +25 -26
- nautobot/virtualization/tests/test_filters.py +41 -15
- nautobot/virtualization/tests/test_models.py +31 -7
- nautobot/virtualization/tests/test_views.py +42 -25
- nautobot/virtualization/views.py +7 -6
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +3 -7
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +744 -602
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
- nautobot/circuits/api/nested_serializers.py +0 -69
- nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
- nautobot/dcim/api/nested_serializers.py +0 -356
- nautobot/dcim/templates/dcim/device_import.html +0 -5
- nautobot/dcim/templates/dcim/device_import_child.html +0 -5
- nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
- nautobot/extras/api/nested_serializers.py +0 -353
- nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -41
- nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -46
- nautobot/extras/reports.py +0 -60
- nautobot/extras/scripts.py +0 -72
- nautobot/extras/tests/example_jobs/script_variables.py +0 -67
- nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
- nautobot/extras/tests/example_jobs/test_fail.py +0 -16
- nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
- nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
- nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
- nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
- nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
- nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
- nautobot/extras/tests/example_jobs/test_modify_db.py +0 -18
- nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
- nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
- nautobot/extras/tests/example_jobs/test_pass.py +0 -19
- nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
- nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
- nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
- nautobot/ipam/api/nested_serializers.py +0 -159
- nautobot/ipam/migrations/0029_ipam__prefix__add_parent.py +0 -31
- nautobot/ipam/migrations/0030_ipam__prefix__data_migration.py +0 -13
- nautobot/ipam/migrations/0031_ipam__ipaddress__add_parent.py +0 -41
- nautobot/ipam/migrations/0032_ipam__ipaddress__data_migration.py +0 -11
- nautobot/tenancy/api/nested_serializers.py +0 -31
- nautobot/users/api/nested_serializers.py +0 -67
- nautobot/virtualization/api/nested_serializers.py +0 -65
- /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
- /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
nautobot/dcim/api/serializers.py
CHANGED
|
@@ -6,19 +6,24 @@ from rest_framework.validators import UniqueTogetherValidator
|
|
|
6
6
|
from nautobot.core.api import (
|
|
7
7
|
ChoiceField,
|
|
8
8
|
ContentTypeField,
|
|
9
|
-
|
|
9
|
+
NautobotModelSerializer,
|
|
10
10
|
TimeZoneSerializerField,
|
|
11
11
|
TreeModelSerializerMixin,
|
|
12
12
|
ValidatedModelSerializer,
|
|
13
|
-
WritableNestedSerializer,
|
|
14
13
|
)
|
|
15
14
|
from nautobot.core.api.serializers import PolymorphicProxySerializer
|
|
16
|
-
from nautobot.core.api.utils import
|
|
15
|
+
from nautobot.core.api.utils import (
|
|
16
|
+
get_nested_serializer_depth,
|
|
17
|
+
get_serializer_for_model,
|
|
18
|
+
get_serializers_for_models,
|
|
19
|
+
return_nested_serializer_data_based_on_depth,
|
|
20
|
+
)
|
|
17
21
|
from nautobot.core.models.utils import get_all_concrete_models
|
|
18
22
|
from nautobot.core.utils.config import get_settings_or_config
|
|
19
23
|
from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
|
|
20
24
|
from nautobot.dcim.choices import (
|
|
21
25
|
CableLengthUnitChoices,
|
|
26
|
+
CableTypeChoices,
|
|
22
27
|
ConsolePortTypeChoices,
|
|
23
28
|
DeviceFaceChoices,
|
|
24
29
|
DeviceRedundancyGroupFailoverStrategyChoices,
|
|
@@ -74,59 +79,10 @@ from nautobot.dcim.models import (
|
|
|
74
79
|
RearPortTemplate,
|
|
75
80
|
VirtualChassis,
|
|
76
81
|
)
|
|
77
|
-
from nautobot.extras.api.
|
|
78
|
-
NautobotModelSerializer,
|
|
79
|
-
RoleRequiredRoleModelSerializerMixin,
|
|
80
|
-
RoleModelSerializerMixin,
|
|
81
|
-
StatusModelSerializerMixin,
|
|
82
|
+
from nautobot.extras.api.mixins import (
|
|
82
83
|
TaggedModelSerializerMixin,
|
|
83
84
|
)
|
|
84
|
-
from nautobot.extras.api.nested_serializers import NestedConfigContextSchemaSerializer, NestedSecretsGroupSerializer
|
|
85
85
|
from nautobot.extras.utils import FeatureQuery
|
|
86
|
-
from nautobot.ipam.api.nested_serializers import (
|
|
87
|
-
NestedIPAddressSerializer,
|
|
88
|
-
NestedVLANSerializer,
|
|
89
|
-
)
|
|
90
|
-
from nautobot.ipam.models import IPAddress, VLAN
|
|
91
|
-
from nautobot.tenancy.api.nested_serializers import NestedTenantSerializer
|
|
92
|
-
from nautobot.users.api.nested_serializers import NestedUserSerializer
|
|
93
|
-
from nautobot.virtualization.api.nested_serializers import NestedClusterSerializer
|
|
94
|
-
|
|
95
|
-
# Not all of these variable(s) are not actually used anywhere in this file, but required for the
|
|
96
|
-
# automagically replacing a Serializer with its corresponding NestedSerializer.
|
|
97
|
-
from .nested_serializers import ( # noqa: F401
|
|
98
|
-
NestedCableSerializer,
|
|
99
|
-
NestedConsolePortSerializer,
|
|
100
|
-
NestedConsolePortTemplateSerializer,
|
|
101
|
-
NestedConsoleServerPortSerializer,
|
|
102
|
-
NestedConsoleServerPortTemplateSerializer,
|
|
103
|
-
NestedDeviceBaySerializer,
|
|
104
|
-
NestedDeviceBayTemplateSerializer,
|
|
105
|
-
NestedDeviceRedundancyGroupSerializer,
|
|
106
|
-
NestedDeviceSerializer,
|
|
107
|
-
NestedDeviceTypeSerializer,
|
|
108
|
-
NestedFrontPortSerializer,
|
|
109
|
-
NestedFrontPortTemplateSerializer,
|
|
110
|
-
NestedInterfaceSerializer,
|
|
111
|
-
NestedInterfaceTemplateSerializer,
|
|
112
|
-
NestedInventoryItemSerializer,
|
|
113
|
-
NestedLocationSerializer,
|
|
114
|
-
NestedLocationTypeSerializer,
|
|
115
|
-
NestedManufacturerSerializer,
|
|
116
|
-
NestedPlatformSerializer,
|
|
117
|
-
NestedPowerFeedSerializer,
|
|
118
|
-
NestedPowerOutletSerializer,
|
|
119
|
-
NestedPowerOutletTemplateSerializer,
|
|
120
|
-
NestedPowerPanelSerializer,
|
|
121
|
-
NestedPowerPortSerializer,
|
|
122
|
-
NestedPowerPortTemplateSerializer,
|
|
123
|
-
NestedRackGroupSerializer,
|
|
124
|
-
NestedRackReservationSerializer,
|
|
125
|
-
NestedRackSerializer,
|
|
126
|
-
NestedRearPortSerializer,
|
|
127
|
-
NestedRearPortTemplateSerializer,
|
|
128
|
-
NestedVirtualChassisSerializer,
|
|
129
|
-
)
|
|
130
86
|
|
|
131
87
|
|
|
132
88
|
class CableTerminationModelSerializerMixin(serializers.ModelSerializer):
|
|
@@ -143,7 +99,7 @@ class CableTerminationModelSerializerMixin(serializers.ModelSerializer):
|
|
|
143
99
|
PolymorphicProxySerializer(
|
|
144
100
|
component_name="CableTermination",
|
|
145
101
|
resource_type_field_name="object_type",
|
|
146
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)
|
|
102
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)),
|
|
147
103
|
allow_null=True,
|
|
148
104
|
)
|
|
149
105
|
)
|
|
@@ -152,9 +108,8 @@ class CableTerminationModelSerializerMixin(serializers.ModelSerializer):
|
|
|
152
108
|
Return the appropriate serializer for the cable termination model.
|
|
153
109
|
"""
|
|
154
110
|
if obj._cable_peer is not None:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return serializer(obj._cable_peer, context=context).data
|
|
111
|
+
depth = get_nested_serializer_depth(self)
|
|
112
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj._cable_peer, "_cable_peer")
|
|
158
113
|
return None
|
|
159
114
|
|
|
160
115
|
|
|
@@ -179,7 +134,7 @@ class PathEndpointModelSerializerMixin(ValidatedModelSerializer):
|
|
|
179
134
|
PolymorphicProxySerializer(
|
|
180
135
|
component_name="PathEndpoint",
|
|
181
136
|
resource_type_field_name="object_type",
|
|
182
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)
|
|
137
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)),
|
|
183
138
|
allow_null=True,
|
|
184
139
|
)
|
|
185
140
|
)
|
|
@@ -188,9 +143,10 @@ class PathEndpointModelSerializerMixin(ValidatedModelSerializer):
|
|
|
188
143
|
Return the appropriate serializer for the type of connected object.
|
|
189
144
|
"""
|
|
190
145
|
if obj._path is not None and obj._path.destination is not None:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
146
|
+
depth = get_nested_serializer_depth(self)
|
|
147
|
+
return return_nested_serializer_data_based_on_depth(
|
|
148
|
+
self, depth, obj, obj._path.destination, "connected_endpoint"
|
|
149
|
+
)
|
|
194
150
|
return None
|
|
195
151
|
|
|
196
152
|
@extend_schema_field(serializers.BooleanField(allow_null=True))
|
|
@@ -212,8 +168,6 @@ class ConnectedEndpointSerializer(PathEndpointModelSerializerMixin):
|
|
|
212
168
|
|
|
213
169
|
|
|
214
170
|
class LocationTypeSerializer(NautobotModelSerializer, TreeModelSerializerMixin):
|
|
215
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:locationtype-detail")
|
|
216
|
-
parent = NestedLocationTypeSerializer(required=False, allow_null=True, default=None)
|
|
217
171
|
content_types = ContentTypeField(
|
|
218
172
|
queryset=ContentType.objects.filter(FeatureQuery("locations").get_query()),
|
|
219
173
|
required=False,
|
|
@@ -222,25 +176,15 @@ class LocationTypeSerializer(NautobotModelSerializer, TreeModelSerializerMixin):
|
|
|
222
176
|
|
|
223
177
|
class Meta:
|
|
224
178
|
model = LocationType
|
|
225
|
-
fields =
|
|
226
|
-
|
|
227
|
-
"name",
|
|
228
|
-
"slug",
|
|
229
|
-
"parent",
|
|
230
|
-
"nestable",
|
|
231
|
-
"content_types",
|
|
232
|
-
"description",
|
|
233
|
-
"tree_depth",
|
|
234
|
-
]
|
|
179
|
+
fields = "__all__"
|
|
180
|
+
list_display_fields = ["name", "nestable", "content_types", "description"]
|
|
235
181
|
|
|
236
182
|
|
|
237
183
|
class LocationSerializer(
|
|
238
|
-
NautobotModelSerializer,
|
|
184
|
+
NautobotModelSerializer,
|
|
185
|
+
TaggedModelSerializerMixin,
|
|
186
|
+
TreeModelSerializerMixin,
|
|
239
187
|
):
|
|
240
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:location-detail")
|
|
241
|
-
location_type = NestedLocationTypeSerializer()
|
|
242
|
-
parent = NestedLocationSerializer(required=False, allow_null=True)
|
|
243
|
-
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
|
244
188
|
time_zone = TimeZoneSerializerField(required=False, allow_null=True)
|
|
245
189
|
circuit_count = serializers.IntegerField(read_only=True)
|
|
246
190
|
device_count = serializers.IntegerField(read_only=True)
|
|
@@ -251,35 +195,8 @@ class LocationSerializer(
|
|
|
251
195
|
|
|
252
196
|
class Meta:
|
|
253
197
|
model = Location
|
|
254
|
-
fields =
|
|
255
|
-
|
|
256
|
-
"name",
|
|
257
|
-
"slug",
|
|
258
|
-
"status",
|
|
259
|
-
"location_type",
|
|
260
|
-
"parent",
|
|
261
|
-
"tenant",
|
|
262
|
-
"description",
|
|
263
|
-
"tree_depth",
|
|
264
|
-
"facility",
|
|
265
|
-
"asn",
|
|
266
|
-
"time_zone",
|
|
267
|
-
"description",
|
|
268
|
-
"physical_address",
|
|
269
|
-
"shipping_address",
|
|
270
|
-
"latitude",
|
|
271
|
-
"longitude",
|
|
272
|
-
"contact_name",
|
|
273
|
-
"contact_phone",
|
|
274
|
-
"contact_email",
|
|
275
|
-
"comments",
|
|
276
|
-
"circuit_count",
|
|
277
|
-
"device_count",
|
|
278
|
-
"prefix_count",
|
|
279
|
-
"rack_count",
|
|
280
|
-
"virtual_machine_count",
|
|
281
|
-
"vlan_count",
|
|
282
|
-
]
|
|
198
|
+
fields = "__all__"
|
|
199
|
+
list_display_fields = ["name", "status", "parent", "tenant", "description", "tags"]
|
|
283
200
|
# https://www.django-rest-framework.org/api-guide/validators/#optional-fields
|
|
284
201
|
validators = []
|
|
285
202
|
|
|
@@ -300,23 +217,12 @@ class LocationSerializer(
|
|
|
300
217
|
|
|
301
218
|
|
|
302
219
|
class RackGroupSerializer(NautobotModelSerializer, TreeModelSerializerMixin):
|
|
303
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rackgroup-detail")
|
|
304
|
-
location = NestedLocationSerializer()
|
|
305
|
-
parent = NestedRackGroupSerializer(required=False, allow_null=True)
|
|
306
220
|
rack_count = serializers.IntegerField(read_only=True)
|
|
307
221
|
|
|
308
222
|
class Meta:
|
|
309
223
|
model = RackGroup
|
|
310
|
-
fields =
|
|
311
|
-
|
|
312
|
-
"name",
|
|
313
|
-
"slug",
|
|
314
|
-
"location",
|
|
315
|
-
"parent",
|
|
316
|
-
"description",
|
|
317
|
-
"rack_count",
|
|
318
|
-
"tree_depth",
|
|
319
|
-
]
|
|
224
|
+
fields = "__all__"
|
|
225
|
+
list_display_fields = ["name", "location", "rack_count", "description"]
|
|
320
226
|
# Omit the UniqueTogetherValidator that would be automatically added to validate (location, slug). This
|
|
321
227
|
# prevents slug from being interpreted as a required field.
|
|
322
228
|
# 2.0 TODO: Remove if/when slug is globally unique. This would be a breaking change.
|
|
@@ -336,42 +242,19 @@ class RackGroupSerializer(NautobotModelSerializer, TreeModelSerializerMixin):
|
|
|
336
242
|
|
|
337
243
|
|
|
338
244
|
class RackSerializer(
|
|
339
|
-
NautobotModelSerializer,
|
|
245
|
+
NautobotModelSerializer,
|
|
246
|
+
TaggedModelSerializerMixin,
|
|
340
247
|
):
|
|
341
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rack-detail")
|
|
342
|
-
location = NestedLocationSerializer()
|
|
343
|
-
rack_group = NestedRackGroupSerializer(required=False, allow_null=True, default=None)
|
|
344
|
-
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
|
345
248
|
type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
|
|
346
|
-
width = ChoiceField(choices=RackWidthChoices, required=False)
|
|
249
|
+
width = ChoiceField(choices=RackWidthChoices, required=False, help_text="Rail-to-rail width (in inches)")
|
|
347
250
|
outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
|
|
348
251
|
device_count = serializers.IntegerField(read_only=True)
|
|
349
252
|
power_feed_count = serializers.IntegerField(read_only=True)
|
|
350
253
|
|
|
351
254
|
class Meta:
|
|
352
255
|
model = Rack
|
|
353
|
-
fields =
|
|
354
|
-
|
|
355
|
-
"name",
|
|
356
|
-
"facility_id",
|
|
357
|
-
"location",
|
|
358
|
-
"rack_group",
|
|
359
|
-
"tenant",
|
|
360
|
-
"status",
|
|
361
|
-
"role",
|
|
362
|
-
"serial",
|
|
363
|
-
"asset_tag",
|
|
364
|
-
"type",
|
|
365
|
-
"width",
|
|
366
|
-
"u_height",
|
|
367
|
-
"desc_units",
|
|
368
|
-
"outer_width",
|
|
369
|
-
"outer_depth",
|
|
370
|
-
"outer_unit",
|
|
371
|
-
"comments",
|
|
372
|
-
"device_count",
|
|
373
|
-
"power_feed_count",
|
|
374
|
-
]
|
|
256
|
+
fields = "__all__"
|
|
257
|
+
list_display_fields = ["name", "location", "rack_group", "status", "facility_id", "tenant", "role", "u_height"]
|
|
375
258
|
# Omit the UniqueTogetherValidator that would be automatically added to validate (rack_group, facility_id).
|
|
376
259
|
# This prevents facility_id from being interpreted as a required field.
|
|
377
260
|
validators = [UniqueTogetherValidator(queryset=Rack.objects.all(), fields=("rack_group", "name"))]
|
|
@@ -396,26 +279,27 @@ class RackUnitSerializer(serializers.Serializer):
|
|
|
396
279
|
id = serializers.IntegerField(read_only=True)
|
|
397
280
|
name = serializers.CharField(read_only=True)
|
|
398
281
|
face = ChoiceField(choices=DeviceFaceChoices, read_only=True)
|
|
399
|
-
device = NestedDeviceSerializer(read_only=True)
|
|
400
282
|
occupied = serializers.BooleanField(read_only=True)
|
|
401
283
|
|
|
402
284
|
|
|
403
285
|
class RackReservationSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
404
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rackreservation-detail")
|
|
405
|
-
rack = NestedRackSerializer()
|
|
406
|
-
user = NestedUserSerializer()
|
|
407
|
-
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
|
408
|
-
|
|
409
286
|
class Meta:
|
|
410
287
|
model = RackReservation
|
|
411
|
-
fields =
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
"units",
|
|
415
|
-
"user"
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
288
|
+
fields = "__all__"
|
|
289
|
+
list_display_fields = ["pk", "rack", "units", "user", "description"]
|
|
290
|
+
extra_kwargs = {
|
|
291
|
+
"units": {"help_text": "List of rack unit numbers to reserve"},
|
|
292
|
+
"user": {
|
|
293
|
+
"help_text": "User to associate to reservations. If unspecified, the current user will be used.",
|
|
294
|
+
"required": False,
|
|
295
|
+
},
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
def to_internal_value(self, data):
|
|
299
|
+
"""Add the requesting user as the owner of the RackReservation if not otherwise specified."""
|
|
300
|
+
if "user" not in data and not self.partial:
|
|
301
|
+
data["user"] = self.context["request"].user.id
|
|
302
|
+
return super().to_internal_value(data)
|
|
419
303
|
|
|
420
304
|
|
|
421
305
|
class RackElevationDetailFilterSerializer(serializers.Serializer):
|
|
@@ -445,45 +329,26 @@ class RackElevationDetailFilterSerializer(serializers.Serializer):
|
|
|
445
329
|
|
|
446
330
|
|
|
447
331
|
class ManufacturerSerializer(NautobotModelSerializer):
|
|
448
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:manufacturer-detail")
|
|
449
332
|
device_type_count = serializers.IntegerField(read_only=True)
|
|
450
333
|
inventory_item_count = serializers.IntegerField(read_only=True)
|
|
451
334
|
platform_count = serializers.IntegerField(read_only=True)
|
|
452
335
|
|
|
453
336
|
class Meta:
|
|
454
337
|
model = Manufacturer
|
|
455
|
-
fields =
|
|
456
|
-
|
|
457
|
-
"name",
|
|
458
|
-
"description",
|
|
459
|
-
"device_type_count",
|
|
460
|
-
"inventory_item_count",
|
|
461
|
-
"platform_count",
|
|
462
|
-
]
|
|
338
|
+
fields = "__all__"
|
|
339
|
+
list_display_fields = ["name", "device_type_count", "platform_count", "description"]
|
|
463
340
|
|
|
464
341
|
|
|
465
342
|
class DeviceTypeSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
466
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:devicetype-detail")
|
|
467
|
-
manufacturer = NestedManufacturerSerializer()
|
|
468
343
|
subdevice_role = ChoiceField(choices=SubdeviceRoleChoices, allow_blank=True, required=False)
|
|
344
|
+
front_image = serializers.ImageField(allow_null=True, required=False)
|
|
345
|
+
rear_image = serializers.ImageField(allow_null=True, required=False)
|
|
469
346
|
device_count = serializers.IntegerField(read_only=True)
|
|
470
347
|
|
|
471
348
|
class Meta:
|
|
472
349
|
model = DeviceType
|
|
473
|
-
fields =
|
|
474
|
-
|
|
475
|
-
"manufacturer",
|
|
476
|
-
"model",
|
|
477
|
-
"slug",
|
|
478
|
-
"part_number",
|
|
479
|
-
"u_height",
|
|
480
|
-
"is_full_depth",
|
|
481
|
-
"subdevice_role",
|
|
482
|
-
"front_image",
|
|
483
|
-
"rear_image",
|
|
484
|
-
"comments",
|
|
485
|
-
"device_count",
|
|
486
|
-
]
|
|
350
|
+
fields = "__all__"
|
|
351
|
+
list_display_fields = ["model", "manufacturer", "part_number", "u_height", "is_full_depth", "device_count"]
|
|
487
352
|
# Omit the UniqueTogetherValidator that would be automatically added to validate (manufacturer, slug). This
|
|
488
353
|
# prevents slug from being interpreted as a required field.
|
|
489
354
|
# 2.0 TODO: Remove if/when slug is globally unique. This would be a breaking change.
|
|
@@ -503,148 +368,66 @@ class DeviceTypeSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
|
503
368
|
|
|
504
369
|
|
|
505
370
|
class ConsolePortTemplateSerializer(NautobotModelSerializer):
|
|
506
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:consoleporttemplate-detail")
|
|
507
|
-
device_type = NestedDeviceTypeSerializer()
|
|
508
371
|
type = ChoiceField(choices=ConsolePortTypeChoices, allow_blank=True, required=False)
|
|
509
372
|
|
|
510
373
|
class Meta:
|
|
511
374
|
model = ConsolePortTemplate
|
|
512
|
-
fields =
|
|
513
|
-
"url",
|
|
514
|
-
"device_type",
|
|
515
|
-
"name",
|
|
516
|
-
"label",
|
|
517
|
-
"type",
|
|
518
|
-
"description",
|
|
519
|
-
]
|
|
375
|
+
fields = "__all__"
|
|
520
376
|
|
|
521
377
|
|
|
522
378
|
class ConsoleServerPortTemplateSerializer(NautobotModelSerializer):
|
|
523
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:consoleserverporttemplate-detail")
|
|
524
|
-
device_type = NestedDeviceTypeSerializer()
|
|
525
379
|
type = ChoiceField(choices=ConsolePortTypeChoices, allow_blank=True, required=False)
|
|
526
380
|
|
|
527
381
|
class Meta:
|
|
528
382
|
model = ConsoleServerPortTemplate
|
|
529
|
-
fields =
|
|
530
|
-
"url",
|
|
531
|
-
"device_type",
|
|
532
|
-
"name",
|
|
533
|
-
"label",
|
|
534
|
-
"type",
|
|
535
|
-
"description",
|
|
536
|
-
]
|
|
383
|
+
fields = "__all__"
|
|
537
384
|
|
|
538
385
|
|
|
539
386
|
class PowerPortTemplateSerializer(NautobotModelSerializer):
|
|
540
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:powerporttemplate-detail")
|
|
541
|
-
device_type = NestedDeviceTypeSerializer()
|
|
542
387
|
type = ChoiceField(choices=PowerPortTypeChoices, allow_blank=True, required=False)
|
|
543
388
|
|
|
544
389
|
class Meta:
|
|
545
390
|
model = PowerPortTemplate
|
|
546
|
-
fields =
|
|
547
|
-
"url",
|
|
548
|
-
"device_type",
|
|
549
|
-
"name",
|
|
550
|
-
"label",
|
|
551
|
-
"type",
|
|
552
|
-
"maximum_draw",
|
|
553
|
-
"allocated_draw",
|
|
554
|
-
"description",
|
|
555
|
-
]
|
|
391
|
+
fields = "__all__"
|
|
556
392
|
|
|
557
393
|
|
|
558
394
|
class PowerOutletTemplateSerializer(NautobotModelSerializer):
|
|
559
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:poweroutlettemplate-detail")
|
|
560
|
-
device_type = NestedDeviceTypeSerializer()
|
|
561
395
|
type = ChoiceField(choices=PowerOutletTypeChoices, allow_blank=True, required=False)
|
|
562
|
-
power_port_template = NestedPowerPortTemplateSerializer(required=False)
|
|
563
396
|
feed_leg = ChoiceField(choices=PowerOutletFeedLegChoices, allow_blank=True, required=False)
|
|
564
397
|
|
|
565
398
|
class Meta:
|
|
566
399
|
model = PowerOutletTemplate
|
|
567
|
-
fields =
|
|
568
|
-
"url",
|
|
569
|
-
"device_type",
|
|
570
|
-
"name",
|
|
571
|
-
"label",
|
|
572
|
-
"type",
|
|
573
|
-
"power_port_template",
|
|
574
|
-
"feed_leg",
|
|
575
|
-
"description",
|
|
576
|
-
]
|
|
400
|
+
fields = "__all__"
|
|
577
401
|
|
|
578
402
|
|
|
579
403
|
class InterfaceTemplateSerializer(NautobotModelSerializer):
|
|
580
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:interfacetemplate-detail")
|
|
581
|
-
device_type = NestedDeviceTypeSerializer()
|
|
582
404
|
type = ChoiceField(choices=InterfaceTypeChoices)
|
|
583
405
|
|
|
584
406
|
class Meta:
|
|
585
407
|
model = InterfaceTemplate
|
|
586
|
-
fields =
|
|
587
|
-
"url",
|
|
588
|
-
"device_type",
|
|
589
|
-
"name",
|
|
590
|
-
"label",
|
|
591
|
-
"type",
|
|
592
|
-
"mgmt_only",
|
|
593
|
-
"description",
|
|
594
|
-
]
|
|
408
|
+
fields = "__all__"
|
|
595
409
|
|
|
596
410
|
|
|
597
411
|
class RearPortTemplateSerializer(NautobotModelSerializer):
|
|
598
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rearporttemplate-detail")
|
|
599
|
-
device_type = NestedDeviceTypeSerializer()
|
|
600
412
|
type = ChoiceField(choices=PortTypeChoices)
|
|
601
413
|
|
|
602
414
|
class Meta:
|
|
603
415
|
model = RearPortTemplate
|
|
604
|
-
fields =
|
|
605
|
-
"url",
|
|
606
|
-
"device_type",
|
|
607
|
-
"name",
|
|
608
|
-
"label",
|
|
609
|
-
"type",
|
|
610
|
-
"positions",
|
|
611
|
-
"description",
|
|
612
|
-
]
|
|
416
|
+
fields = "__all__"
|
|
613
417
|
|
|
614
418
|
|
|
615
419
|
class FrontPortTemplateSerializer(NautobotModelSerializer):
|
|
616
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:frontporttemplate-detail")
|
|
617
|
-
device_type = NestedDeviceTypeSerializer()
|
|
618
420
|
type = ChoiceField(choices=PortTypeChoices)
|
|
619
|
-
rear_port_template = NestedRearPortTemplateSerializer()
|
|
620
421
|
|
|
621
422
|
class Meta:
|
|
622
423
|
model = FrontPortTemplate
|
|
623
|
-
fields =
|
|
624
|
-
"url",
|
|
625
|
-
"device_type",
|
|
626
|
-
"name",
|
|
627
|
-
"label",
|
|
628
|
-
"type",
|
|
629
|
-
"rear_port_template",
|
|
630
|
-
"rear_port_position",
|
|
631
|
-
"description",
|
|
632
|
-
]
|
|
424
|
+
fields = "__all__"
|
|
633
425
|
|
|
634
426
|
|
|
635
427
|
class DeviceBayTemplateSerializer(NautobotModelSerializer):
|
|
636
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:devicebaytemplate-detail")
|
|
637
|
-
device_type = NestedDeviceTypeSerializer()
|
|
638
|
-
|
|
639
428
|
class Meta:
|
|
640
429
|
model = DeviceBayTemplate
|
|
641
|
-
fields =
|
|
642
|
-
"url",
|
|
643
|
-
"device_type",
|
|
644
|
-
"name",
|
|
645
|
-
"label",
|
|
646
|
-
"description",
|
|
647
|
-
]
|
|
430
|
+
fields = "__all__"
|
|
648
431
|
|
|
649
432
|
|
|
650
433
|
#
|
|
@@ -653,80 +436,58 @@ class DeviceBayTemplateSerializer(NautobotModelSerializer):
|
|
|
653
436
|
|
|
654
437
|
|
|
655
438
|
class PlatformSerializer(NautobotModelSerializer):
|
|
656
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:platform-detail")
|
|
657
|
-
manufacturer = NestedManufacturerSerializer(required=False, allow_null=True)
|
|
658
439
|
device_count = serializers.IntegerField(read_only=True)
|
|
659
440
|
virtual_machine_count = serializers.IntegerField(read_only=True)
|
|
660
441
|
|
|
661
442
|
class Meta:
|
|
662
443
|
model = Platform
|
|
663
|
-
fields =
|
|
664
|
-
|
|
444
|
+
fields = "__all__"
|
|
445
|
+
list_display_fields = [
|
|
665
446
|
"name",
|
|
666
447
|
"manufacturer",
|
|
667
|
-
"napalm_driver",
|
|
668
|
-
"napalm_args",
|
|
669
|
-
"description",
|
|
670
448
|
"device_count",
|
|
671
449
|
"virtual_machine_count",
|
|
450
|
+
"napalm_driver",
|
|
451
|
+
"description",
|
|
672
452
|
]
|
|
673
453
|
|
|
674
454
|
|
|
675
|
-
class
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
device_type = NestedDeviceTypeSerializer()
|
|
683
|
-
tenant = NestedTenantSerializer(required=False, allow_null=True)
|
|
684
|
-
platform = NestedPlatformSerializer(required=False, allow_null=True)
|
|
685
|
-
location = NestedLocationSerializer()
|
|
686
|
-
rack = NestedRackSerializer(required=False, allow_null=True)
|
|
455
|
+
class DeviceBaySerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
456
|
+
class Meta:
|
|
457
|
+
model = DeviceBay
|
|
458
|
+
fields = "__all__"
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
class DeviceSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
687
462
|
face = ChoiceField(choices=DeviceFaceChoices, allow_blank=True, required=False)
|
|
688
|
-
|
|
689
|
-
primary_ip4 = NestedIPAddressSerializer(required=False, allow_null=True)
|
|
690
|
-
primary_ip6 = NestedIPAddressSerializer(required=False, allow_null=True)
|
|
691
|
-
parent_device = serializers.SerializerMethodField()
|
|
692
|
-
secrets_group = NestedSecretsGroupSerializer(required=False, allow_null=True)
|
|
693
|
-
cluster = NestedClusterSerializer(required=False, allow_null=True)
|
|
694
|
-
virtual_chassis = NestedVirtualChassisSerializer(required=False, allow_null=True)
|
|
695
|
-
device_redundancy_group = NestedDeviceRedundancyGroupSerializer(required=False, allow_null=True)
|
|
696
|
-
local_config_context_schema = NestedConfigContextSchemaSerializer(required=False, allow_null=True)
|
|
463
|
+
config_context = serializers.SerializerMethodField()
|
|
697
464
|
|
|
698
465
|
class Meta:
|
|
699
466
|
model = Device
|
|
700
|
-
fields =
|
|
701
|
-
|
|
702
|
-
"name",
|
|
703
|
-
"device_type",
|
|
704
|
-
"role",
|
|
705
|
-
"tenant",
|
|
706
|
-
"platform",
|
|
707
|
-
"serial",
|
|
708
|
-
"asset_tag",
|
|
709
|
-
"location",
|
|
710
|
-
"rack",
|
|
711
|
-
"position",
|
|
712
|
-
"face",
|
|
713
|
-
"parent_device",
|
|
714
|
-
"status",
|
|
715
|
-
"primary_ip",
|
|
716
|
-
"primary_ip4",
|
|
717
|
-
"primary_ip6",
|
|
718
|
-
"secrets_group",
|
|
719
|
-
"cluster",
|
|
720
|
-
"virtual_chassis",
|
|
721
|
-
"vc_position",
|
|
722
|
-
"vc_priority",
|
|
723
|
-
"device_redundancy_group",
|
|
724
|
-
"device_redundancy_group_priority",
|
|
725
|
-
"comments",
|
|
726
|
-
"local_config_context_schema",
|
|
727
|
-
"local_config_context_data",
|
|
728
|
-
]
|
|
467
|
+
fields = "__all__"
|
|
468
|
+
list_display_fields = ["name", "status", "tenant", "location", "rack", "role", "device_type", "primary_ip"]
|
|
729
469
|
validators = []
|
|
470
|
+
extra_kwargs = {
|
|
471
|
+
"parent_bay": {"required": False, "allow_null": True},
|
|
472
|
+
"vc_position": {"label": "Virtual chassis position"},
|
|
473
|
+
"vc_priority": {"label": "Virtual chassis priority"},
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
def get_field_names(self, declared_fields, info):
|
|
477
|
+
"""
|
|
478
|
+
Add a couple of special fields to the serializer.
|
|
479
|
+
|
|
480
|
+
- As parent_bay is the reverse side of a OneToOneField, DRF can handle it but it isn't auto-included.
|
|
481
|
+
- Config context is expensive to compute and so it's opt-in only.
|
|
482
|
+
"""
|
|
483
|
+
fields = list(super().get_field_names(declared_fields, info))
|
|
484
|
+
self.extend_field_names(fields, "parent_bay")
|
|
485
|
+
self.extend_field_names(fields, "config_context", opt_in_only=True)
|
|
486
|
+
return fields
|
|
487
|
+
|
|
488
|
+
@extend_schema_field(serializers.DictField)
|
|
489
|
+
def get_config_context(self, obj):
|
|
490
|
+
return obj.get_config_context()
|
|
730
491
|
|
|
731
492
|
def validate(self, data):
|
|
732
493
|
# Validate uniqueness of (rack, position, face) since we omitted the automatically-created validator from Meta.
|
|
@@ -743,28 +504,6 @@ class DeviceSerializer(
|
|
|
743
504
|
|
|
744
505
|
return data
|
|
745
506
|
|
|
746
|
-
@extend_schema_field(NestedDeviceSerializer)
|
|
747
|
-
def get_parent_device(self, obj):
|
|
748
|
-
try:
|
|
749
|
-
device_bay = obj.parent_bay
|
|
750
|
-
except DeviceBay.DoesNotExist:
|
|
751
|
-
return None
|
|
752
|
-
context = {"request": self.context["request"]}
|
|
753
|
-
data = NestedDeviceSerializer(instance=device_bay.device, context=context).data
|
|
754
|
-
data["device_bay"] = NestedDeviceBaySerializer(instance=device_bay, context=context).data
|
|
755
|
-
return data
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
class DeviceWithConfigContextSerializer(DeviceSerializer):
|
|
759
|
-
config_context = serializers.SerializerMethodField()
|
|
760
|
-
|
|
761
|
-
class Meta(DeviceSerializer.Meta):
|
|
762
|
-
fields = DeviceSerializer.Meta.fields + ["config_context"]
|
|
763
|
-
|
|
764
|
-
@extend_schema_field(serializers.DictField)
|
|
765
|
-
def get_config_context(self, obj):
|
|
766
|
-
return obj.get_config_context()
|
|
767
|
-
|
|
768
507
|
|
|
769
508
|
class DeviceNAPALMSerializer(serializers.Serializer):
|
|
770
509
|
method = serializers.DictField()
|
|
@@ -776,27 +515,12 @@ class ConsoleServerPortSerializer(
|
|
|
776
515
|
CableTerminationModelSerializerMixin,
|
|
777
516
|
PathEndpointModelSerializerMixin,
|
|
778
517
|
):
|
|
779
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:consoleserverport-detail")
|
|
780
|
-
device = NestedDeviceSerializer()
|
|
781
518
|
type = ChoiceField(choices=ConsolePortTypeChoices, allow_blank=True, required=False)
|
|
782
|
-
cable = NestedCableSerializer(read_only=True)
|
|
783
519
|
|
|
784
520
|
class Meta:
|
|
785
521
|
model = ConsoleServerPort
|
|
786
|
-
fields =
|
|
787
|
-
|
|
788
|
-
"device",
|
|
789
|
-
"name",
|
|
790
|
-
"label",
|
|
791
|
-
"type",
|
|
792
|
-
"description",
|
|
793
|
-
"cable",
|
|
794
|
-
"cable_peer",
|
|
795
|
-
"cable_peer_type",
|
|
796
|
-
"connected_endpoint",
|
|
797
|
-
"connected_endpoint_type",
|
|
798
|
-
"connected_endpoint_reachable",
|
|
799
|
-
]
|
|
522
|
+
fields = "__all__"
|
|
523
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
800
524
|
|
|
801
525
|
|
|
802
526
|
class ConsolePortSerializer(
|
|
@@ -805,27 +529,12 @@ class ConsolePortSerializer(
|
|
|
805
529
|
CableTerminationModelSerializerMixin,
|
|
806
530
|
PathEndpointModelSerializerMixin,
|
|
807
531
|
):
|
|
808
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:consoleport-detail")
|
|
809
|
-
device = NestedDeviceSerializer()
|
|
810
532
|
type = ChoiceField(choices=ConsolePortTypeChoices, allow_blank=True, required=False)
|
|
811
|
-
cable = NestedCableSerializer(read_only=True)
|
|
812
533
|
|
|
813
534
|
class Meta:
|
|
814
535
|
model = ConsolePort
|
|
815
|
-
fields =
|
|
816
|
-
|
|
817
|
-
"device",
|
|
818
|
-
"name",
|
|
819
|
-
"label",
|
|
820
|
-
"type",
|
|
821
|
-
"description",
|
|
822
|
-
"cable",
|
|
823
|
-
"cable_peer",
|
|
824
|
-
"cable_peer_type",
|
|
825
|
-
"connected_endpoint",
|
|
826
|
-
"connected_endpoint_type",
|
|
827
|
-
"connected_endpoint_reachable",
|
|
828
|
-
]
|
|
536
|
+
fields = "__all__"
|
|
537
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
829
538
|
|
|
830
539
|
|
|
831
540
|
class PowerOutletSerializer(
|
|
@@ -834,31 +543,13 @@ class PowerOutletSerializer(
|
|
|
834
543
|
CableTerminationModelSerializerMixin,
|
|
835
544
|
PathEndpointModelSerializerMixin,
|
|
836
545
|
):
|
|
837
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:poweroutlet-detail")
|
|
838
|
-
device = NestedDeviceSerializer()
|
|
839
546
|
type = ChoiceField(choices=PowerOutletTypeChoices, allow_blank=True, required=False)
|
|
840
|
-
power_port = NestedPowerPortSerializer(required=False)
|
|
841
547
|
feed_leg = ChoiceField(choices=PowerOutletFeedLegChoices, allow_blank=True, required=False)
|
|
842
|
-
cable = NestedCableSerializer(read_only=True)
|
|
843
548
|
|
|
844
549
|
class Meta:
|
|
845
550
|
model = PowerOutlet
|
|
846
|
-
fields =
|
|
847
|
-
|
|
848
|
-
"device",
|
|
849
|
-
"name",
|
|
850
|
-
"label",
|
|
851
|
-
"type",
|
|
852
|
-
"power_port",
|
|
853
|
-
"feed_leg",
|
|
854
|
-
"description",
|
|
855
|
-
"cable",
|
|
856
|
-
"cable_peer",
|
|
857
|
-
"cable_peer_type",
|
|
858
|
-
"connected_endpoint",
|
|
859
|
-
"connected_endpoint_type",
|
|
860
|
-
"connected_endpoint_reachable",
|
|
861
|
-
]
|
|
551
|
+
fields = "__all__"
|
|
552
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
862
553
|
|
|
863
554
|
|
|
864
555
|
class PowerPortSerializer(
|
|
@@ -867,29 +558,12 @@ class PowerPortSerializer(
|
|
|
867
558
|
CableTerminationModelSerializerMixin,
|
|
868
559
|
PathEndpointModelSerializerMixin,
|
|
869
560
|
):
|
|
870
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:powerport-detail")
|
|
871
|
-
device = NestedDeviceSerializer()
|
|
872
561
|
type = ChoiceField(choices=PowerPortTypeChoices, allow_blank=True, required=False)
|
|
873
|
-
cable = NestedCableSerializer(read_only=True)
|
|
874
562
|
|
|
875
563
|
class Meta:
|
|
876
564
|
model = PowerPort
|
|
877
|
-
fields =
|
|
878
|
-
|
|
879
|
-
"device",
|
|
880
|
-
"name",
|
|
881
|
-
"label",
|
|
882
|
-
"type",
|
|
883
|
-
"maximum_draw",
|
|
884
|
-
"allocated_draw",
|
|
885
|
-
"description",
|
|
886
|
-
"cable",
|
|
887
|
-
"cable_peer",
|
|
888
|
-
"cable_peer_type",
|
|
889
|
-
"connected_endpoint",
|
|
890
|
-
"connected_endpoint_type",
|
|
891
|
-
"connected_endpoint_reachable",
|
|
892
|
-
]
|
|
565
|
+
fields = "__all__"
|
|
566
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
893
567
|
|
|
894
568
|
|
|
895
569
|
class InterfaceCommonSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
@@ -915,60 +589,17 @@ class InterfaceSerializer(
|
|
|
915
589
|
InterfaceCommonSerializer,
|
|
916
590
|
CableTerminationModelSerializerMixin,
|
|
917
591
|
PathEndpointModelSerializerMixin,
|
|
918
|
-
StatusModelSerializerMixin,
|
|
919
592
|
):
|
|
920
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:interface-detail")
|
|
921
|
-
device = NestedDeviceSerializer()
|
|
922
593
|
type = ChoiceField(choices=InterfaceTypeChoices)
|
|
923
594
|
mode = ChoiceField(choices=InterfaceModeChoices, allow_blank=True, required=False)
|
|
924
|
-
|
|
925
|
-
tagged_vlans = SerializedPKRelatedField(
|
|
926
|
-
queryset=VLAN.objects.all(),
|
|
927
|
-
serializer=NestedVLANSerializer,
|
|
928
|
-
required=False,
|
|
929
|
-
many=True,
|
|
930
|
-
)
|
|
931
|
-
cable = NestedCableSerializer(read_only=True)
|
|
595
|
+
mac_address = serializers.CharField(allow_blank=True, allow_null=True, required=False)
|
|
932
596
|
ip_address_count = serializers.IntegerField(read_only=True)
|
|
933
|
-
ip_addresses = SerializedPKRelatedField(
|
|
934
|
-
queryset=IPAddress.objects.all(),
|
|
935
|
-
serializer=NestedIPAddressSerializer,
|
|
936
|
-
required=False,
|
|
937
|
-
many=True,
|
|
938
|
-
)
|
|
939
|
-
parent_interface = NestedInterfaceSerializer(required=False, allow_null=True)
|
|
940
|
-
bridge = NestedInterfaceSerializer(required=False, allow_null=True)
|
|
941
|
-
lag = NestedInterfaceSerializer(required=False, allow_null=True)
|
|
942
597
|
|
|
943
598
|
class Meta:
|
|
944
599
|
model = Interface
|
|
945
|
-
fields =
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
"name",
|
|
949
|
-
"status",
|
|
950
|
-
"label",
|
|
951
|
-
"type",
|
|
952
|
-
"enabled",
|
|
953
|
-
"parent_interface",
|
|
954
|
-
"bridge",
|
|
955
|
-
"lag",
|
|
956
|
-
"mtu",
|
|
957
|
-
"mac_address",
|
|
958
|
-
"ip_addresses",
|
|
959
|
-
"mgmt_only",
|
|
960
|
-
"description",
|
|
961
|
-
"mode",
|
|
962
|
-
"untagged_vlan",
|
|
963
|
-
"tagged_vlans",
|
|
964
|
-
"cable",
|
|
965
|
-
"cable_peer",
|
|
966
|
-
"cable_peer_type",
|
|
967
|
-
"connected_endpoint",
|
|
968
|
-
"connected_endpoint_type",
|
|
969
|
-
"connected_endpoint_reachable",
|
|
970
|
-
"ip_address_count",
|
|
971
|
-
]
|
|
600
|
+
fields = "__all__"
|
|
601
|
+
list_display_fields = ["device", "name", "status", "label", "enabled", "type", "description"]
|
|
602
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
972
603
|
|
|
973
604
|
def validate(self, data):
|
|
974
605
|
# Validate many-to-many VLAN assignments
|
|
@@ -988,94 +619,37 @@ class InterfaceSerializer(
|
|
|
988
619
|
|
|
989
620
|
|
|
990
621
|
class RearPortSerializer(NautobotModelSerializer, TaggedModelSerializerMixin, CableTerminationModelSerializerMixin):
|
|
991
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rearport-detail")
|
|
992
|
-
device = NestedDeviceSerializer()
|
|
993
622
|
type = ChoiceField(choices=PortTypeChoices)
|
|
994
|
-
cable = NestedCableSerializer(read_only=True)
|
|
995
623
|
|
|
996
624
|
class Meta:
|
|
997
625
|
model = RearPort
|
|
998
|
-
fields =
|
|
999
|
-
|
|
1000
|
-
"device",
|
|
1001
|
-
"name",
|
|
1002
|
-
"label",
|
|
1003
|
-
"type",
|
|
1004
|
-
"positions",
|
|
1005
|
-
"description",
|
|
1006
|
-
"cable",
|
|
1007
|
-
"cable_peer",
|
|
1008
|
-
"cable_peer_type",
|
|
1009
|
-
]
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
class FrontPortRearPortSerializer(WritableNestedSerializer):
|
|
1013
|
-
"""
|
|
1014
|
-
NestedRearPortSerializer but with parent device omitted (since front and rear ports must belong to same device)
|
|
1015
|
-
"""
|
|
1016
|
-
|
|
1017
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:rearport-detail")
|
|
1018
|
-
|
|
1019
|
-
class Meta:
|
|
1020
|
-
model = RearPort
|
|
1021
|
-
fields = ["id", "url", "name", "label"]
|
|
626
|
+
fields = "__all__"
|
|
627
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
1022
628
|
|
|
1023
629
|
|
|
1024
630
|
class FrontPortSerializer(NautobotModelSerializer, TaggedModelSerializerMixin, CableTerminationModelSerializerMixin):
|
|
1025
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:frontport-detail")
|
|
1026
|
-
device = NestedDeviceSerializer()
|
|
1027
631
|
type = ChoiceField(choices=PortTypeChoices)
|
|
1028
|
-
rear_port = FrontPortRearPortSerializer()
|
|
1029
|
-
cable = NestedCableSerializer(read_only=True)
|
|
1030
632
|
|
|
1031
633
|
class Meta:
|
|
1032
634
|
model = FrontPort
|
|
1033
|
-
fields =
|
|
1034
|
-
|
|
1035
|
-
"device",
|
|
1036
|
-
"name",
|
|
1037
|
-
"label",
|
|
1038
|
-
"type",
|
|
1039
|
-
"rear_port",
|
|
1040
|
-
"rear_port_position",
|
|
1041
|
-
"description",
|
|
1042
|
-
"cable",
|
|
1043
|
-
"cable_peer",
|
|
1044
|
-
"cable_peer_type",
|
|
1045
|
-
]
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
class DeviceBaySerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
1049
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:devicebay-detail")
|
|
1050
|
-
device = NestedDeviceSerializer()
|
|
1051
|
-
installed_device = NestedDeviceSerializer(required=False, allow_null=True)
|
|
1052
|
-
|
|
1053
|
-
class Meta:
|
|
1054
|
-
model = DeviceBay
|
|
1055
|
-
fields = [
|
|
1056
|
-
"url",
|
|
1057
|
-
"device",
|
|
1058
|
-
"name",
|
|
1059
|
-
"label",
|
|
1060
|
-
"description",
|
|
1061
|
-
"installed_device",
|
|
1062
|
-
]
|
|
635
|
+
fields = "__all__"
|
|
636
|
+
extra_kwargs = {"cable": {"read_only": True}}
|
|
1063
637
|
|
|
1064
638
|
|
|
1065
|
-
class DeviceRedundancyGroupSerializer(
|
|
1066
|
-
|
|
1067
|
-
|
|
639
|
+
class DeviceRedundancyGroupSerializer(
|
|
640
|
+
NautobotModelSerializer,
|
|
641
|
+
TaggedModelSerializerMixin,
|
|
642
|
+
):
|
|
643
|
+
failover_strategy = ChoiceField(
|
|
644
|
+
choices=DeviceRedundancyGroupFailoverStrategyChoices,
|
|
645
|
+
allow_blank=True,
|
|
646
|
+
default=DeviceRedundancyGroupFailoverStrategyChoices.FAILOVER_UNSPECIFIED,
|
|
647
|
+
)
|
|
1068
648
|
|
|
1069
649
|
class Meta:
|
|
1070
650
|
model = DeviceRedundancyGroup
|
|
1071
|
-
fields =
|
|
1072
|
-
|
|
1073
|
-
"name",
|
|
1074
|
-
"description",
|
|
1075
|
-
"failover_strategy",
|
|
1076
|
-
"secrets_group",
|
|
1077
|
-
"comments",
|
|
1078
|
-
]
|
|
651
|
+
fields = "__all__"
|
|
652
|
+
list_display_fields = ["name", "status", "failover_strategy", "device_count"]
|
|
1079
653
|
|
|
1080
654
|
|
|
1081
655
|
#
|
|
@@ -1084,27 +658,9 @@ class DeviceRedundancyGroupSerializer(NautobotModelSerializer, TaggedModelSerial
|
|
|
1084
658
|
|
|
1085
659
|
|
|
1086
660
|
class InventoryItemSerializer(NautobotModelSerializer, TaggedModelSerializerMixin, TreeModelSerializerMixin):
|
|
1087
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:inventoryitem-detail")
|
|
1088
|
-
device = NestedDeviceSerializer()
|
|
1089
|
-
parent = NestedInventoryItemSerializer(required=False, allow_null=True, default=None)
|
|
1090
|
-
manufacturer = NestedManufacturerSerializer(required=False, allow_null=True, default=None)
|
|
1091
|
-
|
|
1092
661
|
class Meta:
|
|
1093
662
|
model = InventoryItem
|
|
1094
|
-
fields =
|
|
1095
|
-
"url",
|
|
1096
|
-
"device",
|
|
1097
|
-
"parent",
|
|
1098
|
-
"name",
|
|
1099
|
-
"label",
|
|
1100
|
-
"manufacturer",
|
|
1101
|
-
"part_id",
|
|
1102
|
-
"serial",
|
|
1103
|
-
"asset_tag",
|
|
1104
|
-
"discovered",
|
|
1105
|
-
"description",
|
|
1106
|
-
"tree_depth",
|
|
1107
|
-
]
|
|
663
|
+
fields = "__all__"
|
|
1108
664
|
# https://www.django-rest-framework.org/api-guide/validators/#optional-fields
|
|
1109
665
|
validators = []
|
|
1110
666
|
|
|
@@ -1127,30 +683,30 @@ class InventoryItemSerializer(NautobotModelSerializer, TaggedModelSerializerMixi
|
|
|
1127
683
|
#
|
|
1128
684
|
|
|
1129
685
|
|
|
1130
|
-
class CableSerializer(
|
|
1131
|
-
|
|
686
|
+
class CableSerializer(
|
|
687
|
+
NautobotModelSerializer,
|
|
688
|
+
TaggedModelSerializerMixin,
|
|
689
|
+
):
|
|
690
|
+
# TODO: termination_a_type/termination_b_type are a bit redundant with the full termination_a/termination_b dicts
|
|
1132
691
|
termination_a_type = ContentTypeField(queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS))
|
|
1133
692
|
termination_b_type = ContentTypeField(queryset=ContentType.objects.filter(CABLE_TERMINATION_MODELS))
|
|
1134
693
|
termination_a = serializers.SerializerMethodField(read_only=True)
|
|
1135
694
|
termination_b = serializers.SerializerMethodField(read_only=True)
|
|
1136
695
|
length_unit = ChoiceField(choices=CableLengthUnitChoices, allow_blank=True, required=False)
|
|
696
|
+
type = ChoiceField(choices=CableTypeChoices, allow_blank=True, required=False)
|
|
1137
697
|
|
|
1138
698
|
class Meta:
|
|
1139
699
|
model = Cable
|
|
1140
|
-
fields =
|
|
1141
|
-
|
|
1142
|
-
"
|
|
1143
|
-
|
|
700
|
+
fields = "__all__"
|
|
701
|
+
extra_kwargs = {
|
|
702
|
+
"color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
|
|
703
|
+
}
|
|
704
|
+
list_display_fields = [
|
|
705
|
+
"label",
|
|
1144
706
|
"termination_a",
|
|
1145
|
-
"termination_b_type",
|
|
1146
|
-
"termination_b_id",
|
|
1147
707
|
"termination_b",
|
|
1148
|
-
"type",
|
|
1149
708
|
"status",
|
|
1150
|
-
"
|
|
1151
|
-
"color",
|
|
1152
|
-
"length",
|
|
1153
|
-
"length_unit",
|
|
709
|
+
"type",
|
|
1154
710
|
]
|
|
1155
711
|
|
|
1156
712
|
def _get_termination(self, obj, side):
|
|
@@ -1160,17 +716,16 @@ class CableSerializer(NautobotModelSerializer, TaggedModelSerializerMixin, Statu
|
|
|
1160
716
|
if side.lower() not in ["a", "b"]:
|
|
1161
717
|
raise ValueError("Termination side must be either A or B.")
|
|
1162
718
|
termination = getattr(obj, f"termination_{side.lower()}")
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
return data
|
|
719
|
+
depth = get_nested_serializer_depth(self)
|
|
720
|
+
return return_nested_serializer_data_based_on_depth(
|
|
721
|
+
self, depth, obj, termination, f"termination_{side.lower()}"
|
|
722
|
+
)
|
|
1168
723
|
|
|
1169
724
|
@extend_schema_field(
|
|
1170
725
|
PolymorphicProxySerializer(
|
|
1171
726
|
component_name="CableTermination",
|
|
1172
727
|
resource_type_field_name="object_type",
|
|
1173
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)
|
|
728
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)),
|
|
1174
729
|
)
|
|
1175
730
|
)
|
|
1176
731
|
def get_termination_a(self, obj):
|
|
@@ -1180,32 +735,21 @@ class CableSerializer(NautobotModelSerializer, TaggedModelSerializerMixin, Statu
|
|
|
1180
735
|
PolymorphicProxySerializer(
|
|
1181
736
|
component_name="CableTermination",
|
|
1182
737
|
resource_type_field_name="object_type",
|
|
1183
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)
|
|
738
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)),
|
|
1184
739
|
)
|
|
1185
740
|
)
|
|
1186
741
|
def get_termination_b(self, obj):
|
|
1187
742
|
return self._get_termination(obj, "b")
|
|
1188
743
|
|
|
1189
744
|
|
|
1190
|
-
class TracedCableSerializer(
|
|
745
|
+
class TracedCableSerializer(serializers.ModelSerializer):
|
|
1191
746
|
"""
|
|
1192
747
|
Used only while tracing a cable path.
|
|
1193
748
|
"""
|
|
1194
749
|
|
|
1195
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:cable-detail")
|
|
1196
|
-
|
|
1197
750
|
class Meta:
|
|
1198
751
|
model = Cable
|
|
1199
|
-
fields =
|
|
1200
|
-
"id",
|
|
1201
|
-
"url",
|
|
1202
|
-
"type",
|
|
1203
|
-
"status",
|
|
1204
|
-
"label",
|
|
1205
|
-
"color",
|
|
1206
|
-
"length",
|
|
1207
|
-
"length_unit",
|
|
1208
|
-
]
|
|
752
|
+
fields = "__all__"
|
|
1209
753
|
|
|
1210
754
|
|
|
1211
755
|
class CablePathSerializer(serializers.ModelSerializer):
|
|
@@ -1217,37 +761,27 @@ class CablePathSerializer(serializers.ModelSerializer):
|
|
|
1217
761
|
|
|
1218
762
|
class Meta:
|
|
1219
763
|
model = CablePath
|
|
1220
|
-
fields =
|
|
1221
|
-
"id",
|
|
1222
|
-
"origin_type",
|
|
1223
|
-
"origin",
|
|
1224
|
-
"destination_type",
|
|
1225
|
-
"destination",
|
|
1226
|
-
"path",
|
|
1227
|
-
"is_active",
|
|
1228
|
-
"is_split",
|
|
1229
|
-
]
|
|
764
|
+
fields = "__all__"
|
|
1230
765
|
|
|
1231
766
|
@extend_schema_field(
|
|
1232
767
|
PolymorphicProxySerializer(
|
|
1233
768
|
component_name="PathEndpoint",
|
|
1234
769
|
resource_type_field_name="object_type",
|
|
1235
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)
|
|
770
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)),
|
|
1236
771
|
)
|
|
1237
772
|
)
|
|
1238
773
|
def get_origin(self, obj):
|
|
1239
774
|
"""
|
|
1240
775
|
Return the appropriate serializer for the origin.
|
|
1241
776
|
"""
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
return serializer(obj.origin, context=context).data
|
|
777
|
+
depth = get_nested_serializer_depth(self)
|
|
778
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.origin, "origin")
|
|
1245
779
|
|
|
1246
780
|
@extend_schema_field(
|
|
1247
781
|
PolymorphicProxySerializer(
|
|
1248
782
|
component_name="PathEndpoint",
|
|
1249
783
|
resource_type_field_name="object_type",
|
|
1250
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)
|
|
784
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(PathEndpoint)),
|
|
1251
785
|
allow_null=True,
|
|
1252
786
|
)
|
|
1253
787
|
)
|
|
@@ -1256,23 +790,22 @@ class CablePathSerializer(serializers.ModelSerializer):
|
|
|
1256
790
|
Return the appropriate serializer for the destination, if any.
|
|
1257
791
|
"""
|
|
1258
792
|
if obj.destination_id is not None:
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
return serializer(obj.destination, context=context).data
|
|
793
|
+
depth = get_nested_serializer_depth(self)
|
|
794
|
+
return return_nested_serializer_data_based_on_depth(self, depth, obj, obj.destination, "destination")
|
|
1262
795
|
return None
|
|
1263
796
|
|
|
1264
797
|
@extend_schema_field(
|
|
1265
798
|
PolymorphicProxySerializer(
|
|
1266
799
|
component_name="CableTermination",
|
|
1267
800
|
resource_type_field_name="object_type",
|
|
1268
|
-
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)
|
|
801
|
+
serializers=lambda: get_serializers_for_models(get_all_concrete_models(CableTermination)),
|
|
1269
802
|
many=True,
|
|
1270
803
|
)
|
|
1271
804
|
)
|
|
1272
805
|
def get_path(self, obj):
|
|
1273
806
|
ret = []
|
|
1274
807
|
for node in obj.get_path():
|
|
1275
|
-
serializer = get_serializer_for_model(node
|
|
808
|
+
serializer = get_serializer_for_model(node)
|
|
1276
809
|
context = {"request": self.context["request"]}
|
|
1277
810
|
ret.append(serializer(node, context=context).data)
|
|
1278
811
|
return ret
|
|
@@ -1285,17 +818,17 @@ class CablePathSerializer(serializers.ModelSerializer):
|
|
|
1285
818
|
|
|
1286
819
|
class InterfaceConnectionSerializer(ValidatedModelSerializer):
|
|
1287
820
|
interface_a = serializers.SerializerMethodField()
|
|
1288
|
-
interface_b =
|
|
821
|
+
interface_b = InterfaceSerializer(source="connected_endpoint")
|
|
1289
822
|
connected_endpoint_reachable = serializers.SerializerMethodField(read_only=True)
|
|
1290
823
|
|
|
1291
824
|
class Meta:
|
|
1292
825
|
model = Interface
|
|
1293
826
|
fields = ["interface_a", "interface_b", "connected_endpoint_reachable"]
|
|
1294
827
|
|
|
1295
|
-
@extend_schema_field(
|
|
828
|
+
@extend_schema_field(InterfaceSerializer)
|
|
1296
829
|
def get_interface_a(self, obj):
|
|
1297
830
|
context = {"request": self.context["request"]}
|
|
1298
|
-
return
|
|
831
|
+
return InterfaceSerializer(instance=obj, context=context).data
|
|
1299
832
|
|
|
1300
833
|
@extend_schema_field(serializers.BooleanField(allow_null=True))
|
|
1301
834
|
def get_connected_endpoint_reachable(self, obj):
|
|
@@ -1310,19 +843,12 @@ class InterfaceConnectionSerializer(ValidatedModelSerializer):
|
|
|
1310
843
|
|
|
1311
844
|
|
|
1312
845
|
class VirtualChassisSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
1313
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:virtualchassis-detail")
|
|
1314
|
-
master = NestedDeviceSerializer(required=False, allow_null=True)
|
|
1315
846
|
member_count = serializers.IntegerField(read_only=True)
|
|
1316
847
|
|
|
1317
848
|
class Meta:
|
|
1318
849
|
model = VirtualChassis
|
|
1319
|
-
fields =
|
|
1320
|
-
|
|
1321
|
-
"name",
|
|
1322
|
-
"domain",
|
|
1323
|
-
"master",
|
|
1324
|
-
"member_count",
|
|
1325
|
-
]
|
|
850
|
+
fields = "__all__"
|
|
851
|
+
list_display_fields = ["name", "domain", "master", "member_count"]
|
|
1326
852
|
|
|
1327
853
|
|
|
1328
854
|
#
|
|
@@ -1331,20 +857,11 @@ class VirtualChassisSerializer(NautobotModelSerializer, TaggedModelSerializerMix
|
|
|
1331
857
|
|
|
1332
858
|
|
|
1333
859
|
class PowerPanelSerializer(NautobotModelSerializer, TaggedModelSerializerMixin):
|
|
1334
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:powerpanel-detail")
|
|
1335
|
-
location = NestedLocationSerializer()
|
|
1336
|
-
rack_group = NestedRackGroupSerializer(required=False, allow_null=True, default=None)
|
|
1337
860
|
power_feed_count = serializers.IntegerField(read_only=True)
|
|
1338
861
|
|
|
1339
862
|
class Meta:
|
|
1340
863
|
model = PowerPanel
|
|
1341
|
-
fields =
|
|
1342
|
-
"url",
|
|
1343
|
-
"location",
|
|
1344
|
-
"rack_group",
|
|
1345
|
-
"name",
|
|
1346
|
-
"power_feed_count",
|
|
1347
|
-
]
|
|
864
|
+
fields = "__all__"
|
|
1348
865
|
|
|
1349
866
|
|
|
1350
867
|
class PowerFeedSerializer(
|
|
@@ -1352,35 +869,11 @@ class PowerFeedSerializer(
|
|
|
1352
869
|
TaggedModelSerializerMixin,
|
|
1353
870
|
CableTerminationModelSerializerMixin,
|
|
1354
871
|
PathEndpointModelSerializerMixin,
|
|
1355
|
-
StatusModelSerializerMixin,
|
|
1356
872
|
):
|
|
1357
|
-
url = serializers.HyperlinkedIdentityField(view_name="dcim-api:powerfeed-detail")
|
|
1358
|
-
power_panel = NestedPowerPanelSerializer()
|
|
1359
|
-
rack = NestedRackSerializer(required=False, allow_null=True, default=None)
|
|
1360
873
|
type = ChoiceField(choices=PowerFeedTypeChoices, default=PowerFeedTypeChoices.TYPE_PRIMARY)
|
|
1361
874
|
supply = ChoiceField(choices=PowerFeedSupplyChoices, default=PowerFeedSupplyChoices.SUPPLY_AC)
|
|
1362
875
|
phase = ChoiceField(choices=PowerFeedPhaseChoices, default=PowerFeedPhaseChoices.PHASE_SINGLE)
|
|
1363
|
-
cable = NestedCableSerializer(read_only=True)
|
|
1364
876
|
|
|
1365
877
|
class Meta:
|
|
1366
878
|
model = PowerFeed
|
|
1367
|
-
fields =
|
|
1368
|
-
"url",
|
|
1369
|
-
"power_panel",
|
|
1370
|
-
"rack",
|
|
1371
|
-
"name",
|
|
1372
|
-
"status",
|
|
1373
|
-
"type",
|
|
1374
|
-
"supply",
|
|
1375
|
-
"phase",
|
|
1376
|
-
"voltage",
|
|
1377
|
-
"amperage",
|
|
1378
|
-
"max_utilization",
|
|
1379
|
-
"comments",
|
|
1380
|
-
"cable",
|
|
1381
|
-
"cable_peer",
|
|
1382
|
-
"cable_peer_type",
|
|
1383
|
-
"connected_endpoint",
|
|
1384
|
-
"connected_endpoint_type",
|
|
1385
|
-
"connected_endpoint_reachable",
|
|
1386
|
-
]
|
|
879
|
+
fields = "__all__"
|