nautobot 2.3.16__py3-none-any.whl → 2.4.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.

Potentially problematic release.


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

Files changed (675) hide show
  1. nautobot/__init__.py +15 -0
  2. nautobot/apps/api.py +0 -2
  3. nautobot/apps/config.py +32 -3
  4. nautobot/apps/events.py +19 -0
  5. nautobot/apps/exceptions.py +0 -2
  6. nautobot/apps/ui.py +44 -9
  7. nautobot/apps/utils.py +0 -8
  8. nautobot/apps/views.py +2 -0
  9. nautobot/circuits/navigation.py +0 -57
  10. nautobot/circuits/tables.py +1 -2
  11. nautobot/circuits/templates/circuits/circuit_retrieve.html +0 -71
  12. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -64
  13. nautobot/circuits/templates/circuits/inc/circuit_termination_cable_fragment.html +40 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +26 -0
  15. nautobot/circuits/templates/circuits/provider_retrieve.html +0 -76
  16. nautobot/circuits/tests/integration/test_relationships.py +33 -24
  17. nautobot/circuits/tests/test_filters.py +4 -8
  18. nautobot/circuits/views.py +143 -26
  19. nautobot/cloud/factory.py +4 -1
  20. nautobot/cloud/models.py +1 -1
  21. nautobot/cloud/tests/test_filters.py +5 -4
  22. nautobot/core/api/fields.py +5 -5
  23. nautobot/core/api/metadata.py +28 -256
  24. nautobot/core/api/pagination.py +3 -2
  25. nautobot/core/api/renderers.py +3 -0
  26. nautobot/core/api/serializers.py +24 -244
  27. nautobot/core/api/urls.py +3 -4
  28. nautobot/core/api/utils.py +0 -62
  29. nautobot/core/api/views.py +48 -158
  30. nautobot/core/apps/__init__.py +22 -578
  31. nautobot/core/celery/__init__.py +13 -0
  32. nautobot/core/celery/log.py +4 -4
  33. nautobot/core/celery/schedulers.py +48 -3
  34. nautobot/core/cli/__init__.py +8 -0
  35. nautobot/core/constants.py +7 -0
  36. nautobot/core/events/__init__.py +116 -0
  37. nautobot/core/events/base.py +27 -0
  38. nautobot/core/events/exceptions.py +10 -0
  39. nautobot/core/events/redis_broker.py +48 -0
  40. nautobot/core/events/syslog_broker.py +19 -0
  41. nautobot/core/exceptions.py +0 -6
  42. nautobot/core/filters.py +16 -21
  43. nautobot/core/fixtures/user-data.json +59 -0
  44. nautobot/core/forms/fields.py +53 -8
  45. nautobot/core/forms/utils.py +2 -1
  46. nautobot/core/graphql/schema.py +3 -1
  47. nautobot/core/graphql/types.py +1 -1
  48. nautobot/core/jobs/__init__.py +4 -4
  49. nautobot/core/jobs/cleanup.py +13 -49
  50. nautobot/core/jobs/groups.py +1 -1
  51. nautobot/core/management/commands/generate_test_data.py +21 -0
  52. nautobot/core/management/commands/validate_models.py +1 -1
  53. nautobot/core/middleware.py +16 -0
  54. nautobot/core/models/__init__.py +1 -1
  55. nautobot/core/models/fields.py +11 -7
  56. nautobot/core/models/query_functions.py +2 -2
  57. nautobot/core/models/tree_queries.py +3 -6
  58. nautobot/core/settings.py +44 -7
  59. nautobot/core/settings.yaml +86 -8
  60. nautobot/core/tables.py +15 -65
  61. nautobot/core/tasks.py +1 -1
  62. nautobot/core/templates/components/button/default.html +7 -0
  63. nautobot/core/templates/components/button/dropdown.html +20 -0
  64. nautobot/core/templates/components/layout/one_over_two.html +19 -0
  65. nautobot/core/templates/components/layout/two_over_one.html +19 -0
  66. nautobot/core/templates/components/panel/body_content_data_table.html +27 -0
  67. nautobot/core/templates/components/panel/body_content_objects_table.html +4 -0
  68. nautobot/core/templates/components/panel/body_content_tags.html +6 -0
  69. nautobot/core/templates/components/panel/body_content_text.html +12 -0
  70. nautobot/core/templates/components/panel/body_wrapper_generic.html +3 -0
  71. nautobot/core/templates/components/panel/body_wrapper_key_value_table.html +3 -0
  72. nautobot/core/templates/components/panel/body_wrapper_table.html +3 -0
  73. nautobot/core/templates/components/panel/footer_contacts_table.html +20 -0
  74. nautobot/core/templates/components/panel/footer_content_table.html +14 -0
  75. nautobot/core/templates/components/panel/grouping_toggle.html +14 -0
  76. nautobot/core/templates/components/panel/header_extra_content_table.html +3 -0
  77. nautobot/core/templates/components/panel/panel.html +16 -0
  78. nautobot/core/templates/components/panel/stats_panel_body.html +8 -0
  79. nautobot/core/templates/components/tab/content_wrapper.html +3 -0
  80. nautobot/core/templates/components/tab/label_wrapper.html +5 -0
  81. nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +3 -0
  82. nautobot/core/templates/generic/object_retrieve.html +28 -17
  83. nautobot/core/templates/inc/computed_fields/panel_data.html +4 -7
  84. nautobot/core/templates/inc/custom_fields/panel.html +2 -2
  85. nautobot/core/templates/inc/custom_fields/panel_data.html +4 -7
  86. nautobot/core/templates/inc/footer.html +1 -0
  87. nautobot/core/templates/inc/media.html +0 -3
  88. nautobot/core/templates/inc/nav_menu.html +1 -1
  89. nautobot/core/templates/inc/relationships_panel.html +1 -1
  90. nautobot/core/templates/nautobot_config.py.j2 +3 -3
  91. nautobot/core/templates/panel_table.html +12 -0
  92. nautobot/core/templates/search.html +0 -7
  93. nautobot/core/templates/utilities/render_jinja2.html +117 -0
  94. nautobot/core/templatetags/helpers.py +101 -12
  95. nautobot/core/templatetags/ui_framework.py +40 -0
  96. nautobot/core/testing/api.py +23 -128
  97. nautobot/core/testing/context.py +18 -0
  98. nautobot/core/testing/filters.py +41 -58
  99. nautobot/core/testing/mixins.py +2 -7
  100. nautobot/core/testing/views.py +25 -123
  101. nautobot/core/tests/integration/test_app_home.py +1 -0
  102. nautobot/core/tests/integration/test_app_navbar.py +1 -0
  103. nautobot/core/tests/integration/test_filters.py +2 -0
  104. nautobot/core/tests/integration/test_home.py +1 -0
  105. nautobot/core/tests/integration/test_navbar.py +1 -0
  106. nautobot/core/tests/integration/test_view_authentication.py +1 -2
  107. nautobot/core/tests/nautobot_config.py +198 -0
  108. nautobot/core/tests/runner.py +3 -3
  109. nautobot/core/tests/test_api.py +82 -201
  110. nautobot/core/tests/test_csv.py +3 -25
  111. nautobot/core/tests/test_events.py +214 -0
  112. nautobot/core/tests/test_jinja_filters.py +1 -0
  113. nautobot/core/tests/test_jobs.py +84 -13
  114. nautobot/core/tests/test_navigations.py +7 -241
  115. nautobot/core/tests/test_templatetags_helpers.py +16 -0
  116. nautobot/core/tests/test_ui.py +150 -0
  117. nautobot/core/tests/test_utils.py +0 -25
  118. nautobot/core/tests/test_views.py +123 -31
  119. nautobot/core/ui/__init__.py +0 -0
  120. nautobot/core/ui/base.py +11 -0
  121. nautobot/core/ui/choices.py +44 -0
  122. nautobot/core/ui/homepage.py +167 -0
  123. nautobot/core/ui/nav.py +279 -0
  124. nautobot/core/ui/object_detail.py +1841 -0
  125. nautobot/core/ui/utils.py +36 -0
  126. nautobot/core/urls.py +4 -9
  127. nautobot/core/utils/config.py +30 -3
  128. nautobot/core/utils/lookup.py +20 -13
  129. nautobot/core/views/__init__.py +6 -1
  130. nautobot/core/views/generic.py +47 -52
  131. nautobot/core/views/mixins.py +15 -25
  132. nautobot/core/views/paginator.py +8 -5
  133. nautobot/core/views/renderers.py +3 -3
  134. nautobot/core/views/utils.py +11 -0
  135. nautobot/core/wsgi.py +3 -3
  136. nautobot/dcim/api/serializers.py +80 -179
  137. nautobot/dcim/api/urls.py +5 -0
  138. nautobot/dcim/api/views.py +17 -4
  139. nautobot/dcim/apps.py +1 -0
  140. nautobot/dcim/choices.py +28 -0
  141. nautobot/dcim/factory.py +58 -0
  142. nautobot/dcim/filters/__init__.py +197 -24
  143. nautobot/dcim/forms.py +203 -12
  144. nautobot/dcim/graphql/types.py +2 -2
  145. nautobot/dcim/migrations/0063_interfacevdcassignment_virtualdevicecontext_and_more.py +165 -0
  146. nautobot/dcim/migrations/0064_virtualdevicecontext_status_data_migration.py +28 -0
  147. nautobot/dcim/migrations/0065_controller_capabilities_and_more.py +29 -0
  148. nautobot/dcim/migrations/0066_controllermanageddevicegroup_radio_profiles_and_more.py +33 -0
  149. nautobot/dcim/models/__init__.py +4 -0
  150. nautobot/dcim/models/device_component_templates.py +2 -2
  151. nautobot/dcim/models/device_components.py +20 -22
  152. nautobot/dcim/models/devices.py +173 -4
  153. nautobot/dcim/models/locations.py +3 -3
  154. nautobot/dcim/models/power.py +5 -6
  155. nautobot/dcim/models/racks.py +6 -6
  156. nautobot/dcim/navigation.py +25 -224
  157. nautobot/dcim/signals.py +44 -0
  158. nautobot/dcim/tables/__init__.py +5 -3
  159. nautobot/dcim/tables/devices.py +96 -2
  160. nautobot/dcim/tables/devicetypes.py +2 -2
  161. nautobot/dcim/templates/dcim/controller/base.html +10 -0
  162. nautobot/dcim/templates/dcim/controller_create.html +1 -0
  163. nautobot/dcim/templates/dcim/controller_retrieve.html +5 -1
  164. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +25 -0
  165. nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +66 -0
  166. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +46 -0
  167. nautobot/dcim/templates/dcim/device/base.html +6 -42
  168. nautobot/dcim/templates/dcim/device/wireless.html +73 -0
  169. nautobot/dcim/templates/dcim/device.html +3 -1
  170. nautobot/dcim/templates/dcim/interface.html +1 -0
  171. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  172. nautobot/dcim/templates/dcim/locationtype.html +0 -107
  173. nautobot/dcim/templates/dcim/locationtype_retrieve.html +8 -0
  174. nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +76 -0
  175. nautobot/dcim/templates/dcim/virtualdevicecontext_update.html +34 -0
  176. nautobot/dcim/tests/test_api.py +172 -61
  177. nautobot/dcim/tests/test_filters.py +171 -109
  178. nautobot/dcim/tests/test_forms.py +2 -51
  179. nautobot/dcim/tests/test_graphql.py +0 -52
  180. nautobot/dcim/tests/test_models.py +126 -4
  181. nautobot/dcim/tests/test_signals.py +1 -0
  182. nautobot/dcim/tests/test_views.py +103 -11
  183. nautobot/dcim/urls.py +72 -27
  184. nautobot/dcim/utils.py +2 -2
  185. nautobot/dcim/views.py +369 -62
  186. nautobot/extras/api/customfields.py +2 -2
  187. nautobot/extras/api/serializers.py +91 -75
  188. nautobot/extras/api/urls.py +4 -0
  189. nautobot/extras/api/views.py +78 -15
  190. nautobot/extras/choices.py +13 -0
  191. nautobot/extras/constants.py +0 -1
  192. nautobot/extras/context_managers.py +23 -6
  193. nautobot/extras/datasources/git.py +4 -1
  194. nautobot/extras/factory.py +27 -0
  195. nautobot/extras/filters/__init__.py +59 -0
  196. nautobot/extras/forms/forms.py +125 -30
  197. nautobot/extras/forms/mixins.py +3 -11
  198. nautobot/extras/graphql/types.py +25 -1
  199. nautobot/extras/group_sync.py +3 -3
  200. nautobot/extras/health_checks.py +2 -1
  201. nautobot/extras/jobs.py +62 -26
  202. nautobot/extras/management/__init__.py +1 -0
  203. nautobot/extras/management/commands/runjob.py +7 -79
  204. nautobot/extras/management/commands/runjob_with_job_result.py +46 -0
  205. nautobot/extras/management/utils.py +87 -0
  206. nautobot/extras/managers.py +1 -3
  207. nautobot/extras/migrations/0018_joblog_data_migration.py +9 -7
  208. nautobot/extras/migrations/0117_create_job_queue_model.py +129 -0
  209. nautobot/extras/migrations/0118_task_queue_to_job_queue_migration.py +78 -0
  210. nautobot/extras/migrations/0119_remove_task_queues_from_job_and_queue_from_scheduled_job.py +28 -0
  211. nautobot/extras/models/__init__.py +4 -0
  212. nautobot/extras/models/change_logging.py +7 -3
  213. nautobot/extras/models/customfields.py +11 -12
  214. nautobot/extras/models/groups.py +9 -13
  215. nautobot/extras/models/jobs.py +218 -37
  216. nautobot/extras/models/models.py +2 -2
  217. nautobot/extras/models/relationships.py +69 -1
  218. nautobot/extras/models/secrets.py +5 -0
  219. nautobot/extras/navigation.py +20 -262
  220. nautobot/extras/plugins/__init__.py +56 -32
  221. nautobot/extras/plugins/marketplace_manifest.yml +450 -0
  222. nautobot/extras/plugins/urls.py +1 -0
  223. nautobot/extras/plugins/views.py +48 -1
  224. nautobot/extras/signals.py +39 -1
  225. nautobot/extras/tables.py +40 -6
  226. nautobot/extras/templates/extras/externalintegration_retrieve.html +0 -47
  227. nautobot/extras/templates/extras/inc/tags_panel.html +1 -5
  228. nautobot/extras/templates/extras/job_bulk_edit.html +2 -1
  229. nautobot/extras/templates/extras/job_detail.html +36 -6
  230. nautobot/extras/templates/extras/job_edit.html +5 -2
  231. nautobot/extras/templates/extras/job_list.html +2 -7
  232. nautobot/extras/templates/extras/jobqueue_retrieve.html +44 -0
  233. nautobot/extras/templates/extras/marketplace.html +278 -0
  234. nautobot/extras/templates/extras/plugins_list.html +35 -1
  235. nautobot/extras/templates/extras/plugins_tiles.html +79 -0
  236. nautobot/extras/templates/extras/role_retrieve.html +16 -0
  237. nautobot/extras/templates/extras/secret.html +0 -65
  238. nautobot/extras/templates/extras/secret_check.js +16 -0
  239. nautobot/extras/templates/extras/secret_create.html +114 -0
  240. nautobot/extras/templates/extras/secret_edit.html +1 -114
  241. nautobot/extras/templates/extras/secretsgroup_edit.html +1 -1
  242. nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +2 -0
  243. nautobot/extras/templatetags/job_buttons.py +5 -4
  244. nautobot/extras/templatetags/plugins.py +69 -6
  245. nautobot/extras/test_jobs/api_test_job.py +1 -1
  246. nautobot/extras/test_jobs/atomic_transaction.py +2 -2
  247. nautobot/extras/test_jobs/dry_run.py +1 -1
  248. nautobot/extras/test_jobs/fail.py +5 -5
  249. nautobot/extras/test_jobs/file_output.py +1 -1
  250. nautobot/extras/test_jobs/file_upload_fail.py +1 -1
  251. nautobot/extras/test_jobs/file_upload_pass.py +1 -1
  252. nautobot/extras/test_jobs/ipaddress_vars.py +1 -3
  253. nautobot/extras/test_jobs/jobs_module/jobs_submodule/jobs.py +1 -1
  254. nautobot/extras/test_jobs/location_with_custom_field.py +1 -1
  255. nautobot/extras/test_jobs/log_redaction.py +1 -1
  256. nautobot/extras/test_jobs/log_skip_db_logging.py +1 -1
  257. nautobot/extras/test_jobs/modify_db.py +1 -1
  258. nautobot/extras/test_jobs/object_var_optional.py +1 -1
  259. nautobot/extras/test_jobs/object_var_required.py +1 -1
  260. nautobot/extras/test_jobs/object_vars.py +1 -1
  261. nautobot/extras/test_jobs/pass.py +3 -3
  262. nautobot/extras/test_jobs/profiling.py +1 -1
  263. nautobot/extras/test_jobs/relative_import.py +3 -3
  264. nautobot/extras/test_jobs/soft_time_limit_greater_than_time_limit.py +1 -1
  265. nautobot/extras/test_jobs/task_queues.py +1 -1
  266. nautobot/extras/tests/integration/test_plugin_banner.py +2 -0
  267. nautobot/extras/tests/test_api.py +157 -55
  268. nautobot/extras/tests/test_context_managers.py +4 -1
  269. nautobot/extras/tests/test_customfields.py +1 -1
  270. nautobot/extras/tests/test_datasources.py +1 -2
  271. nautobot/extras/tests/test_dynamicgroups.py +1 -1
  272. nautobot/extras/tests/test_filters.py +219 -535
  273. nautobot/extras/tests/test_forms.py +1 -20
  274. nautobot/extras/tests/test_job_variables.py +73 -152
  275. nautobot/extras/tests/test_jobs.py +43 -54
  276. nautobot/extras/tests/test_models.py +71 -16
  277. nautobot/extras/tests/test_relationships.py +5 -2
  278. nautobot/extras/tests/test_utils.py +23 -2
  279. nautobot/extras/tests/test_views.py +183 -43
  280. nautobot/extras/tests/test_webhooks.py +2 -1
  281. nautobot/extras/urls.py +2 -20
  282. nautobot/extras/utils.py +118 -4
  283. nautobot/extras/views.py +203 -92
  284. nautobot/extras/webhooks.py +5 -2
  285. nautobot/ipam/api/fields.py +3 -3
  286. nautobot/ipam/api/serializers.py +36 -137
  287. nautobot/ipam/api/views.py +93 -62
  288. nautobot/ipam/lookups.py +62 -101
  289. nautobot/ipam/models.py +11 -63
  290. nautobot/ipam/navigation.py +0 -90
  291. nautobot/ipam/querysets.py +2 -2
  292. nautobot/ipam/tables.py +6 -20
  293. nautobot/ipam/templates/ipam/routetarget.html +0 -28
  294. nautobot/ipam/templates/ipam/vrf.html +0 -47
  295. nautobot/ipam/tests/test_api.py +8 -419
  296. nautobot/ipam/tests/test_filters.py +39 -119
  297. nautobot/ipam/tests/test_forms.py +47 -51
  298. nautobot/ipam/tests/test_migrations.py +30 -30
  299. nautobot/ipam/tests/test_models.py +0 -41
  300. nautobot/ipam/tests/test_querysets.py +1 -63
  301. nautobot/ipam/urls.py +3 -69
  302. nautobot/ipam/utils/__init__.py +0 -24
  303. nautobot/ipam/views.py +153 -198
  304. nautobot/project-static/css/base.css +38 -3
  305. nautobot/project-static/docs/404.html +421 -19
  306. nautobot/project-static/docs/apps/index.html +421 -19
  307. nautobot/project-static/docs/apps/nautobot-apps.html +421 -19
  308. nautobot/project-static/docs/assets/extra.css +5 -1
  309. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js → bundle.83f73b43.min.js} +2 -2
  310. nautobot/project-static/docs/assets/javascripts/{bundle.88dd0f4e.min.js.map → bundle.83f73b43.min.js.map} +2 -2
  311. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +421 -19
  312. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +421 -19
  313. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +421 -172
  314. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +421 -19
  315. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +421 -19
  316. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +425 -21
  317. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +421 -19
  318. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +424 -22
  319. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +9809 -0
  320. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +424 -63
  321. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +421 -19
  322. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +421 -19
  323. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +457 -20
  324. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +421 -19
  325. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +425 -25
  326. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +457 -19
  327. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +421 -19
  328. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +421 -19
  329. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +425 -215
  330. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +430 -342
  331. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +5799 -1054
  332. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +421 -19
  333. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +447 -176
  334. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +460 -21
  335. nautobot/project-static/docs/development/apps/api/configuration-view.html +421 -19
  336. nautobot/project-static/docs/development/apps/api/database-backend-config.html +421 -19
  337. nautobot/project-static/docs/development/apps/api/models/django-admin.html +421 -19
  338. nautobot/project-static/docs/development/apps/api/models/global-search.html +421 -19
  339. nautobot/project-static/docs/development/apps/api/models/graphql.html +421 -19
  340. nautobot/project-static/docs/development/apps/api/models/index.html +421 -19
  341. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +421 -19
  342. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +421 -19
  343. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +421 -19
  344. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +421 -19
  345. nautobot/project-static/docs/development/apps/api/platform-features/index.html +421 -19
  346. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +421 -19
  347. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +421 -19
  348. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +421 -19
  349. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +421 -19
  350. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +424 -41
  351. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +421 -19
  352. nautobot/project-static/docs/development/apps/api/prometheus.html +421 -19
  353. nautobot/project-static/docs/development/apps/api/setup.html +425 -155
  354. nautobot/project-static/docs/development/apps/api/testing.html +421 -19
  355. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +421 -19
  356. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +421 -19
  357. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +421 -19
  358. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +421 -19
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +701 -130
  360. nautobot/project-static/docs/development/apps/api/views/base-template.html +421 -19
  361. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +421 -19
  362. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +421 -19
  363. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +421 -19
  364. nautobot/project-static/docs/development/apps/api/views/index.html +423 -20
  365. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +425 -19
  366. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +451 -19
  367. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +421 -19
  368. nautobot/project-static/docs/development/apps/api/views/notes.html +421 -19
  369. nautobot/project-static/docs/development/apps/api/views/rest-api.html +421 -19
  370. nautobot/project-static/docs/development/apps/api/views/urls.html +421 -19
  371. nautobot/project-static/docs/development/apps/index.html +421 -19
  372. nautobot/project-static/docs/development/apps/migration/code-updates.html +422 -52
  373. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +422 -20
  374. nautobot/project-static/docs/development/apps/migration/from-v1.html +421 -19
  375. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +421 -19
  376. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +421 -19
  377. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +421 -19
  378. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +424 -22
  379. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +9219 -0
  380. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +9333 -0
  381. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +9474 -0
  382. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +9517 -0
  383. nautobot/project-static/docs/development/apps/porting-from-netbox.html +424 -22
  384. nautobot/project-static/docs/development/core/application-registry.html +421 -19
  385. nautobot/project-static/docs/development/core/best-practices.html +421 -19
  386. nautobot/project-static/docs/development/core/bootstrap-ui.html +421 -19
  387. nautobot/project-static/docs/development/core/caching.html +421 -19
  388. nautobot/project-static/docs/development/core/controllers.html +423 -19
  389. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +490 -45
  390. nautobot/project-static/docs/development/core/generic-views.html +421 -19
  391. nautobot/project-static/docs/development/core/getting-started.html +566 -179
  392. nautobot/project-static/docs/development/core/homepage.html +432 -30
  393. nautobot/project-static/docs/development/core/index.html +421 -19
  394. nautobot/project-static/docs/development/core/local-k8s.html +9453 -0
  395. nautobot/project-static/docs/development/core/model-checklist.html +424 -22
  396. nautobot/project-static/docs/development/core/model-features.html +421 -19
  397. nautobot/project-static/docs/development/core/natural-keys.html +421 -19
  398. nautobot/project-static/docs/development/core/navigation-menu.html +438 -26
  399. nautobot/project-static/docs/development/core/release-checklist.html +435 -45
  400. nautobot/project-static/docs/development/core/role-internals.html +421 -19
  401. nautobot/project-static/docs/development/core/settings.html +421 -19
  402. nautobot/project-static/docs/development/core/style-guide.html +421 -19
  403. nautobot/project-static/docs/development/core/templates.html +431 -22
  404. nautobot/project-static/docs/development/core/testing.html +421 -19
  405. nautobot/project-static/docs/development/core/ui-component-framework.html +11020 -0
  406. nautobot/project-static/docs/development/core/user-preferences.html +424 -22
  407. nautobot/project-static/docs/development/index.html +421 -19
  408. nautobot/project-static/docs/development/jobs/index.html +546 -160
  409. nautobot/project-static/docs/development/jobs/migration/from-v1.html +421 -19
  410. nautobot/project-static/docs/index.html +421 -19
  411. nautobot/project-static/docs/media/development/core/ui-component-framework/basic-panel-layout.png +0 -0
  412. nautobot/project-static/docs/media/development/core/ui-component-framework/button-example.png +0 -0
  413. nautobot/project-static/docs/media/development/core/ui-component-framework/dropdown-button-example.png +0 -0
  414. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-1.png +0 -0
  415. nautobot/project-static/docs/media/development/core/ui-component-framework/grouped-key-value-table-panel-example-2.png +0 -0
  416. nautobot/project-static/docs/media/development/core/ui-component-framework/object-fields-panel-example.png +0 -0
  417. nautobot/project-static/docs/media/development/core/ui-component-framework/stats-panel-example.png +0 -0
  418. nautobot/project-static/docs/media/development/core/ui-component-framework/table-panels-family.png +0 -0
  419. nautobot/project-static/docs/media/development/core/ui-component-framework/text-panels-family.png +0 -0
  420. nautobot/project-static/docs/media/development/core/ui-component-framework/ui-framework-example.png +0 -0
  421. nautobot/project-static/docs/media/models/virtual_device_context_overview.drawio +73 -0
  422. nautobot/project-static/docs/media/models/virtual_device_context_overview.png +0 -0
  423. nautobot/project-static/docs/models/dcim/virtualdevicecontext.html +14 -0
  424. nautobot/project-static/docs/models/extras/jobqueue.html +14 -0
  425. nautobot/project-static/docs/models/wireless/radioprofile.html +14 -0
  426. nautobot/project-static/docs/models/wireless/supporteddatarate.html +14 -0
  427. nautobot/project-static/docs/models/wireless/wirelessnetwork.html +14 -0
  428. nautobot/project-static/docs/objects.inv +0 -0
  429. nautobot/project-static/docs/overview/application_stack.html +426 -20
  430. nautobot/project-static/docs/overview/design_philosophy.html +421 -19
  431. nautobot/project-static/docs/release-notes/index.html +445 -22
  432. nautobot/project-static/docs/release-notes/version-1.0.html +421 -19
  433. nautobot/project-static/docs/release-notes/version-1.1.html +421 -19
  434. nautobot/project-static/docs/release-notes/version-1.2.html +421 -19
  435. nautobot/project-static/docs/release-notes/version-1.3.html +421 -19
  436. nautobot/project-static/docs/release-notes/version-1.4.html +421 -19
  437. nautobot/project-static/docs/release-notes/version-1.5.html +421 -19
  438. nautobot/project-static/docs/release-notes/version-1.6.html +634 -667
  439. nautobot/project-static/docs/release-notes/version-2.0.html +421 -19
  440. nautobot/project-static/docs/release-notes/version-2.1.html +421 -19
  441. nautobot/project-static/docs/release-notes/version-2.2.html +421 -19
  442. nautobot/project-static/docs/release-notes/version-2.3.html +684 -886
  443. nautobot/project-static/docs/release-notes/version-2.4.html +10007 -0
  444. nautobot/project-static/docs/requirements.txt +2 -2
  445. nautobot/project-static/docs/search/search_index.json +1 -1
  446. nautobot/project-static/docs/sitemap.xml +334 -270
  447. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  448. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +421 -19
  449. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +421 -19
  450. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +423 -21
  451. nautobot/project-static/docs/user-guide/administration/configuration/index.html +433 -32
  452. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +421 -19
  453. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +765 -180
  454. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +421 -19
  455. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +421 -19
  456. nautobot/project-static/docs/user-guide/administration/guides/docker.html +434 -29
  457. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +421 -19
  458. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +421 -19
  459. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +421 -19
  460. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +421 -19
  461. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +421 -19
  462. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +421 -19
  463. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +421 -19
  464. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +421 -19
  465. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +421 -19
  466. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +421 -19
  467. nautobot/project-static/docs/user-guide/administration/installation/index.html +426 -20
  468. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +421 -19
  469. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +421 -19
  470. nautobot/project-static/docs/user-guide/administration/installation/services.html +421 -19
  471. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +421 -19
  472. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +442 -41
  473. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +435 -66
  474. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +435 -66
  475. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +421 -19
  476. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +421 -19
  477. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +421 -19
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +421 -19
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +421 -19
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +421 -19
  481. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +421 -19
  482. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/tables/v2-code-nautobot-app-location.yaml +0 -16
  483. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +421 -19
  484. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +427 -21
  485. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +421 -19
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +421 -19
  487. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +421 -19
  488. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +421 -19
  489. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +421 -19
  490. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +421 -19
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +421 -19
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +421 -19
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +421 -19
  494. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +421 -19
  495. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +421 -19
  496. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +421 -19
  497. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +421 -19
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +421 -19
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +421 -19
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +421 -19
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +421 -19
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +457 -20
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +447 -22
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +421 -19
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +421 -19
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +421 -19
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +421 -19
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +421 -19
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +421 -19
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +421 -19
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +421 -19
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +421 -19
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +421 -19
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +421 -19
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +421 -19
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +421 -19
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +421 -19
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +421 -19
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +421 -19
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +421 -19
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +421 -19
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +421 -19
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +421 -19
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +421 -19
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +421 -19
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +421 -19
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +421 -19
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +421 -19
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +421 -19
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +421 -19
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +421 -19
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +421 -19
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +421 -19
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +421 -19
  535. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +421 -19
  536. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +421 -19
  537. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +421 -19
  538. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +9333 -0
  539. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +424 -22
  540. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +421 -19
  541. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +421 -19
  542. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +421 -19
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +421 -19
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +421 -19
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +421 -19
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +421 -19
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +421 -19
  548. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +421 -19
  549. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +421 -19
  550. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +421 -19
  551. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +421 -19
  552. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +421 -19
  553. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +421 -19
  554. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +421 -19
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +421 -19
  556. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +421 -19
  557. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +421 -19
  558. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +421 -19
  559. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +424 -22
  560. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +9271 -0
  561. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +9175 -0
  562. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +9169 -0
  563. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +9235 -0
  564. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +421 -19
  565. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +421 -19
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +421 -19
  567. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +421 -19
  568. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +421 -19
  569. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +421 -19
  570. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +421 -19
  571. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +421 -19
  572. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +421 -19
  573. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +421 -19
  574. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +421 -19
  575. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +421 -19
  576. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +421 -19
  577. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +421 -19
  578. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +421 -19
  579. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +421 -19
  580. nautobot/project-static/docs/user-guide/index.html +421 -19
  581. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +424 -22
  582. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +421 -19
  583. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +421 -19
  584. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +421 -19
  585. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +421 -19
  586. nautobot/project-static/docs/user-guide/platform-functionality/events.html +9575 -0
  587. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +424 -22
  588. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +421 -19
  589. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +421 -19
  590. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +421 -19
  591. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +421 -19
  592. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +421 -19
  593. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +426 -20
  594. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +424 -22
  595. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +421 -19
  596. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +421 -19
  597. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +9182 -0
  598. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +424 -22
  599. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +421 -19
  600. nautobot/project-static/docs/user-guide/platform-functionality/note.html +421 -19
  601. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +421 -19
  602. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +424 -22
  603. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +9250 -0
  604. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +421 -19
  605. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +421 -19
  606. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +424 -22
  607. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +421 -19
  608. nautobot/project-static/docs/user-guide/platform-functionality/role.html +421 -19
  609. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +421 -19
  610. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +421 -19
  611. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +424 -22
  612. nautobot/project-static/docs/user-guide/platform-functionality/status.html +421 -19
  613. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +421 -19
  614. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +489 -56
  615. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +421 -19
  616. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +421 -19
  617. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +421 -19
  618. nautobot/project-static/img/jinja_logo.svg +97 -0
  619. nautobot/project-static/js/forms.js +5 -0
  620. nautobot/project-static/js/nav_menu.js +2 -1
  621. nautobot/tenancy/api/serializers.py +0 -2
  622. nautobot/tenancy/factory.py +1 -1
  623. nautobot/tenancy/navigation.py +0 -29
  624. nautobot/tenancy/templates/tenancy/tenant.html +4 -91
  625. nautobot/tenancy/tests/test_filters.py +29 -134
  626. nautobot/tenancy/views.py +32 -23
  627. nautobot/users/admin.py +3 -1
  628. nautobot/users/api/serializers.py +4 -5
  629. nautobot/users/api/views.py +1 -1
  630. nautobot/users/forms.py +19 -0
  631. nautobot/users/templates/users/preferences.html +22 -0
  632. nautobot/users/tests/test_filters.py +1 -19
  633. nautobot/users/tests/test_views.py +57 -0
  634. nautobot/users/utils.py +8 -0
  635. nautobot/users/views.py +48 -11
  636. nautobot/virtualization/api/serializers.py +4 -4
  637. nautobot/virtualization/filters.py +2 -20
  638. nautobot/virtualization/navigation.py +0 -48
  639. nautobot/virtualization/templates/virtualization/clustertype.html +0 -39
  640. nautobot/virtualization/tests/test_filters.py +57 -183
  641. nautobot/virtualization/views.py +18 -15
  642. nautobot/wireless/__init__.py +0 -0
  643. nautobot/wireless/api/__init__.py +0 -0
  644. nautobot/wireless/api/serializers.py +44 -0
  645. nautobot/wireless/api/urls.py +20 -0
  646. nautobot/wireless/api/views.py +34 -0
  647. nautobot/wireless/apps.py +8 -0
  648. nautobot/wireless/choices.py +345 -0
  649. nautobot/wireless/factory.py +138 -0
  650. nautobot/wireless/filters.py +167 -0
  651. nautobot/wireless/forms.py +283 -0
  652. nautobot/wireless/homepage.py +19 -0
  653. nautobot/wireless/migrations/0001_initial.py +223 -0
  654. nautobot/wireless/migrations/__init__.py +0 -0
  655. nautobot/wireless/models.py +207 -0
  656. nautobot/wireless/navigation.py +105 -0
  657. nautobot/wireless/tables.py +244 -0
  658. nautobot/wireless/templates/wireless/radioprofile_retrieve.html +81 -0
  659. nautobot/wireless/templates/wireless/supporteddatarate_retrieve.html +26 -0
  660. nautobot/wireless/templates/wireless/wirelessnetwork_create.html +88 -0
  661. nautobot/wireless/templates/wireless/wirelessnetwork_retrieve.html +64 -0
  662. nautobot/wireless/tests/__init__.py +0 -0
  663. nautobot/wireless/tests/test_api.py +247 -0
  664. nautobot/wireless/tests/test_filters.py +54 -0
  665. nautobot/wireless/tests/test_models.py +22 -0
  666. nautobot/wireless/tests/test_views.py +378 -0
  667. nautobot/wireless/urls.py +13 -0
  668. nautobot/wireless/views.py +129 -0
  669. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/METADATA +11 -14
  670. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/RECORD +674 -551
  671. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/WHEEL +1 -1
  672. nautobot/core/utils/navigation.py +0 -54
  673. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/LICENSE.txt +0 -0
  674. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/NOTICE +0 -0
  675. {nautobot-2.3.16.dist-info → nautobot-2.4.0b1.dist-info}/entry_points.txt +0 -0
