1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Replace 'is_connected' boolean with Cable attachment

This commit is contained in:
Jeremy Stretch
2018-10-29 13:36:41 -04:00
parent 427226de8c
commit d7766b9828
5 changed files with 26 additions and 66 deletions

View File

@ -245,7 +245,7 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
label='Interface',
widget=APISelect(
api_url='/api/dcim/interfaces/?device_id={{device}}&type=physical',
disabled_indicator='is_connected'
disabled_indicator='cable'
)
)
@ -276,12 +276,12 @@ class CircuitTerminationForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm
super(CircuitTerminationForm, self).__init__(*args, **kwargs)
# Mark connected interfaces as disabled
# Mark occupied interfaces as disabled
self.fields['interface'].choices = []
for iface in self.fields['interface'].queryset:
self.fields['interface'].choices.append(
(iface.id, {
'label': iface.name,
'disabled': iface.is_connected and iface.pk != self.initial.get('interface'),
'disabled': bool(iface.cable) and iface.pk != self.initial.get('interface'),
})
)

View File

@ -559,14 +559,10 @@ class ConsoleServerPortSerializer(TaggitSerializer, ValidatedModelSerializer):
class NestedConsoleServerPortSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail')
device = NestedDeviceSerializer(read_only=True)
is_connected = serializers.SerializerMethodField(read_only=True)
class Meta:
model = ConsoleServerPort
fields = ['id', 'url', 'device', 'name', 'is_connected']
def get_is_connected(self, obj):
return hasattr(obj, 'connected_endpoint') and obj.connected_endpoint is not None
fields = ['id', 'url', 'device', 'name', 'cable']
#
@ -588,14 +584,10 @@ class ConsolePortSerializer(TaggitSerializer, ValidatedModelSerializer):
class NestedConsolePortSerializer(TaggitSerializer, ValidatedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail')
device = NestedDeviceSerializer(read_only=True)
is_connected = serializers.SerializerMethodField(read_only=True)
class Meta:
model = ConsolePort
fields = ['id', 'url', 'device', 'name', 'is_connected']
def get_is_connected(self, obj):
return obj.connected_endpoint is not None
fields = ['id', 'url', 'device', 'name', 'cable']
#
@ -616,14 +608,10 @@ class PowerOutletSerializer(TaggitSerializer, ValidatedModelSerializer):
class NestedPowerOutletSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail')
device = NestedDeviceSerializer(read_only=True)
is_connected = serializers.SerializerMethodField(read_only=True)
class Meta:
model = PowerOutlet
fields = ['id', 'url', 'device', 'name', 'is_connected']
def get_is_connected(self, obj):
return hasattr(obj, 'connected_endpoint') and obj.connected_endpoint is not None
fields = ['id', 'url', 'device', 'name', 'cable']
#
@ -645,43 +633,23 @@ class PowerPortSerializer(TaggitSerializer, ValidatedModelSerializer):
class NestedPowerPortSerializer(TaggitSerializer, ValidatedModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail')
device = NestedDeviceSerializer(read_only=True)
is_connected = serializers.SerializerMethodField(read_only=True)
class Meta:
model = PowerPort
fields = ['id', 'url', 'device', 'name', 'is_connected']
def get_is_connected(self, obj):
return obj.connected_endpoint is not None
fields = ['id', 'url', 'device', 'name', 'cable']
#
# Interfaces
#
class IsConnectedMixin(object):
"""
Provide a method for setting is_connected on Interface serializers.
"""
def get_is_connected(self, obj):
"""
Return True if the interface has a connected interface or circuit.
"""
if obj.connected_endpoint:
return True
if hasattr(obj, 'circuit_termination') and obj.circuit_termination is not None:
return True
return False
class NestedInterfaceSerializer(IsConnectedMixin, WritableNestedSerializer):
class NestedInterfaceSerializer(WritableNestedSerializer):
device = NestedDeviceSerializer(read_only=True)
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
is_connected = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Interface
fields = ['id', 'url', 'device', 'name', 'is_connected']
fields = ['id', 'url', 'device', 'name', 'cable']
class InterfaceNestedCircuitSerializer(serializers.ModelSerializer):
@ -711,12 +679,11 @@ class InterfaceVLANSerializer(WritableNestedSerializer):
fields = ['id', 'url', 'vid', 'name', 'display_name']
class InterfaceSerializer(TaggitSerializer, IsConnectedMixin, ValidatedModelSerializer):
class InterfaceSerializer(TaggitSerializer, ValidatedModelSerializer):
device = NestedDeviceSerializer()
form_factor = ChoiceField(choices=IFACE_FF_CHOICES, required=False)
lag = NestedInterfaceSerializer(required=False, allow_null=True)
connected_endpoint = NestedInterfaceSerializer(read_only=True)
is_connected = serializers.SerializerMethodField(read_only=True)
circuit_termination = InterfaceCircuitTerminationSerializer(read_only=True)
mode = ChoiceField(choices=IFACE_MODE_CHOICES, required=False, allow_null=True)
untagged_vlan = InterfaceVLANSerializer(required=False, allow_null=True)
@ -733,8 +700,7 @@ class InterfaceSerializer(TaggitSerializer, IsConnectedMixin, ValidatedModelSeri
model = Interface
fields = [
'id', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'description',
'is_connected', 'connected_endpoint', 'circuit_termination', 'cable', 'mode', 'untagged_vlan',
'tagged_vlans', 'tags',
'connected_endpoint', 'circuit_termination', 'cable', 'mode', 'untagged_vlan', 'tagged_vlans', 'tags',
]
def validate(self, data):
@ -778,7 +744,7 @@ class NestedRearPortSerializer(WritableNestedSerializer):
class Meta:
model = RearPort
fields = ['id', 'url', 'device', 'name']
fields = ['id', 'url', 'device', 'name', 'cable']
#
@ -811,7 +777,7 @@ class NestedFrontPortSerializer(WritableNestedSerializer):
class Meta:
model = FrontPort
fields = ['id', 'url', 'device', 'name']
fields = ['id', 'url', 'device', 'name', 'cable']
#

View File

@ -1402,7 +1402,7 @@ class ConsolePortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelF
label='Port',
widget=APISelect(
api_url='/api/dcim/console-server-ports/?device_id={{console_server}}',
disabled_indicator='is_connected',
disabled_indicator='cable',
)
)
@ -1493,7 +1493,7 @@ class ConsoleServerPortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.
label='Port',
widget=APISelect(
api_url='/api/dcim/console-ports/?device_id={{device}}',
disabled_indicator='is_connected'
disabled_indicator='cable'
)
)
connection_status = forms.BooleanField(
@ -1671,7 +1671,7 @@ class PowerPortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelFor
label='Outlet',
widget=APISelect(
api_url='/api/dcim/power-outlets/?device_id={{pdu}}',
disabled_indicator='is_connected'
disabled_indicator='cable'
)
)
@ -1762,7 +1762,7 @@ class PowerOutletConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.Form):
label='Port',
widget=APISelect(
api_url='/api/dcim/power-ports/?device_id={{device}}',
disabled_indicator='is_connected'
disabled_indicator='cable'
)
)
connection_status = forms.BooleanField(
@ -2171,7 +2171,7 @@ class CableCreateForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelForm):
label='Name',
widget=APISelect(
api_url='/api/dcim/{{termination_b_type}}s/?device_id={{termination_b_device}}',
disabled_indicator='is_connected'
disabled_indicator='cable'
)
)

