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:
@ -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'),
|
||||
})
|
||||
)
|
||||
|
@ -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']
|
||||
|
||||
|
||||
#
|
||||
|
@ -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'
|
||||
)
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
Reference in New Issue
Block a user