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/urls.py
CHANGED
|
@@ -40,17 +40,17 @@ urlpatterns = [
|
|
|
40
40
|
path("location-types/add/", views.LocationTypeEditView.as_view(), name="locationtype_add"),
|
|
41
41
|
path("location-types/import/", views.LocationTypeBulkImportView.as_view(), name="locationtype_import"),
|
|
42
42
|
path("location-types/delete/", views.LocationTypeBulkDeleteView.as_view(), name="locationtype_bulk_delete"),
|
|
43
|
-
path("location-types/<
|
|
44
|
-
path("location-types/<
|
|
45
|
-
path("location-types/<
|
|
43
|
+
path("location-types/<uuid:pk>/", views.LocationTypeView.as_view(), name="locationtype"),
|
|
44
|
+
path("location-types/<uuid:pk>/edit/", views.LocationTypeEditView.as_view(), name="locationtype_edit"),
|
|
45
|
+
path("location-types/<uuid:pk>/delete/", views.LocationTypeDeleteView.as_view(), name="locationtype_delete"),
|
|
46
46
|
path(
|
|
47
|
-
"location-types/<
|
|
47
|
+
"location-types/<uuid:pk>/changelog/",
|
|
48
48
|
ObjectChangeLogView.as_view(),
|
|
49
49
|
name="locationtype_changelog",
|
|
50
50
|
kwargs={"model": LocationType},
|
|
51
51
|
),
|
|
52
52
|
path(
|
|
53
|
-
"location-types/<
|
|
53
|
+
"location-types/<uuid:pk>/notes/",
|
|
54
54
|
ObjectNotesView.as_view(),
|
|
55
55
|
name="locationtype_notes",
|
|
56
56
|
kwargs={"model": LocationType},
|
|
@@ -61,23 +61,23 @@ urlpatterns = [
|
|
|
61
61
|
path("locations/edit/", views.LocationBulkEditView.as_view(), name="location_bulk_edit"),
|
|
62
62
|
path("locations/import/", views.LocationBulkImportView.as_view(), name="location_import"),
|
|
63
63
|
path("locations/delete/", views.LocationBulkDeleteView.as_view(), name="location_bulk_delete"),
|
|
64
|
-
path("locations/<
|
|
65
|
-
path("locations/<
|
|
66
|
-
path("locations/<
|
|
64
|
+
path("locations/<uuid:pk>/", views.LocationView.as_view(), name="location"),
|
|
65
|
+
path("locations/<uuid:pk>/edit/", views.LocationEditView.as_view(), name="location_edit"),
|
|
66
|
+
path("locations/<uuid:pk>/delete/", views.LocationDeleteView.as_view(), name="location_delete"),
|
|
67
67
|
path(
|
|
68
|
-
"locations/<
|
|
68
|
+
"locations/<uuid:pk>/changelog/",
|
|
69
69
|
ObjectChangeLogView.as_view(),
|
|
70
70
|
name="location_changelog",
|
|
71
71
|
kwargs={"model": Location},
|
|
72
72
|
),
|
|
73
73
|
path(
|
|
74
|
-
"locations/<
|
|
74
|
+
"locations/<uuid:pk>/notes/",
|
|
75
75
|
ObjectNotesView.as_view(),
|
|
76
76
|
name="location_notes",
|
|
77
77
|
kwargs={"model": Location},
|
|
78
78
|
),
|
|
79
79
|
path(
|
|
80
|
-
"locations/<
|
|
80
|
+
"locations/<uuid:pk>/images/add/",
|
|
81
81
|
ImageAttachmentEditView.as_view(),
|
|
82
82
|
name="location_add_image",
|
|
83
83
|
kwargs={"model": Location},
|
|
@@ -582,11 +582,6 @@ urlpatterns = [
|
|
|
582
582
|
path("devices/", views.DeviceListView.as_view(), name="device_list"),
|
|
583
583
|
path("devices/add/", views.DeviceEditView.as_view(), name="device_add"),
|
|
584
584
|
path("devices/import/", views.DeviceBulkImportView.as_view(), name="device_import"),
|
|
585
|
-
path(
|
|
586
|
-
"devices/import/child-devices/",
|
|
587
|
-
views.ChildDeviceBulkImportView.as_view(),
|
|
588
|
-
name="device_import_child",
|
|
589
|
-
),
|
|
590
585
|
path("devices/edit/", views.DeviceBulkEditView.as_view(), name="device_bulk_edit"),
|
|
591
586
|
path(
|
|
592
587
|
"devices/delete/",
|
nautobot/dcim/views.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import uuid
|
|
2
|
-
from collections import OrderedDict
|
|
2
|
+
from collections import OrderedDict
|
|
3
3
|
|
|
4
4
|
from django.contrib import messages
|
|
5
5
|
from django.contrib.contenttypes.models import ContentType
|
|
@@ -25,7 +25,6 @@ from nautobot.core.utils.permissions import get_permission_for_model
|
|
|
25
25
|
from nautobot.core.views import generic
|
|
26
26
|
from nautobot.core.views.mixins import GetReturnURLMixin, ObjectPermissionRequiredMixin
|
|
27
27
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
28
|
-
from nautobot.core.views.utils import csv_format
|
|
29
28
|
from nautobot.core.views.viewsets import NautobotUIViewSet
|
|
30
29
|
from nautobot.extras.views import ObjectChangeLogView, ObjectConfigContextView, ObjectDynamicGroupsView
|
|
31
30
|
from nautobot.ipam.models import IPAddress, Prefix, Service, VLAN
|
|
@@ -190,7 +189,6 @@ class LocationTypeDeleteView(generic.ObjectDeleteView):
|
|
|
190
189
|
|
|
191
190
|
class LocationTypeBulkImportView(generic.BulkImportView):
|
|
192
191
|
queryset = LocationType.objects.all()
|
|
193
|
-
model_form = forms.LocationTypeCSVForm
|
|
194
192
|
table = tables.LocationTypeTable
|
|
195
193
|
|
|
196
194
|
|
|
@@ -280,7 +278,6 @@ class LocationBulkEditView(generic.BulkEditView):
|
|
|
280
278
|
|
|
281
279
|
class LocationBulkImportView(generic.BulkImportView):
|
|
282
280
|
queryset = Location.objects.all()
|
|
283
|
-
model_form = forms.LocationCSVForm
|
|
284
281
|
table = tables.LocationTable
|
|
285
282
|
|
|
286
283
|
|
|
@@ -338,7 +335,6 @@ class RackGroupDeleteView(generic.ObjectDeleteView):
|
|
|
338
335
|
|
|
339
336
|
class RackGroupBulkImportView(generic.BulkImportView):
|
|
340
337
|
queryset = RackGroup.objects.all()
|
|
341
|
-
model_form = forms.RackGroupCSVForm
|
|
342
338
|
table = tables.RackGroupTable
|
|
343
339
|
|
|
344
340
|
|
|
@@ -463,7 +459,6 @@ class RackDeleteView(generic.ObjectDeleteView):
|
|
|
463
459
|
|
|
464
460
|
class RackBulkImportView(generic.BulkImportView):
|
|
465
461
|
queryset = Rack.objects.all()
|
|
466
|
-
model_form = forms.RackCSVForm
|
|
467
462
|
table = tables.RackTable
|
|
468
463
|
|
|
469
464
|
|
|
@@ -515,19 +510,8 @@ class RackReservationDeleteView(generic.ObjectDeleteView):
|
|
|
515
510
|
|
|
516
511
|
class RackReservationImportView(generic.BulkImportView):
|
|
517
512
|
queryset = RackReservation.objects.all()
|
|
518
|
-
model_form = forms.RackReservationCSVForm
|
|
519
513
|
table = tables.RackReservationTable
|
|
520
514
|
|
|
521
|
-
def _save_obj(self, obj_form, request):
|
|
522
|
-
"""
|
|
523
|
-
Assign the currently authenticated user to the RackReservation.
|
|
524
|
-
"""
|
|
525
|
-
instance = obj_form.save(commit=False)
|
|
526
|
-
instance.user = request.user
|
|
527
|
-
instance.save()
|
|
528
|
-
|
|
529
|
-
return instance
|
|
530
|
-
|
|
531
515
|
|
|
532
516
|
class RackReservationBulkEditView(generic.BulkEditView):
|
|
533
517
|
queryset = RackReservation.objects.select_related("rack", "user")
|
|
@@ -592,7 +576,6 @@ class ManufacturerDeleteView(generic.ObjectDeleteView):
|
|
|
592
576
|
|
|
593
577
|
class ManufacturerBulkImportView(generic.BulkImportView):
|
|
594
578
|
queryset = Manufacturer.objects.all()
|
|
595
|
-
model_form = forms.ManufacturerCSVForm
|
|
596
579
|
table = tables.ManufacturerTable
|
|
597
580
|
|
|
598
581
|
|
|
@@ -1069,7 +1052,6 @@ class PlatformDeleteView(generic.ObjectDeleteView):
|
|
|
1069
1052
|
|
|
1070
1053
|
class PlatformBulkImportView(generic.BulkImportView):
|
|
1071
1054
|
queryset = Platform.objects.all()
|
|
1072
|
-
model_form = forms.PlatformCSVForm
|
|
1073
1055
|
table = tables.PlatformTable
|
|
1074
1056
|
|
|
1075
1057
|
|
|
@@ -1128,8 +1110,7 @@ class DeviceView(generic.ObjectView):
|
|
|
1128
1110
|
|
|
1129
1111
|
# VRF assignments
|
|
1130
1112
|
vrf_assignments = instance.vrf_assignments.restrict(request.user, "view")
|
|
1131
|
-
vrf_table = VRFDeviceAssignmentTable(vrf_assignments)
|
|
1132
|
-
vrf_table.exclude = ("device",)
|
|
1113
|
+
vrf_table = VRFDeviceAssignmentTable(vrf_assignments, exclude=("virtual_machine", "device"))
|
|
1133
1114
|
|
|
1134
1115
|
return {
|
|
1135
1116
|
"services": services,
|
|
@@ -1401,26 +1382,7 @@ class DeviceDeleteView(generic.ObjectDeleteView):
|
|
|
1401
1382
|
|
|
1402
1383
|
class DeviceBulkImportView(generic.BulkImportView):
|
|
1403
1384
|
queryset = Device.objects.all()
|
|
1404
|
-
model_form = forms.DeviceCSVForm
|
|
1405
|
-
table = tables.DeviceImportTable
|
|
1406
|
-
template_name = "dcim/device_import.html"
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
class ChildDeviceBulkImportView(generic.BulkImportView):
|
|
1410
|
-
queryset = Device.objects.all()
|
|
1411
|
-
model_form = forms.ChildDeviceCSVForm
|
|
1412
1385
|
table = tables.DeviceImportTable
|
|
1413
|
-
template_name = "dcim/device_import_child.html"
|
|
1414
|
-
|
|
1415
|
-
def _save_obj(self, obj_form, request):
|
|
1416
|
-
obj = obj_form.save()
|
|
1417
|
-
|
|
1418
|
-
# Save the reverse relation to the parent device bay
|
|
1419
|
-
device_bay = obj.parent_bay
|
|
1420
|
-
device_bay.installed_device = obj
|
|
1421
|
-
device_bay.save()
|
|
1422
|
-
|
|
1423
|
-
return obj
|
|
1424
1386
|
|
|
1425
1387
|
|
|
1426
1388
|
class DeviceBulkEditView(generic.BulkEditView):
|
|
@@ -1477,7 +1439,6 @@ class ConsolePortDeleteView(generic.ObjectDeleteView):
|
|
|
1477
1439
|
|
|
1478
1440
|
class ConsolePortBulkImportView(generic.BulkImportView):
|
|
1479
1441
|
queryset = ConsolePort.objects.all()
|
|
1480
|
-
model_form = forms.ConsolePortCSVForm
|
|
1481
1442
|
table = tables.ConsolePortTable
|
|
1482
1443
|
|
|
1483
1444
|
|
|
@@ -1541,7 +1502,6 @@ class ConsoleServerPortDeleteView(generic.ObjectDeleteView):
|
|
|
1541
1502
|
|
|
1542
1503
|
class ConsoleServerPortBulkImportView(generic.BulkImportView):
|
|
1543
1504
|
queryset = ConsoleServerPort.objects.all()
|
|
1544
|
-
model_form = forms.ConsoleServerPortCSVForm
|
|
1545
1505
|
table = tables.ConsoleServerPortTable
|
|
1546
1506
|
|
|
1547
1507
|
|
|
@@ -1605,7 +1565,6 @@ class PowerPortDeleteView(generic.ObjectDeleteView):
|
|
|
1605
1565
|
|
|
1606
1566
|
class PowerPortBulkImportView(generic.BulkImportView):
|
|
1607
1567
|
queryset = PowerPort.objects.all()
|
|
1608
|
-
model_form = forms.PowerPortCSVForm
|
|
1609
1568
|
table = tables.PowerPortTable
|
|
1610
1569
|
|
|
1611
1570
|
|
|
@@ -1669,7 +1628,6 @@ class PowerOutletDeleteView(generic.ObjectDeleteView):
|
|
|
1669
1628
|
|
|
1670
1629
|
class PowerOutletBulkImportView(generic.BulkImportView):
|
|
1671
1630
|
queryset = PowerOutlet.objects.all()
|
|
1672
|
-
model_form = forms.PowerOutletCSVForm
|
|
1673
1631
|
table = tables.PowerOutletTable
|
|
1674
1632
|
|
|
1675
1633
|
|
|
@@ -1763,7 +1721,6 @@ class InterfaceDeleteView(generic.ObjectDeleteView):
|
|
|
1763
1721
|
|
|
1764
1722
|
class InterfaceBulkImportView(generic.BulkImportView):
|
|
1765
1723
|
queryset = Interface.objects.all()
|
|
1766
|
-
model_form = forms.InterfaceCSVForm
|
|
1767
1724
|
table = tables.InterfaceTable
|
|
1768
1725
|
|
|
1769
1726
|
|
|
@@ -1828,7 +1785,6 @@ class FrontPortDeleteView(generic.ObjectDeleteView):
|
|
|
1828
1785
|
|
|
1829
1786
|
class FrontPortBulkImportView(generic.BulkImportView):
|
|
1830
1787
|
queryset = FrontPort.objects.all()
|
|
1831
|
-
model_form = forms.FrontPortCSVForm
|
|
1832
1788
|
table = tables.FrontPortTable
|
|
1833
1789
|
|
|
1834
1790
|
|
|
@@ -1892,7 +1848,6 @@ class RearPortDeleteView(generic.ObjectDeleteView):
|
|
|
1892
1848
|
|
|
1893
1849
|
class RearPortBulkImportView(generic.BulkImportView):
|
|
1894
1850
|
queryset = RearPort.objects.all()
|
|
1895
|
-
model_form = forms.RearPortCSVForm
|
|
1896
1851
|
table = tables.RearPortTable
|
|
1897
1852
|
|
|
1898
1853
|
|
|
@@ -2041,7 +1996,6 @@ class DeviceBayDepopulateView(generic.ObjectEditView):
|
|
|
2041
1996
|
|
|
2042
1997
|
class DeviceBayBulkImportView(generic.BulkImportView):
|
|
2043
1998
|
queryset = DeviceBay.objects.all()
|
|
2044
|
-
model_form = forms.DeviceBayCSVForm
|
|
2045
1999
|
table = tables.DeviceBayTable
|
|
2046
2000
|
|
|
2047
2001
|
|
|
@@ -2100,7 +2054,6 @@ class InventoryItemDeleteView(generic.ObjectDeleteView):
|
|
|
2100
2054
|
|
|
2101
2055
|
class InventoryItemBulkImportView(generic.BulkImportView):
|
|
2102
2056
|
queryset = InventoryItem.objects.all()
|
|
2103
|
-
model_form = forms.InventoryItemCSVForm
|
|
2104
2057
|
table = tables.InventoryItemTable
|
|
2105
2058
|
|
|
2106
2059
|
|
|
@@ -2377,7 +2330,6 @@ class CableDeleteView(generic.ObjectDeleteView):
|
|
|
2377
2330
|
|
|
2378
2331
|
class CableBulkImportView(generic.BulkImportView):
|
|
2379
2332
|
queryset = Cable.objects.all()
|
|
2380
|
-
model_form = forms.CableCSVForm
|
|
2381
2333
|
table = tables.CableTable
|
|
2382
2334
|
|
|
2383
2335
|
|
|
@@ -2400,56 +2352,7 @@ class CableBulkDeleteView(generic.BulkDeleteView):
|
|
|
2400
2352
|
|
|
2401
2353
|
|
|
2402
2354
|
class ConnectionsListView(generic.ObjectListView):
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
def queryset_to_csv_body_data(self):
|
|
2406
|
-
"""
|
|
2407
|
-
The headers may differ from view to view but the formatting of the CSV data is the same.
|
|
2408
|
-
"""
|
|
2409
|
-
csv_body_data = []
|
|
2410
|
-
for obj in self.queryset:
|
|
2411
|
-
# The connected endpoint may or may not be associated with a Device (e.g., CircuitTerminations are not)
|
|
2412
|
-
# and may or may not have a name of its own (e.g., CircuitTerminations do not)
|
|
2413
|
-
dest_device = None
|
|
2414
|
-
dest_name = None
|
|
2415
|
-
if obj.connected_endpoint:
|
|
2416
|
-
if hasattr(obj.connected_endpoint, "device"):
|
|
2417
|
-
dest_device = obj.connected_endpoint.device.identifier
|
|
2418
|
-
if hasattr(obj.connected_endpoint, "name"):
|
|
2419
|
-
dest_name = obj.connected_endpoint.name
|
|
2420
|
-
|
|
2421
|
-
# In the case where a connection exists between two like endpoints,
|
|
2422
|
-
# for consistency of output we want to ensure that it's always represented as
|
|
2423
|
-
# ("device a", "interface a", "device b", "interface b") rather than
|
|
2424
|
-
# ("device b", "interface b", "device a", "interface a")
|
|
2425
|
-
if obj.__class__ == obj.connected_endpoint.__class__ and (
|
|
2426
|
-
obj.device.identifier > obj.connected_endpoint.device.identifier
|
|
2427
|
-
or (
|
|
2428
|
-
obj.device.identifier == obj.connected_endpoint.device.identifier
|
|
2429
|
-
and obj.name > obj.connected_endpoint.name
|
|
2430
|
-
)
|
|
2431
|
-
):
|
|
2432
|
-
# Swap the two endpoints around for consistent output as described above
|
|
2433
|
-
row = self.CSVRow(
|
|
2434
|
-
device=dest_device,
|
|
2435
|
-
name=dest_name,
|
|
2436
|
-
dest_device=obj.device.identifier,
|
|
2437
|
-
dest_name=obj.name,
|
|
2438
|
-
reachable=str(obj.path.is_active),
|
|
2439
|
-
)
|
|
2440
|
-
else:
|
|
2441
|
-
# Existing order of endpoints is fine and correct
|
|
2442
|
-
row = self.CSVRow(
|
|
2443
|
-
device=obj.device.identifier,
|
|
2444
|
-
name=obj.name,
|
|
2445
|
-
dest_device=dest_device,
|
|
2446
|
-
dest_name=dest_name,
|
|
2447
|
-
reachable=str(obj.path.is_active),
|
|
2448
|
-
)
|
|
2449
|
-
|
|
2450
|
-
csv_body_data.append(csv_format(row))
|
|
2451
|
-
|
|
2452
|
-
return sorted(csv_body_data)
|
|
2355
|
+
pass
|
|
2453
2356
|
|
|
2454
2357
|
|
|
2455
2358
|
class ConsoleConnectionsListView(ConnectionsListView):
|
|
@@ -2457,17 +2360,9 @@ class ConsoleConnectionsListView(ConnectionsListView):
|
|
|
2457
2360
|
filterset = filters.ConsoleConnectionFilterSet
|
|
2458
2361
|
filterset_form = forms.ConsoleConnectionFilterForm
|
|
2459
2362
|
table = tables.ConsoleConnectionTable
|
|
2363
|
+
template_name = "dcim/console_port_connection_list.html"
|
|
2460
2364
|
action_buttons = ("export",)
|
|
2461
2365
|
|
|
2462
|
-
def queryset_to_csv(self):
|
|
2463
|
-
csv_data = [
|
|
2464
|
-
# Headers
|
|
2465
|
-
",".join(["device", "console_port", "console_server", "port", "reachable"])
|
|
2466
|
-
]
|
|
2467
|
-
csv_data.extend(self.queryset_to_csv_body_data())
|
|
2468
|
-
|
|
2469
|
-
return "\n".join(csv_data)
|
|
2470
|
-
|
|
2471
2366
|
def extra_context(self):
|
|
2472
2367
|
return {
|
|
2473
2368
|
"title": "Console Connections",
|
|
@@ -2481,17 +2376,9 @@ class PowerConnectionsListView(ConnectionsListView):
|
|
|
2481
2376
|
filterset = filters.PowerConnectionFilterSet
|
|
2482
2377
|
filterset_form = forms.PowerConnectionFilterForm
|
|
2483
2378
|
table = tables.PowerConnectionTable
|
|
2379
|
+
template_name = "dcim/power_port_connection_list.html"
|
|
2484
2380
|
action_buttons = ("export",)
|
|
2485
2381
|
|
|
2486
|
-
def queryset_to_csv(self):
|
|
2487
|
-
csv_data = [
|
|
2488
|
-
# Headers
|
|
2489
|
-
",".join(["device", "power_port", "pdu", "outlet", "reachable"])
|
|
2490
|
-
]
|
|
2491
|
-
csv_data.extend(self.queryset_to_csv_body_data())
|
|
2492
|
-
|
|
2493
|
-
return "\n".join(csv_data)
|
|
2494
|
-
|
|
2495
2382
|
def extra_context(self):
|
|
2496
2383
|
return {
|
|
2497
2384
|
"title": "Power Connections",
|
|
@@ -2505,6 +2392,7 @@ class InterfaceConnectionsListView(ConnectionsListView):
|
|
|
2505
2392
|
filterset = filters.InterfaceConnectionFilterSet
|
|
2506
2393
|
filterset_form = forms.InterfaceConnectionFilterForm
|
|
2507
2394
|
table = tables.InterfaceConnectionTable
|
|
2395
|
+
template_name = "dcim/interface_connection_list.html"
|
|
2508
2396
|
action_buttons = ("export",)
|
|
2509
2397
|
|
|
2510
2398
|
def __init__(self, *args, **kwargs):
|
|
@@ -2520,8 +2408,7 @@ class InterfaceConnectionsListView(ConnectionsListView):
|
|
|
2520
2408
|
# Unfortunately we can't use something consistent to pick which pair to exclude (such as device or name)
|
|
2521
2409
|
# as _path.destination is a GenericForeignKey without a corresponding GenericRelation and so cannot be
|
|
2522
2410
|
# used for reverse querying.
|
|
2523
|
-
# The below at least ensures uniqueness, but doesn't guarantee whether we get (A, B) or (B, A)
|
|
2524
|
-
# we fix it up to be consistently (A, B) in queryset_to_csv_body_data().
|
|
2411
|
+
# The below at least ensures uniqueness, but doesn't guarantee whether we get (A, B) or (B, A)
|
|
2525
2412
|
# TODO: this is very problematic when filtering the view via FilterSet - if the filterset matches (A), then
|
|
2526
2413
|
# the connection will appear in the table, but if it only matches (B) then the connection will not!
|
|
2527
2414
|
_path__destination_type=ContentType.objects.get_for_model(Interface),
|
|
@@ -2532,15 +2419,6 @@ class InterfaceConnectionsListView(ConnectionsListView):
|
|
|
2532
2419
|
|
|
2533
2420
|
return self.queryset
|
|
2534
2421
|
|
|
2535
|
-
def queryset_to_csv(self):
|
|
2536
|
-
csv_data = [
|
|
2537
|
-
# Headers
|
|
2538
|
-
",".join(["device_a", "interface_a", "device_b", "interface_b", "reachable"])
|
|
2539
|
-
]
|
|
2540
|
-
csv_data.extend(self.queryset_to_csv_body_data())
|
|
2541
|
-
|
|
2542
|
-
return "\n".join(csv_data)
|
|
2543
|
-
|
|
2544
2422
|
def extra_context(self):
|
|
2545
2423
|
return {
|
|
2546
2424
|
"title": "Interface Connections",
|
|
@@ -2773,7 +2651,6 @@ class VirtualChassisRemoveMemberView(ObjectPermissionRequiredMixin, GetReturnURL
|
|
|
2773
2651
|
|
|
2774
2652
|
class VirtualChassisBulkImportView(generic.BulkImportView):
|
|
2775
2653
|
queryset = VirtualChassis.objects.all()
|
|
2776
|
-
model_form = forms.VirtualChassisCSVForm
|
|
2777
2654
|
table = tables.VirtualChassisTable
|
|
2778
2655
|
|
|
2779
2656
|
|
|
@@ -2829,7 +2706,6 @@ class PowerPanelDeleteView(generic.ObjectDeleteView):
|
|
|
2829
2706
|
|
|
2830
2707
|
class PowerPanelBulkImportView(generic.BulkImportView):
|
|
2831
2708
|
queryset = PowerPanel.objects.all()
|
|
2832
|
-
model_form = forms.PowerPanelCSVForm
|
|
2833
2709
|
table = tables.PowerPanelTable
|
|
2834
2710
|
|
|
2835
2711
|
|
|
@@ -2876,7 +2752,6 @@ class PowerFeedDeleteView(generic.ObjectDeleteView):
|
|
|
2876
2752
|
|
|
2877
2753
|
class PowerFeedBulkImportView(generic.BulkImportView):
|
|
2878
2754
|
queryset = PowerFeed.objects.all()
|
|
2879
|
-
model_form = forms.PowerFeedCSVForm
|
|
2880
2755
|
table = tables.PowerFeedTable
|
|
2881
2756
|
|
|
2882
2757
|
|
|
@@ -2894,7 +2769,6 @@ class PowerFeedBulkDeleteView(generic.BulkDeleteView):
|
|
|
2894
2769
|
|
|
2895
2770
|
|
|
2896
2771
|
class DeviceRedundancyGroupUIViewSet(NautobotUIViewSet):
|
|
2897
|
-
bulk_create_form_class = forms.DeviceRedundancyGroupCSVForm
|
|
2898
2772
|
bulk_update_form_class = forms.DeviceRedundancyGroupBulkEditForm
|
|
2899
2773
|
filterset_class = filters.DeviceRedundancyGroupFilterSet
|
|
2900
2774
|
filterset_form_class = forms.DeviceRedundancyGroupFilterForm
|
|
@@ -2906,7 +2780,6 @@ class DeviceRedundancyGroupUIViewSet(NautobotUIViewSet):
|
|
|
2906
2780
|
)
|
|
2907
2781
|
serializer_class = serializers.DeviceRedundancyGroupSerializer
|
|
2908
2782
|
table_class = tables.DeviceRedundancyGroupTable
|
|
2909
|
-
lookup_field = "pk"
|
|
2910
2783
|
|
|
2911
2784
|
def get_extra_context(self, request, instance):
|
|
2912
2785
|
context = super().get_extra_context(request, instance)
|
|
@@ -10,75 +10,32 @@ Nautobot makes extensive use of caching; this is not a simple topic but it's a u
|
|
|
10
10
|
|
|
11
11
|
## How it Works
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
!!! caution "Changed in version 1.5.0"
|
|
16
|
-
Query caching is now disabled by default, and will be removed as a supported option in a future release.
|
|
17
|
-
|
|
18
|
-
If a change is made to any of the objects returned by the cached query within that time, or if the timeout expires, the cached results are automatically invalidated and the next request for those results will be sent to the database.
|
|
13
|
+
--- 2.0.0
|
|
14
|
+
`django-cacheops` has been removed as a Nautobot dependency and is no longer used.
|
|
19
15
|
|
|
20
16
|
Caching is a complex topic and there are some important details to clarify with how caching is implemented and configured in Nautobot.
|
|
21
17
|
|
|
22
18
|
### Caching in Django
|
|
23
19
|
|
|
24
|
-
Django includes
|
|
20
|
+
Django includes its own [cache framework](https://docs.djangoproject.com/en/stable/topics/cache/). Nautobot uses this cache framework in a limited number of cases.
|
|
25
21
|
|
|
26
22
|
### `CACHES` and `django-redis`
|
|
27
23
|
|
|
28
|
-
The [`CACHES`](../configuration/required-settings.md#caches) setting is used to, among other things, configure Django's built-in caching.
|
|
24
|
+
The [`CACHES`](../configuration/required-settings.md#caches) setting is used to, among other things, configure Django's built-in caching. *This is a required setting*. Here's why:
|
|
29
25
|
|
|
30
26
|
Nautobot uses the [`django-redis`](https://github.com/jazzband/django-redis) Django plugin which allows it to use Redis as a backend for caching and session storage. This is used to provide a concurrent write lock for preventing race conditions when allocating IP address objects.
|
|
31
27
|
|
|
32
28
|
`django-redis` *also* uses the [`CACHES`](../configuration/required-settings.md#caches) setting, in its case to simplify the configuration for establishing concurrent write locks.
|
|
33
29
|
|
|
34
|
-
Again: **`CACHES` is not used for Django's built-in caching at this time, but it is still a required setting for `django-redis` to function properly.**
|
|
35
|
-
|
|
36
|
-
### Django Cacheops
|
|
37
|
-
|
|
38
|
-
Cacheops (aka [`django-cacheops`](https://github.com/Suor/django-cacheops)) is a Django plugin that does some very advanced caching, but *does not leverage the built-in cache framework*. Instead it uses a technique called ["monkey patching"](https://en.wikipedia.org/wiki/Monkey_patch). By monkey patching, a library can inject its own functionality into the core code behind the scenes.
|
|
39
|
-
|
|
40
|
-
This technique allows Cacheops to do more advanced caching operations that are not provided by the Django built-in cache framework without requiring Nautobot to also include some elaborate code of its own. This is accomplished by intercepting calls to the underlying queryset methods that get and set cached results in Redis.
|
|
41
|
-
|
|
42
|
-
For this purpose, Cacheops has its own `CACHEOPS_*` settings required to configure it that are not related to the `CACHES` setting.
|
|
43
|
-
|
|
44
|
-
For more information on the required settings needed to configure Cacheops, please see the [Caching section of the required settings documentation](../configuration/required-settings.md#caching).
|
|
45
|
-
|
|
46
|
-
The optional settings include:
|
|
47
|
-
|
|
48
|
-
* [`CACHEOPS_DEFAULTS`](../configuration/optional-settings.md#cacheops_defaults): To define the cache timeout value (Defaults to 15 minutes)
|
|
49
|
-
* [`CACHEOPS_ENABLED`](../configuration/optional-settings.md#cacheops_enabled) : To turn on/off caching (Defaults to `False`)
|
|
50
|
-
|
|
51
|
-
## Invalidating Cached Data
|
|
52
|
-
|
|
53
|
-
Although caching is performed automatically and rarely requires administrative intervention, Nautobot provides the `invalidate` management command to force invalidation of cached results. This command can reference a specific object my its type and UUID:
|
|
54
|
-
|
|
55
|
-
> Run these commands as the Nautobot user
|
|
56
|
-
|
|
57
|
-
```no-highlight
|
|
58
|
-
nautobot-server invalidate dcim.Device.84ae706d-c189-4d13-a898-9737648e34b3
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
Alternatively, it can also delete all cached results for an object type:
|
|
62
|
-
|
|
63
|
-
```no-highlight
|
|
64
|
-
nautobot-server invalidate dcim.Device
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Finally, calling it with the `all` argument will force invalidation of the entire cache database:
|
|
68
|
-
|
|
69
|
-
```no-highlight
|
|
70
|
-
nautobot-server invalidate all
|
|
71
|
-
```
|
|
72
|
-
|
|
73
30
|
## High Availability Caching
|
|
74
31
|
|
|
75
|
-
[Redis](https://redis.io/) provides two different methods to achieve high availability: The first is [Redis Sentinel](https://redis.io/topics/sentinel) and the second is the newer [Redis Clustering](https://redis.io/topics/cluster-tutorial) feature.
|
|
32
|
+
[Redis](https://redis.io/) provides two different methods to achieve high availability: The first is [Redis Sentinel](https://redis.io/topics/sentinel) and the second is the newer [Redis Clustering](https://redis.io/topics/cluster-tutorial) feature. Currently, Nautobot only supports Redis Sentinel for high availability.
|
|
76
33
|
|
|
77
34
|
### Using Redis Sentinel
|
|
78
35
|
|
|
79
36
|
The installation/configuration of the [Redis Sentinel](https://redis.io/topics/sentinel) cluster itself is outside the scope of this document, this section is intended to provide the steps necessary to configure Nautobot to connect to a Sentinel cluster.
|
|
80
37
|
|
|
81
|
-
We need to configure `django-redis
|
|
38
|
+
We need to configure `django-redis` and `celery` to use Sentinel. Each library is configured differently, so please pay close attention to the details.
|
|
82
39
|
|
|
83
40
|
#### `django-redis` Sentinel Configuration
|
|
84
41
|
|
|
@@ -117,44 +74,6 @@ CACHES = {
|
|
|
117
74
|
|
|
118
75
|
For more details on configuring django-redis with Redis Sentinel, please see the documentation for [Django Redis](https://github.com/jazzband/django-redis#use-the-sentinel-connection-factory).
|
|
119
76
|
|
|
120
|
-
#### `django-cacheops` Sentinel Configuration
|
|
121
|
-
|
|
122
|
-
Notable settings:
|
|
123
|
-
|
|
124
|
-
* `locations`: List of tuples or tuple of tuples with each inner tuple containing the name or IP address
|
|
125
|
-
of the Redis server and port for each sentinel instance to connect to
|
|
126
|
-
* `service_name`: the master/service name in redis sentinel
|
|
127
|
-
* Additional parameters may be specified in the `CACHEOPS_SENTINEL` dictionary which are passed directly to Sentinel
|
|
128
|
-
|
|
129
|
-
!!! note
|
|
130
|
-
`locations` for `django-cacheops` has a different meaning than the `LOCATION` value for `django-redis`
|
|
131
|
-
|
|
132
|
-
!!! warning
|
|
133
|
-
[`CACHEOPS_REDIS`](../configuration/required-settings.md#cacheops_redis) and [`CACHEOPS_SENTINEL`](../configuration/required-settings.md#cacheops_sentinel) are mutually exclusive and will result in an error if both are set.
|
|
134
|
-
|
|
135
|
-
Example:
|
|
136
|
-
|
|
137
|
-
```python
|
|
138
|
-
CACHEOPS_REDIS = False
|
|
139
|
-
CACHEOPS_SENTINEL = {
|
|
140
|
-
"db": 1,
|
|
141
|
-
"locations": [
|
|
142
|
-
("mysentinel.redis.example.com", 26379),
|
|
143
|
-
("othersentinel.redis.example.com", 26379),
|
|
144
|
-
("thirdsentinel.redis.example.com", 26379)
|
|
145
|
-
],
|
|
146
|
-
"service_name": "nautobot",
|
|
147
|
-
"socket_timeout": 10,
|
|
148
|
-
"sentinel_kwargs": {
|
|
149
|
-
"password": ""
|
|
150
|
-
},
|
|
151
|
-
"password": "",
|
|
152
|
-
# Everything else is passed to `Sentinel()`
|
|
153
|
-
}
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
For more details on how to configure Cacheops to use Redis Sentinel see the documentation for [Cacheops setup](https://github.com/Suor/django-cacheops#setup).
|
|
157
|
-
|
|
158
77
|
#### `celery` Sentinel Configuration
|
|
159
78
|
|
|
160
79
|
!!! note
|
|
@@ -43,6 +43,9 @@ For custom interval, a `crontab` parameter must be added.
|
|
|
43
43
|
|
|
44
44
|
Jobs that have `approval_required` set to `True` on their `Meta` object require another user to approve a scheduled job.
|
|
45
45
|
|
|
46
|
+
!!! warning
|
|
47
|
+
Requiring approval for execution of Job Hooks by setting the `Meta.approval_required` attribute to `True` on your `JobHookReceiver` subclass is not supported. The value of this attribute will be ignored. Support for requiring approval of Job Hooks will be added in a future release.
|
|
48
|
+
|
|
46
49
|
Scheduled jobs can be approved or denied via the UI and API by any user that has the `extras.approve_job` permission for the job in question, as well as the appropriate `extras.change_scheduledjob` and/or `extras.delete_scheduledjob` permissions.
|
|
47
50
|
|
|
48
51
|
+/- 1.3.0
|