mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Add config_template FK to Device
This commit is contained in:
parent
72536d28a7
commit
15be44d06b
@ -72,6 +72,10 @@ The device's operational status.
|
||||
|
||||
A device may be associated with a particular [platform](./platform.md) to indicate its operating system. Note that only platforms assigned to the associated manufacturer (or to no manufacturer) will be available for selection.
|
||||
|
||||
### Configuration Template
|
||||
|
||||
The [configuration template](../extras/configtemplate.md) from which the configuration for this device can be rendered. If set, this will override any config template referenced by the device's role or platform.
|
||||
|
||||
### Primary IPv4 & IPv6 Addresses
|
||||
|
||||
Each device may designate one primary IPv4 address and/or one primary IPv6 address for management purposes.
|
||||
|
@ -19,3 +19,7 @@ The color used when displaying the role in the NetBox UI.
|
||||
### VM Role
|
||||
|
||||
If selected, this role may be assigned to [virtual machines](../virtualization/virtualmachine.md)
|
||||
|
||||
### Configuration Template
|
||||
|
||||
The default [configuration template](../extras/configtemplate.md) for devices assigned to this role.
|
||||
|
@ -606,8 +606,8 @@ class DeviceRoleSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'slug', 'color', 'vm_role', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'device_count', 'virtualmachine_count',
|
||||
'id', 'url', 'display', 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags',
|
||||
'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count',
|
||||
]
|
||||
|
||||
|
||||
|
@ -366,7 +366,7 @@ class InventoryItemTemplateViewSet(NetBoxModelViewSet):
|
||||
#
|
||||
|
||||
class DeviceRoleViewSet(NetBoxModelViewSet):
|
||||
queryset = DeviceRole.objects.prefetch_related('tags').annotate(
|
||||
queryset = DeviceRole.objects.prefetch_related('config_template', 'tags').annotate(
|
||||
device_count=count_related(Device, 'device_role'),
|
||||
virtualmachine_count=count_related(VirtualMachine, 'role')
|
||||
)
|
||||
|
@ -777,6 +777,10 @@ class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeCompo
|
||||
|
||||
|
||||
class DeviceRoleFilterSet(OrganizationalModelFilterSet):
|
||||
config_template_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
label=_('Config template (ID)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
|
@ -455,6 +455,10 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
widget=BulkEditNullBooleanSelect,
|
||||
label=_('VM role')
|
||||
)
|
||||
config_template = DynamicModelChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
max_length=200,
|
||||
required=False
|
||||
@ -462,9 +466,9 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
|
||||
model = DeviceRole
|
||||
fieldsets = (
|
||||
(None, ('color', 'vm_role', 'description')),
|
||||
(None, ('color', 'vm_role', 'config_template', 'description')),
|
||||
)
|
||||
nullable_fields = ('color', 'description')
|
||||
nullable_fields = ('color', 'config_template', 'description')
|
||||
|
||||
|
||||
class PlatformBulkEditForm(NetBoxModelBulkEditForm):
|
||||
|
@ -308,11 +308,17 @@ class ModuleTypeImportForm(NetBoxModelImportForm):
|
||||
|
||||
|
||||
class DeviceRoleImportForm(NetBoxModelImportForm):
|
||||
config_template = CSVModelChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text=_('Config template')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = ('name', 'slug', 'color', 'vm_role', 'description', 'tags')
|
||||
fields = ('name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags')
|
||||
help_texts = {
|
||||
'color': mark_safe(_('RGB color in hexadecimal (e.g. <code>00ff00</code>)')),
|
||||
}
|
||||
@ -438,6 +444,7 @@ class DeviceImportForm(BaseDeviceImportForm):
|
||||
config_template = CSVModelChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
to_field_name='name',
|
||||
required=False,
|
||||
help_text=_('Config template')
|
||||
)
|
||||
|
||||
|
@ -569,6 +569,11 @@ class ModuleTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
|
||||
class DeviceRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
model = DeviceRole
|
||||
config_template_id = DynamicModelMultipleChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False,
|
||||
label=_('Config template')
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
|
@ -417,18 +417,22 @@ class ModuleTypeForm(NetBoxModelForm):
|
||||
|
||||
|
||||
class DeviceRoleForm(NetBoxModelForm):
|
||||
config_template = DynamicModelChoiceField(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
fieldsets = (
|
||||
('Device Role', (
|
||||
'name', 'slug', 'color', 'vm_role', 'description', 'tags',
|
||||
'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags',
|
||||
)),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DeviceRole
|
||||
fields = [
|
||||
'name', 'slug', 'color', 'vm_role', 'description', 'tags',
|
||||
'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags',
|
||||
]
|
||||
|
||||
|
||||
|
20
netbox/dcim/migrations/0170_devicerole_config_template.py
Normal file
20
netbox/dcim/migrations/0170_devicerole_config_template.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Generated by Django 4.1.6 on 2023-02-12 20:41
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('extras', '0086_configtemplate'),
|
||||
('dcim', '0169_device_configtemplate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='devicerole',
|
||||
name='config_template',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='device_roles', to='extras.configtemplate'),
|
||||
),
|
||||
]
|
@ -410,6 +410,13 @@ class DeviceRole(OrganizationalModel):
|
||||
verbose_name='VM Role',
|
||||
help_text=_('Virtual machines may be assigned to this role')
|
||||
)
|
||||
config_template = models.ForeignKey(
|
||||
to='extras.ConfigTemplate',
|
||||
on_delete=models.PROTECT,
|
||||
related_name='device_roles',
|
||||
blank=True,
|
||||
null=True
|
||||
)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('dcim:devicerole', args=[self.pk])
|
||||
@ -869,6 +876,12 @@ class Device(PrimaryModel, ConfigContextModel):
|
||||
def interfaces_count(self):
|
||||
return self.vc_interfaces().count()
|
||||
|
||||
def get_config_template(self):
|
||||
"""
|
||||
Return the appropriate ConfigTemplate (if any) for this Device.
|
||||
"""
|
||||
return self.config_template or self.device_role.config_template
|
||||
|
||||
def get_vc_master(self):
|
||||
"""
|
||||
If this Device is a VirtualChassis member, return the VC master. Otherwise, return None.
|
||||
|
@ -86,6 +86,9 @@ class DeviceRoleTable(NetBoxTable):
|
||||
)
|
||||
color = columns.ColorColumn()
|
||||
vm_role = columns.BooleanColumn()
|
||||
config_template = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:devicerole_list'
|
||||
)
|
||||
@ -93,8 +96,8 @@ class DeviceRoleTable(NetBoxTable):
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = models.DeviceRole
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description', 'slug', 'tags',
|
||||
'actions', 'created', 'last_updated',
|
||||
'pk', 'id', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'config_template', 'description',
|
||||
'slug', 'tags', 'actions', 'created', 'last_updated',
|
||||
)
|
||||
default_columns = ('pk', 'name', 'device_count', 'vm_count', 'color', 'vm_role', 'description')
|
||||
|
||||
|
@ -13,7 +13,7 @@ from django.views.generic import View
|
||||
|
||||
from circuits.models import Circuit, CircuitTermination
|
||||
from extras.views import ObjectConfigContextView
|
||||
from ipam.models import ASN, IPAddress, Prefix, Service, VLAN, VLANGroup
|
||||
from ipam.models import ASN, IPAddress, Prefix, VLAN, VLANGroup
|
||||
from ipam.tables import InterfaceVLANTable
|
||||
from netbox.views import generic
|
||||
from utilities.forms import ConfirmationForm
|
||||
@ -2008,16 +2008,20 @@ class DeviceRenderConfigView(generic.ObjectView):
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
# Compile context data
|
||||
context_data = {
|
||||
'device': instance,
|
||||
}
|
||||
context_data.update(**instance.get_config_context())
|
||||
if instance.config_template:
|
||||
rendered_config = instance.config_template.render(context=context_data)
|
||||
|
||||
# Render the config template
|
||||
if config_template := instance.get_config_template():
|
||||
rendered_config = config_template.render(context=context_data)
|
||||
else:
|
||||
rendered_config = None
|
||||
|
||||
return {
|
||||
'config_template': config_template,
|
||||
'context_data': context_data,
|
||||
'rendered_config': rendered_config,
|
||||
}
|
||||
|
@ -12,15 +12,15 @@
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">Config Template</th>
|
||||
<td>{{ object.config_template|linkify|placeholder }}</td>
|
||||
<td>{{ config_template|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Data Source</th>
|
||||
<td>{{ object.config_template.data_file.source|linkify|placeholder }}</td>
|
||||
<td>{{ config_template.data_file.source|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Data File</th>
|
||||
<td>{{ object.config_template.data_file|linkify|placeholder }}</td>
|
||||
<td>{{ config_template.data_file|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
@ -42,6 +42,10 @@
|
||||
<th scope="row">VM Role</th>
|
||||
<td>{% checkmark object.vm_role %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Config Template</th>
|
||||
<td>{{ object.config_template|linkify|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user