mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 12:06:53 -06:00
Add position field for module bays
This commit is contained in:
parent
ed6a160372
commit
eaa1165611
@ -432,7 +432,10 @@ class ModuleBayTemplateSerializer(ValidatedModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = ModuleBayTemplate
|
||||
fields = ['id', 'url', 'display', 'device_type', 'name', 'label', 'description', 'created', 'last_updated']
|
||||
fields = [
|
||||
'id', 'url', 'display', 'device_type', 'name', 'label', 'position', 'description', 'created',
|
||||
'last_updated',
|
||||
]
|
||||
|
||||
|
||||
class DeviceBayTemplateSerializer(ValidatedModelSerializer):
|
||||
@ -785,8 +788,8 @@ class ModuleBaySerializer(PrimaryModelSerializer):
|
||||
class Meta:
|
||||
model = ModuleBay
|
||||
fields = [
|
||||
'id', 'url', 'display', 'device', 'name', 'label', 'description', 'tags', 'custom_fields', 'created',
|
||||
'last_updated',
|
||||
'id', 'url', 'display', 'device', 'name', 'label', 'position', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated',
|
||||
]
|
||||
|
||||
|
||||
|
@ -886,7 +886,7 @@ class ModuleBayTemplateBulkEditForm(BulkEditForm):
|
||||
)
|
||||
|
||||
class Meta:
|
||||
nullable_fields = ('label', 'description')
|
||||
nullable_fields = ('label', 'position', 'description')
|
||||
|
||||
|
||||
class DeviceBayTemplateBulkEditForm(BulkEditForm):
|
||||
@ -1153,7 +1153,7 @@ class ModuleBayBulkEditForm(
|
||||
)
|
||||
|
||||
class Meta:
|
||||
nullable_fields = ['label', 'description']
|
||||
nullable_fields = ['label', 'position', 'description']
|
||||
|
||||
|
||||
class DeviceBayBulkEditForm(
|
||||
|
@ -717,7 +717,7 @@ class ModuleBayCSVForm(CustomFieldModelCSVForm):
|
||||
|
||||
class Meta:
|
||||
model = ModuleBay
|
||||
fields = ('device', 'name', 'label', 'description')
|
||||
fields = ('device', 'name', 'label', 'position', 'description')
|
||||
|
||||
|
||||
class DeviceBayCSVForm(CustomFieldModelCSVForm):
|
||||
|
@ -1073,10 +1073,13 @@ class ModuleBayFilterForm(DeviceComponentFilterForm):
|
||||
model = ModuleBay
|
||||
field_groups = [
|
||||
['q', 'tag'],
|
||||
['name', 'label'],
|
||||
['name', 'label', 'position'],
|
||||
['region_id', 'site_group_id', 'site_id', 'location_id', 'virtual_chassis_id', 'device_id'],
|
||||
]
|
||||
tag = TagFilterField(model)
|
||||
position = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
|
||||
|
||||
class DeviceBayFilterForm(DeviceComponentFilterForm):
|
||||
|
@ -1059,7 +1059,7 @@ class ModuleBayTemplateForm(BootstrapMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = ModuleBayTemplate
|
||||
fields = [
|
||||
'device_type', 'name', 'label', 'description',
|
||||
'device_type', 'name', 'label', 'position', 'description',
|
||||
]
|
||||
widgets = {
|
||||
'device_type': forms.HiddenInput(),
|
||||
@ -1313,7 +1313,7 @@ class ModuleBayForm(CustomFieldModelForm):
|
||||
class Meta:
|
||||
model = ModuleBay
|
||||
fields = [
|
||||
'device', 'name', 'label', 'description', 'tags',
|
||||
'device', 'name', 'label', 'position', 'description', 'tags',
|
||||
]
|
||||
widgets = {
|
||||
'device': forms.HiddenInput(),
|
||||
|
@ -163,6 +163,12 @@ class ComponentTemplateCreateForm(ComponentForm):
|
||||
'manufacturer_id': '$manufacturer'
|
||||
}
|
||||
)
|
||||
description = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
|
||||
|
||||
class ModularComponentTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
module_type = DynamicModelChoiceField(
|
||||
queryset=ModuleType.objects.all(),
|
||||
required=False,
|
||||
@ -170,12 +176,9 @@ class ComponentTemplateCreateForm(ComponentForm):
|
||||
'manufacturer_id': '$manufacturer'
|
||||
}
|
||||
)
|
||||
description = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
|
||||
|
||||
class ConsolePortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class ConsolePortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=add_blank_choice(ConsolePortTypeChoices),
|
||||
widget=StaticSelect()
|
||||
@ -185,7 +188,7 @@ class ConsolePortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
)
|
||||
|
||||
|
||||
class ConsoleServerPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class ConsoleServerPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=add_blank_choice(ConsolePortTypeChoices),
|
||||
widget=StaticSelect()
|
||||
@ -195,7 +198,7 @@ class ConsoleServerPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
)
|
||||
|
||||
|
||||
class PowerPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class PowerPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=add_blank_choice(PowerPortTypeChoices),
|
||||
required=False
|
||||
@ -216,7 +219,7 @@ class PowerPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
)
|
||||
|
||||
|
||||
class PowerOutletTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class PowerOutletTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=add_blank_choice(PowerOutletTypeChoices),
|
||||
required=False
|
||||
@ -240,7 +243,7 @@ class PowerOutletTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
)
|
||||
|
||||
|
||||
class InterfaceTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class InterfaceTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=InterfaceTypeChoices,
|
||||
widget=StaticSelect()
|
||||
@ -255,7 +258,7 @@ class InterfaceTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
)
|
||||
|
||||
|
||||
class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class FrontPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=PortTypeChoices,
|
||||
widget=StaticSelect()
|
||||
@ -320,7 +323,7 @@ class FrontPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
}
|
||||
|
||||
|
||||
class RearPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
class RearPortTemplateCreateForm(ModularComponentTemplateCreateForm):
|
||||
type = forms.ChoiceField(
|
||||
choices=PortTypeChoices,
|
||||
widget=StaticSelect(),
|
||||
@ -341,6 +344,7 @@ class RearPortTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
|
||||
|
||||
class ModuleBayTemplateCreateForm(ComponentTemplateCreateForm):
|
||||
# TODO: Support patterned position assignment
|
||||
field_order = ('manufacturer', 'device_type', 'name_pattern', 'label_pattern', 'description')
|
||||
|
||||
|
||||
|
@ -155,7 +155,7 @@ class ModuleBayTemplateImportForm(ComponentTemplateImportForm):
|
||||
class Meta:
|
||||
model = ModuleBayTemplate
|
||||
fields = [
|
||||
'device_type', 'name', 'label', 'description',
|
||||
'device_type', 'name', 'label', 'position', 'description',
|
||||
]
|
||||
|
||||
|
||||
|
@ -105,6 +105,7 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=64)),
|
||||
('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
|
||||
('label', models.CharField(blank=True, max_length=64)),
|
||||
('position', models.CharField(blank=True, max_length=30)),
|
||||
('description', models.CharField(blank=True, max_length=200)),
|
||||
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modulebays', to='dcim.device')),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
@ -241,6 +242,7 @@ class Migration(migrations.Migration):
|
||||
('name', models.CharField(max_length=64)),
|
||||
('_name', utilities.fields.NaturalOrderingField('name', blank=True, max_length=100, naturalize_function=utilities.ordering.naturalize)),
|
||||
('label', models.CharField(blank=True, max_length=64)),
|
||||
('position', models.CharField(blank=True, max_length=30)),
|
||||
('description', models.CharField(blank=True, max_length=200)),
|
||||
('device_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modulebaytemplates', to='dcim.devicetype')),
|
||||
],
|
||||
|
@ -123,6 +123,11 @@ class ModularComponentTemplateModel(ComponentTemplateModel):
|
||||
"A component template must be associated with either a device type or a module type."
|
||||
)
|
||||
|
||||
def resolve_name(self, module):
|
||||
if module:
|
||||
return self.name.replace('{module}', module.module_bay.position)
|
||||
return self.name
|
||||
|
||||
|
||||
@extras_features('webhooks')
|
||||
class ConsolePortTemplate(ModularComponentTemplateModel):
|
||||
@ -144,7 +149,7 @@ class ConsolePortTemplate(ModularComponentTemplateModel):
|
||||
|
||||
def instantiate(self, **kwargs):
|
||||
return ConsolePort(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
**kwargs
|
||||
@ -171,7 +176,7 @@ class ConsoleServerPortTemplate(ModularComponentTemplateModel):
|
||||
|
||||
def instantiate(self, **kwargs):
|
||||
return ConsoleServerPort(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
**kwargs
|
||||
@ -210,7 +215,7 @@ class PowerPortTemplate(ModularComponentTemplateModel):
|
||||
|
||||
def instantiate(self, **kwargs):
|
||||
return PowerPort(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
maximum_draw=self.maximum_draw,
|
||||
@ -279,7 +284,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
|
||||
else:
|
||||
power_port = None
|
||||
return PowerOutlet(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
power_port=power_port,
|
||||
@ -318,7 +323,7 @@ class InterfaceTemplate(ModularComponentTemplateModel):
|
||||
|
||||
def instantiate(self, **kwargs):
|
||||
return Interface(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
mgmt_only=self.mgmt_only,
|
||||
@ -387,7 +392,7 @@ class FrontPortTemplate(ModularComponentTemplateModel):
|
||||
else:
|
||||
rear_port = None
|
||||
return FrontPort(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
color=self.color,
|
||||
@ -426,7 +431,7 @@ class RearPortTemplate(ModularComponentTemplateModel):
|
||||
|
||||
def instantiate(self, **kwargs):
|
||||
return RearPort(
|
||||
name=self.name,
|
||||
name=self.resolve_name(kwargs.get('module')),
|
||||
label=self.label,
|
||||
type=self.type,
|
||||
color=self.color,
|
||||
@ -440,6 +445,12 @@ class ModuleBayTemplate(ComponentTemplateModel):
|
||||
"""
|
||||
A template for a ModuleBay to be created for a new parent Device.
|
||||
"""
|
||||
position = models.CharField(
|
||||
max_length=30,
|
||||
blank=True,
|
||||
help_text='Identifier to reference when renaming installed components'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ('device_type', '_name')
|
||||
unique_together = ('device_type', 'name')
|
||||
@ -448,7 +459,8 @@ class ModuleBayTemplate(ComponentTemplateModel):
|
||||
return ModuleBay(
|
||||
device=device,
|
||||
name=self.name,
|
||||
label=self.label
|
||||
label=self.label,
|
||||
position=self.position
|
||||
)
|
||||
|
||||
|
||||
|
@ -880,6 +880,12 @@ class ModuleBay(ComponentModel):
|
||||
"""
|
||||
An empty space within a Device which can house a child device
|
||||
"""
|
||||
position = models.CharField(
|
||||
max_length=30,
|
||||
blank=True,
|
||||
help_text='Identifier to reference when renaming installed components'
|
||||
)
|
||||
|
||||
clone_fields = ['device']
|
||||
|
||||
class Meta:
|
||||
|
@ -749,7 +749,7 @@ class ModuleBayTable(DeviceComponentTable):
|
||||
|
||||
class Meta(DeviceComponentTable.Meta):
|
||||
model = ModuleBay
|
||||
fields = ('pk', 'id', 'name', 'device', 'label', 'installed_module', 'description', 'tags')
|
||||
fields = ('pk', 'id', 'name', 'device', 'label', 'position', 'installed_module', 'description', 'tags')
|
||||
default_columns = ('pk', 'name', 'device', 'label', 'installed_module', 'description')
|
||||
|
||||
|
||||
|
@ -217,7 +217,7 @@ class ModuleBayTemplateTable(ComponentTemplateTable):
|
||||
|
||||
class Meta(ComponentTemplateTable.Meta):
|
||||
model = ModuleBayTemplate
|
||||
fields = ('pk', 'name', 'label', 'description', 'actions')
|
||||
fields = ('pk', 'name', 'label', 'position', 'description', 'actions')
|
||||
empty_text = "None"
|
||||
|
||||
|
||||
|
@ -23,6 +23,10 @@
|
||||
<th scope="row">Label</th>
|
||||
<td>{{ object.label|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Position</th>
|
||||
<td>{{ object.position|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Description</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
{% block tab_items %}
|
||||
<li role="presentation" class="nav-item">
|
||||
<a href="{% url 'dcim:devicetype' pk=object.pk %}" class="nav-link{% if active_tab == 'moduletype' %} active{% endif %}">
|
||||
<a href="{% url 'dcim:moduletype' pk=object.pk %}" class="nav-link{% if active_tab == 'moduletype' %} active{% endif %}">
|
||||
Module Type
|
||||
</a>
|
||||
</li>
|
||||
|
Loading…
Reference in New Issue
Block a user