nautobot 2.0.0a2__py3-none-any.whl → 2.0.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1029) hide show
  1. nautobot/__init__.py +1 -5
  2. nautobot/apps/api.py +6 -8
  3. nautobot/apps/forms.py +0 -2
  4. nautobot/apps/ui.py +0 -8
  5. nautobot/circuits/api/serializers.py +9 -119
  6. nautobot/circuits/api/urls.py +1 -1
  7. nautobot/circuits/api/views.py +0 -1
  8. nautobot/circuits/choices.py +0 -2
  9. nautobot/circuits/filters.py +7 -6
  10. nautobot/circuits/forms.py +3 -73
  11. nautobot/circuits/migrations/0001_initial_part_1.py +0 -1
  12. nautobot/circuits/migrations/0002_initial_part_2.py +0 -1
  13. nautobot/circuits/migrations/0003_auto_slug.py +0 -1
  14. nautobot/circuits/migrations/0004_increase_provider_account_length.py +0 -1
  15. nautobot/circuits/migrations/0005_providernetwork.py +0 -1
  16. nautobot/circuits/migrations/0006_cache_circuit_terminations.py +0 -1
  17. nautobot/circuits/migrations/0007_circuitterminations_primary_model.py +0 -1
  18. nautobot/circuits/migrations/0008_add_natural_indexing.py +0 -1
  19. nautobot/circuits/migrations/0009_circuittermination_location.py +0 -1
  20. nautobot/circuits/migrations/0010_rename_foreign_keys_and_related_names.py +0 -1
  21. nautobot/circuits/migrations/0011_remove_site_foreign_key_from_circuit_termination_class.py +0 -1
  22. nautobot/circuits/migrations/0012_created_datetime.py +0 -1
  23. nautobot/circuits/migrations/0013_alter_circuittermination__path.py +0 -1
  24. nautobot/circuits/migrations/0014_related_name_changes.py +1 -2
  25. nautobot/circuits/migrations/0015_remove_circuittype_provider_slug.py +20 -0
  26. nautobot/circuits/migrations/0016_tagsfield.py +34 -0
  27. nautobot/circuits/migrations/0017_fixup_null_statuses.py +22 -0
  28. nautobot/circuits/migrations/0018_status_nonnullable.py +22 -0
  29. nautobot/circuits/models.py +3 -93
  30. nautobot/circuits/navigation.py +14 -69
  31. nautobot/circuits/signals.py +0 -2
  32. nautobot/circuits/tables.py +42 -5
  33. nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -1
  34. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -1
  35. nautobot/circuits/templates/circuits/circuittype_retrieve.html +1 -1
  36. nautobot/circuits/templates/circuits/provider_create.html +0 -1
  37. nautobot/circuits/templates/circuits/provider_retrieve.html +1 -1
  38. nautobot/circuits/tests/integration/test_relationships.py +13 -16
  39. nautobot/circuits/tests/test_api.py +13 -43
  40. nautobot/circuits/tests/test_filters.py +20 -15
  41. nautobot/circuits/tests/test_models.py +7 -3
  42. nautobot/circuits/tests/test_views.py +57 -67
  43. nautobot/circuits/views.py +18 -9
  44. nautobot/core/api/__init__.py +8 -2
  45. nautobot/core/api/authentication.py +0 -3
  46. nautobot/core/api/fields.py +15 -6
  47. nautobot/core/api/filter_backends.py +3 -2
  48. nautobot/core/api/metadata.py +237 -30
  49. nautobot/core/api/mixins.py +94 -0
  50. nautobot/core/api/pagination.py +3 -3
  51. nautobot/core/api/parsers.py +154 -0
  52. nautobot/core/api/renderers.py +153 -2
  53. nautobot/core/api/schema.py +47 -3
  54. nautobot/core/api/serializers.py +377 -37
  55. nautobot/core/api/urls.py +11 -3
  56. nautobot/core/api/utils.py +174 -2
  57. nautobot/core/api/versioning.py +32 -10
  58. nautobot/core/api/views.py +266 -75
  59. nautobot/core/apps/__init__.py +138 -221
  60. nautobot/core/celery/__init__.py +112 -41
  61. nautobot/core/celery/backends.py +19 -13
  62. nautobot/core/celery/control.py +46 -0
  63. nautobot/core/celery/encoders.py +53 -0
  64. nautobot/core/celery/log.py +38 -0
  65. nautobot/core/celery/schedulers.py +23 -4
  66. nautobot/core/celery/task.py +1 -16
  67. nautobot/core/checks.py +0 -27
  68. nautobot/core/choices.py +21 -113
  69. nautobot/core/{cli.py → cli/__init__.py} +1 -2
  70. nautobot/core/cli/__main__.py +3 -0
  71. nautobot/core/constants.py +25 -43
  72. nautobot/core/context_processors.py +12 -0
  73. nautobot/core/filters.py +2 -2
  74. nautobot/core/forms/__init__.py +0 -4
  75. nautobot/core/forms/fields.py +39 -68
  76. nautobot/core/forms/forms.py +27 -27
  77. nautobot/core/forms/utils.py +7 -59
  78. nautobot/core/forms/widgets.py +0 -1
  79. nautobot/core/graphql/__init__.py +2 -2
  80. nautobot/core/graphql/schema.py +4 -27
  81. nautobot/core/jobs/__init__.py +75 -0
  82. nautobot/core/management/commands/build_ui.py +255 -0
  83. nautobot/core/management/commands/celery.py +0 -1
  84. nautobot/core/management/commands/generate_test_data.py +18 -13
  85. nautobot/core/management/commands/post_upgrade.py +24 -24
  86. nautobot/core/management/commands/validate_models.py +0 -1
  87. nautobot/core/middleware.py +0 -1
  88. nautobot/core/models/__init__.py +26 -1
  89. nautobot/core/models/fields.py +24 -5
  90. nautobot/core/models/generics.py +2 -46
  91. nautobot/core/models/managers.py +5 -0
  92. nautobot/core/models/name_color_content_types.py +1 -19
  93. nautobot/core/models/tree_queries.py +14 -4
  94. nautobot/core/models/utils.py +9 -10
  95. nautobot/core/models/validators.py +17 -8
  96. nautobot/core/releases.py +8 -10
  97. nautobot/core/settings.py +81 -53
  98. nautobot/core/tables.py +5 -5
  99. nautobot/core/tasks.py +4 -7
  100. nautobot/core/templates/base.html +1 -49
  101. nautobot/core/templates/base_django.html +49 -0
  102. nautobot/core/templates/base_react.html +55 -0
  103. nautobot/core/templates/buttons/export.html +6 -4
  104. nautobot/core/templates/generic/object_bulk_create.html +10 -21
  105. nautobot/core/templates/generic/object_list.html +4 -1
  106. nautobot/core/templates/generic/object_retrieve_plugin_full_width.html +3 -0
  107. nautobot/core/templates/inc/footer.html +1 -0
  108. nautobot/core/templates/inc/javascript.html +0 -14
  109. nautobot/core/templates/inc/nav_menu.html +28 -33
  110. nautobot/core/templates/inc/object_details_advanced_panel.html +13 -0
  111. nautobot/core/templates/inc/relationships_table_rows.html +2 -2
  112. nautobot/core/templates/nautobot_config.py.j2 +8 -25
  113. nautobot/core/templates/plugin_template/__init__.py-tpl +1 -2
  114. nautobot/core/templates/rest_framework/api.html +8 -0
  115. nautobot/core/templatetags/buttons.py +32 -29
  116. nautobot/core/templatetags/helpers.py +1 -1
  117. nautobot/core/testing/__init__.py +47 -44
  118. nautobot/core/testing/api.py +365 -47
  119. nautobot/core/testing/filters.py +12 -7
  120. nautobot/core/testing/integration.py +1 -1
  121. nautobot/core/testing/migrations.py +2 -0
  122. nautobot/core/testing/mixins.py +22 -12
  123. nautobot/core/testing/schema.py +2 -1
  124. nautobot/core/testing/views.py +28 -51
  125. nautobot/core/tests/integration/test_filters.py +17 -8
  126. nautobot/core/tests/integration/test_navbar.py +11 -34
  127. nautobot/core/tests/integration/test_plugin_navbar.py +9 -103
  128. nautobot/core/tests/nautobot_config.py +2 -3
  129. nautobot/core/tests/runner.py +0 -1
  130. nautobot/core/tests/test_api.py +290 -24
  131. nautobot/core/tests/test_authentication.py +57 -14
  132. nautobot/core/tests/test_checks.py +0 -7
  133. nautobot/core/tests/test_choices.py +0 -1
  134. nautobot/core/tests/test_filters.py +117 -110
  135. nautobot/core/tests/test_forms.py +47 -110
  136. nautobot/core/tests/test_graphql.py +158 -135
  137. nautobot/core/tests/test_logging.py +4 -1
  138. nautobot/core/tests/test_managers.py +3 -5
  139. nautobot/core/tests/test_models.py +2 -0
  140. nautobot/core/tests/test_ordering.py +0 -2
  141. nautobot/core/tests/test_paginator.py +3 -1
  142. nautobot/core/tests/test_releases.py +12 -12
  143. nautobot/core/tests/test_templatetags_helpers.py +7 -4
  144. nautobot/core/tests/test_utils.py +112 -78
  145. nautobot/core/tests/test_views.py +12 -17
  146. nautobot/core/tests/test_views_utils.py +6 -9
  147. nautobot/core/utils/data.py +17 -0
  148. nautobot/core/utils/deprecation.py +13 -20
  149. nautobot/core/utils/filtering.py +53 -9
  150. nautobot/core/utils/git.py +12 -4
  151. nautobot/core/utils/lookup.py +3 -1
  152. nautobot/core/utils/requests.py +23 -116
  153. nautobot/core/views/__init__.py +1 -2
  154. nautobot/core/views/generic.py +131 -119
  155. nautobot/core/views/mixins.py +53 -62
  156. nautobot/core/views/paginator.py +0 -1
  157. nautobot/core/views/renderers.py +14 -12
  158. nautobot/core/views/utils.py +87 -4
  159. nautobot/dcim/api/serializers.py +160 -672
  160. nautobot/dcim/api/urls.py +1 -1
  161. nautobot/dcim/api/views.py +7 -46
  162. nautobot/dcim/choices.py +2 -25
  163. nautobot/dcim/elevations.py +0 -1
  164. nautobot/dcim/factory.py +15 -4
  165. nautobot/dcim/filters/__init__.py +42 -13
  166. nautobot/dcim/form_mixins.py +1 -27
  167. nautobot/dcim/forms.py +58 -797
  168. nautobot/dcim/management/commands/trace_paths.py +0 -1
  169. nautobot/dcim/migrations/0001_initial_part_1.py +0 -1
  170. nautobot/dcim/migrations/0002_initial_part_2.py +0 -1
  171. nautobot/dcim/migrations/0003_initial_part_3.py +0 -1
  172. nautobot/dcim/migrations/0004_initial_part_4.py +0 -1
  173. nautobot/dcim/migrations/0005_device_local_context_schema.py +0 -1
  174. nautobot/dcim/migrations/0006_auto_slug.py +0 -1
  175. nautobot/dcim/migrations/0007_device_secrets_group.py +0 -1
  176. nautobot/dcim/migrations/0008_increase_all_serial_lengths.py +0 -1
  177. nautobot/dcim/migrations/0009_add_natural_indexing.py +0 -1
  178. nautobot/dcim/migrations/0010_interface_status.py +0 -1
  179. nautobot/dcim/migrations/0011_interface_status_data_migration.py +0 -1
  180. nautobot/dcim/migrations/0012_interface_parent_bridge.py +0 -1
  181. nautobot/dcim/migrations/0013_location_location_type.py +0 -1
  182. nautobot/dcim/migrations/0014_location_status_data_migration.py +0 -1
  183. nautobot/dcim/migrations/0015_device_components__changeloggedmodel.py +0 -1
  184. nautobot/dcim/migrations/0016_device_components__timestamp_data_migration.py +0 -1
  185. nautobot/dcim/migrations/0017_locationtype_nestable.py +0 -1
  186. nautobot/dcim/migrations/0018_device_redundancy_group.py +0 -1
  187. nautobot/dcim/migrations/0019_device_redundancy_group_data_migration.py +0 -1
  188. nautobot/dcim/migrations/0020_move_site_fields_to_location_model.py +0 -1
  189. nautobot/dcim/migrations/0021_mptt_to_tree_queries.py +0 -1
  190. nautobot/dcim/migrations/0022_interface_mac_address_data_migration.py +0 -1
  191. nautobot/dcim/migrations/0023_alter_interface_mac_address.py +0 -1
  192. nautobot/dcim/migrations/0024_alter_device_and_rack_role_add_new_role.py +2 -2
  193. nautobot/dcim/migrations/0025_device_and_rack_roles_data_migrations.py +19 -14
  194. nautobot/dcim/migrations/0026_rename_device_and_rack_role.py +0 -1
  195. nautobot/dcim/migrations/0027_remove_device_role_and_rack_role.py +1 -2
  196. nautobot/dcim/migrations/0028_rename_foreignkey_fields.py +1 -2
  197. nautobot/dcim/migrations/0029_add_tree_managers_and_foreign_keys_pre_data_migration.py +0 -1
  198. nautobot/dcim/migrations/0030_migrate_region_and_site_data_to_locations.py +2 -2
  199. nautobot/dcim/migrations/0031_rename_path_end_point_related_name.py +0 -1
  200. nautobot/dcim/migrations/0032_remove_site_foreign_key_from_dcim_models.py +0 -1
  201. nautobot/dcim/migrations/0033_created_datetime.py +0 -1
  202. nautobot/dcim/migrations/0034_fixup_fks_and_related_names.py +0 -1
  203. nautobot/dcim/migrations/0035_related_name_changes.py +1 -2
  204. nautobot/dcim/migrations/0036_remove_region_and_site.py +1 -2
  205. nautobot/dcim/migrations/0037_interface_ip_addresses_m2m.py +0 -1
  206. nautobot/dcim/migrations/0038_alter_location_managers.py +0 -1
  207. nautobot/dcim/migrations/0039_remove_slug.py +24 -0
  208. nautobot/dcim/migrations/0040_tagsfield.py +109 -0
  209. nautobot/dcim/migrations/0041_ipam__namespaces.py +25 -0
  210. nautobot/dcim/migrations/0042_fixup_null_statuses.py +51 -0
  211. nautobot/dcim/migrations/0043_status_nonnullable.py +72 -0
  212. nautobot/dcim/models/cables.py +4 -35
  213. nautobot/dcim/models/device_component_templates.py +7 -2
  214. nautobot/dcim/models/device_components.py +26 -203
  215. nautobot/dcim/models/devices.py +30 -152
  216. nautobot/dcim/models/locations.py +3 -64
  217. nautobot/dcim/models/power.py +3 -51
  218. nautobot/dcim/models/racks.py +7 -86
  219. nautobot/dcim/navigation.py +141 -467
  220. nautobot/dcim/signals.py +0 -2
  221. nautobot/dcim/tables/devices.py +8 -5
  222. nautobot/dcim/tables/devicetypes.py +1 -1
  223. nautobot/dcim/tables/locations.py +2 -2
  224. nautobot/dcim/tables/power.py +2 -2
  225. nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -0
  226. nautobot/dcim/templates/dcim/device.html +15 -4
  227. nautobot/dcim/templates/dcim/device_edit.html +6 -0
  228. nautobot/dcim/templates/dcim/deviceredundancygroup_create.html +0 -1
  229. nautobot/dcim/templates/dcim/devicetype.html +2 -2
  230. nautobot/dcim/templates/dcim/interface.html +4 -0
  231. nautobot/dcim/templates/dcim/interface_connection_list.html +7 -0
  232. nautobot/dcim/templates/dcim/interface_edit.html +1 -0
  233. nautobot/dcim/templates/dcim/location.html +16 -1
  234. nautobot/dcim/templates/dcim/locationtype.html +15 -0
  235. nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -0
  236. nautobot/dcim/templates/dcim/rackgroup.html +0 -12
  237. nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
  238. nautobot/dcim/tests/test_api.py +202 -130
  239. nautobot/dcim/tests/test_cablepaths.py +47 -42
  240. nautobot/dcim/tests/test_filters.py +156 -134
  241. nautobot/dcim/tests/test_forms.py +12 -213
  242. nautobot/dcim/tests/test_graphql.py +8 -3
  243. nautobot/dcim/tests/test_migrations.py +6 -11
  244. nautobot/dcim/tests/test_models.py +208 -158
  245. nautobot/dcim/tests/test_natural_ordering.py +12 -14
  246. nautobot/dcim/tests/test_signals.py +7 -4
  247. nautobot/dcim/tests/test_views.py +270 -264
  248. nautobot/dcim/urls.py +21 -26
  249. nautobot/dcim/views.py +14 -156
  250. nautobot/docs/additional-features/caching.md +6 -87
  251. nautobot/docs/additional-features/job-scheduling-and-approvals.md +3 -0
  252. nautobot/docs/additional-features/jobs.md +179 -197
  253. nautobot/docs/administration/nautobot-server.md +9 -24
  254. nautobot/docs/administration/nautobot-shell.md +6 -6
  255. nautobot/docs/administration/replicating-nautobot.md +0 -10
  256. nautobot/docs/configuration/index.md +9 -9
  257. nautobot/docs/configuration/optional-settings.md +32 -61
  258. nautobot/docs/configuration/required-settings.md +11 -52
  259. nautobot/docs/development/application-registry.md +2 -13
  260. nautobot/docs/development/best-practices.md +2 -1
  261. nautobot/docs/development/docker-compose-advanced-use-cases.md +1 -1
  262. nautobot/docs/development/extending-models.md +15 -17
  263. nautobot/docs/development/generic-views.md +0 -2
  264. nautobot/docs/development/getting-started.md +56 -6
  265. nautobot/docs/development/navigation-menu.md +22 -93
  266. nautobot/docs/development/react-ui.md +105 -0
  267. nautobot/docs/development/release-checklist.md +3 -3
  268. nautobot/docs/development/role-internals.md +1 -3
  269. nautobot/docs/development/style-guide.md +6 -4
  270. nautobot/docs/development/templates.md +2 -1
  271. nautobot/docs/docker/index.md +16 -14
  272. nautobot/docs/index.md +7 -3
  273. nautobot/docs/installation/index.md +4 -1
  274. nautobot/docs/installation/migrating-from-netbox.md +12 -43
  275. nautobot/docs/installation/migrating-from-postgresql.md +1 -1
  276. nautobot/docs/installation/nautobot.md +1 -1
  277. nautobot/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  278. nautobot/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  279. nautobot/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  280. nautobot/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  281. nautobot/docs/installation/tables/v2-code-removals.yaml +67 -0
  282. nautobot/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  283. nautobot/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  284. nautobot/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  285. nautobot/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  286. nautobot/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  287. nautobot/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  288. nautobot/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  289. nautobot/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  290. nautobot/docs/installation/upgrading-from-nautobot-v1.md +190 -636
  291. nautobot/docs/installation/upgrading.md +5 -2
  292. nautobot/docs/models/dcim/device.md +3 -0
  293. nautobot/docs/models/dcim/deviceredundancygroup.md +3 -3
  294. nautobot/docs/models/extras/computedfield.md +4 -4
  295. nautobot/docs/models/extras/dynamicgroup.md +9 -9
  296. nautobot/docs/models/extras/gitrepository.md +3 -0
  297. nautobot/docs/models/extras/job.md +1 -0
  298. nautobot/docs/models/extras/jobbutton.md +18 -13
  299. nautobot/docs/models/extras/jobhook.md +7 -4
  300. nautobot/docs/models/extras/jobresult.md +6 -2
  301. nautobot/docs/models/extras/relationship.md +2 -2
  302. nautobot/docs/models/extras/status.md +6 -19
  303. nautobot/docs/models/ipam/ipaddress.md +3 -0
  304. nautobot/docs/models/ipam/vrf.md +0 -3
  305. nautobot/docs/models/virtualization/virtualmachine.md +3 -0
  306. nautobot/docs/plugins/development.md +92 -24
  307. nautobot/docs/release-notes/version-1.5.md +96 -0
  308. nautobot/docs/release-notes/version-2.0.md +216 -0
  309. nautobot/docs/requirements.txt +5 -4
  310. nautobot/docs/rest-api/overview.md +384 -215
  311. nautobot/docs/rest-api/ui-related-endpoints.md +9 -0
  312. nautobot/extras/admin.py +3 -5
  313. nautobot/extras/api/customfields.py +15 -39
  314. nautobot/extras/api/fields.py +0 -11
  315. nautobot/extras/api/mixins.py +45 -0
  316. nautobot/extras/api/relationships.py +63 -159
  317. nautobot/extras/api/serializers.py +165 -706
  318. nautobot/extras/api/urls.py +1 -1
  319. nautobot/extras/api/views.py +295 -282
  320. nautobot/extras/apps.py +4 -7
  321. nautobot/extras/choices.py +11 -22
  322. nautobot/extras/constants.py +9 -3
  323. nautobot/extras/datasources/__init__.py +2 -0
  324. nautobot/extras/datasources/git.py +135 -186
  325. nautobot/extras/datasources/registry.py +25 -35
  326. nautobot/extras/factory.py +1 -3
  327. nautobot/extras/filters/__init__.py +49 -47
  328. nautobot/extras/filters/mixins.py +10 -8
  329. nautobot/extras/forms/forms.py +72 -148
  330. nautobot/extras/forms/mixins.py +34 -57
  331. nautobot/extras/health_checks.py +0 -33
  332. nautobot/extras/jobs.py +387 -566
  333. nautobot/extras/management/__init__.py +55 -48
  334. nautobot/extras/management/commands/renaturalize.py +0 -1
  335. nautobot/extras/management/commands/runjob.py +24 -62
  336. nautobot/extras/management/commands/webhook_receiver.py +0 -1
  337. nautobot/extras/managers.py +30 -7
  338. nautobot/extras/migrations/0001_initial_part_1.py +0 -1
  339. nautobot/extras/migrations/0002_initial_part_2.py +0 -1
  340. nautobot/extras/migrations/0003_initial_part_3.py +0 -1
  341. nautobot/extras/migrations/0004_populate_default_status_records.py +0 -1
  342. nautobot/extras/migrations/0005_configcontext_device_types.py +0 -1
  343. nautobot/extras/migrations/0006_graphqlquery.py +0 -1
  344. nautobot/extras/migrations/0007_configcontextschema.py +0 -1
  345. nautobot/extras/migrations/0008_jobresult__custom_field_data.py +0 -1
  346. nautobot/extras/migrations/0009_computedfield.py +0 -1
  347. nautobot/extras/migrations/0010_change_cf_validation_max_min_field_to_bigint.py +0 -1
  348. nautobot/extras/migrations/0011_fileattachment_fileproxy.py +0 -1
  349. nautobot/extras/migrations/0012_healthchecktestmodel.py +0 -1
  350. nautobot/extras/migrations/0013_default_fallback_value_computedfield.py +0 -1
  351. nautobot/extras/migrations/0014_auto_slug.py +0 -1
  352. nautobot/extras/migrations/0015_scheduled_job.py +0 -1
  353. nautobot/extras/migrations/0016_secret.py +0 -1
  354. nautobot/extras/migrations/0017_joblogentry.py +0 -1
  355. nautobot/extras/migrations/0018_joblog_data_migration.py +0 -2
  356. nautobot/extras/migrations/0019_joblogentry__meta_options__related_name.py +0 -1
  357. nautobot/extras/migrations/0020_customfield_changelog.py +0 -1
  358. nautobot/extras/migrations/0021_customfield_changelog_data.py +0 -1
  359. nautobot/extras/migrations/0022_objectchange_object_datav2.py +0 -1
  360. nautobot/extras/migrations/0023_job_model.py +0 -1
  361. nautobot/extras/migrations/0024_job_data_migration.py +0 -1
  362. nautobot/extras/migrations/0025_add_advanced_ui_boolean_to_customfield_conputedfield_and_relationship.py +0 -1
  363. nautobot/extras/migrations/0026_job_add_gitrepository_fk.py +0 -1
  364. nautobot/extras/migrations/0027_job_gitrepository_data_migration.py +0 -1
  365. nautobot/extras/migrations/0028_job_reduce_source.py +0 -1
  366. nautobot/extras/migrations/0029_dynamicgroup.py +0 -1
  367. nautobot/extras/migrations/0030_webhook_alter_unique_together.py +0 -1
  368. nautobot/extras/migrations/0031_tag_content_types.py +0 -1
  369. nautobot/extras/migrations/0032_tag_content_types_data_migration.py +0 -1
  370. nautobot/extras/migrations/0033_add__optimized_indexing.py +0 -1
  371. nautobot/extras/migrations/0034_alter_fileattachment_mimetype.py +0 -1
  372. nautobot/extras/migrations/0035_scheduledjob_crontab.py +0 -1
  373. nautobot/extras/migrations/0036_job_add_has_sensitive_variables.py +0 -1
  374. nautobot/extras/migrations/0037_configcontextschema__remove_name_unique__create_constraint_unique_name_owner.py +0 -1
  375. nautobot/extras/migrations/0038_configcontext_locations.py +0 -1
  376. nautobot/extras/migrations/0039_objectchange__add_change_context.py +0 -1
  377. nautobot/extras/migrations/0040_dynamicgroup__dynamicgroupmembership.py +0 -1
  378. nautobot/extras/migrations/0041_jobresult_job_kwargs.py +0 -1
  379. nautobot/extras/migrations/0042_job__add_is_job_hook_receiver.py +0 -1
  380. nautobot/extras/migrations/0043_note.py +0 -1
  381. nautobot/extras/migrations/0044_add_job_hook.py +0 -1
  382. nautobot/extras/migrations/0045_add_custom_field_slug.py +0 -1
  383. nautobot/extras/migrations/0046_populate_custom_field_slug_label.py +0 -1
  384. nautobot/extras/migrations/0047_enforce_custom_field_slug.py +0 -1
  385. nautobot/extras/migrations/0048_alter_objectchange_change_context_detail.py +0 -1
  386. nautobot/extras/migrations/0049_alter_tag_slug.py +0 -1
  387. nautobot/extras/migrations/0050_customfield_grouping.py +0 -1
  388. nautobot/extras/migrations/0051_add_job_task_queues.py +0 -1
  389. nautobot/extras/migrations/0052_configcontext_device_redundancy_groups.py +0 -1
  390. nautobot/extras/migrations/0053_relationship_required_on.py +0 -1
  391. nautobot/extras/migrations/0054_scheduledjob_kwargs_request_user_change.py +0 -1
  392. nautobot/extras/migrations/0055_configcontext_dynamic_groups.py +0 -1
  393. nautobot/extras/migrations/0056_objectchange_add_reverse_time_idx.py +0 -1
  394. nautobot/extras/migrations/0057_jobbutton.py +0 -1
  395. nautobot/extras/migrations/0058_jobresult_add_time_status_idxs.py +38 -0
  396. nautobot/extras/migrations/{0058_joblogentry_scheduledjob_webhook_data_migration.py → 0059_joblogentry_scheduledjob_webhook_data_migration.py} +1 -2
  397. nautobot/extras/migrations/{0059_alter_joblogentry_scheduledjob_webhook_fields.py → 0060_alter_joblogentry_scheduledjob_webhook_fields.py} +1 -2
  398. nautobot/extras/migrations/{0060_role_and_alter_status.py → 0061_role_and_alter_status.py} +1 -8
  399. nautobot/extras/migrations/{0061_collect_roles_from_related_apps_roles.py → 0062_collect_roles_from_related_apps_roles.py} +33 -33
  400. nautobot/extras/migrations/{0062_alter_role_options.py → 0063_alter_role_options.py} +1 -2
  401. nautobot/extras/migrations/{0063_alter_configcontext_and_add_new_role.py → 0064_alter_configcontext_and_add_new_role.py} +1 -2
  402. nautobot/extras/migrations/0065_configcontext_data_migrations.py +44 -0
  403. nautobot/extras/migrations/{0065_rename_configcontext_role.py → 0066_rename_configcontext_role.py} +1 -2
  404. nautobot/extras/migrations/{0066_jobresult__add_celery_fields.py → 0067_jobresult__add_celery_fields.py} +36 -3
  405. nautobot/extras/migrations/{0067_created_datetime.py → 0068_created_datetime.py} +1 -2
  406. nautobot/extras/migrations/{0068_remove_site_and_region_attributes_from_config_context.py → 0069_remove_site_and_region_attributes_from_config_context.py} +1 -2
  407. nautobot/extras/migrations/{0069_replace_related_names.py → 0070_replace_related_names.py} +1 -1
  408. nautobot/extras/migrations/{0070_rename_model_fields.py → 0071_rename_model_fields.py} +1 -2
  409. nautobot/extras/migrations/0072_job__unique_name_data_migration.py +86 -0
  410. nautobot/extras/migrations/{0072_job__unique_name.py → 0073_job__unique_name.py} +13 -10
  411. nautobot/extras/migrations/{0073_remove_gitrepository_fields.py → 0074_remove_gitrepository_fields.py} +1 -2
  412. nautobot/extras/migrations/{0074_rename_slug_to_key_for_custom_field.py → 0075_rename_slug_to_key_for_custom_field.py} +1 -1
  413. nautobot/extras/migrations/{0075_migrate_custom_field_data.py → 0076_migrate_custom_field_data.py} +1 -1
  414. nautobot/extras/migrations/{0076_remove_name_field_and_make_label_field_non_nullable.py → 0077_remove_name_field_and_make_label_field_non_nullable.py} +1 -1
  415. nautobot/extras/migrations/0078_remove_slug.py +45 -0
  416. nautobot/extras/migrations/0079_tagsfield.py +28 -0
  417. nautobot/extras/migrations/0080_rename_relationship_slug_to_key.py +17 -0
  418. nautobot/extras/migrations/0081_rename_relationship_name_to_label.py +29 -0
  419. nautobot/extras/migrations/0082_ensure_relationship_keys_are_unique.py +43 -0
  420. nautobot/extras/migrations/0083_rename_computed_field_slug_to_key.py +21 -0
  421. nautobot/extras/migrations/0084_taggeditem_cleanup.py +43 -0
  422. nautobot/extras/migrations/0085_taggeditem_uniqueness.py +22 -0
  423. nautobot/extras/migrations/0086_job__celery_task_fields__dryrun_support.py +81 -0
  424. nautobot/extras/migrations/0087_job__commit_default_data_migration.py +26 -0
  425. nautobot/extras/migrations/0088_joblogentry__log_level_default.py +17 -0
  426. nautobot/extras/migrations/0089_joblogentry__log_level_data_migration.py +34 -0
  427. nautobot/extras/migrations/0090_scheduledjob__data_migration.py +57 -0
  428. nautobot/extras/models/__init__.py +2 -3
  429. nautobot/extras/models/change_logging.py +0 -36
  430. nautobot/extras/models/customfields.py +39 -33
  431. nautobot/extras/models/datasources.py +48 -50
  432. nautobot/extras/models/groups.py +5 -12
  433. nautobot/extras/models/jobs.py +190 -323
  434. nautobot/extras/models/mixins.py +0 -71
  435. nautobot/extras/models/models.py +1 -22
  436. nautobot/extras/models/relationships.py +20 -21
  437. nautobot/extras/models/roles.py +0 -23
  438. nautobot/extras/models/secrets.py +2 -31
  439. nautobot/extras/models/statuses.py +6 -5
  440. nautobot/extras/models/tags.py +2 -17
  441. nautobot/extras/navigation.py +89 -307
  442. nautobot/extras/plugins/__init__.py +3 -121
  443. nautobot/extras/plugins/utils.py +0 -3
  444. nautobot/extras/plugins/validators.py +5 -4
  445. nautobot/extras/plugins/views.py +16 -4
  446. nautobot/extras/querysets.py +1 -7
  447. nautobot/extras/registry.py +3 -0
  448. nautobot/extras/signals.py +26 -60
  449. nautobot/extras/tables.py +42 -49
  450. nautobot/extras/tasks.py +0 -12
  451. nautobot/extras/templates/extras/configcontext.html +1 -1
  452. nautobot/extras/templates/extras/configcontextschema.html +16 -1
  453. nautobot/extras/templates/extras/customfield.html +0 -13
  454. nautobot/extras/templates/extras/dynamicgroup_edit.html +0 -1
  455. nautobot/extras/templates/extras/gitrepository.html +3 -3
  456. nautobot/extras/templates/extras/inc/jobresult.html +10 -0
  457. nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
  458. nautobot/extras/templates/extras/job.html +35 -25
  459. nautobot/extras/templates/extras/job_approval_request.html +15 -30
  460. nautobot/extras/templates/extras/job_detail.html +13 -31
  461. nautobot/extras/templates/extras/job_edit.html +14 -17
  462. nautobot/extras/templates/extras/jobresult.html +24 -6
  463. nautobot/extras/templates/extras/objectchange_list.html +1 -1
  464. nautobot/extras/templates/extras/scheduledjob.html +2 -2
  465. nautobot/extras/templates/extras/secret.html +28 -0
  466. nautobot/extras/templates/extras/secret_edit.html +0 -1
  467. nautobot/extras/templates/extras/secretsgroup_edit.html +0 -1
  468. nautobot/extras/templatetags/custom_links.py +0 -2
  469. nautobot/extras/templatetags/job_buttons.py +1 -0
  470. nautobot/extras/templatetags/plugins.py +0 -1
  471. nautobot/extras/{tests/example_jobs → test_jobs}/api_test_job.py +13 -6
  472. nautobot/extras/test_jobs/atomic_transaction.py +53 -0
  473. nautobot/extras/test_jobs/dry_run.py +29 -0
  474. nautobot/extras/{tests/example_jobs/test_duplicate_name.py → test_jobs/duplicate_name.py} +4 -0
  475. nautobot/extras/test_jobs/duplicate_name2.py +9 -0
  476. nautobot/extras/test_jobs/fail.py +23 -0
  477. nautobot/extras/{tests/example_jobs/test_field_default.py → test_jobs/field_default.py} +4 -0
  478. nautobot/extras/{tests/example_jobs/test_field_order.py → test_jobs/field_order.py} +4 -0
  479. nautobot/extras/{tests/example_jobs/test_file_upload_fail.py → test_jobs/file_upload_fail.py} +11 -6
  480. nautobot/extras/test_jobs/file_upload_pass.py +25 -0
  481. nautobot/extras/test_jobs/has_sensitive_variables.py +25 -0
  482. nautobot/extras/test_jobs/ipaddress_vars.py +66 -0
  483. nautobot/extras/test_jobs/job_button_receiver.py +28 -0
  484. nautobot/extras/test_jobs/job_hook_receiver.py +29 -0
  485. nautobot/extras/test_jobs/job_variables.py +88 -0
  486. nautobot/extras/test_jobs/location_with_custom_field.py +45 -0
  487. nautobot/extras/test_jobs/log_redaction.py +20 -0
  488. nautobot/extras/test_jobs/log_skip_db_logging.py +17 -0
  489. nautobot/extras/test_jobs/modify_db.py +25 -0
  490. nautobot/extras/{tests/example_jobs/test_no_field_order.py → test_jobs/no_field_order.py} +4 -0
  491. nautobot/extras/test_jobs/object_var_optional.py +21 -0
  492. nautobot/extras/test_jobs/object_var_required.py +21 -0
  493. nautobot/extras/test_jobs/object_vars.py +26 -0
  494. nautobot/extras/test_jobs/pass.py +25 -0
  495. nautobot/extras/test_jobs/profiling.py +32 -0
  496. nautobot/extras/test_jobs/read_only_job.py +15 -0
  497. nautobot/extras/{tests/example_jobs/test_required_args.py → test_jobs/required_args.py} +4 -0
  498. nautobot/extras/{tests/example_jobs/test_soft_time_limit_greater_than_time_limit.py → test_jobs/soft_time_limit_greater_than_time_limit.py} +5 -1
  499. nautobot/extras/{tests/example_jobs/test_task_queues.py → test_jobs/task_queues.py} +5 -1
  500. nautobot/extras/tests/integration/__init__.py +3 -3
  501. nautobot/extras/tests/integration/test_computedfields.py +1 -1
  502. nautobot/extras/tests/integration/test_configcontextschema.py +7 -5
  503. nautobot/extras/tests/integration/test_customfields.py +4 -2
  504. nautobot/extras/tests/integration/test_dynamicgroups.py +2 -2
  505. nautobot/extras/tests/integration/test_jobs.py +25 -27
  506. nautobot/extras/tests/integration/test_notes.py +8 -4
  507. nautobot/extras/tests/integration/test_plugins.py +4 -4
  508. nautobot/extras/tests/integration/test_relationships.py +2 -2
  509. nautobot/extras/tests/test_api.py +371 -381
  510. nautobot/extras/tests/test_changelog.py +17 -16
  511. nautobot/extras/tests/test_context_managers.py +5 -6
  512. nautobot/extras/tests/test_customfields.py +112 -73
  513. nautobot/extras/tests/test_datasources.py +191 -117
  514. nautobot/extras/tests/test_dynamicgroups.py +45 -68
  515. nautobot/extras/tests/test_filters.py +170 -130
  516. nautobot/extras/tests/test_forms.py +107 -109
  517. nautobot/extras/tests/{test_scripts.py → test_job_variables.py} +43 -49
  518. nautobot/extras/tests/test_jobs.py +271 -273
  519. nautobot/extras/tests/test_management.py +3 -6
  520. nautobot/extras/tests/test_migrations.py +5 -3
  521. nautobot/extras/tests/test_models.py +121 -173
  522. nautobot/extras/tests/test_notes.py +0 -1
  523. nautobot/extras/tests/test_plugins.py +55 -89
  524. nautobot/extras/tests/test_relationships.py +174 -130
  525. nautobot/extras/tests/test_tags.py +6 -12
  526. nautobot/extras/tests/test_utils.py +31 -1
  527. nautobot/extras/tests/test_views.py +223 -184
  528. nautobot/extras/tests/test_webhooks.py +16 -15
  529. nautobot/extras/urls.py +69 -69
  530. nautobot/extras/utils.py +137 -163
  531. nautobot/extras/views.py +81 -153
  532. nautobot/ipam/api/fields.py +17 -0
  533. nautobot/ipam/api/serializers.py +77 -164
  534. nautobot/ipam/api/urls.py +4 -1
  535. nautobot/ipam/api/views.py +28 -19
  536. nautobot/ipam/apps.py +1 -0
  537. nautobot/ipam/choices.py +5 -12
  538. nautobot/ipam/constants.py +1 -0
  539. nautobot/ipam/factory.py +41 -30
  540. nautobot/ipam/filters.py +58 -25
  541. nautobot/ipam/forms.py +82 -211
  542. nautobot/ipam/graphql/types.py +0 -9
  543. nautobot/ipam/lookups.py +13 -8
  544. nautobot/ipam/management/commands/__init__.py +0 -0
  545. nautobot/ipam/management/commands/fix_prefix_broadcast.py +17 -0
  546. nautobot/ipam/migrations/0001_initial_part_1.py +0 -1
  547. nautobot/ipam/migrations/0002_initial_part_2.py +0 -1
  548. nautobot/ipam/migrations/0003_remove_max_length.py +0 -1
  549. nautobot/ipam/migrations/0004_fixup_p2p_broadcast.py +0 -1
  550. nautobot/ipam/migrations/0005_auto_slug.py +0 -1
  551. nautobot/ipam/migrations/0006_ipaddress_nat_outside_list.py +0 -1
  552. nautobot/ipam/migrations/0007_add_natural_indexing.py +0 -1
  553. nautobot/ipam/migrations/0008_prefix_vlan_vlangroup_location.py +0 -1
  554. nautobot/ipam/migrations/0009_alter_vlan_name.py +0 -1
  555. nautobot/ipam/migrations/0010_alter_ipam_role_add_new_role.py +1 -2
  556. nautobot/ipam/migrations/0011_migrate_ipam_role_data.py +32 -39
  557. nautobot/ipam/migrations/0012_rename_ipam_roles.py +0 -1
  558. nautobot/ipam/migrations/0013_delete_role.py +0 -1
  559. nautobot/ipam/migrations/0014_rename_foreign_keys_and_related_names.py +0 -1
  560. nautobot/ipam/migrations/0015_prefix_add_type.py +0 -1
  561. nautobot/ipam/migrations/0016_prefix_type_data_migration.py +0 -3
  562. nautobot/ipam/migrations/0017_prefix_remove_is_pool.py +0 -1
  563. nautobot/ipam/migrations/0018_remove_site_foreign_key_from_ipam_models.py +0 -1
  564. nautobot/ipam/migrations/0019_created_datetime.py +0 -1
  565. nautobot/ipam/migrations/0020_related_name_changes.py +1 -2
  566. nautobot/ipam/migrations/0021_prefix_add_rir_and_date_allocated.py +0 -1
  567. nautobot/ipam/migrations/0022_aggregate_to_prefix_data_migration.py +3 -5
  568. nautobot/ipam/migrations/0023_delete_aggregate.py +0 -1
  569. nautobot/ipam/migrations/0024_interface_to_ipaddress_m2m.py +0 -1
  570. nautobot/ipam/migrations/0025_interface_ipaddress_m2m_data_migration.py +0 -1
  571. nautobot/ipam/migrations/0026_ipaddress_remove_assigned_object.py +0 -1
  572. nautobot/ipam/migrations/0027_remove_rir_slug.py +16 -0
  573. nautobot/ipam/migrations/0028_tagsfield.py +44 -0
  574. nautobot/ipam/migrations/0029_ip_address_to_interface_uniqueness_constraints.py +18 -0
  575. nautobot/ipam/migrations/0030_ipam__namespaces.py +231 -0
  576. nautobot/ipam/migrations/0031_ipam__prefix__add_parent.py +58 -0
  577. nautobot/ipam/migrations/0032_ipam__namespaces_finish.py +63 -0
  578. nautobot/ipam/migrations/0033_fixup_null_statuses.py +26 -0
  579. nautobot/ipam/migrations/0034_status_nonnullable.py +36 -0
  580. nautobot/ipam/models.py +579 -368
  581. nautobot/ipam/navigation.py +36 -159
  582. nautobot/ipam/querysets.py +117 -90
  583. nautobot/ipam/signals.py +89 -0
  584. nautobot/ipam/tables.py +86 -28
  585. nautobot/ipam/templates/ipam/ipaddress.html +14 -30
  586. nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -0
  587. nautobot/ipam/templates/ipam/namespace_ipaddresses.html +11 -0
  588. nautobot/ipam/templates/ipam/namespace_prefixes.html +11 -0
  589. nautobot/ipam/templates/ipam/namespace_retrieve.html +42 -0
  590. nautobot/ipam/templates/ipam/namespace_vrfs.html +11 -0
  591. nautobot/ipam/templates/ipam/prefix.html +27 -33
  592. nautobot/ipam/templates/ipam/prefix_edit.html +7 -1
  593. nautobot/ipam/templates/ipam/vlangroup.html +0 -13
  594. nautobot/ipam/templates/ipam/vrf.html +6 -4
  595. nautobot/ipam/templates/ipam/vrf_edit.html +20 -2
  596. nautobot/ipam/tests/integration/test_prefixes.py +4 -27
  597. nautobot/ipam/tests/test_api.py +60 -61
  598. nautobot/ipam/tests/test_filters.py +187 -126
  599. nautobot/ipam/tests/test_forms.py +12 -6
  600. nautobot/ipam/tests/test_graphql.py +8 -6
  601. nautobot/ipam/tests/test_migrations.py +8 -13
  602. nautobot/ipam/tests/test_models.py +426 -274
  603. nautobot/ipam/tests/test_ordering.py +6 -3
  604. nautobot/ipam/tests/test_querysets.py +340 -96
  605. nautobot/ipam/tests/test_views.py +100 -55
  606. nautobot/ipam/urls.py +28 -5
  607. nautobot/ipam/{utils.py → utils/__init__.py} +2 -2
  608. nautobot/ipam/utils/migrations.py +713 -0
  609. nautobot/ipam/views.py +237 -122
  610. nautobot/project-static/docs/404.html +1399 -166
  611. nautobot/project-static/docs/additional-features/caching.html +1416 -320
  612. nautobot/project-static/docs/additional-features/change-logging.html +1389 -190
  613. nautobot/project-static/docs/additional-features/config-contexts.html +1389 -190
  614. nautobot/project-static/docs/additional-features/graphql.html +1389 -190
  615. nautobot/project-static/docs/additional-features/healthcheck.html +1389 -190
  616. nautobot/project-static/docs/additional-features/job-scheduling-and-approvals.html +1393 -190
  617. nautobot/project-static/docs/additional-features/jobs.html +1677 -460
  618. nautobot/project-static/docs/additional-features/napalm.html +1389 -190
  619. nautobot/project-static/docs/additional-features/prometheus-metrics.html +1389 -190
  620. nautobot/project-static/docs/additional-features/template-filters.html +1389 -190
  621. nautobot/project-static/docs/administration/celery-queues.html +1389 -190
  622. nautobot/project-static/docs/administration/nautobot-server.html +1553 -375
  623. nautobot/project-static/docs/administration/nautobot-shell.html +1395 -196
  624. nautobot/project-static/docs/administration/permissions.html +1389 -190
  625. nautobot/project-static/docs/administration/replicating-nautobot.html +1387 -207
  626. nautobot/project-static/docs/apps/index.html +1389 -190
  627. nautobot/project-static/docs/apps/nautobot-apps.html +1387 -175
  628. nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js +29 -0
  629. nautobot/project-static/docs/assets/javascripts/bundle.51198bba.min.js.map +8 -0
  630. nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js → search.208ed371.min.js} +9 -15
  631. nautobot/project-static/docs/assets/javascripts/workers/{search.16e2a7d4.min.js.map → search.208ed371.min.js.map} +4 -4
  632. nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css +1 -0
  633. nautobot/project-static/docs/assets/stylesheets/main.ded33207.min.css.map +1 -0
  634. nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css +1 -0
  635. nautobot/project-static/docs/assets/stylesheets/palette.a0c5b2b5.min.css.map +1 -0
  636. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +1775 -590
  637. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +1389 -190
  638. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +3588 -1922
  639. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +1461 -262
  640. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +1401 -170
  641. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +1396 -191
  642. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +2095 -894
  643. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +2357 -1194
  644. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2258 -940
  645. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +1389 -190
  646. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1400 -201
  647. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +11068 -7861
  648. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +2867 -2224
  649. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +1389 -190
  650. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +2641 -1573
  651. nautobot/project-static/docs/configuration/authentication/ldap.html +1389 -190
  652. nautobot/project-static/docs/configuration/authentication/remote.html +1389 -190
  653. nautobot/project-static/docs/configuration/authentication/sso.html +1389 -190
  654. nautobot/project-static/docs/configuration/index.html +1398 -199
  655. nautobot/project-static/docs/configuration/optional-settings.html +1418 -274
  656. nautobot/project-static/docs/configuration/required-settings.html +1419 -287
  657. nautobot/project-static/docs/core-functionality/circuits.html +1446 -247
  658. nautobot/project-static/docs/core-functionality/device-types.html +1448 -249
  659. nautobot/project-static/docs/core-functionality/devices.html +1452 -249
  660. nautobot/project-static/docs/core-functionality/ipam.html +1452 -253
  661. nautobot/project-static/docs/core-functionality/power.html +1448 -249
  662. nautobot/project-static/docs/core-functionality/secrets.html +1448 -249
  663. nautobot/project-static/docs/core-functionality/services.html +1448 -249
  664. nautobot/project-static/docs/core-functionality/sites-and-racks.html +1448 -249
  665. nautobot/project-static/docs/core-functionality/tenancy.html +1448 -249
  666. nautobot/project-static/docs/core-functionality/virtualization.html +1452 -249
  667. nautobot/project-static/docs/core-functionality/vlans.html +1448 -249
  668. nautobot/project-static/docs/development/application-registry.html +1393 -214
  669. nautobot/project-static/docs/development/best-practices.html +1392 -192
  670. nautobot/project-static/docs/development/docker-compose-advanced-use-cases.html +1390 -191
  671. nautobot/project-static/docs/development/extending-models.html +1443 -257
  672. nautobot/project-static/docs/development/generic-views.html +1403 -174
  673. nautobot/project-static/docs/development/getting-started.html +1568 -262
  674. nautobot/project-static/docs/development/homepage.html +1389 -190
  675. nautobot/project-static/docs/development/index.html +1389 -190
  676. nautobot/project-static/docs/development/model-features.html +1389 -190
  677. nautobot/project-static/docs/development/natural-keys.html +1389 -190
  678. nautobot/project-static/docs/development/navigation-menu.html +1451 -330
  679. nautobot/project-static/docs/development/react-ui.html +4199 -0
  680. nautobot/project-static/docs/development/release-checklist.html +1392 -193
  681. nautobot/project-static/docs/development/role-internals.html +1402 -172
  682. nautobot/project-static/docs/development/style-guide.html +1399 -199
  683. nautobot/project-static/docs/development/templates.html +1391 -191
  684. nautobot/project-static/docs/development/testing.html +1389 -190
  685. nautobot/project-static/docs/development/user-preferences.html +1389 -190
  686. nautobot/project-static/docs/docker/index.html +1408 -206
  687. nautobot/project-static/docs/index.html +1397 -180
  688. nautobot/project-static/docs/installation/centos.html +1401 -170
  689. nautobot/project-static/docs/installation/external-authentication.html +1389 -190
  690. nautobot/project-static/docs/installation/http-server.html +1389 -190
  691. nautobot/project-static/docs/installation/index.html +1394 -191
  692. nautobot/project-static/docs/installation/migrating-from-netbox.html +1452 -305
  693. nautobot/project-static/docs/installation/migrating-from-postgresql.html +1390 -191
  694. nautobot/project-static/docs/installation/nautobot.html +1390 -191
  695. nautobot/project-static/docs/installation/region-and-site-data-migration-guide.html +1389 -190
  696. nautobot/project-static/docs/installation/selinux-troubleshooting.html +1401 -170
  697. nautobot/project-static/docs/installation/services.html +1389 -190
  698. nautobot/project-static/docs/installation/tables/v2-api-behavior-changes.yaml +70 -0
  699. nautobot/project-static/docs/installation/tables/v2-api-removed-fields.yaml +142 -0
  700. nautobot/project-static/docs/installation/tables/v2-api-renamed-fields.yaml +124 -0
  701. nautobot/project-static/docs/installation/tables/v2-code-location-changes.yaml +241 -0
  702. nautobot/project-static/docs/installation/tables/v2-code-removals.yaml +67 -0
  703. nautobot/project-static/docs/installation/tables/v2-database-behavior-changes.yaml +37 -0
  704. nautobot/project-static/docs/installation/tables/v2-database-removed-fields.yaml +166 -0
  705. nautobot/project-static/docs/installation/tables/v2-database-renamed-fields.yaml +340 -0
  706. nautobot/project-static/docs/installation/tables/v2-filters-corrected-fields.yaml +28 -0
  707. nautobot/project-static/docs/installation/tables/v2-filters-enhanced-fields.yaml +241 -0
  708. nautobot/project-static/docs/installation/tables/v2-filters-removed-fields.yaml +553 -0
  709. nautobot/project-static/docs/installation/tables/v2-filters-renamed-fields.yaml +223 -0
  710. nautobot/project-static/docs/installation/tables/v2-logging-renamed-loggers.yaml +23 -0
  711. nautobot/project-static/docs/installation/ubuntu.html +1401 -170
  712. nautobot/project-static/docs/installation/upgrading-from-nautobot-v1.html +4254 -1923
  713. nautobot/project-static/docs/installation/upgrading.html +1395 -192
  714. nautobot/project-static/docs/models/circuits/circuit.html +1427 -174
  715. nautobot/project-static/docs/models/circuits/circuittermination.html +1427 -174
  716. nautobot/project-static/docs/models/circuits/circuittype.html +1427 -174
  717. nautobot/project-static/docs/models/circuits/provider.html +1427 -174
  718. nautobot/project-static/docs/models/circuits/providernetwork.html +1427 -174
  719. nautobot/project-static/docs/models/dcim/cable.html +1458 -174
  720. nautobot/project-static/docs/models/dcim/consoleport.html +1427 -174
  721. nautobot/project-static/docs/models/dcim/consoleporttemplate.html +1427 -174
  722. nautobot/project-static/docs/models/dcim/consoleserverport.html +1427 -174
  723. nautobot/project-static/docs/models/dcim/consoleserverporttemplate.html +1427 -174
  724. nautobot/project-static/docs/models/dcim/device.html +1431 -174
  725. nautobot/project-static/docs/models/dcim/devicebay.html +1427 -174
  726. nautobot/project-static/docs/models/dcim/devicebaytemplate.html +1427 -174
  727. nautobot/project-static/docs/models/dcim/deviceredundancygroup.html +1522 -177
  728. nautobot/project-static/docs/models/dcim/devicetype.html +1427 -174
  729. nautobot/project-static/docs/models/dcim/frontport.html +1427 -174
  730. nautobot/project-static/docs/models/dcim/frontporttemplate.html +1427 -174
  731. nautobot/project-static/docs/models/dcim/interface.html +1427 -174
  732. nautobot/project-static/docs/models/dcim/interfacetemplate.html +1427 -174
  733. nautobot/project-static/docs/models/dcim/inventoryitem.html +1427 -174
  734. nautobot/project-static/docs/models/dcim/location.html +1427 -174
  735. nautobot/project-static/docs/models/dcim/locationtype.html +1427 -174
  736. nautobot/project-static/docs/models/dcim/manufacturer.html +1427 -174
  737. nautobot/project-static/docs/models/dcim/platform.html +1427 -174
  738. nautobot/project-static/docs/models/dcim/powerfeed.html +1425 -172
  739. nautobot/project-static/docs/models/dcim/poweroutlet.html +1427 -174
  740. nautobot/project-static/docs/models/dcim/poweroutlettemplate.html +1427 -174
  741. nautobot/project-static/docs/models/dcim/powerpanel.html +1425 -172
  742. nautobot/project-static/docs/models/dcim/powerport.html +1427 -174
  743. nautobot/project-static/docs/models/dcim/powerporttemplate.html +1427 -174
  744. nautobot/project-static/docs/models/dcim/rack.html +1427 -174
  745. nautobot/project-static/docs/models/dcim/rackgroup.html +1427 -174
  746. nautobot/project-static/docs/models/dcim/rackreservation.html +1427 -174
  747. nautobot/project-static/docs/models/dcim/rearport.html +1427 -174
  748. nautobot/project-static/docs/models/dcim/rearporttemplate.html +1427 -174
  749. nautobot/project-static/docs/models/dcim/region.html +1401 -170
  750. nautobot/project-static/docs/models/dcim/site.html +1401 -170
  751. nautobot/project-static/docs/models/dcim/virtualchassis.html +1425 -172
  752. nautobot/project-static/docs/models/extras/computedfield.html +1393 -194
  753. nautobot/project-static/docs/models/extras/configcontext.html +1465 -174
  754. nautobot/project-static/docs/models/extras/configcontextschema.html +1421 -168
  755. nautobot/project-static/docs/models/extras/customfield.html +1389 -190
  756. nautobot/project-static/docs/models/extras/customlink.html +1389 -190
  757. nautobot/project-static/docs/models/extras/dynamicgroup.html +1398 -199
  758. nautobot/project-static/docs/models/extras/exporttemplate.html +1389 -190
  759. nautobot/project-static/docs/models/extras/gitrepository.html +1393 -190
  760. nautobot/project-static/docs/models/extras/graphqlquery.html +1469 -171
  761. nautobot/project-static/docs/models/extras/imageattachment.html +1434 -181
  762. nautobot/project-static/docs/models/extras/job.html +1411 -157
  763. nautobot/project-static/docs/models/extras/jobbutton.html +1410 -207
  764. nautobot/project-static/docs/models/extras/jobhook.html +1397 -194
  765. nautobot/project-static/docs/models/extras/joblogentry.html +1408 -155
  766. nautobot/project-static/docs/models/extras/jobresult.html +1417 -159
  767. nautobot/project-static/docs/models/extras/note.html +1389 -190
  768. nautobot/project-static/docs/models/extras/relationship.html +1391 -192
  769. nautobot/project-static/docs/models/extras/role.html +1495 -198
  770. nautobot/project-static/docs/models/extras/secret.html +1492 -201
  771. nautobot/project-static/docs/models/extras/secretsgroup.html +1410 -157
  772. nautobot/project-static/docs/models/extras/status.html +1381 -221
  773. nautobot/project-static/docs/models/extras/tag.html +1389 -190
  774. nautobot/project-static/docs/models/extras/webhook.html +1389 -190
  775. nautobot/project-static/docs/models/ipam/ipaddress.html +1488 -200
  776. nautobot/project-static/docs/models/ipam/prefix.html +1410 -157
  777. nautobot/project-static/docs/models/ipam/rir.html +1410 -157
  778. nautobot/project-static/docs/models/ipam/routetarget.html +1410 -157
  779. nautobot/project-static/docs/models/ipam/service.html +1410 -157
  780. nautobot/project-static/docs/models/ipam/vlan.html +1410 -157
  781. nautobot/project-static/docs/models/ipam/vlangroup.html +1410 -157
  782. nautobot/project-static/docs/models/ipam/vrf.html +1410 -161
  783. nautobot/project-static/docs/models/tenancy/tenant.html +1412 -159
  784. nautobot/project-static/docs/models/tenancy/tenantgroup.html +1412 -159
  785. nautobot/project-static/docs/models/users/objectpermission.html +1462 -171
  786. nautobot/project-static/docs/models/users/token.html +1410 -157
  787. nautobot/project-static/docs/models/virtualization/cluster.html +1410 -157
  788. nautobot/project-static/docs/models/virtualization/clustergroup.html +1410 -157
  789. nautobot/project-static/docs/models/virtualization/clustertype.html +1410 -157
  790. nautobot/project-static/docs/models/virtualization/virtualmachine.html +1414 -157
  791. nautobot/project-static/docs/models/virtualization/vminterface.html +1410 -157
  792. nautobot/project-static/docs/objects.inv +0 -0
  793. nautobot/project-static/docs/plugins/development.html +1916 -646
  794. nautobot/project-static/docs/plugins/index.html +1389 -190
  795. nautobot/project-static/docs/plugins/porting-from-netbox.html +1389 -190
  796. nautobot/project-static/docs/release-notes/index.html +1389 -190
  797. nautobot/project-static/docs/release-notes/version-1.0.html +1389 -190
  798. nautobot/project-static/docs/release-notes/version-1.1.html +1389 -190
  799. nautobot/project-static/docs/release-notes/version-1.2.html +1389 -190
  800. nautobot/project-static/docs/release-notes/version-1.3.html +1389 -190
  801. nautobot/project-static/docs/release-notes/version-1.4.html +1389 -190
  802. nautobot/project-static/docs/release-notes/version-1.5.html +2016 -397
  803. nautobot/project-static/docs/release-notes/version-2.0.html +1935 -287
  804. nautobot/project-static/docs/requirements.txt +5 -4
  805. nautobot/project-static/docs/rest-api/authentication.html +1389 -190
  806. nautobot/project-static/docs/rest-api/filtering.html +1389 -190
  807. nautobot/project-static/docs/rest-api/overview.html +2002 -576
  808. nautobot/project-static/docs/rest-api/ui-related-endpoints.html +4057 -0
  809. nautobot/project-static/docs/search/search_index.json +1 -1
  810. nautobot/project-static/docs/sitemap.xml +197 -187
  811. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  812. nautobot/project-static/docs/user-guides/custom-fields.html +1390 -191
  813. nautobot/project-static/docs/user-guides/getting-started/creating-devices.html +1392 -193
  814. nautobot/project-static/docs/user-guides/getting-started/index.html +1388 -189
  815. nautobot/project-static/docs/user-guides/getting-started/interfaces.html +1388 -189
  816. nautobot/project-static/docs/user-guides/getting-started/ipam.html +1386 -187
  817. nautobot/project-static/docs/user-guides/getting-started/platforms.html +1448 -249
  818. nautobot/project-static/docs/user-guides/getting-started/regions.html +1411 -212
  819. nautobot/project-static/docs/user-guides/getting-started/search-bar.html +1395 -196
  820. nautobot/project-static/docs/user-guides/getting-started/tenants.html +1448 -249
  821. nautobot/project-static/docs/user-guides/getting-started/vlans-and-vlan-groups.html +1448 -249
  822. nautobot/project-static/docs/user-guides/git-data-source.html +1405 -206
  823. nautobot/project-static/docs/user-guides/graphql.html +1402 -203
  824. nautobot/project-static/docs/user-guides/relationships.html +1448 -249
  825. nautobot/project-static/docs/user-guides/s3-django-storage.html +1448 -249
  826. nautobot/project-static/js/forms.js +16 -9
  827. nautobot/project-static/js/theme.js +5 -0
  828. nautobot/tenancy/api/serializers.py +4 -34
  829. nautobot/tenancy/api/urls.py +1 -1
  830. nautobot/tenancy/filters/__init__.py +9 -7
  831. nautobot/tenancy/filters/mixins.py +3 -2
  832. nautobot/tenancy/forms.py +3 -36
  833. nautobot/tenancy/migrations/0001_initial.py +0 -1
  834. nautobot/tenancy/migrations/0002_auto_slug.py +0 -1
  835. nautobot/tenancy/migrations/0003_mptt_to_tree_queries.py +0 -1
  836. nautobot/tenancy/migrations/0004_change_tree_manager_on_tree_models.py +0 -1
  837. nautobot/tenancy/migrations/0005_rename_foreign_keys_and_related_names.py +0 -1
  838. nautobot/tenancy/migrations/0006_created_datetime.py +0 -1
  839. nautobot/tenancy/migrations/0007_remove_tenant_tenantgroup_slug.py +20 -0
  840. nautobot/tenancy/migrations/0008_tagsfield.py +19 -0
  841. nautobot/tenancy/models.py +0 -30
  842. nautobot/tenancy/navigation.py +6 -39
  843. nautobot/tenancy/tables.py +4 -4
  844. nautobot/tenancy/templates/tenancy/tenant.html +12 -12
  845. nautobot/tenancy/templates/tenancy/tenant_edit.html +0 -1
  846. nautobot/tenancy/templates/tenancy/tenantgroup.html +1 -1
  847. nautobot/tenancy/tests/test_api.py +1 -12
  848. nautobot/tenancy/tests/test_filters.py +20 -12
  849. nautobot/tenancy/tests/test_views.py +11 -29
  850. nautobot/tenancy/urls.py +10 -10
  851. nautobot/tenancy/views.py +0 -3
  852. nautobot/ui/.eslintignore +6 -0
  853. nautobot/ui/.gitignore +10 -0
  854. nautobot/ui/.prettierignore +9 -0
  855. nautobot/ui/.prettierrc +4 -0
  856. nautobot/ui/README.md +33 -0
  857. nautobot/ui/app_imports.js.j2 +7 -0
  858. nautobot/ui/craco.config.js +46 -0
  859. nautobot/ui/jsconfig-base.json +11 -0
  860. nautobot/ui/jsconfig.json +5 -0
  861. nautobot/ui/lib/nautobot-craco-alias-plugin.js +40 -0
  862. nautobot/ui/package-lock.json +21451 -0
  863. nautobot/ui/package.json +70 -0
  864. nautobot/ui/public/index.html +47 -0
  865. nautobot/ui/public/logo192.png +0 -0
  866. nautobot/ui/public/logo512.png +0 -0
  867. nautobot/ui/public/manifest.json +25 -0
  868. nautobot/ui/public/nautobot_logo.svg +131 -0
  869. nautobot/ui/public/robots.txt +3 -0
  870. nautobot/ui/src/App.js +71 -0
  871. nautobot/ui/src/components/AppFullWidthComponents.js +8 -0
  872. nautobot/ui/src/components/AppTab.js +40 -0
  873. nautobot/ui/src/components/Apps.js +60 -0
  874. nautobot/ui/src/components/HomeChangelogPanel.js +98 -0
  875. nautobot/ui/src/components/HomePanel.js +58 -0
  876. nautobot/ui/src/components/JobHistoryTable.js +78 -0
  877. nautobot/ui/src/components/Layout.js +53 -0
  878. nautobot/ui/src/components/LoadingWidget.js +25 -0
  879. nautobot/ui/src/components/Navbar.js +116 -0
  880. nautobot/ui/src/components/NotificationPopover.js +27 -0
  881. nautobot/ui/src/components/ObjectListTable.js +209 -0
  882. nautobot/ui/src/components/ReferenceDataTag.js +35 -0
  883. nautobot/ui/src/components/RouterButton.js +10 -0
  884. nautobot/ui/src/components/RouterLink.js +10 -0
  885. nautobot/ui/src/components/SidebarNav.js +147 -0
  886. nautobot/ui/src/components/Table.js +48 -0
  887. nautobot/ui/src/components/TableItem.js +71 -0
  888. nautobot/ui/src/components/__tests__/AppFullWidthComponents.test.js +16 -0
  889. nautobot/ui/src/components/__tests__/AppTab.test.js +21 -0
  890. nautobot/ui/src/components/__tests__/Apps.test.js +14 -0
  891. nautobot/ui/src/components/__tests__/Layout.test.js +33 -0
  892. nautobot/ui/src/components/__tests__/Table.test.js +36 -0
  893. nautobot/ui/src/components/__tests__/TableItem.test.js +37 -0
  894. nautobot/ui/src/components/__tests__/paginator.test.js +43 -0
  895. nautobot/ui/src/components/__tests__/paginator_form.test.js +13 -0
  896. nautobot/ui/src/components/pagination.js +93 -0
  897. nautobot/ui/src/components/paginator.js +79 -0
  898. nautobot/ui/src/components/paginator_form.js +43 -0
  899. nautobot/ui/src/components/usePagination.js +57 -0
  900. nautobot/ui/src/constants/apiPath.js +10 -0
  901. nautobot/ui/src/constants/icons.js +15 -0
  902. nautobot/ui/src/constants/size.js +15 -0
  903. nautobot/ui/src/index.js +65 -0
  904. nautobot/ui/src/reportWebVitals.js +15 -0
  905. nautobot/ui/src/router.js +77 -0
  906. nautobot/ui/src/utils/api.js +131 -0
  907. nautobot/ui/src/utils/app-import.js +15 -0
  908. nautobot/ui/src/utils/color.js +15 -0
  909. nautobot/ui/src/utils/date.js +14 -0
  910. nautobot/ui/src/utils/index.js +15 -0
  911. nautobot/ui/src/utils/navigation.js +32 -0
  912. nautobot/ui/src/utils/session.js +64 -0
  913. nautobot/ui/src/utils/store.js +242 -0
  914. nautobot/ui/src/utils/string.js +6 -0
  915. nautobot/ui/src/utils/url.js +4 -0
  916. nautobot/ui/src/views/Home.js +138 -0
  917. nautobot/ui/src/views/InstalledApps.js +80 -0
  918. nautobot/ui/src/views/Login.js +48 -0
  919. nautobot/ui/src/views/Logout.js +20 -0
  920. nautobot/ui/src/views/__tests__/BSCreateViewTemplate.test.js +11 -0
  921. nautobot/ui/src/views/__tests__/BSListViewTemplate.test.js +107 -0
  922. nautobot/ui/src/views/__tests__/Login.test.js +15 -0
  923. nautobot/ui/src/views/generic/GenericView.js +142 -0
  924. nautobot/ui/src/views/generic/ObjectCreate.js +96 -0
  925. nautobot/ui/src/views/generic/ObjectList.js +127 -0
  926. nautobot/ui/src/views/generic/ObjectRetrieve.js +551 -0
  927. nautobot/users/admin.py +1 -1
  928. nautobot/users/api/serializers.py +51 -61
  929. nautobot/users/api/urls.py +1 -1
  930. nautobot/users/api/views.py +53 -2
  931. nautobot/users/migrations/0001_initial.py +0 -1
  932. nautobot/users/migrations/0002_token_ordering_by_created.py +0 -1
  933. nautobot/users/migrations/0003_alter_user_options.py +0 -1
  934. nautobot/users/migrations/0004_alter_user_managers.py +0 -1
  935. nautobot/users/tests/test_api.py +109 -28
  936. nautobot/users/tests/test_filters.py +0 -4
  937. nautobot/users/tests/test_models.py +0 -1
  938. nautobot/users/views.py +0 -7
  939. nautobot/virtualization/api/serializers.py +18 -132
  940. nautobot/virtualization/api/urls.py +1 -1
  941. nautobot/virtualization/api/views.py +1 -22
  942. nautobot/virtualization/choices.py +0 -2
  943. nautobot/virtualization/filters.py +12 -7
  944. nautobot/virtualization/forms.py +21 -117
  945. nautobot/virtualization/migrations/0001_initial.py +0 -1
  946. nautobot/virtualization/migrations/0002_virtualmachine_local_context_schema.py +0 -1
  947. nautobot/virtualization/migrations/0003_vminterface_verbose_name.py +0 -1
  948. nautobot/virtualization/migrations/0004_auto_slug.py +0 -1
  949. nautobot/virtualization/migrations/0005_add_natural_indexing.py +0 -1
  950. nautobot/virtualization/migrations/0006_vminterface_status.py +0 -1
  951. nautobot/virtualization/migrations/0007_vminterface_status_data_migration.py +0 -1
  952. nautobot/virtualization/migrations/0008_vminterface_parent.py +0 -1
  953. nautobot/virtualization/migrations/0009_cluster_location.py +0 -1
  954. nautobot/virtualization/migrations/0010_vminterface_mac_address_data_migration.py +0 -1
  955. nautobot/virtualization/migrations/0011_alter_vminterface_mac_address.py +0 -1
  956. nautobot/virtualization/migrations/0012_alter_virtualmachine_role_add_new_role.py +1 -2
  957. nautobot/virtualization/migrations/0013_migrate_virtualmachine_role_data.py +18 -12
  958. nautobot/virtualization/migrations/0014_rename_virtualmachine_roles.py +0 -1
  959. nautobot/virtualization/migrations/0015_rename_foreignkey_fields.py +1 -2
  960. nautobot/virtualization/migrations/0016_remove_site_foreign_key_from_cluster_class.py +0 -1
  961. nautobot/virtualization/migrations/0017_created_datetime.py +0 -1
  962. nautobot/virtualization/migrations/0018_related_name_changes.py +1 -2
  963. nautobot/virtualization/migrations/0019_vminterface_ip_addresses_m2m.py +0 -1
  964. nautobot/virtualization/migrations/0020_remove_clustergroup_clustertype_slug.py +20 -0
  965. nautobot/virtualization/migrations/0021_tagsfield_and_vminterface_to_primarymodel.py +39 -0
  966. nautobot/virtualization/migrations/0022_vminterface_timestamps_data_migration.py +17 -0
  967. nautobot/virtualization/migrations/0023_ipam__namespaces.py +25 -0
  968. nautobot/virtualization/migrations/0024_fixup_null_statuses.py +25 -0
  969. nautobot/virtualization/migrations/0025_status_nonnullable.py +29 -0
  970. nautobot/virtualization/models.py +39 -131
  971. nautobot/virtualization/navigation.py +18 -99
  972. nautobot/virtualization/tables.py +4 -4
  973. nautobot/virtualization/templates/virtualization/virtualmachine.html +13 -2
  974. nautobot/virtualization/templates/virtualization/virtualmachine_edit.html +6 -0
  975. nautobot/virtualization/tests/test_api.py +42 -52
  976. nautobot/virtualization/tests/test_filters.py +98 -75
  977. nautobot/virtualization/tests/test_models.py +36 -13
  978. nautobot/virtualization/tests/test_views.py +68 -73
  979. nautobot/virtualization/urls.py +10 -10
  980. nautobot/virtualization/views.py +8 -14
  981. {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/METADATA +15 -22
  982. {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/RECORD +987 -834
  983. {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/WHEEL +1 -1
  984. nautobot/circuits/api/nested_serializers.py +0 -69
  985. nautobot/core/templates/plugin_template/navigation.py-tpl +0 -22
  986. nautobot/dcim/api/nested_serializers.py +0 -356
  987. nautobot/dcim/templates/dcim/device_import.html +0 -5
  988. nautobot/dcim/templates/dcim/device_import_child.html +0 -5
  989. nautobot/dcim/templates/dcim/inc/device_import_header.html +0 -4
  990. nautobot/extras/api/nested_serializers.py +0 -353
  991. nautobot/extras/migrations/0064_configcontext_data_migrations.py +0 -42
  992. nautobot/extras/migrations/0071_job__unique_name_data_migration.py +0 -47
  993. nautobot/extras/reports.py +0 -60
  994. nautobot/extras/scripts.py +0 -72
  995. nautobot/extras/tests/example_jobs/script_variables.py +0 -67
  996. nautobot/extras/tests/example_jobs/test_duplicate_name2.py +0 -5
  997. nautobot/extras/tests/example_jobs/test_fail.py +0 -16
  998. nautobot/extras/tests/example_jobs/test_file_upload_pass.py +0 -20
  999. nautobot/extras/tests/example_jobs/test_ipaddress_vars.py +0 -52
  1000. nautobot/extras/tests/example_jobs/test_job_button_receiver.py +0 -21
  1001. nautobot/extras/tests/example_jobs/test_job_hook_receiver.py +0 -20
  1002. nautobot/extras/tests/example_jobs/test_location_with_custom_field.py +0 -35
  1003. nautobot/extras/tests/example_jobs/test_log_redaction.py +0 -14
  1004. nautobot/extras/tests/example_jobs/test_modify_db.py +0 -19
  1005. nautobot/extras/tests/example_jobs/test_object_var_optional.py +0 -14
  1006. nautobot/extras/tests/example_jobs/test_object_var_required.py +0 -14
  1007. nautobot/extras/tests/example_jobs/test_object_vars.py +0 -29
  1008. nautobot/extras/tests/example_jobs/test_pass.py +0 -19
  1009. nautobot/extras/tests/example_jobs/test_read_only_fail.py +0 -24
  1010. nautobot/extras/tests/example_jobs/test_read_only_no_commit_field.py +0 -10
  1011. nautobot/extras/tests/example_jobs/test_read_only_pass.py +0 -22
  1012. nautobot/ipam/api/nested_serializers.py +0 -143
  1013. nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js +0 -29
  1014. nautobot/project-static/docs/assets/javascripts/bundle.5a2dcb6a.min.js.map +0 -8
  1015. nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js +0 -18
  1016. nautobot/project-static/docs/assets/javascripts/extra/bundle.5f09fbc3.min.js.map +0 -8
  1017. nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css +0 -1
  1018. nautobot/project-static/docs/assets/stylesheets/extra.0d2c79a8.min.css.map +0 -1
  1019. nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css +0 -1
  1020. nautobot/project-static/docs/assets/stylesheets/main.975780f9.min.css.map +0 -1
  1021. nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css +0 -1
  1022. nautobot/project-static/docs/assets/stylesheets/palette.2505c338.min.css.map +0 -1
  1023. nautobot/tenancy/api/nested_serializers.py +0 -31
  1024. nautobot/users/api/nested_serializers.py +0 -67
  1025. nautobot/virtualization/api/nested_serializers.py +0 -65
  1026. /nautobot/extras/{tests/example_jobs → test_jobs}/__init__.py +0 -0
  1027. /nautobot/{dcim/models/sites.py → ipam/management/__init__.py} +0 -0
  1028. {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/LICENSE.txt +0 -0
  1029. {nautobot-2.0.0a2.dist-info → nautobot-2.0.0b1.dist-info}/entry_points.txt +0 -0
@@ -10,8 +10,14 @@
10
10
 
11
11
  <link rel="canonical" href="https://docs.nautobot.com/projects/core/en/stable/additional-features/jobs.html">
12
12
 
13
+
14
+ <link rel="prev" href="healthcheck.html">
15
+
16
+
17
+ <link rel="next" href="../models/extras/jobbutton.html">
18
+
13
19
  <link rel="icon" href="../assets/favicon.ico">
14
- <meta name="generator" content="mkdocs-1.4.2, mkdocs-material-8.5.10">
20
+ <meta name="generator" content="mkdocs-1.4.2, mkdocs-material-9.1.6">
15
21
 
16
22
 
17
23
 
@@ -19,11 +25,10 @@
19
25
 
20
26
 
21
27
 
22
- <link rel="stylesheet" href="../assets/stylesheets/main.975780f9.min.css">
28
+ <link rel="stylesheet" href="../assets/stylesheets/main.ded33207.min.css">
23
29
 
24
30
 
25
- <link rel="stylesheet" href="../assets/stylesheets/palette.2505c338.min.css">
26
-
31
+ <link rel="stylesheet" href="../assets/stylesheets/palette.a0c5b2b5.min.css">
27
32
 
28
33
 
29
34
 
@@ -86,7 +91,7 @@
86
91
 
87
92
 
88
93
 
89
- <header class="md-header md-header--lifted" data-md-component="header">
94
+ <header class="md-header md-header--shadow md-header--lifted" data-md-component="header">
90
95
  <nav class="md-header__inner md-grid" aria-label="Header">
91
96
  <a href="../index.html" title="Nautobot Documentation" class="md-header__button md-logo" aria-label="Nautobot Documentation" data-md-component="logo">
92
97
 
@@ -116,8 +121,6 @@
116
121
  <form class="md-header__option" data-md-component="palette">
117
122
 
118
123
 
119
-
120
-
121
124
  <input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
122
125
 
123
126
  <label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
@@ -126,8 +129,6 @@
126
129
 
127
130
 
128
131
 
129
-
130
-
131
132
  <input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_2">
132
133
 
133
134
  <label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
@@ -171,7 +172,7 @@
171
172
  <div class="md-search-result__meta">
172
173
  Initializing search
173
174
  </div>
174
- <ol class="md-search-result__list"></ol>
175
+ <ol class="md-search-result__list" role="presentation"></ol>
175
176
  </div>
176
177
  </div>
177
178
  </div>
@@ -183,7 +184,7 @@
183
184
  <a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
184
185
  <div class="md-source__icon md-icon">
185
186
 
186
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
187
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
187
188
  </div>
188
189
  <div class="md-source__repository">
189
190
  GitHub
@@ -196,7 +197,7 @@
196
197
 
197
198
 
198
199
  <nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
199
- <div class="md-tabs__inner md-grid">
200
+ <div class="md-grid">
200
201
  <ul class="md-tabs__list">
201
202
 
202
203
 
@@ -351,7 +352,7 @@
351
352
  <a href="https://github.com/nautobot/nautobot" title="Go to repository" class="md-source" data-md-component="source">
352
353
  <div class="md-source__icon md-icon">
353
354
 
354
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
355
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81z"/></svg>
355
356
  </div>
356
357
  <div class="md-source__repository">
357
358
  GitHub
@@ -389,17 +390,18 @@
389
390
  <li class="md-nav__item md-nav__item--active md-nav__item--nested">
390
391
 
391
392
 
392
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2" type="checkbox" id="__nav_2" checked>
393
393
 
394
394
 
395
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" checked>
396
+
395
397
 
396
398
 
397
- <label class="md-nav__link" for="__nav_2">
399
+ <label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
398
400
  Documentation
399
401
  <span class="md-nav__icon md-icon"></span>
400
402
  </label>
401
403
 
402
- <nav class="md-nav" aria-label="Documentation" data-md-level="1">
404
+ <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="true">
403
405
  <label class="md-nav__title" for="__nav_2">
404
406
  <span class="md-nav__icon md-icon"></span>
405
407
  Documentation
@@ -415,17 +417,18 @@
415
417
  <li class="md-nav__item md-nav__item--nested">
416
418
 
417
419
 
418
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_1" type="checkbox" id="__nav_2_1" >
419
420
 
420
421
 
422
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_1" >
421
423
 
422
424
 
423
- <label class="md-nav__link" for="__nav_2_1">
425
+
426
+ <label class="md-nav__link" for="__nav_2_1" id="__nav_2_1_label" tabindex="0">
424
427
  Installation
425
428
  <span class="md-nav__icon md-icon"></span>
426
429
  </label>
427
430
 
428
- <nav class="md-nav" aria-label="Installation" data-md-level="2">
431
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_1_label" aria-expanded="false">
429
432
  <label class="md-nav__title" for="__nav_2_1">
430
433
  <span class="md-nav__icon md-icon"></span>
431
434
  Installation
@@ -532,17 +535,18 @@
532
535
  <li class="md-nav__item md-nav__item--nested">
533
536
 
534
537
 
535
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_2" type="checkbox" id="__nav_2_2" >
536
538
 
537
539
 
540
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_2" >
541
+
538
542
 
539
543
 
540
- <label class="md-nav__link" for="__nav_2_2">
544
+ <label class="md-nav__link" for="__nav_2_2" id="__nav_2_2_label" tabindex="0">
541
545
  Migration
542
546
  <span class="md-nav__icon md-icon"></span>
543
547
  </label>
544
548
 
545
- <nav class="md-nav" aria-label="Migration" data-md-level="2">
549
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_2_label" aria-expanded="false">
546
550
  <label class="md-nav__title" for="__nav_2_2">
547
551
  <span class="md-nav__icon md-icon"></span>
548
552
  Migration
@@ -635,17 +639,18 @@
635
639
  <li class="md-nav__item md-nav__item--nested">
636
640
 
637
641
 
638
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_3" type="checkbox" id="__nav_2_3" >
639
642
 
640
643
 
644
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_3" >
641
645
 
642
646
 
643
- <label class="md-nav__link" for="__nav_2_3">
647
+
648
+ <label class="md-nav__link" for="__nav_2_3" id="__nav_2_3_label" tabindex="0">
644
649
  Configuration
645
650
  <span class="md-nav__icon md-icon"></span>
646
651
  </label>
647
652
 
648
- <nav class="md-nav" aria-label="Configuration" data-md-level="2">
653
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_3_label" aria-expanded="false">
649
654
  <label class="md-nav__title" for="__nav_2_3">
650
655
  <span class="md-nav__icon md-icon"></span>
651
656
  Configuration
@@ -710,17 +715,18 @@
710
715
  <li class="md-nav__item md-nav__item--nested">
711
716
 
712
717
 
713
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_4" type="checkbox" id="__nav_2_4" >
714
718
 
715
719
 
720
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_4" >
721
+
716
722
 
717
723
 
718
- <label class="md-nav__link" for="__nav_2_4">
724
+ <label class="md-nav__link" for="__nav_2_4" id="__nav_2_4_label" tabindex="0">
719
725
  External Authentication
720
726
  <span class="md-nav__icon md-icon"></span>
721
727
  </label>
722
728
 
723
- <nav class="md-nav" aria-label="External Authentication" data-md-level="2">
729
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_4_label" aria-expanded="false">
724
730
  <label class="md-nav__title" for="__nav_2_4">
725
731
  <span class="md-nav__icon md-icon"></span>
726
732
  External Authentication
@@ -785,17 +791,18 @@
785
791
  <li class="md-nav__item md-nav__item--nested">
786
792
 
787
793
 
788
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_5" type="checkbox" id="__nav_2_5" >
789
794
 
790
795
 
796
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_5" >
791
797
 
792
798
 
793
- <label class="md-nav__link" for="__nav_2_5">
799
+
800
+ <label class="md-nav__link" for="__nav_2_5" id="__nav_2_5_label" tabindex="0">
794
801
  Administration
795
802
  <span class="md-nav__icon md-icon"></span>
796
803
  </label>
797
804
 
798
- <nav class="md-nav" aria-label="Administration" data-md-level="2">
805
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_5_label" aria-expanded="false">
799
806
  <label class="md-nav__title" for="__nav_2_5">
800
807
  <span class="md-nav__icon md-icon"></span>
801
808
  Administration
@@ -888,17 +895,18 @@
888
895
  <li class="md-nav__item md-nav__item--nested">
889
896
 
890
897
 
891
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_6" type="checkbox" id="__nav_2_6" >
892
898
 
893
899
 
900
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_6" >
901
+
894
902
 
895
903
 
896
- <label class="md-nav__link" for="__nav_2_6">
904
+ <label class="md-nav__link" for="__nav_2_6" id="__nav_2_6_label" tabindex="0">
897
905
  User Guides
898
906
  <span class="md-nav__icon md-icon"></span>
899
907
  </label>
900
908
 
901
- <nav class="md-nav" aria-label="User Guides" data-md-level="2">
909
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_6_label" aria-expanded="false">
902
910
  <label class="md-nav__title" for="__nav_2_6">
903
911
  <span class="md-nav__icon md-icon"></span>
904
912
  User Guides
@@ -1145,17 +1153,18 @@
1145
1153
  <li class="md-nav__item md-nav__item--nested">
1146
1154
 
1147
1155
 
1148
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_7" type="checkbox" id="__nav_2_7" >
1149
1156
 
1150
1157
 
1158
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_7" >
1151
1159
 
1152
1160
 
1153
- <label class="md-nav__link" for="__nav_2_7">
1161
+
1162
+ <label class="md-nav__link" for="__nav_2_7" id="__nav_2_7_label" tabindex="0">
1154
1163
  Core Functionality
1155
1164
  <span class="md-nav__icon md-icon"></span>
1156
1165
  </label>
1157
1166
 
1158
- <nav class="md-nav" aria-label="Core Functionality" data-md-level="2">
1167
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_7_label" aria-expanded="false">
1159
1168
  <label class="md-nav__title" for="__nav_2_7">
1160
1169
  <span class="md-nav__icon md-icon"></span>
1161
1170
  Core Functionality
@@ -1210,8 +1219,1135 @@
1210
1219
 
1211
1220
 
1212
1221
  <li class="md-nav__item">
1213
- <a href="../core-functionality/ipam.html" class="md-nav__link">
1214
- IP Address Management
1222
+ <a href="../core-functionality/ipam.html" class="md-nav__link">
1223
+ IP Address Management
1224
+ </a>
1225
+ </li>
1226
+
1227
+
1228
+
1229
+
1230
+
1231
+
1232
+
1233
+
1234
+
1235
+ <li class="md-nav__item">
1236
+ <a href="../core-functionality/power.html" class="md-nav__link">
1237
+ Power Tracking
1238
+ </a>
1239
+ </li>
1240
+
1241
+
1242
+
1243
+
1244
+
1245
+
1246
+
1247
+
1248
+
1249
+ <li class="md-nav__item">
1250
+ <a href="../core-functionality/secrets.html" class="md-nav__link">
1251
+ Secrets
1252
+ </a>
1253
+ </li>
1254
+
1255
+
1256
+
1257
+
1258
+
1259
+
1260
+
1261
+
1262
+
1263
+ <li class="md-nav__item">
1264
+ <a href="../core-functionality/services.html" class="md-nav__link">
1265
+ Service Mapping
1266
+ </a>
1267
+ </li>
1268
+
1269
+
1270
+
1271
+
1272
+
1273
+
1274
+
1275
+
1276
+
1277
+ <li class="md-nav__item">
1278
+ <a href="../core-functionality/sites-and-racks.html" class="md-nav__link">
1279
+ Sites, Locations, and Racks
1280
+ </a>
1281
+ </li>
1282
+
1283
+
1284
+
1285
+
1286
+
1287
+
1288
+
1289
+
1290
+
1291
+ <li class="md-nav__item">
1292
+ <a href="../core-functionality/tenancy.html" class="md-nav__link">
1293
+ Tenancy
1294
+ </a>
1295
+ </li>
1296
+
1297
+
1298
+
1299
+
1300
+
1301
+
1302
+
1303
+
1304
+
1305
+ <li class="md-nav__item">
1306
+ <a href="../core-functionality/virtualization.html" class="md-nav__link">
1307
+ Virtualization
1308
+ </a>
1309
+ </li>
1310
+
1311
+
1312
+
1313
+
1314
+
1315
+
1316
+
1317
+
1318
+
1319
+ <li class="md-nav__item">
1320
+ <a href="../core-functionality/vlans.html" class="md-nav__link">
1321
+ VLAN Management
1322
+ </a>
1323
+ </li>
1324
+
1325
+
1326
+
1327
+
1328
+ </ul>
1329
+ </nav>
1330
+ </li>
1331
+
1332
+
1333
+
1334
+
1335
+
1336
+
1337
+
1338
+
1339
+
1340
+
1341
+ <li class="md-nav__item md-nav__item--nested">
1342
+
1343
+
1344
+
1345
+
1346
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8" >
1347
+
1348
+
1349
+
1350
+ <label class="md-nav__link" for="__nav_2_8" id="__nav_2_8_label" tabindex="0">
1351
+ Model Details
1352
+ <span class="md-nav__icon md-icon"></span>
1353
+ </label>
1354
+
1355
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_8_label" aria-expanded="false">
1356
+ <label class="md-nav__title" for="__nav_2_8">
1357
+ <span class="md-nav__icon md-icon"></span>
1358
+ Model Details
1359
+ </label>
1360
+ <ul class="md-nav__list" data-md-scrollfix>
1361
+
1362
+
1363
+
1364
+
1365
+
1366
+
1367
+
1368
+ <li class="md-nav__item md-nav__item--nested">
1369
+
1370
+
1371
+
1372
+
1373
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_1" >
1374
+
1375
+
1376
+
1377
+ <label class="md-nav__link" for="__nav_2_8_1" id="__nav_2_8_1_label" tabindex="0">
1378
+ Circuits
1379
+ <span class="md-nav__icon md-icon"></span>
1380
+ </label>
1381
+
1382
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_1_label" aria-expanded="false">
1383
+ <label class="md-nav__title" for="__nav_2_8_1">
1384
+ <span class="md-nav__icon md-icon"></span>
1385
+ Circuits
1386
+ </label>
1387
+ <ul class="md-nav__list" data-md-scrollfix>
1388
+
1389
+
1390
+
1391
+
1392
+
1393
+
1394
+ <li class="md-nav__item">
1395
+ <a href="../models/circuits/circuit.html" class="md-nav__link">
1396
+ Circuit
1397
+ </a>
1398
+ </li>
1399
+
1400
+
1401
+
1402
+
1403
+
1404
+
1405
+
1406
+
1407
+
1408
+ <li class="md-nav__item">
1409
+ <a href="../models/circuits/circuittermination.html" class="md-nav__link">
1410
+ Circuit Termination
1411
+ </a>
1412
+ </li>
1413
+
1414
+
1415
+
1416
+
1417
+
1418
+
1419
+
1420
+
1421
+
1422
+ <li class="md-nav__item">
1423
+ <a href="../models/circuits/circuittype.html" class="md-nav__link">
1424
+ Circuit Type
1425
+ </a>
1426
+ </li>
1427
+
1428
+
1429
+
1430
+
1431
+
1432
+
1433
+
1434
+
1435
+
1436
+ <li class="md-nav__item">
1437
+ <a href="../models/circuits/provider.html" class="md-nav__link">
1438
+ Circuit Provider
1439
+ </a>
1440
+ </li>
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+ <li class="md-nav__item">
1451
+ <a href="../models/circuits/providernetwork.html" class="md-nav__link">
1452
+ Circuit Provider Network
1453
+ </a>
1454
+ </li>
1455
+
1456
+
1457
+
1458
+
1459
+ </ul>
1460
+ </nav>
1461
+ </li>
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+
1471
+
1472
+ <li class="md-nav__item md-nav__item--nested">
1473
+
1474
+
1475
+
1476
+
1477
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_2" >
1478
+
1479
+
1480
+
1481
+ <label class="md-nav__link" for="__nav_2_8_2" id="__nav_2_8_2_label" tabindex="0">
1482
+ DCIM
1483
+ <span class="md-nav__icon md-icon"></span>
1484
+ </label>
1485
+
1486
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_2_label" aria-expanded="false">
1487
+ <label class="md-nav__title" for="__nav_2_8_2">
1488
+ <span class="md-nav__icon md-icon"></span>
1489
+ DCIM
1490
+ </label>
1491
+ <ul class="md-nav__list" data-md-scrollfix>
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+ <li class="md-nav__item">
1499
+ <a href="../models/dcim/cable.html" class="md-nav__link">
1500
+ Cable
1501
+ </a>
1502
+ </li>
1503
+
1504
+
1505
+
1506
+
1507
+
1508
+
1509
+
1510
+
1511
+
1512
+ <li class="md-nav__item">
1513
+ <a href="../models/dcim/consoleport.html" class="md-nav__link">
1514
+ Console Port
1515
+ </a>
1516
+ </li>
1517
+
1518
+
1519
+
1520
+
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+ <li class="md-nav__item">
1527
+ <a href="../models/dcim/consoleporttemplate.html" class="md-nav__link">
1528
+ Console Port Template
1529
+ </a>
1530
+ </li>
1531
+
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1539
+
1540
+ <li class="md-nav__item">
1541
+ <a href="../models/dcim/consoleserverport.html" class="md-nav__link">
1542
+ Console Server Port
1543
+ </a>
1544
+ </li>
1545
+
1546
+
1547
+
1548
+
1549
+
1550
+
1551
+
1552
+
1553
+
1554
+ <li class="md-nav__item">
1555
+ <a href="../models/dcim/consoleserverporttemplate.html" class="md-nav__link">
1556
+ Console Server Port Template
1557
+ </a>
1558
+ </li>
1559
+
1560
+
1561
+
1562
+
1563
+
1564
+
1565
+
1566
+
1567
+
1568
+ <li class="md-nav__item">
1569
+ <a href="../models/dcim/device.html" class="md-nav__link">
1570
+ Device
1571
+ </a>
1572
+ </li>
1573
+
1574
+
1575
+
1576
+
1577
+
1578
+
1579
+
1580
+
1581
+
1582
+ <li class="md-nav__item">
1583
+ <a href="../models/dcim/devicebay.html" class="md-nav__link">
1584
+ Device Bay
1585
+ </a>
1586
+ </li>
1587
+
1588
+
1589
+
1590
+
1591
+
1592
+
1593
+
1594
+
1595
+
1596
+ <li class="md-nav__item">
1597
+ <a href="../models/dcim/devicebaytemplate.html" class="md-nav__link">
1598
+ Device Bay Template
1599
+ </a>
1600
+ </li>
1601
+
1602
+
1603
+
1604
+
1605
+
1606
+
1607
+
1608
+
1609
+
1610
+ <li class="md-nav__item">
1611
+ <a href="../models/dcim/deviceredundancygroup.html" class="md-nav__link">
1612
+ Device Redundancy Group
1613
+ </a>
1614
+ </li>
1615
+
1616
+
1617
+
1618
+
1619
+
1620
+
1621
+
1622
+
1623
+
1624
+ <li class="md-nav__item">
1625
+ <a href="../models/dcim/devicetype.html" class="md-nav__link">
1626
+ Device Type
1627
+ </a>
1628
+ </li>
1629
+
1630
+
1631
+
1632
+
1633
+
1634
+
1635
+
1636
+
1637
+
1638
+ <li class="md-nav__item">
1639
+ <a href="../models/dcim/frontport.html" class="md-nav__link">
1640
+ Front Port
1641
+ </a>
1642
+ </li>
1643
+
1644
+
1645
+
1646
+
1647
+
1648
+
1649
+
1650
+
1651
+
1652
+ <li class="md-nav__item">
1653
+ <a href="../models/dcim/frontporttemplate.html" class="md-nav__link">
1654
+ Front Port Template
1655
+ </a>
1656
+ </li>
1657
+
1658
+
1659
+
1660
+
1661
+
1662
+
1663
+
1664
+
1665
+
1666
+ <li class="md-nav__item">
1667
+ <a href="../models/dcim/interface.html" class="md-nav__link">
1668
+ Interface
1669
+ </a>
1670
+ </li>
1671
+
1672
+
1673
+
1674
+
1675
+
1676
+
1677
+
1678
+
1679
+
1680
+ <li class="md-nav__item">
1681
+ <a href="../models/dcim/interfacetemplate.html" class="md-nav__link">
1682
+ Interface Template
1683
+ </a>
1684
+ </li>
1685
+
1686
+
1687
+
1688
+
1689
+
1690
+
1691
+
1692
+
1693
+
1694
+ <li class="md-nav__item">
1695
+ <a href="../models/dcim/inventoryitem.html" class="md-nav__link">
1696
+ Inventory Item
1697
+ </a>
1698
+ </li>
1699
+
1700
+
1701
+
1702
+
1703
+
1704
+
1705
+
1706
+
1707
+
1708
+ <li class="md-nav__item">
1709
+ <a href="../models/dcim/location.html" class="md-nav__link">
1710
+ Location
1711
+ </a>
1712
+ </li>
1713
+
1714
+
1715
+
1716
+
1717
+
1718
+
1719
+
1720
+
1721
+
1722
+ <li class="md-nav__item">
1723
+ <a href="../models/dcim/locationtype.html" class="md-nav__link">
1724
+ Location Type
1725
+ </a>
1726
+ </li>
1727
+
1728
+
1729
+
1730
+
1731
+
1732
+
1733
+
1734
+
1735
+
1736
+ <li class="md-nav__item">
1737
+ <a href="../models/dcim/manufacturer.html" class="md-nav__link">
1738
+ Manufacturer
1739
+ </a>
1740
+ </li>
1741
+
1742
+
1743
+
1744
+
1745
+
1746
+
1747
+
1748
+
1749
+
1750
+ <li class="md-nav__item">
1751
+ <a href="../models/dcim/platform.html" class="md-nav__link">
1752
+ Platform
1753
+ </a>
1754
+ </li>
1755
+
1756
+
1757
+
1758
+
1759
+
1760
+
1761
+
1762
+
1763
+
1764
+ <li class="md-nav__item">
1765
+ <a href="../models/dcim/powerfeed.html" class="md-nav__link">
1766
+ Power Feed
1767
+ </a>
1768
+ </li>
1769
+
1770
+
1771
+
1772
+
1773
+
1774
+
1775
+
1776
+
1777
+
1778
+ <li class="md-nav__item">
1779
+ <a href="../models/dcim/poweroutlet.html" class="md-nav__link">
1780
+ Power Outlet
1781
+ </a>
1782
+ </li>
1783
+
1784
+
1785
+
1786
+
1787
+
1788
+
1789
+
1790
+
1791
+
1792
+ <li class="md-nav__item">
1793
+ <a href="../models/dcim/poweroutlettemplate.html" class="md-nav__link">
1794
+ Power Outlet Template
1795
+ </a>
1796
+ </li>
1797
+
1798
+
1799
+
1800
+
1801
+
1802
+
1803
+
1804
+
1805
+
1806
+ <li class="md-nav__item">
1807
+ <a href="../models/dcim/powerpanel.html" class="md-nav__link">
1808
+ Power Panel
1809
+ </a>
1810
+ </li>
1811
+
1812
+
1813
+
1814
+
1815
+
1816
+
1817
+
1818
+
1819
+
1820
+ <li class="md-nav__item">
1821
+ <a href="../models/dcim/powerport.html" class="md-nav__link">
1822
+ Power Port
1823
+ </a>
1824
+ </li>
1825
+
1826
+
1827
+
1828
+
1829
+
1830
+
1831
+
1832
+
1833
+
1834
+ <li class="md-nav__item">
1835
+ <a href="../models/dcim/powerporttemplate.html" class="md-nav__link">
1836
+ Power Port Template
1837
+ </a>
1838
+ </li>
1839
+
1840
+
1841
+
1842
+
1843
+
1844
+
1845
+
1846
+
1847
+
1848
+ <li class="md-nav__item">
1849
+ <a href="../models/dcim/rack.html" class="md-nav__link">
1850
+ Rack
1851
+ </a>
1852
+ </li>
1853
+
1854
+
1855
+
1856
+
1857
+
1858
+
1859
+
1860
+
1861
+
1862
+ <li class="md-nav__item">
1863
+ <a href="../models/dcim/rackgroup.html" class="md-nav__link">
1864
+ Rack Group
1865
+ </a>
1866
+ </li>
1867
+
1868
+
1869
+
1870
+
1871
+
1872
+
1873
+
1874
+
1875
+
1876
+ <li class="md-nav__item">
1877
+ <a href="../models/dcim/rackreservation.html" class="md-nav__link">
1878
+ Rack Reservation
1879
+ </a>
1880
+ </li>
1881
+
1882
+
1883
+
1884
+
1885
+
1886
+
1887
+
1888
+
1889
+
1890
+ <li class="md-nav__item">
1891
+ <a href="../models/dcim/rearport.html" class="md-nav__link">
1892
+ Rear Port
1893
+ </a>
1894
+ </li>
1895
+
1896
+
1897
+
1898
+
1899
+
1900
+
1901
+
1902
+
1903
+
1904
+ <li class="md-nav__item">
1905
+ <a href="../models/dcim/rearporttemplate.html" class="md-nav__link">
1906
+ Rear Port Template
1907
+ </a>
1908
+ </li>
1909
+
1910
+
1911
+
1912
+
1913
+
1914
+
1915
+
1916
+
1917
+
1918
+ <li class="md-nav__item">
1919
+ <a href="../models/dcim/virtualchassis.html" class="md-nav__link">
1920
+ Virtual Chassis
1921
+ </a>
1922
+ </li>
1923
+
1924
+
1925
+
1926
+
1927
+ </ul>
1928
+ </nav>
1929
+ </li>
1930
+
1931
+
1932
+
1933
+
1934
+
1935
+
1936
+
1937
+
1938
+
1939
+
1940
+ <li class="md-nav__item md-nav__item--nested">
1941
+
1942
+
1943
+
1944
+
1945
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_3" >
1946
+
1947
+
1948
+
1949
+ <label class="md-nav__link" for="__nav_2_8_3" id="__nav_2_8_3_label" tabindex="0">
1950
+ Extras
1951
+ <span class="md-nav__icon md-icon"></span>
1952
+ </label>
1953
+
1954
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_3_label" aria-expanded="false">
1955
+ <label class="md-nav__title" for="__nav_2_8_3">
1956
+ <span class="md-nav__icon md-icon"></span>
1957
+ Extras
1958
+ </label>
1959
+ <ul class="md-nav__list" data-md-scrollfix>
1960
+
1961
+
1962
+
1963
+
1964
+
1965
+
1966
+ <li class="md-nav__item">
1967
+ <a href="../models/extras/configcontext.html" class="md-nav__link">
1968
+ Config Context
1969
+ </a>
1970
+ </li>
1971
+
1972
+
1973
+
1974
+
1975
+
1976
+
1977
+
1978
+
1979
+
1980
+ <li class="md-nav__item">
1981
+ <a href="../models/extras/configcontextschema.html" class="md-nav__link">
1982
+ Config Context Schema
1983
+ </a>
1984
+ </li>
1985
+
1986
+
1987
+
1988
+
1989
+
1990
+
1991
+
1992
+
1993
+
1994
+ <li class="md-nav__item">
1995
+ <a href="../models/extras/graphqlquery.html" class="md-nav__link">
1996
+ GraphQL Query
1997
+ </a>
1998
+ </li>
1999
+
2000
+
2001
+
2002
+
2003
+
2004
+
2005
+
2006
+
2007
+
2008
+ <li class="md-nav__item">
2009
+ <a href="../models/extras/imageattachment.html" class="md-nav__link">
2010
+ Image Attachment
2011
+ </a>
2012
+ </li>
2013
+
2014
+
2015
+
2016
+
2017
+
2018
+
2019
+
2020
+
2021
+
2022
+ <li class="md-nav__item">
2023
+ <a href="../models/extras/job.html" class="md-nav__link">
2024
+ Job
2025
+ </a>
2026
+ </li>
2027
+
2028
+
2029
+
2030
+
2031
+
2032
+
2033
+
2034
+
2035
+
2036
+ <li class="md-nav__item">
2037
+ <a href="../models/extras/joblogentry.html" class="md-nav__link">
2038
+ Job Log Entry
2039
+ </a>
2040
+ </li>
2041
+
2042
+
2043
+
2044
+
2045
+
2046
+
2047
+
2048
+
2049
+
2050
+ <li class="md-nav__item">
2051
+ <a href="../models/extras/jobresult.html" class="md-nav__link">
2052
+ Job Result
2053
+ </a>
2054
+ </li>
2055
+
2056
+
2057
+
2058
+
2059
+
2060
+
2061
+
2062
+
2063
+
2064
+ <li class="md-nav__item">
2065
+ <a href="../models/extras/role.html" class="md-nav__link">
2066
+ Role
2067
+ </a>
2068
+ </li>
2069
+
2070
+
2071
+
2072
+
2073
+
2074
+
2075
+
2076
+
2077
+
2078
+ <li class="md-nav__item">
2079
+ <a href="../models/extras/secret.html" class="md-nav__link">
2080
+ Secret
2081
+ </a>
2082
+ </li>
2083
+
2084
+
2085
+
2086
+
2087
+
2088
+
2089
+
2090
+
2091
+
2092
+ <li class="md-nav__item">
2093
+ <a href="../models/extras/secretsgroup.html" class="md-nav__link">
2094
+ Secrets group
2095
+ </a>
2096
+ </li>
2097
+
2098
+
2099
+
2100
+
2101
+ </ul>
2102
+ </nav>
2103
+ </li>
2104
+
2105
+
2106
+
2107
+
2108
+
2109
+
2110
+
2111
+
2112
+
2113
+
2114
+ <li class="md-nav__item md-nav__item--nested">
2115
+
2116
+
2117
+
2118
+
2119
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_4" >
2120
+
2121
+
2122
+
2123
+ <label class="md-nav__link" for="__nav_2_8_4" id="__nav_2_8_4_label" tabindex="0">
2124
+ IPAM
2125
+ <span class="md-nav__icon md-icon"></span>
2126
+ </label>
2127
+
2128
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_4_label" aria-expanded="false">
2129
+ <label class="md-nav__title" for="__nav_2_8_4">
2130
+ <span class="md-nav__icon md-icon"></span>
2131
+ IPAM
2132
+ </label>
2133
+ <ul class="md-nav__list" data-md-scrollfix>
2134
+
2135
+
2136
+
2137
+
2138
+
2139
+
2140
+ <li class="md-nav__item">
2141
+ <a href="../models/ipam/ipaddress.html" class="md-nav__link">
2142
+ IP Address
2143
+ </a>
2144
+ </li>
2145
+
2146
+
2147
+
2148
+
2149
+
2150
+
2151
+
2152
+
2153
+
2154
+ <li class="md-nav__item">
2155
+ <a href="../models/ipam/prefix.html" class="md-nav__link">
2156
+ Prefix
2157
+ </a>
2158
+ </li>
2159
+
2160
+
2161
+
2162
+
2163
+
2164
+
2165
+
2166
+
2167
+
2168
+ <li class="md-nav__item">
2169
+ <a href="../models/ipam/rir.html" class="md-nav__link">
2170
+ Rir
2171
+ </a>
2172
+ </li>
2173
+
2174
+
2175
+
2176
+
2177
+
2178
+
2179
+
2180
+
2181
+
2182
+ <li class="md-nav__item">
2183
+ <a href="../models/ipam/routetarget.html" class="md-nav__link">
2184
+ Route Target
2185
+ </a>
2186
+ </li>
2187
+
2188
+
2189
+
2190
+
2191
+
2192
+
2193
+
2194
+
2195
+
2196
+ <li class="md-nav__item">
2197
+ <a href="../models/ipam/service.html" class="md-nav__link">
2198
+ Service
2199
+ </a>
2200
+ </li>
2201
+
2202
+
2203
+
2204
+
2205
+
2206
+
2207
+
2208
+
2209
+
2210
+ <li class="md-nav__item">
2211
+ <a href="../models/ipam/vlan.html" class="md-nav__link">
2212
+ VLAN
2213
+ </a>
2214
+ </li>
2215
+
2216
+
2217
+
2218
+
2219
+
2220
+
2221
+
2222
+
2223
+
2224
+ <li class="md-nav__item">
2225
+ <a href="../models/ipam/vlangroup.html" class="md-nav__link">
2226
+ VLAN Group
2227
+ </a>
2228
+ </li>
2229
+
2230
+
2231
+
2232
+
2233
+
2234
+
2235
+
2236
+
2237
+
2238
+ <li class="md-nav__item">
2239
+ <a href="../models/ipam/vrf.html" class="md-nav__link">
2240
+ VRF
2241
+ </a>
2242
+ </li>
2243
+
2244
+
2245
+
2246
+
2247
+ </ul>
2248
+ </nav>
2249
+ </li>
2250
+
2251
+
2252
+
2253
+
2254
+
2255
+
2256
+
2257
+
2258
+
2259
+
2260
+ <li class="md-nav__item md-nav__item--nested">
2261
+
2262
+
2263
+
2264
+
2265
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_5" >
2266
+
2267
+
2268
+
2269
+ <label class="md-nav__link" for="__nav_2_8_5" id="__nav_2_8_5_label" tabindex="0">
2270
+ Tenancy
2271
+ <span class="md-nav__icon md-icon"></span>
2272
+ </label>
2273
+
2274
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_5_label" aria-expanded="false">
2275
+ <label class="md-nav__title" for="__nav_2_8_5">
2276
+ <span class="md-nav__icon md-icon"></span>
2277
+ Tenancy
2278
+ </label>
2279
+ <ul class="md-nav__list" data-md-scrollfix>
2280
+
2281
+
2282
+
2283
+
2284
+
2285
+
2286
+ <li class="md-nav__item">
2287
+ <a href="../models/tenancy/tenant.html" class="md-nav__link">
2288
+ Tenant
2289
+ </a>
2290
+ </li>
2291
+
2292
+
2293
+
2294
+
2295
+
2296
+
2297
+
2298
+
2299
+
2300
+ <li class="md-nav__item">
2301
+ <a href="../models/tenancy/tenantgroup.html" class="md-nav__link">
2302
+ Tenant Group
2303
+ </a>
2304
+ </li>
2305
+
2306
+
2307
+
2308
+
2309
+ </ul>
2310
+ </nav>
2311
+ </li>
2312
+
2313
+
2314
+
2315
+
2316
+
2317
+
2318
+
2319
+
2320
+
2321
+
2322
+ <li class="md-nav__item md-nav__item--nested">
2323
+
2324
+
2325
+
2326
+
2327
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_6" >
2328
+
2329
+
2330
+
2331
+ <label class="md-nav__link" for="__nav_2_8_6" id="__nav_2_8_6_label" tabindex="0">
2332
+ Users
2333
+ <span class="md-nav__icon md-icon"></span>
2334
+ </label>
2335
+
2336
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_6_label" aria-expanded="false">
2337
+ <label class="md-nav__title" for="__nav_2_8_6">
2338
+ <span class="md-nav__icon md-icon"></span>
2339
+ Users
2340
+ </label>
2341
+ <ul class="md-nav__list" data-md-scrollfix>
2342
+
2343
+
2344
+
2345
+
2346
+
2347
+
2348
+ <li class="md-nav__item">
2349
+ <a href="../models/users/objectpermission.html" class="md-nav__link">
2350
+ Object Permission
1215
2351
  </a>
1216
2352
  </li>
1217
2353
 
@@ -1224,27 +2360,47 @@
1224
2360
 
1225
2361
 
1226
2362
  <li class="md-nav__item">
1227
- <a href="../core-functionality/power.html" class="md-nav__link">
1228
- Power Tracking
2363
+ <a href="../models/users/token.html" class="md-nav__link">
2364
+ Token
1229
2365
  </a>
1230
2366
  </li>
1231
2367
 
1232
2368
 
1233
2369
 
1234
2370
 
2371
+ </ul>
2372
+ </nav>
2373
+ </li>
2374
+
2375
+
2376
+
2377
+
1235
2378
 
1236
2379
 
1237
2380
 
1238
2381
 
1239
2382
 
1240
- <li class="md-nav__item">
1241
- <a href="../core-functionality/secrets.html" class="md-nav__link">
1242
- Secrets
1243
- </a>
1244
- </li>
1245
-
1246
-
1247
-
2383
+
2384
+ <li class="md-nav__item md-nav__item--nested">
2385
+
2386
+
2387
+
2388
+
2389
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_8_7" >
2390
+
2391
+
2392
+
2393
+ <label class="md-nav__link" for="__nav_2_8_7" id="__nav_2_8_7_label" tabindex="0">
2394
+ Virtualization
2395
+ <span class="md-nav__icon md-icon"></span>
2396
+ </label>
2397
+
2398
+ <nav class="md-nav" data-md-level="3" aria-labelledby="__nav_2_8_7_label" aria-expanded="false">
2399
+ <label class="md-nav__title" for="__nav_2_8_7">
2400
+ <span class="md-nav__icon md-icon"></span>
2401
+ Virtualization
2402
+ </label>
2403
+ <ul class="md-nav__list" data-md-scrollfix>
1248
2404
 
1249
2405
 
1250
2406
 
@@ -1252,8 +2408,8 @@
1252
2408
 
1253
2409
 
1254
2410
  <li class="md-nav__item">
1255
- <a href="../core-functionality/services.html" class="md-nav__link">
1256
- Service Mapping
2411
+ <a href="../models/virtualization/cluster.html" class="md-nav__link">
2412
+ Cluster
1257
2413
  </a>
1258
2414
  </li>
1259
2415
 
@@ -1266,8 +2422,8 @@
1266
2422
 
1267
2423
 
1268
2424
  <li class="md-nav__item">
1269
- <a href="../core-functionality/sites-and-racks.html" class="md-nav__link">
1270
- Sites, Locations, and Racks
2425
+ <a href="../models/virtualization/clustergroup.html" class="md-nav__link">
2426
+ Cluster Group
1271
2427
  </a>
1272
2428
  </li>
1273
2429
 
@@ -1280,8 +2436,8 @@
1280
2436
 
1281
2437
 
1282
2438
  <li class="md-nav__item">
1283
- <a href="../core-functionality/tenancy.html" class="md-nav__link">
1284
- Tenancy
2439
+ <a href="../models/virtualization/clustertype.html" class="md-nav__link">
2440
+ Cluster Type
1285
2441
  </a>
1286
2442
  </li>
1287
2443
 
@@ -1294,8 +2450,8 @@
1294
2450
 
1295
2451
 
1296
2452
  <li class="md-nav__item">
1297
- <a href="../core-functionality/virtualization.html" class="md-nav__link">
1298
- Virtualization
2453
+ <a href="../models/virtualization/virtualmachine.html" class="md-nav__link">
2454
+ Virtual Machine
1299
2455
  </a>
1300
2456
  </li>
1301
2457
 
@@ -1308,8 +2464,8 @@
1308
2464
 
1309
2465
 
1310
2466
  <li class="md-nav__item">
1311
- <a href="../core-functionality/vlans.html" class="md-nav__link">
1312
- VLAN Management
2467
+ <a href="../models/virtualization/vminterface.html" class="md-nav__link">
2468
+ VM Interface
1313
2469
  </a>
1314
2470
  </li>
1315
2471
 
@@ -1323,6 +2479,13 @@
1323
2479
 
1324
2480
 
1325
2481
 
2482
+ </ul>
2483
+ </nav>
2484
+ </li>
2485
+
2486
+
2487
+
2488
+
1326
2489
 
1327
2490
 
1328
2491
 
@@ -1334,18 +2497,19 @@
1334
2497
  <li class="md-nav__item md-nav__item--active md-nav__item--nested">
1335
2498
 
1336
2499
 
1337
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_8" type="checkbox" id="__nav_2_8" checked>
1338
2500
 
1339
2501
 
2502
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_9" checked>
2503
+
1340
2504
 
1341
2505
 
1342
- <label class="md-nav__link" for="__nav_2_8">
2506
+ <label class="md-nav__link" for="__nav_2_9" id="__nav_2_9_label" tabindex="0">
1343
2507
  Additional Features
1344
2508
  <span class="md-nav__icon md-icon"></span>
1345
2509
  </label>
1346
2510
 
1347
- <nav class="md-nav" aria-label="Additional Features" data-md-level="2">
1348
- <label class="md-nav__title" for="__nav_2_8">
2511
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_9_label" aria-expanded="true">
2512
+ <label class="md-nav__title" for="__nav_2_9">
1349
2513
  <span class="md-nav__icon md-icon"></span>
1350
2514
  Additional Features
1351
2515
  </label>
@@ -1500,7 +2664,7 @@
1500
2664
 
1501
2665
  <li class="md-nav__item md-nav__item--active">
1502
2666
 
1503
- <input class="md-nav__toggle md-toggle" data-md-toggle="toc" type="checkbox" id="__toc">
2667
+ <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
1504
2668
 
1505
2669
 
1506
2670
 
@@ -1588,8 +2752,8 @@
1588
2752
  </li>
1589
2753
 
1590
2754
  <li class="md-nav__item">
1591
- <a href="#commit_default" class="md-nav__link">
1592
- commit_default
2755
+ <a href="#dryrun_default" class="md-nav__link">
2756
+ dryrun_default
1593
2757
  </a>
1594
2758
 
1595
2759
  </li>
@@ -1696,6 +2860,13 @@
1696
2860
  BooleanVar
1697
2861
  </a>
1698
2862
 
2863
+ </li>
2864
+
2865
+ <li class="md-nav__item">
2866
+ <a href="#dryrunvar" class="md-nav__link">
2867
+ DryRunVar
2868
+ </a>
2869
+
1699
2870
  </li>
1700
2871
 
1701
2872
  <li class="md-nav__item">
@@ -1767,29 +2938,22 @@
1767
2938
  </li>
1768
2939
 
1769
2940
  <li class="md-nav__item">
1770
- <a href="#the-test_-methods" class="md-nav__link">
1771
- The test_*() Methods
1772
- </a>
1773
-
1774
- </li>
1775
-
1776
- <li class="md-nav__item">
1777
- <a href="#the-post_run-method" class="md-nav__link">
1778
- The post_run() Method
2941
+ <a href="#logging" class="md-nav__link">
2942
+ Logging
1779
2943
  </a>
1780
2944
 
1781
2945
  </li>
1782
2946
 
1783
2947
  <li class="md-nav__item">
1784
- <a href="#logging" class="md-nav__link">
1785
- Logging
2948
+ <a href="#marking-a-job-as-failed" class="md-nav__link">
2949
+ Marking a Job as Failed
1786
2950
  </a>
1787
2951
 
1788
2952
  </li>
1789
2953
 
1790
2954
  <li class="md-nav__item">
1791
- <a href="#accessing-request-data" class="md-nav__link">
1792
- Accessing Request Data
2955
+ <a href="#accessing-user-and-job-result" class="md-nav__link">
2956
+ Accessing User and Job Result
1793
2957
  </a>
1794
2958
 
1795
2959
  </li>
@@ -1909,9 +3073,22 @@
1909
3073
 
1910
3074
  </li>
1911
3075
 
3076
+ </ul>
3077
+ </nav>
3078
+
3079
+ </li>
3080
+
3081
+ <li class="md-nav__item">
3082
+ <a href="#debugging-job-performance" class="md-nav__link">
3083
+ Debugging job performance
3084
+ </a>
3085
+
3086
+ <nav class="md-nav" aria-label="Debugging job performance">
3087
+ <ul class="md-nav__list">
3088
+
1912
3089
  <li class="md-nav__item">
1913
- <a href="#nautobot-132-and-earlier-including-12" class="md-nav__link">
1914
- Nautobot 1.3.2 and earlier (including 1.2)
3090
+ <a href="#reading-profiling-reports" class="md-nav__link">
3091
+ Reading profiling reports
1915
3092
  </a>
1916
3093
 
1917
3094
  </li>
@@ -1930,8 +3107,8 @@
1930
3107
  <ul class="md-nav__list">
1931
3108
 
1932
3109
  <li class="md-nav__item">
1933
- <a href="#creating-objects-for-a-planned-site" class="md-nav__link">
1934
- Creating objects for a planned site
3110
+ <a href="#creating-objects-for-a-planned-location" class="md-nav__link">
3111
+ Creating objects for a planned location
1935
3112
  </a>
1936
3113
 
1937
3114
  </li>
@@ -2127,18 +3304,19 @@
2127
3304
  <li class="md-nav__item md-nav__item--nested">
2128
3305
 
2129
3306
 
2130
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_9" type="checkbox" id="__nav_2_9" >
2131
3307
 
2132
3308
 
3309
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_10" >
2133
3310
 
2134
3311
 
2135
- <label class="md-nav__link" for="__nav_2_9">
3312
+
3313
+ <label class="md-nav__link" for="__nav_2_10" id="__nav_2_10_label" tabindex="0">
2136
3314
  REST API
2137
3315
  <span class="md-nav__icon md-icon"></span>
2138
3316
  </label>
2139
3317
 
2140
- <nav class="md-nav" aria-label="REST API" data-md-level="2">
2141
- <label class="md-nav__title" for="__nav_2_9">
3318
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_10_label" aria-expanded="false">
3319
+ <label class="md-nav__title" for="__nav_2_10">
2142
3320
  <span class="md-nav__icon md-icon"></span>
2143
3321
  REST API
2144
3322
  </label>
@@ -2186,6 +3364,20 @@
2186
3364
 
2187
3365
 
2188
3366
 
3367
+
3368
+
3369
+
3370
+
3371
+
3372
+ <li class="md-nav__item">
3373
+ <a href="../rest-api/ui-related-endpoints.html" class="md-nav__link">
3374
+ UI Endpoints
3375
+ </a>
3376
+ </li>
3377
+
3378
+
3379
+
3380
+
2189
3381
  </ul>
2190
3382
  </nav>
2191
3383
  </li>
@@ -2202,18 +3394,19 @@
2202
3394
  <li class="md-nav__item md-nav__item--nested">
2203
3395
 
2204
3396
 
2205
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_2_10" type="checkbox" id="__nav_2_10" >
2206
3397
 
2207
3398
 
3399
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_11" >
3400
+
2208
3401
 
2209
3402
 
2210
- <label class="md-nav__link" for="__nav_2_10">
3403
+ <label class="md-nav__link" for="__nav_2_11" id="__nav_2_11_label" tabindex="0">
2211
3404
  GraphQL API
2212
3405
  <span class="md-nav__icon md-icon"></span>
2213
3406
  </label>
2214
3407
 
2215
- <nav class="md-nav" aria-label="GraphQL API" data-md-level="2">
2216
- <label class="md-nav__title" for="__nav_2_10">
3408
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_11_label" aria-expanded="false">
3409
+ <label class="md-nav__title" for="__nav_2_11">
2217
3410
  <span class="md-nav__icon md-icon"></span>
2218
3411
  GraphQL API
2219
3412
  </label>
@@ -2271,17 +3464,18 @@
2271
3464
  <li class="md-nav__item md-nav__item--nested">
2272
3465
 
2273
3466
 
2274
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3" type="checkbox" id="__nav_3" >
2275
3467
 
2276
3468
 
3469
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
3470
+
2277
3471
 
2278
3472
 
2279
- <label class="md-nav__link" for="__nav_3">
3473
+ <label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
2280
3474
  App Developer Guide
2281
3475
  <span class="md-nav__icon md-icon"></span>
2282
3476
  </label>
2283
3477
 
2284
- <nav class="md-nav" aria-label="App Developer Guide" data-md-level="1">
3478
+ <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
2285
3479
  <label class="md-nav__title" for="__nav_3">
2286
3480
  <span class="md-nav__icon md-icon"></span>
2287
3481
  App Developer Guide
@@ -2325,17 +3519,18 @@
2325
3519
  <li class="md-nav__item md-nav__item--nested">
2326
3520
 
2327
3521
 
2328
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_3_3" type="checkbox" id="__nav_3_3" >
2329
3522
 
2330
3523
 
3524
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3_3" >
2331
3525
 
2332
3526
 
2333
- <label class="md-nav__link" for="__nav_3_3">
3527
+
3528
+ <label class="md-nav__link" for="__nav_3_3" id="__nav_3_3_label" tabindex="0">
2334
3529
  Code Reference
2335
3530
  <span class="md-nav__icon md-icon"></span>
2336
3531
  </label>
2337
3532
 
2338
- <nav class="md-nav" aria-label="Code Reference" data-md-level="2">
3533
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_3_3_label" aria-expanded="false">
2339
3534
  <label class="md-nav__title" for="__nav_3_3">
2340
3535
  <span class="md-nav__icon md-icon"></span>
2341
3536
  Code Reference
@@ -2562,17 +3757,18 @@
2562
3757
  <li class="md-nav__item md-nav__item--nested">
2563
3758
 
2564
3759
 
2565
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_4" type="checkbox" id="__nav_4" >
2566
3760
 
2567
3761
 
3762
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
3763
+
2568
3764
 
2569
3765
 
2570
- <label class="md-nav__link" for="__nav_4">
3766
+ <label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0">
2571
3767
  Core Developer Guide
2572
3768
  <span class="md-nav__icon md-icon"></span>
2573
3769
  </label>
2574
3770
 
2575
- <nav class="md-nav" aria-label="Core Developer Guide" data-md-level="1">
3771
+ <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
2576
3772
  <label class="md-nav__title" for="__nav_4">
2577
3773
  <span class="md-nav__icon md-icon"></span>
2578
3774
  Core Developer Guide
@@ -2806,17 +4002,18 @@
2806
4002
  <li class="md-nav__item md-nav__item--nested">
2807
4003
 
2808
4004
 
2809
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_5" type="checkbox" id="__nav_5" >
2810
4005
 
2811
4006
 
4007
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
2812
4008
 
2813
4009
 
2814
- <label class="md-nav__link" for="__nav_5">
4010
+
4011
+ <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
2815
4012
  Release Notes
2816
4013
  <span class="md-nav__icon md-icon"></span>
2817
4014
  </label>
2818
4015
 
2819
- <nav class="md-nav" aria-label="Release Notes" data-md-level="1">
4016
+ <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
2820
4017
  <label class="md-nav__title" for="__nav_5">
2821
4018
  <span class="md-nav__icon md-icon"></span>
2822
4019
  Release Notes
@@ -2952,17 +4149,18 @@
2952
4149
  <li class="md-nav__item md-nav__item--nested">
2953
4150
 
2954
4151
 
2955
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6" type="checkbox" id="__nav_6" >
2956
4152
 
2957
4153
 
4154
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
4155
+
2958
4156
 
2959
4157
 
2960
- <label class="md-nav__link" for="__nav_6">
4158
+ <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0">
2961
4159
  Nautobot Apps
2962
4160
  <span class="md-nav__icon md-icon"></span>
2963
4161
  </label>
2964
4162
 
2965
- <nav class="md-nav" aria-label="Nautobot Apps" data-md-level="1">
4163
+ <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
2966
4164
  <label class="md-nav__title" for="__nav_6">
2967
4165
  <span class="md-nav__icon md-icon"></span>
2968
4166
  Nautobot Apps
@@ -2992,17 +4190,18 @@
2992
4190
  <li class="md-nav__item md-nav__item--nested">
2993
4191
 
2994
4192
 
2995
- <input class="md-nav__toggle md-toggle" data-md-toggle="__nav_6_2" type="checkbox" id="__nav_6_2" >
2996
4193
 
2997
4194
 
4195
+ <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_2" >
2998
4196
 
2999
4197
 
3000
- <label class="md-nav__link" for="__nav_6_2">
4198
+
4199
+ <label class="md-nav__link" for="__nav_6_2" id="__nav_6_2_label" tabindex="0">
3001
4200
  Network to Code App Docs
3002
4201
  <span class="md-nav__icon md-icon"></span>
3003
4202
  </label>
3004
4203
 
3005
- <nav class="md-nav" aria-label="Network to Code App Docs" data-md-level="2">
4204
+ <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_2_label" aria-expanded="false">
3006
4205
  <label class="md-nav__title" for="__nav_6_2">
3007
4206
  <span class="md-nav__icon md-icon"></span>
3008
4207
  Network to Code App Docs
@@ -3029,8 +4228,8 @@
3029
4228
 
3030
4229
 
3031
4230
  <li class="md-nav__item">
3032
- <a href="https://nautobot-plugin-firewall-models.readthedocs.io/en/latest/" class="md-nav__link">
3033
- Nautobot Firewall Models
4231
+ <a href="https://docs.nautobot.com/projects/circuit-maintenance/en/latest/" class="md-nav__link">
4232
+ Nautobot Circuit Maintenance
3034
4233
  </a>
3035
4234
  </li>
3036
4235
 
@@ -3043,8 +4242,36 @@
3043
4242
 
3044
4243
 
3045
4244
  <li class="md-nav__item">
3046
- <a href="https://docs.nautobot.com/projects/plugin-nornir/en/latest/" class="md-nav__link">
3047
- Nautobot Plugin Nornir
4245
+ <a href="https://docs.nautobot.com/projects/device-lifecycle/en/latest/" class="md-nav__link">
4246
+ Nautobot Device LifeCycle Management
4247
+ </a>
4248
+ </li>
4249
+
4250
+
4251
+
4252
+
4253
+
4254
+
4255
+
4256
+
4257
+
4258
+ <li class="md-nav__item">
4259
+ <a href="https://docs.nautobot.com/projects/device-onboarding/en/latest/" class="md-nav__link">
4260
+ Nautobot Device Onboarding
4261
+ </a>
4262
+ </li>
4263
+
4264
+
4265
+
4266
+
4267
+
4268
+
4269
+
4270
+
4271
+
4272
+ <li class="md-nav__item">
4273
+ <a href="https://nautobot-plugin-firewall-models.readthedocs.io/en/latest/" class="md-nav__link">
4274
+ Nautobot Firewall Models
3048
4275
  </a>
3049
4276
  </li>
3050
4277
 
@@ -3071,7 +4298,21 @@
3071
4298
 
3072
4299
 
3073
4300
  <li class="md-nav__item">
3074
- <a href="https://nautobot-plugin-ssot.readthedocs.io/en/latest/" class="md-nav__link">
4301
+ <a href="https://docs.nautobot.com/projects/plugin-nornir/en/latest/" class="md-nav__link">
4302
+ Nautobot Plugin Nornir
4303
+ </a>
4304
+ </li>
4305
+
4306
+
4307
+
4308
+
4309
+
4310
+
4311
+
4312
+
4313
+
4314
+ <li class="md-nav__item">
4315
+ <a href="https://docs.nautobot.com/projects/ssot/en/latest/" class="md-nav__link">
3075
4316
  Nautobot Single Source of Truth
3076
4317
  </a>
3077
4318
  </li>
@@ -3205,8 +4446,8 @@
3205
4446
  </li>
3206
4447
 
3207
4448
  <li class="md-nav__item">
3208
- <a href="#commit_default" class="md-nav__link">
3209
- commit_default
4449
+ <a href="#dryrun_default" class="md-nav__link">
4450
+ dryrun_default
3210
4451
  </a>
3211
4452
 
3212
4453
  </li>
@@ -3313,6 +4554,13 @@
3313
4554
  BooleanVar
3314
4555
  </a>
3315
4556
 
4557
+ </li>
4558
+
4559
+ <li class="md-nav__item">
4560
+ <a href="#dryrunvar" class="md-nav__link">
4561
+ DryRunVar
4562
+ </a>
4563
+
3316
4564
  </li>
3317
4565
 
3318
4566
  <li class="md-nav__item">
@@ -3384,29 +4632,22 @@
3384
4632
  </li>
3385
4633
 
3386
4634
  <li class="md-nav__item">
3387
- <a href="#the-test_-methods" class="md-nav__link">
3388
- The test_*() Methods
3389
- </a>
3390
-
3391
- </li>
3392
-
3393
- <li class="md-nav__item">
3394
- <a href="#the-post_run-method" class="md-nav__link">
3395
- The post_run() Method
4635
+ <a href="#logging" class="md-nav__link">
4636
+ Logging
3396
4637
  </a>
3397
4638
 
3398
4639
  </li>
3399
4640
 
3400
4641
  <li class="md-nav__item">
3401
- <a href="#logging" class="md-nav__link">
3402
- Logging
4642
+ <a href="#marking-a-job-as-failed" class="md-nav__link">
4643
+ Marking a Job as Failed
3403
4644
  </a>
3404
4645
 
3405
4646
  </li>
3406
4647
 
3407
4648
  <li class="md-nav__item">
3408
- <a href="#accessing-request-data" class="md-nav__link">
3409
- Accessing Request Data
4649
+ <a href="#accessing-user-and-job-result" class="md-nav__link">
4650
+ Accessing User and Job Result
3410
4651
  </a>
3411
4652
 
3412
4653
  </li>
@@ -3526,9 +4767,22 @@
3526
4767
 
3527
4768
  </li>
3528
4769
 
4770
+ </ul>
4771
+ </nav>
4772
+
4773
+ </li>
4774
+
4775
+ <li class="md-nav__item">
4776
+ <a href="#debugging-job-performance" class="md-nav__link">
4777
+ Debugging job performance
4778
+ </a>
4779
+
4780
+ <nav class="md-nav" aria-label="Debugging job performance">
4781
+ <ul class="md-nav__list">
4782
+
3529
4783
  <li class="md-nav__item">
3530
- <a href="#nautobot-132-and-earlier-including-12" class="md-nav__link">
3531
- Nautobot 1.3.2 and earlier (including 1.2)
4784
+ <a href="#reading-profiling-reports" class="md-nav__link">
4785
+ Reading profiling reports
3532
4786
  </a>
3533
4787
 
3534
4788
  </li>
@@ -3547,8 +4801,8 @@
3547
4801
  <ul class="md-nav__list">
3548
4802
 
3549
4803
  <li class="md-nav__item">
3550
- <a href="#creating-objects-for-a-planned-site" class="md-nav__link">
3551
- Creating objects for a planned site
4804
+ <a href="#creating-objects-for-a-planned-location" class="md-nav__link">
4805
+ Creating objects for a planned location
3552
4806
  </a>
3553
4807
 
3554
4808
  </li>
@@ -3579,10 +4833,8 @@
3579
4833
 
3580
4834
 
3581
4835
 
3582
- <a href="https://github.com/nautobot/nautobot/edit/main/nautobot/docs/additional-features/jobs.md" title="Edit this page" class="md-content__button md-icon">
3583
-
3584
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25Z"/></svg>
3585
- </a>
4836
+
4837
+
3586
4838
 
3587
4839
 
3588
4840
  <h1 id="jobs">Jobs<a class="headerlink" href="#jobs" title="Permanent link">&para;</a></h1>
@@ -3596,9 +4848,13 @@
3596
4848
  <li>Check and report whether all IP addresses have a parent prefix</li>
3597
4849
  </ul>
3598
4850
  <p>...and so on. Jobs are Python code and exist outside of the official Nautobot code base, so they can be updated and changed without interfering with the core Nautobot installation. And because they're completely customizable, there's practically no limit to what a job can accomplish.</p>
4851
+ <div class="admonition version-changed">
4852
+ <p class="admonition-title">Changed in version 2.0.0</p>
4853
+ <p>Backwards compatibility with NetBox scripts and reports has been removed. This includes removal of automatic calls to the <code>post_run()</code> and <code>test_*()</code> methods.</p>
4854
+ </div>
3599
4855
  <div class="admonition note">
3600
4856
  <p class="admonition-title">Note</p>
3601
- <p>Jobs unify and supersede the functionality previously provided in NetBox by "custom scripts" and "reports". Jobs are backwards-compatible for now with the <code>Script</code> and <code>Report</code> class APIs, but you are urged to move to the new <code>Job</code> class API described below. Jobs may be optionally marked as <a href="#read_only">read-only</a> which equates to the <code>Report</code> functionally, but in all cases, user input is supported via <a href="#variables">job variables</a>.</p>
4857
+ <p>Jobs unify and supersede the functionality previously provided in NetBox by "custom scripts" and "reports". User input is supported via <a href="#variables">job variables</a>.</p>
3602
4858
  </div>
3603
4859
  <h2 id="writing-jobs">Writing Jobs<a class="headerlink" href="#writing-jobs" title="Permanent link">&para;</a></h2>
3604
4860
  <p>Jobs may be installed in one of three ways:</p>
@@ -3620,34 +4876,34 @@
3620
4876
  </ul>
3621
4877
  <p>In any case, each module holds one or more Jobs (Python classes), each of which serves a specific purpose. The logic of each job can be split into a number of distinct methods, each of which performs a discrete portion of the overall job logic.</p>
3622
4878
  <p>For example, we can create a module named <code>devices.py</code> to hold all of our jobs which pertain to devices in Nautobot. Within that module, we might define several jobs. Each job is defined as a Python class inheriting from <code>extras.jobs.Job</code>, which provides the base functionality needed to accept user input and log activity.</p>
4879
+ <div class="admonition version-changed">
4880
+ <p class="admonition-title">Changed in version 2.0.0</p>
4881
+ <p>All job classes must now be registered with <code>nautobot.core.celery.register_jobs</code> on module import. For plugins providing jobs, the module containing the jobs must be imported by the plugin's <code>__init__.py</code> and the <code>register_jobs</code> method called at import time. The <code>register_jobs</code> method accepts one or more job classes as arguments.</p>
4882
+ </div>
3623
4883
  <div class="admonition warning">
3624
4884
  <p class="admonition-title">Warning</p>
3625
4885
  <p>Make sure you are <em>not</em> inheriting <code>extras.jobs.models.Job</code> instead, otherwise Django will think you want to define a new database model.</p>
3626
4886
  </div>
3627
- <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
3628
- <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>
3629
- <a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
3630
- <a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="o">...</span>
3631
- <a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>
3632
- <a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a><span class="k">class</span> <span class="nc">DeviceConnectionsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
3633
- <a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a> <span class="o">...</span>
3634
- <a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a>
3635
- <a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a><span class="k">class</span> <span class="nc">DeviceIPsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
3636
- <a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a> <span class="o">...</span>
4887
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="kn">from</span> <span class="nn">nautobot.core.celery</span> <span class="kn">import</span> <span class="n">register_jobs</span>
4888
+ <a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span>
4889
+ <a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>
4890
+ <a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
4891
+ <a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a> <span class="o">...</span>
4892
+ <a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>
4893
+ <a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a><span class="k">class</span> <span class="nc">DeviceConnectionsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
4894
+ <a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a> <span class="o">...</span>
4895
+ <a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a>
4896
+ <a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a><span class="k">class</span> <span class="nc">DeviceIPsReport</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
4897
+ <a id="__codelineno-0-11" name="__codelineno-0-11" href="#__codelineno-0-11"></a> <span class="o">...</span>
4898
+ <a id="__codelineno-0-12" name="__codelineno-0-12" href="#__codelineno-0-12"></a>
4899
+ <a id="__codelineno-0-13" name="__codelineno-0-13" href="#__codelineno-0-13"></a><span class="n">register_jobs</span><span class="p">(</span><span class="n">CreateDevices</span><span class="p">,</span> <span class="n">DeviceConnectionsReport</span><span class="p">,</span> <span class="n">DeviceIPsReport</span><span class="p">)</span>
3637
4900
  </code></pre></div>
3638
4901
  <p>Each job class will implement some or all of the following components:</p>
3639
4902
  <ul>
3640
4903
  <li>Module and class attributes, providing for default behavior, documentation and discoverability</li>
3641
4904
  <li>a set of variables for user input via the Nautobot UI (if your job requires any user inputs)</li>
3642
- <li>a <code>run()</code> method, which is executed first and receives the user input values, if any</li>
3643
- <li>any number of <code>test_*()</code> methods, which will be invoked next in order of declaration. Log messages generated by the job will be grouped together by the test method they were invoked from.</li>
3644
- <li>a <code>post_run()</code> method, which is executed last and can be used to handle any necessary cleanup or final events (such as sending an email or triggering a webhook). The status of the overall job is available at this time as <code>self.failed</code> and the <code>JobResult</code> data object is available as <code>self.result</code>.</li>
4905
+ <li>a <code>run()</code> method, which is the only required attribute on a Job class and receives the user input values, if any</li>
3645
4906
  </ul>
3646
- <p>You can implement the entire job within the <code>run()</code> function, but for more complex jobs, you may want to provide more granularity in the output and logging of activity. For this purpose, you can implement portions of the logic as <code>test_*()</code> methods (i.e., methods whose name begins with <code>test_*</code>) and/or a <code>post_run()</code> method. Log messages generated by the job logging APIs (more below on this topic) will be grouped together according to their base method (<code>run</code>, <code>test_a</code>, <code>test_b</code>, ..., <code>post_run</code>) which can aid in understanding the operation of the job.</p>
3647
- <div class="admonition note">
3648
- <p class="admonition-title">Note</p>
3649
- <p>Your job can of course define additional Python methods to compartmentalize and reuse logic as required; however the <code>run</code>, <code>test_*</code>, and <code>post_run</code> methods are the only ones that will be automatically invoked by Nautobot.</p>
3650
- </div>
3651
4907
  <p>It's important to understand that jobs execute on the server asynchronously as background tasks; they log messages and report their status to the database by updating <a href="../models/extras/jobresult.html"><code>JobResult</code></a> records and creating <a href="../models/extras/joblogentry.html"><code>JobLogEntry</code></a> records.</p>
3652
4908
  <div class="admonition note">
3653
4909
  <p class="admonition-title">Note</p>
@@ -3686,12 +4942,16 @@ This can accept either plain text or Markdown-formatted text. It can also be mul
3686
4942
  <h4 id="approval_required"><code>approval_required</code><a class="headerlink" href="#approval_required" title="Permanent link">&para;</a></h4>
3687
4943
  <p>Default: <code>False</code></p>
3688
4944
  <p>A boolean that will mark this job as requiring approval from another user to be run. For more details on approvals, <a href="job-scheduling-and-approvals.html">please refer to the section on scheduling and approvals</a>.</p>
3689
- <h4 id="commit_default"><code>commit_default</code><a class="headerlink" href="#commit_default" title="Permanent link">&para;</a></h4>
3690
- <p>Default: <code>True</code></p>
3691
- <p>The checkbox to commit database changes when executing a job is checked by default in the Nautobot UI. You can set <code>commit_default</code> to <code>False</code> under the <code>Meta</code> class if you want this option to instead be unchecked by default.</p>
4945
+ <h4 id="dryrun_default"><code>dryrun_default</code><a class="headerlink" href="#dryrun_default" title="Permanent link">&para;</a></h4>
4946
+ <div class="admonition version-changed">
4947
+ <p class="admonition-title">Changed in version 2.0.0</p>
4948
+ <p>The <code>commit_default</code> field was renamed to <code>dryrun_default</code> and the default value was changed from <code>True</code> to <code>False</code>. The <code>commit</code> functionality that provided an automatic rollback of database changes if the job failed was removed. The <code>dryrun</code> functionality was added to provide a way to bypass job approval if a job implements a <a href="#dryrunvar"><code>DryRunVar</code></a>.</p>
4949
+ </div>
4950
+ <p>Default: <code>False</code></p>
4951
+ <p>The checkbox to enable dryrun when executing a job is unchecked by default in the Nautobot UI. You can set <code>dryrun_default</code> to <code>True</code> under the <code>Meta</code> class if you want this option to instead be checked by default.</p>
3692
4952
  <div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
3693
4953
  <a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
3694
- <a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> <span class="n">commit_default</span> <span class="o">=</span> <span class="kc">False</span>
4954
+ <a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a> <span class="n">dryrun_default</span> <span class="o">=</span> <span class="kc">True</span>
3695
4955
  </code></pre></div>
3696
4956
  <h4 id="field_order"><code>field_order</code><a class="headerlink" href="#field_order" title="Permanent link">&para;</a></h4>
3697
4957
  <p>Default: <code>[]</code></p>
@@ -3723,8 +4983,12 @@ This can accept either plain text or Markdown-formatted text. It can also be mul
3723
4983
  <div class="admonition version-added">
3724
4984
  <p class="admonition-title">Added in version 1.1.0</p>
3725
4985
  </div>
4986
+ <div class="admonition version-changed">
4987
+ <p class="admonition-title">Changed in version 2.0.0</p>
4988
+ <p>The <code>read_only</code> flag no longer changes the behavior of Nautobot core and is up to the job author to decide whether their job should be considered read only.</p>
4989
+ </div>
3726
4990
  <p>Default: <code>False</code></p>
3727
- <p>A boolean that designates whether the job is able to make changes to data in the database. The value defaults to <code>False</code> but when set to <code>True</code>, any data modifications executed from the job's code will be automatically aborted at the end of the job. The job input form is also modified to remove the <code>commit</code> checkbox as it is irrelevant for read-only jobs. When a job is marked as read-only, log messages that are normally automatically emitted about the DB transaction state are not included because no changes to data are allowed. Note that user input may still be optionally collected with read-only jobs via job variables, as described below.</p>
4991
+ <p>A boolean that can be set by the job author to indicate that the job does not make any changes to the environment. What behavior makes each job "read only" is up to the individual job author to decide. Note that user input may still be optionally collected with read-only jobs via job variables, as described below.</p>
3728
4992
  <h4 id="soft_time_limit"><code>soft_time_limit</code><a class="headerlink" href="#soft_time_limit" title="Permanent link">&para;</a></h4>
3729
4993
  <div class="admonition version-added">
3730
4994
  <p class="admonition-title">Added in version 1.3.0</p>
@@ -3740,7 +5004,7 @@ This can accept either plain text or Markdown-formatted text. It can also be mul
3740
5004
  <a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot;Set a soft time limit of 10 seconds`&quot;</span>
3741
5005
  <a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a> <span class="n">soft_time_limit</span> <span class="o">=</span> <span class="mi">10</span>
3742
5006
  <a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>
3743
- <a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">commit</span><span class="p">):</span>
5007
+ <a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3744
5008
  <a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a> <span class="k">try</span><span class="p">:</span>
3745
5009
  <a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a> <span class="c1"># code which might take longer than 10 seconds to run</span>
3746
5010
  <a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a> <span class="n">job_code</span><span class="p">()</span>
@@ -3795,7 +5059,7 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3795
5059
  <a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot;Set a hard time limit of 10 seconds`&quot;</span>
3796
5060
  <a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a> <span class="n">time_limit</span> <span class="o">=</span> <span class="mi">10</span>
3797
5061
  <a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a>
3798
- <a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">commit</span><span class="p">):</span>
5062
+ <a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
3799
5063
  <a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a> <span class="c1"># code which might take longer than 10 seconds to run</span>
3800
5064
  <a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a> <span class="c1"># this code will fail silently if the time_limit is exceeded</span>
3801
5065
  <a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a> <span class="n">job_code</span><span class="p">()</span>
@@ -3813,7 +5077,7 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3813
5077
  <a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a> <span class="n">var2</span> <span class="o">=</span> <span class="n">IntegerVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
3814
5078
  <a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a> <span class="n">var3</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
3815
5079
  <a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a>
3816
- <a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">commit</span><span class="p">):</span>
5080
+ <a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">var1</span><span class="p">,</span> <span class="n">var2</span><span class="p">,</span> <span class="n">var3</span><span class="p">):</span>
3817
5081
  <a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a> <span class="o">...</span>
3818
5082
  </code></pre></div>
3819
5083
  <p>The remainder of this section documents the various supported variable types and how to make use of them.</p>
@@ -3844,6 +5108,8 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3844
5108
  </ul>
3845
5109
  <h4 id="booleanvar"><code>BooleanVar</code><a class="headerlink" href="#booleanvar" title="Permanent link">&para;</a></h4>
3846
5110
  <p>A true/false flag. This field has no options beyond the defaults listed above.</p>
5111
+ <h4 id="dryrunvar"><code>DryRunVar</code><a class="headerlink" href="#dryrunvar" title="Permanent link">&para;</a></h4>
5112
+ <p>A true/false flag with special handling for jobs that require approval. If <code>dryrun = DryRunVar()</code> is declared on a job class, approval may be bypassed if <code>dryrun</code> is set to <code>True</code> on job execution.</p>
3847
5113
  <h4 id="choicevar"><code>ChoiceVar</code><a class="headerlink" href="#choicevar" title="Permanent link">&para;</a></h4>
3848
5114
  <p>A set of choices from which the user can select one.</p>
3849
5115
  <ul>
@@ -3883,18 +5149,18 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3883
5149
  <a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a> <span class="p">}</span>
3884
5150
  <a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="p">)</span>
3885
5151
  </code></pre></div>
3886
- <p>Multiple values can be specified by assigning a list to the dictionary key. It is also possible to reference the value of other fields in the form by prepending a dollar sign (<code>$</code>) to the variable's name. The keys you can use in this dictionary are the same ones that are available in the REST API - as an example it is also possible to filter the <code>Site</code> <code>ObjectVar</code> for its <code>tenant_group</code>.</p>
3887
- <div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="n">region</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
3888
- <a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">Region</span>
5152
+ <p>Multiple values can be specified by assigning a list to the dictionary key. It is also possible to reference the value of other fields in the form by prepending a dollar sign (<code>$</code>) to the variable's name. The keys you can use in this dictionary are the same ones that are available in the REST API - as an example it is also possible to filter the <code>Location</code> <code>ObjectVar</code> for its <code>location_type</code> and <code>tenant_group</code>.</p>
5153
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a><span class="n">location_type</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
5154
+ <a id="__codelineno-10-2" name="__codelineno-10-2" href="#__codelineno-10-2"></a> <span class="n">model</span><span class="o">=</span><span class="n">LocationType</span>
3889
5155
  <a id="__codelineno-10-3" name="__codelineno-10-3" href="#__codelineno-10-3"></a><span class="p">)</span>
3890
5156
  <a id="__codelineno-10-4" name="__codelineno-10-4" href="#__codelineno-10-4"></a><span class="n">tenant_group</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
3891
5157
  <a id="__codelineno-10-5" name="__codelineno-10-5" href="#__codelineno-10-5"></a> <span class="n">model</span><span class="o">=</span><span class="n">TenantGroup</span>
3892
5158
  <a id="__codelineno-10-6" name="__codelineno-10-6" href="#__codelineno-10-6"></a><span class="p">)</span>