@@ -9,6 +9,7 @@ from django.urls import resolve
9
9
  from django_tables2 import RequestConfig
10
10
  from rest_framework import renderers
11
11
 
12
+ from nautobot.core.constants import MAX_PAGE_SIZE_DEFAULT
12
13
  from nautobot.core.forms import (
13
14
  restrict_form_fields,
14
15
  SearchForm,
@@ -124,7 +125,7 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
124
125
  "paginator_class": EnhancedPaginator,
125
126
  "per_page": get_paginate_count(request, self.saved_view),
126
127
  }
127
- max_page_size = get_settings_or_config("MAX_PAGE_SIZE")
128
+ max_page_size = get_settings_or_config("MAX_PAGE_SIZE", fallback=MAX_PAGE_SIZE_DEFAULT)
128
129
  if max_page_size and paginate["per_page"] > max_page_size:
129
130
  messages.warning(
130
131
  request,
@@ -294,6 +295,7 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
294
295
  "verbose_name_plural": queryset.model._meta.verbose_name_plural,
295
296
  }
296
297
  if view.action == "retrieve":
298
+ context["object_detail_content"] = view.object_detail_content
297
299
  context.update(common_detail_view_context(request, instance))
298
300
  elif view.action == "list":
299
301
  # Construct valid actions for list view.
