nautobot 2.2.9__py3-none-any.whl → 2.3.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 (697) hide show
  1. nautobot/apps/forms.py +4 -0
  2. nautobot/apps/models.py +10 -1
  3. nautobot/circuits/__init__.py +0 -1
  4. nautobot/circuits/apps.py +1 -0
  5. nautobot/circuits/factory.py +15 -3
  6. nautobot/circuits/filters.py +13 -0
  7. nautobot/circuits/forms.py +13 -0
  8. nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
  9. nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
  10. nautobot/circuits/models.py +16 -3
  11. nautobot/circuits/tables.py +16 -2
  12. nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
  13. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
  14. nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
  15. nautobot/circuits/tests/test_api.py +7 -5
  16. nautobot/circuits/tests/test_filters.py +12 -5
  17. nautobot/circuits/tests/test_models.py +33 -2
  18. nautobot/circuits/views.py +2 -3
  19. nautobot/cloud/__init__.py +0 -0
  20. nautobot/cloud/api/__init__.py +0 -0
  21. nautobot/cloud/api/serializers.py +54 -0
  22. nautobot/cloud/api/urls.py +16 -0
  23. nautobot/cloud/api/views.py +48 -0
  24. nautobot/cloud/apps.py +13 -0
  25. nautobot/cloud/factory.py +111 -0
  26. nautobot/cloud/filters.py +184 -0
  27. nautobot/cloud/forms.py +333 -0
  28. nautobot/cloud/homepage.py +43 -0
  29. nautobot/cloud/migrations/0001_initial.py +304 -0
  30. nautobot/cloud/migrations/__init__.py +0 -0
  31. nautobot/cloud/models.py +247 -0
  32. nautobot/cloud/navigation.py +85 -0
  33. nautobot/cloud/tables.py +173 -0
  34. nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
  35. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +128 -0
  36. nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
  37. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +100 -0
  38. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +65 -0
  39. nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
  40. nautobot/cloud/tests/__init__.py +0 -0
  41. nautobot/cloud/tests/test_api.py +248 -0
  42. nautobot/cloud/tests/test_filters.py +113 -0
  43. nautobot/cloud/tests/test_models.py +43 -0
  44. nautobot/cloud/tests/test_views.py +153 -0
  45. nautobot/cloud/urls.py +14 -0
  46. nautobot/cloud/views.py +181 -0
  47. nautobot/core/__init__.py +0 -3
  48. nautobot/core/api/metadata.py +1 -0
  49. nautobot/core/api/parsers.py +7 -1
  50. nautobot/core/api/urls.py +1 -0
  51. nautobot/core/api/utils.py +1 -0
  52. nautobot/core/api/views.py +4 -0
  53. nautobot/core/apps/__init__.py +6 -3
  54. nautobot/core/constants.py +8 -0
  55. nautobot/core/factory.py +32 -1
  56. nautobot/core/filters.py +96 -28
  57. nautobot/core/forms/fields.py +10 -4
  58. nautobot/core/forms/forms.py +1 -1
  59. nautobot/core/forms/widgets.py +18 -1
  60. nautobot/core/graphql/generators.py +2 -2
  61. nautobot/core/graphql/schema.py +34 -4
  62. nautobot/core/jobs/__init__.py +17 -6
  63. nautobot/core/jobs/cleanup.py +100 -0
  64. nautobot/core/jobs/groups.py +38 -0
  65. nautobot/core/management/commands/generate_test_data.py +116 -3
  66. nautobot/core/models/__init__.py +34 -9
  67. nautobot/core/models/generics.py +19 -3
  68. nautobot/core/models/name_color_content_types.py +7 -28
  69. nautobot/core/models/querysets.py +4 -3
  70. nautobot/core/models/tree_queries.py +1 -1
  71. nautobot/core/models/utils.py +21 -5
  72. nautobot/core/settings.py +4 -30
  73. nautobot/core/settings.yaml +34 -27
  74. nautobot/core/settings_funcs.py +103 -0
  75. nautobot/core/tables.py +127 -56
  76. nautobot/core/templates/admin/search_form.html +1 -1
  77. nautobot/core/templates/buttons/add.html +11 -3
  78. nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
  79. nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
  80. nautobot/core/templates/buttons/export.html +101 -53
  81. nautobot/core/templates/buttons/job_import.html +11 -3
  82. nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
  83. nautobot/core/templates/generic/object_bulk_update.html +3 -1
  84. nautobot/core/templates/generic/object_changelog.html +0 -9
  85. nautobot/core/templates/generic/object_list.html +156 -17
  86. nautobot/core/templates/generic/object_retrieve.html +80 -16
  87. nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
  88. nautobot/core/templates/inc/javascript.html +2 -0
  89. nautobot/core/templates/inc/media.html +2 -2
  90. nautobot/core/templates/inc/nav_menu.html +1 -0
  91. nautobot/core/templates/inc/paginator.html +7 -7
  92. nautobot/core/templates/inc/search_panel.html +2 -2
  93. nautobot/core/templates/inc/table.html +2 -2
  94. nautobot/core/templates/nautobot_config.py.j2 +13 -23
  95. nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
  96. nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
  97. nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
  98. nautobot/core/templates/utilities/theme_preview.html +25 -8
  99. nautobot/core/templates/utilities/worker_status.html +152 -0
  100. nautobot/core/templatetags/buttons.py +335 -38
  101. nautobot/core/templatetags/form_helpers.py +1 -1
  102. nautobot/core/templatetags/helpers.py +181 -11
  103. nautobot/core/testing/api.py +5 -4
  104. nautobot/core/testing/filters.py +51 -13
  105. nautobot/core/testing/mixins.py +46 -0
  106. nautobot/core/testing/models.py +22 -0
  107. nautobot/core/testing/schema.py +4 -8
  108. nautobot/core/testing/views.py +31 -14
  109. nautobot/core/tests/integration/test_general_functionality.py +1 -1
  110. nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
  111. nautobot/core/tests/integration/test_swagger.py +1 -1
  112. nautobot/core/tests/nautobot_config.py +0 -1
  113. nautobot/core/tests/runner.py +2 -2
  114. nautobot/core/tests/test_api.py +1 -0
  115. nautobot/core/tests/test_authentication.py +7 -2
  116. nautobot/core/tests/test_filters.py +11 -9
  117. nautobot/core/tests/test_forms.py +9 -0
  118. nautobot/core/tests/test_graphql.py +27 -16
  119. nautobot/core/tests/test_jobs.py +123 -74
  120. nautobot/core/tests/test_tables.py +3 -1
  121. nautobot/core/tests/test_templatetags_helpers.py +12 -5
  122. nautobot/core/tests/test_utils.py +31 -20
  123. nautobot/core/tests/test_views.py +6 -6
  124. nautobot/core/urls.py +8 -3
  125. nautobot/core/utils/deprecation.py +29 -0
  126. nautobot/core/utils/filtering.py +12 -9
  127. nautobot/core/utils/lookup.py +37 -2
  128. nautobot/core/utils/requests.py +4 -1
  129. nautobot/core/views/__init__.py +137 -24
  130. nautobot/core/views/generic.py +118 -66
  131. nautobot/core/views/mixins.py +104 -35
  132. nautobot/core/views/paginator.py +9 -3
  133. nautobot/core/views/renderers.py +121 -56
  134. nautobot/core/views/utils.py +79 -1
  135. nautobot/dcim/__init__.py +0 -1
  136. nautobot/dcim/api/serializers.py +180 -44
  137. nautobot/dcim/api/urls.py +7 -3
  138. nautobot/dcim/api/views.py +53 -7
  139. nautobot/dcim/apps.py +3 -0
  140. nautobot/dcim/choices.py +25 -0
  141. nautobot/dcim/constants.py +7 -0
  142. nautobot/dcim/factory.py +249 -18
  143. nautobot/dcim/filters/__init__.py +369 -193
  144. nautobot/dcim/filters/mixins.py +274 -1
  145. nautobot/dcim/forms.py +817 -109
  146. nautobot/dcim/graphql/types.py +2 -2
  147. nautobot/dcim/homepage.py +1 -1
  148. nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
  149. nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
  150. nautobot/dcim/migrations/0061_module_models.py +861 -0
  151. nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
  152. nautobot/dcim/models/__init__.py +8 -0
  153. nautobot/dcim/models/cables.py +15 -0
  154. nautobot/dcim/models/device_component_templates.py +207 -53
  155. nautobot/dcim/models/device_components.py +275 -106
  156. nautobot/dcim/models/devices.py +466 -13
  157. nautobot/dcim/navigation.py +47 -0
  158. nautobot/dcim/signals.py +3 -3
  159. nautobot/dcim/tables/__init__.py +35 -23
  160. nautobot/dcim/tables/devices.py +231 -59
  161. nautobot/dcim/tables/devicetypes.py +65 -9
  162. nautobot/dcim/tables/racks.py +5 -1
  163. nautobot/dcim/tables/template_code.py +46 -26
  164. nautobot/dcim/templates/dcim/cable_connect.html +76 -3
  165. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
  166. nautobot/dcim/templates/dcim/device/base.html +15 -7
  167. nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
  168. nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
  169. nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
  170. nautobot/dcim/templates/dcim/device/frontports.html +2 -3
  171. nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
  172. nautobot/dcim/templates/dcim/device/inventory.html +2 -3
  173. nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
  174. nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
  175. nautobot/dcim/templates/dcim/device/powerports.html +2 -3
  176. nautobot/dcim/templates/dcim/device/rearports.html +2 -3
  177. nautobot/dcim/templates/dcim/device.html +45 -1
  178. nautobot/dcim/templates/dcim/device_component.html +13 -5
  179. nautobot/dcim/templates/dcim/device_list.html +2 -1
  180. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -6
  181. nautobot/dcim/templates/dcim/devicetype.html +99 -98
  182. nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
  183. nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
  184. nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
  185. nautobot/dcim/templates/dcim/interface.html +17 -2
  186. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
  187. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  188. nautobot/dcim/templates/dcim/manufacturer.html +24 -0
  189. nautobot/dcim/templates/dcim/module/base.html +97 -0
  190. nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
  191. nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
  192. nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
  193. nautobot/dcim/templates/dcim/module_destroy.html +5 -0
  194. nautobot/dcim/templates/dcim/module_frontports.html +53 -0
  195. nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
  196. nautobot/dcim/templates/dcim/module_list.html +20 -0
  197. nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
  198. nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
  199. nautobot/dcim/templates/dcim/module_powerports.html +53 -0
  200. nautobot/dcim/templates/dcim/module_rearports.html +53 -0
  201. nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
  202. nautobot/dcim/templates/dcim/module_update.html +71 -0
  203. nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
  204. nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
  205. nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
  206. nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
  207. nautobot/dcim/templates/dcim/moduletype_retrieve.html +142 -0
  208. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
  209. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
  210. nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
  211. nautobot/dcim/tests/test_api.py +691 -208
  212. nautobot/dcim/tests/test_filters.py +836 -217
  213. nautobot/dcim/tests/test_models.py +1072 -39
  214. nautobot/dcim/tests/test_views.py +1488 -358
  215. nautobot/dcim/urls.py +17 -2
  216. nautobot/dcim/utils.py +2 -3
  217. nautobot/dcim/views.py +1107 -120
  218. nautobot/extras/__init__.py +0 -1
  219. nautobot/extras/api/serializers.py +115 -3
  220. nautobot/extras/api/urls.py +12 -0
  221. nautobot/extras/api/views.py +125 -7
  222. nautobot/extras/apps.py +2 -2
  223. nautobot/extras/choices.py +43 -0
  224. nautobot/extras/context_managers.py +13 -8
  225. nautobot/extras/datasources/git.py +2 -0
  226. nautobot/extras/factory.py +422 -9
  227. nautobot/extras/filters/__init__.py +174 -3
  228. nautobot/extras/filters/mixins.py +46 -43
  229. nautobot/extras/forms/base.py +17 -4
  230. nautobot/extras/forms/forms.py +227 -8
  231. nautobot/extras/forms/mixins.py +93 -0
  232. nautobot/extras/graphql/types.py +23 -10
  233. nautobot/extras/homepage.py +16 -13
  234. nautobot/extras/jobs.py +2 -2
  235. nautobot/extras/management/__init__.py +1 -0
  236. nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
  237. nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
  238. nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
  239. nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
  240. nautobot/extras/migrations/0111_metadata.py +162 -0
  241. nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
  242. nautobot/extras/migrations/0113_saved_views.py +77 -0
  243. nautobot/extras/models/__init__.py +15 -1
  244. nautobot/extras/models/change_logging.py +3 -3
  245. nautobot/extras/models/contacts.py +4 -0
  246. nautobot/extras/models/customfields.py +18 -3
  247. nautobot/extras/models/groups.py +389 -225
  248. nautobot/extras/models/jobs.py +4 -84
  249. nautobot/extras/models/metadata.py +441 -0
  250. nautobot/extras/models/mixins.py +72 -62
  251. nautobot/extras/models/models.py +116 -9
  252. nautobot/extras/models/relationships.py +9 -2
  253. nautobot/extras/models/tags.py +13 -2
  254. nautobot/extras/navigation.py +57 -0
  255. nautobot/extras/plugins/__init__.py +3 -1
  256. nautobot/extras/querysets.py +30 -66
  257. nautobot/extras/signals.py +96 -114
  258. nautobot/extras/tables.py +171 -47
  259. nautobot/extras/templates/extras/dynamicgroup.html +44 -15
  260. nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
  261. nautobot/extras/templates/extras/job.html +1 -1
  262. nautobot/extras/templates/extras/job_detail.html +0 -11
  263. nautobot/extras/templates/extras/jobresult.html +61 -74
  264. nautobot/extras/templates/extras/metadatatype_create.html +89 -0
  265. nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
  266. nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
  267. nautobot/extras/templates/extras/objectchange_list.html +0 -12
  268. nautobot/extras/templates/extras/plugins_list.html +1 -3
  269. nautobot/extras/templates/extras/role_retrieve.html +48 -0
  270. nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
  271. nautobot/extras/tests/integration/test_customfields.py +1 -0
  272. nautobot/extras/tests/test_api.py +501 -22
  273. nautobot/extras/tests/test_changelog.py +20 -9
  274. nautobot/extras/tests/test_context_managers.py +22 -15
  275. nautobot/extras/tests/test_datasources.py +13 -1
  276. nautobot/extras/tests/test_dynamicgroups.py +201 -171
  277. nautobot/extras/tests/test_filters.py +211 -12
  278. nautobot/extras/tests/test_jobs.py +4 -4
  279. nautobot/extras/tests/test_models.py +499 -4
  280. nautobot/extras/tests/test_relationships.py +1 -0
  281. nautobot/extras/tests/test_views.py +565 -28
  282. nautobot/extras/tests/test_webhooks.py +1 -1
  283. nautobot/extras/urls.py +5 -0
  284. nautobot/extras/utils.py +56 -45
  285. nautobot/extras/views.py +585 -96
  286. nautobot/ipam/__init__.py +0 -1
  287. nautobot/ipam/apps.py +1 -0
  288. nautobot/ipam/factory.py +17 -19
  289. nautobot/ipam/filters.py +14 -1
  290. nautobot/ipam/forms.py +9 -5
  291. nautobot/ipam/graphql/types.py +2 -2
  292. nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
  293. nautobot/ipam/models.py +23 -9
  294. nautobot/ipam/querysets.py +1 -1
  295. nautobot/ipam/signals.py +4 -2
  296. nautobot/ipam/tables.py +1 -0
  297. nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
  298. nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
  299. nautobot/ipam/templates/ipam/prefix.html +1 -0
  300. nautobot/ipam/tests/test_api.py +37 -18
  301. nautobot/ipam/tests/test_filters.py +26 -2
  302. nautobot/ipam/tests/test_models.py +8 -3
  303. nautobot/ipam/tests/test_querysets.py +1 -1
  304. nautobot/ipam/tests/test_views.py +3 -2
  305. nautobot/ipam/urls.py +2 -2
  306. nautobot/ipam/views.py +25 -28
  307. nautobot/project-static/css/base.css +20 -1
  308. nautobot/project-static/css/dark.css +11 -0
  309. nautobot/project-static/docs/404.html +884 -80
  310. nautobot/project-static/docs/apps/index.html +884 -80
  311. nautobot/project-static/docs/apps/nautobot-apps.html +884 -80
  312. nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
  313. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +911 -112
  314. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +896 -93
  315. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1457 -790
  316. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +927 -136
  317. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +969 -180
  318. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +893 -91
  319. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +889 -85
  320. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +983 -185
  321. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +938 -143
  322. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1064 -274
  323. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1190 -346
  324. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1663 -865
  325. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1156 -373
  326. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2200 -1502
  327. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2229 -1421
  328. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +904 -103
  329. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +955 -155
  330. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1002 -215
  331. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1911 -1275
  332. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1835 -1091
  333. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +896 -93
  334. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2323 -1693
  335. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1785 -1023
  336. nautobot/project-static/docs/development/apps/api/configuration-view.html +884 -80
  337. nautobot/project-static/docs/development/apps/api/database-backend-config.html +884 -80
  338. nautobot/project-static/docs/development/apps/api/models/django-admin.html +884 -80
  339. nautobot/project-static/docs/development/apps/api/models/global-search.html +884 -80
  340. nautobot/project-static/docs/development/apps/api/models/graphql.html +884 -80
  341. nautobot/project-static/docs/development/apps/api/models/index.html +922 -81
  342. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +884 -80
  343. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +884 -80
  344. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +884 -80
  345. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +884 -80
  346. nautobot/project-static/docs/development/apps/api/platform-features/index.html +884 -80
  347. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +884 -80
  348. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +884 -80
  349. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +884 -80
  350. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +884 -80
  351. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +884 -80
  352. nautobot/project-static/docs/development/apps/api/prometheus.html +884 -80
  353. nautobot/project-static/docs/development/apps/api/setup.html +884 -80
  354. nautobot/project-static/docs/development/apps/api/testing.html +884 -80
  355. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +884 -80
  356. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +884 -80
  357. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +884 -80
  358. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +884 -80
  359. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +884 -80
  360. nautobot/project-static/docs/development/apps/api/views/base-template.html +884 -80
  361. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +884 -80
  362. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +884 -80
  363. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +884 -80
  364. nautobot/project-static/docs/development/apps/api/views/index.html +884 -80
  365. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +884 -80
  366. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +884 -80
  367. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +884 -80
  368. nautobot/project-static/docs/development/apps/api/views/notes.html +884 -80
  369. nautobot/project-static/docs/development/apps/api/views/rest-api.html +884 -80
  370. nautobot/project-static/docs/development/apps/api/views/urls.html +884 -80
  371. nautobot/project-static/docs/development/apps/index.html +884 -80
  372. nautobot/project-static/docs/development/apps/migration/code-updates.html +884 -80
  373. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +884 -80
  374. nautobot/project-static/docs/development/apps/migration/from-v1.html +884 -80
  375. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +884 -80
  376. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +884 -80
  377. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +884 -80
  378. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +884 -80
  379. nautobot/project-static/docs/development/apps/porting-from-netbox.html +884 -80
  380. nautobot/project-static/docs/development/core/application-registry.html +884 -80
  381. nautobot/project-static/docs/development/core/best-practices.html +885 -80
  382. nautobot/project-static/docs/development/core/bootstrap-ui.html +884 -80
  383. nautobot/project-static/docs/development/core/caching.html +884 -80
  384. nautobot/project-static/docs/development/core/controllers.html +884 -80
  385. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +884 -80
  386. nautobot/project-static/docs/development/core/generic-views.html +884 -80
  387. nautobot/project-static/docs/development/core/getting-started.html +884 -80
  388. nautobot/project-static/docs/development/core/homepage.html +884 -80
  389. nautobot/project-static/docs/development/core/index.html +884 -91
  390. nautobot/project-static/docs/development/core/model-checklist.html +887 -81
  391. nautobot/project-static/docs/development/core/model-features.html +884 -80
  392. nautobot/project-static/docs/development/core/natural-keys.html +884 -80
  393. nautobot/project-static/docs/development/core/navigation-menu.html +884 -80
  394. nautobot/project-static/docs/development/core/release-checklist.html +887 -83
  395. nautobot/project-static/docs/development/core/role-internals.html +884 -80
  396. nautobot/project-static/docs/development/core/settings.html +884 -80
  397. nautobot/project-static/docs/development/core/style-guide.html +885 -81
  398. nautobot/project-static/docs/development/core/templates.html +896 -81
  399. nautobot/project-static/docs/development/core/testing.html +884 -80
  400. nautobot/project-static/docs/development/core/user-preferences.html +884 -80
  401. nautobot/project-static/docs/development/index.html +884 -80
  402. nautobot/project-static/docs/development/jobs/index.html +1247 -457
  403. nautobot/project-static/docs/development/jobs/migration/from-v1.html +884 -80
  404. nautobot/project-static/docs/index.html +13 -8228
  405. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
  406. nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
  407. nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
  408. nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
  409. nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
  410. nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
  411. nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
  412. nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
  413. nautobot/project-static/docs/models/dcim/module.html +15 -0
  414. nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
  415. nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
  416. nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
  417. nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
  418. nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
  419. nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
  420. nautobot/project-static/docs/models/extras/role.html +15 -0
  421. nautobot/project-static/docs/models/extras/savedview.html +15 -0
  422. nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
  423. nautobot/project-static/docs/models/extras/status.html +15 -0
  424. nautobot/project-static/docs/objects.inv +0 -0
  425. nautobot/project-static/docs/overview/application_stack.html +892 -81
  426. nautobot/project-static/docs/overview/design_philosophy.html +886 -82
  427. nautobot/project-static/docs/overview/index.html +9032 -13
  428. nautobot/project-static/docs/release-notes/index.html +887 -83
  429. nautobot/project-static/docs/release-notes/version-1.0.html +884 -80
  430. nautobot/project-static/docs/release-notes/version-1.1.html +884 -80
  431. nautobot/project-static/docs/release-notes/version-1.2.html +884 -80
  432. nautobot/project-static/docs/release-notes/version-1.3.html +884 -80
  433. nautobot/project-static/docs/release-notes/version-1.4.html +884 -80
  434. nautobot/project-static/docs/release-notes/version-1.5.html +885 -81
  435. nautobot/project-static/docs/release-notes/version-1.6.html +885 -81
  436. nautobot/project-static/docs/release-notes/version-2.0.html +884 -80
  437. nautobot/project-static/docs/release-notes/version-2.1.html +884 -80
  438. nautobot/project-static/docs/release-notes/version-2.2.html +990 -323
  439. nautobot/project-static/docs/release-notes/version-2.3.html +9524 -0
  440. nautobot/project-static/docs/requirements.txt +4 -4
  441. nautobot/project-static/docs/search/search_index.json +1 -1
  442. nautobot/project-static/docs/sitemap.xml +335 -260
  443. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  444. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +884 -80
  445. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +884 -80
  446. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +884 -80
  447. nautobot/project-static/docs/user-guide/administration/configuration/index.html +884 -80
  448. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +983 -197
  449. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +884 -80
  450. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +884 -80
  451. nautobot/project-static/docs/user-guide/administration/guides/caching.html +884 -80
  452. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +888 -84
  453. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +884 -80
  454. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +884 -80
  455. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +884 -80
  456. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +884 -80
  457. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +884 -80
  458. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +884 -80
  459. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +884 -80
  460. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +884 -80
  461. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +884 -80
  462. nautobot/project-static/docs/user-guide/administration/installation/index.html +888 -80
  463. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +884 -80
  464. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +884 -80
  465. nautobot/project-static/docs/user-guide/administration/installation/services.html +888 -80
  466. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +900 -91
  467. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +884 -80
  468. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +884 -80
  469. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +884 -80
  470. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +884 -80
  471. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +915 -163
  472. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +884 -80
  473. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +884 -80
  474. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +884 -80
  475. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +884 -80
  476. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +884 -80
  477. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +884 -80
  478. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +884 -80
  479. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +884 -80
  480. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +884 -80
  481. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +884 -80
  482. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +884 -80
  483. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +885 -81
  484. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +884 -80
  485. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +888 -80
  486. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +887 -83
  487. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
  488. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
  489. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
  490. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
  491. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
  492. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
  493. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
  494. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +898 -94
  495. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +915 -97
  496. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +915 -97
  497. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +910 -92
  498. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +915 -97
  499. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +898 -94
  500. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +898 -94
  501. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +905 -97
  502. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +912 -108
  503. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +913 -109
  504. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +910 -106
  505. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +898 -94
  506. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +906 -97
  507. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +918 -100
  508. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +928 -110
  509. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +920 -98
  510. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +898 -94
  511. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +929 -111
  512. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +920 -102
  513. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +910 -106
  514. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +913 -109
  515. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +914 -106
  516. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
  517. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
  518. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
  519. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
  520. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +908 -104
  521. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +898 -94
  522. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +932 -75
  523. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +916 -98
  524. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +898 -94
  525. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +935 -78
  526. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +913 -95
  527. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +921 -117
  528. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +910 -106
  529. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +898 -94
  530. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +914 -96
  531. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +916 -98
  532. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +898 -94
  533. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +898 -94
  534. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +898 -94
  535. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +884 -80
  536. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +884 -80
  537. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +889 -81
  538. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +889 -81
  539. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +884 -80
  540. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +884 -80
  541. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +884 -80
  542. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +884 -80
  543. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +884 -80
  544. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +884 -80
  545. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +884 -80
  546. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +884 -80
  547. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +884 -80
  548. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +884 -80
  549. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +893 -88
  550. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +884 -80
  551. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +884 -80
  552. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +884 -80
  553. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +884 -80
  554. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +884 -80
  555. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +889 -81
  556. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +884 -80
  557. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +884 -80
  558. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +884 -80
  559. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +884 -80
  560. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +884 -80
  561. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +884 -80
  562. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +884 -80
  563. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +884 -80
  564. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +884 -80
  565. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +884 -80
  566. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +884 -80
  567. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +884 -80
  568. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +884 -80
  569. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
  570. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
  571. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
  572. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
  573. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
  574. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
  575. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
  576. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
  577. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
  578. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
  579. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
  580. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
  581. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
  582. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
  583. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
  584. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
  585. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
  586. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
  587. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
  588. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
  589. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
  590. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
  591. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
  592. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
  593. nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
  594. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +884 -80
  595. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +884 -80
  596. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +884 -80
  597. nautobot/project-static/docs/user-guide/index.html +884 -80
  598. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +884 -80
  599. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +884 -80
  600. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +884 -80
  601. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +884 -80
  602. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1250 -777
  603. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +887 -83
  604. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +884 -80
  605. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +884 -80
  606. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +884 -80
  607. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +884 -80
  608. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +884 -80
  609. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +884 -80
  610. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +887 -83
  611. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +884 -80
  612. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +884 -80
  613. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +888 -80
  614. nautobot/project-static/docs/user-guide/platform-functionality/metadata.html +8948 -0
  615. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +887 -83
  616. nautobot/project-static/docs/user-guide/platform-functionality/note.html +884 -80
  617. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +884 -80
  618. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +884 -80
  619. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +884 -80
  620. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +884 -80
  621. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +884 -80
  622. nautobot/project-static/docs/user-guide/platform-functionality/role.html +887 -83
  623. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
  624. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +887 -83
  625. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
  626. nautobot/project-static/docs/user-guide/platform-functionality/status.html +884 -80
  627. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +884 -80
  628. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +942 -113
  629. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +884 -80
  630. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +884 -80
  631. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +884 -80
  632. nautobot/project-static/js/forms.js +71 -0
  633. nautobot/project-static/js/table_sorting_indicator.js +46 -0
  634. nautobot/project-static/js/tableconfig.js +6 -1
  635. nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
  636. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
  637. nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
  638. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
  639. nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
  640. nautobot/tenancy/__init__.py +0 -1
  641. nautobot/tenancy/apps.py +1 -0
  642. nautobot/tenancy/factory.py +3 -2
  643. nautobot/tenancy/filters/__init__.py +1 -0
  644. nautobot/tenancy/forms.py +1 -1
  645. nautobot/tenancy/templates/tenancy/tenant.html +22 -18
  646. nautobot/tenancy/views.py +11 -10
  647. nautobot/users/__init__.py +0 -1
  648. nautobot/users/api/serializers.py +1 -1
  649. nautobot/users/api/views.py +4 -2
  650. nautobot/users/apps.py +3 -2
  651. nautobot/users/factory.py +3 -3
  652. nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
  653. nautobot/users/models.py +12 -0
  654. nautobot/users/tests/test_filters.py +6 -3
  655. nautobot/users/urls.py +8 -0
  656. nautobot/virtualization/__init__.py +0 -1
  657. nautobot/virtualization/apps.py +1 -0
  658. nautobot/virtualization/filters.py +6 -1
  659. nautobot/virtualization/forms.py +11 -3
  660. nautobot/virtualization/graphql/types.py +2 -2
  661. nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
  662. nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
  663. nautobot/virtualization/tables.py +15 -5
  664. nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
  665. nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
  666. nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
  667. nautobot/virtualization/tests/test_api.py +9 -4
  668. nautobot/virtualization/tests/test_filters.py +22 -0
  669. nautobot/virtualization/tests/test_models.py +7 -3
  670. nautobot/virtualization/tests/test_views.py +19 -3
  671. nautobot/virtualization/urls.py +2 -2
  672. nautobot/virtualization/views.py +10 -32
  673. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/METADATA +21 -19
  674. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/RECORD +679 -559
  675. nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
  676. nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
  677. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
  678. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
  679. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
  680. nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
  681. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
  682. nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
  683. nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
  684. nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
  685. nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
  686. nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
  687. nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
  688. nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
  689. nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
  690. nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
  691. nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
  692. nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
  693. /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
  694. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/LICENSE.txt +0 -0
  695. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/NOTICE +0 -0
  696. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/WHEEL +0 -0
  697. {nautobot-2.2.9.dist-info → nautobot-2.3.0b1.dist-info}/entry_points.txt +0 -0