3893
- <a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="n">site</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
3894
- <a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a> <span class="n">model</span><span class="o">=</span><span class="n">Site</span><span class="p">,</span>
5159
+ <a id="__codelineno-10-7" name="__codelineno-10-7" href="#__codelineno-10-7"></a><span class="n">location</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
5160
+ <a id="__codelineno-10-8" name="__codelineno-10-8" href="#__codelineno-10-8"></a> <span class="n">model</span><span class="o">=</span><span class="n">Location</span><span class="p">,</span>
3895
5161
  <a id="__codelineno-10-9" name="__codelineno-10-9" href="#__codelineno-10-9"></a> <span class="n">query_params</span><span class="o">=</span><span class="p">{</span>
3896
- <a id="__codelineno-10-10" name="__codelineno-10-10" href="#__codelineno-10-10"></a> <span class="s1">&#39;region&#39;</span><span class="p">:</span> <span class="s1">&#39;$region&#39;</span><span class="p">,</span>
3897
- <a id="__codelineno-10-11" name="__codelineno-10-11" href="#__codelineno-10-11"></a> <span class="s1">&#39;tenant_group&#39;</span><span class="p">:</span> <span class="s1">&#39;$tenant_group&#39;</span>
5162
+ <a id="__codelineno-10-10" name="__codelineno-10-10" href="#__codelineno-10-10"></a> <span class="s2">&quot;location_type&quot;</span><span class="p">:</span> <span class="s2">&quot;$location_type&quot;</span><span class="p">,</span>
5163
+ <a id="__codelineno-10-11" name="__codelineno-10-11" href="#__codelineno-10-11"></a> <span class="s2">&quot;tenant_group&quot;</span><span class="p">:</span> <span class="s2">&quot;$tenant_group&quot;</span>
3898
5164
  <a id="__codelineno-10-12" name="__codelineno-10-12" href="#__codelineno-10-12"></a> <span class="p">}</span>
