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.
Files changed (780) hide show
  1. nautobot/apps/api.py +6 -8
  2. nautobot/apps/forms.py +0 -2
  3. nautobot/apps/ui.py +0 -8
  4. nautobot/circuits/api/serializers.py +9 -117
  5. nautobot/circuits/api/urls.py +1 -1
  6. nautobot/circuits/api/views.py +0 -1
  7. nautobot/circuits/forms.py +0 -65
  8. nautobot/circuits/migrations/0014_related_name_changes.py +1 -1
  9. nautobot/circuits/migrations/0016_tagsfield.py +34 -0
  10. nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
  11. nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
  12. nautobot/circuits/models.py +3 -87
  13. nautobot/circuits/navigation.py +14 -69
  14. nautobot/circuits/signals.py +0 -2
  15. nautobot/circuits/tables.py +39 -1
  16. nautobot/circuits/tests/integration/test_relationships.py +9 -9
  17. nautobot/circuits/tests/test_api.py +4 -8
  18. nautobot/circuits/tests/test_filters.py +10 -4
  19. nautobot/circuits/tests/test_models.py +5 -1
  20. nautobot/circuits/tests/test_views.py +27 -5
  21. nautobot/circuits/views.py +18 -10
  22. nautobot/core/api/__init__.py +8 -2
  23. nautobot/core/api/fields.py +15 -6
  24. nautobot/core/api/filter_backends.py +3 -2
  25. nautobot/core/api/metadata.py +237 -30
  26. nautobot/core/api/mixins.py +94 -0
  27. nautobot/core/api/pagination.py +4 -0
  28. nautobot/core/api/parsers.py +154 -0
  29. nautobot/core/api/renderers.py +153 -2
  30. nautobot/core/api/schema.py +46 -2
  31. nautobot/core/api/serializers.py +377 -35
  32. nautobot/core/api/urls.py +11 -3
  33. nautobot/core/api/utils.py +174 -2
  34. nautobot/core/api/versioning.py +32 -10
  35. nautobot/core/api/views.py +266 -72
  36. nautobot/core/apps/__init__.py +138 -220
  37. nautobot/core/celery/__init__.py +112 -41
  38. nautobot/core/celery/backends.py +19 -12
  39. nautobot/core/celery/control.py +46 -0
  40. nautobot/core/celery/encoders.py +53 -0
  41. nautobot/core/celery/log.py +38 -0
  42. nautobot/core/celery/schedulers.py +23 -4
  43. nautobot/core/celery/task.py +1 -16
  44. nautobot/core/checks.py +0 -27
  45. nautobot/core/choices.py +0 -113
  46. nautobot/core/{cli.py → cli/__init__.py} +1 -1
  47. nautobot/core/cli/__main__.py +3 -0
  48. nautobot/core/constants.py +0 -24
  49. nautobot/core/context_processors.py +12 -0
  50. nautobot/core/filters.py +2 -2
  51. nautobot/core/forms/__init__.py +0 -4
  52. nautobot/core/forms/fields.py +38 -65
  53. nautobot/core/forms/forms.py +4 -1
  54. nautobot/core/forms/utils.py +0 -52
  55. nautobot/core/graphql/schema.py +4 -27
  56. nautobot/core/jobs/__init__.py +75 -0
  57. nautobot/core/management/commands/build_ui.py +255 -0
  58. nautobot/core/management/commands/generate_test_data.py +3 -2
  59. nautobot/core/management/commands/post_upgrade.py +24 -24
  60. nautobot/core/models/__init__.py +26 -1
  61. nautobot/core/models/fields.py +24 -5
  62. nautobot/core/models/generics.py +2 -42
  63. nautobot/core/models/managers.py +5 -0
  64. nautobot/core/models/name_color_content_types.py +0 -14
  65. nautobot/core/models/tree_queries.py +14 -4
  66. nautobot/core/models/utils.py +5 -6
  67. nautobot/core/models/validators.py +17 -8
  68. nautobot/core/releases.py +8 -10
  69. nautobot/core/settings.py +80 -42
  70. nautobot/core/tables.py +5 -5
  71. nautobot/core/tasks.py +4 -7
  72. nautobot/core/templates/base.html +1 -49
  73. nautobot/core/templates/base_django.html +49 -0
  74. nautobot/core/templates/base_react.html +55 -0
  75. nautobot/core/templates/buttons/export.html +6 -4
  76. nautobot/core/templates/generic/object_bulk_create.html +10 -21
  77. nautobot/core/templates/generic/object_list.html +3 -1
  78. nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
  79. nautobot/core/templates/inc/footer.html +1 -0
  80. nautobot/core/templates/inc/javascript.html +0 -14
  81. nautobot/core/templates/inc/nav_menu.html +28 -33
  82. nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
  83. nautobot/core/templates/inc/relationships_table_rows.html +2 -2
  84. nautobot/core/templates/nautobot_config.py.j2 +8 -20
  85. nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
  86. nautobot/core/templates/rest_framework/api.html +8 -0
  87. nautobot/core/templatetags/buttons.py +32 -28
  88. nautobot/core/testing/__init__.py +47 -44
  89. nautobot/core/testing/api.py +362 -47
  90. nautobot/core/testing/filters.py +1 -1
  91. nautobot/core/testing/migrations.py +2 -0
  92. nautobot/core/testing/mixins.py +22 -9
  93. nautobot/core/testing/schema.py +2 -1
  94. nautobot/core/testing/views.py +21 -46
  95. nautobot/core/tests/integration/test_filters.py +17 -8
  96. nautobot/core/tests/integration/test_navbar.py +11 -34
  97. nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
  98. nautobot/core/tests/nautobot_config.py +2 -3
  99. nautobot/core/tests/test_api.py +290 -21
  100. nautobot/core/tests/test_checks.py +0 -7
  101. nautobot/core/tests/test_filters.py +107 -59
  102. nautobot/core/tests/test_forms.py +26 -92
  103. nautobot/core/tests/test_graphql.py +110 -77
  104. nautobot/core/tests/test_logging.py +4 -0
  105. nautobot/core/tests/test_managers.py +3 -1
  106. nautobot/core/tests/test_models.py +2 -0
  107. nautobot/core/tests/test_paginator.py +3 -1
  108. nautobot/core/tests/test_releases.py +12 -12
  109. nautobot/core/tests/test_templatetags_helpers.py +4 -4
  110. nautobot/core/tests/test_utils.py +32 -68
  111. nautobot/core/tests/test_views.py +12 -15
  112. nautobot/core/utils/data.py +17 -0
  113. nautobot/core/utils/deprecation.py +9 -6
  114. nautobot/core/utils/filtering.py +8 -3
  115. nautobot/core/utils/git.py +12 -4
  116. nautobot/core/utils/lookup.py +3 -1
  117. nautobot/core/utils/requests.py +1 -104
  118. nautobot/core/views/__init__.py +1 -0
  119. nautobot/core/views/generic.py +75 -110
  120. nautobot/core/views/mixins.py +52 -61
  121. nautobot/core/views/renderers.py +6 -7
  122. nautobot/core/views/utils.py +80 -0
  123. nautobot/dcim/api/serializers.py +160 -667
  124. nautobot/dcim/api/urls.py +1 -1
  125. nautobot/dcim/api/views.py +7 -44
  126. nautobot/dcim/choices.py +2 -0
  127. nautobot/dcim/filters/__init__.py +21 -0
  128. nautobot/dcim/form_mixins.py +1 -27
  129. nautobot/dcim/forms.py +19 -765
  130. nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -1
  131. nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -13
  132. nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -1
  133. nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -1
  134. nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
  135. nautobot/dcim/migrations/0035_related_name_changes.py +1 -1
  136. nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -1
  137. nautobot/dcim/migrations/0040_tagsfield.py +109 -0
  138. nautobot/dcim/migrations/{0040_ipam__namespaces.py → 0041_ipam__namespaces.py} +1 -1
  139. nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
  140. nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
  141. nautobot/dcim/models/cables.py +3 -33
  142. nautobot/dcim/models/device_component_templates.py +6 -0
  143. nautobot/dcim/models/device_components.py +12 -198
  144. nautobot/dcim/models/devices.py +30 -143
  145. nautobot/dcim/models/locations.py +3 -64
  146. nautobot/dcim/models/power.py +3 -50
  147. nautobot/dcim/models/racks.py +7 -84
  148. nautobot/dcim/navigation.py +141 -467
  149. nautobot/dcim/signals.py +0 -2
  150. nautobot/dcim/tables/locations.py +2 -2
  151. nautobot/dcim/tables/power.py +1 -2
  152. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
  153. nautobot/dcim/templates/dcim/devicetype.html +2 -2
  154. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
  155. nautobot/dcim/templates/dcim/location.html +16 -1
  156. nautobot/dcim/templates/dcim/locationtype.html +15 -0
  157. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
  158. nautobot/dcim/templates/dcim/rackgroup.html +0 -12
  159. nautobot/dcim/tests/test_api.py +166 -81
  160. nautobot/dcim/tests/test_cablepaths.py +41 -35
  161. nautobot/dcim/tests/test_filters.py +67 -23
  162. nautobot/dcim/tests/test_forms.py +5 -205
  163. nautobot/dcim/tests/test_graphql.py +7 -2
  164. nautobot/dcim/tests/test_migrations.py +6 -11
  165. nautobot/dcim/tests/test_models.py +182 -110
  166. nautobot/dcim/tests/test_natural_ordering.py +11 -8
  167. nautobot/dcim/tests/test_signals.py +6 -3
  168. nautobot/dcim/tests/test_views.py +197 -175
  169. nautobot/dcim/urls.py +11 -16
  170. nautobot/dcim/views.py +7 -134
  171. nautobot/docs/additional-features/caching.md +6 -87
  172. nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
  173. nautobot/docs/additional-features/jobs.md +177 -195
  174. nautobot/docs/administration/nautobot-server.md +6 -21
  175. nautobot/docs/administration/replicating-nautobot.md +0 -10
  176. nautobot/docs/configuration/optional-settings.md +32 -41
  177. nautobot/docs/configuration/required-settings.md +11 -52
  178. nautobot/docs/development/application-registry.md +2 -13
  179. nautobot/docs/development/extending-models.md +15 -17
  180. nautobot/docs/development/generic-views.md +0 -2
  181. nautobot/docs/development/getting-started.md +55 -5
  182. nautobot/docs/development/navigation-menu.md +22 -93
  183. nautobot/docs/development/react-ui.md +105 -0
  184. nautobot/docs/development/role-internals.md +1 -3
  185. nautobot/docs/development/style-guide.md +6 -4
  186. nautobot/docs/index.md +3 -2
  187. nautobot/docs/installation/migrating-from-netbox.md +11 -42
  188. nautobot/docs/installation/nautobot.md +1 -1
  189. nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  190. nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  191. nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  192. nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  193. nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
  194. nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  195. nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  196. nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  197. nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  198. nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  199. nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  200. nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  201. nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  202. nautobot/docs/installation/upgrading-from-nautobot-v1.md +170 -747
  203. nautobot/docs/models/dcim/device.md +3 -0
  204. nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
  205. nautobot/docs/models/extras/computedfield.md +4 -4
  206. nautobot/docs/models/extras/gitrepository.md +3 -0
  207. nautobot/docs/models/extras/job.md +1 -0
  208. nautobot/docs/models/extras/jobbutton.md +18 -13
  209. nautobot/docs/models/extras/jobhook.md +7 -4
  210. nautobot/docs/models/extras/jobresult.md +6 -2
  211. nautobot/docs/models/extras/relationship.md +2 -2
  212. nautobot/docs/models/extras/status.md +6 -19
  213. nautobot/docs/models/ipam/ipaddress.md +3 -0
  214. nautobot/docs/models/virtualization/virtualmachine.md +3 -0
  215. nautobot/docs/plugins/development.md +83 -21
  216. nautobot/docs/release-notes/version-1.5.md +53 -0
  217. nautobot/docs/release-notes/version-2.0.md +180 -0
  218. nautobot/docs/requirements.txt +1 -0
  219. nautobot/docs/rest-api/overview.md +384 -215
  220. nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
  221. nautobot/extras/admin.py +3 -5
  222. nautobot/extras/api/customfields.py +15 -39
  223. nautobot/extras/api/fields.py +0 -11
  224. nautobot/extras/api/mixins.py +45 -0
  225. nautobot/extras/api/relationships.py +63 -158
  226. nautobot/extras/api/serializers.py +165 -700
  227. nautobot/extras/api/urls.py +1 -1
  228. nautobot/extras/api/views.py +294 -280
  229. nautobot/extras/apps.py +4 -7
  230. nautobot/extras/choices.py +11 -9
  231. nautobot/extras/constants.py +9 -3
  232. nautobot/extras/datasources/__init__.py +2 -0
  233. nautobot/extras/datasources/git.py +135 -186
  234. nautobot/extras/datasources/registry.py +25 -35
  235. nautobot/extras/filters/__init__.py +20 -19
  236. nautobot/extras/filters/mixins.py +4 -4
  237. nautobot/extras/forms/forms.py +63 -127
  238. nautobot/extras/forms/mixins.py +23 -51
  239. nautobot/extras/health_checks.py +0 -33
  240. nautobot/extras/jobs.py +387 -565
  241. nautobot/extras/management/commands/runjob.py +24 -62
  242. nautobot/extras/managers.py +30 -7
  243. nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
  244. nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -1
  245. nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -1
  246. nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -7
  247. nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -32
  248. nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -1
  249. nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -1
  250. nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
  251. nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -1
  252. nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -2
  253. nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -1
  254. 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
  255. nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
  256. nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -1
  257. nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
  258. nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -9
  259. nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -1
  260. nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
  261. nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
  262. 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
  263. nautobot/extras/migrations/{0077_remove_slug.py → 0078_remove_slug.py} +1 -5
  264. nautobot/extras/migrations/0079_tagsfield.py +28 -0
  265. nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
  266. nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
  267. nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
  268. nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
  269. nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
  270. nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
  271. nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
  272. nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
  273. nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
  274. nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
  275. nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
  276. nautobot/extras/models/__init__.py +2 -3
  277. nautobot/extras/models/change_logging.py +0 -36
  278. nautobot/extras/models/customfields.py +39 -33
  279. nautobot/extras/models/datasources.py +48 -50
  280. nautobot/extras/models/groups.py +5 -6
  281. nautobot/extras/models/jobs.py +189 -321
  282. nautobot/extras/models/mixins.py +0 -71
  283. nautobot/extras/models/models.py +0 -19
  284. nautobot/extras/models/relationships.py +19 -13
  285. nautobot/extras/models/roles.py +0 -34
  286. nautobot/extras/models/secrets.py +2 -26
  287. nautobot/extras/models/statuses.py +6 -5
  288. nautobot/extras/models/tags.py +2 -17
  289. nautobot/extras/navigation.py +89 -307
  290. nautobot/extras/plugins/__init__.py +3 -120
  291. nautobot/extras/plugins/utils.py +0 -3
  292. nautobot/extras/plugins/validators.py +5 -4
  293. nautobot/extras/plugins/views.py +16 -3
  294. nautobot/extras/querysets.py +1 -7
  295. nautobot/extras/registry.py +3 -0
  296. nautobot/extras/signals.py +26 -60
  297. nautobot/extras/tables.py +34 -40
  298. nautobot/extras/tasks.py +0 -12
  299. nautobot/extras/templates/extras/configcontext.html +1 -1
  300. nautobot/extras/templates/extras/configcontextschema.html +16 -1
  301. nautobot/extras/templates/extras/customfield.html +0 -13
  302. nautobot/extras/templates/extras/gitrepository.html +3 -3
  303. nautobot/extras/templates/extras/inc/jobresult.html +10 -0
  304. nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
  305. nautobot/extras/templates/extras/job.html +35 -25
  306. nautobot/extras/templates/extras/job_approval_request.html +15 -30
  307. nautobot/extras/templates/extras/job_detail.html +13 -31
  308. nautobot/extras/templates/extras/job_edit.html +15 -17
  309. nautobot/extras/templates/extras/jobresult.html +24 -6
  310. nautobot/extras/templates/extras/scheduledjob.html +2 -2
  311. nautobot/extras/templates/extras/secret.html +28 -0
  312. nautobot/extras/templatetags/job_buttons.py +1 -0
  313. nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
  314. nautobot/extras/test_jobs/atomic_transaction.py +53 -0
  315. nautobot/extras/test_jobs/dry_run.py +29 -0
  316. nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
  317. nautobot/extras/test_jobs/duplicate_name2.py +9 -0
  318. nautobot/extras/test_jobs/fail.py +23 -0
  319. nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
  320. nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
  321. nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
  322. nautobot/extras/test_jobs/file_upload_pass.py +25 -0
  323. nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
  324. nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
  325. nautobot/extras/test_jobs/job_button_receiver.py +28 -0
  326. nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
  327. nautobot/extras/test_jobs/job_variables.py +88 -0
  328. nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
  329. nautobot/extras/test_jobs/log_redaction.py +20 -0
  330. nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
  331. nautobot/extras/test_jobs/modify_db.py +25 -0
  332. nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
  333. nautobot/extras/test_jobs/object_var_optional.py +21 -0
  334. nautobot/extras/test_jobs/object_var_required.py +21 -0
  335. nautobot/extras/test_jobs/object_vars.py +26 -0
  336. nautobot/extras/test_jobs/pass.py +25 -0
  337. nautobot/extras/test_jobs/profiling.py +32 -0
  338. nautobot/extras/test_jobs/read_only_job.py +15 -0
  339. nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
  340. 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
  341. nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
  342. nautobot/extras/tests/integration/test_computedfields.py +1 -1
  343. nautobot/extras/tests/integration/test_configcontextschema.py +5 -3
  344. nautobot/extras/tests/integration/test_customfields.py +4 -2
  345. nautobot/extras/tests/integration/test_dynamicgroups.py +1 -1
  346. nautobot/extras/tests/integration/test_jobs.py +25 -27
  347. nautobot/extras/tests/integration/test_notes.py +8 -4
  348. nautobot/extras/tests/integration/test_relationships.py +2 -2
  349. nautobot/extras/tests/test_api.py +649 -642
  350. nautobot/extras/tests/test_changelog.py +3 -3
  351. nautobot/extras/tests/test_context_managers.py +5 -3
  352. nautobot/extras/tests/test_customfields.py +92 -50
  353. nautobot/extras/tests/test_datasources.py +189 -112
  354. nautobot/extras/tests/test_dynamicgroups.py +7 -8
  355. nautobot/extras/tests/test_filters.py +137 -89
  356. nautobot/extras/tests/test_forms.py +73 -75
  357. nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
  358. nautobot/extras/tests/test_jobs.py +262 -263
  359. nautobot/extras/tests/test_migrations.py +4 -3
  360. nautobot/extras/tests/test_models.py +116 -161
  361. nautobot/extras/tests/test_plugins.py +38 -60
  362. nautobot/extras/tests/test_relationships.py +167 -120
  363. nautobot/extras/tests/test_tags.py +6 -11
  364. nautobot/extras/tests/test_utils.py +31 -1
  365. nautobot/extras/tests/test_views.py +201 -145
  366. nautobot/extras/tests/test_webhooks.py +6 -2
  367. nautobot/extras/urls.py +42 -42
  368. nautobot/extras/utils.py +137 -163
  369. nautobot/extras/views.py +78 -152
  370. nautobot/ipam/api/fields.py +17 -0
  371. nautobot/ipam/api/serializers.py +58 -164
  372. nautobot/ipam/api/urls.py +1 -1
  373. nautobot/ipam/api/views.py +3 -2
  374. nautobot/ipam/apps.py +1 -2
  375. nautobot/ipam/filters.py +1 -10
  376. nautobot/ipam/forms.py +4 -177
  377. nautobot/ipam/lookups.py +1 -0
  378. nautobot/ipam/management/commands/__init__.py +0 -0
  379. nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
  380. nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -1
  381. nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -38
  382. nautobot/ipam/migrations/0020_related_name_changes.py +1 -1
  383. nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +2 -2
  384. nautobot/ipam/migrations/0028_tagsfield.py +44 -0
  385. nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
  386. nautobot/ipam/migrations/{0028_ipam__namespaces.py → 0030_ipam__namespaces.py} +77 -28
  387. nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
  388. nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
  389. nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
  390. nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
  391. nautobot/ipam/models.py +100 -236
  392. nautobot/ipam/navigation.py +36 -181
  393. nautobot/ipam/querysets.py +20 -25
  394. nautobot/ipam/signals.py +49 -6
  395. nautobot/ipam/tables.py +10 -3
  396. nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
  397. nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
  398. nautobot/ipam/templates/ipam/namespace_retrieve.html +17 -4
  399. nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
  400. nautobot/ipam/templates/ipam/prefix.html +1 -1
  401. nautobot/ipam/templates/ipam/vlangroup.html +0 -13
  402. nautobot/ipam/templates/ipam/vrf_edit.html +6 -0
  403. nautobot/ipam/tests/integration/test_prefixes.py +3 -26
  404. nautobot/ipam/tests/test_api.py +22 -19
  405. nautobot/ipam/tests/test_filters.py +59 -23
  406. nautobot/ipam/tests/test_migrations.py +6 -10
  407. nautobot/ipam/tests/test_models.py +323 -198
  408. nautobot/ipam/tests/test_ordering.py +2 -2
  409. nautobot/ipam/tests/test_querysets.py +44 -24
  410. nautobot/ipam/tests/test_views.py +73 -26
  411. nautobot/ipam/urls.py +16 -0
  412. nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
  413. nautobot/ipam/utils/migrations.py +713 -0
  414. nautobot/ipam/views.py +137 -20
  415. nautobot/project-static/docs/404.html +1178 -10
  416. nautobot/project-static/docs/additional-features/caching.html +1224 -159
  417. nautobot/project-static/docs/additional-features/change-logging.html +1180 -12
  418. nautobot/project-static/docs/additional-features/config-contexts.html +1180 -12
  419. nautobot/project-static/docs/additional-features/graphql.html +1179 -11
  420. nautobot/project-static/docs/additional-features/healthcheck.html +1180 -12
  421. nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1184 -12
  422. nautobot/project-static/docs/additional-features/jobs.html +1514 -328
  423. nautobot/project-static/docs/additional-features/napalm.html +1180 -12
  424. nautobot/project-static/docs/additional-features/prometheus-metrics.html +1180 -12
  425. nautobot/project-static/docs/additional-features/template-filters.html +1180 -12
  426. nautobot/project-static/docs/administration/celery-queues.html +1178 -10
  427. nautobot/project-static/docs/administration/nautobot-server.html +1451 -304
  428. nautobot/project-static/docs/administration/nautobot-shell.html +1178 -10
  429. nautobot/project-static/docs/administration/permissions.html +1178 -10
  430. nautobot/project-static/docs/administration/replicating-nautobot.html +1262 -113
  431. nautobot/project-static/docs/apps/index.html +1178 -10
  432. nautobot/project-static/docs/apps/nautobot-apps.html +1178 -10
  433. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1580 -426
  434. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1178 -10
  435. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3481 -1838
  436. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1178 -10
  437. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1178 -10
  438. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1185 -11
  439. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1719 -551
  440. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2062 -930
  441. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +1946 -659
  442. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1180 -12
  443. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1189 -21
  444. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +9283 -6218
  445. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2734 -2122
  446. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1178 -10
  447. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2337 -1300
  448. nautobot/project-static/docs/configuration/authentication/ldap.html +1178 -10
  449. nautobot/project-static/docs/configuration/authentication/remote.html +1178 -10
  450. nautobot/project-static/docs/configuration/authentication/sso.html +1178 -10
  451. nautobot/project-static/docs/configuration/index.html +1178 -10
  452. nautobot/project-static/docs/configuration/optional-settings.html +1311 -160
  453. nautobot/project-static/docs/configuration/required-settings.html +1312 -211
  454. nautobot/project-static/docs/core-functionality/circuits.html +1178 -10
  455. nautobot/project-static/docs/core-functionality/device-types.html +1178 -10
  456. nautobot/project-static/docs/core-functionality/devices.html +1182 -10
  457. nautobot/project-static/docs/core-functionality/ipam.html +1182 -10
  458. nautobot/project-static/docs/core-functionality/power.html +1178 -10
  459. nautobot/project-static/docs/core-functionality/secrets.html +1178 -10
  460. nautobot/project-static/docs/core-functionality/services.html +1178 -10
  461. nautobot/project-static/docs/core-functionality/sites-and-racks.html +1178 -10
  462. nautobot/project-static/docs/core-functionality/tenancy.html +1178 -10
  463. nautobot/project-static/docs/core-functionality/virtualization.html +1182 -10
  464. nautobot/project-static/docs/core-functionality/vlans.html +1179 -11
  465. nautobot/project-static/docs/development/application-registry.html +1190 -42
  466. nautobot/project-static/docs/development/best-practices.html +1178 -10
  467. nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1178 -10
  468. nautobot/project-static/docs/development/extending-models.html +1238 -83
  469. nautobot/project-static/docs/development/generic-views.html +1180 -14
  470. nautobot/project-static/docs/development/getting-started.html +1365 -90
  471. nautobot/project-static/docs/development/homepage.html +1178 -10
  472. nautobot/project-static/docs/development/index.html +1178 -10
  473. nautobot/project-static/docs/development/model-features.html +1178 -10
  474. nautobot/project-static/docs/development/natural-keys.html +1178 -10
  475. nautobot/project-static/docs/development/navigation-menu.html +1215 -125
  476. nautobot/project-static/docs/development/react-ui.html +4199 -0
  477. nautobot/project-static/docs/development/release-checklist.html +1178 -10
  478. nautobot/project-static/docs/development/role-internals.html +1179 -12
  479. nautobot/project-static/docs/development/style-guide.html +1188 -19
  480. nautobot/project-static/docs/development/templates.html +1178 -10
  481. nautobot/project-static/docs/development/testing.html +1178 -10
  482. nautobot/project-static/docs/development/user-preferences.html +1178 -10
  483. nautobot/project-static/docs/docker/index.html +1178 -10
  484. nautobot/project-static/docs/index.html +1183 -12
  485. nautobot/project-static/docs/installation/centos.html +1178 -10
  486. nautobot/project-static/docs/installation/external-authentication.html +1178 -10
  487. nautobot/project-static/docs/installation/http-server.html +1178 -10
  488. nautobot/project-static/docs/installation/index.html +1178 -10
  489. nautobot/project-static/docs/installation/migrating-from-netbox.html +1305 -189
  490. nautobot/project-static/docs/installation/migrating-from-postgresql.html +1178 -10
  491. nautobot/project-static/docs/installation/nautobot.html +1179 -11
  492. nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1178 -10
  493. nautobot/project-static/docs/installation/selinux-troubleshooting.html +1178 -10
  494. nautobot/project-static/docs/installation/services.html +1178 -10
  495. nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  496. nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  497. nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  498. nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  499. nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
  500. nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  501. nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  502. nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  503. nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  504. nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  505. nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  506. nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  507. nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  508. nautobot/project-static/docs/installation/ubuntu.html +1178 -10
  509. nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +3823 -2152
  510. nautobot/project-static/docs/installation/upgrading.html +1178 -10
  511. nautobot/project-static/docs/models/circuits/circuit.html +1293 -103
  512. nautobot/project-static/docs/models/circuits/circuittermination.html +1293 -103
  513. nautobot/project-static/docs/models/circuits/circuittype.html +1293 -103
  514. nautobot/project-static/docs/models/circuits/provider.html +1293 -103
  515. nautobot/project-static/docs/models/circuits/providernetwork.html +1293 -103
  516. nautobot/project-static/docs/models/dcim/cable.html +1324 -103
  517. nautobot/project-static/docs/models/dcim/consoleport.html +1293 -103
  518. nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1293 -103
  519. nautobot/project-static/docs/models/dcim/consoleserverport.html +1293 -103
  520. nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1293 -103
  521. nautobot/project-static/docs/models/dcim/device.html +1326 -132
  522. nautobot/project-static/docs/models/dcim/devicebay.html +1293 -103
  523. nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1293 -103
  524. nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1379 -97
  525. nautobot/project-static/docs/models/dcim/devicetype.html +1293 -103
  526. nautobot/project-static/docs/models/dcim/frontport.html +1293 -103
  527. nautobot/project-static/docs/models/dcim/frontporttemplate.html +1293 -103
  528. nautobot/project-static/docs/models/dcim/interface.html +1293 -103
  529. nautobot/project-static/docs/models/dcim/interfacetemplate.html +1293 -103
  530. nautobot/project-static/docs/models/dcim/inventoryitem.html +1293 -103
  531. nautobot/project-static/docs/models/dcim/location.html +1293 -103
  532. nautobot/project-static/docs/models/dcim/locationtype.html +1293 -103
  533. nautobot/project-static/docs/models/dcim/manufacturer.html +1292 -102
  534. nautobot/project-static/docs/models/dcim/platform.html +1272 -82
  535. nautobot/project-static/docs/models/dcim/powerfeed.html +1270 -80
  536. nautobot/project-static/docs/models/dcim/poweroutlet.html +1272 -82
  537. nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1272 -82
  538. nautobot/project-static/docs/models/dcim/powerpanel.html +1270 -80
  539. nautobot/project-static/docs/models/dcim/powerport.html +1272 -82
  540. nautobot/project-static/docs/models/dcim/powerporttemplate.html +1272 -82
  541. nautobot/project-static/docs/models/dcim/rack.html +1272 -82
  542. nautobot/project-static/docs/models/dcim/rackgroup.html +1272 -82
  543. nautobot/project-static/docs/models/dcim/rackreservation.html +1272 -82
  544. nautobot/project-static/docs/models/dcim/rearport.html +1286 -96
  545. nautobot/project-static/docs/models/dcim/rearporttemplate.html +1286 -96
  546. nautobot/project-static/docs/models/dcim/region.html +1178 -10
  547. nautobot/project-static/docs/models/dcim/site.html +1178 -10
  548. nautobot/project-static/docs/models/dcim/virtualchassis.html +1284 -94
  549. nautobot/project-static/docs/models/extras/computedfield.html +1184 -16
  550. nautobot/project-static/docs/models/extras/configcontext.html +1314 -86
  551. nautobot/project-static/docs/models/extras/configcontextschema.html +1276 -86
  552. nautobot/project-static/docs/models/extras/customfield.html +1180 -12
  553. nautobot/project-static/docs/models/extras/customlink.html +1180 -12
  554. nautobot/project-static/docs/models/extras/dynamicgroup.html +1180 -12
  555. nautobot/project-static/docs/models/extras/exporttemplate.html +1180 -12
  556. nautobot/project-static/docs/models/extras/gitrepository.html +1184 -12
  557. nautobot/project-static/docs/models/extras/graphqlquery.html +1321 -86
  558. nautobot/project-static/docs/models/extras/imageattachment.html +1276 -86
  559. nautobot/project-static/docs/models/extras/job.html +1277 -86
  560. nautobot/project-static/docs/models/extras/jobbutton.html +1201 -29
  561. nautobot/project-static/docs/models/extras/jobhook.html +1188 -16
  562. nautobot/project-static/docs/models/extras/joblogentry.html +1274 -84
  563. nautobot/project-static/docs/models/extras/jobresult.html +1364 -169
  564. nautobot/project-static/docs/models/extras/note.html +1180 -12
  565. nautobot/project-static/docs/models/extras/relationship.html +1182 -14
  566. nautobot/project-static/docs/models/extras/role.html +1320 -86
  567. nautobot/project-static/docs/models/extras/secret.html +1314 -86
  568. nautobot/project-static/docs/models/extras/secretsgroup.html +1276 -86
  569. nautobot/project-static/docs/models/extras/status.html +1188 -59
  570. nautobot/project-static/docs/models/extras/tag.html +1180 -12
  571. nautobot/project-static/docs/models/extras/webhook.html +1180 -12
  572. nautobot/project-static/docs/models/ipam/ipaddress.html +1327 -102
  573. nautobot/project-static/docs/models/ipam/prefix.html +1276 -86
  574. nautobot/project-static/docs/models/ipam/rir.html +1276 -86
  575. nautobot/project-static/docs/models/ipam/routetarget.html +1276 -86
  576. nautobot/project-static/docs/models/ipam/service.html +1276 -86
  577. nautobot/project-static/docs/models/ipam/vlan.html +1276 -86
  578. nautobot/project-static/docs/models/ipam/vlangroup.html +1276 -86
  579. nautobot/project-static/docs/models/ipam/vrf.html +1276 -86
  580. nautobot/project-static/docs/models/tenancy/tenant.html +1276 -86
  581. nautobot/project-static/docs/models/tenancy/tenantgroup.html +1276 -86
  582. nautobot/project-static/docs/models/users/objectpermission.html +1314 -86
  583. nautobot/project-static/docs/models/users/token.html +1276 -86
  584. nautobot/project-static/docs/models/virtualization/cluster.html +1276 -86
  585. nautobot/project-static/docs/models/virtualization/clustergroup.html +1276 -86
  586. nautobot/project-static/docs/models/virtualization/clustertype.html +1276 -86
  587. nautobot/project-static/docs/models/virtualization/virtualmachine.html +1321 -127
  588. nautobot/project-static/docs/models/virtualization/vminterface.html +1276 -86
  589. nautobot/project-static/docs/objects.inv +0 -0
  590. nautobot/project-static/docs/plugins/development.html +1726 -495
  591. nautobot/project-static/docs/plugins/index.html +1178 -10
  592. nautobot/project-static/docs/plugins/porting-from-netbox.html +1178 -10
  593. nautobot/project-static/docs/release-notes/index.html +1178 -10
  594. nautobot/project-static/docs/release-notes/version-1.0.html +1178 -10
  595. nautobot/project-static/docs/release-notes/version-1.1.html +1178 -10
  596. nautobot/project-static/docs/release-notes/version-1.2.html +1178 -10
  597. nautobot/project-static/docs/release-notes/version-1.3.html +1178 -10
  598. nautobot/project-static/docs/release-notes/version-1.4.html +1178 -10
  599. nautobot/project-static/docs/release-notes/version-1.5.html +1608 -225
  600. nautobot/project-static/docs/release-notes/version-2.0.html +1547 -47
  601. nautobot/project-static/docs/requirements.txt +1 -0
  602. nautobot/project-static/docs/rest-api/authentication.html +1179 -11
  603. nautobot/project-static/docs/rest-api/filtering.html +1178 -10
  604. nautobot/project-static/docs/rest-api/overview.html +1841 -446
  605. nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
  606. nautobot/project-static/docs/search/search_index.json +1 -1
  607. nautobot/project-static/docs/sitemap.xml +197 -187
  608. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  609. nautobot/project-static/docs/user-guides/custom-fields.html +1178 -10
  610. nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1178 -10
  611. nautobot/project-static/docs/user-guides/getting-started/index.html +1178 -10
  612. nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1178 -10
  613. nautobot/project-static/docs/user-guides/getting-started/ipam.html +1178 -10
  614. nautobot/project-static/docs/user-guides/getting-started/platforms.html +1178 -10
  615. nautobot/project-static/docs/user-guides/getting-started/regions.html +1178 -10
  616. nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1178 -10
  617. nautobot/project-static/docs/user-guides/getting-started/tenants.html +1178 -10
  618. nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1178 -10
  619. nautobot/project-static/docs/user-guides/git-data-source.html +1178 -10
  620. nautobot/project-static/docs/user-guides/graphql.html +1178 -10
  621. nautobot/project-static/docs/user-guides/relationships.html +1178 -10
  622. nautobot/project-static/docs/user-guides/s3-django-storage.html +1178 -10
  623. nautobot/project-static/js/forms.js +16 -9
  624. nautobot/project-static/js/theme.js +5 -0
  625. nautobot/tenancy/api/serializers.py +4 -32
  626. nautobot/tenancy/api/urls.py +1 -1
  627. nautobot/tenancy/forms.py +0 -28
  628. nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
  629. nautobot/tenancy/models.py +0 -25
  630. nautobot/tenancy/navigation.py +6 -39
  631. nautobot/tenancy/templates/tenancy/tenant.html +12 -12
  632. nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
  633. nautobot/tenancy/tests/test_api.py +1 -3
  634. nautobot/tenancy/tests/test_filters.py +10 -5
  635. nautobot/tenancy/views.py +0 -2
  636. nautobot/ui/.eslintignore +6 -0
  637. nautobot/ui/.gitignore +10 -0
  638. nautobot/ui/.prettierignore +9 -0
  639. nautobot/ui/.prettierrc +4 -0
  640. nautobot/ui/README.md +33 -0
  641. nautobot/ui/app_imports.js.j2 +7 -0
  642. nautobot/ui/craco.config.js +46 -0
  643. nautobot/ui/jsconfig-base.json +11 -0
  644. nautobot/ui/jsconfig.json +5 -0
  645. nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
  646. nautobot/ui/package-lock.json +21451 -0
  647. nautobot/ui/package.json +70 -0
  648. nautobot/ui/public/index.html +47 -0
  649. nautobot/ui/public/logo192.png +0 -0
  650. nautobot/ui/public/logo512.png +0 -0
  651. nautobot/ui/public/manifest.json +25 -0
  652. nautobot/ui/public/nautobot_logo.svg +131 -0
  653. nautobot/ui/public/robots.txt +3 -0
  654. nautobot/ui/src/App.js +71 -0
  655. nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
  656. nautobot/ui/src/components/AppTab.js +40 -0
  657. nautobot/ui/src/components/Apps.js +60 -0
  658. nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
  659. nautobot/ui/src/components/HomePanel.js +58 -0
  660. nautobot/ui/src/components/JobHistoryTable.js +78 -0
  661. nautobot/ui/src/components/Layout.js +53 -0
  662. nautobot/ui/src/components/LoadingWidget.js +25 -0
  663. nautobot/ui/src/components/Navbar.js +116 -0
  664. nautobot/ui/src/components/NotificationPopover.js +27 -0
  665. nautobot/ui/src/components/ObjectListTable.js +209 -0
  666. nautobot/ui/src/components/ReferenceDataTag.js +35 -0
  667. nautobot/ui/src/components/RouterButton.js +10 -0
  668. nautobot/ui/src/components/RouterLink.js +10 -0
  669. nautobot/ui/src/components/SidebarNav.js +147 -0
  670. nautobot/ui/src/components/Table.js +48 -0
  671. nautobot/ui/src/components/TableItem.js +71 -0
  672. nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
  673. nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
  674. nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
  675. nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
  676. nautobot/ui/src/components/__tests__/Table.test.js +36 -0
  677. nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
  678. nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
  679. nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
  680. nautobot/ui/src/components/pagination.js +93 -0
  681. nautobot/ui/src/components/paginator.js +79 -0
  682. nautobot/ui/src/components/paginator_form.js +43 -0
  683. nautobot/ui/src/components/usePagination.js +57 -0
  684. nautobot/ui/src/constants/apiPath.js +10 -0
  685. nautobot/ui/src/constants/icons.js +15 -0
  686. nautobot/ui/src/constants/size.js +15 -0
  687. nautobot/ui/src/index.js +65 -0
  688. nautobot/ui/src/reportWebVitals.js +15 -0
  689. nautobot/ui/src/router.js +77 -0
  690. nautobot/ui/src/utils/api.js +131 -0
  691. nautobot/ui/src/utils/app-import.js +15 -0
  692. nautobot/ui/src/utils/color.js +15 -0
  693. nautobot/ui/src/utils/date.js +14 -0
  694. nautobot/ui/src/utils/index.js +15 -0
  695. nautobot/ui/src/utils/navigation.js +32 -0
  696. nautobot/ui/src/utils/session.js +64 -0
  697. nautobot/ui/src/utils/store.js +242 -0
  698. nautobot/ui/src/utils/string.js +6 -0
  699. nautobot/ui/src/utils/url.js +4 -0
  700. nautobot/ui/src/views/Home.js +138 -0
  701. nautobot/ui/src/views/InstalledApps.js +80 -0
  702. nautobot/ui/src/views/Login.js +48 -0
  703. nautobot/ui/src/views/Logout.js +20 -0
  704. nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
  705. nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
  706. nautobot/ui/src/views/__tests__/Login.test.js +15 -0
  707. nautobot/ui/src/views/generic/GenericView.js +142 -0
  708. nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
  709. nautobot/ui/src/views/generic/ObjectList.js +127 -0
  710. nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
  711. nautobot/users/admin.py +1 -1
  712. nautobot/users/api/serializers.py +51 -61
  713. nautobot/users/api/urls.py +1 -1
  714. nautobot/users/api/views.py +53 -2
  715. nautobot/users/tests/test_api.py +110 -25
  716. nautobot/virtualization/api/serializers.py +18 -130
  717. nautobot/virtualization/api/urls.py +1 -1
  718. nautobot/virtualization/api/views.py +1 -22
  719. nautobot/virtualization/forms.py +13 -99
  720. nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -1
  721. nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -11
  722. nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -1
  723. nautobot/virtualization/migrations/0018_related_name_changes.py +1 -1
  724. nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
  725. nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
  726. nautobot/virtualization/migrations/{0021_ipam__namespaces.py → 0023_ipam__namespaces.py} +2 -2
  727. nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
  728. nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
  729. nautobot/virtualization/models.py +31 -123
  730. nautobot/virtualization/navigation.py +18 -99
  731. nautobot/virtualization/templates/virtualization/virtualmachine.html +2 -1
  732. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
  733. nautobot/virtualization/tests/test_api.py +25 -26
  734. nautobot/virtualization/tests/test_filters.py +41 -15
  735. nautobot/virtualization/tests/test_models.py +31 -7
  736. nautobot/virtualization/tests/test_views.py +42 -25
  737. nautobot/virtualization/views.py +7 -6
  738. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +3 -7
  739. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +744 -602
  740. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
  741. nautobot/circuits/api/nested_serializers.py +0 -69
  742. nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
  743. nautobot/dcim/api/nested_serializers.py +0 -356
  744. nautobot/dcim/templates/dcim/device_import.html +0 -5
  745. nautobot/dcim/templates/dcim/device_import_child.html +0 -5
  746. nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
  747. nautobot/extras/api/nested_serializers.py +0 -353
  748. nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -41
  749. nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -46
  750. nautobot/extras/reports.py +0 -60
  751. nautobot/extras/scripts.py +0 -72
  752. nautobot/extras/tests/example_jobs/script_variables.py +0 -67
  753. nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
  754. nautobot/extras/tests/example_jobs/test_fail.py +0 -16
  755. nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
  756. nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
  757. nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
  758. nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
  759. nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
  760. nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
  761. nautobot/extras/tests/example_jobs/test_modify_db.py +0 -18
  762. nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
  763. nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
  764. nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
  765. nautobot/extras/tests/example_jobs/test_pass.py +0 -19
  766. nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
  767. nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
  768. nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
  769. nautobot/ipam/api/nested_serializers.py +0 -159
  770. nautobot/ipam/migrations/0029_ipam__prefix__add_parent.py +0 -31
  771. nautobot/ipam/migrations/0030_ipam__prefix__data_migration.py +0 -13
  772. nautobot/ipam/migrations/0031_ipam__ipaddress__add_parent.py +0 -41
  773. nautobot/ipam/migrations/0032_ipam__ipaddress__data_migration.py +0 -11
  774. nautobot/tenancy/api/nested_serializers.py +0 -31
  775. nautobot/users/api/nested_serializers.py +0 -67
  776. nautobot/virtualization/api/nested_serializers.py +0 -65
  777. /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
  778. /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
  779. {nautobot-2.0.0a3.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
  780. {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/<slug:slug>/", views.LocationTypeView.as_view(), name="locationtype"),
44
- path("location-types/<slug:slug>/edit/", views.LocationTypeEditView.as_view(), name="locationtype_edit"),
45
- path("location-types/<slug:slug>/delete/", views.LocationTypeDeleteView.as_view(), name="locationtype_delete"),
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/<slug:slug>/changelog/",
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/<slug:slug>/notes/",
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/<slug:slug>/", views.LocationView.as_view(), name="location"),
65
- path("locations/<slug:slug>/edit/", views.LocationEditView.as_view(), name="location_edit"),
66
- path("locations/<slug:slug>/delete/", views.LocationDeleteView.as_view(), name="location_delete"),
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/<slug:slug>/changelog/",
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/<slug:slug>/notes/",
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/<slug:slug>/images/add/",
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, namedtuple
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
- CSVRow = namedtuple("CSVRow", ["device", "name", "dest_device", "dest_name", "reachable"])
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
- Nautobot optionally supports database query caching using [`django-cacheops`](https://github.com/Suor/django-cacheops) and Redis. Caching can be enabled by toggling [`CACHEOPS_ENABLED`](../configuration/optional-settings.md#cacheops_enabled) to `True` (it is `False` by default). When caching is enabled, and a query is made, the results are cached in Redis for a short period of time, as defined by the [`CACHEOPS_DEFAULTS`](../configuration/optional-settings.md#cacheops_defaults) parameter (15 minutes by default). Within that time, all recurrences of that specific query will return the pre-fetched results from the cache.
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 with its own [cache framework](https://docs.djangoproject.com/en/stable/topics/cache/) that works for common cases, but does not work well for the wide array of use-cases within Nautobot. For that reason, **Django's built-in caching is not used for the caching of web UI views, API results, and underlying database queries.** Instead, we use [`django-cacheops`](https://github.com/Suor/django-cacheops). Please see below for more on this.
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. You'll observe that, even though we aren't using Django's built-in caching, *we still have this as a required setting*. Here's why:
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. Unfortunately, due to an [known issue with django-cacheops](https://github.com/Suor/django-cacheops/issues/35) (last updated November 2021) Nautobot is unable to support Redis Clustering at this time. Therefore, Nautobot only supports Redis Sentinel for high availability.
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`, `django-cacheops`, and `celery` to use Sentinel. Each library is configured differently, so please pay close attention to the details.
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