nautobot 2.4.10__py3-none-any.whl → 2.4.12__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 (439) hide show
  1. nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -114
  2. nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +1 -1
  3. nautobot/circuits/views.py +76 -6
  4. nautobot/cloud/navigation.py +1 -1
  5. nautobot/cloud/tests/test_views.py +13 -1
  6. nautobot/cloud/views.py +39 -9
  7. nautobot/core/celery/__init__.py +21 -0
  8. nautobot/core/celery/encoders.py +3 -0
  9. nautobot/core/forms/forms.py +4 -1
  10. nautobot/core/jobs/bulk_actions.py +8 -8
  11. nautobot/core/jobs/cleanup.py +11 -0
  12. nautobot/core/management/commands/generate_test_data.py +2 -1
  13. nautobot/core/templates/components/panel/header_extra_content_table.html +12 -1
  14. nautobot/core/templates/components/panel/panel.html +4 -0
  15. nautobot/core/templates/generic/object_retrieve.html +2 -1
  16. nautobot/core/testing/mixins.py +19 -1
  17. nautobot/core/testing/views.py +104 -8
  18. nautobot/core/tests/test_jobs.py +20 -4
  19. nautobot/core/tests/test_utils.py +17 -0
  20. nautobot/core/tests/test_views.py +2 -2
  21. nautobot/core/tests/test_views_utils.py +53 -2
  22. nautobot/core/ui/object_detail.py +5 -1
  23. nautobot/core/utils/lookup.py +4 -2
  24. nautobot/core/utils/module_loading.py +23 -0
  25. nautobot/core/views/generic.py +2 -12
  26. nautobot/core/views/mixins.py +19 -1
  27. nautobot/core/views/renderers.py +4 -13
  28. nautobot/core/views/utils.py +16 -0
  29. nautobot/dcim/api/serializers.py +13 -0
  30. nautobot/dcim/api/urls.py +1 -0
  31. nautobot/dcim/api/views.py +20 -0
  32. nautobot/dcim/apps.py +1 -0
  33. nautobot/dcim/factory.py +11 -0
  34. nautobot/dcim/filters/__init__.py +116 -0
  35. nautobot/dcim/filters/mixins.py +2 -1
  36. nautobot/dcim/forms.py +205 -19
  37. nautobot/dcim/migrations/0070_modulefamily_models.py +92 -0
  38. nautobot/dcim/models/__init__.py +2 -0
  39. nautobot/dcim/models/device_component_templates.py +14 -0
  40. nautobot/dcim/models/device_components.py +13 -1
  41. nautobot/dcim/models/devices.py +72 -0
  42. nautobot/dcim/navigation.py +16 -0
  43. nautobot/dcim/tables/__init__.py +2 -0
  44. nautobot/dcim/tables/devices.py +50 -0
  45. nautobot/dcim/tables/devicetypes.py +35 -1
  46. nautobot/dcim/tables/template_code.py +2 -0
  47. nautobot/dcim/templates/dcim/controller/base.html +1 -9
  48. nautobot/dcim/templates/dcim/controller_retrieve.html +2 -83
  49. nautobot/dcim/templates/dcim/controller_wirelessnetworks.html +2 -25
  50. nautobot/dcim/templates/dcim/controllermanageddevicegroup_retrieve.html +1 -90
  51. nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
  52. nautobot/dcim/templates/dcim/interfaceredundancygroup_retrieve.html +1 -63
  53. nautobot/dcim/templates/dcim/location.html +2 -249
  54. nautobot/dcim/templates/dcim/location_edit.html +2 -38
  55. nautobot/dcim/templates/dcim/location_retrieve.html +249 -0
  56. nautobot/dcim/templates/dcim/location_update.html +38 -0
  57. nautobot/dcim/templates/dcim/module_update.html +1 -0
  58. nautobot/dcim/templates/dcim/modulebay_retrieve.html +93 -1
  59. nautobot/dcim/templates/dcim/modulefamily_retrieve.html +31 -0
  60. nautobot/dcim/templates/dcim/moduletype_retrieve.html +6 -0
  61. nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -160
  62. nautobot/dcim/templates/dcim/virtualchassis.html +2 -51
  63. nautobot/dcim/templates/dcim/virtualchassis_add.html +2 -22
  64. nautobot/dcim/templates/dcim/virtualchassis_create.html +22 -0
  65. nautobot/dcim/templates/dcim/virtualchassis_edit.html +2 -93
  66. nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +51 -0
  67. nautobot/dcim/templates/dcim/virtualchassis_update.html +93 -0
  68. nautobot/dcim/tests/test_api.py +35 -0
  69. nautobot/dcim/tests/test_filters.py +102 -3
  70. nautobot/dcim/tests/test_models.py +146 -0
  71. nautobot/dcim/tests/test_views.py +70 -97
  72. nautobot/dcim/urls.py +5 -80
  73. nautobot/dcim/views.py +584 -342
  74. nautobot/extras/api/views.py +9 -2
  75. nautobot/extras/datasources/git.py +9 -1
  76. nautobot/extras/forms/forms.py +9 -5
  77. nautobot/extras/jobs.py +4 -2
  78. nautobot/extras/jobs_ui.py +208 -0
  79. nautobot/extras/models/datasources.py +5 -8
  80. nautobot/extras/models/jobs.py +5 -0
  81. nautobot/extras/models/tags.py +4 -0
  82. nautobot/extras/plugins/__init__.py +3 -0
  83. nautobot/extras/tables.py +40 -3
  84. nautobot/extras/templates/extras/configcontext.html +2 -220
  85. nautobot/extras/templates/extras/configcontext_edit.html +2 -50
  86. nautobot/extras/templates/extras/configcontext_retrieve.html +2 -0
  87. nautobot/extras/templates/extras/configcontext_update.html +50 -0
  88. nautobot/extras/templates/extras/configcontextschema.html +2 -48
  89. nautobot/extras/templates/extras/configcontextschema_edit.html +2 -19
  90. nautobot/extras/templates/extras/configcontextschema_retrieve.html +48 -0
  91. nautobot/extras/templates/extras/configcontextschema_update.html +19 -0
  92. nautobot/extras/templates/extras/inc/configcontext_data.html +1 -0
  93. nautobot/extras/templates/extras/inc/configcontext_format.html +6 -0
  94. nautobot/extras/templates/extras/job_detail.html +1 -326
  95. nautobot/extras/templates/extras/job_edit.html +12 -6
  96. nautobot/extras/templates/extras/tag.html +2 -52
  97. nautobot/extras/templates/extras/tag_edit.html +2 -15
  98. nautobot/extras/templates/extras/tag_retrieve.html +2 -0
  99. nautobot/extras/templates/extras/tag_update.html +15 -0
  100. nautobot/extras/templates/extras/team_retrieve.html +2 -2
  101. nautobot/extras/tests/test_api.py +15 -15
  102. nautobot/extras/tests/test_filters.py +4 -4
  103. nautobot/extras/tests/test_jobs.py +23 -10
  104. nautobot/extras/tests/test_models.py +19 -8
  105. nautobot/extras/tests/test_plugins.py +6 -3
  106. nautobot/extras/tests/test_views.py +66 -11
  107. nautobot/extras/urls.py +4 -134
  108. nautobot/extras/views.py +186 -178
  109. nautobot/ipam/models.py +19 -4
  110. nautobot/ipam/tables.py +19 -0
  111. nautobot/ipam/templates/ipam/vlan.html +2 -84
  112. nautobot/ipam/templates/ipam/vlan_edit.html +2 -24
  113. nautobot/ipam/templates/ipam/vlan_retrieve.html +84 -0
  114. nautobot/ipam/templates/ipam/vlan_update.html +24 -0
  115. nautobot/ipam/tests/test_views.py +5 -0
  116. nautobot/ipam/urls.py +1 -21
  117. nautobot/ipam/views.py +45 -70
  118. nautobot/project-static/docs/404.html +33 -10
  119. nautobot/project-static/docs/apps/index.html +33 -10
  120. nautobot/project-static/docs/apps/nautobot-apps.html +33 -10
  121. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js → bundle.56ea9cef.min.js} +2 -2
  122. nautobot/project-static/docs/assets/javascripts/{bundle.13a4f30d.min.js.map → bundle.56ea9cef.min.js.map} +2 -2
  123. nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +33 -10
  124. nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +33 -10
  125. nautobot/project-static/docs/code-reference/nautobot/apps/api.html +33 -10
  126. nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +33 -10
  127. nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +33 -10
  128. nautobot/project-static/docs/code-reference/nautobot/apps/config.html +33 -10
  129. nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +33 -10
  130. nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +33 -10
  131. nautobot/project-static/docs/code-reference/nautobot/apps/events.html +33 -10
  132. nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +33 -10
  133. nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +33 -10
  134. nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +33 -10
  135. nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +33 -10
  136. nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +33 -10
  137. nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +33 -10
  138. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +33 -10
  139. nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +33 -10
  140. nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +33 -10
  141. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +33 -10
  142. nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +122 -10
  143. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +33 -10
  144. nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +33 -10
  145. nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +33 -10
  146. nautobot/project-static/docs/code-reference/nautobot/apps/views.html +33 -10
  147. nautobot/project-static/docs/development/apps/api/configuration-view.html +33 -10
  148. nautobot/project-static/docs/development/apps/api/database-backend-config.html +33 -10
  149. nautobot/project-static/docs/development/apps/api/models/django-admin.html +33 -10
  150. nautobot/project-static/docs/development/apps/api/models/global-search.html +33 -10
  151. nautobot/project-static/docs/development/apps/api/models/graphql.html +33 -10
  152. nautobot/project-static/docs/development/apps/api/models/index.html +33 -10
  153. nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +42 -10
  154. nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +33 -10
  155. nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +33 -10
  156. nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +33 -10
  157. nautobot/project-static/docs/development/apps/api/platform-features/index.html +33 -10
  158. nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +33 -10
  159. nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +33 -10
  160. nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +33 -10
  161. nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +34 -11
  162. nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +33 -10
  163. nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +33 -10
  164. nautobot/project-static/docs/development/apps/api/prometheus.html +33 -10
  165. nautobot/project-static/docs/development/apps/api/setup.html +33 -10
  166. nautobot/project-static/docs/development/apps/api/testing.html +33 -10
  167. nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +33 -10
  168. nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +33 -10
  169. nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +33 -10
  170. nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +33 -10
  171. nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +33 -10
  172. nautobot/project-static/docs/development/apps/api/views/base-template.html +33 -10
  173. nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +33 -10
  174. nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +33 -10
  175. nautobot/project-static/docs/development/apps/api/views/help-documentation.html +33 -10
  176. nautobot/project-static/docs/development/apps/api/views/index.html +33 -10
  177. nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +33 -10
  178. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +33 -10
  179. nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +33 -10
  180. nautobot/project-static/docs/development/apps/api/views/notes.html +33 -10
  181. nautobot/project-static/docs/development/apps/api/views/rest-api.html +33 -10
  182. nautobot/project-static/docs/development/apps/api/views/urls.html +33 -10
  183. nautobot/project-static/docs/development/apps/index.html +33 -10
  184. nautobot/project-static/docs/development/apps/migration/code-updates.html +33 -10
  185. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +33 -10
  186. nautobot/project-static/docs/development/apps/migration/from-v1.html +33 -10
  187. nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +33 -10
  188. nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +33 -10
  189. nautobot/project-static/docs/development/apps/migration/model-updates/global.html +33 -10
  190. nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +33 -10
  191. nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +33 -10
  192. nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +33 -10
  193. nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +33 -10
  194. nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +33 -10
  195. nautobot/project-static/docs/development/apps/porting-from-netbox.html +33 -10
  196. nautobot/project-static/docs/development/core/application-registry.html +33 -10
  197. nautobot/project-static/docs/development/core/best-practices.html +33 -10
  198. nautobot/project-static/docs/development/core/bootstrap-ui.html +33 -10
  199. nautobot/project-static/docs/development/core/caching.html +33 -10
  200. nautobot/project-static/docs/development/core/controllers.html +33 -10
  201. nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +33 -10
  202. nautobot/project-static/docs/development/core/generic-views.html +33 -10
  203. nautobot/project-static/docs/development/core/getting-started.html +33 -10
  204. nautobot/project-static/docs/development/core/homepage.html +33 -10
  205. nautobot/project-static/docs/development/core/index.html +33 -10
  206. nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +33 -10
  207. nautobot/project-static/docs/development/core/model-checklist.html +33 -10
  208. nautobot/project-static/docs/development/core/model-features.html +33 -10
  209. nautobot/project-static/docs/development/core/natural-keys.html +33 -10
  210. nautobot/project-static/docs/development/core/navigation-menu.html +33 -10
  211. nautobot/project-static/docs/development/core/release-checklist.html +33 -10
  212. nautobot/project-static/docs/development/core/role-internals.html +33 -10
  213. nautobot/project-static/docs/development/core/settings.html +33 -10
  214. nautobot/project-static/docs/development/core/style-guide.html +33 -10
  215. nautobot/project-static/docs/development/core/templates.html +33 -10
  216. nautobot/project-static/docs/development/core/testing.html +33 -10
  217. nautobot/project-static/docs/development/core/ui-component-framework.html +33 -10
  218. nautobot/project-static/docs/development/core/user-preferences.html +33 -10
  219. nautobot/project-static/docs/development/index.html +33 -10
  220. nautobot/project-static/docs/development/jobs/getting-started.html +33 -10
  221. nautobot/project-static/docs/development/jobs/index.html +33 -10
  222. nautobot/project-static/docs/development/jobs/installation.html +33 -10
  223. nautobot/project-static/docs/development/jobs/job-extensions.html +33 -10
  224. nautobot/project-static/docs/development/jobs/job-logging.html +33 -10
  225. nautobot/project-static/docs/development/jobs/job-patterns.html +33 -10
  226. nautobot/project-static/docs/development/jobs/job-structure.html +33 -10
  227. nautobot/project-static/docs/development/jobs/migration/from-v1.html +33 -10
  228. nautobot/project-static/docs/development/jobs/testing.html +33 -10
  229. nautobot/project-static/docs/index.html +33 -10
  230. nautobot/project-static/docs/insert-analytics.sh +36 -0
  231. nautobot/project-static/docs/objects.inv +0 -0
  232. nautobot/project-static/docs/overview/application_stack.html +33 -10
  233. nautobot/project-static/docs/overview/design_philosophy.html +33 -10
  234. nautobot/project-static/docs/release-notes/index.html +33 -10
  235. nautobot/project-static/docs/release-notes/version-1.0.html +33 -10
  236. nautobot/project-static/docs/release-notes/version-1.1.html +33 -10
  237. nautobot/project-static/docs/release-notes/version-1.2.html +33 -10
  238. nautobot/project-static/docs/release-notes/version-1.3.html +33 -10
  239. nautobot/project-static/docs/release-notes/version-1.4.html +33 -10
  240. nautobot/project-static/docs/release-notes/version-1.5.html +33 -10
  241. nautobot/project-static/docs/release-notes/version-1.6.html +33 -10
  242. nautobot/project-static/docs/release-notes/version-2.0.html +33 -10
  243. nautobot/project-static/docs/release-notes/version-2.1.html +33 -10
  244. nautobot/project-static/docs/release-notes/version-2.2.html +33 -10
  245. nautobot/project-static/docs/release-notes/version-2.3.html +33 -10
  246. nautobot/project-static/docs/release-notes/version-2.4.html +363 -10
  247. nautobot/project-static/docs/requirements.txt +1 -1
  248. nautobot/project-static/docs/search/search_index.json +1 -1
  249. nautobot/project-static/docs/sitemap.xml +302 -298
  250. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  251. nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +33 -10
  252. nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +33 -10
  253. nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +33 -10
  254. nautobot/project-static/docs/user-guide/administration/configuration/index.html +33 -10
  255. nautobot/project-static/docs/user-guide/administration/configuration/redis.html +33 -10
  256. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +33 -10
  257. nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +33 -10
  258. nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +33 -10
  259. nautobot/project-static/docs/user-guide/administration/guides/docker.html +33 -10
  260. nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +33 -10
  261. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +33 -10
  262. nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +33 -10
  263. nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +33 -10
  264. nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +33 -10
  265. nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +33 -10
  266. nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +33 -10
  267. nautobot/project-static/docs/user-guide/administration/installation/app-install.html +33 -10
  268. nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +33 -10
  269. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +33 -10
  270. nautobot/project-static/docs/user-guide/administration/installation/index.html +33 -10
  271. nautobot/project-static/docs/user-guide/administration/installation/install_system.html +33 -10
  272. nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +33 -10
  273. nautobot/project-static/docs/user-guide/administration/installation/services.html +33 -10
  274. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +33 -10
  275. nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +33 -10
  276. nautobot/project-static/docs/user-guide/administration/security/index.html +33 -10
  277. nautobot/project-static/docs/user-guide/administration/security/notices.html +33 -10
  278. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +33 -10
  279. nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +33 -10
  280. nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +33 -10
  281. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +33 -10
  282. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +33 -10
  283. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +33 -10
  284. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +33 -10
  285. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +33 -10
  286. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +33 -10
  287. nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +33 -10
  288. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +33 -10
  289. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +33 -10
  290. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +33 -10
  291. nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +33 -10
  292. nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +33 -10
  293. nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +33 -10
  294. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +33 -10
  295. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +33 -10
  296. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +33 -10
  297. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +33 -10
  298. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +33 -10
  299. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +33 -10
  300. nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +33 -10
  301. nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +33 -10
  302. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +33 -10
  303. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +33 -10
  304. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +33 -10
  305. nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +33 -10
  306. nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +33 -10
  307. nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +33 -10
  308. nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +33 -10
  309. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +33 -10
  310. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +33 -10
  311. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +33 -10
  312. nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +45 -22
  313. nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +33 -10
  314. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +33 -10
  315. nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +33 -10
  316. nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +33 -10
  317. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +33 -10
  318. nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +33 -10
  319. nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +33 -10
  320. nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +33 -10
  321. nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +33 -10
  322. nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +33 -10
  323. nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +37 -10
  324. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +37 -10
  325. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +37 -10
  326. nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +10261 -0
  327. nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +36 -13
  328. nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +33 -10
  329. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +33 -10
  330. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +33 -10
  331. nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +33 -10
  332. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +33 -10
  333. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +33 -10
  334. nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +33 -10
  335. nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +33 -10
  336. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +33 -10
  337. nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +33 -10
  338. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +33 -10
  339. nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +33 -10
  340. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +33 -10
  341. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +33 -10
  342. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +33 -10
  343. nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +33 -10
  344. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +33 -10
  345. nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +33 -10
  346. nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +33 -10
  347. nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +33 -10
  348. nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +33 -10
  349. nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +33 -10
  350. nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +33 -10
  351. nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +33 -10
  352. nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +33 -10
  353. nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +33 -10
  354. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +33 -10
  355. nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +33 -10
  356. nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +33 -10
  357. nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +33 -10
  358. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +33 -10
  359. nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +33 -10
  360. nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +33 -10
  361. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +33 -10
  362. nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +33 -10
  363. nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +33 -10
  364. nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +33 -10
  365. nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +33 -10
  366. nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +33 -10
  367. nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +33 -10
  368. nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +33 -10
  369. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +33 -10
  370. nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +33 -10
  371. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +33 -10
  372. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +33 -10
  373. nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +33 -10
  374. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +33 -10
  375. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +33 -10
  376. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +33 -10
  377. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +33 -10
  378. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +33 -10
  379. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +33 -10
  380. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +44 -18
  381. nautobot/project-static/docs/user-guide/feature-guides/graphql.html +33 -10
  382. nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +33 -10
  383. nautobot/project-static/docs/user-guide/feature-guides/relationships.html +33 -10
  384. nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +33 -10
  385. nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +33 -10
  386. nautobot/project-static/docs/user-guide/index.html +33 -10
  387. nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +33 -10
  388. nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +33 -10
  389. nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +33 -10
  390. nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +33 -10
  391. nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +33 -10
  392. nautobot/project-static/docs/user-guide/platform-functionality/events.html +33 -10
  393. nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +33 -10
  394. nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +33 -10
  395. nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +39 -11
  396. nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +33 -10
  397. nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +33 -10
  398. nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +33 -10
  399. nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +33 -10
  400. nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +33 -10
  401. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +33 -10
  402. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +33 -10
  403. nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +33 -10
  404. nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +33 -10
  405. nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +33 -10
  406. nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +33 -10
  407. nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +33 -10
  408. nautobot/project-static/docs/user-guide/platform-functionality/note.html +33 -10
  409. nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +33 -10
  410. nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +33 -10
  411. nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +33 -10
  412. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +33 -10
  413. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +33 -10
  414. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +33 -10
  415. nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +33 -10
  416. nautobot/project-static/docs/user-guide/platform-functionality/role.html +33 -10
  417. nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +33 -10
  418. nautobot/project-static/docs/user-guide/platform-functionality/secret.html +33 -10
  419. nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +33 -10
  420. nautobot/project-static/docs/user-guide/platform-functionality/status.html +33 -10
  421. nautobot/project-static/docs/user-guide/platform-functionality/tag.html +33 -10
  422. nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +33 -10
  423. nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +33 -10
  424. nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +33 -10
  425. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +33 -10
  426. nautobot/tenancy/tables.py +2 -0
  427. nautobot/virtualization/tests/test_views.py +1 -1
  428. nautobot/wireless/forms.py +0 -1
  429. nautobot/wireless/models.py +1 -1
  430. nautobot/wireless/navigation.py +1 -1
  431. nautobot/wireless/tables.py +18 -3
  432. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/METADATA +4 -4
  433. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/RECORD +439 -419
  434. /nautobot/dcim/templates/dcim/{platform_edit.html → platform_create.html} +0 -0
  435. /nautobot/extras/test_jobs/{pass.py → pass_job.py} +0 -0
  436. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/LICENSE.txt +0 -0
  437. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/NOTICE +0 -0
  438. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/WHEEL +0 -0
  439. {nautobot-2.4.10.dist-info → nautobot-2.4.12.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,92 @@
1
+ # Generated by Django 4.2.19 on 2025-03-18 17:22
2
+
3
+ import uuid
4
+
5
+ import django.core.serializers.json
6
+ from django.db import migrations, models
7
+ import django.db.models.deletion
8
+
9
+ import nautobot.core.models.fields
10
+ import nautobot.extras.models.mixins
11
+
12
+
13
+ class Migration(migrations.Migration):
14
+ dependencies = [
15
+ ("extras", "0122_add_graphqlquery_owner_content_type"),
16
+ ("dcim", "0069_softwareimagefile_external_integration"),
17
+ ]
18
+
19
+ operations = [
20
+ migrations.AddField(
21
+ model_name="modulebay",
22
+ name="requires_first_party_modules",
23
+ field=models.BooleanField(default=False),
24
+ ),
25
+ migrations.AddField(
26
+ model_name="modulebaytemplate",
27
+ name="requires_first_party_modules",
28
+ field=models.BooleanField(default=False),
29
+ ),
30
+ migrations.CreateModel(
31
+ name="ModuleFamily",
32
+ fields=[
33
+ (
34
+ "id",
35
+ models.UUIDField(
36
+ default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True
37
+ ),
38
+ ),
39
+ ("created", models.DateTimeField(auto_now_add=True, null=True)),
40
+ ("last_updated", models.DateTimeField(auto_now=True, null=True)),
41
+ (
42
+ "_custom_field_data",
43
+ models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder),
44
+ ),
45
+ ("name", models.CharField(max_length=255, unique=True)),
46
+ ("description", models.CharField(blank=True, max_length=255)),
47
+ ("tags", nautobot.core.models.fields.TagsField(through="extras.TaggedItem", to="extras.Tag")),
48
+ ],
49
+ options={
50
+ "verbose_name_plural": "module families",
51
+ "ordering": ["name"],
52
+ },
53
+ bases=(
54
+ nautobot.extras.models.mixins.DynamicGroupMixin,
55
+ nautobot.extras.models.mixins.NotesMixin,
56
+ models.Model,
57
+ ),
58
+ ),
59
+ migrations.AddField(
60
+ model_name="modulebay",
61
+ name="module_family",
62
+ field=models.ForeignKey(
63
+ blank=True,
64
+ null=True,
65
+ on_delete=django.db.models.deletion.PROTECT,
66
+ related_name="module_bays",
67
+ to="dcim.modulefamily",
68
+ ),
69
+ ),
70
+ migrations.AddField(
71
+ model_name="modulebaytemplate",
72
+ name="module_family",
73
+ field=models.ForeignKey(
74
+ blank=True,
75
+ null=True,
76
+ on_delete=django.db.models.deletion.PROTECT,
77
+ related_name="module_bay_templates",
78
+ to="dcim.modulefamily",
79
+ ),
80
+ ),
81
+ migrations.AddField(
82
+ model_name="moduletype",
83
+ name="module_family",
84
+ field=models.ForeignKey(
85
+ blank=True,
86
+ null=True,
87
+ on_delete=django.db.models.deletion.PROTECT,
88
+ related_name="module_types",
89
+ to="dcim.modulefamily",
90
+ ),
91
+ ),
92
+ ]
@@ -38,6 +38,7 @@ from .devices import (
38
38
  InterfaceVDCAssignment,
39
39
  Manufacturer,
40
40
  Module,
41
+ ModuleFamily,
41
42
  ModuleType,
42
43
  Platform,
43
44
  SoftwareImageFile,
@@ -81,6 +82,7 @@ __all__ = (
81
82
  "Module",
82
83
  "ModuleBay",
83
84
  "ModuleBayTemplate",
85
+ "ModuleFamily",
84
86
  "ModuleType",
85
87
  "PathEndpoint",
86
88
  "Platform",
@@ -481,6 +481,18 @@ class ModuleBayTemplate(ModularComponentTemplateModel):
481
481
  )
482
482
  label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
483
483
  description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
484
+ module_family = models.ForeignKey(
485
+ to="dcim.ModuleFamily",
486
+ on_delete=models.PROTECT,
487
+ related_name="module_bay_templates",
488
+ blank=True,
489
+ null=True,
490
+ help_text="Module family that can be installed in this bay. Leave blank for no restriction.",
491
+ )
492
+ requires_first_party_modules = models.BooleanField(
493
+ default=False,
494
+ help_text="This bay will only accept modules from the same manufacturer as the parent device or module",
495
+ )
484
496
 
485
497
  natural_key_field_names = ["device_type", "module_type", "name"]
486
498
 
@@ -505,6 +517,8 @@ class ModuleBayTemplate(ModularComponentTemplateModel):
505
517
  position=self.position,
506
518
  label=self.label,
507
519
  description=self.description,
520
+ module_family=self.module_family,
521
+ requires_first_party_modules=self.requires_first_party_modules,
508
522
  _custom_field_data=custom_field_data,
509
523
  )