3899
5165
  <a id="__codelineno-10-13" name="__codelineno-10-13" href="#__codelineno-10-13"></a><span class="p">)</span>
3900
5166
  </code></pre></div>
@@ -3913,11 +5179,7 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3913
5179
  <li><code>max_prefix_length</code> - Maximum length of the mask</li>
3914
5180
  </ul>
3915
5181
  <h3 id="the-run-method">The <code>run()</code> Method<a class="headerlink" href="#the-run-method" title="Permanent link">&para;</a></h3>
3916
- <p>The <code>run()</code> method, if you choose to implement it, should accept two arguments:</p>
3917
- <ol>
3918
- <li><code>data</code> - A dictionary which will contain all of the variable data passed in by the user (via the web UI or REST API)</li>
3919
- <li><code>commit</code> - A boolean indicating whether database changes should be committed. If this is <code>False</code>, even if your Job attempts to make database changes, they will be automatically rolled back when the Job completes.</li>
3920
- </ol>
5182
+ <p>The <code>run()</code> method must be implemented. After the <code>self</code> argument, it should accept keyword arguments for any variables defined on the job:</p>
3921
5183
  <div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span><span class="p">,</span> <span class="n">IntegerVar</span><span class="p">,</span> <span class="n">ObjectVar</span>
3922
5184
  <a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a>