nautobot/ipam/__init__.py CHANGED
@@ -1 +0,0 @@
1
- default_app_config = "nautobot.ipam.apps.IPAMConfig"
nautobot/ipam/apps.py CHANGED
@@ -2,6 +2,7 @@ from nautobot.core.apps import NautobotConfig
2
2
 
3
3
 
4
4
  class IPAMConfig(NautobotConfig):
5
+ default = True
5
6
  name = "nautobot.ipam"
6
7
  verbose_name = "IPAM"
7
8
  searchable_models = [
nautobot/ipam/factory.py CHANGED
@@ -6,6 +6,7 @@ from django.contrib.contenttypes.models import ContentType
6
6
  import factory
7
7
  import faker
8
8
 
9
+ from nautobot.core.constants import CHARFIELD_MAX_LENGTH
9
10
  from nautobot.core.factory import (
10
11
  get_random_instances,
11
12
  NautobotBoolIterator,
@@ -36,7 +37,7 @@ class RIRFactory(OrganizationalModelFactory):
36
37
  is_private = factory.LazyAttribute(lambda rir: rir.name.startswith("RFC"))
37
38
 
38
39
  has_description = NautobotBoolIterator()
39
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
40
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
40
41
 
41
42
 
42
43
  def random_route_distinguisher():
@@ -72,7 +73,7 @@ class RouteTargetFactory(PrimaryModelFactory):
72
73
  name = factory.LazyFunction(random_route_distinguisher)
73
74
 
74
75
  has_description = NautobotBoolIterator()
75
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
76
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
76
77
 
77
78
  has_tenant = factory.Faker("boolean", chance_of_getting_true=75)
78
79
  tenant = factory.Maybe("has_tenant", random_instance(Tenant), None)
@@ -100,7 +101,7 @@ class VRFFactory(PrimaryModelFactory):
100
101
  tenant = factory.Maybe("has_tenant", random_instance(Tenant), None)
101
102
 
102
103
  has_description = NautobotBoolIterator()
103
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
104
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
104
105
 
105
106
  namespace = random_instance(Namespace, allow_null=False)
106
107
 
@@ -135,7 +136,7 @@ class VLANGroupFactory(OrganizationalModelFactory):
135
136
  name = factory.LazyAttribute(lambda o: o.unique_name.upper())
136
137
 
137
138
  has_description = NautobotBoolIterator()
138
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
139
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
139
140
 
140
141
  has_location = NautobotBoolIterator()
141
142
  location = factory.Maybe(
@@ -211,7 +212,7 @@ class VLANFactory(PrimaryModelFactory):
211
212
  )
212
213
 
213
214
  has_description = NautobotBoolIterator()
214
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
215
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
215
216
 
216
217
  has_vlan_group = NautobotBoolIterator()
217
218
  vlan_group = factory.Maybe("has_vlan_group", random_instance(VLANGroup, allow_null=False), None)
@@ -235,7 +236,7 @@ class VLANFactory(PrimaryModelFactory):
235
236
 
236
237
  class VLANGetOrCreateFactory(VLANFactory):
237
238
  class Meta:
238
- django_get_or_create = ("vlan_group", "tenant")
239
+ django_get_or_create = ("vlan_group", "vid")
239
240
 
240
241
 
241
242
  class VRFGetOrCreateFactory(VRFFactory):
@@ -251,7 +252,7 @@ class NamespaceFactory(PrimaryModelFactory):
251
252
  class Meta:
252
253
  model = Namespace
253
254
 
254
- name = UniqueFaker("text", max_nb_chars=20)
255
+ name = UniqueFaker("text", max_nb_chars=20) # could be up to CHARFIELD_MAX_LENGTH but that gets unwieldy fast
255
256
 
256
257
 
257
258
  class PrefixFactory(PrimaryModelFactory):
@@ -293,7 +294,7 @@ class PrefixFactory(PrimaryModelFactory):
293
294
  UniqueFaker("ipv6_network"),
294
295
  UniqueFaker("ipv4", network=True),
295
296
  )
296
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
297
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
297
298
  role = factory.Maybe(
298
299
  "has_role",
299
300
  random_instance(lambda: Role.objects.get_for_model(Prefix), allow_null=False),
@@ -357,7 +358,7 @@ class PrefixFactory(PrimaryModelFactory):
357
358
  return
358
359
 
359
360
  # 50% chance to create children
360
- if not faker.Faker().pybool():
361
+ if factory.random.randgen.choice([True, False]):
361
362
  return
362
363
 
363
364
  action = "create" if create else "build"
@@ -376,9 +377,9 @@ class PrefixFactory(PrimaryModelFactory):
376
377
 
377
378
  # Default to maximum of 4 children unless overridden in kwargs
378
379
  max_count = int(kwargs.pop("max_count", 4))
379
- child_count = faker.Faker().pyint(min_value=0, max_value=min(max_count, self.prefix.size))
380
- if child_count == 0:
380
+ if max_count == 0:
381
381
  return
382
+ child_count = faker.Faker().pyint(min_value=1, max_value=min(max_count, self.prefix.size))
382
383
 
383
384
  # Propagate parent tenant to children if parent tenant is set
384
385
  if self.tenant is not None:
@@ -403,13 +404,10 @@ class PrefixFactory(PrimaryModelFactory):
403
404
  if child_cidr > 128 or self.ip_version == 4 and child_cidr > 32:
404
405
  raise ValueError(f"Unable to create {child_count} child prefixes in container prefix {self.cidr_str}.")
405
406
 
406
- if self.type == PrefixTypeChoices.TYPE_CONTAINER:
407
- weights = [10, 1] # prefer network prefixes
408
- child_type = factory.random.randgen.choices(
409
- [PrefixTypeChoices.TYPE_NETWORK, PrefixTypeChoices.TYPE_CONTAINER], weights
410
- )[0]
411
- else:
412
- child_type = PrefixTypeChoices.TYPE_POOL
407
+ weights = [1, 6, 3] # prefer network and pool prefixes
408
+ child_type = factory.random.randgen.choices(
409
+ [PrefixTypeChoices.TYPE_CONTAINER, PrefixTypeChoices.TYPE_NETWORK, PrefixTypeChoices.TYPE_POOL], weights
410
+ )[0]
413
411
 
414
412
  # Create child prefixes, preserving is_ipv6 from parent
415
413
  for count, address in enumerate(self.prefix.subnet(child_cidr)):
@@ -462,7 +460,7 @@ class IPAddressFactory(PrimaryModelFactory):
462
460
  # UniqueFaker("ipv6"),
463
461
  # UniqueFaker("ipv4_private"),
464
462
  # )
465
- description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=200), "")
463
+ description = factory.Maybe("has_description", factory.Faker("text", max_nb_chars=CHARFIELD_MAX_LENGTH), "")
466
464
  dns_name = factory.Maybe("has_dns_name", factory.Faker("hostname"), "")
