diff --git a/docs/models/dcim/modulebaytemplate.md b/docs/models/dcim/modulebaytemplate.md index 3b4d2b14b..70c3c3c61 100644 --- a/docs/models/dcim/modulebaytemplate.md +++ b/docs/models/dcim/modulebaytemplate.md @@ -4,4 +4,4 @@ A template for a module bay that will be created on all instantiations of the pa [Bay types](./modulebaytype.md) assigned to a module bay template are copied to each instantiated module bay, so constraints defined on the device type propagate automatically to all devices of that type. -Bay types are importable and exportable as part of a device type's YAML definition (`module-bays[].module_bay_types`), referenced by name. A referenced name is resolved against bay types belonging to the device type's own manufacturer or with no manufacturer set (global); a name may match both, since a bay type's uniqueness is scoped to `(manufacturer, name)` rather than name alone, in which case the manufacturer-specific type takes precedence. +Bay types are importable and exportable as part of a device type's or module type's YAML definition (`module-bays[].module_bay_types`), referenced by name. A referenced name is resolved against bay types belonging to the parent type's own manufacturer or with no manufacturer set (global); a name may match both, since a bay type's uniqueness is scoped to `(manufacturer, name)` rather than name alone, in which case the manufacturer-specific type takes precedence. A name matching only some other manufacturer's bay type is rejected rather than resolved to it. diff --git a/docs/models/dcim/moduletype.md b/docs/models/dcim/moduletype.md index 993c5cbfe..9f491c8bb 100644 --- a/docs/models/dcim/moduletype.md +++ b/docs/models/dcim/moduletype.md @@ -91,6 +91,8 @@ The assigned [profile](./moduletypeprofile.md) for the type of module. Profiles Zero or more [module bay types](./modulebaytype.md) that this module type is compatible with. When at least one bay type is set, the module type may only be installed into bays that share a common type. Leave empty to allow installation into any bay. +Bay types are included, by name, in a module type's exported YAML definition, but are not currently importable back through it; re-importing an exported definition leaves this field unset. + ### Attributes Depending on the module type's assigned [profile](./moduletypeprofile.md) (if any), one or more user-defined attributes may be available to configure. diff --git a/netbox/dcim/forms/object_import.py b/netbox/dcim/forms/object_import.py index b2899baa2..0cf73dad5 100644 --- a/netbox/dcim/forms/object_import.py +++ b/netbox/dcim/forms/object_import.py @@ -263,6 +263,12 @@ class ModuleBayTemplateImportForm(forms.ModelForm): own manufacturer (narrowed by clean_device_type/clean_module_type above); the field's default name-based lookup resolves both matches into cleaned_data rather than picking one, since it has no way to know which is meant. + + If neither device_type nor module_type resolved (so the queryset above was never + narrowed), a name could in principle collide across two unrelated manufacturers here + too. That's not reachable with valid data: ModularComponentTemplateModel.clean() + rejects a template with neither parent, so the form fails in _post_clean() before this + method's result would ever be saved. """ module_bay_types = self.cleaned_data['module_bay_types'] diff --git a/netbox/dcim/tests/test_views.py b/netbox/dcim/tests/test_views.py index 81da915c8..e33b93048 100644 --- a/netbox/dcim/tests/test_views.py +++ b/netbox/dcim/tests/test_views.py @@ -1793,8 +1793,10 @@ module-bays: self.assertEqual(list(mb1.module_bay_types.values_list('name', flat=True)), ['SFP28']) def test_bulk_yaml_export_prefetches_module_bay_types_on_the_module_type_itself(self): - """Compares the same queryset with/without the prefetch, since row-count comparisons - would be swamped by other per-instance relations that legitimately scale with it.""" + """Compares an unprefetched to_yaml() call per instance against export_yaml() (which + prefetches and issues no queries of its own beyond that), rather than a row-count + comparison, which other per-instance relations that legitimately scale with it would + swamp.""" manufacturer = Manufacturer.objects.create(name='Export Query MT Manufacturer', slug='export-query-mt-mfr') bay_type = ModuleBayType.objects.create(name='Export Query MT SFP28', slug='export-query-mt-sfp28')