3923
5185
  <a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="k">class</span> <span class="nc">CreateDevices</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
@@ -3925,18 +5187,10 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3925
5187
  <a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a> <span class="n">var2</span> <span class="o">=</span> <span class="n">IntegerVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
3926
5188
  <a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a> <span class="n">var3</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
3927
5189
  <a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a>
3928
- <a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">commit</span><span class="p">):</span>
5190
+ <a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">var1</span><span class="p">,</span> <span class="n">var2</span><span class="p">,</span> <span class="n">var3</span><span class="p">):</span>
3929
5191
  <a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a> <span class="o">...</span>
3930
5192
  </code></pre></div>
3931
- <p>Again, defining user variables is totally optional; you may create a job with just a <code>run()</code> method if no user input is needed, in which case <code>data</code> will be an empty dictionary.</p>
3932
- <div class="admonition note">
3933
- <p class="admonition-title">Note</p>
3934
- <p>The <code>test_*()</code> and <code>post_run()</code> methods do not accept any arguments; if you need to access user <code>data</code> or the <code>commit</code> flag, your <code>run()</code> method is responsible for storing these values in the job instance, such as:</p>
3935
- <div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a>def run(self, data, commit):
3936
- <a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a> self.data = data
3937
- <a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a> self.commit = commit
3938
- </code></pre></div>
3939
- </div>
5193
+ <p>Again, defining user variables is totally optional; you may create a job with a <code>run()</code> method with only the <code>self</code> argument if no user input is needed.</p>
3940
5194
  <div class="admonition warning">