467
465
  # TODO: Needs to be made more robust because prefixes and namespaces need to exist first
468
466
  # nat_inside = factory.SubFactory(
nautobot/ipam/filters.py CHANGED
@@ -5,6 +5,7 @@ from django.db.models import Q
5
5
  import django_filters
6
6
  import netaddr
7
7
 
8
+ from nautobot.cloud.models import CloudNetwork
8
9
  from nautobot.core.filters import (
9
10
  MultiValueCharFilter,
10
11
  MultiValueNumberFilter,
@@ -256,16 +257,23 @@ class PrefixFilterSet(
256
257
  )
257
258
  ip_version = django_filters.NumberFilter()
258
259
  location = TreeNodeMultipleChoiceFilter(
260
+ prefers_id=True,
259
261
  queryset=Location.objects.all(),
260
262
  to_field_name="name",
261
263
  field_name="locations",
262
264
  label='Location (name or ID) (deprecated, use "locations" filter instead)',
263
265
  )
264
266
  locations = TreeNodeMultipleChoiceFilter(
267
+ prefers_id=True,
265
268
  queryset=Location.objects.all(),
266
269
  to_field_name="name",
267
270
  label="Locations (name or ID)",
268
271
  )
272
+ cloud_networks = NaturalKeyOrPKMultipleChoiceFilter(
273
+ queryset=CloudNetwork.objects.all(),
274
+ to_field_name="name",
275
+ label="Cloud Network (name or ID)",
276
+ )
269
277
 
270
278
  class Meta:
271
279
  model = Prefix
@@ -334,6 +342,7 @@ class PrefixLocationAssignmentFilterSet(NautobotFilterSet):
334
342
  label="Prefix",
335
343
  )
