nautobot 2.3.16__py3-none-any.whl → 2.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nautobot might be problematic. Click here for more details.

Files changed (721) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/__init__.py +1 -1
  3. nautobot/apps/api.py +8 -10
  4. nautobot/apps/change_logging.py +2 -2
  5. nautobot/apps/choices.py +4 -4
  6. nautobot/apps/config.py +32 -3
  7. nautobot/apps/events.py +19 -0
  8. nautobot/apps/exceptions.py +0 -2
  9. nautobot/apps/factory.py +2 -2
  10. nautobot/apps/filters.py +1 -1
  11. nautobot/apps/forms.py +20 -20
  12. nautobot/apps/graphql.py +2 -2
  13. nautobot/apps/jobs.py +8 -8
  14. nautobot/apps/models.py +19 -19
  15. nautobot/apps/tables.py +1 -1
  16. nautobot/apps/testing.py +10 -10
  17. nautobot/apps/ui.py +44 -9
  18. nautobot/apps/utils.py +7 -15
  19. nautobot/apps/views.py +8 -6
  20. nautobot/circuits/api/serializers.py +1 -0
  21. nautobot/circuits/api/views.py +4 -8
  22. nautobot/circuits/navigation.py +0 -57
  23. nautobot/circuits/templates/circuits/circuit_create.html +1 -7
  24. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  25. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  26. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  27. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  28. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  29. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  30. nautobot/circuits/tests/test_filters.py +4 -8
  31. nautobot/circuits/views.py +140 -23
  32. nautobot/cloud/api/views.py +6 -10
  33. nautobot/cloud/factory.py +4 -1
  34. nautobot/cloud/tests/test_filters.py +5 -4
  35. nautobot/cloud/views.py +0 -16
  36. nautobot/core/api/constants.py +11 -0
  37. nautobot/core/api/filter_backends.py +3 -9
  38. nautobot/core/api/metadata.py +28 -256
  39. nautobot/core/api/pagination.py +3 -2
  40. nautobot/core/api/renderers.py +3 -0
  41. nautobot/core/api/schema.py +13 -2
  42. nautobot/core/api/serializers.py +45 -259
  43. nautobot/core/api/urls.py +3 -4
  44. nautobot/core/api/utils.py +0 -62
  45. nautobot/core/api/views.py +99 -157
  46. nautobot/core/apps/__init__.py +22 -578
  47. nautobot/core/celery/__init__.py +13 -0
  48. nautobot/core/celery/schedulers.py +47 -2
  49. nautobot/core/choices.py +2 -2
  50. nautobot/core/cli/__init__.py +8 -0
  51. nautobot/core/constants.py +7 -0
  52. nautobot/core/events/__init__.py +116 -0
  53. nautobot/core/events/base.py +27 -0
  54. nautobot/core/events/exceptions.py +10 -0
  55. nautobot/core/events/redis_broker.py +48 -0
  56. nautobot/core/events/syslog_broker.py +19 -0
  57. nautobot/core/exceptions.py +0 -6
  58. nautobot/core/forms/__init__.py +19 -19
  59. nautobot/core/forms/fields.py +57 -9
  60. nautobot/core/forms/forms.py +33 -2
  61. nautobot/core/forms/utils.py +2 -1
  62. nautobot/core/graphql/schema.py +3 -1
  63. nautobot/core/jobs/__init__.py +24 -3
  64. nautobot/core/jobs/bulk_actions.py +248 -0
  65. nautobot/core/jobs/cleanup.py +1 -1
  66. nautobot/core/management/commands/generate_test_data.py +21 -0
  67. nautobot/core/middleware.py +16 -0
  68. nautobot/core/models/fields.py +11 -7
  69. nautobot/core/settings.py +68 -4
  70. nautobot/core/settings.yaml +99 -0
  71. nautobot/core/tables.py +10 -46
  72. nautobot/core/tasks.py +1 -1
  73. nautobot/core/templates/about.html +67 -0
  74. nautobot/core/templates/components/button/default.html +7 -0
  75. nautobot/core/templates/components/button/dropdown.html +20 -0
  76. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  77. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  78. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  79. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  80. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  81. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  82. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  83. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  84. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  85. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  86. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  87. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  88. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  89. nautobot/core/templates/components/panel/panel.html +16 -0
  90. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  91. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  92. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  93. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  94. nautobot/core/templates/generic/object_retrieve.html +28 -17
  95. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  96. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  97. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  98. nautobot/core/templates/inc/footer.html +1 -0
  99. nautobot/core/templates/inc/nav_menu.html +2 -1
  100. nautobot/core/templates/inc/relationships_panel.html +1 -1
  101. nautobot/core/templates/inc/tenancy_form_panel.html +9 -0
  102. nautobot/core/templates/inc/tenant_table_row.html +11 -0
  103. nautobot/core/templates/nautobot_config.py.j2 +13 -0
  104. nautobot/core/templates/panel_table.html +12 -0
  105. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  106. nautobot/core/templates/utilities/templatetags/tag.html +1 -1
  107. nautobot/core/templates/utilities/theme_preview.html +7 -0
  108. nautobot/core/templatetags/helpers.py +104 -6
  109. nautobot/core/templatetags/ui_framework.py +40 -0
  110. nautobot/core/testing/__init__.py +8 -8
  111. nautobot/core/testing/api.py +187 -137
  112. nautobot/core/testing/context.py +18 -0
  113. nautobot/core/testing/filters.py +41 -35
  114. nautobot/core/testing/forms.py +2 -0
  115. nautobot/core/testing/views.py +65 -148
  116. nautobot/core/tests/integration/test_view_authentication.py +1 -1
  117. nautobot/core/tests/nautobot_config.py +198 -0
  118. nautobot/core/tests/runner.py +2 -2
  119. nautobot/core/tests/test_api.py +154 -176
  120. nautobot/core/tests/test_events.py +214 -0
  121. nautobot/core/tests/test_forms.py +1 -0
  122. nautobot/core/tests/test_jinja_filters.py +1 -0
  123. nautobot/core/tests/test_jobs.py +387 -14
  124. nautobot/core/tests/test_navigations.py +7 -241
  125. nautobot/core/tests/test_settings_schema.py +7 -0
  126. nautobot/core/tests/test_tables.py +100 -0
  127. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  128. nautobot/core/tests/test_ui.py +150 -0
  129. nautobot/core/tests/test_utils.py +55 -18
  130. nautobot/core/tests/test_views.py +124 -5
  131. nautobot/core/ui/__init__.py +0 -0
  132. nautobot/core/ui/base.py +11 -0
  133. nautobot/core/ui/choices.py +44 -0
  134. nautobot/core/ui/homepage.py +167 -0
  135. nautobot/core/ui/nav.py +280 -0
  136. nautobot/core/ui/object_detail.py +1855 -0
  137. nautobot/core/ui/utils.py +36 -0
  138. nautobot/core/urls.py +6 -0
  139. nautobot/core/utils/config.py +30 -3
  140. nautobot/core/utils/lookup.py +12 -2
  141. nautobot/core/utils/querysets.py +64 -0
  142. nautobot/core/utils/requests.py +24 -9
  143. nautobot/core/views/__init__.py +48 -1
  144. nautobot/core/views/generic.py +37 -140
  145. nautobot/core/views/mixins.py +82 -32
  146. nautobot/core/views/paginator.py +8 -5
  147. nautobot/core/views/renderers.py +9 -9
  148. nautobot/core/views/utils.py +11 -0
  149. nautobot/core/wsgi.py +3 -3
  150. nautobot/dcim/api/serializers.py +34 -141
  151. nautobot/dcim/api/urls.py +5 -0
  152. nautobot/dcim/api/views.py +57 -110
  153. nautobot/dcim/apps.py +1 -0
  154. nautobot/dcim/choices.py +28 -0
  155. nautobot/dcim/factory.py +58 -0
  156. nautobot/dcim/filters/__init__.py +204 -2
  157. nautobot/dcim/forms.py +219 -9
  158. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  159. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  160. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  161. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  162. nautobot/dcim/migrations/0067_controllermanageddevicegroup_tenant.py +25 -0
  163. nautobot/dcim/models/__init__.py +5 -1
  164. nautobot/dcim/models/devices.py +180 -2
  165. nautobot/dcim/models/racks.py +2 -2
  166. nautobot/dcim/navigation.py +25 -224
  167. nautobot/dcim/signals.py +44 -0
  168. nautobot/dcim/tables/__init__.py +2 -0
  169. nautobot/dcim/tables/devices.py +103 -7
  170. nautobot/dcim/tables/racks.py +1 -1
  171. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  172. nautobot/dcim/templates/dcim/controller_create.html +2 -7
  173. nautobot/dcim/templates/dcim/controller_retrieve.html +6 -10
  174. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  175. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -0
  176. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +51 -0
  177. nautobot/dcim/templates/dcim/device/base.html +6 -42
  178. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  179. nautobot/dcim/templates/dcim/device.html +4 -10
  180. nautobot/dcim/templates/dcim/device_edit.html +36 -37
  181. nautobot/dcim/templates/dcim/interface.html +1 -0
  182. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  183. nautobot/dcim/templates/dcim/location.html +1 -9
  184. nautobot/dcim/templates/dcim/location_edit.html +1 -7
  185. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  186. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  187. nautobot/dcim/templates/dcim/rack.html +1 -9
  188. nautobot/dcim/templates/dcim/rack_edit.html +1 -7
  189. nautobot/dcim/templates/dcim/rackreservation.html +1 -9
  190. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +68 -0
  191. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +28 -0
  192. nautobot/dcim/tests/integration/test_controller.py +62 -0
  193. nautobot/dcim/tests/integration/test_controller_managed_device_group.py +71 -0
  194. nautobot/dcim/tests/test_api.py +188 -64
  195. nautobot/dcim/tests/test_filters.py +171 -76
  196. nautobot/dcim/tests/test_jobs.py +118 -0
  197. nautobot/dcim/tests/test_models.py +157 -6
  198. nautobot/dcim/tests/test_signals.py +1 -0
  199. nautobot/dcim/tests/test_views.py +118 -88
  200. nautobot/dcim/urls.py +72 -27
  201. nautobot/dcim/utils.py +2 -2
  202. nautobot/dcim/views.py +356 -61
  203. nautobot/extras/api/serializers.py +39 -18
  204. nautobot/extras/api/urls.py +4 -0
  205. nautobot/extras/api/views.py +89 -31
  206. nautobot/extras/choices.py +13 -0
  207. nautobot/extras/constants.py +2 -1
  208. nautobot/extras/context_managers.py +23 -6
  209. nautobot/extras/datasources/git.py +4 -1
  210. nautobot/extras/factory.py +27 -0
  211. nautobot/extras/filters/__init__.py +66 -5
  212. nautobot/extras/forms/base.py +2 -2
  213. nautobot/extras/forms/forms.py +262 -59
  214. nautobot/extras/forms/mixins.py +2 -2
  215. nautobot/extras/graphql/types.py +25 -1
  216. nautobot/extras/jobs.py +109 -15
  217. nautobot/extras/management/__init__.py +1 -0
  218. nautobot/extras/management/commands/runjob.py +7 -79
  219. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  220. nautobot/extras/management/utils.py +87 -0
  221. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  222. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  223. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  224. nautobot/extras/migrations/0120_job_is_singleton_job_is_singleton_override.py +22 -0
  225. nautobot/extras/migrations/0121_alter_team_contacts.py +17 -0
  226. nautobot/extras/models/__init__.py +5 -1
  227. nautobot/extras/models/change_logging.py +7 -3
  228. nautobot/extras/models/contacts.py +1 -1
  229. nautobot/extras/models/groups.py +0 -2
  230. nautobot/extras/models/jobs.py +233 -33
  231. nautobot/extras/models/relationships.py +69 -1
  232. nautobot/extras/models/secrets.py +5 -0
  233. nautobot/extras/navigation.py +20 -262
  234. nautobot/extras/plugins/__init__.py +54 -19
  235. nautobot/extras/plugins/marketplace_manifest.yml +455 -0
  236. nautobot/extras/plugins/tables.py +16 -14
  237. nautobot/extras/plugins/urls.py +1 -0
  238. nautobot/extras/plugins/views.py +103 -60
  239. nautobot/extras/registry.py +1 -1
  240. nautobot/extras/secrets/__init__.py +2 -2
  241. nautobot/extras/signals.py +39 -1
  242. nautobot/extras/tables.py +37 -1
  243. nautobot/extras/templates/extras/dynamicgroup.html +1 -9
  244. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  245. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  246. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  247. nautobot/extras/templates/extras/job_detail.html +52 -6
  248. nautobot/extras/templates/extras/job_edit.html +6 -2
  249. nautobot/extras/templates/extras/job_list.html +2 -7
  250. nautobot/extras/templates/extras/jobqueue_retrieve.html +36 -0
  251. nautobot/extras/templates/extras/marketplace.html +296 -0
  252. nautobot/extras/templates/extras/plugin_detail.html +32 -15
  253. nautobot/extras/templates/extras/plugins_list.html +35 -1
  254. nautobot/extras/templates/extras/plugins_tiles.html +90 -0
  255. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  256. nautobot/extras/templates/extras/secret.html +0 -65
  257. nautobot/extras/templates/extras/secret_check.js +16 -0
  258. nautobot/extras/templates/extras/secret_create.html +114 -0
  259. nautobot/extras/templates/extras/secret_edit.html +1 -114
  260. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  261. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  262. nautobot/extras/templatetags/job_buttons.py +5 -4
  263. nautobot/extras/templatetags/plugins.py +69 -6
  264. nautobot/extras/test_jobs/singleton.py +16 -0
  265. nautobot/extras/tests/test_api.py +145 -43
  266. nautobot/extras/tests/test_context_managers.py +4 -1
  267. nautobot/extras/tests/test_filters.py +213 -529
  268. nautobot/extras/tests/test_job_variables.py +73 -152
  269. nautobot/extras/tests/test_jobs.py +181 -51
  270. nautobot/extras/tests/test_models.py +61 -6
  271. nautobot/extras/tests/test_plugins.py +62 -9
  272. nautobot/extras/tests/test_relationships.py +123 -9
  273. nautobot/extras/tests/test_utils.py +23 -2
  274. nautobot/extras/tests/test_views.py +146 -145
  275. nautobot/extras/tests/test_webhooks.py +2 -1
  276. nautobot/extras/urls.py +2 -20
  277. nautobot/extras/utils.py +119 -4
  278. nautobot/extras/views.py +168 -125
  279. nautobot/extras/webhooks.py +5 -2
  280. nautobot/ipam/api/serializers.py +10 -103
  281. nautobot/ipam/api/views.py +31 -49
  282. nautobot/ipam/factory.py +1 -1
  283. nautobot/ipam/filters.py +3 -2
  284. nautobot/ipam/models.py +10 -12
  285. nautobot/ipam/navigation.py +0 -90
  286. nautobot/ipam/tables.py +3 -1
  287. nautobot/ipam/templates/ipam/ipaddress.html +1 -9
  288. nautobot/ipam/templates/ipam/ipaddress_bulk_add.html +1 -7
  289. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -7
  290. nautobot/ipam/templates/ipam/prefix.html +1 -9
  291. nautobot/ipam/templates/ipam/prefix_edit.html +1 -7
  292. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  293. nautobot/ipam/templates/ipam/vlan.html +1 -9
  294. nautobot/ipam/templates/ipam/vlan_edit.html +1 -7
  295. nautobot/ipam/templates/ipam/vrf.html +0 -47
  296. nautobot/ipam/templates/ipam/vrf_edit.html +1 -7
  297. nautobot/ipam/tests/test_api.py +7 -5
  298. nautobot/ipam/tests/test_filters.py +39 -119
  299. nautobot/ipam/tests/test_forms.py +0 -2
  300. nautobot/ipam/tests/test_models.py +56 -36
  301. nautobot/ipam/tests/test_views.py +3 -0
  302. nautobot/ipam/urls.py +3 -69
  303. nautobot/ipam/utils/__init__.py +16 -10
  304. nautobot/ipam/views.py +91 -162
  305. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.css.map +1 -1
  306. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap-theme.min.css.map +1 -1
  307. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css +40 -2
  308. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.css.map +1 -1
  309. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css +1 -1
  310. nautobot/project-static/bootstrap-3.4.1-dist/css/bootstrap.min.css.map +1 -1
  311. nautobot/project-static/css/base.css +38 -3
  312. nautobot/project-static/docs/404.html +461 -17
  313. nautobot/project-static/docs/apps/index.html +461 -17
  314. nautobot/project-static/docs/apps/nautobot-apps.html +462 -19
  315. nautobot/project-static/docs/assets/_mkdocstrings.css +25 -1
  316. nautobot/project-static/docs/assets/extra.css +5 -1
  317. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +477 -23
  318. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +474 -20
  319. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +790 -289
  320. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +505 -31
  321. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +510 -34
  322. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +471 -20
  323. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +467 -18
  324. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +497 -33
  325. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9883 -0
  326. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +523 -75
  327. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +546 -51
  328. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +670 -94
  329. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1030 -177
  330. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +524 -49
  331. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +874 -188
  332. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +955 -235
  333. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +475 -21
  334. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +486 -28
  335. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +661 -99
  336. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +947 -479
  337. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +6425 -1234
  338. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +474 -20
  339. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +877 -344
  340. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +828 -171
  341. nautobot/project-static/docs/development/apps/api/configuration-view.html +461 -17
  342. nautobot/project-static/docs/development/apps/api/database-backend-config.html +461 -17
  343. nautobot/project-static/docs/development/apps/api/models/django-admin.html +461 -17
  344. nautobot/project-static/docs/development/apps/api/models/global-search.html +461 -17
  345. nautobot/project-static/docs/development/apps/api/models/graphql.html +461 -17
  346. nautobot/project-static/docs/development/apps/api/models/index.html +461 -17
  347. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +461 -17
  348. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +461 -17
  349. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +461 -17
  350. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +461 -17
  351. nautobot/project-static/docs/development/apps/api/platform-features/index.html +461 -17
  352. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +461 -17
  353. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +461 -17
  354. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +461 -17
  355. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +461 -17
  356. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +461 -17
  357. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +461 -17
  358. nautobot/project-static/docs/development/apps/api/prometheus.html +461 -17
  359. nautobot/project-static/docs/development/apps/api/setup.html +465 -153
  360. nautobot/project-static/docs/development/apps/api/testing.html +461 -17
  361. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +461 -17
  362. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +461 -17
  363. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +461 -17
  364. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +461 -17
  365. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +741 -128
  366. nautobot/project-static/docs/development/apps/api/views/base-template.html +461 -17
  367. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +461 -17
  368. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +461 -17
  369. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +461 -17
  370. nautobot/project-static/docs/development/apps/api/views/index.html +463 -18
  371. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +465 -17
  372. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +491 -17
  373. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +461 -17
  374. nautobot/project-static/docs/development/apps/api/views/notes.html +461 -17
  375. nautobot/project-static/docs/development/apps/api/views/rest-api.html +467 -19
  376. nautobot/project-static/docs/development/apps/api/views/urls.html +461 -17
  377. nautobot/project-static/docs/development/apps/index.html +461 -17
  378. nautobot/project-static/docs/development/apps/migration/code-updates.html +462 -50
  379. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +462 -18
  380. nautobot/project-static/docs/development/apps/migration/from-v1.html +461 -17
  381. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +461 -17
  382. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +461 -17
  383. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +461 -17
  384. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +464 -20
  385. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9261 -0
  386. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9375 -0
  387. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9671 -0
  388. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9559 -0
  389. nautobot/project-static/docs/development/apps/porting-from-netbox.html +464 -20
  390. nautobot/project-static/docs/development/core/application-registry.html +461 -17
  391. nautobot/project-static/docs/development/core/best-practices.html +461 -17
  392. nautobot/project-static/docs/development/core/bootstrap-ui.html +461 -17
  393. nautobot/project-static/docs/development/core/caching.html +461 -17
  394. nautobot/project-static/docs/development/core/controllers.html +463 -17
  395. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +464 -20
  396. nautobot/project-static/docs/development/core/generic-views.html +461 -17
  397. nautobot/project-static/docs/development/core/getting-started.html +539 -127
  398. nautobot/project-static/docs/development/core/homepage.html +472 -28
  399. nautobot/project-static/docs/development/core/index.html +461 -17
  400. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +9754 -0
  401. nautobot/project-static/docs/development/core/model-checklist.html +471 -25
  402. nautobot/project-static/docs/development/core/model-features.html +461 -17
  403. nautobot/project-static/docs/development/core/natural-keys.html +461 -17
  404. nautobot/project-static/docs/development/core/navigation-menu.html +478 -24
  405. nautobot/project-static/docs/development/core/release-checklist.html +478 -46
  406. nautobot/project-static/docs/development/core/role-internals.html +461 -17
  407. nautobot/project-static/docs/development/core/settings.html +461 -17
  408. nautobot/project-static/docs/development/core/style-guide.html +464 -20
  409. nautobot/project-static/docs/development/core/templates.html +471 -20
  410. nautobot/project-static/docs/development/core/testing.html +461 -17
  411. nautobot/project-static/docs/development/core/ui-component-framework.html +11116 -0
  412. nautobot/project-static/docs/development/core/user-preferences.html +464 -20
  413. nautobot/project-static/docs/development/index.html +461 -17
  414. nautobot/project-static/docs/development/jobs/index.html +499 -19
  415. nautobot/project-static/docs/development/jobs/migration/from-v1.html +461 -17
  416. nautobot/project-static/docs/index.html +469 -36
  417. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit.png +0 -0
  418. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_edit_button.png +0 -0
  419. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_nav.png +0 -0
  420. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_list_view.png +0 -0
  421. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue.png +0 -0
  422. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_add.png +0 -0
  423. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_queue_config.png +0 -0
  424. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_completed.png +0 -0
  425. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_nav.png +0 -0
  426. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_result_pending.png +0 -0
  427. nautobot/project-static/docs/media/development/core/kubernetes/k8s_job_run_form.png +0 -0
  428. nautobot/project-static/docs/media/development/core/kubernetes/k8s_nautobot_login.png +0 -0
  429. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_job.png +0 -0
  430. nautobot/project-static/docs/media/development/core/kubernetes/k8s_run_scheduled_job_form.png +0 -0
  431. nautobot/project-static/docs/media/development/core/kubernetes/k8s_scheduled_job_result.png +0 -0
  432. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  433. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  434. nautobot/project-static/docs/media/development/core/ui-component-framework/buttons-example.png +0 -0
  435. nautobot/project-static/docs/media/development/core/ui-component-framework/cluster-type-before-after-example.png +0 -0
  436. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  437. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  438. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  439. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  440. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example_2.png +0 -0
  441. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example-code.png +0 -0
  442. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  443. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  444. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  445. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  446. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  447. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  448. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  449. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  450. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  451. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  452. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  453. nautobot/project-static/docs/objects.inv +0 -0
  454. nautobot/project-static/docs/overview/application_stack.html +467 -21
  455. nautobot/project-static/docs/overview/design_philosophy.html +461 -17
  456. nautobot/project-static/docs/release-notes/index.html +483 -20
  457. nautobot/project-static/docs/release-notes/version-1.0.html +649 -206
  458. nautobot/project-static/docs/release-notes/version-1.1.html +646 -203
  459. nautobot/project-static/docs/release-notes/version-1.2.html +721 -278
  460. nautobot/project-static/docs/release-notes/version-1.3.html +747 -304
  461. nautobot/project-static/docs/release-notes/version-1.4.html +832 -390
  462. nautobot/project-static/docs/release-notes/version-1.5.html +1020 -579
  463. nautobot/project-static/docs/release-notes/version-1.6.html +940 -516
  464. nautobot/project-static/docs/release-notes/version-2.0.html +943 -502
  465. nautobot/project-static/docs/release-notes/version-2.1.html +778 -337
  466. nautobot/project-static/docs/release-notes/version-2.2.html +771 -330
  467. nautobot/project-static/docs/release-notes/version-2.3.html +914 -471
  468. nautobot/project-static/docs/release-notes/version-2.4.html +10323 -0
  469. nautobot/project-static/docs/search/search_index.json +1 -1
  470. nautobot/project-static/docs/sitemap.xml +342 -270
  471. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  472. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +461 -17
  473. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +461 -17
  474. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +461 -17
  475. nautobot/project-static/docs/user-guide/administration/configuration/index.html +473 -30
  476. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +461 -17
  477. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +842 -155
  478. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +461 -17
  479. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +461 -17
  480. nautobot/project-static/docs/user-guide/administration/guides/docker.html +474 -27
  481. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +461 -17
  482. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +461 -17
  483. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +461 -17
  484. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +461 -17
  485. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +461 -17
  486. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +463 -19
  487. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +461 -17
  488. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +461 -17
  489. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +461 -17
  490. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +481 -21
  491. nautobot/project-static/docs/user-guide/administration/installation/index.html +466 -18
  492. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +462 -18
  493. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +461 -17
  494. nautobot/project-static/docs/user-guide/administration/installation/services.html +461 -17
  495. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +461 -17
  496. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +482 -39
  497. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +475 -64
  498. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +475 -64
  499. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +461 -17
  500. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +461 -17
  501. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +461 -17
  502. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +461 -17
  503. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +461 -17
  504. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +464 -21
  505. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +461 -17
  506. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  507. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +461 -17
  508. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +467 -19
  509. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +461 -17
  510. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +461 -17
  511. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +461 -17
  512. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +461 -17
  513. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +461 -17
  514. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +461 -17
  515. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +461 -17
  516. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +461 -17
  517. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +461 -17
  518. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +461 -17
  519. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +461 -17
  520. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +461 -17
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +461 -17
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +461 -17
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +461 -17
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +461 -17
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +461 -17
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +497 -18
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +487 -20
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +461 -17
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +461 -17
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +461 -17
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +461 -17
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +461 -17
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +461 -17
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +461 -17
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +461 -17
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +461 -17
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +461 -17
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +461 -17
  539. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +461 -17
  540. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +461 -17
  541. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +461 -17
  542. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +461 -17
  543. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +461 -17
  544. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +461 -17
  545. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +461 -17
  546. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +461 -17
  547. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +461 -17
  548. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +461 -17
  549. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +461 -17
  550. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +461 -17
  551. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +461 -17
  552. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +461 -17
  553. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +461 -17
  554. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +461 -17
  555. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +461 -17
  556. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +461 -17
  557. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +461 -17
  558. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +461 -17
  559. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +461 -17
  560. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +461 -17
  561. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +461 -17
  562. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9375 -0
  563. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +468 -28
  564. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +461 -17
  565. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +461 -17
  566. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +461 -17
  567. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +461 -17
  568. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +461 -17
  569. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +461 -17
  570. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +461 -17
  571. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +461 -17
  572. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +461 -17
  573. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +461 -17
  574. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +461 -17
  575. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +461 -17
  576. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +464 -20
  577. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +461 -17
  578. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +461 -17
  579. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +461 -17
  580. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +461 -17
  581. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +461 -17
  582. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +461 -17
  583. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +464 -20
  584. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9313 -0
  585. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9217 -0
  586. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9211 -0
  587. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9277 -0
  588. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +461 -17
  589. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +461 -17
  590. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +461 -17
  591. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +461 -17
  592. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +461 -17
  593. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +461 -17
  594. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +461 -17
  595. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +461 -17
  596. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +461 -17
  597. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +461 -17
  598. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +461 -17
  599. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +466 -20
  600. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +461 -17
  601. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/central-mode.png +0 -0
  602. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-add.png +0 -0
  603. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-1.png +0 -0
  604. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/device-group-create-2.png +0 -0
  605. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-add.png +0 -0
  606. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/radio-profile-create.png +0 -0
  607. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-add.png +0 -0
  608. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/supported-data-rate-create.png +0 -0
  609. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-add.png +0 -0
  610. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-1.png +0 -0
  611. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-controller-create-2.png +0 -0
  612. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-add.png +0 -0
  613. nautobot/project-static/docs/user-guide/feature-guides/images/wireless/wireless-network-create.png +0 -0
  614. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +461 -17
  615. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +461 -17
  616. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +464 -20
  617. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +9444 -0
  618. nautobot/project-static/docs/user-guide/index.html +461 -17
  619. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +464 -20
  620. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +465 -21
  621. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +461 -17
  622. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +461 -17
  623. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +461 -17
  624. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9617 -0
  625. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +464 -20
  626. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +461 -17
  627. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +461 -17
  628. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +461 -17
  629. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +461 -17
  630. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +461 -17
  631. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +470 -21
  632. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +464 -20
  633. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +464 -20
  634. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +461 -17
  635. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9224 -0
  636. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +9722 -0
  637. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +464 -20
  638. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +461 -17
  639. nautobot/project-static/docs/user-guide/platform-functionality/note.html +461 -17
  640. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +461 -17
  641. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +465 -21
  642. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9292 -0
  643. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +461 -17
  644. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +509 -38
  645. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +492 -21
  646. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +461 -17
  647. nautobot/project-static/docs/user-guide/platform-functionality/role.html +461 -17
  648. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +461 -17
  649. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +461 -17
  650. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +464 -20
  651. nautobot/project-static/docs/user-guide/platform-functionality/status.html +461 -17
  652. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +461 -17
  653. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +529 -54
  654. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +461 -17
  655. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +461 -17
  656. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +461 -17
  657. nautobot/project-static/img/jinja_logo.svg +97 -0
  658. nautobot/project-static/js/forms.js +6 -1
  659. nautobot/project-static/js/nav_menu.js +2 -1
  660. nautobot/tenancy/api/serializers.py +0 -2
  661. nautobot/tenancy/api/views.py +9 -13
  662. nautobot/tenancy/factory.py +1 -1
  663. nautobot/tenancy/navigation.py +0 -29
  664. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  665. nautobot/tenancy/tests/test_filters.py +29 -134
  666. nautobot/tenancy/views.py +35 -24
  667. nautobot/users/admin.py +2 -0
  668. nautobot/users/api/views.py +2 -2
  669. nautobot/users/forms.py +19 -0
  670. nautobot/users/templates/users/preferences.html +22 -0
  671. nautobot/users/tests/test_filters.py +1 -19
  672. nautobot/users/tests/test_views.py +57 -0
  673. nautobot/users/utils.py +8 -0
  674. nautobot/users/views.py +48 -11
  675. nautobot/virtualization/api/views.py +5 -24
  676. nautobot/virtualization/filters.py +1 -2
  677. nautobot/virtualization/models.py +1 -1
  678. nautobot/virtualization/navigation.py +0 -48
  679. nautobot/virtualization/tables.py +2 -2
  680. nautobot/virtualization/templates/virtualization/cluster_edit.html +1 -7
  681. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  682. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -9
  683. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +2 -8
  684. nautobot/virtualization/tests/test_filters.py +57 -166
  685. nautobot/virtualization/views.py +18 -15
  686. nautobot/wireless/__init__.py +0 -0
  687. nautobot/wireless/api/__init__.py +0 -0
  688. nautobot/wireless/api/serializers.py +44 -0
  689. nautobot/wireless/api/urls.py +20 -0
  690. nautobot/wireless/api/views.py +34 -0
  691. nautobot/wireless/apps.py +8 -0
  692. nautobot/wireless/choices.py +345 -0
  693. nautobot/wireless/factory.py +138 -0
  694. nautobot/wireless/filters.py +167 -0
  695. nautobot/wireless/forms.py +283 -0
  696. nautobot/wireless/homepage.py +19 -0
  697. nautobot/wireless/migrations/0001_initial.py +223 -0
  698. nautobot/wireless/migrations/__init__.py +0 -0
  699. nautobot/wireless/models.py +207 -0
  700. nautobot/wireless/navigation.py +105 -0
  701. nautobot/wireless/tables.py +244 -0
  702. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  703. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  704. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  705. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +56 -0
  706. nautobot/wireless/tests/__init__.py +0 -0
  707. nautobot/wireless/tests/integration/__init__.py +0 -0
  708. nautobot/wireless/tests/integration/test_radio_profile.py +42 -0
  709. nautobot/wireless/tests/test_api.py +247 -0
  710. nautobot/wireless/tests/test_filters.py +82 -0
  711. nautobot/wireless/tests/test_models.py +22 -0
  712. nautobot/wireless/tests/test_views.py +378 -0
  713. nautobot/wireless/urls.py +13 -0
  714. nautobot/wireless/views.py +119 -0
  715. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/METADATA +9 -12
  716. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/RECORD +720 -549
  717. nautobot/core/utils/navigation.py +0 -54
  718. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/LICENSE.txt +0 -0
  719. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/NOTICE +0 -0
  720. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/WHEEL +0 -0
  721. {nautobot-2.3.16.dist-info → nautobot-2.4.0.dist-info}/entry_points.txt +0 -0