View File

@ -1888,7 +1888,9 @@ class Interface(CableTermination, ComponentModel):
})
# Virtual interfaces cannot be connected
if self.form_factor in NONCONNECTABLE_IFACE_TYPES and self.is_connected:
if self.form_factor in NONCONNECTABLE_IFACE_TYPES and (
self.cable or getattr(self, 'circuit_termination', False)
):
raise ValidationError({
'form_factor': "Virtual and wireless interfaces cannot be connected to another interface or circuit. "
"Disconnect the interface or choose a suitable form factor."
@ -1977,14 +1979,6 @@ class Interface(CableTermination, ComponentModel):
def is_lag(self):
return self.form_factor == IFACE_FF_LAG
@property
def is_connected(self):
try:
return bool(self.circuit_termination)
except ObjectDoesNotExist:
pass
return bool(self.connected_endpoint)
#
# Pass-through ports

View File

@ -1953,7 +1953,7 @@ class ConsolePortTest(APITestCase):
self.assertEqual(
sorted(response.data['results'][0]),
['device', 'id', 'is_connected', 'name', 'url']
['cable', 'device', 'id', 'name', 'url']
)
def test_create_consoleport(self):
@ -2068,7 +2068,7 @@ class ConsoleServerPortTest(APITestCase):
self.assertEqual(
sorted(response.data['results'][0]),
['device', 'id', 'is_connected', 'name', 'url']
['cable', 'device', 'id', 'name', 'url']
)
def test_create_consoleserverport(self):
@ -2179,7 +2179,7 @@ class PowerPortTest(APITestCase):
self.assertEqual(
sorted(response.data['results'][0]),
['device', 'id', 'is_connected', 'name', 'url']
['cable', 'device', 'id', 'name', 'url']
)
def test_create_powerport(self):
@ -2294,7 +2294,7 @@ class PowerOutletTest(APITestCase):
self.assertEqual(
sorted(response.data['results'][0]),
['device', 'id', 'is_connected', 'name', 'url']
['cable', 'device', 'id', 'name', 'url']
)
def test_create_poweroutlet(self):
@ -2431,7 +2431,7 @@ class InterfaceTest(APITestCase):
self.assertEqual(
sorted(response.data['results'][0]),
['device', 'id', 'is_connected', 'name', 'url']
['cable', 'device', 'id', 'name', 'url']
)
def test_create_interface(self):