3941
5195
  <p class="admonition-title">Warning</p>
3942
5196
  <p>When writing Jobs that create and manipulate data it is recommended to make use of the <code>validated_save()</code> convenience method which exists on all core models. This method saves the instance data but first enforces model validation logic. Simply calling <code>save()</code> on the model instance <strong>does not</strong> enforce validation automatically and may lead to bad data. See the development <a href="../development/best-practices.html">best practices</a>.</p>
@@ -3945,44 +5199,74 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
3945
5199
  <p class="admonition-title">Warning</p>
3946
5200
  <p>The Django ORM provides methods to create/edit many objects at once, namely <code>bulk_create()</code> and <code>update()</code>. These are best avoided in most cases as they bypass a model's built-in validation and can easily lead to database corruption if not used carefully.</p>
3947
5201
  </div>
3948
- <h3 id="the-test_-methods">The <code>test_*()</code> Methods<a class="headerlink" href="#the-test_-methods" title="Permanent link">&para;</a></h3>
3949
- <p>If your job class defines any number of methods whose names begin with <code>test_</code>, these will be automatically invoked after the <code>run()</code> method (if any) completes. These methods must take no arguments (other than <code>self</code>).</p>
3950
- <p>Log messages generated by any of these methods will be automatically grouped together by the test method they were invoked from, which can be helpful for readability.</p>
3951
- <h3 id="the-post_run-method">The <code>post_run()</code> Method<a class="headerlink" href="#the-post_run-method" title="Permanent link">&para;</a></h3>
3952
- <p>If your job class implements a <code>post_run()</code> method (which must take no arguments other than <code>self</code>), this method will be automatically invoked after the <code>run()</code> and <code>test_*()</code> methods (if any). It will be called even if one of the other methods raises an exception, so this method can be used to handle any necessary cleanup or final events (such as sending an email or triggering a webhook). The status of the overall job is available at this time as <code>self.failed</code> and the associated <a href="../models/extras/jobresult.html"><code>JobResult</code></a> <code>data</code> field is available as <code>self.results</code>.</p>
5202
+ <div class="admonition version-removed">
5203
+ <p class="admonition-title">Removed in version 2.0.0</p>
5204
+ <p>The NetBox backwards compatible <code>test_*()</code> and <code>post_run()</code> methods have been removed.</p>
5205
+ </div>
3953
5206
  <h3 id="logging">Logging<a class="headerlink" href="#logging" title="Permanent link">&para;</a></h3>
