nautobot 2.3.0__py3-none-any.whl → 2.3.0b1__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (366) hide show
  1. nautobot/cloud/factory.py +0 -2
  2. nautobot/cloud/filters.py +0 -3
  3. nautobot/cloud/forms.py +1 -7
  4. nautobot/cloud/migrations/0001_initial.py +1 -1
  5. nautobot/cloud/models.py +2 -1
  6. nautobot/cloud/tables.py +17 -1
  7. nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +7 -1
  8. nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +0 -11
  9. nautobot/cloud/templates/cloud/cloudservice_retrieve.html +0 -4
  10. nautobot/cloud/tests/test_filters.py +0 -12
  11. nautobot/core/filters.py +1 -15
  12. nautobot/core/forms/forms.py +2 -10
  13. nautobot/core/graphql/generators.py +2 -2
  14. nautobot/core/graphql/schema.py +14 -6
  15. nautobot/core/jobs/__init__.py +1 -4
  16. nautobot/core/management/commands/generate_test_data.py +2 -2
  17. nautobot/core/models/__init__.py +2 -2
  18. nautobot/core/settings.py +2 -13
  19. nautobot/core/settings.yaml +2 -16
  20. nautobot/core/tables.py +0 -3
  21. nautobot/core/templates/generic/object_retrieve.html +5 -5
  22. nautobot/core/templates/nautobot_config.py.j2 +0 -15
  23. nautobot/core/testing/filters.py +1 -12
  24. nautobot/core/tests/integration/test_general_functionality.py +1 -1
  25. nautobot/core/tests/test_jobs.py +1 -74
  26. nautobot/core/views/generic.py +1 -1
  27. nautobot/core/views/mixins.py +1 -1
  28. nautobot/core/views/utils.py +6 -8
  29. nautobot/dcim/factory.py +1 -4
  30. nautobot/dcim/filters/__init__.py +0 -4
  31. nautobot/dcim/forms.py +0 -5
  32. nautobot/dcim/migrations/0061_module_models.py +0 -1
  33. nautobot/dcim/models/device_components.py +0 -7
  34. nautobot/dcim/models/devices.py +4 -6
  35. nautobot/dcim/models/racks.py +1 -0
  36. nautobot/dcim/tables/devices.py +3 -17
  37. nautobot/dcim/tables/devicetypes.py +1 -1
  38. nautobot/dcim/templates/dcim/device/base.html +1 -1
  39. nautobot/dcim/templates/dcim/device.html +2 -2
  40. nautobot/dcim/templates/dcim/deviceredundancygroup_retrieve.html +0 -6
  41. nautobot/dcim/templates/dcim/moduletype_retrieve.html +0 -17
  42. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +2 -2
  43. nautobot/dcim/tests/test_api.py +0 -2
  44. nautobot/dcim/tests/test_filters.py +7 -14
  45. nautobot/dcim/tests/test_models.py +0 -31
  46. nautobot/dcim/tests/test_views.py +0 -39
  47. nautobot/dcim/views.py +1 -4
  48. nautobot/extras/api/views.py +59 -7
  49. nautobot/extras/factory.py +12 -50
  50. nautobot/extras/forms/base.py +4 -10
  51. nautobot/extras/homepage.py +2 -12
  52. nautobot/extras/jobs.py +2 -2
  53. nautobot/extras/migrations/0111_metadata.py +4 -4
  54. nautobot/extras/models/jobs.py +0 -83
  55. nautobot/extras/models/metadata.py +18 -18
  56. nautobot/extras/models/models.py +0 -2
  57. nautobot/extras/signals.py +1 -14
  58. nautobot/extras/tables.py +14 -43
  59. nautobot/extras/templates/extras/job_detail.html +0 -11
  60. nautobot/extras/tests/test_api.py +9 -16
  61. nautobot/extras/tests/test_jobs.py +2 -2
  62. nautobot/extras/tests/test_models.py +18 -20
  63. nautobot/extras/tests/test_views.py +3 -23
  64. nautobot/extras/utils.py +6 -35
  65. nautobot/extras/views.py +50 -27
  66. nautobot/ipam/filters.py +1 -1
  67. nautobot/ipam/forms.py +1 -1
  68. nautobot/ipam/models.py +20 -9
  69. nautobot/ipam/tables.py +0 -4
  70. nautobot/ipam/tests/test_models.py +2 -3
  71. nautobot/ipam/views.py +11 -6
  72. nautobot/project-static/css/base.css +0 -1
  73. nautobot/project-static/docs/404.html +18 -18
  74. nautobot/project-static/docs/apps/index.html +18 -18
  75. nautobot/project-static/docs/apps/nautobot-apps.html +18 -18
  76. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +1 -0
  77. nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +1 -0
  78. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +18 -18
  79. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +18 -18
  80. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +18 -66
  81. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +18 -18
  82. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +18 -18
  83. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +18 -18
  84. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +18 -18
  85. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +18 -18
  86. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +18 -66
  87. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +18 -34
  88. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +18 -82
  89. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +21 -75
  90. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +18 -18
  91. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +18 -34
  92. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +18 -34
  93. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +18 -18
  94. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +18 -18
  95. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -18
  96. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +18 -18
  97. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +18 -18
  98. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +18 -18
  99. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +19 -21
  100. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +18 -34
  101. nautobot/project-static/docs/development/apps/api/configuration-view.html +18 -18
  102. nautobot/project-static/docs/development/apps/api/database-backend-config.html +18 -18
  103. nautobot/project-static/docs/development/apps/api/models/django-admin.html +18 -18
  104. nautobot/project-static/docs/development/apps/api/models/global-search.html +18 -18
  105. nautobot/project-static/docs/development/apps/api/models/graphql.html +18 -18
  106. nautobot/project-static/docs/development/apps/api/models/index.html +22 -33
  107. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +18 -18
  108. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +18 -18
  109. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +18 -18
  110. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +18 -18
  111. nautobot/project-static/docs/development/apps/api/platform-features/index.html +18 -18
  112. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +18 -18
  113. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +18 -18
  114. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +18 -18
  115. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +18 -18
  116. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +18 -18
  117. nautobot/project-static/docs/development/apps/api/prometheus.html +18 -18
  118. nautobot/project-static/docs/development/apps/api/setup.html +18 -18
  119. nautobot/project-static/docs/development/apps/api/testing.html +18 -18
  120. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +18 -18
  121. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +18 -18
  122. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +18 -18
  123. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +18 -18
  124. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +18 -18
  125. nautobot/project-static/docs/development/apps/api/views/base-template.html +18 -18
  126. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +18 -18
  127. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +18 -18
  128. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +18 -18
  129. nautobot/project-static/docs/development/apps/api/views/index.html +18 -18
  130. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +18 -18
  131. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +18 -18
  132. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +18 -18
  133. nautobot/project-static/docs/development/apps/api/views/notes.html +18 -18
  134. nautobot/project-static/docs/development/apps/api/views/rest-api.html +18 -18
  135. nautobot/project-static/docs/development/apps/api/views/urls.html +18 -18
  136. nautobot/project-static/docs/development/apps/index.html +18 -18
  137. nautobot/project-static/docs/development/apps/migration/code-updates.html +18 -18
  138. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +18 -18
  139. nautobot/project-static/docs/development/apps/migration/from-v1.html +18 -18
  140. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +18 -18
  141. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +18 -18
  142. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +18 -18
  143. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +18 -18
  144. nautobot/project-static/docs/development/apps/porting-from-netbox.html +18 -18
  145. nautobot/project-static/docs/development/core/application-registry.html +18 -18
  146. nautobot/project-static/docs/development/core/best-practices.html +18 -18
  147. nautobot/project-static/docs/development/core/bootstrap-ui.html +18 -18
  148. nautobot/project-static/docs/development/core/caching.html +18 -18
  149. nautobot/project-static/docs/development/core/controllers.html +18 -18
  150. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +18 -18
  151. nautobot/project-static/docs/development/core/generic-views.html +18 -18
  152. nautobot/project-static/docs/development/core/getting-started.html +18 -18
  153. nautobot/project-static/docs/development/core/homepage.html +18 -18
  154. nautobot/project-static/docs/development/core/index.html +18 -29
  155. nautobot/project-static/docs/development/core/model-checklist.html +20 -26
  156. nautobot/project-static/docs/development/core/model-features.html +18 -18
  157. nautobot/project-static/docs/development/core/natural-keys.html +18 -18
  158. nautobot/project-static/docs/development/core/navigation-menu.html +18 -18
  159. nautobot/project-static/docs/development/core/release-checklist.html +18 -18
  160. nautobot/project-static/docs/development/core/role-internals.html +18 -18
  161. nautobot/project-static/docs/development/core/settings.html +18 -18
  162. nautobot/project-static/docs/development/core/style-guide.html +19 -19
  163. nautobot/project-static/docs/development/core/templates.html +18 -18
  164. nautobot/project-static/docs/development/core/testing.html +18 -18
  165. nautobot/project-static/docs/development/core/user-preferences.html +18 -18
  166. nautobot/project-static/docs/development/index.html +18 -18
  167. nautobot/project-static/docs/development/jobs/index.html +379 -393
  168. nautobot/project-static/docs/development/jobs/migration/from-v1.html +18 -18
  169. nautobot/project-static/docs/index.html +13 -9032
  170. nautobot/project-static/docs/models/extras/metadatachoice.html +3 -3
  171. nautobot/project-static/docs/models/extras/metadatatype.html +3 -3
  172. nautobot/project-static/docs/models/extras/objectmetadata.html +3 -3
  173. nautobot/project-static/docs/objects.inv +0 -0
  174. nautobot/project-static/docs/overview/application_stack.html +18 -18
  175. nautobot/project-static/docs/overview/design_philosophy.html +20 -20
  176. nautobot/project-static/docs/overview/index.html +9032 -13
  177. nautobot/project-static/docs/release-notes/index.html +19 -252
  178. nautobot/project-static/docs/release-notes/version-1.0.html +18 -18
  179. nautobot/project-static/docs/release-notes/version-1.1.html +18 -18
  180. nautobot/project-static/docs/release-notes/version-1.2.html +18 -18
  181. nautobot/project-static/docs/release-notes/version-1.3.html +18 -18
  182. nautobot/project-static/docs/release-notes/version-1.4.html +18 -18
  183. nautobot/project-static/docs/release-notes/version-1.5.html +18 -18
  184. nautobot/project-static/docs/release-notes/version-1.6.html +18 -18
  185. nautobot/project-static/docs/release-notes/version-2.0.html +18 -18
  186. nautobot/project-static/docs/release-notes/version-2.1.html +18 -18
  187. nautobot/project-static/docs/release-notes/version-2.2.html +111 -248
  188. nautobot/project-static/docs/release-notes/version-2.3.html +90 -520
  189. nautobot/project-static/docs/requirements.txt +3 -3
  190. nautobot/project-static/docs/search/search_index.json +1 -1
  191. nautobot/project-static/docs/sitemap.xml +278 -278
  192. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  193. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +18 -18
  194. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +18 -18
  195. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +18 -18
  196. nautobot/project-static/docs/user-guide/administration/configuration/index.html +18 -18
  197. nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +20 -52
  198. nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +18 -18
  199. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +18 -18
  200. nautobot/project-static/docs/user-guide/administration/guides/caching.html +18 -18
  201. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +18 -22
  202. nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +18 -18
  203. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +18 -18
  204. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +18 -18
  205. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +18 -18
  206. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +18 -18
  207. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +18 -18
  208. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +18 -18
  209. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +18 -18
  210. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +82 -69
  211. nautobot/project-static/docs/user-guide/administration/installation/index.html +24 -24
  212. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +52 -60
  213. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +87 -80
  214. nautobot/project-static/docs/user-guide/administration/installation/services.html +44 -37
  215. nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +18 -18
  216. nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +18 -18
  217. nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +18 -18
  218. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +18 -18
  219. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +18 -18
  220. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +24 -76
  221. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +18 -18
  222. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +18 -18
  223. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +18 -18
  224. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +18 -18
  225. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +18 -18
  226. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +18 -18
  227. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +18 -18
  228. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +18 -18
  229. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +18 -18
  230. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +18 -18
  231. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +18 -18
  232. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +18 -18
  233. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +18 -18
  234. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +18 -18
  235. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +18 -18
  236. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +18 -18
  237. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +18 -18
  238. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +18 -18
  239. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +18 -18
  240. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +18 -18
  241. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +18 -18
  242. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +18 -18
  243. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +18 -18
  244. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +18 -18
  245. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +18 -18
  246. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +18 -18
  247. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +18 -18
  248. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +18 -18
  249. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +18 -18
  250. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +19 -19
  251. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +18 -18
  252. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +18 -18
  253. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +18 -18
  254. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +18 -18
  255. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +18 -18
  256. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +18 -18
  257. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +18 -18
  258. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +18 -18
  259. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +18 -18
  260. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +18 -18
  261. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +18 -18
  262. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +18 -18
  263. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +18 -18
  264. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +19 -19
  265. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +18 -18
  266. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +18 -18
  267. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +18 -18
  268. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +18 -18
  269. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +18 -18
  270. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +18 -18
  271. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +18 -18
  272. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +18 -18
  273. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +18 -18
  274. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +18 -18
  275. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +18 -18
  276. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +18 -18
  277. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +18 -18
  278. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +18 -18
  279. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +18 -18
  280. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +18 -18
  281. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +18 -18
  282. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +18 -18
  283. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +18 -18
  284. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +18 -62
  285. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +18 -18
  286. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +18 -18
  287. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +18 -18
  288. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +18 -18
  289. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +18 -18
  290. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +18 -18
  291. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +18 -18
  292. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +18 -18
  293. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +18 -18
  294. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +18 -18
  295. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +18 -18
  296. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +18 -18
  297. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +18 -18
  298. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +18 -18
  299. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +18 -18
  300. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +18 -18
  301. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +18 -18
  302. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +18 -18
  303. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +18 -18
  304. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +18 -18
  305. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +18 -18
  306. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +18 -18
  307. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +18 -18
  308. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +18 -18
  309. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +18 -18
  310. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +18 -18
  311. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +18 -18
  312. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +18 -18
  313. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +18 -18
  314. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +18 -18
  315. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +18 -18
  316. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +18 -18
  317. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +18 -18
  318. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +18 -18
  319. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +18 -18
  320. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +18 -18
  321. nautobot/project-static/docs/user-guide/index.html +18 -18
  322. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +18 -18
  323. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +18 -18
  324. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +18 -18
  325. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +18 -18
  326. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +18 -18
  327. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +18 -18
  328. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +18 -18
  329. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +18 -18
  330. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +18 -18
  331. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +18 -18
  332. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +18 -18
  333. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +18 -18
  334. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +21 -21
  335. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +18 -18
  336. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +18 -18
  337. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +18 -18
  338. nautobot/project-static/docs/user-guide/platform-functionality/{objectmetadata.html → metadata.html} +84 -197
  339. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +36 -36
  340. nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -33
  341. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +21 -21
  342. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +18 -18
  343. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +18 -18
  344. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +18 -18
  345. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +18 -18
  346. nautobot/project-static/docs/user-guide/platform-functionality/role.html +18 -18
  347. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +18 -18
  348. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +18 -18
  349. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +18 -18
  350. nautobot/project-static/docs/user-guide/platform-functionality/status.html +18 -18
  351. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +18 -18
  352. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +18 -18
  353. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +18 -18
  354. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +18 -18
  355. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +18 -18
  356. nautobot/tenancy/templates/tenancy/tenant.html +4 -4
  357. nautobot/virtualization/models.py +2 -0
  358. nautobot/virtualization/tables.py +5 -2
  359. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/METADATA +3 -3
  360. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/RECORD +364 -364
  361. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +0 -1
  362. nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +0 -1
  363. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/LICENSE.txt +0 -0
  364. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/NOTICE +0 -0
  365. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/WHEEL +0 -0
  366. {nautobot-2.3.0.dist-info → nautobot-2.3.0b1.dist-info}/entry_points.txt +0 -0
