From 702c862a34e9b76176ee6c6f711f5d487dff4bd1 Mon Sep 17 00:00:00 2001 From: Arthur Hanson Date: Fri, 26 Jul 2024 17:12:28 +0700 Subject: [PATCH] 10500 token resolution --- netbox/dcim/forms/common.py | 34 ++++++++++++++++--- .../dcim/models/device_component_templates.py | 24 +++++++++++-- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/netbox/dcim/forms/common.py b/netbox/dcim/forms/common.py index 3be4d08e8..aececa200 100644 --- a/netbox/dcim/forms/common.py +++ b/netbox/dcim/forms/common.py @@ -70,6 +70,18 @@ class InterfaceCommonForm(forms.Form): class ModuleCommonForm(forms.Form): + def _get_module_bay_tree(self, module_bay): + module_bays = [] + all_module_bays = module.device.modulebays.all().select_related('module') + while module_bay: + module_bays.append(module_bay) + if module_bay.module: + module_bay = module_bay.module.module_bay + else: + module_bay = None + + return module_bays.reverse() + def clean(self): super().clean() @@ -104,13 +116,25 @@ class ModuleCommonForm(forms.Form): # Get the templates for the module type. for template in getattr(module_type, templates).all(): + resolved_name = template.name # Installing modules with placeholders require that the bay has a position value - if MODULE_TOKEN in template.name and not module_bay.position: - raise forms.ValidationError( - _("Cannot install module with placeholder values in a module bay with no position defined.") - ) + if MODULE_TOKEN in template.name: + if not module_bay.position: + raise forms.ValidationError( + _("Cannot install module with placeholder values in a module bay with no position defined.") + ) + + module_bays = self._get_module_bay_tree(template) + if len(module_bays) != template.name.count(MODULE_TOKEN): + raise forms.ValidationError( + _("Cannot install module with placeholder values in a module bay tree {level} in tree but {tokens} placeholders given.").format( + level=len(module_bays), tokens=template.name.count(MODULE_TOKEN) + ) + ) + + for module_bay in module_bays: + resolved_name = resolved_name.replace(MODULE_TOKEN, module_bay.position, 1) - resolved_name = template.name.replace(MODULE_TOKEN, module_bay.position) existing_item = installed_components.get(resolved_name) # It is not possible to adopt components already belonging to a module diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py index bad9ee09b..dfc64f9c8 100644 --- a/netbox/dcim/models/device_component_templates.py +++ b/netbox/dcim/models/device_component_templates.py @@ -158,14 +158,34 @@ class ModularComponentTemplateModel(ComponentTemplateModel): _("A component template must be associated with either a device type or a module type.") ) + def _get_module_tree(self, module): + modules = [] + all_module_bays = module.device.modulebays.all().select_related('module') + while module: + modules.append(module) + if module.module_bay: + module = module.module_bay.module + else: + module = None + + return modules.reverse() + def resolve_name(self, module): if module: - return self.name.replace(MODULE_TOKEN, module.module_bay.position) + modules = self._get_module_tree(module) + name = self.name + for module in modules: + name = name.replace(MODULE_TOKEN, module.module_bay.position, 1) + return name return self.name def resolve_label(self, module): if module: - return self.label.replace(MODULE_TOKEN, module.module_bay.position) + modules = self._get_module_tree(module) + label = self.label + for module in modules: + label = label.replace(MODULE_TOKEN, module.module_bay.position, 1) + return label return self.label