nautobot 2.2.9__py3-none-any.whl → 2.3.0__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.
- nautobot/apps/forms.py +4 -0
- nautobot/apps/models.py +10 -1
- nautobot/circuits/__init__.py +0 -1
- nautobot/circuits/apps.py +1 -0
- nautobot/circuits/factory.py +15 -3
- nautobot/circuits/filters.py +13 -0
- nautobot/circuits/forms.py +13 -0
- nautobot/circuits/migrations/0021_alter_circuit_status_alter_circuittermination__path.py +32 -0
- nautobot/circuits/migrations/0022_circuittermination_cloud_network.py +25 -0
- nautobot/circuits/models.py +16 -3
- nautobot/circuits/tables.py +16 -2
- nautobot/circuits/templates/circuits/circuittermination_create.html +10 -2
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +6 -0
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +6 -1
- nautobot/circuits/tests/test_api.py +7 -5
- nautobot/circuits/tests/test_filters.py +12 -5
- nautobot/circuits/tests/test_models.py +33 -2
- nautobot/circuits/views.py +2 -3
- nautobot/cloud/__init__.py +0 -0
- nautobot/cloud/api/__init__.py +0 -0
- nautobot/cloud/api/serializers.py +54 -0
- nautobot/cloud/api/urls.py +16 -0
- nautobot/cloud/api/views.py +48 -0
- nautobot/cloud/apps.py +13 -0
- nautobot/cloud/factory.py +113 -0
- nautobot/cloud/filters.py +187 -0
- nautobot/cloud/forms.py +339 -0
- nautobot/cloud/homepage.py +43 -0
- nautobot/cloud/migrations/0001_initial.py +304 -0
- nautobot/cloud/migrations/__init__.py +0 -0
- nautobot/cloud/models.py +246 -0
- nautobot/cloud/navigation.py +85 -0
- nautobot/cloud/tables.py +157 -0
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +43 -0
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +122 -0
- nautobot/cloud/templates/cloud/cloudnetwork_update.html +33 -0
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +111 -0
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +69 -0
- nautobot/cloud/templates/cloud/cloudservice_update.html +25 -0
- nautobot/cloud/tests/__init__.py +0 -0
- nautobot/cloud/tests/test_api.py +248 -0
- nautobot/cloud/tests/test_filters.py +125 -0
- nautobot/cloud/tests/test_models.py +43 -0
- nautobot/cloud/tests/test_views.py +153 -0
- nautobot/cloud/urls.py +14 -0
- nautobot/cloud/views.py +181 -0
- nautobot/core/__init__.py +0 -3
- nautobot/core/api/metadata.py +1 -0
- nautobot/core/api/parsers.py +7 -1
- nautobot/core/api/urls.py +1 -0
- nautobot/core/api/utils.py +1 -0
- nautobot/core/api/views.py +4 -0
- nautobot/core/apps/__init__.py +6 -3
- nautobot/core/constants.py +8 -0
- nautobot/core/factory.py +32 -1
- nautobot/core/filters.py +95 -13
- nautobot/core/forms/fields.py +10 -4
- nautobot/core/forms/forms.py +11 -3
- nautobot/core/forms/widgets.py +18 -1
- nautobot/core/graphql/schema.py +26 -4
- nautobot/core/jobs/__init__.py +16 -2
- nautobot/core/jobs/cleanup.py +100 -0
- nautobot/core/jobs/groups.py +38 -0
- nautobot/core/management/commands/generate_test_data.py +116 -3
- nautobot/core/models/__init__.py +34 -9
- nautobot/core/models/generics.py +19 -3
- nautobot/core/models/name_color_content_types.py +7 -28
- nautobot/core/models/querysets.py +4 -3
- nautobot/core/models/tree_queries.py +1 -1
- nautobot/core/models/utils.py +21 -5
- nautobot/core/settings.py +2 -17
- nautobot/core/settings.yaml +34 -13
- nautobot/core/settings_funcs.py +103 -0
- nautobot/core/tables.py +130 -56
- nautobot/core/templates/admin/search_form.html +1 -1
- nautobot/core/templates/buttons/add.html +11 -3
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +13 -0
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +13 -0
- nautobot/core/templates/buttons/export.html +101 -53
- nautobot/core/templates/buttons/job_import.html +11 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +3 -1
- nautobot/core/templates/generic/object_bulk_update.html +3 -1
- nautobot/core/templates/generic/object_changelog.html +0 -9
- nautobot/core/templates/generic/object_list.html +156 -17
- nautobot/core/templates/generic/object_retrieve.html +80 -16
- nautobot/core/templates/inc/extras_features_edit_form_fields.html +8 -0
- nautobot/core/templates/inc/javascript.html +2 -0
- nautobot/core/templates/inc/media.html +2 -2
- nautobot/core/templates/inc/nav_menu.html +1 -0
- nautobot/core/templates/inc/paginator.html +7 -7
- nautobot/core/templates/inc/search_panel.html +2 -2
- nautobot/core/templates/inc/table.html +2 -2
- nautobot/core/templates/nautobot_config.py.j2 +13 -8
- nautobot/core/templates/utilities/templatetags/dynamic_group_assignment_modal.html +37 -0
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +2 -2
- nautobot/core/templates/utilities/templatetags/saved_view_modal.html +38 -0
- nautobot/core/templates/utilities/theme_preview.html +25 -8
- nautobot/core/templates/utilities/worker_status.html +152 -0
- nautobot/core/templatetags/buttons.py +335 -38
- nautobot/core/templatetags/form_helpers.py +1 -1
- nautobot/core/templatetags/helpers.py +181 -11
- nautobot/core/testing/api.py +5 -4
- nautobot/core/testing/filters.py +63 -14
- nautobot/core/testing/mixins.py +46 -0
- nautobot/core/testing/models.py +22 -0
- nautobot/core/testing/schema.py +4 -8
- nautobot/core/testing/views.py +31 -14
- nautobot/core/tests/integration/test_import_objects_ui.py +1 -0
- nautobot/core/tests/integration/test_swagger.py +1 -1
- nautobot/core/tests/nautobot_config.py +0 -1
- nautobot/core/tests/runner.py +2 -2
- nautobot/core/tests/test_api.py +1 -0
- nautobot/core/tests/test_authentication.py +7 -2
- nautobot/core/tests/test_filters.py +11 -9
- nautobot/core/tests/test_forms.py +9 -0
- nautobot/core/tests/test_graphql.py +27 -16
- nautobot/core/tests/test_jobs.py +122 -0
- nautobot/core/tests/test_tables.py +3 -1
- nautobot/core/tests/test_templatetags_helpers.py +12 -5
- nautobot/core/tests/test_utils.py +31 -20
- nautobot/core/tests/test_views.py +6 -6
- nautobot/core/urls.py +8 -3
- nautobot/core/utils/deprecation.py +29 -0
- nautobot/core/utils/filtering.py +12 -9
- nautobot/core/utils/lookup.py +37 -2
- nautobot/core/utils/requests.py +4 -1
- nautobot/core/views/__init__.py +137 -24
- nautobot/core/views/generic.py +119 -67
- nautobot/core/views/mixins.py +105 -36
- nautobot/core/views/paginator.py +9 -3
- nautobot/core/views/renderers.py +121 -56
- nautobot/core/views/utils.py +81 -1
- nautobot/dcim/__init__.py +0 -1
- nautobot/dcim/api/serializers.py +180 -44
- nautobot/dcim/api/urls.py +7 -3
- nautobot/dcim/api/views.py +53 -7
- nautobot/dcim/apps.py +3 -0
- nautobot/dcim/choices.py +25 -0
- nautobot/dcim/constants.py +7 -0
- nautobot/dcim/factory.py +252 -18
- nautobot/dcim/filters/__init__.py +373 -193
- nautobot/dcim/filters/mixins.py +274 -1
- nautobot/dcim/forms.py +834 -121
- nautobot/dcim/graphql/types.py +2 -2
- nautobot/dcim/homepage.py +1 -1
- nautobot/dcim/migrations/0059_add_role_field_to_interface_models.py +27 -0
- nautobot/dcim/migrations/0060_alter_cable_status_alter_consoleport__path_and_more.py +303 -0
- nautobot/dcim/migrations/0061_module_models.py +862 -0
- nautobot/dcim/migrations/0062_module_data_migration.py +25 -0
- nautobot/dcim/models/__init__.py +8 -0
- nautobot/dcim/models/cables.py +15 -0
- nautobot/dcim/models/device_component_templates.py +207 -53
- nautobot/dcim/models/device_components.py +275 -99
- nautobot/dcim/models/devices.py +468 -13
- nautobot/dcim/models/racks.py +0 -1
- nautobot/dcim/navigation.py +47 -0
- nautobot/dcim/signals.py +3 -3
- nautobot/dcim/tables/__init__.py +35 -23
- nautobot/dcim/tables/devices.py +229 -43
- nautobot/dcim/tables/devicetypes.py +65 -9
- nautobot/dcim/tables/racks.py +5 -1
- nautobot/dcim/tables/template_code.py +46 -26
- nautobot/dcim/templates/dcim/cable_connect.html +76 -3
- nautobot/dcim/templates/dcim/console_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/device/base.html +14 -6
- nautobot/dcim/templates/dcim/device/consoleports.html +2 -3
- nautobot/dcim/templates/dcim/device/consoleserverports.html +2 -3
- nautobot/dcim/templates/dcim/device/devicebays.html +6 -7
- nautobot/dcim/templates/dcim/device/frontports.html +2 -3
- nautobot/dcim/templates/dcim/device/interfaces.html +2 -3
- nautobot/dcim/templates/dcim/device/inventory.html +2 -3
- nautobot/dcim/templates/dcim/device/modulebays.html +49 -0
- nautobot/dcim/templates/dcim/device/poweroutlets.html +2 -3
- nautobot/dcim/templates/dcim/device/powerports.html +2 -3
- nautobot/dcim/templates/dcim/device/rearports.html +2 -3
- nautobot/dcim/templates/dcim/device.html +45 -1
- nautobot/dcim/templates/dcim/device_component.html +13 -5
- nautobot/dcim/templates/dcim/device_list.html +2 -1
- nautobot/dcim/templates/dcim/devicetype.html +99 -98
- nautobot/dcim/templates/dcim/devicetype_list.html +8 -16
- nautobot/dcim/templates/dcim/inc/devicetype_component_table.html +1 -1
- nautobot/dcim/templates/dcim/inc/moduletype_component_table.html +39 -0
- nautobot/dcim/templates/dcim/interface.html +17 -2
- nautobot/dcim/templates/dcim/interface_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/interface_edit.html +1 -0
- nautobot/dcim/templates/dcim/manufacturer.html +24 -0
- nautobot/dcim/templates/dcim/module/base.html +97 -0
- nautobot/dcim/templates/dcim/module_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_consoleports.html +53 -0
- nautobot/dcim/templates/dcim/module_consoleserverports.html +53 -0
- nautobot/dcim/templates/dcim/module_destroy.html +5 -0
- nautobot/dcim/templates/dcim/module_frontports.html +53 -0
- nautobot/dcim/templates/dcim/module_interfaces.html +57 -0
- nautobot/dcim/templates/dcim/module_list.html +20 -0
- nautobot/dcim/templates/dcim/module_modulebays.html +49 -0
- nautobot/dcim/templates/dcim/module_poweroutlets.html +53 -0
- nautobot/dcim/templates/dcim/module_powerports.html +53 -0
- nautobot/dcim/templates/dcim/module_rearports.html +53 -0
- nautobot/dcim/templates/dcim/module_retrieve.html +63 -0
- nautobot/dcim/templates/dcim/module_update.html +71 -0
- nautobot/dcim/templates/dcim/modulebay_bulk_destroy.html +5 -0
- nautobot/dcim/templates/dcim/modulebay_destroy.html +8 -0
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +101 -0
- nautobot/dcim/templates/dcim/moduletype_list.html +11 -0
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +159 -0
- nautobot/dcim/templates/dcim/power_port_connection_list.html +7 -5
- nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +65 -19
- nautobot/dcim/tests/integration/test_cable_connect_form.py +4 -4
- nautobot/dcim/tests/test_api.py +693 -208
- nautobot/dcim/tests/test_filters.py +843 -217
- nautobot/dcim/tests/test_models.py +1072 -8
- nautobot/dcim/tests/test_views.py +1510 -341
- nautobot/dcim/urls.py +17 -2
- nautobot/dcim/utils.py +2 -3
- nautobot/dcim/views.py +1106 -116
- nautobot/extras/__init__.py +0 -1
- nautobot/extras/api/serializers.py +115 -3
- nautobot/extras/api/urls.py +12 -0
- nautobot/extras/api/views.py +66 -0
- nautobot/extras/apps.py +2 -2
- nautobot/extras/choices.py +43 -0
- nautobot/extras/context_managers.py +13 -8
- nautobot/extras/datasources/git.py +2 -0
- nautobot/extras/factory.py +460 -9
- nautobot/extras/filters/__init__.py +174 -3
- nautobot/extras/filters/mixins.py +46 -43
- nautobot/extras/forms/base.py +24 -5
- nautobot/extras/forms/forms.py +227 -8
- nautobot/extras/forms/mixins.py +93 -0
- nautobot/extras/graphql/types.py +23 -10
- nautobot/extras/homepage.py +14 -1
- nautobot/extras/management/__init__.py +1 -0
- nautobot/extras/management/commands/refresh_dynamic_group_member_caches.py +1 -16
- nautobot/extras/migrations/0021_customfield_changelog_data.py +1 -0
- nautobot/extras/migrations/0109_dynamicgroup_group_type_dynamicgroup_tags_and_more.py +108 -0
- nautobot/extras/migrations/0110_alter_configcontext_cluster_groups_and_more.py +111 -0
- nautobot/extras/migrations/0111_metadata.py +162 -0
- nautobot/extras/migrations/0112_dynamic_group_group_type_data_migration.py +28 -0
- nautobot/extras/migrations/0113_saved_views.py +77 -0
- nautobot/extras/models/__init__.py +15 -1
- nautobot/extras/models/change_logging.py +3 -3
- nautobot/extras/models/contacts.py +4 -0
- nautobot/extras/models/customfields.py +18 -3
- nautobot/extras/models/groups.py +389 -225
- nautobot/extras/models/jobs.py +6 -3
- nautobot/extras/models/metadata.py +441 -0
- nautobot/extras/models/mixins.py +72 -62
- nautobot/extras/models/models.py +118 -9
- nautobot/extras/models/relationships.py +9 -2
- nautobot/extras/models/tags.py +13 -2
- nautobot/extras/navigation.py +57 -0
- nautobot/extras/plugins/__init__.py +3 -1
- nautobot/extras/querysets.py +30 -66
- nautobot/extras/signals.py +95 -100
- nautobot/extras/tables.py +165 -12
- nautobot/extras/templates/extras/dynamicgroup.html +44 -15
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -0
- nautobot/extras/templates/extras/job.html +1 -1
- nautobot/extras/templates/extras/jobresult.html +61 -74
- nautobot/extras/templates/extras/metadatatype_create.html +89 -0
- nautobot/extras/templates/extras/metadatatype_retrieve.html +67 -0
- nautobot/extras/templates/extras/object_dynamicgroups.html +7 -0
- nautobot/extras/templates/extras/objectchange_list.html +0 -12
- nautobot/extras/templates/extras/plugins_list.html +1 -3
- nautobot/extras/templates/extras/role_retrieve.html +48 -0
- nautobot/extras/templates/extras/staticgroupassociation_retrieve.html +20 -0
- nautobot/extras/tests/integration/test_customfields.py +1 -0
- nautobot/extras/tests/test_api.py +509 -23
- nautobot/extras/tests/test_changelog.py +20 -9
- nautobot/extras/tests/test_context_managers.py +22 -15
- nautobot/extras/tests/test_datasources.py +13 -1
- nautobot/extras/tests/test_dynamicgroups.py +201 -171
- nautobot/extras/tests/test_filters.py +211 -12
- nautobot/extras/tests/test_jobs.py +6 -6
- nautobot/extras/tests/test_models.py +501 -4
- nautobot/extras/tests/test_relationships.py +1 -0
- nautobot/extras/tests/test_views.py +565 -8
- nautobot/extras/tests/test_webhooks.py +1 -1
- nautobot/extras/urls.py +5 -0
- nautobot/extras/utils.py +51 -11
- nautobot/extras/views.py +542 -76
- nautobot/ipam/__init__.py +0 -1
- nautobot/ipam/apps.py +1 -0
- nautobot/ipam/factory.py +17 -19
- nautobot/ipam/filters.py +13 -0
- nautobot/ipam/forms.py +8 -4
- nautobot/ipam/graphql/types.py +2 -2
- nautobot/ipam/migrations/0047_alter_ipaddress_role_alter_ipaddress_status_and_more.py +59 -0
- nautobot/ipam/models.py +11 -8
- nautobot/ipam/querysets.py +1 -1
- nautobot/ipam/signals.py +4 -2
- nautobot/ipam/tables.py +5 -0
- nautobot/ipam/templates/ipam/ipaddress_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_vm_interfaces.html +1 -1
- nautobot/ipam/templates/ipam/prefix.html +1 -0
- nautobot/ipam/tests/test_api.py +37 -18
- nautobot/ipam/tests/test_filters.py +26 -2
- nautobot/ipam/tests/test_models.py +6 -0
- nautobot/ipam/tests/test_querysets.py +1 -1
- nautobot/ipam/tests/test_views.py +3 -2
- nautobot/ipam/urls.py +2 -2
- nautobot/ipam/views.py +18 -26
- nautobot/project-static/css/base.css +20 -0
- nautobot/project-static/css/dark.css +11 -0
- nautobot/project-static/docs/404.html +892 -88
- nautobot/project-static/docs/apps/index.html +892 -88
- nautobot/project-static/docs/apps/nautobot-apps.html +892 -88
- nautobot/project-static/docs/assets/_mkdocstrings.css +5 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css +1 -0
- nautobot/project-static/docs/assets/stylesheets/main.3cba04c6.min.css.map +1 -0
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +919 -120
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +904 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +1618 -903
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +935 -144
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +977 -188
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +901 -99
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +897 -93
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +991 -193
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +974 -131
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +1078 -272
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +1242 -334
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +1727 -875
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +1164 -381
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +2088 -1374
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +2246 -1422
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +912 -111
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +963 -163
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +1010 -223
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +1913 -1277
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1846 -1102
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +904 -101
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +2331 -1699
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +1802 -1024
- nautobot/project-static/docs/development/apps/api/configuration-view.html +892 -88
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/global-search.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/graphql.html +892 -88
- nautobot/project-static/docs/development/apps/api/models/index.html +942 -90
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/populating-extensibility-features.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +892 -88
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +892 -88
- nautobot/project-static/docs/development/apps/api/prometheus.html +892 -88
- nautobot/project-static/docs/development/apps/api/setup.html +892 -88
- nautobot/project-static/docs/development/apps/api/testing.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +892 -88
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/base-template.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/index.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/notes.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +892 -88
- nautobot/project-static/docs/development/apps/api/views/urls.html +892 -88
- nautobot/project-static/docs/development/apps/index.html +892 -88
- nautobot/project-static/docs/development/apps/migration/code-updates.html +892 -88
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +892 -88
- nautobot/project-static/docs/development/apps/migration/from-v1.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +892 -88
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +892 -88
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +892 -88
- nautobot/project-static/docs/development/core/application-registry.html +892 -88
- nautobot/project-static/docs/development/core/best-practices.html +893 -88
- nautobot/project-static/docs/development/core/bootstrap-ui.html +892 -88
- nautobot/project-static/docs/development/core/caching.html +892 -88
- nautobot/project-static/docs/development/core/controllers.html +892 -88
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +892 -88
- nautobot/project-static/docs/development/core/generic-views.html +892 -88
- nautobot/project-static/docs/development/core/getting-started.html +892 -88
- nautobot/project-static/docs/development/core/homepage.html +892 -88
- nautobot/project-static/docs/development/core/index.html +892 -88
- nautobot/project-static/docs/development/core/model-checklist.html +901 -89
- nautobot/project-static/docs/development/core/model-features.html +892 -88
- nautobot/project-static/docs/development/core/natural-keys.html +892 -88
- nautobot/project-static/docs/development/core/navigation-menu.html +892 -88
- nautobot/project-static/docs/development/core/release-checklist.html +895 -91
- nautobot/project-static/docs/development/core/role-internals.html +892 -88
- nautobot/project-static/docs/development/core/settings.html +892 -88
- nautobot/project-static/docs/development/core/style-guide.html +893 -89
- nautobot/project-static/docs/development/core/templates.html +904 -89
- nautobot/project-static/docs/development/core/testing.html +892 -88
- nautobot/project-static/docs/development/core/user-preferences.html +892 -88
- nautobot/project-static/docs/development/index.html +892 -88
- nautobot/project-static/docs/development/jobs/index.html +893 -89
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +892 -88
- nautobot/project-static/docs/index.html +892 -88
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_dark.png +0 -0
- nautobot/project-static/docs/media/models/cloud_aws_direct_connect_light.png +0 -0
- nautobot/project-static/docs/models/cloud/cloudaccount.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetwork.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudnetworkprefixassignment.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudresourcetype.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservice.html +15 -0
- nautobot/project-static/docs/models/cloud/cloudservicenetworkassignment.html +15 -0
- nautobot/project-static/docs/models/dcim/module.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebay.html +15 -0
- nautobot/project-static/docs/models/dcim/modulebaytemplate.html +15 -0
- nautobot/project-static/docs/models/dcim/moduletype.html +15 -0
- nautobot/project-static/docs/models/extras/metadatachoice.html +15 -0
- nautobot/project-static/docs/models/extras/metadatatype.html +15 -0
- nautobot/project-static/docs/models/extras/objectmetadata.html +15 -0
- nautobot/project-static/docs/models/extras/role.html +15 -0
- nautobot/project-static/docs/models/extras/savedview.html +15 -0
- nautobot/project-static/docs/models/extras/staticgroupassociation.html +15 -0
- nautobot/project-static/docs/models/extras/status.html +15 -0
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +900 -89
- nautobot/project-static/docs/overview/design_philosophy.html +892 -88
- nautobot/project-static/docs/release-notes/index.html +1129 -92
- nautobot/project-static/docs/release-notes/version-1.0.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.1.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.2.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.3.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.4.html +892 -88
- nautobot/project-static/docs/release-notes/version-1.5.html +893 -89
- nautobot/project-static/docs/release-notes/version-1.6.html +893 -89
- nautobot/project-static/docs/release-notes/version-2.0.html +892 -88
- nautobot/project-static/docs/release-notes/version-2.1.html +892 -88
- nautobot/project-static/docs/release-notes/version-2.2.html +895 -91
- nautobot/project-static/docs/release-notes/version-2.3.html +9954 -0
- nautobot/project-static/docs/requirements.txt +5 -5
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +331 -256
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/optional-settings.html +992 -174
- nautobot/project-static/docs/user-guide/administration/configuration/required-settings.html +892 -88
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/caching.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +896 -88
- nautobot/project-static/docs/user-guide/administration/guides/healthcheck.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +892 -88
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +944 -153
- nautobot/project-static/docs/user-guide/administration/installation/index.html +901 -93
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +934 -122
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +954 -157
- nautobot/project-static/docs/user-guide/administration/installation/services.html +913 -112
- nautobot/project-static/docs/user-guide/administration/installation-extras/docker.html +908 -99
- nautobot/project-static/docs/user-guide/administration/installation-extras/health-checks.html +892 -88
- nautobot/project-static/docs/user-guide/administration/installation-extras/selinux-troubleshooting.html +892 -88
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +892 -88
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +892 -88
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +893 -89
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +892 -88
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +893 -89
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +896 -88
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +895 -91
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +8984 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +8829 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +8833 -0
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +918 -100
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +923 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +913 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +920 -116
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +914 -105
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +926 -108
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +936 -118
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +928 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +937 -119
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +928 -110
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +921 -117
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +923 -115
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +8828 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +8846 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +8843 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +8823 -0
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +916 -112
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +940 -83
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +943 -86
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +921 -103
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +929 -125
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +918 -114
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +922 -104
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +924 -106
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +906 -102
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +936 -88
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +897 -89
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +897 -89
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +901 -96
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +892 -88
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +897 -89
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/clear-view-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/cleared-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/config-table-columns-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/configure-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/create-saved-view-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/current-saved-view-drop-down-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/dropdown-button-after-new-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-application-to-locations.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/filter-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/global-default-location-list-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/location-list-view-with-saved-views.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/navigation-menu.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-as-new-view-drop-down.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/save-view-modal.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-buttons.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-admin-edit-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-different-user.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/saved-view-modal-unchecked.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-button.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/set-as-my-default-success.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/unsaved-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/images/saved-views/updated-saved-view.png +0 -0
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +892 -88
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +892 -88
- nautobot/project-static/docs/user-guide/index.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +1258 -785
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +896 -88
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +9061 -0
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +9137 -0
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +895 -91
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +8933 -0
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +950 -121
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +892 -88
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +892 -88
- nautobot/project-static/js/forms.js +71 -0
- nautobot/project-static/js/table_sorting_indicator.js +46 -0
- nautobot/project-static/js/tableconfig.js +6 -1
- nautobot/project-static/materialdesignicons-7.4.47/css/materialdesignicons.min.css +3 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.eot +0 -0
- nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/fonts/materialdesignicons-webfont.ttf +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-7.4.47/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/tenancy/__init__.py +0 -1
- nautobot/tenancy/apps.py +1 -0
- nautobot/tenancy/factory.py +3 -2
- nautobot/tenancy/filters/__init__.py +1 -0
- nautobot/tenancy/forms.py +1 -1
- nautobot/tenancy/templates/tenancy/tenant.html +24 -20
- nautobot/tenancy/views.py +11 -10
- nautobot/users/__init__.py +0 -1
- nautobot/users/api/serializers.py +1 -1
- nautobot/users/api/views.py +4 -2
- nautobot/users/apps.py +3 -2
- nautobot/users/factory.py +3 -3
- nautobot/users/migrations/0010_user_default_saved_views.py +20 -0
- nautobot/users/models.py +12 -0
- nautobot/users/tests/test_filters.py +6 -3
- nautobot/users/urls.py +8 -0
- nautobot/virtualization/__init__.py +0 -1
- nautobot/virtualization/apps.py +1 -0
- nautobot/virtualization/filters.py +6 -1
- nautobot/virtualization/forms.py +11 -3
- nautobot/virtualization/graphql/types.py +2 -2
- nautobot/virtualization/migrations/0029_add_role_field_to_interface_models.py +27 -0
- nautobot/virtualization/migrations/0030_alter_virtualmachine_local_config_context_data_owner_content_type_and_more.py +67 -0
- nautobot/virtualization/models.py +0 -2
- nautobot/virtualization/tables.py +10 -3
- nautobot/virtualization/templates/virtualization/virtualmachine.html +1 -1
- nautobot/virtualization/templates/virtualization/vminterface.html +7 -1
- nautobot/virtualization/templates/virtualization/vminterface_edit.html +1 -0
- nautobot/virtualization/tests/test_api.py +9 -4
- nautobot/virtualization/tests/test_filters.py +22 -0
- nautobot/virtualization/tests/test_models.py +7 -3
- nautobot/virtualization/tests/test_views.py +19 -3
- nautobot/virtualization/urls.py +2 -2
- nautobot/virtualization/views.py +10 -32
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/METADATA +20 -18
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/RECORD +677 -557
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css +0 -1
- nautobot/project-static/docs/assets/stylesheets/main.76a95c52.min.css.map +0 -1
- nautobot/project-static/materialdesignicons-6.5.95/.github/ISSUE_TEMPLATE.md +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/README.md +0 -25
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css +0 -26654
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css +0 -3
- nautobot/project-static/materialdesignicons-6.5.95/css/materialdesignicons.min.css.map +0 -16
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/fonts/materialdesignicons-webfont.woff2 +0 -0
- nautobot/project-static/materialdesignicons-6.5.95/package.json +0 -28
- nautobot/project-static/materialdesignicons-6.5.95/preview.html +0 -717
- nautobot/project-static/materialdesignicons-6.5.95/scss/_animated.scss +0 -27
- nautobot/project-static/materialdesignicons-6.5.95/scss/_core.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_extras.scss +0 -65
- nautobot/project-static/materialdesignicons-6.5.95/scss/_functions.scss +0 -20
- nautobot/project-static/materialdesignicons-6.5.95/scss/_icons.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_path.scss +0 -10
- nautobot/project-static/materialdesignicons-6.5.95/scss/_variables.scss +0 -6606
- nautobot/project-static/materialdesignicons-6.5.95/scss/materialdesignicons.scss +0 -8
- /nautobot/project-static/{materialdesignicons-6.5.95 → materialdesignicons-7.4.47}/LICENSE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/NOTICE +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/WHEEL +0 -0
- {nautobot-2.2.9.dist-info → nautobot-2.3.0.dist-info}/entry_points.txt +0 -0
nautobot/dcim/forms.py
CHANGED
|
@@ -49,11 +49,21 @@ from nautobot.extras.forms import (
|
|
|
49
49
|
NoteModelFormMixin,
|
|
50
50
|
RoleModelBulkEditFormMixin,
|
|
51
51
|
RoleModelFilterFormMixin,
|
|
52
|
+
RoleNotRequiredModelFormMixin,
|
|
52
53
|
StatusModelBulkEditFormMixin,
|
|
53
54
|
StatusModelFilterFormMixin,
|
|
54
55
|
TagsBulkEditFormMixin,
|
|
55
56
|
)
|
|
56
|
-
from nautobot.extras.models import
|
|
57
|
+
from nautobot.extras.models import (
|
|
58
|
+
Contact,
|
|
59
|
+
ContactAssociation,
|
|
60
|
+
ExternalIntegration,
|
|
61
|
+
Role,
|
|
62
|
+
SecretsGroup,
|
|
63
|
+
Status,
|
|
64
|
+
Tag,
|
|
65
|
+
Team,
|
|
66
|
+
)
|
|
57
67
|
from nautobot.ipam.constants import BGP_ASN_MAX, BGP_ASN_MIN
|
|
58
68
|
from nautobot.ipam.models import IPAddress, IPAddressToInterface, VLAN, VLANLocationAssignment, VRF
|
|
59
69
|
from nautobot.tenancy.forms import TenancyFilterForm, TenancyForm
|
|
@@ -113,6 +123,10 @@ from .models import (
|
|
|
113
123
|
Location,
|
|
114
124
|
LocationType,
|
|
115
125
|
Manufacturer,
|
|
126
|
+
Module,
|
|
127
|
+
ModuleBay,
|
|
128
|
+
ModuleBayTemplate,
|
|
129
|
+
ModuleType,
|
|
116
130
|
Platform,
|
|
117
131
|
PowerFeed,
|
|
118
132
|
PowerOutlet,
|
|
@@ -172,6 +186,14 @@ class DeviceComponentFilterForm(NautobotFilterForm):
|
|
|
172
186
|
)
|
|
173
187
|
|
|
174
188
|
|
|
189
|
+
class ModularDeviceComponentFilterForm(DeviceComponentFilterForm):
|
|
190
|
+
module = DynamicModelMultipleChoiceField(
|
|
191
|
+
queryset=Module.objects.all(),
|
|
192
|
+
required=False,
|
|
193
|
+
label="Module",
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
|
|
175
197
|
class InterfaceCommonForm(forms.Form):
|
|
176
198
|
def clean(self):
|
|
177
199
|
super().clean()
|
|
@@ -242,6 +264,26 @@ class ComponentForm(BootstrapMixin, forms.Form):
|
|
|
242
264
|
)
|
|
243
265
|
|
|
244
266
|
|
|
267
|
+
class ModularComponentForm(ComponentForm):
|
|
268
|
+
name_pattern = ExpandableNameField(
|
|
269
|
+
label="Name",
|
|
270
|
+
help_text="""
|
|
271
|
+
Alphanumeric ranges are supported for bulk creation. Mixed cases and types within a single range
|
|
272
|
+
are not supported. Examples:
|
|
273
|
+
<ul>
|
|
274
|
+
<li><code>[ge,xe]-0/0/[0-9]</code></li>
|
|
275
|
+
<li><code>e[0-3][a-d,f]</code></li>
|
|
276
|
+
</ul>
|
|
277
|
+
|
|
278
|
+
The variables <code>{module}</code>, <code>{module.parent}</code>, <code>{module.parent.parent}</code>, etc.
|
|
279
|
+
may be used in the name field and will be replaced by the <code>position</code> of the module bay that the
|
|
280
|
+
module occupies (skipping over any bays with a blank <code>position</code>). These variables can be used
|
|
281
|
+
multiple times in the component name and there is no limit to the depth of parent levels.
|
|
282
|
+
Any variables that cannot be replaced by a suitable position value will remain unchanged.
|
|
283
|
+
""",
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
245
287
|
#
|
|
246
288
|
# Fields
|
|
247
289
|
#
|
|
@@ -844,6 +886,7 @@ class DeviceTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
|
844
886
|
software_image_files = DynamicModelMultipleChoiceField(queryset=SoftwareImageFile.objects.all(), required=False)
|
|
845
887
|
u_height = forms.IntegerField(required=False)
|
|
846
888
|
is_full_depth = forms.NullBooleanField(required=False, widget=BulkEditNullBooleanSelect(), label="Is full depth")
|
|
889
|
+
comments = CommentField(label="Comments", required=False)
|
|
847
890
|
|
|
848
891
|
class Meta:
|
|
849
892
|
nullable_fields = ["device_family", "software_image_files"]
|
|
@@ -897,48 +940,160 @@ class DeviceTypeFilterForm(NautobotFilterForm):
|
|
|
897
940
|
tags = TagFilterField(model)
|
|
898
941
|
|
|
899
942
|
|
|
943
|
+
#
|
|
944
|
+
# Module types
|
|
945
|
+
#
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
class ModuleTypeForm(NautobotModelForm):
|
|
949
|
+
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all())
|
|
950
|
+
comments = CommentField(label="Comments")
|
|
951
|
+
|
|
952
|
+
class Meta:
|
|
953
|
+
model = ModuleType
|
|
954
|
+
fields = [
|
|
955
|
+
"manufacturer",
|
|
956
|
+
"model",
|
|
957
|
+
"part_number",
|
|
958
|
+
"comments",
|
|
959
|
+
"tags",
|
|
960
|
+
]
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
class ModuleTypeImportForm(BootstrapMixin, forms.ModelForm):
|
|
964
|
+
"""
|
|
965
|
+
Form for JSON/YAML import of ModuleType objects.
|
|
966
|
+
|
|
967
|
+
TODO: at some point we'll want to add general-purpose YAML serialization/deserialization,
|
|
968
|
+
similar to what we've done for CSV in 2.0, but for the moment we're leaving this as-is so that we can remain
|
|
969
|
+
at least nominally compatible with the netbox-community/devicetype-library repo.
|
|
970
|
+
"""
|
|
971
|
+
|
|
972
|
+
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(), to_field_name="name")
|
|
973
|
+
|
|
974
|
+
class Meta:
|
|
975
|
+
model = ModuleType
|
|
976
|
+
fields = [
|
|
977
|
+
"manufacturer",
|
|
978
|
+
"model",
|
|
979
|
+
"part_number",
|
|
980
|
+
"comments",
|
|
981
|
+
]
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
class ModuleTypeBulkEditForm(TagsBulkEditFormMixin, NautobotBulkEditForm):
|
|
985
|
+
pk = forms.ModelMultipleChoiceField(queryset=ModuleType.objects.all(), widget=forms.MultipleHiddenInput())
|
|
986
|
+
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
|
987
|
+
part_number = forms.CharField(required=False)
|
|
988
|
+
comments = CommentField(label="Comments", required=False)
|
|
989
|
+
|
|
990
|
+
class Meta:
|
|
991
|
+
nullable_fields = []
|
|
992
|
+
|
|
993
|
+
|
|
994
|
+
class ModuleTypeFilterForm(NautobotFilterForm):
|
|
995
|
+
model = ModuleType
|
|
996
|
+
q = forms.CharField(required=False, label="Search")
|
|
997
|
+
manufacturer = DynamicModelMultipleChoiceField(
|
|
998
|
+
queryset=Manufacturer.objects.all(), to_field_name="name", required=False
|
|
999
|
+
)
|
|
1000
|
+
has_console_ports = forms.NullBooleanField(
|
|
1001
|
+
required=False,
|
|
1002
|
+
label="Has console ports",
|
|
1003
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
1004
|
+
)
|
|
1005
|
+
has_console_server_ports = forms.NullBooleanField(
|
|
1006
|
+
required=False,
|
|
1007
|
+
label="Has console server ports",
|
|
1008
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
1009
|
+
)
|
|
1010
|
+
has_power_ports = forms.NullBooleanField(
|
|
1011
|
+
required=False,
|
|
1012
|
+
label="Has power ports",
|
|
1013
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
1014
|
+
)
|
|
1015
|
+
has_power_outlets = forms.NullBooleanField(
|
|
1016
|
+
required=False,
|
|
1017
|
+
label="Has power outlets",
|
|
1018
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
1019
|
+
)
|
|
1020
|
+
has_interfaces = forms.NullBooleanField(
|
|
1021
|
+
required=False,
|
|
1022
|
+
label="Has interfaces",
|
|
1023
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
1024
|
+
)
|
|
1025
|
+
tags = TagFilterField(model)
|
|
1026
|
+
|
|
1027
|
+
|
|
900
1028
|
#
|
|
901
1029
|
# Device component templates
|
|
902
1030
|
#
|
|
903
1031
|
|
|
904
1032
|
|
|
1033
|
+
class ComponentTemplateForm(NautobotModelForm):
|
|
1034
|
+
# TODO: placeholder values shouldn't be form controls, instead use:
|
|
1035
|
+
# <p class="form-control-static">{{ obj|hyperlinked_object_target_new_tab }}</p>
|
|
1036
|
+
device_type = DynamicModelChoiceField(
|
|
1037
|
+
queryset=DeviceType.objects.all(),
|
|
1038
|
+
)
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
class ModularComponentTemplateForm(ComponentTemplateForm):
|
|
1042
|
+
device_type = DynamicModelChoiceField(
|
|
1043
|
+
queryset=DeviceType.objects.all(),
|
|
1044
|
+
required=False,
|
|
1045
|
+
)
|
|
1046
|
+
module_type = DynamicModelChoiceField(
|
|
1047
|
+
queryset=ModuleType.objects.all(),
|
|
1048
|
+
required=False,
|
|
1049
|
+
)
|
|
1050
|
+
|
|
1051
|
+
|
|
905
1052
|
class ComponentTemplateCreateForm(ComponentForm):
|
|
906
1053
|
"""
|
|
907
1054
|
Base form for the creation of device component templates (subclassed from ComponentTemplateModel).
|
|
908
1055
|
"""
|
|
909
1056
|
|
|
910
|
-
|
|
911
|
-
queryset=
|
|
912
|
-
required=False,
|
|
913
|
-
initial_params={"device_types": "device_type"},
|
|
1057
|
+
device_type = DynamicModelChoiceField(
|
|
1058
|
+
queryset=DeviceType.objects.all(),
|
|
914
1059
|
)
|
|
1060
|
+
description = forms.CharField(required=False)
|
|
1061
|
+
|
|
1062
|
+
|
|
1063
|
+
class ModularComponentTemplateCreateForm(ModularComponentForm):
|
|
1064
|
+
"""
|
|
1065
|
+
Base form for the creation of modular device component templates (subclassed from ModularComponentTemplateModel).
|
|
1066
|
+
"""
|
|
1067
|
+
|
|
915
1068
|
device_type = DynamicModelChoiceField(
|
|
916
1069
|
queryset=DeviceType.objects.all(),
|
|
917
|
-
|
|
1070
|
+
required=False,
|
|
1071
|
+
)
|
|
1072
|
+
module_type = DynamicModelChoiceField(
|
|
1073
|
+
queryset=ModuleType.objects.all(),
|
|
1074
|
+
required=False,
|
|
918
1075
|
)
|
|
919
1076
|
description = forms.CharField(required=False)
|
|
920
1077
|
|
|
921
1078
|
|
|
922
|
-
class ConsolePortTemplateForm(
|
|
1079
|
+
class ConsolePortTemplateForm(ModularComponentTemplateForm):
|
|
923
1080
|
class Meta:
|
|
924
1081
|
model = ConsolePortTemplate
|
|
925
1082
|
fields = [
|
|
926
1083
|
"device_type",
|
|
1084
|
+
"module_type",
|
|
927
1085
|
"name",
|
|
928
1086
|
"label",
|
|
929
1087
|
"type",
|
|
930
1088
|
"description",
|
|
931
1089
|
]
|
|
932
|
-
widgets = {
|
|
933
|
-
"device_type": forms.HiddenInput(),
|
|
934
|
-
}
|
|
935
1090
|
|
|
936
1091
|
|
|
937
|
-
class ConsolePortTemplateCreateForm(
|
|
1092
|
+
class ConsolePortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
938
1093
|
type = forms.ChoiceField(choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2())
|
|
939
1094
|
field_order = (
|
|
940
|
-
"manufacturer",
|
|
941
1095
|
"device_type",
|
|
1096
|
+
"module_type",
|
|
942
1097
|
"name_pattern",
|
|
943
1098
|
"label_pattern",
|
|
944
1099
|
"type",
|
|
@@ -959,26 +1114,24 @@ class ConsolePortTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
959
1114
|
nullable_fields = ["label", "type", "description"]
|
|
960
1115
|
|
|
961
1116
|
|
|
962
|
-
class ConsoleServerPortTemplateForm(
|
|
1117
|
+
class ConsoleServerPortTemplateForm(ModularComponentTemplateForm):
|
|
963
1118
|
class Meta:
|
|
964
1119
|
model = ConsoleServerPortTemplate
|
|
965
1120
|
fields = [
|
|
966
1121
|
"device_type",
|
|
1122
|
+
"module_type",
|
|
967
1123
|
"name",
|
|
968
1124
|
"label",
|
|
969
1125
|
"type",
|
|
970
1126
|
"description",
|
|
971
1127
|
]
|
|
972
|
-
widgets = {
|
|
973
|
-
"device_type": forms.HiddenInput(),
|
|
974
|
-
}
|
|
975
1128
|
|
|
976
1129
|
|
|
977
|
-
class ConsoleServerPortTemplateCreateForm(
|
|
1130
|
+
class ConsoleServerPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
978
1131
|
type = forms.ChoiceField(choices=add_blank_choice(ConsolePortTypeChoices), widget=StaticSelect2())
|
|
979
1132
|
field_order = (
|
|
980
|
-
"manufacturer",
|
|
981
1133
|
"device_type",
|
|
1134
|
+
"module_type",
|
|
982
1135
|
"name_pattern",
|
|
983
1136
|
"label_pattern",
|
|
984
1137
|
"type",
|
|
@@ -1003,11 +1156,12 @@ class ConsoleServerPortTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1003
1156
|
nullable_fields = ["label", "type", "description"]
|
|
1004
1157
|
|
|
1005
1158
|
|
|
1006
|
-
class PowerPortTemplateForm(
|
|
1159
|
+
class PowerPortTemplateForm(ModularComponentTemplateForm):
|
|
1007
1160
|
class Meta:
|
|
1008
1161
|
model = PowerPortTemplate
|
|
1009
1162
|
fields = [
|
|
1010
1163
|
"device_type",
|
|
1164
|
+
"module_type",
|
|
1011
1165
|
"name",
|
|
1012
1166
|
"label",
|
|
1013
1167
|
"type",
|
|
@@ -1015,18 +1169,15 @@ class PowerPortTemplateForm(NautobotModelForm):
|
|
|
1015
1169
|
"allocated_draw",
|
|
1016
1170
|
"description",
|
|
1017
1171
|
]
|
|
1018
|
-
widgets = {
|
|
1019
|
-
"device_type": forms.HiddenInput(),
|
|
1020
|
-
}
|
|
1021
1172
|
|
|
1022
1173
|
|
|
1023
|
-
class PowerPortTemplateCreateForm(
|
|
1174
|
+
class PowerPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1024
1175
|
type = forms.ChoiceField(choices=add_blank_choice(PowerPortTypeChoices), required=False)
|
|
1025
1176
|
maximum_draw = forms.IntegerField(min_value=1, required=False, help_text="Maximum power draw (watts)")
|
|
1026
1177
|
allocated_draw = forms.IntegerField(min_value=1, required=False, help_text="Allocated power draw (watts)")
|
|
1027
1178
|
field_order = (
|
|
1028
|
-
"manufacturer",
|
|
1029
1179
|
"device_type",
|
|
1180
|
+
"module_type",
|
|
1030
1181
|
"name_pattern",
|
|
1031
1182
|
"label_pattern",
|
|
1032
1183
|
"type",
|
|
@@ -1058,11 +1209,12 @@ class PowerPortTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1058
1209
|
]
|
|
1059
1210
|
|
|
1060
1211
|
|
|
1061
|
-
class PowerOutletTemplateForm(
|
|
1212
|
+
class PowerOutletTemplateForm(ModularComponentTemplateForm):
|
|
1062
1213
|
class Meta:
|
|
1063
1214
|
model = PowerOutletTemplate
|
|
1064
1215
|
fields = [
|
|
1065
1216
|
"device_type",
|
|
1217
|
+
"module_type",
|
|
1066
1218
|
"name",
|
|
1067
1219
|
"label",
|
|
1068
1220
|
"type",
|
|
@@ -1070,21 +1222,22 @@ class PowerOutletTemplateForm(NautobotModelForm):
|
|
|
1070
1222
|
"feed_leg",
|
|
1071
1223
|
"description",
|
|
1072
1224
|
]
|
|
1073
|
-
widgets = {
|
|
1074
|
-
"device_type": forms.HiddenInput(),
|
|
1075
|
-
}
|
|
1076
1225
|
|
|
1077
1226
|
def __init__(self, *args, **kwargs):
|
|
1078
1227
|
super().__init__(*args, **kwargs)
|
|
1079
1228
|
|
|
1080
|
-
# Limit power_port_template choices to current DeviceType
|
|
1081
|
-
if
|
|
1229
|
+
# Limit power_port_template choices to current DeviceType or ModuleType
|
|
1230
|
+
if getattr(self.instance, "device_type", None):
|
|
1082
1231
|
self.fields["power_port_template"].queryset = PowerPortTemplate.objects.filter(
|
|
1083
1232
|
device_type=self.instance.device_type
|
|
1084
1233
|
)
|
|
1234
|
+
elif getattr(self.instance, "module_type", None):
|
|
1235
|
+
self.fields["power_port_template"].queryset = PowerPortTemplate.objects.filter(
|
|
1236
|
+
module_type=self.instance.module_type
|
|
1237
|
+
)
|
|
1085
1238
|
|
|
1086
1239
|
|
|
1087
|
-
class PowerOutletTemplateCreateForm(
|
|
1240
|
+
class PowerOutletTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1088
1241
|
type = forms.ChoiceField(choices=add_blank_choice(PowerOutletTypeChoices), required=False)
|
|
1089
1242
|
power_port_template = DynamicModelChoiceField(
|
|
1090
1243
|
queryset=PowerPortTemplate.objects.all(),
|
|
@@ -1097,8 +1250,8 @@ class PowerOutletTemplateCreateForm(ComponentTemplateCreateForm):
|
|
|
1097
1250
|
widget=StaticSelect2(),
|
|
1098
1251
|
)
|
|
1099
1252
|
field_order = (
|
|
1100
|
-
"manufacturer",
|
|
1101
1253
|
"device_type",
|
|
1254
|
+
"module_type",
|
|
1102
1255
|
"name_pattern",
|
|
1103
1256
|
"label_pattern",
|
|
1104
1257
|
"type",
|
|
@@ -1113,7 +1266,6 @@ class PowerOutletTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1113
1266
|
device_type = forms.ModelChoiceField(
|
|
1114
1267
|
queryset=DeviceType.objects.all(),
|
|
1115
1268
|
required=False,
|
|
1116
|
-
disabled=True,
|
|
1117
1269
|
widget=forms.HiddenInput(),
|
|
1118
1270
|
)
|
|
1119
1271
|
label = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
@@ -1145,11 +1297,12 @@ class PowerOutletTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1145
1297
|
self.fields["power_port_template"].widget.attrs["disabled"] = True
|
|
1146
1298
|
|
|
1147
1299
|
|
|
1148
|
-
class InterfaceTemplateForm(
|
|
1300
|
+
class InterfaceTemplateForm(ModularComponentTemplateForm):
|
|
1149
1301
|
class Meta:
|
|
1150
1302
|
model = InterfaceTemplate
|
|
1151
1303
|
fields = [
|
|
1152
1304
|
"device_type",
|
|
1305
|
+
"module_type",
|
|
1153
1306
|
"name",
|
|
1154
1307
|
"label",
|
|
1155
1308
|
"type",
|
|
@@ -1157,17 +1310,16 @@ class InterfaceTemplateForm(NautobotModelForm):
|
|
|
1157
1310
|
"description",
|
|
1158
1311
|
]
|
|
1159
1312
|
widgets = {
|
|
1160
|
-
"device_type": forms.HiddenInput(),
|
|
1161
1313
|
"type": StaticSelect2(),
|
|
1162
1314
|
}
|
|
1163
1315
|
|
|
1164
1316
|
|
|
1165
|
-
class InterfaceTemplateCreateForm(
|
|
1317
|
+
class InterfaceTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1166
1318
|
type = forms.ChoiceField(choices=InterfaceTypeChoices, widget=StaticSelect2())
|
|
1167
1319
|
mgmt_only = forms.BooleanField(required=False, label="Management only")
|
|
1168
1320
|
field_order = (
|
|
1169
|
-
"manufacturer",
|
|
1170
1321
|
"device_type",
|
|
1322
|
+
"module_type",
|
|
1171
1323
|
"name_pattern",
|
|
1172
1324
|
"label_pattern",
|
|
1173
1325
|
"type",
|
|
@@ -1191,11 +1343,12 @@ class InterfaceTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1191
1343
|
nullable_fields = ["label", "description"]
|
|
1192
1344
|
|
|
1193
1345
|
|
|
1194
|
-
class FrontPortTemplateForm(
|
|
1346
|
+
class FrontPortTemplateForm(ModularComponentTemplateForm):
|
|
1195
1347
|
class Meta:
|
|
1196
1348
|
model = FrontPortTemplate
|
|
1197
1349
|
fields = [
|
|
1198
1350
|
"device_type",
|
|
1351
|
+
"module_type",
|
|
1199
1352
|
"name",
|
|
1200
1353
|
"label",
|
|
1201
1354
|
"type",
|
|
@@ -1204,21 +1357,24 @@ class FrontPortTemplateForm(NautobotModelForm):
|
|
|
1204
1357
|
"description",
|
|
1205
1358
|
]
|
|
1206
1359
|
widgets = {
|
|
1207
|
-
"device_type": forms.HiddenInput(),
|
|
1208
1360
|
"rear_port_template": StaticSelect2(),
|
|
1209
1361
|
}
|
|
1210
1362
|
|
|
1211
1363
|
def __init__(self, *args, **kwargs):
|
|
1212
1364
|
super().__init__(*args, **kwargs)
|
|
1213
1365
|
|
|
1214
|
-
# Limit rear_port_template choices to current DeviceType
|
|
1215
|
-
if
|
|
1366
|
+
# Limit rear_port_template choices to current DeviceType or ModuleType
|
|
1367
|
+
if getattr(self.instance, "device_type", None):
|
|
1216
1368
|
self.fields["rear_port_template"].queryset = RearPortTemplate.objects.filter(
|
|
1217
1369
|
device_type=self.instance.device_type
|
|
1218
1370
|
)
|
|
1371
|
+
elif getattr(self.instance, "module_type", None):
|
|
1372
|
+
self.fields["rear_port_template"].queryset = RearPortTemplate.objects.filter(
|
|
1373
|
+
module_type=self.instance.module_type
|
|
1374
|
+
)
|
|
1219
1375
|
|
|
1220
1376
|
|
|
1221
|
-
class FrontPortTemplateCreateForm(
|
|
1377
|
+
class FrontPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1222
1378
|
type = forms.ChoiceField(choices=PortTypeChoices, widget=StaticSelect2())
|
|
1223
1379
|
rear_port_template_set = forms.MultipleChoiceField(
|
|
1224
1380
|
choices=[],
|
|
@@ -1226,8 +1382,8 @@ class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
|
|
|
1226
1382
|
help_text="Select one rear port assignment for each front port being created.",
|
|
1227
1383
|
)
|
|
1228
1384
|
field_order = (
|
|
1229
|
-
"manufacturer",
|
|
1230
1385
|
"device_type",
|
|
1386
|
+
"module_type",
|
|
1231
1387
|
"name_pattern",
|
|
1232
1388
|
"label_pattern",
|
|
1233
1389
|
"type",
|
|
@@ -1238,17 +1394,25 @@ class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
|
|
|
1238
1394
|
def __init__(self, *args, **kwargs):
|
|
1239
1395
|
super().__init__(*args, **kwargs)
|
|
1240
1396
|
|
|
1241
|
-
device_type =
|
|
1397
|
+
device_type = self.initial.get("device_type") or self.data.get("device_type")
|
|
1398
|
+
module_type = self.initial.get("module_type") or self.data.get("module_type")
|
|
1399
|
+
if device_type:
|
|
1400
|
+
parent = DeviceType.objects.get(pk=device_type)
|
|
1401
|
+
elif module_type:
|
|
1402
|
+
parent = ModuleType.objects.get(pk=module_type)
|
|
1403
|
+
else:
|
|
1404
|
+
return
|
|
1242
1405
|
|
|
1243
1406
|
# Determine which rear port positions are occupied. These will be excluded from the list of available mappings.
|
|
1244
1407
|
occupied_port_positions = [
|
|
1245
1408
|
(front_port_template.rear_port_template_id, front_port_template.rear_port_position)
|
|
1246
|
-
for front_port_template in
|
|
1409
|
+
for front_port_template in parent.front_port_templates.all()
|
|
1247
1410
|
]
|
|
1248
1411
|
|
|
1249
1412
|
# Populate rear port choices
|
|
1250
1413
|
choices = []
|
|
1251
|
-
|
|
1414
|
+
parent_field_name = parent._meta.verbose_name.replace(" ", "_")
|
|
1415
|
+
rear_port_templates = RearPortTemplate.objects.filter(**{parent_field_name: parent})
|
|
1252
1416
|
for rear_port_template in rear_port_templates:
|
|
1253
1417
|
for i in range(1, rear_port_template.positions + 1):
|
|
1254
1418
|
if (rear_port_template.pk, i) not in occupied_port_positions:
|
|
@@ -1300,11 +1464,12 @@ class FrontPortTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1300
1464
|
nullable_fields = ["description"]
|
|
1301
1465
|
|
|
1302
1466
|
|
|
1303
|
-
class RearPortTemplateForm(
|
|
1467
|
+
class RearPortTemplateForm(ModularComponentTemplateForm):
|
|
1304
1468
|
class Meta:
|
|
1305
1469
|
model = RearPortTemplate
|
|
1306
1470
|
fields = [
|
|
1307
1471
|
"device_type",
|
|
1472
|
+
"module_type",
|
|
1308
1473
|
"name",
|
|
1309
1474
|
"label",
|
|
1310
1475
|
"type",
|
|
@@ -1312,12 +1477,11 @@ class RearPortTemplateForm(NautobotModelForm):
|
|
|
1312
1477
|
"description",
|
|
1313
1478
|
]
|
|
1314
1479
|
widgets = {
|
|
1315
|
-
"device_type": forms.HiddenInput(),
|
|
1316
1480
|
"type": StaticSelect2(),
|
|
1317
1481
|
}
|
|
1318
1482
|
|
|
1319
1483
|
|
|
1320
|
-
class RearPortTemplateCreateForm(
|
|
1484
|
+
class RearPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
|
1321
1485
|
type = forms.ChoiceField(
|
|
1322
1486
|
choices=PortTypeChoices,
|
|
1323
1487
|
widget=StaticSelect2(),
|
|
@@ -1329,8 +1493,8 @@ class RearPortTemplateCreateForm(ComponentTemplateCreateForm):
|
|
|
1329
1493
|
help_text="The number of front ports which may be mapped to each rear port",
|
|
1330
1494
|
)
|
|
1331
1495
|
field_order = (
|
|
1332
|
-
"manufacturer",
|
|
1333
1496
|
"device_type",
|
|
1497
|
+
"module_type",
|
|
1334
1498
|
"name_pattern",
|
|
1335
1499
|
"label_pattern",
|
|
1336
1500
|
"type",
|
|
@@ -1353,7 +1517,7 @@ class RearPortTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1353
1517
|
nullable_fields = ["description"]
|
|
1354
1518
|
|
|
1355
1519
|
|
|
1356
|
-
class DeviceBayTemplateForm(
|
|
1520
|
+
class DeviceBayTemplateForm(ComponentTemplateForm):
|
|
1357
1521
|
class Meta:
|
|
1358
1522
|
model = DeviceBayTemplate
|
|
1359
1523
|
fields = [
|
|
@@ -1362,14 +1526,10 @@ class DeviceBayTemplateForm(NautobotModelForm):
|
|
|
1362
1526
|
"label",
|
|
1363
1527
|
"description",
|
|
1364
1528
|
]
|
|
1365
|
-
widgets = {
|
|
1366
|
-
"device_type": forms.HiddenInput(),
|
|
1367
|
-
}
|
|
1368
1529
|
|
|
1369
1530
|
|
|
1370
1531
|
class DeviceBayTemplateCreateForm(ComponentTemplateCreateForm):
|
|
1371
1532
|
field_order = (
|
|
1372
|
-
"manufacturer",
|
|
1373
1533
|
"device_type",
|
|
1374
1534
|
"name_pattern",
|
|
1375
1535
|
"label_pattern",
|
|
@@ -1386,6 +1546,92 @@ class DeviceBayTemplateBulkEditForm(NautobotBulkEditForm):
|
|
|
1386
1546
|
nullable_fields = ("label", "description")
|
|
1387
1547
|
|
|
1388
1548
|
|
|
1549
|
+
class ModuleBayTemplateForm(ModularComponentTemplateForm):
|
|
1550
|
+
class Meta:
|
|
1551
|
+
model = ModuleBayTemplate
|
|
1552
|
+
fields = [
|
|
1553
|
+
"device_type",
|
|
1554
|
+
"module_type",
|
|
1555
|
+
"name",
|
|
1556
|
+
"position",
|
|
1557
|
+
"label",
|
|
1558
|
+
"description",
|
|
1559
|
+
]
|
|
1560
|
+
|
|
1561
|
+
|
|
1562
|
+
class ModuleBayBaseCreateForm(BootstrapMixin, forms.Form):
|
|
1563
|
+
name_pattern = ExpandableNameField(label="Name")
|
|
1564
|
+
label_pattern = ExpandableNameField(
|
|
1565
|
+
label="Label",
|
|
1566
|
+
required=False,
|
|
1567
|
+
help_text="Alphanumeric ranges are supported. (Must match the number of names being created.)",
|
|
1568
|
+
)
|
|
1569
|
+
position_pattern = ExpandableNameField(
|
|
1570
|
+
label="Position",
|
|
1571
|
+
required=False,
|
|
1572
|
+
help_text="Alphanumeric ranges are supported. (Must match the number of names being created.)",
|
|
1573
|
+
)
|
|
1574
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1575
|
+
|
|
1576
|
+
def clean(self):
|
|
1577
|
+
super().clean()
|
|
1578
|
+
|
|
1579
|
+
# Validate that the number of components being created from both the name_pattern, position_pattern and label_pattern are equal
|
|
1580
|
+
if self.cleaned_data["label_pattern"]:
|
|
1581
|
+
name_pattern_count = len(self.cleaned_data["name_pattern"])
|
|
1582
|
+
label_pattern_count = len(self.cleaned_data["label_pattern"])
|
|
1583
|
+
if name_pattern_count != label_pattern_count:
|
|
1584
|
+
raise forms.ValidationError(
|
|
1585
|
+
{
|
|
1586
|
+
"label_pattern": f"The provided name pattern will create {name_pattern_count} components, however "
|
|
1587
|
+
f"{label_pattern_count} labels will be generated. These counts must match."
|
|
1588
|
+
},
|
|
1589
|
+
code="label_pattern_mismatch",
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
if self.cleaned_data["position_pattern"]:
|
|
1593
|
+
name_pattern_count = len(self.cleaned_data["name_pattern"])
|
|
1594
|
+
position_pattern_count = len(self.cleaned_data["position_pattern"])
|
|
1595
|
+
if name_pattern_count != position_pattern_count:
|
|
1596
|
+
raise forms.ValidationError(
|
|
1597
|
+
{
|
|
1598
|
+
"position_pattern": f"The provided name pattern will create {name_pattern_count} components, however "
|
|
1599
|
+
f"{position_pattern_count} positions will be generated. These counts must match."
|
|
1600
|
+
},
|
|
1601
|
+
code="position_pattern_mismatch",
|
|
1602
|
+
)
|
|
1603
|
+
|
|
1604
|
+
|
|
1605
|
+
class ModuleBayTemplateCreateForm(ModuleBayBaseCreateForm):
|
|
1606
|
+
device_type = DynamicModelChoiceField(
|
|
1607
|
+
queryset=DeviceType.objects.all(),
|
|
1608
|
+
required=False,
|
|
1609
|
+
)
|
|
1610
|
+
module_type = DynamicModelChoiceField(
|
|
1611
|
+
queryset=ModuleType.objects.all(),
|
|
1612
|
+
required=False,
|
|
1613
|
+
)
|
|
1614
|
+
|
|
1615
|
+
field_order = (
|
|
1616
|
+
"device_type",
|
|
1617
|
+
"module_type",
|
|
1618
|
+
"name_pattern",
|
|
1619
|
+
"label_pattern",
|
|
1620
|
+
"position_pattern",
|
|
1621
|
+
"description",
|
|
1622
|
+
)
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
class ModuleBayTemplateBulkEditForm(NautobotBulkEditForm):
|
|
1626
|
+
pk = forms.ModelMultipleChoiceField(queryset=ModuleBayTemplate.objects.all(), widget=forms.MultipleHiddenInput())
|
|
1627
|
+
label = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1628
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1629
|
+
position = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
1630
|
+
|
|
1631
|
+
class Meta:
|
|
1632
|
+
nullable_fields = ("label", "description")
|
|
1633
|
+
|
|
1634
|
+
|
|
1389
1635
|
#
|
|
1390
1636
|
# Component template import forms
|
|
1391
1637
|
#
|
|
@@ -1400,14 +1646,7 @@ class ComponentTemplateImportForm(BootstrapMixin, CustomFieldModelCSVForm):
|
|
|
1400
1646
|
netbox-community/devicetype-library repository.
|
|
1401
1647
|
"""
|
|
1402
1648
|
|
|
1403
|
-
def __init__(self,
|
|
1404
|
-
# Must pass the parent DeviceType on form initialization
|
|
1405
|
-
data.update(
|
|
1406
|
-
{
|
|
1407
|
-
"device_type": device_type.pk,
|
|
1408
|
-
}
|
|
1409
|
-
)
|
|
1410
|
-
|
|
1649
|
+
def __init__(self, data=None, *args, **kwargs):
|
|
1411
1650
|
super().__init__(data, *args, **kwargs)
|
|
1412
1651
|
|
|
1413
1652
|
if "type" in self.fields:
|
|
@@ -1419,9 +1658,21 @@ class ComponentTemplateImportForm(BootstrapMixin, CustomFieldModelCSVForm):
|
|
|
1419
1658
|
data = self.cleaned_data["device_type"]
|
|
1420
1659
|
|
|
1421
1660
|
# Limit fields referencing other components to the parent DeviceType
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
field.
|
|
1661
|
+
if data:
|
|
1662
|
+
for field_name, field in self.fields.items():
|
|
1663
|
+
if isinstance(field, forms.ModelChoiceField) and field_name not in ["device_type", "module_type"]:
|
|
1664
|
+
field.queryset = field.queryset.filter(device_type=data)
|
|
1665
|
+
|
|
1666
|
+
return data
|
|
1667
|
+
|
|
1668
|
+
def clean_module_type(self):
|
|
1669
|
+
data = self.cleaned_data["module_type"]
|
|
1670
|
+
|
|
1671
|
+
# Limit fields referencing other components to the parent ModuleType
|
|
1672
|
+
if data:
|
|
1673
|
+
for field_name, field in self.fields.items():
|
|
1674
|
+
if isinstance(field, forms.ModelChoiceField) and field_name not in ["device_type", "module_type"]:
|
|
1675
|
+
field.queryset = field.queryset.filter(module_type=data)
|
|
1425
1676
|
|
|
1426
1677
|
return data
|
|
1427
1678
|
|
|
@@ -1454,6 +1705,7 @@ class ConsolePortTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1454
1705
|
model = ConsolePortTemplate
|
|
1455
1706
|
fields = [
|
|
1456
1707
|
"device_type",
|
|
1708
|
+
"module_type",
|
|
1457
1709
|
"name",
|
|
1458
1710
|
"label",
|
|
1459
1711
|
"type",
|
|
@@ -1465,6 +1717,7 @@ class ConsoleServerPortTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1465
1717
|
model = ConsoleServerPortTemplate
|
|
1466
1718
|
fields = [
|
|
1467
1719
|
"device_type",
|
|
1720
|
+
"module_type",
|
|
1468
1721
|
"name",
|
|
1469
1722
|
"label",
|
|
1470
1723
|
"type",
|
|
@@ -1476,6 +1729,7 @@ class PowerPortTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1476
1729
|
model = PowerPortTemplate
|
|
1477
1730
|
fields = [
|
|
1478
1731
|
"device_type",
|
|
1732
|
+
"module_type",
|
|
1479
1733
|
"name",
|
|
1480
1734
|
"label",
|
|
1481
1735
|
"type",
|
|
@@ -1495,6 +1749,7 @@ class PowerOutletTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1495
1749
|
model = PowerOutletTemplate
|
|
1496
1750
|
fields = [
|
|
1497
1751
|
"device_type",
|
|
1752
|
+
"module_type",
|
|
1498
1753
|
"name",
|
|
1499
1754
|
"label",
|
|
1500
1755
|
"type",
|
|
@@ -1517,6 +1772,7 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1517
1772
|
model = InterfaceTemplate
|
|
1518
1773
|
fields = [
|
|
1519
1774
|
"device_type",
|
|
1775
|
+
"module_type",
|
|
1520
1776
|
"name",
|
|
1521
1777
|
"label",
|
|
1522
1778
|
"type",
|
|
@@ -1535,6 +1791,7 @@ class FrontPortTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1535
1791
|
model = FrontPortTemplate
|
|
1536
1792
|
fields = [
|
|
1537
1793
|
"device_type",
|
|
1794
|
+
"module_type",
|
|
1538
1795
|
"name",
|
|
1539
1796
|
"type",
|
|
1540
1797
|
"rear_port_template",
|
|
@@ -1556,6 +1813,7 @@ class RearPortTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1556
1813
|
model = RearPortTemplate
|
|
1557
1814
|
fields = [
|
|
1558
1815
|
"device_type",
|
|
1816
|
+
"module_type",
|
|
1559
1817
|
"name",
|
|
1560
1818
|
"type",
|
|
1561
1819
|
"positions",
|
|
@@ -1571,6 +1829,17 @@ class DeviceBayTemplateImportForm(ComponentTemplateImportForm):
|
|
|
1571
1829
|
]
|
|
1572
1830
|
|
|
1573
1831
|
|
|
1832
|
+
class ModuleBayTemplateImportForm(ComponentTemplateImportForm):
|
|
1833
|
+
class Meta:
|
|
1834
|
+
model = ModuleBayTemplate
|
|
1835
|
+
fields = [
|
|
1836
|
+
"device_type",
|
|
1837
|
+
"module_type",
|
|
1838
|
+
"name",
|
|
1839
|
+
"position",
|
|
1840
|
+
]
|
|
1841
|
+
|
|
1842
|
+
|
|
1574
1843
|
#
|
|
1575
1844
|
# Platforms
|
|
1576
1845
|
#
|
|
@@ -1734,7 +2003,7 @@ class DeviceForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm, LocalC
|
|
|
1734
2003
|
ip_choices = [(None, "---------")]
|
|
1735
2004
|
|
|
1736
2005
|
# Gather PKs of all interfaces belonging to this Device or a peer VirtualChassis member
|
|
1737
|
-
interface_ids = self.instance.
|
|
2006
|
+
interface_ids = self.instance.all_interfaces.values_list("pk", flat=True)
|
|
1738
2007
|
|
|
1739
2008
|
# Collect interface IPs
|
|
1740
2009
|
interface_ip_assignments = IPAddressToInterface.objects.filter(
|
|
@@ -2001,36 +2270,247 @@ class DeviceFilterForm(
|
|
|
2001
2270
|
|
|
2002
2271
|
|
|
2003
2272
|
#
|
|
2004
|
-
#
|
|
2273
|
+
# Modules
|
|
2005
2274
|
#
|
|
2006
2275
|
|
|
2007
2276
|
|
|
2008
|
-
class
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2277
|
+
class ModuleForm(LocatableModelFormMixin, NautobotModelForm, TenancyForm):
|
|
2278
|
+
manufacturer = DynamicModelChoiceField(
|
|
2279
|
+
queryset=Manufacturer.objects.all(),
|
|
2280
|
+
required=False,
|
|
2281
|
+
initial_params={"module_types": "$module_type"},
|
|
2282
|
+
)
|
|
2283
|
+
module_type = DynamicModelChoiceField(
|
|
2284
|
+
queryset=ModuleType.objects.all(),
|
|
2285
|
+
query_params={"manufacturer": "$manufacturer"},
|
|
2286
|
+
)
|
|
2287
|
+
parent_module_bay_device_filter = DynamicModelChoiceField(
|
|
2288
|
+
queryset=Device.objects.all(),
|
|
2289
|
+
required=False,
|
|
2290
|
+
label="Parent Device",
|
|
2291
|
+
query_params={"has_empty_module_bays": True},
|
|
2292
|
+
initial_params={"module_bays": "$parent_module_bay"},
|
|
2293
|
+
)
|
|
2294
|
+
parent_module_bay_device = DynamicModelChoiceField(
|
|
2295
|
+
queryset=ModuleBay.objects.all(),
|
|
2296
|
+
label="Parent Module Bay",
|
|
2297
|
+
required=False,
|
|
2298
|
+
query_params={"parent_device": "$parent_module_bay_device_filter", "has_installed_module": False},
|
|
2299
|
+
initial_params={"pk": "$parent_module_bay", "parent_device__module_bays": "$parent_module_bay"},
|
|
2300
|
+
)
|
|
2301
|
+
parent_module_bay_module_filter = DynamicModelChoiceField(
|
|
2302
|
+
queryset=Module.objects.all(),
|
|
2303
|
+
required=False,
|
|
2304
|
+
label="Parent Module",
|
|
2305
|
+
query_params={"has_empty_module_bays": True},
|
|
2306
|
+
initial_params={"module_bays": "$parent_module_bay"},
|
|
2307
|
+
)
|
|
2308
|
+
parent_module_bay_module = DynamicModelChoiceField(
|
|
2309
|
+
queryset=ModuleBay.objects.all(),
|
|
2310
|
+
label="Parent Module Bay",
|
|
2311
|
+
required=False,
|
|
2312
|
+
query_params={"parent_module": "$parent_module_bay_module_filter", "has_installed_module": False},
|
|
2313
|
+
initial_params={"pk": "$parent_module_bay", "parent_module__module_bays": "$parent_module_bay"},
|
|
2314
|
+
)
|
|
2315
|
+
location = DynamicModelChoiceField(
|
|
2316
|
+
queryset=Location.objects.all(),
|
|
2317
|
+
required=False,
|
|
2318
|
+
label="Location",
|
|
2319
|
+
query_params={"content_type": Module._meta.label_lower},
|
|
2320
|
+
)
|
|
2321
|
+
role = DynamicModelChoiceField(
|
|
2322
|
+
queryset=Role.objects.all(),
|
|
2323
|
+
required=False,
|
|
2324
|
+
query_params={"content_types": Module._meta.label_lower},
|
|
2325
|
+
)
|
|
2025
2326
|
|
|
2026
|
-
|
|
2327
|
+
class Meta:
|
|
2328
|
+
model = Module
|
|
2329
|
+
fields = [
|
|
2330
|
+
"manufacturer",
|
|
2331
|
+
"module_type",
|
|
2332
|
+
"parent_module_bay",
|
|
2333
|
+
"location",
|
|
2334
|
+
"serial",
|
|
2335
|
+
"asset_tag",
|
|
2336
|
+
"role",
|
|
2337
|
+
"status",
|
|
2338
|
+
"tenant_group",
|
|
2339
|
+
"tenant",
|
|
2340
|
+
"tags",
|
|
2341
|
+
]
|
|
2342
|
+
help_texts = {
|
|
2343
|
+
"serial": "Module serial number",
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
def clean(self):
|
|
2347
|
+
cleaned_data = self.cleaned_data
|
|
2348
|
+
if cleaned_data["parent_module_bay_device"] and cleaned_data["parent_module_bay_module"]:
|
|
2349
|
+
raise forms.ValidationError("Multiple parent module bays selected.")
|
|
2350
|
+
elif cleaned_data["parent_module_bay_device"]:
|
|
2351
|
+
cleaned_data["parent_module_bay"] = cleaned_data.pop("parent_module_bay_device")
|
|
2352
|
+
elif cleaned_data["parent_module_bay_module"]:
|
|
2353
|
+
cleaned_data["parent_module_bay"] = cleaned_data.pop("parent_module_bay_module")
|
|
2354
|
+
|
|
2355
|
+
return cleaned_data
|
|
2356
|
+
|
|
2357
|
+
|
|
2358
|
+
class ModuleBulkEditForm(
|
|
2359
|
+
TagsBulkEditFormMixin,
|
|
2360
|
+
LocatableModelBulkEditFormMixin,
|
|
2361
|
+
StatusModelBulkEditFormMixin,
|
|
2362
|
+
RoleModelBulkEditFormMixin,
|
|
2363
|
+
NautobotBulkEditForm,
|
|
2364
|
+
LocalContextModelBulkEditForm,
|
|
2365
|
+
):
|
|
2366
|
+
pk = forms.ModelMultipleChoiceField(queryset=Module.objects.all(), widget=forms.MultipleHiddenInput())
|
|
2367
|
+
manufacturer = DynamicModelChoiceField(queryset=Manufacturer.objects.all(), required=False)
|
|
2368
|
+
module_type = DynamicModelChoiceField(
|
|
2369
|
+
queryset=ModuleType.objects.all(),
|
|
2370
|
+
required=False,
|
|
2371
|
+
query_params={"manufacturer": "$manufacturer"},
|
|
2372
|
+
)
|
|
2373
|
+
tenant = DynamicModelChoiceField(queryset=Tenant.objects.all(), required=False)
|
|
2374
|
+
serial = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False, label="Serial Number")
|
|
2375
|
+
|
|
2376
|
+
class Meta:
|
|
2377
|
+
model = Module
|
|
2378
|
+
nullable_fields = [
|
|
2379
|
+
"location",
|
|
2380
|
+
"tenant",
|
|
2381
|
+
"serial",
|
|
2382
|
+
]
|
|
2383
|
+
|
|
2384
|
+
|
|
2385
|
+
class ModuleFilterForm(
|
|
2386
|
+
NautobotFilterForm,
|
|
2387
|
+
LocalContextFilterForm,
|
|
2388
|
+
LocatableModelFilterFormMixin,
|
|
2389
|
+
TenancyFilterForm,
|
|
2390
|
+
StatusModelFilterFormMixin,
|
|
2391
|
+
RoleModelFilterFormMixin,
|
|
2392
|
+
):
|
|
2393
|
+
model = Module
|
|
2394
|
+
field_order = [
|
|
2395
|
+
"q",
|
|
2396
|
+
"location",
|
|
2397
|
+
"status",
|
|
2398
|
+
"role",
|
|
2399
|
+
"tenant_group",
|
|
2400
|
+
"tenant",
|
|
2401
|
+
"manufacturer",
|
|
2402
|
+
"module_type",
|
|
2403
|
+
"mac_address",
|
|
2404
|
+
]
|
|
2405
|
+
q = forms.CharField(required=False, label="Search")
|
|
2406
|
+
manufacturer = DynamicModelMultipleChoiceField(
|
|
2407
|
+
queryset=Manufacturer.objects.all(),
|
|
2408
|
+
to_field_name="name",
|
|
2409
|
+
required=False,
|
|
2410
|
+
label="Manufacturer",
|
|
2411
|
+
)
|
|
2412
|
+
module_type = DynamicModelMultipleChoiceField(
|
|
2413
|
+
queryset=ModuleType.objects.all(),
|
|
2414
|
+
required=False,
|
|
2415
|
+
label="Model",
|
|
2416
|
+
query_params={"manufacturer": "$manufacturer"},
|
|
2417
|
+
)
|
|
2418
|
+
mac_address = forms.CharField(required=False, label="MAC address")
|
|
2419
|
+
has_console_ports = forms.NullBooleanField(
|
|
2420
|
+
required=False,
|
|
2421
|
+
label="Has console ports",
|
|
2422
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2423
|
+
)
|
|
2424
|
+
has_console_server_ports = forms.NullBooleanField(
|
|
2425
|
+
required=False,
|
|
2426
|
+
label="Has console server ports",
|
|
2427
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2428
|
+
)
|
|
2429
|
+
has_power_ports = forms.NullBooleanField(
|
|
2430
|
+
required=False,
|
|
2431
|
+
label="Has power ports",
|
|
2432
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2433
|
+
)
|
|
2434
|
+
has_power_outlets = forms.NullBooleanField(
|
|
2435
|
+
required=False,
|
|
2436
|
+
label="Has power outlets",
|
|
2437
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2438
|
+
)
|
|
2439
|
+
has_interfaces = forms.NullBooleanField(
|
|
2440
|
+
required=False,
|
|
2441
|
+
label="Has interfaces",
|
|
2442
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2443
|
+
)
|
|
2444
|
+
has_front_ports = forms.NullBooleanField(
|
|
2445
|
+
required=False,
|
|
2446
|
+
label="Has front ports",
|
|
2447
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2448
|
+
)
|
|
2449
|
+
has_rear_ports = forms.NullBooleanField(
|
|
2450
|
+
required=False,
|
|
2451
|
+
label="Has rear ports",
|
|
2452
|
+
widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES),
|
|
2453
|
+
)
|
|
2454
|
+
tags = TagFilterField(model)
|
|
2455
|
+
|
|
2456
|
+
|
|
2457
|
+
#
|
|
2458
|
+
# Device components
|
|
2459
|
+
#
|
|
2460
|
+
|
|
2461
|
+
|
|
2462
|
+
class ComponentCreateForm(ComponentForm):
|
|
2463
|
+
"""
|
|
2464
|
+
Base form for the creation of device components (models subclassed from ComponentModel).
|
|
2465
|
+
"""
|
|
2466
|
+
|
|
2467
|
+
device = DynamicModelChoiceField(queryset=Device.objects.all())
|
|
2468
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
2469
|
+
|
|
2470
|
+
|
|
2471
|
+
class ModularComponentCreateForm(ModularComponentForm):
|
|
2472
|
+
"""
|
|
2473
|
+
Base form for the creation of modular device components (models subclassed from ModularComponentModel).
|
|
2474
|
+
"""
|
|
2475
|
+
|
|
2476
|
+
device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False)
|
|
2477
|
+
module = DynamicModelChoiceField(queryset=Module.objects.all(), required=False)
|
|
2478
|
+
|
|
2479
|
+
|
|
2480
|
+
class ComponentEditForm(NautobotModelForm):
|
|
2481
|
+
"""
|
|
2482
|
+
Base class for editing device components (models subclassed from ComponentModel).
|
|
2483
|
+
|
|
2484
|
+
Distinct from ComponentCreateForm in that it has a name/label instead of a name_pattern/label_pattern.
|
|
2485
|
+
"""
|
|
2486
|
+
|
|
2487
|
+
device = DynamicModelChoiceField(queryset=Device.objects.all())
|
|
2488
|
+
|
|
2489
|
+
def __init__(self, *args, **kwargs):
|
|
2027
2490
|
super().__init__(*args, **kwargs)
|
|
2028
2491
|
|
|
2029
|
-
#
|
|
2030
|
-
if
|
|
2492
|
+
# Disable the device field if an initial value is provided
|
|
2493
|
+
if "device" in self.initial:
|
|
2031
2494
|
self.fields["device"].disabled = True
|
|
2032
2495
|
|
|
2033
2496
|
|
|
2497
|
+
class ModularComponentEditForm(ComponentEditForm):
|
|
2498
|
+
"""
|
|
2499
|
+
Base class for editing modular device components (models subclassed from ModularComponentModel).
|
|
2500
|
+
"""
|
|
2501
|
+
|
|
2502
|
+
device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False)
|
|
2503
|
+
module = DynamicModelChoiceField(queryset=Module.objects.all(), required=False)
|
|
2504
|
+
|
|
2505
|
+
def __init__(self, *args, **kwargs):
|
|
2506
|
+
super().__init__(*args, **kwargs)
|
|
2507
|
+
|
|
2508
|
+
# Disable the device and module fields if an initial value is provided for either
|
|
2509
|
+
if "device" in self.initial or "module" in self.initial:
|
|
2510
|
+
self.fields["device"].disabled = True
|
|
2511
|
+
self.fields["module"].disabled = True
|
|
2512
|
+
|
|
2513
|
+
|
|
2034
2514
|
class DeviceBulkAddComponentForm(ComponentForm, CustomFieldModelBulkEditFormMixin):
|
|
2035
2515
|
pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput())
|
|
2036
2516
|
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
@@ -2039,22 +2519,31 @@ class DeviceBulkAddComponentForm(ComponentForm, CustomFieldModelBulkEditFormMixi
|
|
|
2039
2519
|
nullable_fields = []
|
|
2040
2520
|
|
|
2041
2521
|
|
|
2522
|
+
class ModuleBulkAddComponentForm(ModularComponentForm, CustomFieldModelBulkEditFormMixin):
|
|
2523
|
+
pk = forms.ModelMultipleChoiceField(queryset=Module.objects.all(), widget=forms.MultipleHiddenInput())
|
|
2524
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
2525
|
+
|
|
2526
|
+
class Meta:
|
|
2527
|
+
nullable_fields = []
|
|
2528
|
+
|
|
2529
|
+
|
|
2042
2530
|
#
|
|
2043
2531
|
# Console ports
|
|
2044
2532
|
#
|
|
2045
2533
|
|
|
2046
2534
|
|
|
2047
|
-
class ConsolePortFilterForm(
|
|
2535
|
+
class ConsolePortFilterForm(ModularDeviceComponentFilterForm):
|
|
2048
2536
|
model = ConsolePort
|
|
2049
2537
|
type = forms.MultipleChoiceField(choices=ConsolePortTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2050
2538
|
tags = TagFilterField(model)
|
|
2051
2539
|
|
|
2052
2540
|
|
|
2053
|
-
class ConsolePortForm(
|
|
2541
|
+
class ConsolePortForm(ModularComponentEditForm):
|
|
2054
2542
|
class Meta:
|
|
2055
2543
|
model = ConsolePort
|
|
2056
2544
|
fields = [
|
|
2057
2545
|
"device",
|
|
2546
|
+
"module",
|
|
2058
2547
|
"name",
|
|
2059
2548
|
"label",
|
|
2060
2549
|
"type",
|
|
@@ -2063,7 +2552,7 @@ class ConsolePortForm(ComponentEditForm):
|
|
|
2063
2552
|
]
|
|
2064
2553
|
|
|
2065
2554
|
|
|
2066
|
-
class ConsolePortCreateForm(
|
|
2555
|
+
class ConsolePortCreateForm(ModularComponentCreateForm):
|
|
2067
2556
|
type = forms.ChoiceField(
|
|
2068
2557
|
choices=add_blank_choice(ConsolePortTypeChoices),
|
|
2069
2558
|
required=False,
|
|
@@ -2071,6 +2560,7 @@ class ConsolePortCreateForm(ComponentCreateForm):
|
|
|
2071
2560
|
)
|
|
2072
2561
|
field_order = (
|
|
2073
2562
|
"device",
|
|
2563
|
+
"module",
|
|
2074
2564
|
"name_pattern",
|
|
2075
2565
|
"label_pattern",
|
|
2076
2566
|
"type",
|
|
@@ -2083,6 +2573,10 @@ class ConsolePortBulkCreateForm(form_from_model(ConsolePort, ["type", "tags"]),
|
|
|
2083
2573
|
field_order = ("name_pattern", "label_pattern", "type", "description", "tags")
|
|
2084
2574
|
|
|
2085
2575
|
|
|
2576
|
+
class ModuleConsolePortBulkCreateForm(form_from_model(ConsolePort, ["type", "tags"]), ModuleBulkAddComponentForm):
|
|
2577
|
+
field_order = ("name_pattern", "label_pattern", "type", "description", "tags")
|
|
2578
|
+
|
|
2579
|
+
|
|
2086
2580
|
class ConsolePortBulkEditForm(
|
|
2087
2581
|
form_from_model(ConsolePort, ["label", "type", "description"]),
|
|
2088
2582
|
TagsBulkEditFormMixin,
|
|
@@ -2099,17 +2593,18 @@ class ConsolePortBulkEditForm(
|
|
|
2099
2593
|
#
|
|
2100
2594
|
|
|
2101
2595
|
|
|
2102
|
-
class ConsoleServerPortFilterForm(
|
|
2596
|
+
class ConsoleServerPortFilterForm(ModularDeviceComponentFilterForm):
|
|
2103
2597
|
model = ConsoleServerPort
|
|
2104
2598
|
type = forms.MultipleChoiceField(choices=ConsolePortTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2105
2599
|
tags = TagFilterField(model)
|
|
2106
2600
|
|
|
2107
2601
|
|
|
2108
|
-
class ConsoleServerPortForm(
|
|
2602
|
+
class ConsoleServerPortForm(ModularComponentEditForm):
|
|
2109
2603
|
class Meta:
|
|
2110
2604
|
model = ConsoleServerPort
|
|
2111
2605
|
fields = [
|
|
2112
2606
|
"device",
|
|
2607
|
+
"module",
|
|
2113
2608
|
"name",
|
|
2114
2609
|
"label",
|
|
2115
2610
|
"type",
|
|
@@ -2118,7 +2613,7 @@ class ConsoleServerPortForm(ComponentEditForm):
|
|
|
2118
2613
|
]
|
|
2119
2614
|
|
|
2120
2615
|
|
|
2121
|
-
class ConsoleServerPortCreateForm(
|
|
2616
|
+
class ConsoleServerPortCreateForm(ModularComponentCreateForm):
|
|
2122
2617
|
type = forms.ChoiceField(
|
|
2123
2618
|
choices=add_blank_choice(ConsolePortTypeChoices),
|
|
2124
2619
|
required=False,
|
|
@@ -2126,6 +2621,7 @@ class ConsoleServerPortCreateForm(ComponentCreateForm):
|
|
|
2126
2621
|
)
|
|
2127
2622
|
field_order = (
|
|
2128
2623
|
"device",
|
|
2624
|
+
"module",
|
|
2129
2625
|
"name_pattern",
|
|
2130
2626
|
"label_pattern",
|
|
2131
2627
|
"type",
|
|
@@ -2138,6 +2634,12 @@ class ConsoleServerPortBulkCreateForm(form_from_model(ConsoleServerPort, ["type"
|
|
|
2138
2634
|
field_order = ("name_pattern", "label_pattern", "type", "description", "tags")
|
|
2139
2635
|
|
|
2140
2636
|
|
|
2637
|
+
class ModuleConsoleServerPortBulkCreateForm(
|
|
2638
|
+
form_from_model(ConsoleServerPort, ["type", "tags"]), ModuleBulkAddComponentForm
|
|
2639
|
+
):
|
|
2640
|
+
field_order = ("name_pattern", "label_pattern", "type", "description", "tags")
|
|
2641
|
+
|
|
2642
|
+
|
|
2141
2643
|
class ConsoleServerPortBulkEditForm(
|
|
2142
2644
|
form_from_model(ConsoleServerPort, ["label", "type", "description"]),
|
|
2143
2645
|
TagsBulkEditFormMixin,
|
|
@@ -2154,17 +2656,18 @@ class ConsoleServerPortBulkEditForm(
|
|
|
2154
2656
|
#
|
|
2155
2657
|
|
|
2156
2658
|
|
|
2157
|
-
class PowerPortFilterForm(
|
|
2659
|
+
class PowerPortFilterForm(ModularDeviceComponentFilterForm):
|
|
2158
2660
|
model = PowerPort
|
|
2159
2661
|
type = forms.MultipleChoiceField(choices=PowerPortTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2160
2662
|
tags = TagFilterField(model)
|
|
2161
2663
|
|
|
2162
2664
|
|
|
2163
|
-
class PowerPortForm(
|
|
2665
|
+
class PowerPortForm(ModularComponentEditForm):
|
|
2164
2666
|
class Meta:
|
|
2165
2667
|
model = PowerPort
|
|
2166
2668
|
fields = [
|
|
2167
2669
|
"device",
|
|
2670
|
+
"module",
|
|
2168
2671
|
"name",
|
|
2169
2672
|
"label",
|
|
2170
2673
|
"type",
|
|
@@ -2175,7 +2678,7 @@ class PowerPortForm(ComponentEditForm):
|
|
|
2175
2678
|
]
|
|
2176
2679
|
|
|
2177
2680
|
|
|
2178
|
-
class PowerPortCreateForm(
|
|
2681
|
+
class PowerPortCreateForm(ModularComponentCreateForm):
|
|
2179
2682
|
type = forms.ChoiceField(
|
|
2180
2683
|
choices=add_blank_choice(PowerPortTypeChoices),
|
|
2181
2684
|
required=False,
|
|
@@ -2185,6 +2688,7 @@ class PowerPortCreateForm(ComponentCreateForm):
|
|
|
2185
2688
|
allocated_draw = forms.IntegerField(min_value=1, required=False, help_text="Allocated draw in watts")
|
|
2186
2689
|
field_order = (
|
|
2187
2690
|
"device",
|
|
2691
|
+
"module",
|
|
2188
2692
|
"name_pattern",
|
|
2189
2693
|
"label_pattern",
|
|
2190
2694
|
"type",
|
|
@@ -2210,6 +2714,21 @@ class PowerPortBulkCreateForm(
|
|
|
2210
2714
|
)
|
|
2211
2715
|
|
|
2212
2716
|
|
|
2717
|
+
class ModulePowerPortBulkCreateForm(
|
|
2718
|
+
form_from_model(PowerPort, ["type", "maximum_draw", "allocated_draw", "tags"]),
|
|
2719
|
+
ModuleBulkAddComponentForm,
|
|
2720
|
+
):
|
|
2721
|
+
field_order = (
|
|
2722
|
+
"name_pattern",
|
|
2723
|
+
"label_pattern",
|
|
2724
|
+
"type",
|
|
2725
|
+
"maximum_draw",
|
|
2726
|
+
"allocated_draw",
|
|
2727
|
+
"description",
|
|
2728
|
+
"tags",
|
|
2729
|
+
)
|
|
2730
|
+
|
|
2731
|
+
|
|
2213
2732
|
class PowerPortBulkEditForm(
|
|
2214
2733
|
form_from_model(PowerPort, ["label", "type", "maximum_draw", "allocated_draw", "description"]),
|
|
2215
2734
|
TagsBulkEditFormMixin,
|
|
@@ -2226,13 +2745,13 @@ class PowerPortBulkEditForm(
|
|
|
2226
2745
|
#
|
|
2227
2746
|
|
|
2228
2747
|
|
|
2229
|
-
class PowerOutletFilterForm(
|
|
2748
|
+
class PowerOutletFilterForm(ModularDeviceComponentFilterForm):
|
|
2230
2749
|
model = PowerOutlet
|
|
2231
2750
|
type = forms.MultipleChoiceField(choices=PowerOutletTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2232
2751
|
tags = TagFilterField(model)
|
|
2233
2752
|
|
|
2234
2753
|
|
|
2235
|
-
class PowerOutletForm(
|
|
2754
|
+
class PowerOutletForm(ModularComponentEditForm):
|
|
2236
2755
|
power_port = DynamicModelChoiceField(
|
|
2237
2756
|
queryset=PowerPort.objects.all(),
|
|
2238
2757
|
required=False,
|
|
@@ -2243,6 +2762,7 @@ class PowerOutletForm(ComponentEditForm):
|
|
|
2243
2762
|
model = PowerOutlet
|
|
2244
2763
|
fields = [
|
|
2245
2764
|
"device",
|
|
2765
|
+
"module",
|
|
2246
2766
|
"name",
|
|
2247
2767
|
"label",
|
|
2248
2768
|
"type",
|
|
@@ -2253,7 +2773,7 @@ class PowerOutletForm(ComponentEditForm):
|
|
|
2253
2773
|
]
|
|
2254
2774
|
|
|
2255
2775
|
|
|
2256
|
-
class PowerOutletCreateForm(
|
|
2776
|
+
class PowerOutletCreateForm(ModularComponentCreateForm):
|
|
2257
2777
|
type = forms.ChoiceField(
|
|
2258
2778
|
choices=add_blank_choice(PowerOutletTypeChoices),
|
|
2259
2779
|
required=False,
|
|
@@ -2267,6 +2787,7 @@ class PowerOutletCreateForm(ComponentCreateForm):
|
|
|
2267
2787
|
feed_leg = forms.ChoiceField(choices=add_blank_choice(PowerOutletFeedLegChoices), required=False)
|
|
2268
2788
|
field_order = (
|
|
2269
2789
|
"device",
|
|
2790
|
+
"module",
|
|
2270
2791
|
"name_pattern",
|
|
2271
2792
|
"label_pattern",
|
|
2272
2793
|
"type",
|
|
@@ -2288,6 +2809,19 @@ class PowerOutletBulkCreateForm(form_from_model(PowerOutlet, ["type", "feed_leg"
|
|
|
2288
2809
|
)
|
|
2289
2810
|
|
|
2290
2811
|
|
|
2812
|
+
class ModulePowerOutletBulkCreateForm(
|
|
2813
|
+
form_from_model(PowerOutlet, ["type", "feed_leg", "tags"]), ModuleBulkAddComponentForm
|
|
2814
|
+
):
|
|
2815
|
+
field_order = (
|
|
2816
|
+
"name_pattern",
|
|
2817
|
+
"label_pattern",
|
|
2818
|
+
"type",
|
|
2819
|
+
"feed_leg",
|
|
2820
|
+
"description",
|
|
2821
|
+
"tags",
|
|
2822
|
+
)
|
|
2823
|
+
|
|
2824
|
+
|
|
2291
2825
|
class PowerOutletBulkEditForm(
|
|
2292
2826
|
form_from_model(PowerOutlet, ["label", "type", "feed_leg", "power_port", "description"]),
|
|
2293
2827
|
TagsBulkEditFormMixin,
|
|
@@ -2297,7 +2831,6 @@ class PowerOutletBulkEditForm(
|
|
|
2297
2831
|
device = forms.ModelChoiceField(
|
|
2298
2832
|
queryset=Device.objects.all(),
|
|
2299
2833
|
required=False,
|
|
2300
|
-
disabled=True,
|
|
2301
2834
|
widget=forms.HiddenInput(),
|
|
2302
2835
|
)
|
|
2303
2836
|
|
|
@@ -2321,7 +2854,7 @@ class PowerOutletBulkEditForm(
|
|
|
2321
2854
|
#
|
|
2322
2855
|
|
|
2323
2856
|
|
|
2324
|
-
class InterfaceFilterForm(
|
|
2857
|
+
class InterfaceFilterForm(ModularDeviceComponentFilterForm, RoleModelFilterFormMixin, StatusModelFilterFormMixin):
|
|
2325
2858
|
model = Interface
|
|
2326
2859
|
type = forms.MultipleChoiceField(choices=InterfaceTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2327
2860
|
enabled = forms.NullBooleanField(required=False, widget=StaticSelect2(choices=BOOLEAN_WITH_BLANK_CHOICES))
|
|
@@ -2330,7 +2863,7 @@ class InterfaceFilterForm(DeviceComponentFilterForm, StatusModelFilterFormMixin)
|
|
|
2330
2863
|
tags = TagFilterField(model)
|
|
2331
2864
|
|
|
2332
2865
|
|
|
2333
|
-
class InterfaceForm(InterfaceCommonForm,
|
|
2866
|
+
class InterfaceForm(InterfaceCommonForm, ModularComponentEditForm):
|
|
2334
2867
|
parent_interface = DynamicModelChoiceField(
|
|
2335
2868
|
queryset=Interface.objects.all(),
|
|
2336
2869
|
required=False,
|
|
@@ -2389,7 +2922,9 @@ class InterfaceForm(InterfaceCommonForm, ComponentEditForm):
|
|
|
2389
2922
|
model = Interface
|
|
2390
2923
|
fields = [
|
|
2391
2924
|
"device",
|
|
2925
|
+
"module",
|
|
2392
2926
|
"name",
|
|
2927
|
+
"role",
|
|
2393
2928
|
"label",
|
|
2394
2929
|
"type",
|
|
2395
2930
|
"enabled",
|
|
@@ -2420,7 +2955,8 @@ class InterfaceForm(InterfaceCommonForm, ComponentEditForm):
|
|
|
2420
2955
|
}
|
|
2421
2956
|
|
|
2422
2957
|
|
|
2423
|
-
class InterfaceCreateForm(
|
|
2958
|
+
class InterfaceCreateForm(ModularComponentCreateForm, InterfaceCommonForm, RoleNotRequiredModelFormMixin):
|
|
2959
|
+
model = Interface
|
|
2424
2960
|
type = forms.ChoiceField(
|
|
2425
2961
|
choices=InterfaceTypeChoices,
|
|
2426
2962
|
widget=StaticSelect2(),
|
|
@@ -2503,9 +3039,11 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
|
|
|
2503
3039
|
)
|
|
2504
3040
|
field_order = (
|
|
2505
3041
|
"device",
|
|
3042
|
+
"module",
|
|
2506
3043
|
"name_pattern",
|
|
2507
3044
|
"label_pattern",
|
|
2508
3045
|
"status",
|
|
3046
|
+
"role",
|
|
2509
3047
|
"type",
|
|
2510
3048
|
"enabled",
|
|
2511
3049
|
"parent_interface",
|
|
@@ -2527,7 +3065,41 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
|
|
|
2527
3065
|
class InterfaceBulkCreateForm(
|
|
2528
3066
|
form_from_model(Interface, ["enabled", "mtu", "vrf", "mgmt_only", "mode", "tags"]),
|
|
2529
3067
|
DeviceBulkAddComponentForm,
|
|
3068
|
+
RoleNotRequiredModelFormMixin,
|
|
3069
|
+
):
|
|
3070
|
+
model = Interface
|
|
3071
|
+
type = forms.ChoiceField(
|
|
3072
|
+
choices=InterfaceTypeChoices,
|
|
3073
|
+
widget=StaticSelect2(),
|
|
3074
|
+
)
|
|
3075
|
+
status = DynamicModelChoiceField(
|
|
3076
|
+
required=True,
|
|
3077
|
+
queryset=Status.objects.all(),
|
|
3078
|
+
query_params={"content_types": Interface._meta.label_lower},
|
|
3079
|
+
)
|
|
3080
|
+
|
|
3081
|
+
field_order = (
|
|
3082
|
+
"name_pattern",
|
|
3083
|
+
"label_pattern",
|
|
3084
|
+
"status",
|
|
3085
|
+
"role",
|
|
3086
|
+
"type",
|
|
3087
|
+
"enabled",
|
|
3088
|
+
"mtu",
|
|
3089
|
+
"vrf",
|
|
3090
|
+
"mgmt_only",
|
|
3091
|
+
"description",
|
|
3092
|
+
"mode",
|
|
3093
|
+
"tags",
|
|
3094
|
+
)
|
|
3095
|
+
|
|
3096
|
+
|
|
3097
|
+
class ModuleInterfaceBulkCreateForm(
|
|
3098
|
+
form_from_model(Interface, ["enabled", "mtu", "vrf", "mgmt_only", "mode", "tags"]),
|
|
3099
|
+
ModuleBulkAddComponentForm,
|
|
3100
|
+
RoleNotRequiredModelFormMixin,
|
|
2530
3101
|
):
|
|
3102
|
+
model = Interface
|
|
2531
3103
|
type = forms.ChoiceField(
|
|
2532
3104
|
choices=InterfaceTypeChoices,
|
|
2533
3105
|
widget=StaticSelect2(),
|
|
@@ -2542,6 +3114,7 @@ class InterfaceBulkCreateForm(
|
|
|
2542
3114
|
"name_pattern",
|
|
2543
3115
|
"label_pattern",
|
|
2544
3116
|
"status",
|
|
3117
|
+
"role",
|
|
2545
3118
|
"type",
|
|
2546
3119
|
"enabled",
|
|
2547
3120
|
"mtu",
|
|
@@ -2559,6 +3132,7 @@ class InterfaceBulkEditForm(
|
|
|
2559
3132
|
),
|
|
2560
3133
|
TagsBulkEditFormMixin,
|
|
2561
3134
|
StatusModelBulkEditFormMixin,
|
|
3135
|
+
RoleModelBulkEditFormMixin,
|
|
2562
3136
|
NautobotBulkEditForm,
|
|
2563
3137
|
):
|
|
2564
3138
|
pk = forms.ModelMultipleChoiceField(queryset=Interface.objects.all(), widget=forms.MultipleHiddenInput())
|
|
@@ -2670,13 +3244,13 @@ class InterfaceBulkEditForm(
|
|
|
2670
3244
|
#
|
|
2671
3245
|
|
|
2672
3246
|
|
|
2673
|
-
class FrontPortFilterForm(
|
|
3247
|
+
class FrontPortFilterForm(ModularDeviceComponentFilterForm):
|
|
2674
3248
|
model = FrontPort
|
|
2675
3249
|
type = forms.MultipleChoiceField(choices=PortTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2676
3250
|
tags = TagFilterField(model)
|
|
2677
3251
|
|
|
2678
3252
|
|
|
2679
|
-
class FrontPortForm(
|
|
3253
|
+
class FrontPortForm(ModularComponentEditForm):
|
|
2680
3254
|
rear_port = DynamicModelChoiceField(
|
|
2681
3255
|
queryset=RearPort.objects.all(),
|
|
2682
3256
|
query_params={"device": "$device"},
|
|
@@ -2686,6 +3260,7 @@ class FrontPortForm(ComponentEditForm):
|
|
|
2686
3260
|
model = FrontPort
|
|
2687
3261
|
fields = [
|
|
2688
3262
|
"device",
|
|
3263
|
+
"module",
|
|
2689
3264
|
"name",
|
|
2690
3265
|
"label",
|
|
2691
3266
|
"type",
|
|
@@ -2700,7 +3275,7 @@ class FrontPortForm(ComponentEditForm):
|
|
|
2700
3275
|
|
|
2701
3276
|
|
|
2702
3277
|
# TODO: Merge with FrontPortTemplateCreateForm to remove duplicate logic
|
|
2703
|
-
class FrontPortCreateForm(
|
|
3278
|
+
class FrontPortCreateForm(ModularComponentCreateForm):
|
|
2704
3279
|
type = forms.ChoiceField(
|
|
2705
3280
|
choices=PortTypeChoices,
|
|
2706
3281
|
widget=StaticSelect2(),
|
|
@@ -2712,6 +3287,7 @@ class FrontPortCreateForm(ComponentCreateForm):
|
|
|
2712
3287
|
)
|
|
2713
3288
|
field_order = (
|
|
2714
3289
|
"device",
|
|
3290
|
+
"module",
|
|
2715
3291
|
"name_pattern",
|
|
2716
3292
|
"label_pattern",
|
|
2717
3293
|
"type",
|
|
@@ -2723,17 +3299,24 @@ class FrontPortCreateForm(ComponentCreateForm):
|
|
|
2723
3299
|
def __init__(self, *args, **kwargs):
|
|
2724
3300
|
super().__init__(*args, **kwargs)
|
|
2725
3301
|
|
|
2726
|
-
device =
|
|
3302
|
+
device = self.initial.get("device") or self.data.get("device")
|
|
3303
|
+
module = self.initial.get("module") or self.data.get("module")
|
|
3304
|
+
if device:
|
|
3305
|
+
parent = Device.objects.get(pk=device)
|
|
3306
|
+
elif module:
|
|
3307
|
+
parent = Module.objects.get(pk=module)
|
|
3308
|
+
else:
|
|
3309
|
+
return
|
|
2727
3310
|
|
|
2728
3311
|
# Determine which rear port positions are occupied. These will be excluded from the list of available
|
|
2729
3312
|
# mappings.
|
|
2730
3313
|
occupied_port_positions = [
|
|
2731
|
-
(front_port.rear_port_id, front_port.rear_port_position) for front_port in
|
|
3314
|
+
(front_port.rear_port_id, front_port.rear_port_position) for front_port in parent.front_ports.all()
|
|
2732
3315
|
]
|
|
2733
3316
|
|
|
2734
3317
|
# Populate rear port choices
|
|
2735
3318
|
choices = []
|
|
2736
|
-
rear_ports = RearPort.objects.filter(
|
|
3319
|
+
rear_ports = RearPort.objects.filter(**{parent._meta.model_name: parent})
|
|
2737
3320
|
for rear_port in rear_ports:
|
|
2738
3321
|
for i in range(1, rear_port.positions + 1):
|
|
2739
3322
|
if (rear_port.pk, i) not in occupied_port_positions:
|
|
@@ -2794,17 +3377,18 @@ class FrontPortBulkEditForm(
|
|
|
2794
3377
|
#
|
|
2795
3378
|
|
|
2796
3379
|
|
|
2797
|
-
class RearPortFilterForm(
|
|
3380
|
+
class RearPortFilterForm(ModularDeviceComponentFilterForm):
|
|
2798
3381
|
model = RearPort
|
|
2799
3382
|
type = forms.MultipleChoiceField(choices=PortTypeChoices, required=False, widget=StaticSelect2Multiple())
|
|
2800
3383
|
tags = TagFilterField(model)
|
|
2801
3384
|
|
|
2802
3385
|
|
|
2803
|
-
class RearPortForm(
|
|
3386
|
+
class RearPortForm(ModularComponentEditForm):
|
|
2804
3387
|
class Meta:
|
|
2805
3388
|
model = RearPort
|
|
2806
3389
|
fields = [
|
|
2807
3390
|
"device",
|
|
3391
|
+
"module",
|
|
2808
3392
|
"name",
|
|
2809
3393
|
"label",
|
|
2810
3394
|
"type",
|
|
@@ -2817,7 +3401,7 @@ class RearPortForm(ComponentEditForm):
|
|
|
2817
3401
|
}
|
|
2818
3402
|
|
|
2819
3403
|
|
|
2820
|
-
class RearPortCreateForm(
|
|
3404
|
+
class RearPortCreateForm(ModularComponentCreateForm):
|
|
2821
3405
|
type = forms.ChoiceField(
|
|
2822
3406
|
choices=PortTypeChoices,
|
|
2823
3407
|
widget=StaticSelect2(),
|
|
@@ -2830,6 +3414,7 @@ class RearPortCreateForm(ComponentCreateForm):
|
|
|
2830
3414
|
)
|
|
2831
3415
|
field_order = (
|
|
2832
3416
|
"device",
|
|
3417
|
+
"module",
|
|
2833
3418
|
"name_pattern",
|
|
2834
3419
|
"label_pattern",
|
|
2835
3420
|
"type",
|
|
@@ -2850,6 +3435,19 @@ class RearPortBulkCreateForm(form_from_model(RearPort, ["type", "positions", "ta
|
|
|
2850
3435
|
)
|
|
2851
3436
|
|
|
2852
3437
|
|
|
3438
|
+
class ModuleRearPortBulkCreateForm(
|
|
3439
|
+
form_from_model(RearPort, ["type", "positions", "tags"]), ModuleBulkAddComponentForm
|
|
3440
|
+
):
|
|
3441
|
+
field_order = (
|
|
3442
|
+
"name_pattern",
|
|
3443
|
+
"label_pattern",
|
|
3444
|
+
"type",
|
|
3445
|
+
"positions",
|
|
3446
|
+
"description",
|
|
3447
|
+
"tags",
|
|
3448
|
+
)
|
|
3449
|
+
|
|
3450
|
+
|
|
2853
3451
|
class RearPortBulkEditForm(
|
|
2854
3452
|
form_from_model(RearPort, ["label", "type", "description"]),
|
|
2855
3453
|
TagsBulkEditFormMixin,
|
|
@@ -2922,13 +3520,119 @@ class DeviceBayBulkEditForm(
|
|
|
2922
3520
|
nullable_fields = ["label", "description"]
|
|
2923
3521
|
|
|
2924
3522
|
|
|
3523
|
+
#
|
|
3524
|
+
# Module bays
|
|
3525
|
+
#
|
|
3526
|
+
|
|
3527
|
+
|
|
3528
|
+
class ModuleBayFilterForm(NautobotFilterForm):
|
|
3529
|
+
model = ModuleBay
|
|
3530
|
+
|
|
3531
|
+
field_order = ["q", "parent_device", "parent_module"]
|
|
3532
|
+
q = forms.CharField(required=False, label="Search")
|
|
3533
|
+
parent_device = DynamicModelMultipleChoiceField(
|
|
3534
|
+
queryset=Device.objects.all(),
|
|
3535
|
+
required=False,
|
|
3536
|
+
label="Parent device",
|
|
3537
|
+
)
|
|
3538
|
+
parent_module = DynamicModelMultipleChoiceField(
|
|
3539
|
+
queryset=Module.objects.all(),
|
|
3540
|
+
required=False,
|
|
3541
|
+
label="Parent module",
|
|
3542
|
+
)
|
|
3543
|
+
|
|
3544
|
+
|
|
3545
|
+
class ModuleBayForm(NautobotModelForm):
|
|
3546
|
+
parent_device = DynamicModelChoiceField(
|
|
3547
|
+
queryset=Device.objects.all(),
|
|
3548
|
+
required=False,
|
|
3549
|
+
label="Parent Device",
|
|
3550
|
+
)
|
|
3551
|
+
parent_module = DynamicModelChoiceField(
|
|
3552
|
+
queryset=Module.objects.all(),
|
|
3553
|
+
required=False,
|
|
3554
|
+
label="Parent Module",
|
|
3555
|
+
)
|
|
3556
|
+
# TODO: Installed module field
|
|
3557
|
+
|
|
3558
|
+
class Meta:
|
|
3559
|
+
model = ModuleBay
|
|
3560
|
+
fields = [
|
|
3561
|
+
"parent_device",
|
|
3562
|
+
"parent_module",
|
|
3563
|
+
"name",
|
|
3564
|
+
"position",
|
|
3565
|
+
"label",
|
|
3566
|
+
"description",
|
|
3567
|
+
"tags",
|
|
3568
|
+
]
|
|
3569
|
+
|
|
3570
|
+
def __init__(self, *args, **kwargs):
|
|
3571
|
+
super().__init__(*args, **kwargs)
|
|
3572
|
+
|
|
3573
|
+
# Disable the parent_device and parent_module fields if an initial value is provided for either
|
|
3574
|
+
if "parent_device" in self.initial or "parent_module" in self.initial:
|
|
3575
|
+
self.fields["parent_device"].disabled = True
|
|
3576
|
+
self.fields["parent_module"].disabled = True
|
|
3577
|
+
|
|
3578
|
+
|
|
3579
|
+
class ModuleBayCreateForm(ModuleBayBaseCreateForm):
|
|
3580
|
+
parent_device = DynamicModelChoiceField(queryset=Device.objects.all(), required=False)
|
|
3581
|
+
parent_module = DynamicModelChoiceField(queryset=Module.objects.all(), required=False)
|
|
3582
|
+
tags = DynamicModelMultipleChoiceField(
|
|
3583
|
+
queryset=Tag.objects.all(),
|
|
3584
|
+
required=False,
|
|
3585
|
+
query_params={"content_types": ModuleBay._meta.label_lower},
|
|
3586
|
+
)
|
|
3587
|
+
field_order = (
|
|
3588
|
+
"parent_device",
|
|
3589
|
+
"parent_module",
|
|
3590
|
+
"name_pattern",
|
|
3591
|
+
"label_pattern",
|
|
3592
|
+
"position_pattern",
|
|
3593
|
+
"description",
|
|
3594
|
+
"tags",
|
|
3595
|
+
)
|
|
3596
|
+
|
|
3597
|
+
|
|
3598
|
+
class ModuleBayBulkCreateForm(
|
|
3599
|
+
form_from_model(ModuleBay, ["tags"]),
|
|
3600
|
+
ModuleBayBaseCreateForm,
|
|
3601
|
+
CustomFieldModelBulkEditFormMixin,
|
|
3602
|
+
):
|
|
3603
|
+
pk = forms.ModelMultipleChoiceField(queryset=Device.objects.all(), widget=forms.MultipleHiddenInput())
|
|
3604
|
+
description = forms.CharField(max_length=CHARFIELD_MAX_LENGTH, required=False)
|
|
3605
|
+
|
|
3606
|
+
field_order = ("name_pattern", "label_pattern", "position_pattern", "description", "tags")
|
|
3607
|
+
|
|
3608
|
+
class Meta:
|
|
3609
|
+
nullable_fields = []
|
|
3610
|
+
|
|
3611
|
+
|
|
3612
|
+
class ModuleModuleBayBulkCreateForm(ModuleBayBulkCreateForm):
|
|
3613
|
+
pk = forms.ModelMultipleChoiceField(queryset=Module.objects.all(), widget=forms.MultipleHiddenInput())
|
|
3614
|
+
|
|
3615
|
+
class Meta(ModuleBayBulkCreateForm.Meta):
|
|
3616
|
+
pass
|
|
3617
|
+
|
|
3618
|
+
|
|
3619
|
+
class ModuleBayBulkEditForm(
|
|
3620
|
+
form_from_model(ModuleBay, ["label", "description", "position"]),
|
|
3621
|
+
TagsBulkEditFormMixin,
|
|
3622
|
+
NautobotBulkEditForm,
|
|
3623
|
+
):
|
|
3624
|
+
pk = forms.ModelMultipleChoiceField(queryset=ModuleBay.objects.all(), widget=forms.MultipleHiddenInput())
|
|
3625
|
+
|
|
3626
|
+
class Meta:
|
|
3627
|
+
nullable_fields = ["label", "description"]
|
|
3628
|
+
|
|
3629
|
+
|
|
2925
3630
|
#
|
|
2926
3631
|
# Inventory items
|
|
2927
3632
|
#
|
|
2928
3633
|
|
|
2929
3634
|
|
|
2930
|
-
class InventoryItemForm(
|
|
2931
|
-
device = DynamicModelChoiceField(queryset=Device.objects.all())
|
|
3635
|
+
class InventoryItemForm(ComponentEditForm):
|
|
2932
3636
|
parent = DynamicModelChoiceField(
|
|
2933
3637
|
queryset=InventoryItem.objects.all(),
|
|
2934
3638
|
required=False,
|
|
@@ -3101,6 +3805,14 @@ class ConnectCableToDeviceForm(ConnectCableExcludeIDMixin, NautobotModelForm):
|
|
|
3101
3805
|
"rack": "$termination_b_rack",
|
|
3102
3806
|
},
|
|
3103
3807
|
)
|
|
3808
|
+
termination_b_module = DynamicModelChoiceField(
|
|
3809
|
+
queryset=Module.objects.all(),
|
|
3810
|
+
label="Module",
|
|
3811
|
+
required=False,
|
|
3812
|
+
query_params={
|
|
3813
|
+
"device": "$termination_b_device",
|
|
3814
|
+
},
|
|
3815
|
+
)
|
|
3104
3816
|
|
|
3105
3817
|
class Meta:
|
|
3106
3818
|
model = Cable
|
|
@@ -3135,7 +3847,7 @@ class ConnectCableToConsolePortForm(ConnectCableToDeviceForm):
|
|
|
3135
3847
|
queryset=ConsolePort.objects.all(),
|
|
3136
3848
|
label="Name",
|
|
3137
3849
|
disabled_indicator="cable",
|
|
3138
|
-
query_params={"device": "$termination_b_device"},
|
|
3850
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3139
3851
|
)
|
|
3140
3852
|
|
|
3141
3853
|
|
|
@@ -3144,7 +3856,7 @@ class ConnectCableToConsoleServerPortForm(ConnectCableToDeviceForm):
|
|
|
3144
3856
|
queryset=ConsoleServerPort.objects.all(),
|
|
3145
3857
|
label="Name",
|
|
3146
3858
|
disabled_indicator="cable",
|
|
3147
|
-
query_params={"device": "$termination_b_device"},
|
|
3859
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3148
3860
|
)
|
|
3149
3861
|
|
|
3150
3862
|
|
|
@@ -3153,7 +3865,7 @@ class ConnectCableToPowerPortForm(ConnectCableToDeviceForm):
|
|
|
3153
3865
|
queryset=PowerPort.objects.all(),
|
|
3154
3866
|
label="Name",
|
|
3155
3867
|
disabled_indicator="cable",
|
|
3156
|
-
query_params={"device": "$termination_b_device"},
|
|
3868
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3157
3869
|
)
|
|
3158
3870
|
|
|
3159
3871
|
|
|
@@ -3162,7 +3874,7 @@ class ConnectCableToPowerOutletForm(ConnectCableToDeviceForm):
|
|
|
3162
3874
|
queryset=PowerOutlet.objects.all(),
|
|
3163
3875
|
label="Name",
|
|
3164
3876
|
disabled_indicator="cable",
|
|
3165
|
-
query_params={"device": "$termination_b_device"},
|
|
3877
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3166
3878
|
)
|
|
3167
3879
|
|
|
3168
3880
|
|
|
@@ -3173,6 +3885,7 @@ class ConnectCableToInterfaceForm(ConnectCableToDeviceForm):
|
|
|
3173
3885
|
disabled_indicator="cable",
|
|
3174
3886
|
query_params={
|
|
3175
3887
|
"device_id": "$termination_b_device",
|
|
3888
|
+
"module": "$termination_b_module",
|
|
3176
3889
|
"kind": "physical",
|
|
3177
3890
|
},
|
|
3178
3891
|
)
|
|
@@ -3183,7 +3896,7 @@ class ConnectCableToFrontPortForm(ConnectCableToDeviceForm):
|
|
|
3183
3896
|
queryset=FrontPort.objects.all(),
|
|
3184
3897
|
label="Name",
|
|
3185
3898
|
disabled_indicator="cable",
|
|
3186
|
-
query_params={"device": "$termination_b_device"},
|
|
3899
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3187
3900
|
)
|
|
3188
3901
|
|
|
3189
3902
|
|
|
@@ -3192,7 +3905,7 @@ class ConnectCableToRearPortForm(ConnectCableToDeviceForm):
|
|
|
3192
3905
|
queryset=RearPort.objects.all(),
|
|
3193
3906
|
label="Name",
|
|
3194
3907
|
disabled_indicator="cable",
|
|
3195
|
-
query_params={"device": "$termination_b_device"},
|
|
3908
|
+
query_params={"device": "$termination_b_device", "module": "$termination_b_module"},
|
|
3196
3909
|
)
|
|
3197
3910
|
|
|
3198
3911
|
|