mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-15 11:42:52 -06:00
13130 dont allow reassigning ipaddress assigned object if primary ip (#13893)
* 13130 dont allow reassigning ipaddress assigned object if primary ip * 13130 add tests fix parent check * Misc cleanup --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
parent
f65744faee
commit
db40119faa
@ -782,6 +782,13 @@ class IPAddress(PrimaryModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return str(self.address)
|
return str(self.address)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
# Denote the original assigned object (if any) for validation in clean()
|
||||||
|
self._original_assigned_object_id = self.__dict__.get('assigned_object_id')
|
||||||
|
self._original_assigned_object_type_id = self.__dict__.get('assigned_object_type_id')
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('ipam:ipaddress', args=[self.pk])
|
return reverse('ipam:ipaddress', args=[self.pk])
|
||||||
|
|
||||||
@ -843,6 +850,26 @@ class IPAddress(PrimaryModel):
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if self._original_assigned_object_id and self._original_assigned_object_type_id:
|
||||||
|
parent = getattr(self.assigned_object, 'parent_object', None)
|
||||||
|
ct = ContentType.objects.get_for_id(self._original_assigned_object_type_id)
|
||||||
|
original_assigned_object = ct.get_object_for_this_type(pk=self._original_assigned_object_id)
|
||||||
|
original_parent = getattr(original_assigned_object, 'parent_object', None)
|
||||||
|
|
||||||
|
# can't use is_primary_ip as self.assigned_object might be changed
|
||||||
|
is_primary = False
|
||||||
|
if self.family == 4 and hasattr(original_parent, 'primary_ip4') and original_parent.primary_ip4_id == self.pk:
|
||||||
|
is_primary = True
|
||||||
|
if self.family == 6 and hasattr(original_parent, 'primary_ip6') and original_parent.primary_ip6_id == self.pk:
|
||||||
|
is_primary = True
|
||||||
|
|
||||||
|
if is_primary and (parent != original_parent):
|
||||||
|
raise ValidationError({
|
||||||
|
'assigned_object': _(
|
||||||
|
"Cannot reassign IP address while it is designated as the primary IP for the parent object"
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
# Validate IP status selection
|
# Validate IP status selection
|
||||||
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:
|
if self.status == IPAddressStatusChoices.STATUS_SLAAC and self.family != 6:
|
||||||
raise ValidationError({
|
raise ValidationError({
|
||||||
|
@ -659,6 +659,62 @@ class IPAddressTest(APIViewTestCases.APIViewTestCase):
|
|||||||
)
|
)
|
||||||
IPAddress.objects.bulk_create(ip_addresses)
|
IPAddress.objects.bulk_create(ip_addresses)
|
||||||
|
|
||||||
|
def test_assign_object(self):
|
||||||
|
"""
|
||||||
|
Test the creation of available IP addresses within a parent IP range.
|
||||||
|
"""
|
||||||
|
site = Site.objects.create(name='Site 1')
|
||||||
|
manufacturer = Manufacturer.objects.create(name='Manufacturer 1')
|
||||||
|
device_type = DeviceType.objects.create(model='Device Type 1', manufacturer=manufacturer)
|
||||||
|
role = DeviceRole.objects.create(name='Switch')
|
||||||
|
device1 = Device.objects.create(
|
||||||
|
name='Device 1',
|
||||||
|
site=site,
|
||||||
|
device_type=device_type,
|
||||||
|
role=role,
|
||||||
|
status='active'
|
||||||
|
)
|
||||||
|
interface1 = Interface.objects.create(name='Interface 1', device=device1, type='1000baset')
|
||||||
|
interface2 = Interface.objects.create(name='Interface 2', device=device1, type='1000baset')
|
||||||
|
device2 = Device.objects.create(
|
||||||
|
name='Device 2',
|
||||||
|
site=site,
|
||||||
|
device_type=device_type,
|
||||||
|
role=role,
|
||||||
|
status='active'
|
||||||
|
)
|
||||||
|
interface3 = Interface.objects.create(name='Interface 3', device=device2, type='1000baset')
|
||||||
|
|
||||||
|
ip_addresses = (
|
||||||
|
IPAddress(address=IPNetwork('192.168.0.4/24'), assigned_object=interface1),
|
||||||
|
IPAddress(address=IPNetwork('192.168.1.4/24')),
|
||||||
|
)
|
||||||
|
IPAddress.objects.bulk_create(ip_addresses)
|
||||||
|
|
||||||
|
ip1 = ip_addresses[0]
|
||||||
|
ip1.assigned_object = interface1
|
||||||
|
device1.primary_ip4 = ip_addresses[0]
|
||||||
|
device1.save()
|
||||||
|
|
||||||
|
ip2 = ip_addresses[1]
|
||||||
|
|
||||||
|
url = reverse('ipam-api:ipaddress-detail', kwargs={'pk': ip1.pk})
|
||||||
|
self.add_permissions('ipam.change_ipaddress')
|
||||||
|
|
||||||
|
# assign to same parent
|
||||||
|
data = {
|
||||||
|
'assigned_object_id': interface2.pk
|
||||||
|
}
|
||||||
|
response = self.client.patch(url, data, format='json', **self.header)
|
||||||
|
self.assertHttpStatus(response, status.HTTP_200_OK)
|
||||||
|
|
||||||
|
# assign to same different parent - should error
|
||||||
|
data = {
|
||||||
|
'assigned_object_id': interface3.pk
|
||||||
|
}
|
||||||
|
response = self.client.patch(url, data, format='json', **self.header)
|
||||||
|
self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
class FHRPGroupTest(APIViewTestCases.APIViewTestCase):
|
class FHRPGroupTest(APIViewTestCases.APIViewTestCase):
|
||||||
model = FHRPGroup
|
model = FHRPGroup
|
||||||
|
Loading…
Reference in New Issue
Block a user