3954
- <p>The following instance methods are available to log results from an executing job to be stored into <a href="../models/extras/joblogentry.html"><code>JobLogEntry</code></a> records associated with the current <a href="../models/extras/jobresult.html"><code>JobResult</code></a>:</p>
3955
- <ul>
3956
- <li><code>self.log(message)</code></li>
3957
- <li><code>self.log_debug(message)</code></li>
3958
- <li><code>self.log_success(obj=None, message=None)</code></li>
3959
- <li><code>self.log_info(obj=None, message=None)</code></li>
3960
- <li><code>self.log_warning(obj=None, message=None)</code></li>
3961
- <li><code>self.log_failure(obj=None, message=None)</code></li>
3962
- </ul>
3963
- <p>Messages recorded with <code>log()</code> or <code>log_debug()</code> will appear in a job's results but are never associated with a particular object; the other <code>log_*</code> functions may be invoked with or without a provided object to associate the message with.</p>
3964
- <p>It is advised to log a message for each object that is evaluated so that the results will reflect how many objects are being manipulated or reported on.</p>
5207
+ <div class="admonition version-changed">
5208
+ <p class="admonition-title">Changed in version 2.0.0</p>
5209
+ </div>
5210
+ <p>Messages logged from a job's logger will be stored in <a href="../models/extras/joblogentry.html"><code>JobLogEntry</code></a> records associated with the current <a href="../models/extras/jobresult.html"><code>JobResult</code></a>.</p>
5211
+ <p>The logger can be accessed either by using the <code>logger</code> property on the job class or <code>nautobot.extras.jobs.get_task_logger(__name__)</code>. Both will return the same logger instance. For more information on the standard Python logging module, see the <a href="https://docs.python.org/3/library/logging.html">Python documentation</a>.</p>
5212
+ <p>An optional <code>grouping</code> and/or <code>object</code> may be provided in log messages by passing them in the log function call's <code>extra</code> kwarg. If a <code>grouping</code> is not provided it will default to the function name that logged the message. The <code>object</code> will default to <code>None</code>.</p>
5213
+ <div class="admonition example">
5214
+ <p class="admonition-title">Example</p>
5215
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">BaseJob</span>
5216
+ <a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a>
5217
+ <a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">BaseJob</span><span class="p">):</span>
5218
+ <a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
5219
+ <a id="__codelineno-12-5" name="__codelineno-12-5" href="#__codelineno-12-5"></a> <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;This job is running!&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;grouping&quot;</span><span class="p">:</span> <span class="s2">&quot;myjobisrunning&quot;</span><span class="p">,</span> <span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">job_result</span><span class="p">})</span>
5220
+ </code></pre></div>
5221
+ </div>
5222
+ <p>To skip writing a log entry to the database, set the <code>skip_db_logging</code> key in the "extra" kwarg to <code>True</code> when calling the log function. The output will still be written to the console.</p>
5223
+ <div class="admonition example">
5224
+ <p class="admonition-title">Example</p>
5225
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">BaseJob</span>
5226
+ <a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a>
5227
+ <a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">BaseJob</span><span class="p">):</span>
5228
+ <a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
5229
+ <a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a> <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;This job is running!&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;skip_db_logging&quot;</span><span class="p">:</span> <span class="kc">True</span><span class="p">})</span>
5230
+ </code></pre></div>
5231
+ </div>
3965
5232
  <p>Markdown rendering is supported for log messages.</p>
3966
5233
  <div class="admonition version-changed">
3967
5234
  <p class="admonition-title">Changed in version 1.3.4</p>
3968
5235
  <p>As a security measure, the <code>message</code> passed to any of these methods will be passed through the <code>nautobot.core.utils.logging.sanitize()</code> function in an attempt to strip out information such as usernames/passwords that should not be saved to the logs. This is of course best-effort only, and Job authors should take pains to ensure that such information is not passed to the logging APIs in the first place. The set of redaction rules used by the <code>sanitize()</code> function can be configured as <a href="../configuration/optional-settings.html#sanitizer_patterns">settings.SANITIZER_PATTERNS</a>.</p>
3969
5236
  </div>
3970
- <div class="admonition note">
3971
- <p class="admonition-title">Note</p>
3972
- <p>Using <code>self.log_failure()</code>, in addition to recording a log message, will flag the overall job as failed, but it will <strong>not</strong> stop the execution of the job, nor will it result in an automatic rollback of any database changes made by the job. To end a job early, you can use a Python <code>raise</code> or <code>return</code> as appropriate. Raising any exception (e.g. <code>ValueError</code> for malformed input values) will ensure that any database changes are rolled back as part of the process of ending the job. <code>AbortTransaction</code> from Nautobot, which was recommended in past versions of the docs, should explicitly <strong>not</strong> be used, as it is only intended for use by Nautobot's internal job handling.</p>
5237
+ <div class="admonition version-changed">
5238
+ <p class="admonition-title">Changed in version 2.0.0</p>
5239
+ <p>The Job class logging functions (example: <code>self.log(message)</code>, <code>self.log_success(obj=None, message=message)</code>, etc) have been removed. Also, the convenience method to mark a job as failed, <code>log_failure()</code>, has been removed. To replace the functionality of this method, you can log an error message with <code>self.logger.error()</code> and then raise an exception to fail the job. Note that it is no longer possible to manually set the job result status as failed without raising an exception in the job.</p>
3973
5240
  </div>
3974
5241
  <div class="admonition version-changed">
3975
5242
  <p class="admonition-title">Changed in version 2.0.0</p>
3976
5243
  <p>The <code>AbortTransaction</code> class was moved from the <code>nautobot.utilities.exceptions</code> module to <code>nautobot.core.exceptions</code>.</p>
3977
5244
  </div>