@@ -586,7 +586,6 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
586
586
 
587
587
  if form.is_valid():
588
588
  logger.debug("Form validation was successful")
589
- msg = f"Deleted {self.queryset.model._meta.verbose_name} {obj}"
590
589
 
591
590
  try:
592
591
  obj.delete()
@@ -595,6 +594,7 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
595
594
  handle_protectederror([obj], request, e)
596
595
  return redirect(obj.get_absolute_url())
597
596
 
597
+ msg = f"Deleted {self.queryset.model._meta.verbose_name} {obj}"
598
598
  logger.info(msg)
599
599
  messages.success(request, msg)
600
600
 
@@ -745,8 +745,8 @@ class ObjectDestroyViewMixin(NautobotViewSetMixin, mixins.DestroyModelMixin):
745
745
  queryset = self.get_queryset()
746
746
  try:
747
747
  with transaction.atomic():
748
- msg = f"Deleted {queryset.model._meta.verbose_name} {obj}"
749
748
  obj.delete()
749
+ msg = f"Deleted {queryset.model._meta.verbose_name} {obj}"
750
750
  self.logger.info(msg)
751
751
  messages.success(request, msg)
752
752
  self.success_url = self.get_return_url(request, obj)
@@ -360,14 +360,12 @@ def common_detail_view_context(request, instance):
360
360
 