@@ -365,6 +367,4 @@ class NautobotHTMLRenderer(renderers.BrowsableAPIRenderer):
365
367
  # See form_valid() for self.action == "bulk_create".
366
368
  self.template = data.get("template", view.get_template_name())
367
369
 
368
- # NautobotUIViewSets pass "use_new_ui" in context as they share the same class and are just different methods
369
- self.use_new_ui = data.get("use_new_ui", False)
370
370
  return super().render(data, accepted_media_type=accepted_media_type, renderer_context=renderer_context)
@@ -98,6 +98,17 @@ def csv_format(data):
98
98
  return ",".join(csv)
99
99
 
100
100
 
101
+ def get_obj_from_context(context, key=None):
102
+ """From the given context, return the `object` that is in the context.
103
+
104
+ If a key is specified, return the value for that key.
105
+ Otherwise return the value for either of the keys `"obj"` or `"object"` as default behavior.
106
+ """
107
+ if key is not None:
108
+ return context.get(key)
109
+ return context.get("obj") or context.get("object")
110
+
111
+
101
112
  def get_csv_form_fields_from_serializer_class(serializer_class):
102
113
  """From the given serializer class, build a list of field dicts suitable for rendering in the CSV import form."""
103
114
  serializer = serializer_class(context={"request": None, "depth": 0})