@@ -23,6 +23,7 @@ from nautobot.core.filters import (
23
23
  from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
24
24
  from nautobot.dcim.models import DeviceRedundancyGroup, DeviceType, Location, Platform
25
25
  from nautobot.extras.choices import (
26
+ JobQueueTypeChoices,
26
27
  JobResultStatusChoices,
27
28
  MetadataTypeDataTypeChoices,
28
29
  RelationshipTypeChoices,
@@ -73,6 +74,8 @@ from nautobot.extras.models import (
73
74
  JobButton,
74
75
  JobHook,
75
76
  JobLogEntry,
77
+ JobQueue,
78
+ JobQueueAssignment,
76
79
  JobResult,
77
80
  MetadataChoice,
78
81
  MetadataType,
@@ -116,13 +119,13 @@ __all__ = (
116
119
  "CustomFieldDateFilter",
117
120
  "CustomFieldFilterMixin",
118
121
  "CustomFieldJSONFilter",
122
+ "CustomFieldModelFilterSet",
123
+ "CustomFieldModelFilterSetMixin",
119
124
  "CustomFieldMultiSelectFilter",
120
125
  "CustomFieldMultiValueCharFilter",
121
126
  "CustomFieldMultiValueDateFilter",
122
127
  "CustomFieldMultiValueNumberFilter",
123
128
  "CustomFieldNumberFilter",
124
- "CustomFieldModelFilterSet",
125
- "CustomFieldModelFilterSetMixin",
126
129
  "CustomLinkFilterSet",
127
130
  "DynamicGroupFilterSet",
128
131
  "DynamicGroupMembershipFilterSet",
@@ -133,23 +136,25 @@ __all__ = (
133
136
  "ImageAttachmentFilterSet",
134
137
  "JobFilterSet",
135
138
  "JobLogEntryFilterSet",
139
+ "JobQueueAssignmentFilterSet",
140
+ "JobQueueFilterSet",
136
141
  "JobResultFilterSet",
137
142
  "LocalContextFilterSet",
138
143
  "LocalContextModelFilterSetMixin",
139
- "MetadataTypeFilterSet",
140
144
  "MetadataChoiceFilterSet",
145
+ "MetadataTypeFilterSet",
141
146
  "NautobotFilterSet",
142
147
  "NoteFilterSet",
143
148
  "ObjectChangeFilterSet",
149
+ "RelationshipAssociationFilterSet",
144
150
  "RelationshipFilter",
145
151
  "RelationshipFilterSet",
146
- "RelationshipAssociationFilterSet",
147
152
  "RoleFilterSet",
148
153
  "RoleModelFilterSetMixin",
149
154
  "ScheduledJobFilterSet",
150
155
  "SecretFilterSet",
151
- "SecretsGroupFilterSet",
152
156
  "SecretsGroupAssociationFilterSet",
157
+ "SecretsGroupFilterSet",
153
158
  "StatusFilter",
154
159
  "StatusFilterSet",
155
160
  "StatusModelFilterSetMixin",
@@ -869,6 +874,7 @@ class JobFilterSet(BaseFilterSet, CustomFieldModelFilterSetMixin):
869
874
  "is_job_button_receiver",
870
875
  "soft_time_limit",
871
876
  "time_limit",
877
+ "is_singleton",
872
878
  "grouping_override",
873
879
  "name_override",
874
880
  "approval_required_override",
@@ -878,6 +884,7 @@ class JobFilterSet(BaseFilterSet, CustomFieldModelFilterSetMixin):
878
884
  "soft_time_limit_override",
879
885
  "time_limit_override",
880
886
  "has_sensitive_variables_override",
887
+ "is_singleton_override",
881
888
  "tags",
882
889
  ]
883
890
 
@@ -906,6 +913,60 @@ class JobHookFilterSet(BaseFilterSet):
906
913
  ]
907
914
 
908
915
 
916
+ class JobQueueFilterSet(NautobotFilterSet, TenancyModelFilterSetMixin):
917
+ q = SearchFilter(
918
+ filter_predicates={
919
+ "name": "icontains",
920
+ "queue_type": "icontains",
921
+ "description": "icontains",
922
+ "tenant__name": "icontains",
923
+ },
924
+ )
925
+ queue_type = django_filters.MultipleChoiceFilter(choices=JobQueueTypeChoices, null_value=None)
926
+ jobs = NaturalKeyOrPKMultipleChoiceFilter(
927
+ queryset=Job.objects.all(),
928
+ label="Job (name or ID)",
929
+ )
930
+ has_jobs = RelatedMembershipBooleanFilter(
931
+ field_name="jobs",
932
+ label="Has jobs",
933
+ )
934
+
935
+ class Meta:
936
+ model = JobQueue
937
+ fields = [
938
+ "id",
939
+ "name",
940
+ "description",
941
+ "tags",
942
+ ]
943
+
944
+
945
+ class JobQueueAssignmentFilterSet(BaseFilterSet):
946
+ q = SearchFilter(
947
+ filter_predicates={
948
+ "job__name": "icontains",
949
+ "job__grouping": "icontains",
950
+ "job__description": "icontains",
951
+ "job_queue__name": "icontains",
952
+ "job_queue__description": "icontains",
953
+ "job_queue__queue_type": "icontains",
954
+ }
955
+ )
956
+ job = NaturalKeyOrPKMultipleChoiceFilter(
957
+ queryset=Job.objects.all(),
958
+ label="Job (name or ID)",
959
+ )
960
+ job_queue = NaturalKeyOrPKMultipleChoiceFilter(
961
+ queryset=JobQueue.objects.all(),
962
+ label="Job Queue (name or ID)",
963
+ )
964
+
965
+ class Meta:
966
+ model = JobQueueAssignment
967
+ fields = ["id"]
968
+
969
+
909
970
  class JobResultFilterSet(BaseFilterSet, CustomFieldModelFilterSetMixin):
910
971
  q = SearchFilter(
911
972
  filter_predicates={
@@ -14,9 +14,9 @@ from .mixins import (
14
14
  )
15
15
 
16
16
  __all__ = (
17
- "NautobotModelForm",
18
- "NautobotFilterForm",
19
17
  "NautobotBulkEditForm",
18
+ "NautobotFilterForm",
19
+ "NautobotModelForm",
20
20
  )
21
21
 
22
22
 
@@ -1,5 +1,7 @@
1
1
  import inspect
2
+ import logging
2
3
 
4
+ from celery import chain
3
5
  from django import forms
4
6
  from django.conf import settings
5
7
  from django.contrib.auth import get_user_model
@@ -7,8 +9,9 @@ from django.contrib.contenttypes.models import ContentType
7
9
  from django.core.exceptions import ValidationError
8
10
  from django.core.validators import MinValueValidator
9
11
  from django.db.models.fields import TextField
10
- from django.forms import inlineformset_factory, ModelMultipleChoiceField
12
+ from django.forms import inlineformset_factory, ModelMultipleChoiceField, MultipleHiddenInput
11
13
  from django.urls.base import reverse
14
+ from django.utils.timezone import get_current_timezone_name
12
15
 
13
16
  from nautobot.core.constants import CHARFIELD_MAX_LENGTH
14
17
  from nautobot.core.forms import (
@@ -25,7 +28,6 @@ from nautobot.core.forms import (
25
28
  DateTimePicker,
26
29
  DynamicModelChoiceField,
27
30
  DynamicModelMultipleChoiceField,
28
- JSONArrayFormField,
29
31
  JSONField,
30
32
  LaxURLField,
31
33
  MultipleContentTypeField,
@@ -35,11 +37,13 @@ from nautobot.core.forms import (
35
37
  TagFilterField,
36
38
  )
37
39
  from nautobot.core.forms.constants import BOOLEAN_WITH_BLANK_CHOICES
40
+ from nautobot.core.forms.forms import ConfirmationForm
38
41
  from nautobot.core.utils.deprecation import class_deprecated_in_favor_of
39
42
  from nautobot.dcim.models import Device, DeviceRedundancyGroup, DeviceType, Location, Platform
40
43
  from nautobot.extras.choices import (
41
44
  DynamicGroupTypeChoices,
42
45
  JobExecutionType,
46
+ JobQueueTypeChoices,
43
47
  JobResultStatusChoices,
44
48
  ObjectChangeActionChoices,
45
49
  RelationshipTypeChoices,
@@ -65,6 +69,7 @@ from nautobot.extras.models import (
65
69
  Job,
66
70
  JobButton,
67
71
  JobHook,
72
+ JobQueue,
68
73
  JobResult,
69
74
  MetadataChoice,
70
75
  MetadataType,
@@ -86,9 +91,12 @@ from nautobot.extras.models import (
86
91
  Webhook,
87
92
  )
88
93
  from nautobot.extras.registry import registry
94
+ from nautobot.extras.signals import change_context_state
95
+ from nautobot.extras.tasks import delete_custom_field_data
89
96
  from nautobot.extras.utils import (
90
97
  ChangeLoggedModelsQuery,
91
98
  FeatureQuery,
99
+ get_worker_count,
92
100
  RoleModelsQuery,
93
101
  TaggableClassesQuery,
94
102
  )
@@ -106,86 +114,93 @@ from .mixins import (
106
114
  CustomFieldModelFormMixin,
107
115
  NoteModelBulkEditFormMixin,
108
116
  NoteModelFormMixin,
117
+ TagsBulkEditFormMixin,
109
118
  )
110
119
 
120
+ logger = logging.getLogger(__name__)
121
+
111
122
  __all__ = (
112
123
  "BaseDynamicGroupMembershipFormSet",
113
- "ComputedFieldForm",
114
124
  "ComputedFieldFilterForm",
115
- "ConfigContextForm",
125
+ "ComputedFieldForm",
116
126
  "ConfigContextBulkEditForm",
117
127
  "ConfigContextFilterForm",
118
- "ConfigContextSchemaForm",
128
+ "ConfigContextForm",
119
129
  "ConfigContextSchemaBulkEditForm",
120
130
  "ConfigContextSchemaFilterForm",
121
- "CustomFieldForm",
122
- "CustomFieldFilterForm",
123
- "CustomFieldModelCSVForm",
131
+ "ConfigContextSchemaForm",
124
132
  "CustomFieldBulkCreateForm", # 2.0 TODO remove this deprecated class
133
+ "CustomFieldBulkDeleteForm",
125
134
  "CustomFieldChoiceFormSet",
126
- "CustomLinkForm",
135
+ "CustomFieldFilterForm",
136
+ "CustomFieldForm",
137
+ "CustomFieldModelCSVForm",
127
138
  "CustomLinkFilterForm",
139
+ "CustomLinkForm",
128
140
  "DynamicGroupBulkAssignForm",
129
- "DynamicGroupForm",
130
141
  "DynamicGroupFilterForm",
142
+ "DynamicGroupForm",
131
143
  "DynamicGroupMembershipFormSet",
132
- "ExportTemplateForm",
133
144
  "ExportTemplateFilterForm",
145
+ "ExportTemplateForm",
146
+ "ExternalIntegrationBulkEditForm",
134
147
  "ExternalIntegrationFilterForm",
135
148
  "ExternalIntegrationForm",
136
- "ExternalIntegrationBulkEditForm",
137
- "GitRepositoryForm",
138
149
  "GitRepositoryBulkEditForm",
139
150
  "GitRepositoryFilterForm",
140
- "GraphQLQueryForm",
151
+ "GitRepositoryForm",
141
152
  "GraphQLQueryFilterForm",
153
+ "GraphQLQueryForm",
142
154
  "ImageAttachmentForm",
143
- "JobForm",
144
155
  "JobBulkEditForm",
145
- "JobButtonForm",
146
156
  "JobButtonBulkEditForm",
147
157
  "JobButtonFilterForm",
158
+ "JobButtonForm",
148
159
  "JobEditForm",
149
160
  "JobFilterForm",
150
- "JobHookForm",
161
+ "JobForm",
151
162
  "JobHookFilterForm",
152
- "JobScheduleForm",
163
+ "JobHookForm",
164
+ "JobQueueBulkEditForm",
165
+ "JobQueueFilterForm",
166
+ "JobQueueForm",
153
167
  "JobResultFilterForm",
168
+ "JobScheduleForm",
154
169
  "LocalContextFilterForm",
155
- "LocalContextModelForm",
156
170
  "LocalContextModelBulkEditForm",
171
+ "LocalContextModelForm",
172
+ "MetadataChoiceFormSet",
157
173
  "MetadataTypeBulkEditForm",
158
- "MetadataTypeForm",
159
174
  "MetadataTypeFilterForm",
160
- "MetadataChoiceFormSet",
161
- "NoteForm",
175
+ "MetadataTypeForm",
162
176
  "NoteFilterForm",
177
+ "NoteForm",
163
178
  "ObjectChangeFilterForm",
164
179
  "ObjectMetadataFilterForm",
165
180
  "PasswordInputWithPlaceholder",
166
- "RelationshipForm",
167
- "RelationshipFilterForm",
168
181
  "RelationshipAssociationFilterForm",
182
+ "RelationshipFilterForm",
183
+ "RelationshipForm",
169
184
  "RoleBulkEditForm",
170
185
  "RoleFilterForm",
171
186
  "RoleForm",
172
187
  "SavedViewForm",
173
188
  "SavedViewModalForm",
174
189
  "ScheduledJobFilterForm",
175
- "SecretForm",
176
190
  "SecretFilterForm",
177
- "SecretsGroupForm",
178
- "SecretsGroupFilterForm",
191
+ "SecretForm",
179
192
  "SecretsGroupAssociationFormSet",
193
+ "SecretsGroupFilterForm",
194
+ "SecretsGroupForm",
180
195
  "StaticGroupAssociationFilterForm",
181
- "StatusForm",
182
- "StatusFilterForm",
183
196
  "StatusBulkEditForm",
184
- "TagForm",
185
- "TagFilterForm",
197
+ "StatusFilterForm",
198
+ "StatusForm",
186
199
  "TagBulkEditForm",
187
- "WebhookForm",
200
+ "TagFilterForm",
201
+ "TagForm",
188
202
  "WebhookFilterForm",
203
+ "WebhookForm",
189
204
  )
190
205
 
191
206
 
@@ -485,6 +500,44 @@ class CustomFieldBulkCreateForm(CustomFieldModelBulkEditFormMixin):
485
500
  """No longer needed as a separate class - use CustomFieldModelBulkEditFormMixin instead."""
486
501
 
487
502
 
503
+ class CustomFieldBulkDeleteForm(ConfirmationForm):
504
+ def __init__(self, *args, delete_all=False, **kwargs):
505
+ super().__init__(*args, **kwargs)
506
+ queryset = CustomField.objects.all()
507
+ self.fields["pk"] = ModelMultipleChoiceField(
508
+ queryset=queryset, widget=MultipleHiddenInput, required=not delete_all
509
+ )
510
+
511
+ def construct_custom_field_delete_tasks(self, queryset):
512
+ """
513
+ Helper method to construct a list of celery tasks to execute when bulk deleting custom fields.
514
+ """
515
+ change_context = change_context_state.get()
516
+ if change_context is None:
517
+ context = None
518
+ else:
519
+ context = change_context.as_dict(queryset)
520
+ context["context_detail"] = "bulk delete custom field data"
521
+ tasks = [
522
+ delete_custom_field_data.si(obj.key, set(obj.content_types.values_list("pk", flat=True)), context)
523
+ for obj in queryset
524
+ ]
525
+ return tasks
526
+
527
+ def perform_pre_delete(self, queryset):
528
+ """
529
+ Remove all Custom Field Keys/Values from _custom_field_data of the related ContentType in the background.
530
+ """
531
+ if not get_worker_count():
532
+ logger.error("Celery worker process not running. Object custom fields may fail to reflect this deletion.")
533
+ return
534
+ tasks = self.construct_custom_field_delete_tasks(queryset)
535
+ # Executing the tasks in the background sequentially using chain() aligns with how a single
536
+ # CustomField object is deleted. We decided to not check the result because it needs at least one worker
537
+ # to be active and comes with extra performance penalty.
538
+ chain(*tasks).apply_async()
539
+
540
+
488
541
  #
489
542
  # Custom Links
490
543
  #
@@ -945,28 +998,19 @@ class JobForm(BootstrapMixin, forms.Form):
945
998
  controlled by the job definition. See `nautobot.extras.jobs.BaseJob.as_form`
946
999
  """
947
1000
 
948
- _profile = forms.BooleanField(
949
- required=False,
950
- initial=False,
951
- label="Profile job execution",
952
- help_text="Profiles the job execution using cProfile and outputs a report to /tmp/",
1001
+
1002
+ class JobEditForm(NautobotModelForm):
1003
+ job_queues = DynamicModelMultipleChoiceField(
1004
+ label="Job Queues",
1005
+ queryset=JobQueue.objects.all(),
953
1006
  )
954
- _task_queue = forms.ChoiceField(
1007
+ default_job_queue = DynamicModelChoiceField(
1008
+ label="Default Job Queue",
1009
+ queryset=JobQueue.objects.all(),
1010
+ help_text="The default job queue to route this job to",
955
1011
  required=False,
956
- help_text="The task queue to route this job to",
957
- label="Task queue",
958
1012
  )
959
1013
 
960
- def __init__(self, *args, **kwargs):
961
- super().__init__(*args, **kwargs)
962
-
963
- # Move special fields to the end of the form
964
- for field in ["_task_queue", "_profile"]:
965
- value = self.fields.pop(field)
966
- self.fields[field] = value
967
-
968
-
969
- class JobEditForm(NautobotModelForm):
970
1014
  class Meta:
971
1015
  model = Job
972
1016
  fields = [
@@ -989,8 +1033,12 @@ class JobEditForm(NautobotModelForm):
989
1033
  "time_limit",
990
1034
  "has_sensitive_variables_override",
991
1035
  "has_sensitive_variables",
992
- "task_queues_override",
993
- "task_queues",
1036
+ "job_queues_override",
1037
+ "job_queues",
1038
+ "default_job_queue_override",
1039
+ "default_job_queue",
1040
+ "is_singleton",
1041
+ "is_singleton_override",
994
1042
  "tags",
995
1043
  ]
996
1044
 
@@ -1006,8 +1054,28 @@ class JobEditForm(NautobotModelForm):
1006
1054
  for field_name in JOB_OVERRIDABLE_FIELDS:
1007
1055
  if not cleaned_data.get(f"{field_name}_override", False):
1008
1056
  cleaned_data[field_name] = getattr(job_class, field_name)
1057
+ # Get default Job Queue first
1058
+ if not cleaned_data.get("default_job_queue_override", False):
1059
+ meta_task_queues = getattr(job_class, "task_queues", []) or [settings.CELERY_TASK_DEFAULT_QUEUE]
1060
+ cleaned_data["default_job_queue"], _ = JobQueue.objects.get_or_create(
1061
+ name=meta_task_queues[0], defaults={"queue_type": JobQueueTypeChoices.TYPE_CELERY}
1062
+ )
1063
+ default_job_queue = cleaned_data["default_job_queue"]
1064
+ # Include the default Job Queue in the Job Queues selection
1065
+ if not cleaned_data.get("job_queues_override", False):
1066
+ names = getattr(job_class, "task_queues", []) or [settings.CELERY_TASK_DEFAULT_QUEUE]
1067
+ else:
1068
+ names = list(cleaned_data["job_queues"].values_list("name", flat=True))
1069
+ names += [default_job_queue]
1070
+ cleaned_data["job_queues"] = JobQueue.objects.filter(name__in=names)
1071
+
1009
1072
  return cleaned_data
1010
1073
 
1074
+ def save(self, *args, **kwargs):
1075
+ instance = super().save(*args, **kwargs)
1076
+ instance.job_queues.set(self.cleaned_data["job_queues"])
1077
+ return instance
1078
+
1011
1079
 
1012
1080
  class JobBulkEditForm(NautobotBulkEditForm):
1013
1081
  """Bulk edit form for `Job` objects."""
@@ -1058,10 +1126,22 @@ class JobBulkEditForm(NautobotBulkEditForm):
1058
1126
  help_text="Maximum runtime in seconds before the job will be forcibly terminated."
1059
1127
  "<br>Set to 0 to use Nautobot system default",
1060
1128
  )
1061
- task_queues = JSONArrayFormField(
1062
- base_field=forms.CharField(max_length=CHARFIELD_MAX_LENGTH),
1063
- help_text="Comma separated list of task queues that this job can run on. A blank list will use the default queue",
1129
+ job_queues = DynamicModelMultipleChoiceField(
1130
+ label="Job Queues",
1131
+ queryset=JobQueue.objects.all(),
1132
+ required=False,
1133
+ help_text="Job Queue instances that this job can run on",
1134
+ )
1135
+ default_job_queue = DynamicModelChoiceField(
1136
+ label="Default Job Queue",
1137
+ queryset=JobQueue.objects.all(),
1064
1138
  required=False,
1139
+ help_text="Default Job Queue the job runs on if no Job Queue is specified",
1140
+ )
1141
+ is_singleton = forms.NullBooleanField(
1142
+ required=False,
1143
+ widget=BulkEditNullBooleanSelect,
1144
+ help_text="Whether this job should fail to run if another instance of this job is already running",
1065
1145
  )
1066
1146
  # Flags to indicate whether the above properties are inherited from the source code or overridden by the database
1067
1147
  # Text field overrides
@@ -1081,9 +1161,13 @@ class JobBulkEditForm(NautobotBulkEditForm):
1081
1161
  required=False,
1082
1162
  help_text="If checked, time limits will be reverted to the default values defined in each Job's source code",
1083
1163
  )
1084
- clear_task_queues_override = forms.BooleanField(
1164
+ clear_job_queues_override = forms.BooleanField(
1165
+ required=False,
1166
+ help_text="If checked, the selected job queues will be reverted to the default values defined in each Job's source code",
1167
+ )
1168
+ clear_default_job_queue_override = forms.BooleanField(
1085
1169
  required=False,
1086
- help_text="If checked, task queue overrides will be reverted to the default values defined in each Job's source code",
1170
+ help_text="If checked, the default job queue will be reverted to the first value of task_queues defined in each Job's source code",
1087
1171
  )
1088
1172
  # Boolean overrides
1089
1173
  clear_approval_required_override = forms.BooleanField(
@@ -1102,10 +1186,62 @@ class JobBulkEditForm(NautobotBulkEditForm):
1102
1186
  required=False,
1103
1187
  help_text="If checked, the values of has sensitive variables will be reverted to the default values defined in each Job's source code",
1104
1188
  )
1189
+ is_singleton_override = forms.BooleanField(
1190
+ required=False,
1191
+ help_text="If checked, the values of is singleton will be reverted to the default values defined in each Job's source code",
1192
+ )
1105
1193
 
1106
1194
  class Meta:
1107
1195
  model = Job
1108
1196
 
1197
+ def post_save(self, obj):
1198
+ super().post_save(obj)
1199
+
1200
+ cleaned_data = self.cleaned_data
1201
+
1202
+ # Handle text related fields
1203
+ for overridable_field in JOB_OVERRIDABLE_FIELDS:
1204
+ override_field = overridable_field + "_override"
1205
+ clear_override_field = "clear_" + overridable_field + "_override"
1206
+ reset_override = cleaned_data.get(clear_override_field, False)
1207
+ override_value = cleaned_data.get(overridable_field)
1208
+ if reset_override:
1209
+ setattr(obj, override_field, False)
1210
+ elif not reset_override and override_value not in [None, ""]:
1211
+ setattr(obj, override_field, True)
1212
+ setattr(obj, overridable_field, override_value)
1213
+
1214
+ # Handle job queues
1215
+ clear_override_field = "clear_job_queues_override"
1216
+ reset_override = cleaned_data.get(clear_override_field, False)
1217
+ if reset_override:
1218
+ meta_task_queues = obj.job_class.task_queues
1219
+ job_queues = []
1220
+ for queue_name in meta_task_queues:
1221
+ try:
1222
+ job_queues.append(JobQueue.objects.get(name=queue_name))
1223
+ except JobQueue.DoesNotExist:
1224
+ # Do we want to create the Job Queue for the users here if we do not have it in the database?
1225
+ pass
1226
+ obj.job_queues_override = False
1227
+ obj.job_queues.set(job_queues)
1228
+ elif cleaned_data["job_queues"]:
1229
+ obj.job_queues_override = True
1230
+
1231
+ # Handle default job queue
1232
+ clear_override_field = "clear_default_job_queue_override"
1233
+ reset_override = cleaned_data.get(clear_override_field, False)
1234
+ if reset_override:
1235
+ meta_task_queues = obj.job_class.task_queues
1236
+ obj.default_job_queue_override = False
1237
+ obj.default_job_queue, _ = JobQueue.objects.get_or_create(
1238
+ name=meta_task_queues[0] if meta_task_queues else settings.CELERY_TASK_DEFAULT_QUEUE
1239
+ )
1240
+ elif cleaned_data["default_job_queue"]:
1241
+ obj.default_job_queue_override = True
1242
+
1243
+ obj.validated_save()
1244
+
1109
1245
 
1110
1246
  class JobFilterForm(BootstrapMixin, forms.Form):
1111
1247
  model = Job
@@ -1201,6 +1337,64 @@ class JobHookFilterForm(BootstrapMixin, forms.Form):
1201
1337
  type_delete = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
1202
1338
 
1203
1339
 
1340
+ class JobQueueBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
1341
+ pk = forms.ModelMultipleChoiceField(
1342
+ queryset=JobQueue.objects.all(),
1343
+ widget=forms.MultipleHiddenInput(),
1344
+ )
1345
+ queue_type = forms.ChoiceField(
1346
+ choices=JobQueueTypeChoices,
1347
+ help_text="The job can either run immediately, once in the future, or on a recurring schedule.",
1348
+ label="Type",
1349
+ required=False,
1350
+ )
1351
+ tenant = DynamicModelChoiceField(
1352
+ queryset=Tenant.objects.all(),
1353
+ required=False,
1354
+ )
1355
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1356
+
1357
+ class Meta:
1358
+ model = JobQueue
1359
+ nullable_fields = [
1360
+ "secrets_group",
1361
+ "description",
1362
+ "tenant",
1363
+ ]
1364
+
1365
+
1366
+ class JobQueueFilterForm(NautobotFilterForm):
1367
+ model = JobQueue
1368
+ q = forms.CharField(required=False, label="Search")
1369
+ name = forms.CharField(required=False)
1370
+ jobs = DynamicModelMultipleChoiceField(queryset=Job.objects.all(), required=False)
1371
+ queue_type = forms.MultipleChoiceField(
1372
+ choices=JobQueueTypeChoices,
1373
+ required=False,
1374
+ widget=StaticSelect2Multiple(),
1375
+ )
1376
+ tenant = DynamicModelMultipleChoiceField(queryset=Tenant.objects.all(), to_field_name="name", required=False)
1377
+ tags = TagFilterField(model)
1378
+
1379
+
1380
+ class JobQueueForm(NautobotModelForm):
1381
+ name = forms.CharField(required=True, max_length=CHARFIELD_MAX_LENGTH)
1382
+ queue_type = forms.ChoiceField(
1383
+ choices=JobQueueTypeChoices,
1384
+ label="Queue Type",
1385
+ )
1386
+ tenant = DynamicModelChoiceField(
1387
+ queryset=Tenant.objects.all(),
1388
+ required=False,
1389
+ )
1390
+ description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1391
+ tags = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False)
1392
+
1393
+ class Meta:
1394
+ model = JobQueue
1395
+ fields = ("name", "queue_type", "description", "tenant", "tags")
1396
+
1397
+
1204
1398
  class JobScheduleForm(BootstrapMixin, forms.Form):
1205
1399
  """
1206
1400
  This form is rendered alongside the JobForm but deals specifically with the fields needed to either
@@ -1223,7 +1417,6 @@ class JobScheduleForm(BootstrapMixin, forms.Form):
1223
1417
  required=False,
1224
1418
  label="Starting date and time",
1225
1419
  widget=DateTimePicker(),
1226
- help_text=f"The scheduled time is relative to the Nautobot configured timezone: {settings.TIME_ZONE}.",
1227
1420
  )
1228
1421
  _recurrence_custom_time = forms.CharField(
1229
1422
  required=False,
@@ -1260,6 +1453,16 @@ class JobScheduleForm(BootstrapMixin, forms.Form):
1260
1453
  except Exception as e:
1261
1454
  raise ValidationError({"_recurrence_custom_time": e})
1262
1455
 
1456
+ def __init__(self, *args, **kwargs):
1457
+ super().__init__(*args, **kwargs)
1458
+ # setting the help_text for `_schedule_start_time` here instead of in the field definition
1459
+ # because Django needs to be fully initialized before we can accurately retrieve the current timezone.
1460
+ self.fields[
1461
+ "_schedule_start_time"
1462
+ ].help_text = (
1463
+ f"The scheduled time is relative to the Nautobot configured timezone: {get_current_timezone_name()}."
1464
+ )
1465
+
1263
1466
 
1264
1467
  class JobResultFilterForm(BootstrapMixin, forms.Form):
1265
1468
  model = JobResult
@@ -1429,7 +1632,7 @@ class MetadataTypeFilterForm(NautobotFilterForm):
1429
1632
  tags = TagFilterField(model)
1430
1633
 
1431
1634
 
1432
- class MetadataTypeBulkEditForm(NautobotBulkEditForm):
1635
+ class MetadataTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
1433
1636
  pk = forms.ModelMultipleChoiceField(queryset=MetadataType.objects.all(), widget=forms.MultipleHiddenInput)
1434
1637
  description = forms.CharField(required=False, max_length=CHARFIELD_MAX_LENGTH)
1435
1638
 
@@ -34,7 +34,7 @@ from nautobot.extras.utils import remove_prefix_from_cf_key
34
34
  logger = logging.getLogger(__name__)
35
35
 
36
36
 
37
- __all__ = (
37
+ __all__ = ( # noqa:RUF022
38
38
  "ContactTeamModelFilterFormMixin",
39
39
  "CustomFieldModelBulkEditFormMixin",
40
40
  "CustomFieldModelFilterFormMixin",
@@ -673,7 +673,7 @@ class RelationshipModelFormMixin(forms.ModelForm):
673
673
  for peer_id in target_peer_ids:
674
674
  relationship = self.fields[field_name].model
675
675
  if not relationship.symmetric:
676
- association = RelationshipAssociation(
676
+ association = RelationshipAssociation( # pylint: disable=repeated-keyword
677
677
  relationship=relationship,
678
678
  **{
679
679
  f"{side}_type": self.obj_type,