336
344
  location = TreeNodeMultipleChoiceFilter(
345
+ prefers_id=True,
337
346
  queryset=Location.objects.all(),
338
347
  to_field_name="name",
339
348
  label="Locations (name or ID)",
@@ -489,7 +498,7 @@ class IPAddressFilterSet(
489
498
  return queryset.none()
490
499
  interface_ids = []
491
500
  for device in devices:
492
- interface_ids.extend(device.vc_interfaces.values_list("id", flat=True))
501
+ interface_ids.extend(device.all_interfaces.values_list("id", flat=True))
493
502
  return queryset.filter(interfaces__in=interface_ids)
494
503
 
495
504
  def filter_virtual_machine(self, queryset, name, value):
@@ -559,12 +568,14 @@ class VLANFilterSet(
559
568
  label="VLAN Group (name or ID)",
560
569
  )
561
570
  location = TreeNodeMultipleChoiceFilter(
571
+ prefers_id=True,
562
572
  queryset=Location.objects.all(),
563
573
  to_field_name="name",
564
574
  field_name="locations",
565
575
  label='Location (name or ID) (deprecated, use "locations" filter instead)',
566
576
  )
567
577
  locations = TreeNodeMultipleChoiceFilter(
578
+ prefers_id=True,
568
579
  queryset=Location.objects.all(),
569
580
  to_field_name="name",
570
581
  label="Locations (name or ID)",
@@ -593,11 +604,13 @@ class VLANLocationAssignmentFilterSet(NautobotFilterSet):
593
604
  },
594
605
  )
595
606
  vlan = NaturalKeyOrPKMultipleChoiceFilter(
607
+ prefers_id=True,
596
608
  to_field_name="vid",
597
609
  queryset=VLAN.objects.all(),
598
610
  label="VLAN (VID or ID)",
599
611
  )
600
612
  location = TreeNodeMultipleChoiceFilter(
613
+ prefers_id=True,
601
614
  queryset=Location.objects.all(),
602
615
  to_field_name="name",
603
616
  label="Locations (name or ID)",
nautobot/ipam/forms.py CHANGED
@@ -580,10 +580,14 @@ class IPAddressForm(IPAddressFormMixin, ReturnURLForm):
580
580
  if nat_inside_parent.count() == 1:
581
581
  nat_inside_parent = nat_inside_parent.first()
582
582
  if nat_inside_parent.interface is not None:
583
- initial["nat_location"] = nat_inside_parent.interface.device.location.pk
584
- if nat_inside_parent.interface.device.rack:
585
- initial["nat_rack"] = nat_inside_parent.interface.device.rack.pk
586
- initial["nat_device"] = nat_inside_parent.interface.device.pk
583
+ parent_device = nat_inside_parent.interface.device
584
+ if parent_device is None and nat_inside_parent.interface.module is not None:
585
+ parent_device = nat_inside_parent.interface.module.device
586
+ if parent_device:
587
+ initial["nat_location"] = parent_device.location.pk
588
+ if parent_device.rack:
589
+ initial["nat_rack"] = parent_device.rack.pk
590
+ initial["nat_device"] = parent_device.pk
587
591
  elif nat_inside_parent.vm_interface is not None:
588
592
  initial["nat_cluster"] = nat_inside_parent.vm_interface.virtual_machine.cluster.pk
589
593
  initial["nat_virtual_machine"] = nat_inside_parent.vm_interface.virtual_machine.pk
@@ -895,7 +899,7 @@ class ServiceForm(NautobotModelForm):
895
899
  # Limit IP address choices to those assigned to interfaces of the parent device/VM
896
900
  if self.instance.device:
897
901
  self.fields["ip_addresses"].queryset = IPAddress.objects.filter(
898
- interfaces__in=self.instance.device.vc_interfaces.values_list("id", flat=True)
902
+ interfaces__in=self.instance.device.all_interfaces.values_list("id", flat=True)
899
903
  )
900
904
  elif self.instance.virtual_machine:
901
905
  self.fields["ip_addresses"].queryset = IPAddress.objects.filter(
@@ -17,7 +17,7 @@ class IPAddressType(OptimizedNautobotObjectType):
17
17
  filterset_class = filters.IPAddressFilterSet
18
18
 
19
19
  def resolve_dynamic_groups(self, args):
20
- return DynamicGroup.objects.get_for_object(self, use_cache=True)
20
+ return DynamicGroup.objects.get_for_object(self)
21
21
 
22
22
 
23
23
  class PrefixType(OptimizedNautobotObjectType):
@@ -33,7 +33,7 @@ class PrefixType(OptimizedNautobotObjectType):
33
33
  filterset_class = filters.PrefixFilterSet
34
34
 
35
35
  def resolve_dynamic_groups(self, args):
36
- return DynamicGroup.objects.get_for_object(self, use_cache=True)
36
+ return DynamicGroup.objects.get_for_object(self)
37
37
 
38
38
 
39
39
  class VLANType(OptimizedNautobotObjectType):
@@ -0,0 +1,59 @@
1
+ # Generated by Django 4.2.9 on 2024-01-17 18:52
2
+
3
+ from django.db import migrations
4
+ import django.db.models.deletion
5
+
6
+ import nautobot.extras.models.roles
7
+ import nautobot.extras.models.statuses
8
+
9
+
10
+ class Migration(migrations.Migration):
11
+ dependencies = [
12
+ ("extras", "0110_alter_configcontext_cluster_groups_and_more"),
13
+ ("ipam", "0046_update_all_charfields_max_length_to_255"),
14
+ ]
15
+
16
+ operations = [
17
+ migrations.AlterField(
18
+ model_name="ipaddress",
19
+ name="role",
20
+ field=nautobot.extras.models.roles.RoleField(
21
+ blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to="extras.role"
22
+ ),
23
+ ),
24
+ migrations.AlterField(
25
+ model_name="ipaddress",
26
+ name="status",
27
+ field=nautobot.extras.models.statuses.StatusField(
28
+ on_delete=django.db.models.deletion.PROTECT, to="extras.status"
29
+ ),
30
+ ),
31
+ migrations.AlterField(
32
+ model_name="prefix",
33
+ name="role",
34
+ field=nautobot.extras.models.roles.RoleField(
35
+ blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to="extras.role"
36
+ ),
37
+ ),
38
+ migrations.AlterField(
39
+ model_name="prefix",
40
+ name="status",
41
+ field=nautobot.extras.models.statuses.StatusField(
42
+ on_delete=django.db.models.deletion.PROTECT, to="extras.status"
43
+ ),
44
+ ),
45
+ migrations.AlterField(
46
+ model_name="vlan",
47
+ name="role",
48
+ field=nautobot.extras.models.roles.RoleField(
49
+ blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to="extras.role"
50
+ ),
51
+ ),
52
+ migrations.AlterField(
53
+ model_name="vlan",
54
+ name="status",
55
+ field=nautobot.extras.models.statuses.StatusField(
56
+ on_delete=django.db.models.deletion.PROTECT, to="extras.status"
57
+ ),
58
+ ),
59
+ ]
nautobot/ipam/models.py CHANGED
@@ -27,13 +27,19 @@ from .validators import DNSValidator
27
27
 
28
28
  __all__ = (
29
29
  "IPAddress",
30
+ "IPAddressToInterface",
31
+ "Namespace",
30
32
  "Prefix",
33
+ "PrefixLocationAssignment",
31
34
  "RIR",
32
35
  "RouteTarget",
33
36
  "Service",
34
37
  "VLAN",
35
38
  "VLANGroup",
39
+ "VLANLocationAssignment",
36
40
  "VRF",
41
+ "VRFDeviceAssignment",
42
+ "VRFPrefixAssignment",
37
43
  )
38
44
 
39
45
 
@@ -275,6 +281,7 @@ class VRFDeviceAssignment(BaseModel):
275
281
  help_text="Unique route distinguisher (as defined in RFC 4364)",
276
282
  )
277
283
  name = models.CharField(blank=True, max_length=CHARFIELD_MAX_LENGTH)
284
+ is_metadata_associable_model = False
278
285
 
279
286
  class Meta:
280
287
  unique_together = [
@@ -312,6 +319,7 @@ class VRFDeviceAssignment(BaseModel):
312
319
  class VRFPrefixAssignment(BaseModel):
313
320
  vrf = models.ForeignKey("ipam.VRF", on_delete=models.CASCADE, related_name="+")
314
321
  prefix = models.ForeignKey("ipam.Prefix", on_delete=models.CASCADE, related_name="vrf_assignments")
322
+ is_metadata_associable_model = False
315
323
 
316
324
  class Meta:
317
325
  unique_together = ["vrf", "prefix"]
@@ -965,6 +973,7 @@ class Prefix(PrimaryModel):
965
973
  class PrefixLocationAssignment(BaseModel):
966
974
  prefix = models.ForeignKey("ipam.Prefix", on_delete=models.CASCADE, related_name="location_assignments")
967
975
  location = models.ForeignKey("dcim.Location", on_delete=models.CASCADE, related_name="prefix_assignments")
976
+ is_metadata_associable_model = False
968
977
 
969
978
  class Meta:
970
979
  unique_together = ["prefix", "location"]
@@ -1011,7 +1020,7 @@ class IPAddress(PrimaryModel):
1011
1020
  parent = models.ForeignKey(
1012
1021
  "ipam.Prefix",
1013
1022
  blank=True,
1014
- null=True, # TODO remove this, it shouldn't be permitted for the database!
1023
+ null=True,
1015
1024
  related_name="ip_addresses", # `IPAddress` to use `related_name="ip_addresses"`
1016
1025
  on_delete=models.PROTECT,
1017
1026
  help_text="The parent Prefix of this IPAddress.",
@@ -1108,7 +1117,7 @@ class IPAddress(PrimaryModel):
1108
1117
  raise ValidationError({"namespace": "No suitable parent Prefix exists in this Namespace"}) from e
1109
1118
 
1110
1119
  def clean(self):
1111
- self.address = self.address # not a no-op - forces re-calling of self._deconstruct_address()
1120
+ super().clean()
1112
1121
 
1113
1122
  # Validate that host is not being modified
1114
1123
  if self.present_in_database:
@@ -1122,8 +1131,8 @@ class IPAddress(PrimaryModel):
1122
1131
 
1123
1132
  closest_parent = self._get_closest_parent()
1124
1133
  # Validate `parent` can be used as the parent for this ipaddress
1125
- if closest_parent is not None:
1126
- if self.parent is not None and self.parent != closest_parent:
1134
+ if self.parent and closest_parent:
1135
+ if self.parent != closest_parent:
1127
1136
  raise ValidationError(
1128
1137
  {
1129
1138
  "parent": (
@@ -1135,20 +1144,23 @@ class IPAddress(PrimaryModel):
1135
1144
  self.parent = closest_parent
1136
1145
  self._namespace = None
1137
1146
 
1147
+ def save(self, *args, **kwargs):
1138
1148
  # 3.0 TODO: uncomment the below to enforce this constraint
1139
1149
  # if self.parent.type != choices.PrefixTypeChoices.TYPE_NETWORK:
1140
1150
  # err_msg = f"IP addresses cannot be created in {self.parent.type} prefixes. You must create a network prefix first."
1141
1151
  # raise ValidationError({"address": err_msg})
1142
1152
 
1153
+ self.address = self.address # not a no-op - forces re-calling of self._deconstruct_address()
1154
+
1143
1155
  # Force dns_name to lowercase
1144
1156
  if not self.dns_name.islower:
1145
1157
  self.dns_name = self.dns_name.lower()
1146
1158
 
1147
- super().clean()
1148
-
1149
- def save(self, *args, **kwargs):
1150
- self.clean() # MUST do data fixup as above
1151
-
1159
+ # Host and mask_length are required to get closest parent
1160
+ closest_parent = self._get_closest_parent()
1161
+ if closest_parent is not None:
1162
+ self.parent = closest_parent
1163
+ self._namespace = None
1152
1164
  super().save(*args, **kwargs)
1153
1165
 
1154
1166
  @property
@@ -1244,6 +1256,7 @@ class IPAddressToInterface(BaseModel):
1244
1256
  is_primary = models.BooleanField(default=False, help_text="Is primary address on interface")
1245
1257
  is_secondary = models.BooleanField(default=False, help_text="Is secondary address on interface")
1246
1258
  is_standby = models.BooleanField(default=False, help_text="Is standby address on interface")
1259
+ is_metadata_associable_model = False
1247
1260
 
1248
1261
  class Meta:
1249
1262
  unique_together = [
@@ -1441,6 +1454,7 @@ class VLAN(PrimaryModel):
1441
1454
  class VLANLocationAssignment(BaseModel):
1442
1455
  vlan = models.ForeignKey("ipam.VLAN", on_delete=models.CASCADE, related_name="location_assignments")
1443
1456
  location = models.ForeignKey("dcim.Location", on_delete=models.CASCADE, related_name="vlan_assignments")
1457
+ is_metadata_associable_model = False
1444
1458
 
1445
1459
  class Meta:
1446
1460
  unique_together = ["vlan", "location"]
@@ -56,7 +56,7 @@ class BaseNetworkQuerySet(RestrictedQuerySet):
56
56
  return call_map[version](search)
57
57
 
58
58
  except netaddr.core.AddrFormatError:
59
- ver_map = {4: "0/32", 6: "::/128"}
59
+ ver_map = {4: "0.0.0.0/32", 6: "::/128"}
60
60
  return netaddr.IPNetwork(ver_map[version])
61
61
 
62
62
  def _check_and_prep_ipv6(self, search):
nautobot/ipam/signals.py CHANGED
@@ -109,8 +109,10 @@ def assert_locations_content_types(sender, instance, action, reverse, model, pk_
109
109
  # instance = the Prefix or VLAN
110
110
  # model = Location class
111
111
  instance_ct = ContentType.objects.get_for_model(instance)
112
- invalid_locations = model.objects.select_related("location_type").filter(
113
- Q(pk__in=pk_set), ~Q(location_type__content_types__in=[instance_ct])
112
+ invalid_locations = (
113
+ model.objects.without_tree_fields()
114
+ .select_related("location_type")
115
+ .filter(Q(pk__in=pk_set), ~Q(location_type__content_types__in=[instance_ct]))
114
116
  )
115
117
  if invalid_locations.exists():
116
118
  invalid_location_types = {location.location_type.name for location in invalid_locations}
nautobot/ipam/tables.py CHANGED
@@ -443,6 +443,7 @@ class IPAddressTable(StatusTableMixin, RoleTableMixin, BaseTable):
443
443
  )
444
444
  tenant = TenantColumn()
445
445
  parent__namespace = tables.Column(linkify=True)
446
+ # Interface, Device, and VirtualMachine tables aren't currently filterable by IP address (?) so no LinkedCountColumn
446
447
  interface_count = tables.Column(verbose_name="Interfaces")
447
448
  interface_parent_count = tables.Column(verbose_name="Devices")
448
449
  vm_interface_count = LinkedCountColumn(
@@ -11,7 +11,7 @@
11
11
  <strong>Interfaces</strong>
12
12
  <div class="pull-right noprint">
13
13
  {% if request.user.is_authenticated %}
14
- <button type="button" class="btn btn-default btn-xs" data-toggle="modal" data-target="#IPAddressInterfaceTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
14
+ {% table_config_button_small interface_table %}
15
15
  {% endif %}
16
16
  </div>
17
17
  <div class="pull-right col-md-2 noprint">
@@ -11,7 +11,7 @@
11
11
  <strong>Interfaces</strong>
12
12
  <div class="pull-right noprint">
13
13
  {% if request.user.is_authenticated %}
14
- <button type="button" class="btn btn-default btn-xs" data-toggle="modal" data-target="#IPAddressVMInterfaceTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
14
+ {% table_config_button_small vm_interface_table %}
15
15
  {% endif %}
16
16
  </div>
17
17
  <div class="pull-right col-md-2 noprint">
@@ -119,4 +119,5 @@
119
119
  {% block content_right_page %}
120
120
  {% include 'panel_table.html' with table=parent_prefix_table heading='Parent Prefixes' panel_class='default' %}
121
121
  {% include "utilities/obj_table.html" with table=vrf_table table_template="panel_table.html" heading="Assigned VRFs" disable_pagination=False %}
122
+ {% include "utilities/obj_table.html" with table=cloud_network_table table_template="panel_table.html" heading="Assigned Cloud Networks" disable_pagination=False %}
122
123
  {% endblock content_right_page %}
@@ -15,7 +15,6 @@ from nautobot.dcim.choices import InterfaceTypeChoices
15
15
  from nautobot.dcim.models import Device, DeviceType, Interface, Location, LocationType, Manufacturer
16
16
  from nautobot.extras.models import Role, Status
17
17
  from nautobot.ipam import choices
18
- from nautobot.ipam.factory import VLANGroupFactory
19
18
  from nautobot.ipam.models import (
20
19
  IPAddress,
21
20
  IPAddressToInterface,
@@ -51,17 +50,17 @@ class NamespaceTest(APIViewTestCases.APIViewTestCase):
51
50
  location = Location.objects.first()
52
51
  cls.create_data = [
53
52
  {
54
- "name": "Purple Monkey Namesapce 1",
53
+ "name": "Purple Monkey Namespace 1",
55
54
  "description": "A perfectly cromulent namespace.",
56
55
  "location": location.pk,
57
56
  },
58
57
  {
59
- "name": "Purple Monkey Namesapce 2",
58
+ "name": "Purple Monkey Namespace 2",
60
59
  "description": "A secondarily cromulent namespace.",
61
60
  "location": location.pk,
62
61
  },
63
62
  {
64
- "name": "Purple Monkey Namesapce 3",
63
+ "name": "Purple Monkey Namespace 3",
65
64
  "description": "A third cromulent namespace.",
66
65
  "location": location.pk,
67
66
  },
@@ -211,7 +210,9 @@ class VRFPrefixAssignmentTest(APIViewTestCases.APIViewTestCase):
211
210
 
212
211
  @classmethod
213
212
  def setUpTestData(cls):
214
- cls.vrfs = VRF.objects.all()
213
+ cls.vrfs = (
214
+ VRF.objects.annotate(prefixes_count=Count("namespace__prefixes")).filter(prefixes_count__gte=2).distinct()
215
+ )
215
216
  cls.prefixes = Prefix.objects.all()
216
217
 
217
218
  VRFPrefixAssignment.objects.create(
@@ -233,15 +234,15 @@ class VRFPrefixAssignmentTest(APIViewTestCases.APIViewTestCase):
233
234
  cls.create_data = [
234
235
  {
235
236
  "vrf": cls.vrfs[2].pk,
236
- "prefix": cls.prefixes.filter(namespace=cls.vrfs[2].namespace)[0].pk,
237
+ "prefix": cls.prefixes.filter(namespace=cls.vrfs[2].namespace).exclude(vrfs=cls.vrfs[2])[0].pk,
237
238
  },
238
239
  {
239
240
  "vrf": cls.vrfs[3].pk,
240
- "prefix": cls.prefixes.filter(namespace=cls.vrfs[3].namespace)[0].pk,
241
+ "prefix": cls.prefixes.filter(namespace=cls.vrfs[3].namespace).exclude(vrfs=cls.vrfs[3])[0].pk,
241
242
  },
242
243
  {
243
244
  "vrf": cls.vrfs[4].pk,
244
- "prefix": cls.prefixes.filter(namespace=cls.vrfs[4].namespace)[0].pk,
245
+ "prefix": cls.prefixes.filter(namespace=cls.vrfs[4].namespace).exclude(vrfs=cls.vrfs[4])[0].pk,
245
246
  },
246
247
  ]
247
248
 
@@ -622,26 +623,33 @@ class PrefixLocationAssignmentTest(APIViewTestCases.APIViewTestCase):
622
623
 
623
624
  @classmethod
624
625
  def setUpTestData(cls):
625
- cls.prefixes = Prefix.objects.filter(locations__isnull=False)
626
+ cls.prefixes = Prefix.objects.all()
626
627
  cls.locations = Location.objects.filter(location_type__content_types=ContentType.objects.get_for_model(Prefix))
627
- locations_without_prefix = cls.locations.exclude(prefixes__in=[cls.prefixes[0], cls.prefixes[1]])
628
+
629
+ # Guarantees that at-least 3 locations do not have this prefix
630
+ for location in cls.locations[:3]:
631
+ location.prefixes.remove(cls.prefixes[0])
632
+ for location in cls.locations[3:6]:
633
+ location.prefixes.remove(cls.prefixes[1])
634
+ locations_without_prefix_0 = cls.locations.exclude(prefixes__in=[cls.prefixes[0]])
635
+ locations_without_prefix_1 = cls.locations.exclude(prefixes__in=[cls.prefixes[1]])
628
636
 
629
637
  cls.create_data = [
630
638
  {
631
639
  "prefix": cls.prefixes[0].pk,
632
- "location": locations_without_prefix[1].pk,
640
+ "location": locations_without_prefix_0[0].pk,
633
641
  },
634
642
  {
635
643
  "prefix": cls.prefixes[0].pk,
636
- "location": locations_without_prefix[2].pk,
644
+ "location": locations_without_prefix_0[1].pk,
637
645
  },
638
646
  {
639
647
  "prefix": cls.prefixes[1].pk,
640
- "location": locations_without_prefix[3].pk,
648
+ "location": locations_without_prefix_1[0].pk,
641
649
  },
642
650
  {
643
651
  "prefix": cls.prefixes[1].pk,
644
- "location": locations_without_prefix[4].pk,
652
+ "location": locations_without_prefix_1[1].pk,
645
653
  },
646
654
  ]
647
655
 
@@ -877,11 +885,12 @@ class IPAddressToInterfaceTest(APIViewTestCases.APIViewTestCase):
877
885
  status=devicestatus,
878
886
  )
879
887
  int_status = Status.objects.get_for_model(Interface).first()
888
+ int_role = Role.objects.get_for_model(Interface).first()
880
889
  int_type = InterfaceTypeChoices.TYPE_1GE_FIXED
881
890
  interfaces = [
882
- Interface.objects.create(device=device, name="eth0", status=int_status, type=int_type),
891
+ Interface.objects.create(device=device, name="eth0", status=int_status, role=int_role, type=int_type),
883
892
  Interface.objects.create(device=device, name="eth1", status=int_status, type=int_type),
884
- Interface.objects.create(device=device, name="eth2", status=int_status, type=int_type),
893
+ Interface.objects.create(device=device, name="eth2", status=int_status, role=int_role, type=int_type),
885
894
  Interface.objects.create(device=device, name="eth3", status=int_status, type=int_type),
886
895
  ]
887
896
 
@@ -890,8 +899,11 @@ class IPAddressToInterfaceTest(APIViewTestCases.APIViewTestCase):
890
899
  vm_status = Status.objects.get_for_model(VirtualMachine).first()
891
900
  virtual_machine = (VirtualMachine.objects.create(name="Virtual Machine 1", cluster=cluster, status=vm_status),)
892
901
  vm_int_status = Status.objects.get_for_model(VMInterface).first()
902
+ vm_int_role = Role.objects.get_for_model(VMInterface).first()
893
903
  vm_interfaces = [
894
- VMInterface.objects.create(virtual_machine=virtual_machine[0], name="veth0", status=vm_int_status),
904
+ VMInterface.objects.create(
905
+ virtual_machine=virtual_machine[0], name="veth0", status=vm_int_status, role=vm_int_role
906
+ ),
895
907
  VMInterface.objects.create(virtual_machine=virtual_machine[0], name="veth1", status=vm_int_status),
896
908
  ]
897
909
 
@@ -942,7 +954,11 @@ class VLANGroupTest(APIViewTestCases.APIViewTestCase):
942
954
  return VLANGroup.objects.create(name="DELETE ME")
943
955
 
944
956
  def get_deletable_object_pks(self):
945
- vlangroups = VLANGroupFactory.create_batch(size=3)
957
+ vlangroups = [
958
+ VLANGroup.objects.create(name="DELETE ME"),
959
+ VLANGroup.objects.create(name="ME TOO"),
960
+ VLANGroup.objects.create(name="AND ME"),
961
+ ]
946
962
  return [vg.pk for vg in vlangroups]
947
963
 
948
964
 
@@ -1063,6 +1079,9 @@ class VLANLocationAssignmentTest(APIViewTestCases.APIViewTestCase):
1063
1079
  def setUpTestData(cls):
1064
1080
  cls.vlans = VLAN.objects.filter(locations__isnull=False)
1065
1081
  cls.locations = Location.objects.filter(location_type__content_types=ContentType.objects.get_for_model(VLAN))
1082
+ # make sure there are 4 locations without vlans 1 and 2 for the create_data below
1083
+ for i in range(4):
1084
+ cls.locations[i].vlans.set([])
1066
1085
  locations_without_vlans = cls.locations.exclude(vlans__in=[cls.vlans[0], cls.vlans[1]])
1067
1086
 
1068
1087
  cls.create_data = [