mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-29 11:56:25 -06:00
Implements #777 Add Service Identifier field to VLAN, to store VXLAN or ISID.
This commit is contained in:
parent
39d083eae7
commit
e18c1752ac
@ -83,7 +83,7 @@ One IP address can be designated as the network address translation (NAT) IP add
|
|||||||
|
|
||||||
# VLANs
|
# VLANs
|
||||||
|
|
||||||
A VLAN represents an isolated layer two domain, identified by a name and a numeric ID (1-4094). Note that while it is good practice, neither VLAN names nor IDs must be unique within a site. This is to accommodate the fact that many real-world network use less-than-optimal VLAN allocations and may have overlapping VLAN ID assignments in practice.
|
A VLAN represents an isolated layer two domain, identified by a name and a numeric ID (1-4094). Note that while it is good practice, neither VLAN names nor IDs must be unique within a site. This is to accommodate the fact that many real-world network use less-than-optimal VLAN allocations and may have overlapping VLAN ID assignments in practice. A "service identifier" (VXLAN or ISID, 1-16777215) can uniquely identify a VLAN where the ID is not unique.
|
||||||
|
|
||||||
Like prefixes, each VLAN is assigned an operational status and (optionally) a functional role.
|
Like prefixes, each VLAN is assigned an operational status and (optionally) a functional role.
|
||||||
|
|
||||||
|
@ -72,9 +72,9 @@ class VLANGroupAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
@admin.register(VLAN)
|
@admin.register(VLAN)
|
||||||
class VLANAdmin(admin.ModelAdmin):
|
class VLANAdmin(admin.ModelAdmin):
|
||||||
list_display = ['site', 'vid', 'name', 'tenant', 'status', 'role']
|
list_display = ['site', 'vid', 'name', 'tenant', 'status', 'role', 'service_identifier']
|
||||||
list_filter = ['site', 'tenant', 'status', 'role']
|
list_filter = ['site', 'tenant', 'status', 'role']
|
||||||
search_fields = ['vid', 'name']
|
search_fields = ['vid', 'name', 'service_identifier']
|
||||||
|
|
||||||
def get_queryset(self, request):
|
def get_queryset(self, request):
|
||||||
qs = super(VLANAdmin, self).get_queryset(request)
|
qs = super(VLANAdmin, self).get_queryset(request)
|
||||||
|
@ -484,7 +484,7 @@ class VLANForm(BootstrapMixin, CustomFieldForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLAN
|
model = VLAN
|
||||||
fields = ['site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description']
|
fields = ['site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'service_identifier']
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'site': "The site at which this VLAN exists",
|
'site': "The site at which this VLAN exists",
|
||||||
'group': "VLAN group (optional)",
|
'group': "VLAN group (optional)",
|
||||||
@ -492,6 +492,7 @@ class VLANForm(BootstrapMixin, CustomFieldForm):
|
|||||||
'name': "Configured VLAN name",
|
'name': "Configured VLAN name",
|
||||||
'status': "Operational status of this VLAN",
|
'status': "Operational status of this VLAN",
|
||||||
'role': "The primary function of this VLAN",
|
'role': "The primary function of this VLAN",
|
||||||
|
'service_identifier': "Unique identifier: VXLAN or ISID",
|
||||||
}
|
}
|
||||||
widgets = {
|
widgets = {
|
||||||
'site': forms.Select(attrs={'filter-for': 'group'}),
|
'site': forms.Select(attrs={'filter-for': 'group'}),
|
||||||
@ -523,7 +524,7 @@ class VLANFromCSVForm(forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = VLAN
|
model = VLAN
|
||||||
fields = ['site', 'group', 'vid', 'name', 'tenant', 'status_name', 'role', 'description']
|
fields = ['site', 'group', 'vid', 'name', 'tenant', 'status_name', 'role', 'description', 'service_identifier']
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
m = super(VLANFromCSVForm, self).save(commit=False)
|
m = super(VLANFromCSVForm, self).save(commit=False)
|
||||||
@ -548,7 +549,7 @@ class VLANBulkEditForm(BootstrapMixin, CustomFieldBulkEditForm):
|
|||||||
description = forms.CharField(max_length=100, required=False)
|
description = forms.CharField(max_length=100, required=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
nullable_fields = ['group', 'tenant', 'role', 'description']
|
nullable_fields = ['group', 'tenant', 'role', 'description', 'service_identifier']
|
||||||
|
|
||||||
|
|
||||||
def vlan_status_choices():
|
def vlan_status_choices():
|
||||||
|
25
netbox/ipam/migrations/0014_auto_20170122_0829.py
Normal file
25
netbox/ipam/migrations/0014_auto_20170122_0829.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2017-01-22 08:29
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import django.core.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ipam', '0013_prefix_add_is_pool'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='vlan',
|
||||||
|
options={'ordering': ['site', 'group', 'vid', 'service_identifier'], 'verbose_name': 'VLAN', 'verbose_name_plural': 'VLANs'},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='vlan',
|
||||||
|
name='service_identifier',
|
||||||
|
field=models.PositiveIntegerField(blank=True, default=None, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(16777215)], verbose_name=b'Service Identifier'),
|
||||||
|
),
|
||||||
|
]
|
@ -513,10 +513,14 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
|
|||||||
status = models.PositiveSmallIntegerField('Status', choices=VLAN_STATUS_CHOICES, default=1)
|
status = models.PositiveSmallIntegerField('Status', choices=VLAN_STATUS_CHOICES, default=1)
|
||||||
role = models.ForeignKey('Role', related_name='vlans', on_delete=models.SET_NULL, blank=True, null=True)
|
role = models.ForeignKey('Role', related_name='vlans', on_delete=models.SET_NULL, blank=True, null=True)
|
||||||
description = models.CharField(max_length=100, blank=True)
|
description = models.CharField(max_length=100, blank=True)
|
||||||
|
service_identifier = models.PositiveIntegerField(null=True, blank=True, default=None, verbose_name='Service Identifier', validators=[
|
||||||
|
MinValueValidator(1),
|
||||||
|
MaxValueValidator(16777215)
|
||||||
|
])
|
||||||
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
|
custom_field_values = GenericRelation(CustomFieldValue, content_type_field='obj_type', object_id_field='obj_id')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
ordering = ['site', 'group', 'vid']
|
ordering = ['site', 'group', 'vid', 'service_identifier']
|
||||||
unique_together = [
|
unique_together = [
|
||||||
['group', 'vid'],
|
['group', 'vid'],
|
||||||
['group', 'name'],
|
['group', 'name'],
|
||||||
@ -548,6 +552,7 @@ class VLAN(CreatedUpdatedModel, CustomFieldModel):
|
|||||||
self.get_status_display(),
|
self.get_status_display(),
|
||||||
self.role.name if self.role else None,
|
self.role.name if self.role else None,
|
||||||
self.description,
|
self.description,
|
||||||
|
self.service_identifier
|
||||||
])
|
])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -311,7 +311,8 @@ class VLANTable(BaseTable):
|
|||||||
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
status = tables.TemplateColumn(STATUS_LABEL, verbose_name='Status')
|
||||||
role = tables.TemplateColumn(VLAN_ROLE_LINK, verbose_name='Role')
|
role = tables.TemplateColumn(VLAN_ROLE_LINK, verbose_name='Role')
|
||||||
description = tables.Column(verbose_name='Description')
|
description = tables.Column(verbose_name='Description')
|
||||||
|
service_identifier = tables.Column(verbose_name='Service Identifier')
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = VLAN
|
model = VLAN
|
||||||
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description')
|
fields = ('pk', 'vid', 'site', 'group', 'name', 'prefixes', 'tenant', 'status', 'role', 'description', 'service_identifier')
|
||||||
|
@ -108,6 +108,16 @@
|
|||||||
<span class="text-muted">N/A</span>
|
<span class="text-muted">N/A</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Service Identifier</td>
|
||||||
|
<td>
|
||||||
|
{% if vlan.service_identifier %}
|
||||||
|
{{ vlan.service_identifier }}
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">None</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
{% render_field form.status %}
|
{% render_field form.status %}
|
||||||
{% render_field form.role %}
|
{% render_field form.role %}
|
||||||
{% render_field form.description %}
|
{% render_field form.description %}
|
||||||
|
{% render_field form.service_identifier %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if form.custom_fields %}
|
{% if form.custom_fields %}
|
||||||
|
@ -68,10 +68,15 @@
|
|||||||
<td>Short description (optional)</td>
|
<td>Short description (optional)</td>
|
||||||
<td>Security team only</td>
|
<td>Security team only</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Service Identifier</td>
|
||||||
|
<td>VXLAN identifier or ISID</td>
|
||||||
|
<td>1001400</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h4>Example</h4>
|
<h4>Example</h4>
|
||||||
<pre>LAS2,Backend Network,1400,Cameras,Internal,Active,Security,Security team only</pre>
|
<pre>LAS2,Backend Network,1400,Cameras,Internal,Active,Security,Security team only,1001400</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Loading…
Reference in New Issue
Block a user