510
524
 
@@ -1218,6 +1218,18 @@ class ModuleBay(PrimaryModel):
1218
1218
  blank=True,
1219
1219
  null=True,
1220
1220
  )
1221
+ module_family = models.ForeignKey(
1222
+ to="dcim.ModuleFamily",
1223
+ on_delete=models.PROTECT,
1224
+ related_name="module_bays",
1225
+ blank=True,
1226
+ null=True,
1227
+ help_text="Module family that can be installed in this bay",
1228
+ )
1229
+ requires_first_party_modules = models.BooleanField(
1230
+ default=False,
1231
+ help_text="This bay will only accept modules from the same manufacturer as the parent device or module",
1232
+ )
1221
1233
  name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, db_index=True)
1222
1234
  _name = NaturalOrderingField(target_field="name", max_length=CHARFIELD_MAX_LENGTH, blank=True, db_index=True)
1223
1235
  position = models.CharField(
@@ -1228,7 +1240,7 @@ class ModuleBay(PrimaryModel):
1228
1240
  label = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Physical label")
1229
1241
  description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
1230
1242
 
1231
- clone_fields = ["parent_device", "parent_module"]
1243
+ clone_fields = ["parent_device", "parent_module", "module_family", "requires_first_party_modules"]
1232
1244
 
1233
1245
  # The recursive nature of this model combined with the fact that it can be a child of a
1234
1246
  # device or location makes our natural key implementation unusable, so just use the pk
@@ -30,6 +30,7 @@ from nautobot.dcim.utils import get_all_network_driver_mappings, get_network_dri
30
30
  from nautobot.extras.models import ChangeLoggedModel, ConfigContextModel, RoleField, StatusField
31
31
  from nautobot.extras.querysets import ConfigContextModelQuerySet
32
32
  from nautobot.extras.utils import extras_features
33
+ from nautobot.wireless.models import ControllerManagedDeviceGroupWirelessNetworkAssignment
33
34
 
34
35
  from .device_components import (
35
36
  ConsolePort,
@@ -1456,6 +1457,15 @@ class Controller(PrimaryModel):
1456
1457
  return format_html('<span class="text-muted">&mdash;</span>')
1457
1458
  return format_html_join(" ", '<span class="label label-default">{}</span>', ((v,) for v in self.capabilities))
1458
1459
 
1460
+ @property
1461
+ def wireless_network_assignments(self):
1462
+ """
1463
+ Returns all Controller Managed Device Group Wireless Network Assignment linked to this controller.
1464
+ """
1465
+ return ControllerManagedDeviceGroupWirelessNetworkAssignment.objects.filter(
1466
+ controller_managed_device_group__controller=self
1467
+ )
1468
+
1459
1469
 
1460
1470
  @extras_features(
1461
1471
  "custom_links",
@@ -1550,6 +1560,30 @@ class ControllerManagedDeviceGroup(TreeModel, PrimaryModel):
1550
1560
  #
1551
1561
 
1552
1562
 
1563
+ @extras_features(
1564
+ "custom_links",
1565
+ "custom_validators",
1566
+ "export_templates",
1567
+ "graphql",
1568
+ "webhooks",
1569
+ )
1570
+ class ModuleFamily(PrimaryModel):
1571
+ """
1572
+ A ModuleFamily represents a classification of ModuleTypes.
1573
+ It is used to enforce compatibility between ModuleBays and Modules.
1574
+ """
1575
+
1576
+ name = models.CharField(max_length=CHARFIELD_MAX_LENGTH, unique=True)
1577
+ description = models.CharField(max_length=CHARFIELD_MAX_LENGTH, blank=True)
1578
+
1579
+ class Meta:
1580
+ ordering = ["name"]
1581
+ verbose_name_plural = "module families"
1582
+
1583
+ def __str__(self):
1584
+ return self.name
1585
+
1586
+
1553
1587
  # TODO: 5840 - Translate comments field from devicetype library, Nautobot doesn't use that field for ModuleType
1554
1588
  @extras_features(
1555
1589
  "custom_links",
@@ -1577,6 +1611,13 @@ class ModuleType(PrimaryModel):
1577
1611
  """
1578
1612
 
1579
1613
  manufacturer = models.ForeignKey(to="dcim.Manufacturer", on_delete=models.PROTECT, related_name="module_types")
1614
+ module_family = models.ForeignKey(
1615
+ to="dcim.ModuleFamily",
1616
+ on_delete=models.PROTECT,
1617
+ related_name="module_types",
1618
+ blank=True,
1619
+ null=True,
1620
+ )
1580
1621
  model = models.CharField(max_length=CHARFIELD_MAX_LENGTH)
1581
1622
  part_number = models.CharField(
1582
1623
  max_length=CHARFIELD_MAX_LENGTH, blank=True, help_text="Discrete part number (optional)"
@@ -1585,6 +1626,7 @@ class ModuleType(PrimaryModel):
1585
1626
 
1586
1627
  clone_fields = [
1587
1628
  "manufacturer",
1629
+ "module_family",
1588
1630
  ]
1589
1631
 
1590
1632
  class Meta:
@@ -1810,6 +1852,36 @@ class Module(PrimaryModel):
1810
1852
  {"location": f'Modules may not associate to locations of type "{self.location.location_type}".'}
1811
1853
  )
1812
1854
 
1855
+ # Validate module family compatibility
1856
+ if self.parent_module_bay and self.parent_module_bay.module_family:
1857
+ if self.module_type.module_family != self.parent_module_bay.module_family:
1858
+ module_family_name = self.parent_module_bay.module_family.name
1859
+ if self.module_type.module_family is None:
1860
+ module_type_family = "not assigned to a family"
1861
+ else:
1862
+ module_type_family = f"in the family {self.module_type.module_family.name}"
1863
+ raise ValidationError(
1864
+ {
1865
+ "module_type": f"The selected module bay requires a module type in the family {module_family_name}, "
1866
+ f"but the selected module type is {module_type_family}."
1867
+ }
1868
+ )
1869
+
1870
+ # Validate module manufacturer constraint
1871
+ if self.parent_module_bay and self.parent_module_bay.requires_first_party_modules:
1872
+ if self.parent_module_bay.parent_device:
1873
+ parent_mfr = self.parent_module_bay.parent_device.device_type.manufacturer
1874
+ elif self.parent_module_bay.parent_module:
1875
+ parent_mfr = self.parent_module_bay.parent_module.module_type.manufacturer
1876
+ else:
1877
+ parent_mfr = None
1878
+ if parent_mfr and self.module_type.manufacturer != parent_mfr:
1879
+ raise ValidationError(
1880
+ {
1881
+ "module_type": "The selected module bay requires a module type from the same manufacturer as the parent device or module"
1882
+ }
1883
+ )
1884
+
1813
1885
  def save(self, *args, **kwargs):
1814
1886
  is_new = not self.present_in_database
1815
1887
 
@@ -293,6 +293,22 @@ menu_items = (
293
293
  ),
294
294
  ),
295
295
  ),
296
+ NavMenuItem(
297
+ link="dcim:modulefamily_list",
298
+ name="Module Families",
299
+ weight=300,
300
+ permissions=[
301
+ "dcim.view_modulefamily",
302
+ ],
303
+ buttons=(
304
+ NavMenuAddButton(
305
+ link="dcim:modulefamily_add",
306
+ permissions=[
307
+ "dcim.add_modulefamily",
308
+ ],
309
+ ),
310
+ ),
311
+ ),
296
312
  ),
297
313
  ),
298
314
  NavMenuGroup(
@@ -30,6 +30,7 @@ from .devices import (
30
30
  InterfaceTable,
31
31
  InventoryItemTable,
32
32
  ModuleBayTable,
33
+ ModuleFamilyTable,
33
34
  ModuleModuleBayTable,
34
35
  ModuleTable,
35
36
  PlatformTable,
@@ -104,6 +105,7 @@ __all__ = (
104
105
  "ManufacturerTable",
105
106
  "ModuleBayTable",
106
107
  "ModuleBayTemplateTable",
108
+ "ModuleFamilyTable",
107
109
  "ModuleModuleBayTable",
108
110
  "ModuleTable",
109
111
  "ModuleTypeTable",
@@ -26,6 +26,7 @@ from nautobot.dcim.models import (
26
26
  InventoryItem,
27
27
  Module,
28
28
  ModuleBay,
29
+ ModuleFamily,
29
30
  Platform,
30
31
  PowerOutlet,
31
32
  PowerPort,
@@ -86,6 +87,7 @@ __all__ = (
86
87
  "InterfaceTable",
87
88
  "InventoryItemTable",
88
89
  "ModuleBayTable",
90
+ "ModuleFamilyTable",
89
91
  "ModuleModuleBayTable",
90
92
  "ModuleTable",
91
93
  "PlatformTable",
@@ -179,6 +181,7 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
179
181
  software_version = tables.Column(linkify=True, verbose_name="Software Version")
180
182
  secrets_group = tables.Column(linkify=True)
181
183
  capabilities = tables.Column(orderable=False, accessor="controller_managed_device_group.capabilities")
184
+ manufacturer = tables.Column(orderable=False, accessor="device_type.manufacturer")
182
185
  tags = TagColumn(url_name="dcim:device_list")
183
186
  actions = ButtonsColumn(Device)
184
187
 
@@ -211,6 +214,7 @@ class DeviceTable(StatusTableMixin, RoleTableMixin, BaseTable):
211
214
  "controller_managed_device_group",
212
215
  "secrets_group",
213
216
  "capabilities",
217
+ "manufacturer",
214
218
  "tags",
215
219
  "actions",
216
220
  )
@@ -275,6 +279,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
275
279
  )
276
280
  location = tables.Column(linkify=True)
277
281
  tenant = TenantColumn()
282
+ module_type__module_family = tables.Column(linkify=True, verbose_name="Family")
278
283
  tags = TagColumn(url_name="dcim:module_list")
279
284
  actions = ButtonsColumn(Module, prepend_template=MODULE_BUTTONS)
280
285
 
@@ -283,6 +288,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
283
288
  fields = (
284
289
  "pk",
285
290
  "module_type",
291
+ "module_family",
286
292
  "parent_module_bay",
287
293
  "location",
288
294
  "serial",
@@ -296,6 +302,7 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
296
302
  default_columns = (
297
303
  "pk",
298
304
  "module_type",
305
+ "module_family",
299
306
  "parent_module_bay",
300
307
  "location",
301
308
  "serial",
@@ -307,6 +314,40 @@ class ModuleTable(StatusTableMixin, RoleTableMixin, BaseTable):
307
314
  )
308
315
 
309
316
 
317
+ class ModuleFamilyTable(BaseTable):
318
+ pk = ToggleColumn()
319
+ name = tables.Column(linkify=True)
320
+ module_type_count = LinkedCountColumn(
321
+ viewname="dcim:moduletype_list", url_params={"module_family": "pk"}, verbose_name="Module Types"
322
+ )
323
+ module_bay_count = LinkedCountColumn(
324
+ viewname="dcim:modulebay_list", url_params={"module_family": "pk"}, verbose_name="Module Bays"
325
+ )
326
+ tags = TagColumn()
327
+ actions = ButtonsColumn(ModuleFamily)
328
+
329
+ class Meta(BaseTable.Meta):
330
+ model = ModuleFamily
331
+ fields = (
332
+ "pk",
333
+ "name",
334
+ "description",
335
+ "module_type_count",
336
+ "module_bay_count",
337
+ "tags",
338
+ "created",
339
+ "last_updated",
340
+ "actions",
341
+ )
342
+ default_columns = (
343
+ "name",
344
+ "description",
345
+ "module_type_count",
346
+ "module_bay_count",
347
+ "actions",
348
+ )
349
+
350
+
310
351
  #
311
352
  # Device components
312
353
  #
@@ -943,6 +984,7 @@ class ModuleBayTable(BaseTable):
943
984
  installed_module = tables.Column(linkify=True, verbose_name="Installed Module")
944
985
  installed_module__status = ColoredLabelColumn()
945
986
  tags = TagColumn(url_name="dcim:devicebay_list")
987
+ module_family = tables.Column(linkify=True, verbose_name="Family")
946
988
 
947
989
  class Meta(BaseTable.Meta):
948
990
  model = ModuleBay
@@ -953,6 +995,7 @@ class ModuleBayTable(BaseTable):
953
995
  "name",
954
996
  "position",
955
997
  "label",
998
+ "module_family",
956
999
  "description",
957
1000
  "installed_module",
958
1001
  "installed_module__status",
@@ -965,6 +1008,7 @@ class ModuleBayTable(BaseTable):
965
1008
  "name",
966
1009
  "position",
967
1010
  "label",
1011
+ "module_family",
968
1012
  "description",
969
1013
  "installed_module",
970
1014
  "installed_module__status",
@@ -1008,8 +1052,10 @@ class DeviceModuleBayTable(ModuleBayTable):
1008
1052
  '"></i> <a href="{{ record.get_absolute_url }}">{{ value }}</a>',
1009
1053
  attrs={"td": {"class": "text-nowrap"}},
1010
1054
  )
1055
+ module_family = tables.Column(linkify=True, verbose_name="Family")
1011
1056
  installed_module = tables.Column(linkify=True, verbose_name="Installed Module")
1012
1057
  installed_module__status = ColoredLabelColumn(verbose_name="Installed Module Status")
1058
+ requires_first_party_modules = BooleanColumn(verbose_name="First-Party Only")
1013
1059
  actions = ButtonsColumn(model=ModuleBay, buttons=("edit", "delete"), prepend_template=MODULEBAY_BUTTONS)
1014
1060
 
1015
1061
  class Meta(ModularDeviceComponentTable.Meta):
@@ -1018,6 +1064,8 @@ class DeviceModuleBayTable(ModuleBayTable):
1018
1064
  "pk",
1019
1065
  "name",
1020
1066
  "position",
1067
+ "module_family",
1068
+ "requires_first_party_modules",
1021
1069
  "installed_module",
1022
1070
  "installed_module__status",
1023
1071
  "label",
@@ -1029,6 +1077,8 @@ class DeviceModuleBayTable(ModuleBayTable):
1029
1077
  "pk",
1030
1078
  "name",
1031
1079
  "position",
1080
+ "module_family",
1081
+ "requires_first_party_modules",
1032
1082
  "installed_module",
1033
1083
  "installed_module__status",
1034
1084
  "actions",
@@ -158,6 +158,7 @@ class ModuleTypeTable(BaseTable):
158
158
  pk = ToggleColumn()
159
159
  manufacturer = tables.Column(linkify=True)
160
160
  model = tables.Column(linkify=True, verbose_name="Module Type")
161
+ module_family = tables.Column(linkify=True, verbose_name="Family")
161
162
  module_count = LinkedCountColumn(
162
163
  viewname="dcim:module_list",
163
164
  url_params={"module_type": "pk"},
@@ -172,6 +173,7 @@ class ModuleTypeTable(BaseTable):
172
173
  "model",
173
174
  "manufacturer",
174
175
  "part_number",
176
+ "module_family",
175
177
  "module_count",
176
178
  "tags",
177
179
  )
@@ -180,6 +182,7 @@ class ModuleTypeTable(BaseTable):
180
182
  "model",
181
183
  "manufacturer",
182
184
  "part_number",
185
+ "module_family",
183
186
  "module_count",
184
187
  )
185
188
 
@@ -333,8 +336,39 @@ class ModuleBayTemplateTable(ComponentTemplateTable):
333
336
  buttons=("edit", "delete"),
334
337
  return_url_extra=r"%3Ftab=modulebays",
335
338
  )
339
+ module_family = tables.Column(verbose_name="Family", linkify=True)
340
+ requires_first_party_modules = BooleanColumn(verbose_name="Requires First-Party Modules")
336
341
 
337
342
  class Meta(BaseTable.Meta):
338
343
  model = ModuleBayTemplate
339
- fields = ("pk", "name", "position", "label", "description", "actions")
344
+ fields = (
345
+ "pk",
346
+ "name",
347
+ "position",
348
+ "module_family",
349
+ "label",
350
+ "requires_first_party_modules",
351
+ "description",
352
+ "actions",
353
+ )
354
+ default_columns = (
355
+ "pk",
356
+ "name",
357
+ "position",
358
+ "module_family",
359
+ "label",
360
+ "requires_first_party_modules",
361
+ "description",
362
+ "actions",
363
+ )
364
+ field_order = (
365
+ "pk",
366
+ "name",
367
+ "position",
368
+ "module_family",
369
+ "label",
370
+ "requires_first_party_modules",
371
+ "description",
372
+ "actions",
373
+ )
340
374
  empty_text = "None"
@@ -93,7 +93,9 @@ LINKED_RECORD_COUNT = """
93
93
 
94
94
  TREE_LINK = """
95
95
  {% load helpers %}
96
+ {% if not table.hide_hierarchy_ui %}
96
97
  {% tree_hierarchy_ui_representation record.tree_depth|as_range table.hide_hierarchy_ui %}
98
+ {% endif %}
97
99
  <a href="{{ record.get_absolute_url }}">{{ record.name }}</a>
98
100
  """
99
101
 
@@ -1,10 +1,2 @@
1
1
  {% extends 'generic/object_retrieve.html' %}
2
- {% load helpers %}
3
-
4
- {% block extra_nav_tabs %}
5
- {% if 'wireless' in object.capabilities %}
6
- <li role="presentation" {% if active_tab == 'wireless-networks' %} class="active"{% endif %}>
7
- <a href="{% url 'dcim:controller_wirelessnetworks' pk=object.pk %}">Wireless Networks</a>
8
- </li>
9
- {% endif %}
10
- {% endblock extra_nav_tabs %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,83 +1,2 @@
1
- {% extends 'dcim/controller/base.html' %}
2
- {% load helpers %}
3
-
4
- {% block content_left_page %}
5
- <div class="panel panel-default">
6
- <div class="panel-heading">
7
- <strong>Controller</strong>
8
- </div>
9
- <div class="table-responsive">
10
- <table class="table table-hover panel-body attr-table">
11
- <tr>
12
- <td>Name</td>
13
- <td>{{ object.name|placeholder }}</td>
14
- </tr>
15
- <tr>
16
- <td>Status</td>
17
- <td>
18
- {{ object.status|hyperlinked_object_with_color }}
19
- </td>
20
- </tr>
21
- <tr>
22
- <td>Role</td>
23
- <td>{{ object.role|hyperlinked_object_with_color }}</td>
24
- </tr>
25
- <tr>
26
- <td>Capabilities</td>
27
- <td>{{ object.get_capabilities_display }}</td>
28
- </tr>
29
- <tr>
30
- <td>Location</td>
31
- <td>{{ object.location|hyperlinked_object }}</td>
32
- </tr>
33
- <tr>
34
- <td>Platform</td>
35
- <td>{{ object.platform|hyperlinked_object }}</td>
36
- </tr>
37
- {% include 'inc/tenant_table_row.html' %}
38
- <tr>
39
- <td>Description</td>
40
- <td>{{ object.description|placeholder }}</td>
41
- </tr>
42
- </table>
43
- </div>
44
- </div>
45
- {% endblock content_left_page %}
46
-
47
- {% block content_right_page %}
48
- <div class="panel panel-default">
49
- <div class="panel-heading">
50
- <strong>Integration</strong>
51
- </div>
52
- <div class="table-responsive">
53
- <table class="table table-hover panel-body attr-table">
54
- <tr>
55
- <td>External Integration</td>
56
- <td>{{ object.external_integration|hyperlinked_object }}</td>
57
- </tr>
58
- {% if object.controller_device %}
59
- <tr>
60
- <td>Controller Device</td>
61
- <td>{{ object.controller_device|hyperlinked_object }}</td>
62
- </tr>
63
- {% endif %}
64
- {% if object.controller_device_redundancy_group %}
65
- <tr>
66
- <td>Controller Device Redundancy Group</td>
67
- <td>{{ object.controller_device_redundancy_group|hyperlinked_object }}</td>
68
- </tr>
69
- {% endif %}
70
- </table>
71
- </div>
72
- </div>
73
- {% endblock content_right_page %}
74
-
75
- {% block content_full_width_page %}
76
- <div class="panel panel-default">
77
- <div class="panel-heading">
78
- <strong>Managed Devices</strong>
79
- </div>
80
- {% include 'responsive_table.html' with table=devices_table %}
81
- </div>
82
- {% include 'inc/paginator.html' with paginator=devices_table.paginator page=devices_table.page %}
83
- {% endblock content_full_width_page %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}
@@ -1,25 +1,2 @@
1
- {% extends 'dcim/controller/base.html' %}
2
- {% load helpers %}
3
-
4
- {% block content %}
5
- <form method="post">
6
- {% csrf_token %}
7
- <div class="panel panel-default">
8
- <div class="panel-heading">
9
- <strong>Wireless Networks</strong>
10
- <div class="pull-right noprint">
11
- {% if request.user.is_authenticated %}
12
- {% table_config_button_small wireless_networks_table %}
13
- {% endif %}
14
- </div>
15
- </div>
16
- {% include 'responsive_table.html' with table=wireless_networks_table %}
17
- </div>
18
- </form>
19
- {% table_config_form wireless_networks_table %}
20
- {% endblock content %}
21
-
22
- {% block javascript %}
23
- {{ block.super }}
24
- <script src="{% versioned_static 'js/tableconfig.js' %}"></script>
25
- {% endblock javascript %}
1
+ {% extends 'generic/object_retrieve.html' %}
2
+ {% comment %}3.0 TODO: remove this template, which only exists for backward compatibility with 2.4 and earlier{% endcomment %}