3978
- <h3 id="accessing-request-data">Accessing Request Data<a class="headerlink" href="#accessing-request-data" title="Permanent link">&para;</a></h3>
3979
- <p>Details of the current HTTP request (the one being made to execute the job) are available as the instance attribute <code>self.request</code>. This can be used to infer, for example, the user executing the job and their client IP address:</p>
3980
- <div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="n">username</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">username</span>
3981
- <a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a><span class="n">ip_address</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;HTTP_X_FORWARDED_FOR&#39;</span><span class="p">)</span> <span class="ow">or</span> \
3982
- <a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a> <span class="bp">self</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">META</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;REMOTE_ADDR&#39;</span><span class="p">)</span>
3983
- <a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a><span class="bp">self</span><span class="o">.</span><span class="n">log_info</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Running as user </span><span class="si">{</span><span class="n">username</span><span class="si">}</span><span class="s2"> (IP: </span><span class="si">{</span><span class="n">ip_address</span><span class="si">}</span><span class="s2">)...&quot;</span><span class="p">)</span>
5245
+ <h3 id="marking-a-job-as-failed">Marking a Job as Failed<a class="headerlink" href="#marking-a-job-as-failed" title="Permanent link">&para;</a></h3>
5246
+ <p>To mark a job as failed, raise an exception from within the <code>run()</code> method. The exception message will be logged to the traceback of the job result. The job result status will be set to <code>failed</code>. To output a job log message you can use the <code>self.logger.error()</code> method.</p>
5247
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="n">As</span> <span class="n">an</span> <span class="n">example</span><span class="p">,</span> <span class="n">the</span> <span class="n">following</span> <span class="n">job</span> <span class="n">will</span> <span class="n">fail</span> <span class="k">if</span> <span class="n">the</span> <span class="n">user</span> <span class="n">does</span> <span class="ow">not</span> <span class="n">put</span> <span class="n">the</span> <span class="n">word</span> <span class="s2">&quot;Taco&quot;</span> <span class="ow">in</span> <span class="err">`</span><span class="n">var1</span><span class="err">`</span><span class="p">:</span>
5248
+ <a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a>
5249
+ <a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a><span class="err">```</span><span class="n">python</span>
5250
+ <a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span>
5251
+ <a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a>
5252
+ <a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a><span class="k">class</span> <span class="nc">MyJob</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
5253
+ <a id="__codelineno-14-7" name="__codelineno-14-7" href="#__codelineno-14-7"></a> <span class="n">var1</span> <span class="o">=</span> <span class="n">StringVar</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
5254
+ <a id="__codelineno-14-8" name="__codelineno-14-8" href="#__codelineno-14-8"></a>
5255
+ <a id="__codelineno-14-9" name="__codelineno-14-9" href="#__codelineno-14-9"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">var1</span><span class="p">):</span>
5256
+ <a id="__codelineno-14-10" name="__codelineno-14-10" href="#__codelineno-14-10"></a> <span class="k">if</span> <span class="n">var1</span> <span class="o">!=</span> <span class="s2">&quot;Taco&quot;</span><span class="p">:</span>
5257
+ <a id="__codelineno-14-11" name="__codelineno-14-11" href="#__codelineno-14-11"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span><span class="s2">&quot;var1 must be &#39;Taco&#39;&quot;</span><span class="p">)</span>
5258
+ <a id="__codelineno-14-12" name="__codelineno-14-12" href="#__codelineno-14-12"></a> <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">&quot;Argument input validation failed.&quot;</span><span class="p">)</span>
5259
+ </code></pre></div>
5260
+ <h3 id="accessing-user-and-job-result">Accessing User and Job Result<a class="headerlink" href="#accessing-user-and-job-result" title="Permanent link">&para;</a></h3>
5261
+ <div class="admonition version-changed">
5262
+ <p class="admonition-title">Changed in version 2.0.0</p>
5263
+ <p>The web request is no longer accessible to running jobs.</p>
5264
+ </div>
5265
+ <p>The user that initiated the job and the job result associated to the job can be accessed through properties on the job class:</p>
5266
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="n">username</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="o">.</span><span class="n">username</span>
5267
+ <a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a><span class="n">job_result_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">job_result</span><span class="o">.</span><span class="n">id</span>
5268
+ <a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a><span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Job </span><span class="si">%s</span><span class="s2"> initiated by user </span><span class="si">%s</span><span class="s2"> is running.&quot;</span><span class="p">,</span> <span class="n">job_result_id</span><span class="p">,</span> <span class="n">username</span><span class="p">)</span>
3984
5269
  </code></pre></div>
3985
- <p>For a complete list of available request parameters, please see the <a href="https://docs.djangoproject.com/en/stable/ref/request-response/">Django documentation</a>.</p>
3986
5270
  <h3 id="reading-data-from-files">Reading Data from Files<a class="headerlink" href="#reading-data-from-files" title="Permanent link">&para;</a></h3>
3987
5271
  <p>The <code>Job</code> class provides two convenience methods for reading data from files:</p>
3988
5272
  <ul>
@@ -4006,10 +5290,9 @@ default <a href="../configuration/optional-settings.html#celery_task_time_limit"
4006
5290
  <li><code>name</code></li>
4007
5291
  <li><code>description</code></li>
4008
5292
  <li><code>approval_required</code></li>
4009
- <li><code>commit_default</code></li>
5293
+ <li><code>dryrun_default</code></li>
4010
5294
  <li><code>has_sensitive_variables</code></li>
4011
5295
  <li><code>hidden</code></li>
4012
- <li><code>read_only</code></li>
4013
5296
  <li><code>soft_time_limit</code></li>
4014
5297
  <li><code>time_limit</code></li>
4015
5298
  <li><code>task_queues</code></li>
@@ -4043,21 +5326,25 @@ elements will be important in running jobs programmatically.</p>
4043
5326
  <p>Jobs can be run via the web UI by navigating to the job, completing any required form data (if any), and clicking the "Run Job" button.</p>
4044
5327
  <p>Once a job has been run, the latest <a href="../models/extras/jobresult.html"><code>JobResult</code></a> for that job will be summarized in the job list view.</p>
4045
5328
  <h3 id="via-the-api">Via the API<a class="headerlink" href="#via-the-api" title="Permanent link">&para;</a></h3>
4046
- <p>To run a job via the REST API, issue a POST request to the job's endpoint <code>/api/extras/jobs/&lt;uuid&gt;/run/</code>. You can optionally provide JSON data to set the <code>commit</code> flag, specify any required user input <code>data</code>, optional <code>task_queue</code>, and/or provide optional scheduling information as described in <a href="job-scheduling-and-approvals.html">the section on scheduling and approvals</a>.</p>
4047
- <p>For example, to run a job with no user inputs and without committing any anything to the database:</p>
4048
- <div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a>curl -X POST \
4049
- <a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a>-H &quot;Authorization: Token $TOKEN&quot; \
4050
- <a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a>-H &quot;Content-Type: application/json&quot; \
4051
- <a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
4052
- <a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a>http://nautobot/api/extras/jobs/$JOB_ID/run/
5329
+ <div class="admonition version-removed">
5330
+ <p class="admonition-title">Removed in version 2.0.0</p>
5331
+ <p>The <code>commit</code> parameter was removed. All job input should be provided via the <code>data</code> parameter.</p>
5332
+ </div>
5333
+ <p>To run a job via the REST API, issue a POST request to the job's endpoint <code>/api/extras/jobs/&lt;uuid&gt;/run/</code>. You can optionally provide JSON data to specify any required user input <code>data</code>, optional <code>task_queue</code>, and/or provide optional scheduling information as described in <a href="job-scheduling-and-approvals.html">the section on scheduling and approvals</a>.</p>
5334
+ <p>For example, to run a job with no user inputs:</p>
5335
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a>curl -X POST \
5336
+ <a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>-H &quot;Authorization: Token $TOKEN&quot; \
5337
+ <a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a>-H &quot;Content-Type: application/json&quot; \
5338
+ <a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
5339
+ <a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a>http://nautobot/api/extras/jobs/$JOB_ID/run/
4053
5340
  </code></pre></div>
4054
- <p>Or to run a job that expects user inputs, and commit changes to the database:</p>
4055
- <div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a>curl -X POST \
4056
- <a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a>-H &quot;Authorization: Token $TOKEN&quot; \
4057
- <a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a>-H &quot;Content-Type: application/json&quot; \
4058
- <a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
4059
- <a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a>http://nautobot/api/extras/jobs/$JOB_ID/run/ \
4060
- <a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a>--data &#39;{&quot;data&quot;: {&quot;string_variable&quot;: &quot;somevalue&quot;, &quot;integer_variable&quot;: 123}, &quot;commit&quot;: true}&#39;
5341
+ <p>Or to run a job that expects user inputs:</p>
5342
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a>curl -X POST \
5343
+ <a id="__codelineno-17-2" name="__codelineno-17-2" href="#__codelineno-17-2"></a>-H &quot;Authorization: Token $TOKEN&quot; \
5344
+ <a id="__codelineno-17-3" name="__codelineno-17-3" href="#__codelineno-17-3"></a>-H &quot;Content-Type: application/json&quot; \
5345
+ <a id="__codelineno-17-4" name="__codelineno-17-4" href="#__codelineno-17-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
5346
+ <a id="__codelineno-17-5" name="__codelineno-17-5" href="#__codelineno-17-5"></a>http://nautobot/api/extras/jobs/$JOB_ID/run/ \
5347
+ <a id="__codelineno-17-6" name="__codelineno-17-6" href="#__codelineno-17-6"></a>--data &#39;{&quot;data&quot;: {&quot;string_variable&quot;: &quot;somevalue&quot;, &quot;integer_variable&quot;: 123}}&#39;
4061
5348
  </code></pre></div>
4062
5349
  <p>When providing input data, it is possible to specify complex values contained in <code>ObjectVar</code>s, <code>MultiObjectVar</code>s, and <code>IPAddressVar</code>s.</p>
4063
5350
  <ul>
@@ -4066,22 +5353,21 @@ elements will be important in running jobs programmatically.</p>
4066
5353
  <li><code>IPAddressVar</code>s can be provided as strings in CIDR notation.</li>
4067
5354
  </ul>
4068
5355
  <h4 id="jobs-with-files">Jobs with Files<a class="headerlink" href="#jobs-with-files" title="Permanent link">&para;</a></h4>
4069
- <p>To run a job that contains <code>FileVar</code> inputs via the REST API, you must use <code>multipart/form-data</code> content type requests instead of <code>application/json</code>. This also requires a slightly different request payload than the example above. The <code>commit</code>, <code>task_queue</code>, and <code>schedule</code> data are flattened and prefixed with underscore to differentiate them from job-specific data. Job specific data is also flattened and not located under the top-level <code>data</code> dictionary key.</p>
5356
+ <p>To run a job that contains <code>FileVar</code> inputs via the REST API, you must use <code>multipart/form-data</code> content type requests instead of <code>application/json</code>. This also requires a slightly different request payload than the example above. The <code>task_queue</code> and <code>schedule</code> data are flattened and prefixed with underscore to differentiate them from job-specific data. Job specific data is also flattened and not located under the top-level <code>data</code> dictionary key.</p>
4070
5357
  <p>An example of running a job with both <code>FileVar</code> (named <code>myfile</code>) and <code>StringVar</code> (named <code>interval</code>) input:</p>
4071
- <div class="highlight"><pre><span></span><code><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a>curl -X POST \
4072
- <a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>-H &#39;Authorization: Token $TOKEN&#39; \
4073
- <a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a>-H &#39;Content-Type: multipart/form-data&#39; \
4074
- <a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
4075
- <a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a>&#39;http://nautobot/api/extras/jobs/$JOB_ID/run/&#39; \
4076
- <a id="__codelineno-16-6" name="__codelineno-16-6" href="#__codelineno-16-6"></a>-F &#39;_commit=&quot;true&quot;&#39; \
4077
- <a id="__codelineno-16-7" name="__codelineno-16-7" href="#__codelineno-16-7"></a>-F &#39;_schedule_interval=&quot;immediately&quot;&#39; \
4078
- <a id="__codelineno-16-8" name="__codelineno-16-8" href="#__codelineno-16-8"></a>-F &#39;_schedule_start_time=&quot;2022-10-18T17:31:23.698Z&quot;&#39; \
4079
- <a id="__codelineno-16-9" name="__codelineno-16-9" href="#__codelineno-16-9"></a>-F &#39;interval=&quot;3&quot;&#39; \
4080
- <a id="__codelineno-16-10" name="__codelineno-16-10" href="#__codelineno-16-10"></a>-F &#39;myfile=@&quot;/path/to/my/file.txt&quot;&#39; \
5358
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a>curl -X POST \
5359
+ <a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a>-H &#39;Authorization: Token $TOKEN&#39; \
5360
+ <a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a>-H &#39;Content-Type: multipart/form-data&#39; \
5361
+ <a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a>-H &quot;Accept: application/json; version=1.3; indent=4&quot; \
5362
+ <a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a>&#39;http://nautobot/api/extras/jobs/$JOB_ID/run/&#39; \
5363
+ <a id="__codelineno-18-6" name="__codelineno-18-6" href="#__codelineno-18-6"></a>-F &#39;_schedule_interval=&quot;immediately&quot;&#39; \
5364
+ <a id="__codelineno-18-7" name="__codelineno-18-7" href="#__codelineno-18-7"></a>-F &#39;_schedule_start_time=&quot;2022-10-18T17:31:23.698Z&quot;&#39; \
5365
+ <a id="__codelineno-18-8" name="__codelineno-18-8" href="#__codelineno-18-8"></a>-F &#39;interval=&quot;3&quot;&#39; \
5366
+ <a id="__codelineno-18-9" name="__codelineno-18-9" href="#__codelineno-18-9"></a>-F &#39;myfile=@&quot;/path/to/my/file.txt&quot;&#39; \
4081
5367
  </code></pre></div>
4082
5368
  <h3 id="via-the-cli">Via the CLI<a class="headerlink" href="#via-the-cli" title="Permanent link">&para;</a></h3>
4083
5369
  <p>Jobs can be run from the CLI by invoking the management command:</p>
4084
- <div class="highlight"><pre><span></span><code><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a>nautobot-server runjob [--username &lt;username&gt;] [--commit] [--local] [--data &lt;data&gt;] &lt;class_path&gt;
5370
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a>nautobot-server runjob [--username &lt;username&gt;] [--local] [--data &lt;data&gt;] &lt;class_path&gt;
4085
5371
  </code></pre></div>
4086
5372
  <div class="admonition note">
4087
5373
  <p class="admonition-title">Note</p>
@@ -4093,177 +5379,127 @@ elements will be important in running jobs programmatically.</p>
4093
5379
  <p>The <code>--data</code> parameter must be a JSON string, e.g. <code>--data='{"string_variable": "somevalue", "integer_variable": 123}'</code></p>
4094
5380
  </div>
4095
5381
  <p>Using the same example shown in the API:</p>
4096
- <div class="highlight"><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a>nautobot-server runjob --username myusername local/example/MyJobWithNoVars
5382
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a>nautobot-server runjob --username myusername local/example/MyJobWithNoVars
4097
5383
  </code></pre></div>
4098
5384
  <div class="admonition warning">
4099
5385
  <p class="admonition-title">Warning</p>
4100
- <p>The <code>--username &lt;username&gt;</code> parameter can be used to specify the user that will be identified as the requester of the job. It is optional if the job will not be modifying the database, but is mandatory if you are running with <code>--commit</code>, as the specified user will own any resulting database changes.</p>
5386
+ <p>The <code>--username &lt;username&gt;</code> must be supplied to specify the user that will be identified as the requester of the job.</p>
4101
5387
  <p>Note that <code>nautobot-server</code> commands, like all management commands and other direct interactions with the Django database, are not gated by the usual Nautobot user authentication flow. It is possible to specify any existing <code>--username</code> with the <code>nautobot-server runjob</code> command in order to impersonate any defined user in Nautobot. Use this power wisely and be cautious who you allow to access it.</p>
4102
5388
  </div>
4103
5389
  <h2 id="testing-jobs">Testing Jobs<a class="headerlink" href="#testing-jobs" title="Permanent link">&para;</a></h2>
4104
5390
  <p>Jobs are Python code and can be tested as such, usually via <a href="https://docs.djangoproject.com/en/stable/topics/testing/">Django unit-test features</a>. That said, there are a few useful tricks specific to testing Jobs.</p>
4105
5391
  <p>While individual methods within your Job can and should be tested in isolation, you'll likely also want to test the entire execution of the Job. Nautobot 1.3.3 introduced a few enhancements to make this simpler to do, but it's also quite possible to test in earlier releases with a bit more effort.</p>
4106
5392
  <h3 id="nautobot-133-and-later">Nautobot 1.3.3 and later<a class="headerlink" href="#nautobot-133-and-later" title="Permanent link">&para;</a></h3>
4107
- <p>The simplest way to test the entire execution of Jobs from 1.3.3 on is via calling the <code>nautobot.core.testing.run_job_for_testing()</code> method, which is a helper wrapper around the <code>run_job</code> function used to execute a Job via Nautobot's Celery worker process.</p>
5393
+ <p>The simplest way to test the entire execution of Jobs from 1.3.3 on is via calling the <code>nautobot.core.testing.run_job_for_testing()</code> method, which is a helper wrapper around the <code>JobResult.enqueue_job</code> function used to execute a Job via Nautobot's Celery worker process.</p>
4108
5394
  <div class="admonition version-changed">
4109
5395
  <p class="admonition-title">Changed in version 2.0.0</p>
4110
5396
  <p><code>run_job_for_testing</code> was moved from the <code>nautobot.utilities.testing</code> module to <code>nautobot.core.testing</code>.</p>
4111
5397
  </div>
4112
- <p>Because of the way <code>run_job_for_testing</code> and more specifically <code>run_job()</code> works, which is somewhat complex behind the scenes, you need to inherit from <code>nautobot.core.testing.TransactionTestCase</code> instead of <code>django.test.TestCase</code> (Refer to the <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#provided-test-case-classes">Django documentation</a> if you're interested in the differences between these classes - <code>TransactionTestCase</code> from Nautobot is a small wrapper around Django's <code>TransactionTestCase</code>).</p>
5398
+ <p>Because of the way <code>run_job_for_testing</code> and more specifically Celery tasks work, which is somewhat complex behind the scenes, you need to inherit from <code>nautobot.core.testing.TransactionTestCase</code> instead of <code>django.test.TestCase</code> (Refer to the <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#provided-test-case-classes">Django documentation</a> if you're interested in the differences between these classes - <code>TransactionTestCase</code> from Nautobot is a small wrapper around Django's <code>TransactionTestCase</code>).</p>
4113
5399
  <p>When using <code>TransactionTestCase</code> (whether from Django or from Nautobot) each tests runs on a completely empty database. Furthermore, Nautobot requires new jobs to be enabled before they can run. Therefore, we need to make sure the job is enabled before each run which <code>run_job_for_testing</code> handles for us.</p>
4114
5400
  <p>A simple example of a Job test case for 1.3.3 and forward might look like the following:</p>
4115
- <div class="highlight"><pre><span></span><code><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a><span class="kn">from</span> <span class="nn">nautobot.core.testing</span> <span class="kn">import</span> <span class="n">run_job_for_testing</span><span class="p">,</span> <span class="n">TransactionTestCase</span>
4116
- <a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">JobLogEntry</span>
4117
- <a id="__codelineno-19-3" name="__codelineno-19-3" href="#__codelineno-19-3"></a>
4118
- <a id="__codelineno-19-4" name="__codelineno-19-4" href="#__codelineno-19-4"></a>
4119
- <a id="__codelineno-19-5" name="__codelineno-19-5" href="#__codelineno-19-5"></a><span class="k">class</span> <span class="nc">MyJobTestCase</span><span class="p">(</span><span class="n">TransactionTestCase</span><span class="p">):</span>
4120
- <a id="__codelineno-19-6" name="__codelineno-19-6" href="#__codelineno-19-6"></a> <span class="k">def</span> <span class="nf">test_my_job</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
4121
- <a id="__codelineno-19-7" name="__codelineno-19-7" href="#__codelineno-19-7"></a> <span class="c1"># Testing of Job &quot;MyJob&quot; in file &quot;my_job_file.py&quot; in $JOBS_ROOT</span>
4122
- <a id="__codelineno-19-8" name="__codelineno-19-8" href="#__codelineno-19-8"></a> <span class="n">job</span> <span class="o">=</span> <span class="n">Job</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">job_class_name</span><span class="o">=</span><span class="s2">&quot;MyJob&quot;</span><span class="p">,</span> <span class="n">module_name</span><span class="o">=</span><span class="s2">&quot;my_job_file&quot;</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="s2">&quot;local&quot;</span><span class="p">)</span>
4123
- <a id="__codelineno-19-9" name="__codelineno-19-9" href="#__codelineno-19-9"></a> <span class="c1"># or, job = Job.objects.get_for_class_path(&quot;local/my_job_file/MyJob&quot;)</span>
4124
- <a id="__codelineno-19-10" name="__codelineno-19-10" href="#__codelineno-19-10"></a> <span class="n">job_result</span> <span class="o">=</span> <span class="n">run_job_for_testing</span><span class="p">(</span><span class="n">job</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="p">{},</span> <span class="n">commit</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
4125
- <a id="__codelineno-19-11" name="__codelineno-19-11" href="#__codelineno-19-11"></a>
4126
- <a id="__codelineno-19-12" name="__codelineno-19-12" href="#__codelineno-19-12"></a> <span class="c1"># Since we ran with commit=False, any database changes made by the job won&#39;t persist,</span>
4127
- <a id="__codelineno-19-13" name="__codelineno-19-13" href="#__codelineno-19-13"></a> <span class="c1"># but we can still inspect the logs created by running the job</span>
4128
- <a id="__codelineno-19-14" name="__codelineno-19-14" href="#__codelineno-19-14"></a> <span class="n">log_entries</span> <span class="o">=</span> <span class="n">JobLogEntry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">job_result</span><span class="o">=</span><span class="n">job_result</span><span class="p">)</span>
4129
- <a id="__codelineno-19-15" name="__codelineno-19-15" href="#__codelineno-19-15"></a> <span class="k">for</span> <span class="n">log_entry</span> <span class="ow">in</span> <span class="n">log_entries</span><span class="p">:</span>
4130
- <a id="__codelineno-19-16" name="__codelineno-19-16" href="#__codelineno-19-16"></a> <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">log_entry</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="s2">&quot;...&quot;</span><span class="p">)</span>
5401
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a><span class="kn">from</span> <span class="nn">nautobot.core.testing</span> <span class="kn">import</span> <span class="n">run_job_for_testing</span><span class="p">,</span> <span class="n">TransactionTestCase</span>
5402
+ <a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-2"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">JobLogEntry</span>
5403
+ <a id="__codelineno-21-3" name="__codelineno-21-3" href="#__codelineno-21-3"></a>
5404
+ <a id="__codelineno-21-4" name="__codelineno-21-4" href="#__codelineno-21-4"></a>
5405
+ <a id="__codelineno-21-5" name="__codelineno-21-5" href="#__codelineno-21-5"></a><span class="k">class</span> <span class="nc">MyJobTestCase</span><span class="p">(</span><span class="n">TransactionTestCase</span><span class="p">):</span>
5406
+ <a id="__codelineno-21-6" name="__codelineno-21-6" href="#__codelineno-21-6"></a> <span class="k">def</span> <span class="nf">test_my_job</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
5407
+ <a id="__codelineno-21-7" name="__codelineno-21-7" href="#__codelineno-21-7"></a> <span class="c1"># Testing of Job &quot;MyJob&quot; in file &quot;my_job_file.py&quot; in $JOBS_ROOT</span>
5408
+ <a id="__codelineno-21-8" name="__codelineno-21-8" href="#__codelineno-21-8"></a> <span class="n">job</span> <span class="o">=</span> <span class="n">Job</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">job_class_name</span><span class="o">=</span><span class="s2">&quot;MyJob&quot;</span><span class="p">,</span> <span class="n">module_name</span><span class="o">=</span><span class="s2">&quot;my_job_file&quot;</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="s2">&quot;local&quot;</span><span class="p">)</span>
5409
+ <a id="__codelineno-21-9" name="__codelineno-21-9" href="#__codelineno-21-9"></a> <span class="c1"># or, job = Job.objects.get_for_class_path(&quot;local/my_job_file/MyJob&quot;)</span>
5410
+ <a id="__codelineno-21-10" name="__codelineno-21-10" href="#__codelineno-21-10"></a> <span class="n">job_result</span> <span class="o">=</span> <span class="n">run_job_for_testing</span><span class="p">(</span><span class="n">job</span><span class="p">,</span> <span class="n">var1</span><span class="o">=</span><span class="s2">&quot;abc&quot;</span><span class="p">,</span> <span class="n">var2</span><span class="o">=</span><span class="mi">123</span><span class="p">)</span>
5411
+ <a id="__codelineno-21-11" name="__codelineno-21-11" href="#__codelineno-21-11"></a>
5412
+ <a id="__codelineno-21-12" name="__codelineno-21-12" href="#__codelineno-21-12"></a> <span class="c1"># Inspect the logs created by running the job</span>
5413
+ <a id="__codelineno-21-13" name="__codelineno-21-13" href="#__codelineno-21-13"></a> <span class="n">log_entries</span> <span class="o">=</span> <span class="n">JobLogEntry</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">job_result</span><span class="o">=</span><span class="n">job_result</span><span class="p">)</span>
5414
+ <a id="__codelineno-21-14" name="__codelineno-21-14" href="#__codelineno-21-14"></a> <span class="k">for</span> <span class="n">log_entry</span> <span class="ow">in</span> <span class="n">log_entries</span><span class="p">:</span>
5415
+ <a id="__codelineno-21-15" name="__codelineno-21-15" href="#__codelineno-21-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">log_entry</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="s2">&quot;...&quot;</span><span class="p">)</span>
4131
5416
  </code></pre></div>
4132
5417
  <div class="admonition tip">
4133
5418
  <p class="admonition-title">Tip</p>
4134
- <p>For more advanced examples (such as testing jobs executed with <code>commit=True</code>, for example) refer to the Nautobot source code, specifically <code>nautobot/extras/tests/test_jobs.py</code>.</p>
5419
+ <p>For more advanced examples refer to the Nautobot source code, specifically <code>nautobot/extras/tests/test_jobs.py</code>.</p>
4135
5420
  </div>
4136
- <h3 id="nautobot-132-and-earlier-including-12">Nautobot 1.3.2 and earlier (including 1.2)<a class="headerlink" href="#nautobot-132-and-earlier-including-12" title="Permanent link">&para;</a></h3>
4137
- <p>If your test case needs to be backwards-compatible with test execution against Nautobot 1.3.2 and/or earlier, you need to handle a couple more things manually:</p>
4138
- <p>Set up the <code>"job_logs"</code> database correctly for testing:</p>
4139
- <div class="highlight"><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
4140
- <a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a>
4141
- <a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="k">if</span> <span class="s2">&quot;job_logs&quot;</span> <span class="ow">in</span> <span class="n">settings</span><span class="o">.</span><span class="n">DATABASES</span><span class="p">:</span>
4142
- <a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a> <span class="n">settings</span><span class="o">.</span><span class="n">DATABASES</span><span class="p">[</span><span class="s2">&quot;job_logs&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">DATABASES</span><span class="p">[</span><span class="s2">&quot;job_logs&quot;</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
4143
- <a id="__codelineno-20-5" name="__codelineno-20-5" href="#__codelineno-20-5"></a> <span class="n">settings</span><span class="o">.</span><span class="n">DATABASES</span><span class="p">[</span><span class="s2">&quot;job_logs&quot;</span><span class="p">][</span><span class="s2">&quot;TEST&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;MIRROR&quot;</span><span class="p">:</span> <span class="s2">&quot;default&quot;</span><span class="p">}</span>
4144
- </code></pre></div>
4145
- <p>Replicate the behavior of <code>run_job_for_testing</code> manually so that your test execution most closely resembles the way the celery worker would run the test:</p>
4146
- <div class="highlight"><pre><span></span><code><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a><span class="kn">import</span> <span class="nn">uuid</span>
4147
- <a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-2"></a><span class="kn">from</span> <span class="nn">django.contrib.auth</span> <span class="kn">import</span> <span class="n">get_user_model</span>
4148
- <a id="__codelineno-21-3" name="__codelineno-21-3" href="#__codelineno-21-3"></a><span class="kn">from</span> <span class="nn">django.contrib.contenttypes.models</span> <span class="kn">import</span> <span class="n">ContentType</span>
4149
- <a id="__codelineno-21-4" name="__codelineno-21-4" href="#__codelineno-21-4"></a>
4150
- <a id="__codelineno-21-5" name="__codelineno-21-5" href="#__codelineno-21-5"></a><span class="kn">from</span> <span class="nn">nautobot.extras.context_managers</span> <span class="kn">import</span> <span class="n">web_request_context</span>
4151
- <a id="__codelineno-21-6" name="__codelineno-21-6" href="#__codelineno-21-6"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">run_job</span>
4152
- <a id="__codelineno-21-7" name="__codelineno-21-7" href="#__codelineno-21-7"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">JobResult</span><span class="p">,</span> <span class="n">Job</span>
4153
- <a id="__codelineno-21-8" name="__codelineno-21-8" href="#__codelineno-21-8"></a>
4154
- <a id="__codelineno-21-9" name="__codelineno-21-9" href="#__codelineno-21-9"></a><span class="k">def</span> <span class="nf">run_job_for_testing</span><span class="p">(</span><span class="n">job</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">commit</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">username</span><span class="o">=</span><span class="s2">&quot;test-user&quot;</span><span class="p">):</span>
4155
- <a id="__codelineno-21-10" name="__codelineno-21-10" href="#__codelineno-21-10"></a> <span class="k">if</span> <span class="n">data</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
4156
- <a id="__codelineno-21-11" name="__codelineno-21-11" href="#__codelineno-21-11"></a> <span class="n">data</span> <span class="o">=</span> <span class="p">{}</span>
4157
- <a id="__codelineno-21-12" name="__codelineno-21-12" href="#__codelineno-21-12"></a> <span class="n">user_model</span> <span class="o">=</span> <span class="n">get_user_model</span><span class="p">()</span>
4158
- <a id="__codelineno-21-13" name="__codelineno-21-13" href="#__codelineno-21-13"></a> <span class="n">user</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">user_model</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_or_create</span><span class="p">(</span><span class="n">username</span><span class="o">=</span><span class="n">username</span><span class="p">,</span> <span class="n">is_superuser</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">password</span><span class="o">=</span><span class="s2">&quot;password&quot;</span><span class="p">)</span>
4159
- <a id="__codelineno-21-14" name="__codelineno-21-14" href="#__codelineno-21-14"></a> <span class="n">job_result</span> <span class="o">=</span> <span class="n">JobResult</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
4160
- <a id="__codelineno-21-15" name="__codelineno-21-15" href="#__codelineno-21-15"></a> <span class="n">name</span><span class="o">=</span><span class="n">job</span><span class="o">.</span><span class="n">class_path</span><span class="p">,</span>
4161
- <a id="__codelineno-21-16" name="__codelineno-21-16" href="#__codelineno-21-16"></a> <span class="n">obj_type</span><span class="o">=</span><span class="n">ContentType</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_for_model</span><span class="p">(</span><span class="n">Job</span><span class="p">),</span>
4162
- <a id="__codelineno-21-17" name="__codelineno-21-17" href="#__codelineno-21-17"></a> <span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">,</span>
4163
- <a id="__codelineno-21-18" name="__codelineno-21-18" href="#__codelineno-21-18"></a> <span class="n">task_id</span><span class="o">=</span><span class="n">uuid</span><span class="o">.</span><span class="n">uuid4</span><span class="p">(),</span>
4164
- <a id="__codelineno-21-19" name="__codelineno-21-19" href="#__codelineno-21-19"></a> <span class="p">)</span>
4165
- <a id="__codelineno-21-20" name="__codelineno-21-20" href="#__codelineno-21-20"></a> <span class="k">with</span> <span class="n">web_request_context</span><span class="p">(</span><span class="n">user</span><span class="o">=</span><span class="n">user</span><span class="p">)</span> <span class="k">as</span> <span class="n">request</span><span class="p">:</span>
4166
- <a id="__codelineno-21-21" name="__codelineno-21-21" href="#__codelineno-21-21"></a> <span class="n">run_job</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">,</span> <span class="n">request</span><span class="o">=</span><span class="n">request</span><span class="p">,</span> <span class="n">commit</span><span class="o">=</span><span class="n">commit</span><span class="p">,</span> <span class="n">job_result_pk</span><span class="o">=</span><span class="n">job_result</span><span class="o">.</span><span class="n">pk</span><span class="p">)</span>
4167
- <a id="__codelineno-21-22" name="__codelineno-21-22" href="#__codelineno-21-22"></a> <span class="k">return</span> <span class="n">job_result</span>
4168
- </code></pre></div>
4169
- <p>Setup the <code>databases</code> field on the test class correctly, and re-create the default Statuses on <code>setUp</code> in your test classes, because <code>django.test.TransactionTestCase</code> truncates them on every <code>tearDown</code>:</p>
4170
- <div class="highlight"><pre><span></span><code><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a><span class="kn">from</span> <span class="nn">django.apps</span> <span class="kn">import</span> <span class="n">apps</span>
4171
- <a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a><span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
4172
- <a id="__codelineno-22-3" name="__codelineno-22-3" href="#__codelineno-22-3"></a><span class="kn">from</span> <span class="nn">django.test</span> <span class="kn">import</span> <span class="n">TransactionTestCase</span>
4173
- <a id="__codelineno-22-4" name="__codelineno-22-4" href="#__codelineno-22-4"></a>
4174
- <a id="__codelineno-22-5" name="__codelineno-22-5" href="#__codelineno-22-5"></a><span class="kn">from</span> <span class="nn">nautobot.extras.management</span> <span class="kn">import</span> <span class="n">populate_status_choices</span>
4175
- <a id="__codelineno-22-6" name="__codelineno-22-6" href="#__codelineno-22-6"></a>
4176
- <a id="__codelineno-22-7" name="__codelineno-22-7" href="#__codelineno-22-7"></a><span class="k">class</span> <span class="nc">MyJobTestCase</span><span class="p">(</span><span class="n">TransactionTestCase</span><span class="p">):</span>
4177
- <a id="__codelineno-22-8" name="__codelineno-22-8" href="#__codelineno-22-8"></a> <span class="c1"># &#39;job_logs&#39; is a proxy connection to the same (default) database that&#39;s used exclusively for Job logging</span>
4178
- <a id="__codelineno-22-9" name="__codelineno-22-9" href="#__codelineno-22-9"></a> <span class="k">if</span> <span class="s2">&quot;job_logs&quot;</span> <span class="ow">in</span> <span class="n">settings</span><span class="o">.</span><span class="n">DATABASES</span><span class="p">:</span>
4179
- <a id="__codelineno-22-10" name="__codelineno-22-10" href="#__codelineno-22-10"></a> <span class="n">databases</span> <span class="o">=</span> <span class="p">(</span><span class="s2">&quot;default&quot;</span><span class="p">,</span> <span class="s2">&quot;job_logs&quot;</span><span class="p">)</span>
4180
- <a id="__codelineno-22-11" name="__codelineno-22-11" href="#__codelineno-22-11"></a>
4181
- <a id="__codelineno-22-12" name="__codelineno-22-12" href="#__codelineno-22-12"></a> <span class="k">def</span> <span class="nf">setUp</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
4182
- <a id="__codelineno-22-13" name="__codelineno-22-13" href="#__codelineno-22-13"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">setUp</span><span class="p">()</span>
4183
- <a id="__codelineno-22-14" name="__codelineno-22-14" href="#__codelineno-22-14"></a> <span class="n">populate_status_choices</span><span class="p">(</span><span class="n">apps</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
5421
+ <h2 id="debugging-job-performance">Debugging job performance<a class="headerlink" href="#debugging-job-performance" title="Permanent link">&para;</a></h2>
5422
+ <div class="admonition version-added">
5423
+ <p class="admonition-title">Added in version 1.5.17</p>
5424
+ </div>
5425
+ <p>Debugging the performance of Nautobot jobs can be tricky, because they are executed in the worker context. In order to gain extra visibility, <a href="https://docs.python.org/3/library/profile.html">cProfile</a> can be used to profile the job execution.</p>
5426
+ <p>The 'profile' form field on jobs is automatically available when the <code>DEBUG</code> settings is <code>True</code>. When you select that checkbox, a profiling report in the pstats format will be written to the file system of the environment where the job runs. Normally, this is on the file system of the worker process, but if you are using the <code>nautobot-server runjob</code> command with <code>--local</code>, it will end up in the file system of the web application itself. The path of the written file will be logged in the job.</p>
5427
+ <div class="admonition note">
5428
+ <p class="admonition-title">Note</p>
5429
+ <p>If you need to run this in an environment where <code>DEBUG</code> is <code>False</code>, you have the option of using <code>nautobot-server runjob</code> with the <code>--profile</code> flag. According to the docs, <code>cProfile</code> should have minimal impact on the performance of the job; still, proceed with caution when using this in a production environment.</p>
5430
+ </div>
5431
+ <h3 id="reading-profiling-reports">Reading profiling reports<a class="headerlink" href="#reading-profiling-reports" title="Permanent link">&para;</a></h3>
5432
+ <p>A full description on how to deal with the output of <code>cProfile</code> can be found in the <a href="https://docs.python.org/3/library/profile.html#instant-user-s-manual">Instant User's Manual</a>, but here is something to get you started:</p>
5433
+ <div class="highlight"><pre><span></span><code><a id="__codelineno-22-1" name="__codelineno-22-1" href="#__codelineno-22-1"></a><span class="kn">import</span> <span class="nn">pstats</span>
5434
+ <a id="__codelineno-22-2" name="__codelineno-22-2" href="#__codelineno-22-2"></a><span class="n">job_result_uuid</span> <span class="o">=</span> <span class="s2">&quot;66b70231-002f-412b-8cc4-1cc9609c2c9b&quot;</span>
5435
+ <a id="__codelineno-22-3" name="__codelineno-22-3" href="#__codelineno-22-3"></a><span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;/tmp/job-result-</span><span class="si">{</span><span class="n">job_result_uuid</span><span class="si">}</span><span class="s2">.pstats&quot;</span><span class="p">)</span>
5436
+ <a id="__codelineno-22-4" name="__codelineno-22-4" href="#__codelineno-22-4"></a><span class="n">stats</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="n">pstats</span><span class="o">.</span><span class="n">SortKey</span><span class="o">.</span><span class="n">CUMULATIVE</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
4184
5437
  </code></pre></div>
5438
+ <p>This will print the 10 functions that the job execution spent the most time in - adapt this to your needs!</p>
4185
5439
  <h2 id="example-jobs">Example Jobs<a class="headerlink" href="#example-jobs" title="Permanent link">&para;</a></h2>
4186
- <h3 id="creating-objects-for-a-planned-site">Creating objects for a planned site<a class="headerlink" href="#creating-objects-for-a-planned-site" title="Permanent link">&para;</a></h3>
5440
+ <h3 id="creating-objects-for-a-planned-location">Creating objects for a planned location<a class="headerlink" href="#creating-objects-for-a-planned-location" title="Permanent link">&para;</a></h3>
4187
5441
  <p>This job prompts the user for three variables:</p>
4188
5442
  <ul>
4189
- <li>The name of the new site</li>
5443
+ <li>The name of the new location</li>
4190
5444
  <li>The device model (a filtered list of defined device types)</li>
4191
5445
  <li>The number of access switches to create</li>
4192
5446
  </ul>
4193
5447
  <p>These variables are presented as a web form to be completed by the user. Once submitted, the job's <code>run()</code> method is called to create the appropriate objects, and it returns simple CSV output to the user summarizing the created objects.</p>
4194
5448
  <div class="highlight"><pre><span></span><code><a id="__codelineno-23-1" name="__codelineno-23-1" href="#__codelineno-23-1"></a><span class="kn">from</span> <span class="nn">django.contrib.contenttypes.models</span> <span class="kn">import</span> <span class="n">ContentType</span>
4195
- <a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a><span class="kn">from</span> <span class="nn">django.utils.text</span> <span class="kn">import</span> <span class="n">slugify</span>
4196
- <a id="__codelineno-23-3" name="__codelineno-23-3" href="#__codelineno-23-3"></a>
4197
- <a id="__codelineno-23-4" name="__codelineno-23-4" href="#__codelineno-23-4"></a><span class="kn">from</span> <span class="nn">nautobot.dcim.models</span> <span class="kn">import</span> <span class="n">Device</span><span class="p">,</span> <span class="n">DeviceType</span><span class="p">,</span> <span class="n">Manufacturer</span><span class="p">,</span> <span class="n">Site</span>
4198
- <a id="__codelineno-23-5" name="__codelineno-23-5" href="#__codelineno-23-5"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Role</span><span class="p">,</span> <span class="n">Status</span>
4199
- <a id="__codelineno-23-6" name="__codelineno-23-6" href="#__codelineno-23-6"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="o">*</span>
5449
+ <a id="__codelineno-23-2" name="__codelineno-23-2" href="#__codelineno-23-2"></a>
5450
+ <a id="__codelineno-23-3" name="__codelineno-23-3" href="#__codelineno-23-3"></a><span class="kn">from</span> <span class="nn">nautobot.dcim.models</span> <span class="kn">import</span> <span class="n">Location</span><span class="p">,</span> <span class="n">LocationType</span><span class="p">,</span> <span class="n">Device</span><span class="p">,</span> <span class="n">Manufacturer</span><span class="p">,</span> <span class="n">DeviceType</span>
5451
+ <a id="__codelineno-23-4" name="__codelineno-23-4" href="#__codelineno-23-4"></a><span class="kn">from</span> <span class="nn">nautobot.extras.models</span> <span class="kn">import</span> <span class="n">Status</span><span class="p">,</span> <span class="n">Role</span>
5452
+ <a id="__codelineno-23-5" name="__codelineno-23-5" href="#__codelineno-23-5"></a><span class="kn">from</span> <span class="nn">nautobot.extras.jobs</span> <span class="kn">import</span> <span class="n">Job</span><span class="p">,</span> <span class="n">StringVar</span><span class="p">,</span> <span class="n">IntegerVar</span><span class="p">,</span> <span class="n">ObjectVar</span>
5453
+ <a id="__codelineno-23-6" name="__codelineno-23-6" href="#__codelineno-23-6"></a>
4200
5454
  <a id="__codelineno-23-7" name="__codelineno-23-7" href="#__codelineno-23-7"></a>
4201
- <a id="__codelineno-23-8" name="__codelineno-23-8" href="#__codelineno-23-8"></a>
4202
- <a id="__codelineno-23-9" name="__codelineno-23-9" href="#__codelineno-23-9"></a><span class="k">class</span> <span class="nc">NewBranch</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
4203
- <a id="__codelineno-23-10" name="__codelineno-23-10" href="#__codelineno-23-10"></a>
4204
- <a id="__codelineno-23-11" name="__codelineno-23-11" href="#__codelineno-23-11"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
4205
- <a id="__codelineno-23-12" name="__codelineno-23-12" href="#__codelineno-23-12"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;New Branch&quot;</span>
4206
- <a id="__codelineno-23-13" name="__codelineno-23-13" href="#__codelineno-23-13"></a> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot;Provision a new branch site&quot;</span>
4207
- <a id="__codelineno-23-14" name="__codelineno-23-14" href="#__codelineno-23-14"></a> <span class="n">field_order</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;site_name&#39;</span><span class="p">,</span> <span class="s1">&#39;switch_count&#39;</span><span class="p">,</span> <span class="s1">&#39;switch_model&#39;</span><span class="p">]</span>
4208
- <a id="__codelineno-23-15" name="__codelineno-23-15" href="#__codelineno-23-15"></a>
4209
- <a id="__codelineno-23-16" name="__codelineno-23-16" href="#__codelineno-23-16"></a> <span class="n">site_name</span> <span class="o">=</span> <span class="n">StringVar</span><span class="p">(</span>
4210
- <a id="__codelineno-23-17" name="__codelineno-23-17" href="#__codelineno-23-17"></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Name of the new site&quot;</span>
4211
- <a id="__codelineno-23-18" name="__codelineno-23-18" href="#__codelineno-23-18"></a> <span class="p">)</span>
4212
- <a id="__codelineno-23-19" name="__codelineno-23-19" href="#__codelineno-23-19"></a> <span class="n">switch_count</span> <span class="o">=</span> <span class="n">IntegerVar</span><span class="p">(</span>
4213
- <a id="__codelineno-23-20" name="__codelineno-23-20" href="#__codelineno-23-20"></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Number of access switches to create&quot;</span>
4214
- <a id="__codelineno-23-21" name="__codelineno-23-21" href="#__codelineno-23-21"></a> <span class="p">)</span>
4215
- <a id="__codelineno-23-22" name="__codelineno-23-22" href="#__codelineno-23-22"></a> <span class="n">manufacturer</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
4216
- <a id="__codelineno-23-23" name="__codelineno-23-23" href="#__codelineno-23-23"></a> <span class="n">model</span><span class="o">=</span><span class="n">Manufacturer</span><span class="p">,</span>
4217
- <a id="__codelineno-23-24" name="__codelineno-23-24" href="#__codelineno-23-24"></a> <span class="n">required</span><span class="o">=</span><span class="kc">False</span>
4218
- <a id="__codelineno-23-25" name="__codelineno-23-25" href="#__codelineno-23-25"></a> <span class="p">)</span>
4219
- <a id="__codelineno-23-26" name="__codelineno-23-26" href="#__codelineno-23-26"></a> <span class="n">switch_model</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
4220
- <a id="__codelineno-23-27" name="__codelineno-23-27" href="#__codelineno-23-27"></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Access switch model&quot;</span><span class="p">,</span>
4221
- <a id="__codelineno-23-28" name="__codelineno-23-28" href="#__codelineno-23-28"></a> <span class="n">model</span><span class="o">=</span><span class="n">DeviceType</span><span class="p">,</span>
4222
- <a id="__codelineno-23-29" name="__codelineno-23-29" href="#__codelineno-23-29"></a> <span class="n">query_params</span><span class="o">=</span><span class="p">{</span>
4223
- <a id="__codelineno-23-30" name="__codelineno-23-30" href="#__codelineno-23-30"></a> <span class="s1">&#39;manufacturer_id&#39;</span><span class="p">:</span> <span class="s1">&#39;$manufacturer&#39;</span>
4224
- <a id="__codelineno-23-31" name="__codelineno-23-31" href="#__codelineno-23-31"></a> <span class="p">}</span>
4225
- <a id="__codelineno-23-32" name="__codelineno-23-32" href="#__codelineno-23-32"></a> <span class="p">)</span>
5455
+ <a id="__codelineno-23-8" name="__codelineno-23-8" href="#__codelineno-23-8"></a><span class="k">class</span> <span class="nc">NewBranch</span><span class="p">(</span><span class="n">Job</span><span class="p">):</span>
5456
+ <a id="__codelineno-23-9" name="__codelineno-23-9" href="#__codelineno-23-9"></a> <span class="k">class</span> <span class="nc">Meta</span><span class="p">:</span>
5457
+ <a id="__codelineno-23-10" name="__codelineno-23-10" href="#__codelineno-23-10"></a> <span class="n">name</span> <span class="o">=</span> <span class="s2">&quot;New Branch&quot;</span>
5458
+ <a id="__codelineno-23-11" name="__codelineno-23-11" href="#__codelineno-23-11"></a> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot;Provision a new branch location&quot;</span>
5459
+ <a id="__codelineno-23-12" name="__codelineno-23-12" href="#__codelineno-23-12"></a> <span class="n">field_order</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;location_name&quot;</span><span class="p">,</span> <span class="s2">&quot;switch_count&quot;</span><span class="p">,</span> <span class="s2">&quot;switch_model&quot;</span><span class="p">]</span>
5460
+ <a id="__codelineno-23-13" name="__codelineno-23-13" href="#__codelineno-23-13"></a>
5461
+ <a id="__codelineno-23-14" name="__codelineno-23-14" href="#__codelineno-23-14"></a> <span class="n">location_name</span> <span class="o">=</span> <span class="n">StringVar</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;Name of the new location&quot;</span><span class="p">)</span>
5462
+ <a id="__codelineno-23-15" name="__codelineno-23-15" href="#__codelineno-23-15"></a> <span class="n">switch_count</span> <span class="o">=</span> <span class="n">IntegerVar</span><span class="p">(</span><span class="n">description</span><span class="o">=</span><span class="s2">&quot;Number of access switches to create&quot;</span><span class="p">)</span>
5463
+ <a id="__codelineno-23-16" name="__codelineno-23-16" href="#__codelineno-23-16"></a> <span class="n">manufacturer</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span><span class="n">model</span><span class="o">=</span><span class="n">Manufacturer</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
5464
+ <a id="__codelineno-23-17" name="__codelineno-23-17" href="#__codelineno-23-17"></a> <span class="n">switch_model</span> <span class="o">=</span> <span class="n">ObjectVar</span><span class="p">(</span>
5465
+ <a id="__codelineno-23-18" name="__codelineno-23-18" href="#__codelineno-23-18"></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Access switch model&quot;</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="n">DeviceType</span><span class="p">,</span> <span class="n">query_params</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;manufacturer_id&quot;</span><span class="p">:</span> <span class="s2">&quot;$manufacturer&quot;</span><span class="p">}</span>
5466
+ <a id="__codelineno-23-19" name="__codelineno-23-19" href="#__codelineno-23-19"></a> <span class="p">)</span>
5467
+ <a id="__codelineno-23-20" name="__codelineno-23-20" href="#__codelineno-23-20"></a>
5468
+ <a id="__codelineno-23-21" name="__codelineno-23-21" href="#__codelineno-23-21"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">location_name</span><span class="p">,</span> <span class="n">switch_count</span><span class="p">,</span> <span class="n">switch_model</span><span class="p">):</span>
5469
+ <a id="__codelineno-23-22" name="__codelineno-23-22" href="#__codelineno-23-22"></a> <span class="n">STATUS_PLANNED</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;Planned&quot;</span><span class="p">)</span>
5470
+ <a id="__codelineno-23-23" name="__codelineno-23-23" href="#__codelineno-23-23"></a>
5471
+ <a id="__codelineno-23-24" name="__codelineno-23-24" href="#__codelineno-23-24"></a> <span class="c1"># Create the new location</span>
5472
+ <a id="__codelineno-23-25" name="__codelineno-23-25" href="#__codelineno-23-25"></a> <span class="n">root_type</span> <span class="o">=</span> <span class="n">LocationType</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_or_create</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;Campus&quot;</span><span class="p">)</span>
5473
+ <a id="__codelineno-23-26" name="__codelineno-23-26" href="#__codelineno-23-26"></a> <span class="n">location</span> <span class="o">=</span> <span class="n">Location</span><span class="p">(</span>
5474
+ <a id="__codelineno-23-27" name="__codelineno-23-27" href="#__codelineno-23-27"></a> <span class="n">name</span><span class="o">=</span><span class="n">location_name</span><span class="p">,</span>
5475
+ <a id="__codelineno-23-28" name="__codelineno-23-28" href="#__codelineno-23-28"></a> <span class="n">location_type</span><span class="o">=</span><span class="n">root_type</span><span class="p">,</span>
5476
+ <a id="__codelineno-23-29" name="__codelineno-23-29" href="#__codelineno-23-29"></a> <span class="n">status</span><span class="o">=</span><span class="n">STATUS_PLANNED</span><span class="p">,</span>
5477
+ <a id="__codelineno-23-30" name="__codelineno-23-30" href="#__codelineno-23-30"></a> <span class="p">)</span>
5478
+ <a id="__codelineno-23-31" name="__codelineno-23-31" href="#__codelineno-23-31"></a> <span class="n">location</span><span class="o">.</span><span class="n">validated_save</span><span class="p">()</span>
5479
+ <a id="__codelineno-23-32" name="__codelineno-23-32" href="#__codelineno-23-32"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Created new location&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">location</span><span class="p">})</span>
4226
5480
  <a id="__codelineno-23-33" name="__codelineno-23-33" href="#__codelineno-23-33"></a>
4227
- <a id="__codelineno-23-34" name="__codelineno-23-34" href="#__codelineno-23-34"></a> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">commit</span><span class="p">):</span>
4228
- <a id="__codelineno-23-35" name="__codelineno-23-35" href="#__codelineno-23-35"></a> <span class="n">STATUS_PLANNED</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">slug</span><span class="o">=</span><span class="s1">&#39;planned&#39;</span><span class="p">)</span>
4229
- <a id="__codelineno-23-36" name="__codelineno-23-36" href="#__codelineno-23-36"></a>
4230
- <a id="__codelineno-23-37" name="__codelineno-23-37" href="#__codelineno-23-37"></a> <span class="c1"># Create the new site</span>
4231
- <a id="__codelineno-23-38" name="__codelineno-23-38" href="#__codelineno-23-38"></a> <span class="n">site</span> <span class="o">=</span> <span class="n">Site</span><span class="p">(</span>
4232
- <a id="__codelineno-23-39" name="__codelineno-23-39" href="#__codelineno-23-39"></a> <span class="n">name</span><span class="o">=</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;site_name&#39;</span><span class="p">],</span>
4233
- <a id="__codelineno-23-40" name="__codelineno-23-40" href="#__codelineno-23-40"></a> <span class="n">slug</span><span class="o">=</span><span class="n">slugify</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;site_name&#39;</span><span class="p">]),</span>
4234
- <a id="__codelineno-23-41" name="__codelineno-23-41" href="#__codelineno-23-41"></a> <span class="n">status</span><span class="o">=</span><span class="n">STATUS_PLANNED</span><span class="p">,</span>
4235
- <a id="__codelineno-23-42" name="__codelineno-23-42" href="#__codelineno-23-42"></a> <span class="p">)</span>
4236
- <a id="__codelineno-23-43" name="__codelineno-23-43" href="#__codelineno-23-43"></a> <span class="n">site</span><span class="o">.</span><span class="n">validated_save</span><span class="p">()</span>
4237
- <a id="__codelineno-23-44" name="__codelineno-23-44" href="#__codelineno-23-44"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_success</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="n">site</span><span class="p">,</span> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;Created new site&quot;</span><span class="p">)</span>
4238
- <a id="__codelineno-23-45" name="__codelineno-23-45" href="#__codelineno-23-45"></a>
4239
- <a id="__codelineno-23-46" name="__codelineno-23-46" href="#__codelineno-23-46"></a> <span class="c1"># Create access switches</span>
4240
- <a id="__codelineno-23-47" name="__codelineno-23-47" href="#__codelineno-23-47"></a> <span class="n">device_ct</span> <span class="o">=</span> <span class="n">ContentType</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_for_model</span><span class="p">(</span><span class="n">Device</span><span class="p">)</span>
4241
- <a id="__codelineno-23-48" name="__codelineno-23-48" href="#__codelineno-23-48"></a> <span class="n">switch_role</span> <span class="o">=</span> <span class="n">Role</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Access Switch&#39;</span><span class="p">)</span>
4242
- <a id="__codelineno-23-49" name="__codelineno-23-49" href="#__codelineno-23-49"></a> <span class="n">switch_role</span><span class="o">.</span><span class="n">content_types</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">device_ct</span><span class="p">)</span>
4243
- <a id="__codelineno-23-50" name="__codelineno-23-50" href="#__codelineno-23-50"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">data</span><span class="p">[</span><span class="s1">&#39;switch_count&#39;</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
4244
- <a id="__codelineno-23-51" name="__codelineno-23-51" href="#__codelineno-23-51"></a> <span class="n">switch</span> <span class="o">=</span> <span class="n">Device</span><span class="p">(</span>
4245
- <a id="__codelineno-23-52" name="__codelineno-23-52" href="#__codelineno-23-52"></a> <span class="n">device_type</span><span class="o">=</span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;switch_model&#39;</span><span class="p">],</span>
4246
- <a id="__codelineno-23-53" name="__codelineno-23-53" href="#__codelineno-23-53"></a> <span class="n">name</span><span class="o">=</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">site</span><span class="o">.</span><span class="n">slug</span><span class="si">}</span><span class="s1">-switch</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">,</span>
4247
- <a id="__codelineno-23-54" name="__codelineno-23-54" href="#__codelineno-23-54"></a> <span class="n">site</span><span class="o">=</span><span class="n">site</span><span class="p">,</span>
4248
- <a id="__codelineno-23-55" name="__codelineno-23-55" href="#__codelineno-23-55"></a> <span class="n">status</span><span class="o">=</span><span class="n">STATUS_PLANNED</span><span class="p">,</span>
4249
- <a id="__codelineno-23-56" name="__codelineno-23-56" href="#__codelineno-23-56"></a> <span class="n">role</span><span class="o">=</span><span class="n">switch_role</span>
4250
- <a id="__codelineno-23-57" name="__codelineno-23-57" href="#__codelineno-23-57"></a> <span class="p">)</span>
4251
- <a id="__codelineno-23-58" name="__codelineno-23-58" href="#__codelineno-23-58"></a> <span class="n">switch</span><span class="o">.</span><span class="n">validated_save</span><span class="p">()</span>
4252
- <a id="__codelineno-23-59" name="__codelineno-23-59" href="#__codelineno-23-59"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_success</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="n">switch</span><span class="p">,</span> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;Created new switch&quot;</span><span class="p">)</span>
4253
- <a id="__codelineno-23-60" name="__codelineno-23-60" href="#__codelineno-23-60"></a>
4254
- <a id="__codelineno-23-61" name="__codelineno-23-61" href="#__codelineno-23-61"></a> <span class="c1"># Generate a CSV table of new devices</span>
4255
- <a id="__codelineno-23-62" name="__codelineno-23-62" href="#__codelineno-23-62"></a> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span>
4256
- <a id="__codelineno-23-63" name="__codelineno-23-63" href="#__codelineno-23-63"></a> <span class="s1">&#39;name,make,model&#39;</span>
4257
- <a id="__codelineno-23-64" name="__codelineno-23-64" href="#__codelineno-23-64"></a> <span class="p">]</span>
4258
- <a id="__codelineno-23-65" name="__codelineno-23-65" href="#__codelineno-23-65"></a> <span class="k">for</span> <span class="n">switch</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">site</span><span class="o">=</span><span class="n">site</span><span class="p">):</span>
4259
- <a id="__codelineno-23-66" name="__codelineno-23-66" href="#__codelineno-23-66"></a> <span class="n">attrs</span> <span class="o">=</span> <span class="p">[</span>
4260
- <a id="__codelineno-23-67" name="__codelineno-23-67" href="#__codelineno-23-67"></a> <span class="n">switch</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
4261
- <a id="__codelineno-23-68" name="__codelineno-23-68" href="#__codelineno-23-68"></a> <span class="n">switch</span><span class="o">.</span><span class="n">device_type</span><span class="o">.</span><span class="n">manufacturer</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
4262
- <a id="__codelineno-23-69" name="__codelineno-23-69" href="#__codelineno-23-69"></a> <span class="n">switch</span><span class="o">.</span><span class="n">device_type</span><span class="o">.</span><span class="n">model</span>
4263
- <a id="__codelineno-23-70" name="__codelineno-23-70" href="#__codelineno-23-70"></a> <span class="p">]</span>
4264
- <a id="__codelineno-23-71" name="__codelineno-23-71" href="#__codelineno-23-71"></a> <span class="n">output</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">&#39;,&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">attrs</span><span class="p">))</span>
4265
- <a id="__codelineno-23-72" name="__codelineno-23-72" href="#__codelineno-23-72"></a>
4266
- <a id="__codelineno-23-73" name="__codelineno-23-73" href="#__codelineno-23-73"></a> <span class="k">return</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
5481
+ <a id="__codelineno-23-34" name="__codelineno-23-34" href="#__codelineno-23-34"></a> <span class="c1"># Create access switches</span>
5482
+ <a id="__codelineno-23-35" name="__codelineno-23-35" href="#__codelineno-23-35"></a> <span class="n">device_ct</span> <span class="o">=</span> <span class="n">ContentType</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get_for_model</span><span class="p">(</span><span class="n">Device</span><span class="p">)</span>
5483
+ <a id="__codelineno-23-36" name="__codelineno-23-36" href="#__codelineno-23-36"></a> <span class="n">switch_role</span> <span class="o">=</span> <span class="n">Role</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s2">&quot;Access Switch&quot;</span><span class="p">)</span>
5484
+ <a id="__codelineno-23-37" name="__codelineno-23-37" href="#__codelineno-23-37"></a> <span class="n">switch_role</span><span class="o">.</span><span class="n">content_types</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">device_ct</span><span class="p">)</span>
5485
+ <a id="__codelineno-23-38" name="__codelineno-23-38" href="#__codelineno-23-38"></a> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">switch_count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
5486
+ <a id="__codelineno-23-39" name="__codelineno-23-39" href="#__codelineno-23-39"></a> <span class="n">switch</span> <span class="o">=</span> <span class="n">Device</span><span class="p">(</span>
5487
+ <a id="__codelineno-23-40" name="__codelineno-23-40" href="#__codelineno-23-40"></a> <span class="n">device_type</span><span class="o">=</span><span class="n">switch_model</span><span class="p">,</span>
5488
+ <a id="__codelineno-23-41" name="__codelineno-23-41" href="#__codelineno-23-41"></a> <span class="n">name</span><span class="o">=</span><span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="n">location</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">-switch</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span>
5489
+ <a id="__codelineno-23-42" name="__codelineno-23-42" href="#__codelineno-23-42"></a> <span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">,</span>
5490
+ <a id="__codelineno-23-43" name="__codelineno-23-43" href="#__codelineno-23-43"></a> <span class="n">status</span><span class="o">=</span><span class="n">STATUS_PLANNED</span><span class="p">,</span>
5491
+ <a id="__codelineno-23-44" name="__codelineno-23-44" href="#__codelineno-23-44"></a> <span class="n">role</span><span class="o">=</span><span class="n">switch_role</span><span class="p">,</span>
5492
+ <a id="__codelineno-23-45" name="__codelineno-23-45" href="#__codelineno-23-45"></a> <span class="p">)</span>
5493
+ <a id="__codelineno-23-46" name="__codelineno-23-46" href="#__codelineno-23-46"></a> <span class="n">switch</span><span class="o">.</span><span class="n">validated_save</span><span class="p">()</span>
5494
+ <a id="__codelineno-23-47" name="__codelineno-23-47" href="#__codelineno-23-47"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Created new switch&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">switch</span><span class="p">})</span>
5495
+ <a id="__codelineno-23-48" name="__codelineno-23-48" href="#__codelineno-23-48"></a>
5496
+ <a id="__codelineno-23-49" name="__codelineno-23-49" href="#__codelineno-23-49"></a> <span class="c1"># Generate a CSV table of new devices</span>
5497
+ <a id="__codelineno-23-50" name="__codelineno-23-50" href="#__codelineno-23-50"></a> <span class="n">output</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;name,make,model&quot;</span><span class="p">]</span>
5498
+ <a id="__codelineno-23-51" name="__codelineno-23-51" href="#__codelineno-23-51"></a> <span class="k">for</span> <span class="n">switch</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">location</span><span class="o">=</span><span class="n">location</span><span class="p">):</span>
5499
+ <a id="__codelineno-23-52" name="__codelineno-23-52" href="#__codelineno-23-52"></a> <span class="n">attrs</span> <span class="o">=</span> <span class="p">[</span><span class="n">switch</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">switch</span><span class="o">.</span><span class="n">device_type</span><span class="o">.</span><span class="n">manufacturer</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="n">switch</span><span class="o">.</span><span class="n">device_type</span><span class="o">.</span><span class="n">model</span><span class="p">]</span>
5500
+ <a id="__codelineno-23-53" name="__codelineno-23-53" href="#__codelineno-23-53"></a> <span class="n">output</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">attrs</span><span class="p">))</span>
5501
+ <a id="__codelineno-23-54" name="__codelineno-23-54" href="#__codelineno-23-54"></a>
5502
+ <a id="__codelineno-23-55" name="__codelineno-23-55" href="#__codelineno-23-55"></a> <span class="k">return</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
4267
5503
  </code></pre></div>
4268
5504
  <h3 id="device-validation">Device validation<a class="headerlink" href="#device-validation" title="Permanent link">&para;</a></h3>
4269
5505
  <p>A job to perform various validation of Device data in Nautobot. As this job does not require any user input, it does not define any variables, nor does it implement a <code>run()</code> method.</p>
@@ -4276,44 +5512,52 @@ elements will be important in running jobs programmatically.</p>
4276
5512
  <a id="__codelineno-24-7" name="__codelineno-24-7" href="#__codelineno-24-7"></a> <span class="n">description</span> <span class="o">=</span> <span class="s2">&quot;Validate the minimum physical connections for each device&quot;</span>
4277
5513
  <a id="__codelineno-24-8" name="__codelineno-24-8" href="#__codelineno-24-8"></a>
4278
5514
  <a id="__codelineno-24-9" name="__codelineno-24-9" href="#__codelineno-24-9"></a> <span class="k">def</span> <span class="nf">test_console_connection</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
4279
- <a id="__codelineno-24-10" name="__codelineno-24-10" href="#__codelineno-24-10"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">slug</span><span class="o">=</span><span class="s1">&#39;active&#39;</span><span class="p">)</span>
5515
+ <a id="__codelineno-24-10" name="__codelineno-24-10" href="#__codelineno-24-10"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Active&#39;</span><span class="p">)</span>
4280
5516
  <a id="__codelineno-24-11" name="__codelineno-24-11" href="#__codelineno-24-11"></a>
4281
5517
  <a id="__codelineno-24-12" name="__codelineno-24-12" href="#__codelineno-24-12"></a> <span class="c1"># Check that every console port for every active device has a connection defined.</span>
4282
- <a id="__codelineno-24-13" name="__codelineno-24-13" href="#__codelineno-24-13"></a> <span class="k">for</span> <span class="n">console_port</span> <span class="ow">in</span> <span class="n">ConsolePort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">prefetch_related</span><span class="p">(</span><span class="s1">&#39;device&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device__status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
5518
+ <a id="__codelineno-24-13" name="__codelineno-24-13" href="#__codelineno-24-13"></a> <span class="k">for</span> <span class="n">console_port</span> <span class="ow">in</span> <span class="n">ConsolePort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">select_related</span><span class="p">(</span><span class="s1">&#39;device&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device__status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
4283
5519
  <a id="__codelineno-24-14" name="__codelineno-24-14" href="#__codelineno-24-14"></a> <span class="k">if</span> <span class="n">console_port</span><span class="o">.</span><span class="n">connected_endpoint</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
4284
- <a id="__codelineno-24-15" name="__codelineno-24-15" href="#__codelineno-24-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_failure</span><span class="p">(</span>
4285
- <a id="__codelineno-24-16" name="__codelineno-24-16" href="#__codelineno-24-16"></a> <span class="n">obj</span><span class="o">=</span><span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">,</span>
4286
- <a id="__codelineno-24-17" name="__codelineno-24-17" href="#__codelineno-24-17"></a> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;No console connection defined for </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
4287
- <a id="__codelineno-24-18" name="__codelineno-24-18" href="#__codelineno-24-18"></a> <span class="p">)</span>
4288
- <a id="__codelineno-24-19" name="__codelineno-24-19" href="#__codelineno-24-19"></a> <span class="k">elif</span> <span class="ow">not</span> <span class="n">console_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
4289
- <a id="__codelineno-24-20" name="__codelineno-24-20" href="#__codelineno-24-20"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_warning</span><span class="p">(</span>
4290
- <a id="__codelineno-24-21" name="__codelineno-24-21" href="#__codelineno-24-21"></a> <span class="n">obj</span><span class="o">=</span><span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">,</span>
4291
- <a id="__codelineno-24-22" name="__codelineno-24-22" href="#__codelineno-24-22"></a> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;Console connection for </span><span class="si">{}</span><span class="s2"> marked as planned&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
4292
- <a id="__codelineno-24-23" name="__codelineno-24-23" href="#__codelineno-24-23"></a> <span class="p">)</span>
4293
- <a id="__codelineno-24-24" name="__codelineno-24-24" href="#__codelineno-24-24"></a> <span class="k">else</span><span class="p">:</span>
4294
- <a id="__codelineno-24-25" name="__codelineno-24-25" href="#__codelineno-24-25"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_success</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">)</span>
4295
- <a id="__codelineno-24-26" name="__codelineno-24-26" href="#__codelineno-24-26"></a>
4296
- <a id="__codelineno-24-27" name="__codelineno-24-27" href="#__codelineno-24-27"></a> <span class="k">def</span> <span class="nf">test_power_connections</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
4297
- <a id="__codelineno-24-28" name="__codelineno-24-28" href="#__codelineno-24-28"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">slug</span><span class="o">=</span><span class="s1">&#39;active&#39;</span><span class="p">)</span>
4298
- <a id="__codelineno-24-29" name="__codelineno-24-29" href="#__codelineno-24-29"></a>
4299
- <a id="__codelineno-24-30" name="__codelineno-24-30" href="#__codelineno-24-30"></a> <span class="c1"># Check that every active device has at least two connected power supplies.</span>
4300
- <a id="__codelineno-24-31" name="__codelineno-24-31" href="#__codelineno-24-31"></a> <span class="k">for</span> <span class="n">device</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
4301
- <a id="__codelineno-24-32" name="__codelineno-24-32" href="#__codelineno-24-32"></a> <span class="n">connected_ports</span> <span class="o">=</span> <span class="mi">0</span>
4302
- <a id="__codelineno-24-33" name="__codelineno-24-33" href="#__codelineno-24-33"></a> <span class="k">for</span> <span class="n">power_port</span> <span class="ow">in</span> <span class="n">PowerPort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">):</span>
4303
- <a id="__codelineno-24-34" name="__codelineno-24-34" href="#__codelineno-24-34"></a> <span class="k">if</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connected_endpoint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
4304
- <a id="__codelineno-24-35" name="__codelineno-24-35" href="#__codelineno-24-35"></a> <span class="n">connected_ports</span> <span class="o">+=</span> <span class="mi">1</span>
4305
- <a id="__codelineno-24-36" name="__codelineno-24-36" href="#__codelineno-24-36"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
4306
- <a id="__codelineno-24-37" name="__codelineno-24-37" href="#__codelineno-24-37"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_warning</span><span class="p">(</span>
4307
- <a id="__codelineno-24-38" name="__codelineno-24-38" href="#__codelineno-24-38"></a> <span class="n">obj</span><span class="o">=</span><span class="n">device</span><span class="p">,</span>
4308
- <a id="__codelineno-24-39" name="__codelineno-24-39" href="#__codelineno-24-39"></a> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;Power connection for </span><span class="si">{}</span><span class="s2"> marked as planned&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">power_port</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
4309
- <a id="__codelineno-24-40" name="__codelineno-24-40" href="#__codelineno-24-40"></a> <span class="p">)</span>
4310
- <a id="__codelineno-24-41" name="__codelineno-24-41" href="#__codelineno-24-41"></a> <span class="k">if</span> <span class="n">connected_ports</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
4311
- <a id="__codelineno-24-42" name="__codelineno-24-42" href="#__codelineno-24-42"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_failure</span><span class="p">(</span>
4312
- <a id="__codelineno-24-43" name="__codelineno-24-43" href="#__codelineno-24-43"></a> <span class="n">obj</span><span class="o">=</span><span class="n">device</span><span class="p">,</span>
4313
- <a id="__codelineno-24-44" name="__codelineno-24-44" href="#__codelineno-24-44"></a> <span class="n">message</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">{}</span><span class="s2"> connected power supplies found (2 needed)&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">connected_ports</span><span class="p">)</span>
4314
- <a id="__codelineno-24-45" name="__codelineno-24-45" href="#__codelineno-24-45"></a> <span class="p">)</span>
4315
- <a id="__codelineno-24-46" name="__codelineno-24-46" href="#__codelineno-24-46"></a> <span class="k">else</span><span class="p">:</span>
4316
- <a id="__codelineno-24-47" name="__codelineno-24-47" href="#__codelineno-24-47"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log_success</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="n">device</span><span class="p">)</span>
5520
+ <a id="__codelineno-24-15" name="__codelineno-24-15" href="#__codelineno-24-15"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
5521
+ <a id="__codelineno-24-16" name="__codelineno-24-16" href="#__codelineno-24-16"></a> <span class="s2">&quot;No console connection defined for </span><span class="si">%s</span><span class="s2">&quot;</span><span class="p">,</span>
5522
+ <a id="__codelineno-24-17" name="__codelineno-24-17" href="#__codelineno-24-17"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
5523
+ <a id="__codelineno-24-18" name="__codelineno-24-18" href="#__codelineno-24-18"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
5524
+ <a id="__codelineno-24-19" name="__codelineno-24-19" href="#__codelineno-24-19"></a> <span class="p">)</span>
5525
+ <a id="__codelineno-24-20" name="__codelineno-24-20" href="#__codelineno-24-20"></a> <span class="k">elif</span> <span class="ow">not</span> <span class="n">console_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
5526
+ <a id="__codelineno-24-21" name="__codelineno-24-21" href="#__codelineno-24-21"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
5527
+ <a id="__codelineno-24-22" name="__codelineno-24-22" href="#__codelineno-24-22"></a> <span class="s2">&quot;Console connection for </span><span class="si">%s</span><span class="s2"> marked as planned&quot;</span><span class="p">,</span>
5528
+ <a id="__codelineno-24-23" name="__codelineno-24-23" href="#__codelineno-24-23"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
5529
+ <a id="__codelineno-24-24" name="__codelineno-24-24" href="#__codelineno-24-24"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
5530
+ <a id="__codelineno-24-25" name="__codelineno-24-25" href="#__codelineno-24-25"></a> <span class="p">)</span>
5531
+ <a id="__codelineno-24-26" name="__codelineno-24-26" href="#__codelineno-24-26"></a> <span class="k">else</span><span class="p">:</span>
5532
+ <a id="__codelineno-24-27" name="__codelineno-24-27" href="#__codelineno-24-27"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
5533
+ <a id="__codelineno-24-28" name="__codelineno-24-28" href="#__codelineno-24-28"></a> <span class="s2">&quot;Console port </span><span class="si">%s</span><span class="s2"> has a connection defined&quot;</span><span class="p">,</span>
5534
+ <a id="__codelineno-24-29" name="__codelineno-24-29" href="#__codelineno-24-29"></a> <span class="n">console_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
5535
+ <a id="__codelineno-24-30" name="__codelineno-24-30" href="#__codelineno-24-30"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">console_port</span><span class="o">.</span><span class="n">device</span><span class="p">},</span>
5536
+ <a id="__codelineno-24-31" name="__codelineno-24-31" href="#__codelineno-24-31"></a> <span class="p">)</span>
5537
+ <a id="__codelineno-24-32" name="__codelineno-24-32" href="#__codelineno-24-32"></a>
5538
+ <a id="__codelineno-24-33" name="__codelineno-24-33" href="#__codelineno-24-33"></a> <span class="k">def</span> <span class="nf">test_power_connections</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
5539
+ <a id="__codelineno-24-34" name="__codelineno-24-34" href="#__codelineno-24-34"></a> <span class="n">STATUS_ACTIVE</span> <span class="o">=</span> <span class="n">Status</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;Active&#39;</span><span class="p">)</span>
5540
+ <a id="__codelineno-24-35" name="__codelineno-24-35" href="#__codelineno-24-35"></a>
5541
+ <a id="__codelineno-24-36" name="__codelineno-24-36" href="#__codelineno-24-36"></a> <span class="c1"># Check that every active device has at least two connected power supplies.</span>
5542
+ <a id="__codelineno-24-37" name="__codelineno-24-37" href="#__codelineno-24-37"></a> <span class="k">for</span> <span class="n">device</span> <span class="ow">in</span> <span class="n">Device</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">status</span><span class="o">=</span><span class="n">STATUS_ACTIVE</span><span class="p">):</span>
5543
+ <a id="__codelineno-24-38" name="__codelineno-24-38" href="#__codelineno-24-38"></a> <span class="n">connected_ports</span> <span class="o">=</span> <span class="mi">0</span>
5544
+ <a id="__codelineno-24-39" name="__codelineno-24-39" href="#__codelineno-24-39"></a> <span class="k">for</span> <span class="n">power_port</span> <span class="ow">in</span> <span class="n">PowerPort</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">device</span><span class="o">=</span><span class="n">device</span><span class="p">):</span>
5545
+ <a id="__codelineno-24-40" name="__codelineno-24-40" href="#__codelineno-24-40"></a> <span class="k">if</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connected_endpoint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
5546
+ <a id="__codelineno-24-41" name="__codelineno-24-41" href="#__codelineno-24-41"></a> <span class="n">connected_ports</span> <span class="o">+=</span> <span class="mi">1</span>
5547
+ <a id="__codelineno-24-42" name="__codelineno-24-42" href="#__codelineno-24-42"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">power_port</span><span class="o">.</span><span class="n">connection_status</span><span class="p">:</span>
5548
+ <a id="__codelineno-24-43" name="__codelineno-24-43" href="#__codelineno-24-43"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
5549
+ <a id="__codelineno-24-44" name="__codelineno-24-44" href="#__codelineno-24-44"></a> <span class="s2">&quot;Power connection for </span><span class="si">%s</span><span class="s2"> marked as planned&quot;</span><span class="p">,</span>
5550
+ <a id="__codelineno-24-45" name="__codelineno-24-45" href="#__codelineno-24-45"></a> <span class="n">power_port</span><span class="o">.</span><span class="n">name</span><span class="p">,</span>
5551
+ <a id="__codelineno-24-46" name="__codelineno-24-46" href="#__codelineno-24-46"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">},</span>
5552
+ <a id="__codelineno-24-47" name="__codelineno-24-47" href="#__codelineno-24-47"></a> <span class="p">)</span>
5553
+ <a id="__codelineno-24-48" name="__codelineno-24-48" href="#__codelineno-24-48"></a> <span class="k">if</span> <span class="n">connected_ports</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">:</span>
5554
+ <a id="__codelineno-24-49" name="__codelineno-24-49" href="#__codelineno-24-49"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">error</span><span class="p">(</span>
5555
+ <a id="__codelineno-24-50" name="__codelineno-24-50" href="#__codelineno-24-50"></a> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2"> connected power supplies found (2 needed)&quot;</span><span class="p">,</span>
5556
+ <a id="__codelineno-24-51" name="__codelineno-24-51" href="#__codelineno-24-51"></a> <span class="n">connected_ports</span><span class="p">,</span>
5557
+ <a id="__codelineno-24-52" name="__codelineno-24-52" href="#__codelineno-24-52"></a> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">},</span>
5558
+ <a id="__codelineno-24-53" name="__codelineno-24-53" href="#__codelineno-24-53"></a> <span class="p">)</span>
5559
+ <a id="__codelineno-24-54" name="__codelineno-24-54" href="#__codelineno-24-54"></a> <span class="k">else</span><span class="p">:</span>
5560
+ <a id="__codelineno-24-55" name="__codelineno-24-55" href="#__codelineno-24-55"></a> <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;At least two connected power supplies found&quot;</span><span class="p">,</span> <span class="n">extra</span><span class="o">=</span><span class="p">{</span><span class="s2">&quot;object&quot;</span><span class="p">:</span> <span class="n">device</span><span class="p">})</span>
4317
5561
  </code></pre></div>
4318
5562
 
4319
5563
 
@@ -4331,42 +5575,6 @@ elements will be important in running jobs programmatically.</p>
4331
5575
 
4332
5576
  <footer class="md-footer">
4333
5577
 
4334
-
4335
- <nav class="md-footer__inner md-grid" aria-label="Footer" >
4336
-
4337
-
4338
- <a href="healthcheck.html" class="md-footer__link md-footer__link--prev" aria-label="Previous: Health Check" rel="prev">
4339
- <div class="md-footer__button md-icon">
4340
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
4341
- </div>
4342
- <div class="md-footer__title">
4343
- <div class="md-ellipsis">
4344
- <span class="md-footer__direction">
4345
- Previous
4346
- </span>
4347
- Health Check
4348
- </div>
4349
- </div>
4350
- </a>
4351
-
4352
-
4353
-
4354
- <a href="../models/extras/jobbutton.html" class="md-footer__link md-footer__link--next" aria-label="Next: Job Buttons" rel="next">
4355
- <div class="md-footer__title">
4356
- <div class="md-ellipsis">
4357
- <span class="md-footer__direction">
4358
- Next
4359
- </span>
4360
- Job Buttons
4361
- </div>
4362
- </div>
4363
- <div class="md-footer__button md-icon">
4364
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
4365
- </div>
4366
- </a>
4367
-
4368
- </nav>
4369
-
4370
5578
  <div class="md-footer-meta md-typeset">
4371
5579
  <div class="md-footer-meta__inner md-grid">
4372
5580
  <div class="md-copyright">
@@ -4394,32 +5602,42 @@ elements will be important in running jobs programmatically.</p>
4394
5602
 
4395
5603
 
4396
5604
 
5605
+
5606
+
4397
5607
  <a href="https://blog.networktocode.com/blog/tags/nautobot" target="_blank" rel="noopener" title="Network to Code Blog" class="md-social__link">
4398
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M0 64c0-17.7 14.3-32 32-32 229.8 0 416 186.2 416 416 0 17.7-14.3 32-32 32s-32-14.3-32-32C384 253.6 226.4 96 32 96 14.3 96 0 81.7 0 64zm128 352c0 35.3-28.7 64-64 64S0 451.3 0 416s28.7-64 64-64 64 28.7 64 64zM32 160c159.1 0 288 128.9 288 288 0 17.7-14.3 32-32 32s-32-14.3-32-32c0-123.7-100.3-224-224-224-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>
5608
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M0 64c0-17.7 14.3-32 32-32 229.8 0 416 186.2 416 416 0 17.7-14.3 32-32 32s-32-14.3-32-32C384 253.6 226.4 96 32 96 14.3 96 0 81.7 0 64zm0 352a64 64 0 1 1 128 0 64 64 0 1 1-128 0zm32-256c159.1 0 288 128.9 288 288 0 17.7-14.3 32-32 32s-32-14.3-32-32c0-123.7-100.3-224-224-224-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>
4399
5609
  </a>
4400
5610
 
4401
5611
 
4402
5612
 
5613
+
5614
+
4403
5615
  <a href="https://www.youtube.com/playlist?list=PLjA0bhxgryJ2Ts4GJMDA-tPzVWEncv4pb" target="_blank" rel="noopener" title="Nautobot Videos" class="md-social__link">
4404
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
5616
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>
4405
5617
  </a>
4406
5618
 
4407
5619
 
4408
5620
 
5621
+
5622
+
4409
5623
  <a href="https://www.networktocode.com/community/" target="_blank" rel="noopener" title="Network to Code Community" class="md-social__link">
4410
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
5624
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M94.12 315.1c0 25.9-21.16 47.06-47.06 47.06S0 341 0 315.1c0-25.9 21.16-47.06 47.06-47.06h47.06v47.06zm23.72 0c0-25.9 21.16-47.06 47.06-47.06s47.06 21.16 47.06 47.06v117.84c0 25.9-21.16 47.06-47.06 47.06s-47.06-21.16-47.06-47.06V315.1zm47.06-188.98c-25.9 0-47.06-21.16-47.06-47.06S139 32 164.9 32s47.06 21.16 47.06 47.06v47.06H164.9zm0 23.72c25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06H47.06C21.16 243.96 0 222.8 0 196.9s21.16-47.06 47.06-47.06H164.9zm188.98 47.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06s-21.16 47.06-47.06 47.06h-47.06V196.9zm-23.72 0c0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06V79.06c0-25.9 21.16-47.06 47.06-47.06 25.9 0 47.06 21.16 47.06 47.06V196.9zM283.1 385.88c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06-25.9 0-47.06-21.16-47.06-47.06v-47.06h47.06zm0-23.72c-25.9 0-47.06-21.16-47.06-47.06 0-25.9 21.16-47.06 47.06-47.06h117.84c25.9 0 47.06 21.16 47.06 47.06 0 25.9-21.16 47.06-47.06 47.06H283.1z"/></svg>
4411
5625
  </a>
4412
5626
 
4413
5627
 
4414
5628
 
5629
+
5630
+
4415
5631
  <a href="https://github.com/nautobot/nautobot" target="_blank" rel="noopener" title="GitHub Repo" class="md-social__link">
4416
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
5632
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
4417
5633
  </a>
4418
5634
 
4419
5635
 
4420
5636
 
5637
+
5638
+
4421
5639
  <a href="https://twitter.com/networktocode" target="_blank" rel="noopener" title="Network to Code Twitter" class="md-social__link">
4422
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2022 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
5640
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
4423
5641
  </a>
4424
5642
 
4425
5643
  </div>
@@ -4433,14 +5651,13 @@ elements will be important in running jobs programmatically.</p>
4433
5651
  <div class="md-dialog__inner md-typeset"></div>
4434
5652
  </div>
4435
5653
 
4436
- <script id="__config" type="application/json">{"base": "..", "features": ["navigation.tracking", "navigation.tabs", "navigation.tabs.sticky", "search.suggest", "search.highlight", "search.share"], "search": "../assets/javascripts/workers/search.16e2a7d4.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.config.lang": "en", "search.config.pipeline": "trimmer, stopWordFilter", "search.config.separator": "[\\s\\-]+", "search.placeholder": "Search", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version.title": "Select version"}}</script>
5654
+ <script id="__config" type="application/json">{"base": "..", "features": ["navigation.tracking", "navigation.tabs", "navigation.tabs.sticky", "search.suggest", "search.highlight", "search.share"], "search": "../assets/javascripts/workers/search.208ed371.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
4437
5655
 
4438
5656
 
4439
- <script src="../assets/javascripts/bundle.5a2dcb6a.min.js"></script>
5657
+ <script src="../assets/javascripts/bundle.51198bba.min.js"></script>
4440
5658
 
4441
5659
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
4442
5660
 
4443
5661
 
4444
-
4445
5662
  </body>
4446
5663
  </html>