mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
Merge pull request #170 from peelman/add-mac-address-to-interface
Add mac address to interface
This commit is contained in:
commit
9793b406e9
@ -334,7 +334,7 @@ class InterfaceSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = Interface
|
||||
fields = ['id', 'device', 'name', 'form_factor', 'mgmt_only', 'description', 'is_connected']
|
||||
fields = ['id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected']
|
||||
|
||||
|
||||
class InterfaceNestedSerializer(InterfaceSerializer):
|
||||
@ -348,7 +348,7 @@ class InterfaceDetailSerializer(InterfaceSerializer):
|
||||
connected_interface = InterfaceSerializer(source='get_connected_interface')
|
||||
|
||||
class Meta(InterfaceSerializer.Meta):
|
||||
fields = ['id', 'device', 'name', 'form_factor', 'mgmt_only', 'description', 'is_connected',
|
||||
fields = ['id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected',
|
||||
'connected_interface']
|
||||
|
||||
|
||||
|
44
netbox/dcim/fields.py
Normal file
44
netbox/dcim/fields.py
Normal file
@ -0,0 +1,44 @@
|
||||
from netaddr import EUI, mac_unix_expanded
|
||||
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
|
||||
from .formfields import MACAddressFormField
|
||||
|
||||
|
||||
class mac_unix_expanded_uppercase(mac_unix_expanded):
|
||||
word_fmt = '%.2X'
|
||||
|
||||
|
||||
class MACAddressField(models.Field):
|
||||
description = "PostgreSQL MAC Address field"
|
||||
|
||||
def python_type(self):
|
||||
return EUI
|
||||
|
||||
def from_db_value(self, value, expression, connection, context):
|
||||
return self.to_python(value)
|
||||
|
||||
def to_python(self, value):
|
||||
if not value:
|
||||
return value
|
||||
try:
|
||||
return EUI(value, dialect=mac_unix_expanded_uppercase)
|
||||
except ValueError as e:
|
||||
raise ValidationError(e)
|
||||
|
||||
def db_type(self, connection):
|
||||
return 'macaddr'
|
||||
|
||||
def get_prep_value(self, value):
|
||||
if not value:
|
||||
return None
|
||||
return str(self.to_python(value))
|
||||
|
||||
def form_class(self):
|
||||
return MACAddressFormField
|
||||
|
||||
def formfield(self, **kwargs):
|
||||
defaults = {'form_class': self.form_class()}
|
||||
defaults.update(kwargs)
|
||||
return super(MACAddressField, self).formfield(**defaults)
|
@ -3419,6 +3419,7 @@
|
||||
"fields": {
|
||||
"device": 3,
|
||||
"name": "em0",
|
||||
"mac_address": "00-00-00-AA-BB-CC",
|
||||
"form_factor": 800,
|
||||
"mgmt_only": true,
|
||||
"description": ""
|
||||
@ -3772,6 +3773,7 @@
|
||||
"device": 4,
|
||||
"name": "em0",
|
||||
"form_factor": 1000,
|
||||
"mac_address": "ff-ee-dd-33-22-11",
|
||||
"mgmt_only": true,
|
||||
"description": ""
|
||||
}
|
||||
@ -5686,6 +5688,7 @@
|
||||
"device": 9,
|
||||
"name": "eth0",
|
||||
"form_factor": 1000,
|
||||
"mac_address": "44-55-66-77-88-99",
|
||||
"mgmt_only": true,
|
||||
"description": ""
|
||||
}
|
||||
@ -5865,4 +5868,4 @@
|
||||
"connection_status": true
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
|
26
netbox/dcim/formfields.py
Normal file
26
netbox/dcim/formfields.py
Normal file
@ -0,0 +1,26 @@
|
||||
from netaddr import EUI, AddrFormatError
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
|
||||
#
|
||||
# Form fields
|
||||
#
|
||||
|
||||
class MACAddressFormField(forms.Field):
|
||||
default_error_messages = {
|
||||
'invalid': "Enter a valid MAC address.",
|
||||
}
|
||||
|
||||
def to_python(self, value):
|
||||
if not value:
|
||||
return None
|
||||
|
||||
if isinstance(value, EUI):
|
||||
return value
|
||||
|
||||
try:
|
||||
return EUI(value)
|
||||
except AddrFormatError:
|
||||
raise ValidationError("Please specify a valid MAC address.")
|
@ -925,7 +925,7 @@ class InterfaceForm(forms.ModelForm, BootstrapMixin):
|
||||
|
||||
class Meta:
|
||||
model = Interface
|
||||
fields = ['device', 'name', 'form_factor', 'mgmt_only', 'description']
|
||||
fields = ['device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description']
|
||||
widgets = {
|
||||
'device': forms.HiddenInput(),
|
||||
}
|
||||
@ -936,7 +936,7 @@ class InterfaceCreateForm(forms.ModelForm, BootstrapMixin):
|
||||
|
||||
class Meta:
|
||||
model = Interface
|
||||
fields = ['name_pattern', 'form_factor', 'mgmt_only', 'description']
|
||||
fields = ['name_pattern', 'form_factor', 'mac_address', 'mgmt_only', 'description']
|
||||
|
||||
|
||||
class InterfaceBulkCreateForm(InterfaceCreateForm, BootstrapMixin):
|
||||
|
26
netbox/dcim/migrations/0005_auto_20160706_1722.py
Normal file
26
netbox/dcim/migrations/0005_auto_20160706_1722.py
Normal file
@ -0,0 +1,26 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.7 on 2016-07-06 17:22
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import dcim.fields
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0004_auto_20160701_2049'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='interface',
|
||||
name='mac_address',
|
||||
field=dcim.fields.MACAddressField(blank=True, null=True, verbose_name=b'MAC Address'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='devicetype',
|
||||
name='subdevice_role',
|
||||
field=models.NullBooleanField(choices=[(None, b'None'), (True, b'Parent'), (False, b'Child')], default=None, help_text=b'Parent devices house child devices in device bays. Select "None" if this device type is neither a parent nor a child.', verbose_name=b'Parent/child status'),
|
||||
),
|
||||
]
|
@ -10,6 +10,7 @@ from extras.rpc import RPC_CLIENTS
|
||||
from utilities.fields import NullableCharField
|
||||
from utilities.models import CreatedUpdatedModel
|
||||
|
||||
from .fields import MACAddressField
|
||||
|
||||
RACK_FACE_FRONT = 0
|
||||
RACK_FACE_REAR = 1
|
||||
@ -856,6 +857,7 @@ class Interface(models.Model):
|
||||
device = models.ForeignKey('Device', related_name='interfaces', on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=30)
|
||||
form_factor = models.PositiveSmallIntegerField(choices=IFACE_FF_CHOICES, default=IFACE_FF_SFP_PLUS)
|
||||
mac_address = MACAddressField(null=True, blank=True, verbose_name='MAC Address')
|
||||
mgmt_only = models.BooleanField(default=False, verbose_name='OOB Management',
|
||||
help_text="This interface is used only for out-of-band management")
|
||||
description = models.CharField(max_length=100, blank=True)
|
||||
|
@ -529,6 +529,7 @@ class InterfaceTest(APITestCase):
|
||||
'device',
|
||||
'name',
|
||||
'form_factor',
|
||||
'mac_address',
|
||||
'mgmt_only',
|
||||
'description',
|
||||
'is_connected'
|
||||
@ -541,6 +542,7 @@ class InterfaceTest(APITestCase):
|
||||
'device',
|
||||
'name',
|
||||
'form_factor',
|
||||
'mac_address',
|
||||
'mgmt_only',
|
||||
'description',
|
||||
'is_connected',
|
||||
|
@ -1252,6 +1252,7 @@ def interface_add(request, pk):
|
||||
'device': device.pk,
|
||||
'name': name,
|
||||
'form_factor': form.cleaned_data['form_factor'],
|
||||
'mac_address': form.cleaned_data['mac_address'],
|
||||
'mgmt_only': form.cleaned_data['mgmt_only'],
|
||||
'description': form.cleaned_data['description'],
|
||||
})
|
||||
@ -1339,6 +1340,7 @@ class InterfaceBulkAddView(PermissionRequiredMixin, BulkEditView):
|
||||
iface_form = forms.InterfaceForm({
|
||||
'device': device.pk,
|
||||
'name': name,
|
||||
'mac_address': mac_address,
|
||||
'form_factor': form.cleaned_data['form_factor'],
|
||||
'mgmt_only': form.cleaned_data['mgmt_only'],
|
||||
'description': form.cleaned_data['description'],
|
||||
|
@ -295,9 +295,6 @@
|
||||
{% if interfaces or device.device_type.is_network_device %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{% if perms.dcim.add_interface %}
|
||||
<a href="{% url 'dcim:interface_add' pk=device.pk %}" class="btn btn-primary btn-xs pull-right"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Add Interfaces</a>
|
||||
{% endif %}
|
||||
<strong>Interfaces</strong>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
@ -309,6 +306,14 @@
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% if perms.dcim.add_interface %}
|
||||
<div class="panel-footer text-right">
|
||||
<a href="{% url 'dcim:interface_add' pk=device.pk %}" class="btn btn-xs btn-primary">
|
||||
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
|
||||
Add interface
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if cs_ports or device.device_type.is_console_server %}
|
||||
|
@ -6,22 +6,26 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
{% if not iface.is_physical %}
|
||||
<td colspan="2">Virtual</td>
|
||||
<td>Virtual</td>
|
||||
{% elif iface.connection %}
|
||||
{% with iface.get_connected_interface as connected_iface %}
|
||||
<td>
|
||||
<a href="{% url 'dcim:device' pk=connected_iface.device.pk %}">{{ connected_iface.device }}</a>
|
||||
</td>
|
||||
<td>
|
||||
∷
|
||||
<span title="{{ connected_iface.get_form_factor_display }}">{{ connected_iface }}</span>
|
||||
</td>
|
||||
{% endwith %}
|
||||
{% elif iface.circuit %}
|
||||
<td colspan="2">
|
||||
<td>
|
||||
<a href="{% url 'circuits:circuit' pk=iface.circuit.pk %}">{{ iface.circuit }}</a>
|
||||
</td>
|
||||
{% else %}
|
||||
<td colspan="2">Not connected</td>
|
||||
<td>Not connected</td>
|
||||
{% endif %}
|
||||
{% if iface.mac_address %}
|
||||
<td><span class="small text-muted">{{ iface.mac_address }}</span></td>
|
||||
{% else %}
|
||||
<td><span class="small text-muted">00:00:00:00:00:00</span></td>
|
||||
{% endif %}
|
||||
<td class="text-right">
|
||||
{% if iface.circuit or iface.connection %}
|
||||
|
Loading…
Reference in New Issue
Block a user