361
361
  if instance.is_metadata_associable_model:
362
362
  paginate = {"paginator_class": EnhancedPaginator, "per_page": get_paginate_count(request)}
363
- object_metadata = instance.associated_object_metadata.restrict(request.user, "view").order_by(
364
- "metadata_type", "scoped_fields"
365
- )
366
- object_metadata_table = ObjectMetadataTable(object_metadata, orderable=False)
367
- object_metadata_table.columns.hide("assigned_object")
368
- RequestConfig(request, paginate).configure(object_metadata_table)
369
- context["associated_object_metadata_table"] = object_metadata_table
363
+ object_metadatas = instance.associated_object_metadatas.restrict(request.user, "view").order_by("scoped_fields")
364
+ object_metadatas_table = ObjectMetadataTable(object_metadatas, orderable=False)
365
+ object_metadatas_table.columns.hide("assigned_object")
366
+ RequestConfig(request, paginate).configure(object_metadatas_table)
367
+ context["associated_object_metadatas_table"] = object_metadatas_table
370
368
  else:
371
- context["associated_object_metadata_table"] = None
369
+ context["associated_object_metadatas_table"] = None
372
370
 
373
371
  return context
nautobot/dcim/factory.py CHANGED
@@ -760,16 +760,13 @@ module_types = (
760
760
  class ModuleTypeFactory(PrimaryModelFactory):
761
761
  class Meta:
762
762
  model = ModuleType
763
- exclude = ("has_part_number", "has_comments")
763
+ exclude = ("has_part_number",)
764
764
 
765
765
  manufacturer = random_instance(Manufacturer, allow_null=False)
766
766
 
767
767
  has_part_number = NautobotBoolIterator()
768
768
  part_number = factory.Maybe("has_part_number", factory.Faker("ean", length=8), "")
769
769
 
770
- has_comments = NautobotBoolIterator()
771
- comments = factory.Maybe("has_comments", factory.Faker("bs"))
772
-
773
770
  @factory.lazy_attribute
774
771
  def model(self):
775
772
  """
@@ -1999,10 +1999,6 @@ class ModuleTypeFilterSet(DeviceTypeModuleTypeCommonFiltersMixin, NautobotFilter
1999
1999
  "lookup_expr": "icontains",
2000
2000
  "preprocessor": str.strip,
2001
2001
  },
2002
- "comments": {
2003
- "lookup_expr": "icontains",
2004
- "preprocessor": str.strip,
2005
- },
2006
2002
  },
2007
2003
  )
2008
2004
  has_modules = RelatedMembershipBooleanFilter(
nautobot/dcim/forms.py CHANGED
@@ -886,7 +886,6 @@ class DeviceTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
886
886
  software_image_files = DynamicModelMultipleChoiceField(queryset=SoftwareImageFile.objects.all(), required=False)
887
887
  u_height = forms.IntegerField(required=False)
888
888
  is_full_depth = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect(), label="Is full depth")
889
- comments = CommentField(label="Comments", required=False)
890
889
 
891
890
  class Meta:
892
891
  nullable_fields = ["device_family", "software_image_files"]
@@ -947,7 +946,6 @@ class DeviceTypeFilterForm(NautobotFilterForm):
947
946
 
948
947
  class ModuleTypeForm(NautobotModelForm):
949
948
  manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all())
950
- comments = CommentField(label="Comments")
951
949
 
952
950
  class Meta:
953
951
  model = ModuleType
@@ -955,7 +953,6 @@ class ModuleTypeForm(NautobotModelForm):
955
953
  "manufacturer",
956
954
  "model",
957
955
  "part_number",
958
- "comments",
959
956
  "tags",
960
957
  ]
961
958
 
@@ -977,7 +974,6 @@ class ModuleTypeImportForm(BootstrapMixin, forms.ModelForm):
977
974
  "manufacturer",
978
975
  "model",
979
976
  "part_number",
980
- "comments",
981
977
  ]
982
978
 
983
979
 
@@ -985,7 +981,6 @@ class ModuleTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
985
981
  pk = forms.ModelMultipleChoiceField(queryset=ModuleType.objects.all(), widget=forms.MultipleHiddenInput())
986
982
  manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
987
983
  part_number = forms.CharField(required=False)
988
- comments = CommentField(label="Comments", required=False)
989
984
 
990
985
  class Meta:
991
986
  nullable_fields = []
@@ -138,7 +138,6 @@ class Migration(migrations.Migration):
138
138
  ),
139
139
  ("model", models.CharField(max_length=255)),
140
140
  ("part_number", models.CharField(blank=True, max_length=255)),
141
- ("comments", models.TextField(blank=True)),
142
141
  ],
143
142
  options={
144
143
  "ordering": ("manufacturer", "model"),
@@ -26,7 +26,6 @@ from nautobot.dcim.choices import (
26
26
  PowerOutletFeedLegChoices,
27
27
  PowerOutletTypeChoices,
28
28
  PowerPortTypeChoices,
29
- SubdeviceRoleChoices,
30
29
  )
31
30
  from nautobot.dcim.constants import (
32
31
  NONCONNECTABLE_IFACE_TYPES,
@@ -1097,12 +1096,6 @@ class DeviceBay(ComponentModel):
1097
1096
  "installed_device": f"Cannot install the specified device; device is already installed in {current_bay}"
1098
1097
  }
1099
1098
  )
1100
- if self.installed_device.device_type.subdevice_role != SubdeviceRoleChoices.ROLE_CHILD:
1101
- raise ValidationError(
1102
- {
1103
- "installed_device": f'Cannot install device "{self.installed_device}"; device-type "{self.installed_device.device_type}" subdevice_role is not "child".'
1104
- }
1105
- )
1106
1099
 
1107
1100
 
1108
1101
  #
@@ -452,6 +452,7 @@ class Platform(OrganizationalModel):
452
452
  @extras_features(
453
453
  "custom_links",
454
454
  "custom_validators",
455
+ "dynamic_groups",
455
456
  "export_templates",
456
457
  "graphql",
457
458
  "locations",
@@ -1108,6 +1109,7 @@ class VirtualChassis(PrimaryModel):
1108
1109
  @extras_features(
1109
1110
  "custom_links",
1110
1111
  "custom_validators",
1112
+ "dynamic_groups",
1111
1113
  "export_templates",
1112
1114
  "graphql",
1113
1115
  "statuses",
@@ -1153,10 +1155,6 @@ class DeviceRedundancyGroup(PrimaryModel):
1153
1155
  def devices_sorted(self):
1154
1156
  return self.devices.order_by("device_redundancy_group_priority")
1155
1157
 
1156
- @property
1157
- def controllers_sorted(self):
1158
- return self.controllers.order_by("name")
1159
-
1160
1158
  def __str__(self):
1161
1159
  return self.name
1162
1160
 
@@ -1339,6 +1337,7 @@ class SoftwareVersion(PrimaryModel):
1339
1337
  @extras_features(
1340
1338
  "custom_links",
1341
1339
  "custom_validators",
1340
+ "dynamic_groups",
1342
1341
  "export_templates",
1343
1342
  "graphql",
1344
1343
  "locations",
@@ -1422,6 +1421,7 @@ class Controller(PrimaryModel):
1422
1421
  @extras_features(
1423
1422
  "custom_links",
1424
1423
  "custom_validators",
1424
+ "dynamic_groups",
1425
1425
  "export_templates",
1426
1426
  "graphql",
1427
1427
  "webhooks",
@@ -1510,7 +1510,6 @@ class ModuleType(PrimaryModel):
1510
1510
  part_number = models.CharField(
1511
1511
  max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Discrete part number (optional)"
1512
1512
  )
1513
- comments = models.TextField(blank=True)
1514
1513
 
1515
1514
  clone_fields = [
1516
1515
  "manufacturer",
@@ -1531,7 +1530,6 @@ class ModuleType(PrimaryModel):
1531
1530
  ("manufacturer", self.manufacturer.name),
1532
1531
  ("model", self.model),
1533
1532
  ("part_number", self.part_number),
1534
- ("comments", self.comments),
1535
1533
  )
1536
1534
  )
1537
1535
 
@@ -91,6 +91,7 @@ class RackGroup(TreeModel, OrganizationalModel):
91
91
  @extras_features(
92
92
  "custom_links",
93
93
  "custom_validators",
94
+ "dynamic_groups",
94
95
  "export_templates",
95
96
  "graphql",
96
97
  "locations",
@@ -261,7 +261,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
261
261
  )
262
262
  location = tables.Column(linkify=True)
263
263
  tenant = TenantColumn()
264
- tags = TagColumn(url_name="dcim:module_list")
264
+ tags = TagColumn(url_name="dcim:device_list")
265
265
  actions = ButtonsColumn(Module, prepend_template=MODULE_BUTTONS)
266
266
 
267
267
  class Meta(BaseTable.Meta):
@@ -1125,27 +1125,13 @@ class DeviceRedundancyGroupTable(BaseTable):
1125
1125
  url_params={"device_redundancy_group": "pk"},
1126
1126
  verbose_name="Devices",
1127
1127
  )
1128
- controller_count = LinkedCountColumn(
1129
- viewname="dcim:controller_list",
1130
- url_params={"controller_device_redundancy_group": "pk"},
1131
- verbose_name="Controllers",
1132
- )
1133
1128
  secrets_group = tables.Column(linkify=True)
1134
1129
  tags = TagColumn(url_name="dcim:deviceredundancygroup_list")
1135
1130
 
1136
1131
  class Meta(BaseTable.Meta):
1137
1132
  model = DeviceRedundancyGroup
1138
- fields = (
1139
- "pk",
1140
- "name",
1141
- "status",
1142
- "failover_strategy",
1143
- "controller_count",
1144
- "device_count",
1145
- "secrets_group",
1146
- "tags",
1147
- )
1148
- default_columns = ("pk", "name", "status", "failover_strategy", "controller_count", "device_count")
1133
+ fields = ("pk", "name", "status", "failover_strategy", "device_count", "secrets_group", "tags")
1134
+ default_columns = ("pk", "name", "status", "failover_strategy", "device_count")
1149
1135
 
1150
1136
 
1151
1137
  #
@@ -160,7 +160,7 @@ class ModuleTypeTable(BaseTable):
160
160
  url_params={"module_type": "pk"},
161
161
  verbose_name="Modules",
162
162
  )
163
- tags = TagColumn(url_name="dcim:moduletype_list")
163
+ tags = TagColumn(url_name="dcim:devicetype_list")
164
164
 
165
165
  class Meta(BaseTable.Meta):
166
166
  model = ModuleType
@@ -71,7 +71,7 @@
71
71
  <a href="{% url 'dcim:device_modulebays' pk=object.pk %}">Modules {% badge module_count %}</a>
72
72
  </li>
73
73
  {% endif %}
74
- {% with interface_count=object.vc_interfaces.count %}
74
+ {% with interface_count=object.all_interfaces.count %}
75
75
  {% if interface_count %}
76
76
  <li role="presentation" {% if active_tab == 'interfaces' %} class="active"{% endif %}>
77
77
  <a href="{% url 'dcim:device_interfaces' pk=object.pk %}">Interfaces {% badge interface_count %}</a>
@@ -427,7 +427,7 @@
427
427
  </div>
428
428
  {% endif %}
429
429
  {% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
430
- <div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
430
+ <div id="object_metadatas" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadatas' %}active{% else %}fade{% endif %}">
431
431
  <div class="row">
432
432
  <div class="col-md-12">
433
433
  <form method="post">
@@ -440,7 +440,7 @@
440
440
  </div>
441
441
  </div>
442
442
  <div class="table-responsive">
443
- {% render_table associated_object_metadata_table 'inc/table.html' %}
443
+ {% render_table associated_object_metadatas_table 'inc/table.html' %}
444
444
  </div>
445
445
  </div>
446
446
  </form>
@@ -45,12 +45,6 @@
45
45
  {% endblock content_right_page %}
46
46
 
47
47
  {% block content_full_width_page %}
48
- <div class="panel panel-default">
49
- <div class="panel-heading">
50
- <strong>Controllers</strong>
51
- </div>
52
- {% include 'responsive_table.html' with table=controllers_table %}
53
- </div>
54
48
  <div class="panel panel-default">
55
49
  <div class="panel-heading">
56
50
  <strong>Devices</strong>
@@ -113,23 +113,6 @@
113
113
  </div>
114
114
  {% endblock content_left_page %}
115
115
 
116
- {% block content_right_page %}
117
- <div class="panel panel-default">
118
- <div class="panel-heading">
119
- <strong>Comments</strong>
120
- </div>
121
- <div class="panel-body rendered-markdown">
122
- {% if object.comments %}
123
- {{ object.comments|render_markdown }}
124
- {% else %}
125
- <span class="text-muted">None</span>
126
- {% endif %}
127
- </div>
128
- </div>
129
- {% endblock content_right_page %}
130
-
131
-
132
-
133
116
  {% block extra_tab_content %}
134
117
  <div role="tabpanel" class="tab-pane {% if request.GET.tab == 'interfaces' %}active{% else %}fade{% endif %}" id="interfaces">
135
118
  {% include 'dcim/inc/moduletype_component_table.html' with table=interface_table title='Interfaces' tab='interfaces' %}
@@ -236,7 +236,7 @@
236
236
  </div>
237
237
  {% endif %}
238
238
  {% if object.is_metadata_associable_model and perms.extras.view_objectmetadata %}
239
- <div id="object_metadata" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadata' %}active{% else %}fade{% endif %}">
239
+ <div id="object_metadatas" role="tabpanel" class="tab-pane {% if request.GET.tab == 'object_metadatas' %}active{% else %}fade{% endif %}">
240
240
  <div class="row">
241
241
  <div class="col-md-12">
242
242
  <form method="post">
@@ -249,7 +249,7 @@
249
249
  </div>
250
250
  </div>
251
251
  <div class="table-responsive">
252
- {% render_table associated_object_metadata_table 'inc/table.html' %}
252
+ {% render_table associated_object_metadatas_table 'inc/table.html' %}
253
253
  </div>
254
254
  </div>
255
255
  </form>
@@ -1022,7 +1022,6 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase):
1022
1022
  model = ModuleType
1023
1023
  bulk_update_data = {
1024
1024
  "part_number": "ABC123",
1025
- "comments": "changed comment",
1026
1025
  }
1027
1026
 
1028
1027
  @classmethod
@@ -1034,7 +1033,6 @@ class ModuleTypeTest(APIViewTestCases.APIViewTestCase):
1034
1033
  "manufacturer": manufacturer_id,
1035
1034
  "model": "Module Type 1",
1036
1035
  "part_number": "123456",
1037
- "comments": "test comment",
1038
1036
  },
1039
1037
  {
1040
1038
  "manufacturer": manufacturer_id,
@@ -656,15 +656,9 @@ def common_test_data(cls):
656
656
  device_redundancy_groups = iter(DeviceRedundancyGroup.objects.all())
657
657
 
658
658
  module_types = (
659
- ModuleType.objects.create(
660
- manufacturer=cls.manufacturers[0], model="Filter Test Module Type 1", comments="Module Type 1"
661
- ),
662
- ModuleType.objects.create(
663
- manufacturer=cls.manufacturers[1], model="Filter Test Module Type 2", comments="Module Type 2"
664
- ),
665
- ModuleType.objects.create(
666
- manufacturer=cls.manufacturers[2], model="Filter Test Module Type 3", comments="Module Type 3"
667
- ),
659
+ ModuleType.objects.create(manufacturer=cls.manufacturers[0], model="Filter Test Module Type 1"),
660
+ ModuleType.objects.create(manufacturer=cls.manufacturers[1], model="Filter Test Module Type 2"),
661
+ ModuleType.objects.create(manufacturer=cls.manufacturers[2], model="Filter Test Module Type 3"),
668
662
  )
669
663
 
670
664
  # Create 3 of each component template on the first two module types
@@ -904,7 +898,7 @@ class ModularDeviceComponentTestMixin(DeviceComponentTestMixin):
904
898
  )
905
899
  parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
906
900
  module_type = ModuleType.objects.create(
907
- manufacturer=manufacturer, model=f"Test Device Filter for {model} Module Type", comments="Module Type test"
901
+ manufacturer=manufacturer, model=f"Test Device Filter for {model} Module Type"
908
902
  )
909
903
  module = Module.objects.create(
910
904
  module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
@@ -2532,7 +2526,7 @@ class InterfaceTestCase(PathEndpointModelTestMixin, ModularDeviceComponentTestMi
2532
2526
  name="Parent module bay", position="1", parent_device=device_vc_master
2533
2527
  )
2534
2528
  module_type = ModuleType.objects.create(
2535
- manufacturer=manufacturer, model="Test Device Filter for Interface Module Type", comments="Module Type test"
2529
+ manufacturer=manufacturer, model="Test Device Filter for Interface Module Type"
2536
2530
  )
2537
2531
  module = Module.objects.create(
2538
2532
  module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
@@ -2778,7 +2772,7 @@ class FrontPortTestCase(ModularDeviceComponentTestMixin, FilterTestCases.FilterT
2778
2772
  )
2779
2773
  parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
2780
2774
  module_type = ModuleType.objects.create(
2781
- manufacturer=manufacturer, model="Test Device Filter for FrontPort Module Type", comments="Module Type test"
2775
+ manufacturer=manufacturer, model="Test Device Filter for FrontPort Module Type"
2782
2776
  )
2783
2777
  module = Module.objects.create(
2784
2778
  module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
@@ -3363,7 +3357,7 @@ class CableTestCase(FilterTestCases.FilterTestCase):
3363
3357
  )
3364
3358
  parent_module_bay = ModuleBay.objects.create(name="Parent module bay", position="1", parent_device=device)
3365
3359
  module_type = ModuleType.objects.create(
3366
- manufacturer=manufacturer, model="Test Device Filter for Cable Module Type", comments="Module Type test"
3360
+ manufacturer=manufacturer, model="Test Device Filter for Cable Module Type"
3367
3361
  )
3368
3362
  module = Module.objects.create(
3369
3363
  module_type=module_type, parent_module_bay=parent_module_bay, status=self.module_statuses[0]
@@ -4018,7 +4012,6 @@ class ModuleTypeTestCase(FilterTestCases.FilterTestCase):
4018
4012
  queryset = ModuleType.objects.all()
4019
4013
  filterset = ModuleTypeFilterSet
4020
4014
  generic_filter_tests = [
4021
- ("comments",),
4022
4015
  ("manufacturer", "manufacturer__id"),
4023
4016
  ("manufacturer", "manufacturer__name"),
4024
4017
  ("model",),
@@ -1903,37 +1903,6 @@ class DeviceTestCase(ModelTestCases.BaseModelTestCase):
1903
1903
  self.assertNotEqual(child_mtime_after_parent_rack_update_save, child_mtime_after_parent_site_update_save)
1904
1904
 
1905
1905
 
1906
- class DeviceBayTestCase(ModelTestCases.BaseModelTestCase):
1907
- model = DeviceBay
1908
-
1909
- def setUp(self):
1910
- self.devices = Device.objects.filter(device_type__subdevice_role=SubdeviceRoleChoices.ROLE_PARENT)
1911
- devicetype = DeviceType.objects.create(
1912
- manufacturer=self.devices[0].device_type.manufacturer,
1913
- model="TestDeviceType1",
1914
- u_height=0,
1915
- subdevice_role=SubdeviceRoleChoices.ROLE_CHILD,
1916
- )
1917
- child_device = Device.objects.create(
1918
- device_type=devicetype,
1919
- role=self.devices[0].role,
1920
- name="TestDevice1",
1921
- status=self.devices[0].status,
1922
- location=self.devices[0].location,
1923
- )
1924
- DeviceBay.objects.create(device=self.devices[0], name="Device Bay 1", installed_device=child_device)
1925
-
1926
- def test_assigning_installed_device(self):
1927
- server = Device.objects.exclude(device_type__subdevice_role=SubdeviceRoleChoices.ROLE_CHILD).last()
1928
- bay = DeviceBay(device=self.devices[1], name="Device Bay Err", installed_device=server)
1929
- with self.assertRaises(ValidationError) as err:
1930
- bay.validated_save()
1931
- self.assertIn(
1932
- f'Cannot install device "{server}"; device-type "{server.device_type}" subdevice_role is not "child".',
1933
- str(err.exception),
1934
- )
1935
-
1936
-
1937
1906
  class DeviceTypeToSoftwareImageFileTestCase(ModelTestCases.BaseModelTestCase):
1938
1907
  model = DeviceTypeToSoftwareImageFile
1939
1908
 
@@ -817,7 +817,6 @@ class DeviceTypeTestCase(
817
817
  cls.bulk_edit_data = {
818
818
  "u_height": 0,
819
819
  "is_full_depth": False,
820
- "comments": "changed comment",
821
820
  }
822
821
 
823
822
  def test_list_has_correct_links(self):
@@ -1197,7 +1196,6 @@ class ModuleTypeTestCase(
1197
1196
  ModuleType.objects.create(
1198
1197
  model="Test Module Type 1",
1199
1198
  manufacturer=manufacturers[0],
1200
- comments="test comment",
1201
1199
  )
1202
1200
  ModuleType.objects.create(
1203
1201
  model="Test Module Type 2",
@@ -1217,12 +1215,10 @@ class ModuleTypeTestCase(
1217
1215
  "model": "Test Module Type X",
1218
1216
  "part_number": "123ABC",
1219
1217
  "tags": [t.pk for t in Tag.objects.get_for_model(ModuleType)],
1220
- "comments": "test comment",
1221
1218
  }
1222
1219
 
1223
1220
  cls.bulk_edit_data = {
1224
1221
  "manufacturer": manufacturers[1].pk,
1225
- "comments": "changed comment",
1226
1222
  }
1227
1223
 
1228
1224
  def test_list_has_correct_links(self):
@@ -2363,19 +2359,6 @@ class DeviceTestCase(ViewTestCases.PrimaryObjectViewTestCase):
2363
2359
  sorted(interface_ips),
2364
2360
  )
2365
2361
 
2366
- with self.subTest("Assert Assigning IPAddress Without Selecting Any IPAddress Raises Exception"):
2367
- assign_ip_form_data["pk"] = []
2368
- assign_ip_request = {
2369
- "path": reverse("ipam:ipaddress_assign")
2370
- + f"?interface={self.interfaces[1].id}&return_url={device_list_url}",
2371
- "data": post_data(assign_ip_form_data),
2372
- }
2373
- response = self.client.post(**assign_ip_request, follow=True)
2374
- self.assertHttpStatus(response, 200)
2375
- self.assertIn(
2376
- "Please select at least one IP Address from the table.", response.content.decode(response.charset)
2377
- )
2378
-
2379
2362
  @override_settings(EXEMPT_VIEW_PERMISSIONS=["*"])
2380
2363
  def test_device_rearports(self):
2381
2364
  device = Device.objects.first()
@@ -4189,28 +4172,6 @@ class VirtualChassisTestCase(ViewTestCases.PrimaryObjectViewTestCase):
4189
4172
  "domain": "domain-x",
4190
4173
  }
4191
4174
 
4192
- def test_device_interfaces_count_correct(self):
4193
- """
4194
- This checks whether the other memebers' interfaces are included in the
4195
- interfaces tab of the master device and whether the interface count on the tab header is
4196
- rendered correctly.
4197
- """
4198
- self.user.is_superuser = True
4199
- self.user.save()
4200
- interface_status = Status.objects.get_for_model(Interface).first()
4201
- Interface.objects.create(device=self.devices[0], name="eth0", status=interface_status)
4202
- Interface.objects.create(device=self.devices[0], name="eth1", status=interface_status)
4203
- Interface.objects.create(device=self.devices[1], name="device 1 interface 1", status=interface_status)
4204
- Interface.objects.create(device=self.devices[1], name="device 1 interface 2", status=interface_status)
4205
- Interface.objects.create(device=self.devices[2], name="device 2 interface 1", status=interface_status)
4206
- Interface.objects.create(device=self.devices[2], name="device 2 interface 2", status=interface_status)
4207
- response = self.client.get(reverse("dcim:device_interfaces", kwargs={"pk": self.devices[0].pk}))
4208
- self.assertIn('Interfaces <span class="badge">6</span>', str(response.content))
4209
- self.assertIn("device 1 interface 1", str(response.content))
4210
- self.assertIn("device 1 interface 2", str(response.content))
4211
- self.assertIn("device 2 interface 1", str(response.content))
4212
- self.assertIn("device 2 interface 2", str(response.content))
4213
-
4214
4175
  def test_device_column_visible(self):
4215
4176
  """
4216
4177
  This checks whether the device column on a device's interfaces
nautobot/dcim/views.py CHANGED
@@ -1923,7 +1923,7 @@ class DeviceInterfacesView(DeviceComponentTabView):
1923
1923
 
1924
1924
  def get_extra_context(self, request, instance):
1925
1925
  interfaces = (
1926
- instance.vc_interfaces.restrict(request.user, "view")
1926
+ instance.all_interfaces.restrict(request.user, "view")
1927
1927
  .prefetch_related(
1928
1928
  Prefetch("ip_addresses", queryset=IPAddress.objects.restrict(request.user)),
1929
1929
  Prefetch("member_interfaces", queryset=Interface.objects.restrict(request.user)),
@@ -4049,9 +4049,6 @@ class DeviceRedundancyGroupUIViewSet(NautobotUIViewSet):
4049
4049
  devices_table = tables.DeviceTable(devices)
4050
4050
  devices_table.columns.show("device_redundancy_group_priority")
4051
4051
  context["devices_table"] = devices_table
4052
- controllers = instance.controllers_sorted.restrict(request.user)
4053
- controllers_table = tables.ControllerTable(controllers)
4054
- context["controllers_table"] = controllers_table
4055
4052
  return context
4056
4053
 
4057
4054
 
@@ -1,3 +1,5 @@
1
+ from datetime import timedelta
2
+
1
3
  from django.conf import settings
2
4
  from django.contrib.contenttypes.models import ContentType
3
5
  from django.forms import ValidationError as FormsValidationError
@@ -490,6 +492,59 @@ class ImageAttachmentViewSet(ModelViewSet):
490
492
  #
491
493
 
492
494
 
495
+ def _create_schedule(serializer, data, job_model, user, approval_required, task_queue=None):
496
+ """
497
+ This is an internal function to create a scheduled job from API data.
498
+ It has to handle both once-offs (i.e. of type TYPE_FUTURE) and interval
499
+ jobs.
500
+ """
501
+ type_ = serializer["interval"]
502
+ if type_ == JobExecutionType.TYPE_IMMEDIATELY:
503
+ time = timezone.now()
504
+ name = serializer.get("name") or f"{job_model.name} - {time}"
505
+ elif type_ == JobExecutionType.TYPE_CUSTOM:
506
+ time = serializer.get("start_time") # doing .get("key", "default") returns None instead of "default"
507
+ if time is None:
508
+ # "start_time" is checked against models.ScheduledJob.earliest_possible_time()
509
+ # which returns timezone.now() + timedelta(seconds=15)
510
+ time = timezone.now() + timedelta(seconds=20)
511
+ name = serializer["name"]
512
+ else:
513
+ time = serializer["start_time"]
514
+ name = serializer["name"]
515
+ crontab = serializer.get("crontab", "")
516
+
517
+ celery_kwargs = {
518
+ "nautobot_job_profile": False,
519
+ "queue": task_queue,
520
+ }
521
+
522
+ # 2.0 TODO: To revisit this as part of a larger Jobs cleanup in 2.0.
523
+ #
524
+ # We pass in task and job_model here partly for forward/backward compatibility logic, and
525
+ # part fallback safety. It's mildly useful to store both the task module/class name and the JobModel
526
+ # FK on the ScheduledJob, as in the case where the JobModel gets deleted (and the FK becomes
527
+ # null) you still have a bit of context on the ScheduledJob as to what it was originally
528
+ # scheduled for.
529
+ scheduled_job = ScheduledJob(
530
+ name=name,
531
+ task=job_model.class_path,
532
+ job_model=job_model,
533
+ start_time=time,
534
+ description=f"Nautobot job {name} scheduled by {user} for {time}",
535
+ kwargs=data,
536
+ celery_kwargs=celery_kwargs,
537
+ interval=type_,
538
+ one_off=(type_ == JobExecutionType.TYPE_FUTURE),
539
+ user=user,
540
+ approval_required=approval_required,
541
+ crontab=crontab,
542
+ queue=task_queue,
543
+ )
544
+ scheduled_job.validated_save()
545
+ return scheduled_job
546
+
547
+
493
548
  class JobViewSetBase(
494
549
  NautobotAPIVersionMixin,
495
550
  # note no CreateModelMixin
@@ -689,16 +744,13 @@ class JobViewSetBase(
689
744
 
690
745
  # Try to create a ScheduledJob, or...
691
746
  if schedule_data:
692
- schedule = ScheduledJob.create_schedule(
747
+ schedule = _create_schedule(
748
+ schedule_data,
749
+ job_class.serialize_data(cleaned_data),
693
750
  job_model,
694
751
  request.user,
695
- name=schedule_data.get("name"),
696
- start_time=schedule_data.get("start_time"),
697
- interval=schedule_data.get("interval"),
698
- crontab=schedule_data.get("crontab", ""),
699
- approval_required=approval_required,
752
+ approval_required,
700
753
  task_queue=input_serializer.validated_data.get("task_queue", None),
701
- **job_class.serialize_data(cleaned_data),
702
754
  )
703
755
  else:
704
756
  schedule = None