nautobot/core/wsgi.py CHANGED
@@ -6,6 +6,8 @@ from django.db import connections
6
6
 
7
7
  import nautobot
8
8
 
9
+ logger = logging.getLogger(__name__)
10
+
9
11
  # This is the Django default left here for visibility on how the Nautobot pattern
10
12
  # differs.
11
13
  # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "nautobot.core.settings")
@@ -24,9 +26,7 @@ try:
24
26
  def fix_uwsgi():
25
27
  import uwsgi
26
28
 
27
- logging.getLogger(__name__).info(
28
- f"Closing existing DB and cache connections on worker {uwsgi.worker_id()} after uWSGI forked ..."
29
- )
29
+ logger.info("Closing existing DB and cache connections on worker %s after uWSGI forked ...", uwsgi.worker_id())
30
30
  connections.close_all()
31
31
  cache.close_caches()
32
32
 
@@ -27,6 +27,7 @@ from nautobot.dcim.choices import (
27
27
  CableLengthUnitChoices,
28
28
  CableTypeChoices,
29
29
  ConsolePortTypeChoices,
30
+ ControllerCapabilitiesChoices,
30
31
  DeviceFaceChoices,
31
32
  DeviceRedundancyGroupFailoverStrategyChoices,
32
33
  InterfaceModeChoices,
@@ -69,6 +70,7 @@ from nautobot.dcim.models import (
69
70
  InterfaceRedundancyGroup,
70
71
  InterfaceRedundancyGroupAssociation,
71
72
  InterfaceTemplate,
73
+ InterfaceVDCAssignment,
72
74
  InventoryItem,
73
75
  Location,
74
76
  LocationType,
@@ -93,6 +95,7 @@ from nautobot.dcim.models import (
93
95
  SoftwareImageFile,
94
96
  SoftwareVersion,
95
97
  VirtualChassis,
98
+ VirtualDeviceContext,
96
99
  )
97
100
  from nautobot.extras.api.mixins import (
98
101
  TaggedModelSerializerMixin,
@@ -223,7 +226,6 @@ class LocationTypeSerializer(TreeModelSerializerMixin, NautobotModelSerializer):
223
226
  class Meta:
224
227
  model = LocationType
225
228
  fields = "__all__"
226
- list_display_fields = ["name", "nestable", "content_types", "description"]
227
229
 
228
230
 
229
231
  class LocationSerializer(
@@ -242,47 +244,18 @@ class LocationSerializer(
242
244
  class Meta:
243
245
  model = Location
244
246
  fields = "__all__"
245
- list_display_fields = ["name", "status", "parent", "tenant", "description", "tags"]
246
247
  # https://www.django-rest-framework.org/api-guide/validators/#optional-fields
247
248
  validators = []
248
249
 
249
- detail_view_config = {
250
- "layout": [
251
- {
252
- "Location": {
253
- "fields": [
254
- "location_type",
255
- "tenant",
256
- "facility",
257
- "asn",
258
- "time_zone",
259
- "description",
260
- ]
261
- },
262
- "Contact Info": {
263
- "fields": [
264
- "physical_address",
265
- "shipping_address",
266
- "latitude",
267
- "longitude",
268
- "contact_name",
269
- "contact_phone",
270
- "contact_email",
271
- ]
272
- },
273
- },
274
- ],
275
- }
276
-
277
- def validate(self, attrs):
250
+ def validate(self, data):
278
251
  # Validate uniqueness of (parent, name) since we omitted the automatically created validator from Meta.
279
- if attrs.get("parent") and attrs.get("name"):
252
+ if data.get("parent") and data.get("name"):
280
253
  validator = UniqueTogetherValidator(queryset=Location.objects.all(), fields=("parent", "name"))
281
- validator(attrs, self)
254
+ validator(data, self)
282
255
 
283
- super().validate(attrs)
256
+ super().validate(data)
284
257
 
285
- return attrs
258
+ return data
286
259
 
287
260
 
288
261
  #
@@ -296,7 +269,6 @@ class RackGroupSerializer(TreeModelSerializerMixin, NautobotModelSerializer):
296
269
  class Meta:
297
270
  model = RackGroup
298
271
  fields = "__all__"
299
- list_display_fields = ["name", "location", "rack_count", "description"]
300
272
 
301
273
 
302
274
  class RackSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
@@ -309,39 +281,24 @@ class RackSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
309
281
  class Meta:
310
282
  model = Rack
311
283
  fields = "__all__"
312
- list_display_fields = ["name", "location", "rack_group", "status", "facility_id", "tenant", "role", "u_height"]
313
284
  # Omit the UniqueTogetherValidators that would be automatically added to validate (rack_group, facility_id) and (rack_group, name).
314
285
  # This prevents facility_id and rack_group from being interpreted as required fields.
315
286
  validators = []
316
- detail_view_config = {
317
- "layout": [
318
- {
319
- "Rack": {
320
- "fields": [
321
- "name",
322
- "location",
323
- "rack_group",
324
- ]
325
- },
326
- },
327
- ],
328
- "include_others": True,
329
- }
330
287
 
331
- def validate(self, attrs):
288
+ def validate(self, data):
332
289
  # Validate uniqueness of (rack_group, name) since we omitted the automatically-created validator above.
333
- if attrs.get("rack_group", None):
290
+ if data.get("rack_group", None):
334
291
  validator = UniqueTogetherValidator(queryset=Rack.objects.all(), fields=("rack_group", "name"))
335
- validator(attrs, self)
292
+ validator(data, self)
336
293
  # Validate uniqueness of (rack_group, facility_id) since we omitted the automatically-created validator above.
337
- if attrs.get("facility_id", None) and attrs.get("rack_group", None):
294
+ if data.get("facility_id", None) and data.get("rack_group", None):
338
295
  validator = UniqueTogetherValidator(queryset=Rack.objects.all(), fields=("rack_group", "facility_id"))
339
- validator(attrs, self)
296
+ validator(data, self)
340
297
 
341
298
  # Enforce model validation
342
- super().validate(attrs)
299
+ super().validate(data)
343
300
 
344
- return attrs
301
+ return data
345
302
 
346
303
 
347
304
  class RackUnitSerializer(serializers.Serializer):
@@ -359,7 +316,6 @@ class RackReservationSerializer(TaggedModelSerializerMixin, NautobotModelSeriali
359
316
  class Meta:
360
317
  model = RackReservation
361
318
  fields = "__all__"
362
- list_display_fields = ["pk", "rack", "units", "user", "description"]
363
319
  extra_kwargs = {
364
320
  "units": {"help_text": "List of rack unit numbers to reserve"},
365
321
  "user": {
@@ -392,8 +348,8 @@ class RackElevationDetailFilterSerializer(serializers.Serializer):
392
348
  is_occupied = serializers.BooleanField(required=False, allow_null=True, default=None)
393
349
 
394
350
  def validate(self, attrs):
395
- attrs.setdefault("unit_width", get_settings_or_config("RACK_ELEVATION_DEFAULT_UNIT_WIDTH"))
396
- attrs.setdefault("unit_height", get_settings_or_config("RACK_ELEVATION_DEFAULT_UNIT_HEIGHT"))
351
+ attrs.setdefault("unit_width", get_settings_or_config("RACK_ELEVATION_DEFAULT_UNIT_WIDTH", fallback=230))
352
+ attrs.setdefault("unit_height", get_settings_or_config("RACK_ELEVATION_DEFAULT_UNIT_HEIGHT", fallback=22))
397
353
  return attrs
398
354
 
399
355
 
@@ -411,7 +367,6 @@ class ManufacturerSerializer(NautobotModelSerializer):
411
367
  class Meta:
412
368
  model = Manufacturer
413
369
  fields = "__all__"
414
- list_display_fields = ["name", "device_type_count", "platform_count", "description"]
415
370
 
416
371
 
417
372
  class DeviceFamilySerializer(NautobotModelSerializer):
@@ -420,7 +375,6 @@ class DeviceFamilySerializer(NautobotModelSerializer):
420
375
  class Meta:
421
376
  model = DeviceFamily
422
377
  fields = "__all__"
423
- list_display_fields = ["name", "device_type_count", "description"]
424
378
 
425
379
 
426
380
  class DeviceTypeSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
@@ -432,28 +386,7 @@ class DeviceTypeSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
432
386
  class Meta:
433
387
  model = DeviceType
434
388
  fields = "__all__"
435
- list_display_fields = ["model", "manufacturer", "part_number", "u_height", "is_full_depth", "device_count"]
436
-
437
- detail_view_config = {
438
- "layout": [
439
- {
440
- "Chassis": {
441
- "fields": [
442
- "manufacturer",
443
- "model",
444
- "part_number",
445
- "u_height",
446
- "is_full_depth",
447
- "subdevice_role",
448
- "front_image",
449
- "rear_image",
450
- "device_count",
451
- ]
452
- },
453
- },
454
- ],
455
- "include_others": True,
456
- }
389
+
457
390
  extra_kwargs = {
458
391
  "device_family": {
459
392
  "required": False,
@@ -579,18 +512,6 @@ class PlatformSerializer(NautobotModelSerializer):
579
512
  class Meta:
580
513
  model = Platform
581
514
  fields = "__all__"
582
- list_display_fields = [
583
- "name",
584
- "manufacturer",
585
- "napalm_driver",
586
- "napalm_args",
587
- "network_driver",
588
- "network_driver_mappings",
589
- "device_count",
590
- "virtual_machine_count",
591
- "napalm_driver",
592
- "description",
593
- ]
594
515
 
595
516
 
596
517
  class DeviceBaySerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
@@ -606,7 +527,6 @@ class DeviceSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
606
527
  class Meta:
607
528
  model = Device
608
529
  fields = "__all__"
609
- list_display_fields = ["name", "status", "tenant", "location", "rack", "role", "device_type", "primary_ip"]
610
530
  validators = []
611
531
  extra_kwargs = {
612
532
  "parent_bay": {"required": False, "allow_null": True},
@@ -614,41 +534,6 @@ class DeviceSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
614
534
  "vc_priority": {"label": "Virtual chassis priority"},
615
535
  }
616
536
 
617
- detail_view_config = {
618
- "layout": [
619
- {
620
- "Device": {
621
- "fields": [
622
- "name",
623
- "location",
624
- "rack",
625
- "face",
626
- "position",
627
- "tenant",
628
- "device_type",
629
- "serial",
630
- "asset_tag",
631
- "cluster",
632
- "parent_bay",
633
- ]
634
- },
635
- "Device Management": {
636
- "fields": [
637
- "role",
638
- "platform",
639
- "primary_ip4",
640
- "primary_ip6",
641
- "secrets_group",
642
- "device_redundancy_group",
643
- "device_redundancy_group_priority",
644
- "controller_managed_device_group",
645
- ]
646
- },
647
- },
648
- ],
649
- "include_others": False, # TODO: config_context, local_config_context_data, local_config_context_schema
650
- }
651
-
652
537
  def get_additional_detail_view_tabs(self):
653
538
  """Add "Virtual Chassis" as a separate detail tab."""
654
539
  tabs = super().get_additional_detail_view_tabs()
@@ -673,20 +558,20 @@ class DeviceSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
673
558
  def get_config_context(self, obj):
674
559
  return obj.get_config_context()
675
560
 
676
- def validate(self, attrs):
561
+ def validate(self, data):
677
562
  # Validate uniqueness of (rack, position, face) since we omitted the automatically-created validator from Meta.
678
- if attrs.get("rack") and attrs.get("position") and attrs.get("face"):
563
+ if data.get("rack") and data.get("position") and data.get("face"):
679
564
  validator = UniqueTogetherValidator(
680
565
  queryset=Device.objects.all(),
681
566
  fields=("rack", "position", "face"),
682
567
  message=f"The position and face is already occupied on this rack. {UniqueTogetherValidator.message}",
683
568
  )
684
- validator(attrs, self)
569
+ validator(data, self)
685
570
 
686
571
  # Enforce model validation
687
- super().validate(attrs)
572
+ super().validate(data)
688
573
 
689
- return attrs
574
+ return data
690
575
 
691
576
 
692
577
  class DeviceNAPALMSerializer(serializers.Serializer):
@@ -759,22 +644,22 @@ class PowerPortSerializer(
759
644
 
760
645
 
761
646
  class InterfaceCommonSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
762
- def validate(self, attrs):
647
+ def validate(self, data):
763
648
  # Validate many-to-many VLAN assignments
764
- mode = attrs.get("mode", getattr(self.instance, "mode", None))
649
+ mode = data.get("mode", getattr(self.instance, "mode", None))
765
650
 
766
651
  if mode != InterfaceModeChoices.MODE_TAGGED:
767
- if attrs.get("tagged_vlans"):
652
+ if data.get("tagged_vlans"):
768
653
  raise serializers.ValidationError(
769
654
  {
770
655
  "tagged_vlans": f"Mode must be set to {InterfaceModeChoices.MODE_TAGGED} when specifying tagged_vlans"
771
656
  }
772
657
  )
773
658
 
774
- if attrs.get("tagged_vlans") != [] and self.instance and self.instance.tagged_vlans.exists():
659
+ if data.get("tagged_vlans") != [] and self.instance and self.instance.tagged_vlans.exists():
775
660
  raise serializers.ValidationError({"tagged_vlans": f"Clear tagged_vlans to set mode to {mode}"})
776
661
 
777
- return super().validate(attrs)
662
+ return super().validate(data)
778
663
 
779
664
 
780
665
  class InterfaceSerializer(
@@ -791,7 +676,6 @@ class InterfaceSerializer(
791
676
  class Meta:
792
677
  model = Interface
793
678
  fields = "__all__"
794
- list_display_fields = ["device", "name", "status", "label", "enabled", "type", "description"]
795
679
  extra_kwargs = {"cable": {"read_only": True}}
796
680
  validators = []
797
681
 
@@ -862,7 +746,6 @@ class DeviceRedundancyGroupSerializer(TaggedModelSerializerMixin, NautobotModelS
862
746
  class Meta:
863
747
  model = DeviceRedundancyGroup
864
748
  fields = "__all__"
865
- list_display_fields = ["name", "status", "failover_strategy", "device_count"]
866
749
 
867
750
 
868
751
  #
@@ -877,18 +760,18 @@ class InventoryItemSerializer(TaggedModelSerializerMixin, TreeModelSerializerMix
877
760
  # https://www.django-rest-framework.org/api-guide/validators/#optional-fields
878
761
  validators = []
879
762
 
880
- def validate(self, attrs):
763
+ def validate(self, data):
881
764
  # Validate uniqueness of (device, parent, name) since we omitted the automatically created validator from Meta.
882
- if attrs.get("device") and attrs.get("parent") and attrs.get("name"):
765
+ if data.get("device") and data.get("parent") and data.get("name"):
883
766
  validator = UniqueTogetherValidator(
884
767
  queryset=InventoryItem.objects.all(),
885
768
  fields=("device", "parent", "name"),
886
769
  )
887
- validator(attrs, self)
770
+ validator(data, self)
888
771
 
889
- super().validate(attrs)
772
+ super().validate(data)
890
773
 
891
- return attrs
774
+ return data
892
775
 
893
776
 
894
777
  #
@@ -911,13 +794,6 @@ class CableSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
911
794
  extra_kwargs = {
912
795
  "color": {"help_text": "RGB color in hexadecimal (e.g. 00ff00)"},
913
796
  }
914
- list_display_fields = [
915
- "label",
916
- "termination_a",
917
- "termination_b",
918
- "status",
919
- "type",
920
- ]
921
797
 
922
798
  def _get_termination(self, obj, side):
923
799
  """
@@ -1058,7 +934,6 @@ class VirtualChassisSerializer(TaggedModelSerializerMixin, NautobotModelSerializ
1058
934
  class Meta:
1059
935
  model = VirtualChassis
1060
936
  fields = "__all__"
1061
- list_display_fields = ["name", "domain", "master", "member_count"]
1062
937
 
1063
938
 
1064
939
  #
@@ -1113,12 +988,20 @@ class DeviceTypeToSoftwareImageFileSerializer(ValidatedModelSerializer):
1113
988
 
1114
989
 
1115
990
  class ControllerSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
991
+ capabilities = serializers.ListField(
992
+ child=ChoiceField(choices=ControllerCapabilitiesChoices, required=False), allow_empty=True
993
+ )
994
+
1116
995
  class Meta:
1117
996
  model = Controller
1118
997
  fields = "__all__"
1119
998
 
1120
999
 
1121
1000
  class ControllerManagedDeviceGroupSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
1001
+ capabilities = serializers.ListField(
1002
+ child=ChoiceField(choices=ControllerCapabilitiesChoices, required=False), allow_empty=True
1003
+ )
1004
+
1122
1005
  class Meta:
1123
1006
  model = ControllerManagedDeviceGroup
1124
1007
  fields = "__all__"
@@ -1135,21 +1018,21 @@ class ModuleBaySerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
1135
1018
  fields = "__all__"
1136
1019
  validators = []
1137
1020
 
1138
- def validate(self, attrs):
1021
+ def validate(self, data):
1139
1022
  """Validate device and module field constraints for module bay."""
1140
- if attrs.get("parent_device") and attrs.get("parent_module"):
1023
+ if data.get("parent_device") and data.get("parent_module"):
1141
1024
  raise serializers.ValidationError("Only one of parent_device or parent_module must be set")
1142
- if attrs.get("parent_device"):
1025
+ if data.get("parent_device"):
1143
1026
  validator = UniqueTogetherValidator(
1144
1027
  queryset=self.Meta.model.objects.all(), fields=("parent_device", "name")
1145
1028
  )
1146
- validator(attrs, self)
1147
- if attrs.get("parent_module"):
1029
+ validator(data, self)
1030
+ if data.get("parent_module"):
1148
1031
  validator = UniqueTogetherValidator(
1149
1032
  queryset=self.Meta.model.objects.all(), fields=("parent_module", "name")
1150
1033
  )
1151
- validator(attrs, self)
1152
- return super().validate(attrs)
1034
+ validator(data, self)
1035
+ return super().validate(data)
1153
1036
 
1154
1037
 
1155
1038
  class ModuleBayTemplateSerializer(NautobotModelSerializer):
@@ -1158,17 +1041,17 @@ class ModuleBayTemplateSerializer(NautobotModelSerializer):
1158
1041
  fields = "__all__"
1159
1042
  validators = []
1160
1043
 
1161
- def validate(self, attrs):
1044
+ def validate(self, data):
1162
1045
  """Validate device_type and module_type field constraints for module bay template."""
1163
- if attrs.get("device_type") and attrs.get("module_type"):
1046
+ if data.get("device_type") and data.get("module_type"):
1164
1047
  raise serializers.ValidationError("Only one of device_type or module_type must be set")
1165
- if attrs.get("device_type"):
1048
+ if data.get("device_type"):
1166
1049
  validator = UniqueTogetherValidator(queryset=self.Meta.model.objects.all(), fields=("device_type", "name"))
1167
- validator(attrs, self)
1168
- if attrs.get("module_type"):
1050
+ validator(data, self)
1051
+ if data.get("module_type"):
1169
1052
  validator = UniqueTogetherValidator(queryset=self.Meta.model.objects.all(), fields=("module_type", "name"))
1170
- validator(attrs, self)
1171
- return super().validate(attrs)
1053
+ validator(data, self)
1054
+ return super().validate(data)
1172
1055
 
1173
1056
 
1174
1057
  class ModuleSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
@@ -1178,20 +1061,38 @@ class ModuleSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
1178
1061
 
1179
1062
  validators = []
1180
1063
 
1181
- def validate(self, attrs):
1064
+ def validate(self, data):
1182
1065
  """Validate asset_Tag, serial, parent_module_bay and location field constraints for module."""
1183
- if attrs.get("parent_module_bay") and attrs.get("location"):
1066
+ if data.get("parent_module_bay") and data.get("location"):
1184
1067
  raise serializers.ValidationError("Only one of parent_module_bay or location must be set")
1185
- if attrs.get("serial"):
1068
+ if data.get("serial"):
1186
1069
  validator = UniqueTogetherValidator(queryset=Module.objects.all(), fields=("module_type", "serial"))
1187
- validator(attrs, self)
1188
- if attrs.get("asset_tag"):
1070
+ validator(data, self)
1071
+ if data.get("asset_tag"):
1189
1072
  validator = UniqueValidator(queryset=Module.objects.all())
1190
- validator(attrs["asset_tag"], self.fields["asset_tag"])
1191
- return super().validate(attrs)
1073
+ validator(data["asset_tag"], self.fields["asset_tag"])
1074
+ return super().validate(data)
1192
1075
 
1193
1076
 
1194
1077
  class ModuleTypeSerializer(TaggedModelSerializerMixin, NautobotModelSerializer):
1195
1078
  class Meta:
1196
1079
  model = ModuleType
1197
1080
  fields = "__all__"
1081
+
1082
+
1083
+ class VirtualDeviceContextSerializer(NautobotModelSerializer):
1084
+ class Meta:
1085
+ model = VirtualDeviceContext
1086
+ fields = "__all__"
1087
+
1088
+ def validate(self, data):
1089
+ """Validate device cannot be changed for VirtualDeviceContext."""
1090
+ if data.get("device") and self.instance and self.instance.device != data.get("device"):
1091
+ raise serializers.ValidationError("Changing the device of a VirtualDeviceContext is not allowed.")
1092
+ return super().validate(data)
1093
+
1094
+
1095
+ class InterfaceVDCAssignmentSerializer(ValidatedModelSerializer):
1096
+ class Meta:
1097
+ model = InterfaceVDCAssignment
1098
+ fields = "__all__"
nautobot/dcim/api/urls.py CHANGED
@@ -85,5 +85,10 @@ router.register("connected-device", views.ConnectedDeviceViewSet, basename="conn
85
85
  router.register("controllers", views.ControllerViewSet)
86
86
  router.register("controller-managed-device-groups", views.ControllerManagedDeviceGroupViewSet)
87
87
 
88
+ # Virtual Device Contexts
89
+ router.register("virtual-device-contexts", views.VirtualDeviceContextViewSet)
90
+ router.register("interface-vdc-assignments", views.InterfaceVDCAssignmentViewSet)
91
+
92
+
88
93
  app_name = "dcim-api"
89
94
  urlpatterns = router.urls
@@ -11,7 +11,6 @@ from drf_spectacular.types import OpenApiTypes
11
11
  from drf_spectacular.utils import extend_schema, OpenApiParameter
12
12
  from rest_framework.decorators import action
13
13
  from rest_framework.mixins import ListModelMixin
14
- from rest_framework.parsers import JSONParser, MultiPartParser
15
14
  from rest_framework.permissions import IsAuthenticated
16
15
  from rest_framework.response import Response
17
16
  from rest_framework.viewsets import GenericViewSet, ViewSet
@@ -19,7 +18,6 @@ from rest_framework.viewsets import GenericViewSet, ViewSet
19
18
  from nautobot.circuits.models import Circuit
20
19
  from nautobot.cloud.models import CloudAccount
21
20
  from nautobot.core.api.exceptions import ServiceUnavailable
22
- from nautobot.core.api.parsers import NautobotCSVParser
23
21
  from nautobot.core.api.utils import get_serializer_for_model
24
22
  from nautobot.core.api.views import ModelViewSet
25
23
  from nautobot.core.models.querysets import count_related
@@ -46,6 +44,7 @@ from nautobot.dcim.models import (
46
44
  InterfaceRedundancyGroup,
47
45
  InterfaceRedundancyGroupAssociation,
48
46
  InterfaceTemplate,
47
+ InterfaceVDCAssignment,
49
48
  InventoryItem,
50
49
  Location,
51
50
  LocationType,
@@ -69,6 +68,7 @@ from nautobot.dcim.models import (
69
68
  SoftwareImageFile,
70
69
  SoftwareVersion,
71
70
  VirtualChassis,
71
+ VirtualDeviceContext,
72
72
  )
73
73
  from nautobot.extras.api.views import (
74
74
  ConfigContextQuerySetMixin,
@@ -302,7 +302,6 @@ class DeviceTypeViewSet(NautobotModelViewSet):
302
302
  )
303
303
  serializer_class = serializers.DeviceTypeSerializer
304
304
  filterset_class = filters.DeviceTypeFilterSet
305
- parser_classes = [JSONParser, NautobotCSVParser, MultiPartParser]
306
305
 
307
306
 
308
307
  #
@@ -605,7 +604,9 @@ class InterfaceViewSet(PathEndpointMixin, NautobotModelViewSet):
605
604
  "status",
606
605
  "cable",
607
606
  "untagged_vlan",
608
- ).prefetch_related("tags", "_path__destination", "_cable_peer", "ip_addresses", "tagged_vlans")
607
+ ).prefetch_related(
608
+ "tags", "_path__destination", "_cable_peer", "ip_addresses", "tagged_vlans", "virtual_device_contexts"
609
+ )
609
610
  serializer_class = serializers.InterfaceSerializer
610
611
  filterset_class = filters.InterfaceFilterSet
611
612
 
@@ -888,3 +889,15 @@ class ModuleTypeViewSet(NautobotModelViewSet):
888
889
  queryset = ModuleType.objects.select_related("manufacturer").prefetch_related("tags", "modules")
889
890
  serializer_class = serializers.ModuleTypeSerializer
890
891
  filterset_class = filters.ModuleTypeFilterSet
892
+
893
+
894
+ class VirtualDeviceContextViewSet(NautobotModelViewSet):
895
+ queryset = VirtualDeviceContext.objects.select_related("device", "tenant", "primary_ip4", "primary_ip6", "role")
896
+ serializer_class = serializers.VirtualDeviceContextSerializer
897
+ filterset_class = filters.VirtualDeviceContextFilterSet
898
+
899
+
900
+ class InterfaceVDCAssignmentViewSet(NautobotModelViewSet):
901
+ queryset = InterfaceVDCAssignment.objects.select_related("virtual_device_context", "interface")
902
+ serializer_class = serializers.InterfaceVDCAssignmentSerializer
903
+ filterset_class = filters.InterfaceVDCAssignmentFilterSet
nautobot/dcim/apps.py CHANGED
@@ -20,6 +20,7 @@ class DCIMConfig(NautobotConfig):
20
20
  "rackgroup",
21
21
  "softwareversion",
22
22
  "virtualchassis",
23
+ "virtualdevicecontext",
23
24
  ]
24
25
 
25
26
  def ready(self):