Skip to content

Commit dcdd702

Browse files
committed
Split functions again
1 parent 6ba4032 commit dcdd702

File tree

1 file changed

+79
-28
lines changed

1 file changed

+79
-28
lines changed

serveradmin/serverdb/models.py

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -102,19 +102,22 @@ def is_unique_ip(
102102
ip_interface: Union[IPv4Interface, IPv6Interface],
103103
server: "Server",
104104
addr_types: list[str],
105-
is_net: bool,
106105
attribute_id: Optional[int] = None,
107106
) -> None:
108-
"""Validate if IPv4/IPv6 interface is unique
107+
"""Validate if given IP address is unique
109108
110109
Raises a ValidationError if intern_ip or any other attribute of type inet
111110
with this ip_address already exists.
112111
113-
:param ip_interface:
114-
:param server:
115-
:param addr_types:
116-
:param is_net:
117-
:param attribute_id:
112+
:param ip_interface: The IP address to validate
113+
:param server: The current Server object to which the new IP address is
114+
to be assigned
115+
:param addr_types: Verify only against Servers of given IP_ADDR_TYPES.
116+
Allows for conflicting IP addresses, as long as they are on
117+
Servers with different IP_ADDR_TYPES.
118+
:param attribute_id: Verify only against this attribute. Allows for having
119+
conflicting IP addresses on different attributes, as long
120+
as they are on different Server objects.
118121
:return:
119122
"""
120123

@@ -127,40 +130,88 @@ def is_unique_ip(
127130
# the same IP address as long as it is in different attributes.
128131

129132
duplicates = []
130-
object_id = server.server_id
131133

132-
if is_net:
133-
servertype_inet_attr_q = Q(server__servertype=server.servertype_id)
134-
servertype_intern_ip_q = Q(servertype=server.servertype_id)
135-
inet_attr_q = Q(value__net_overlaps=ip_interface)
136-
intern_ip_q = Q(intern_ip__net_overlaps=ip_interface)
134+
# TODO: Make attribute_id mandatory when intern_ip is gone.
135+
if attribute_id:
136+
object_attribute_q = Q(server_id=server.server_id) | ~Q(
137+
attribute_id=attribute_id
138+
)
137139
else:
138-
servertype_inet_attr_q = Q()
139-
servertype_intern_ip_q = Q()
140-
inet_attr_q = Q(value=ip_interface)
141-
intern_ip_q = Q(intern_ip=ip_interface)
140+
object_attribute_q = Q(server_id=server.server_id)
141+
142+
# TODO: Remove intern_ip.
143+
for d in Server.objects.filter(
144+
Q(
145+
Q(intern_ip=ip_interface) # IP address
146+
& Q(servertype__ip_addr_type__in=addr_types) # IP address type
147+
& ~Q(server_id=server.server_id) # Self-server
148+
)
149+
):
150+
duplicates.append(f"{d.hostname} (intern_ip)")
151+
152+
for d in ServerInetAttribute.objects.filter(
153+
Q(
154+
Q(value=ip_interface) # IP address
155+
& Q(server__servertype__ip_addr_type__in=addr_types) # IP address type
156+
& ~object_attribute_q # Self-server
157+
)
158+
):
159+
duplicates.append(f"{d.server.hostname} ({d.attribute})")
160+
161+
if duplicates:
162+
raise ValidationError(
163+
f"Can't set IP address {ip_interface} on {server.hostname}, conflicts with: {', '.join(duplicates)}"
164+
)
165+
166+
167+
def network_overlaps(
168+
ip_interface: Union[IPv4Interface, IPv6Interface],
169+
server: "Server",
170+
addr_types: list[str],
171+
attribute_id: Optional[int] = None,
172+
) -> None:
173+
"""Validate if given IP prefix is unique
174+
175+
Raises a ValidationError if the IP prefix overlaps with any other existing
176+
objects network of the given servertype.
177+
178+
:param ip_interface: The IP address to validate
179+
:param server: The current Server object to which the new IP prefix is
180+
to be assigned
181+
:param addr_types: Verify only against Servers of given IP_ADDR_TYPES.
182+
Allows for overlapping IP prefixes, as long as they are on
183+
Servers with different IP_ADDR_TYPES.
184+
:param attribute_id: Verify only against this attribute. Allows for having
185+
overlapping IP prefixes on different attributes, as long
186+
as they are on different Server objects.
187+
:return:
188+
"""
189+
190+
duplicates = []
142191

143192
# TODO: Make attribute_id mandatory when intern_ip is gone.
144193
if attribute_id:
145-
object_attribute_q = Q(server_id=object_id) | ~Q(attribute_id=attribute_id)
194+
object_attribute_q = Q(server_id=server.server_id) | ~Q(
195+
attribute_id=attribute_id
196+
)
146197
else:
147-
object_attribute_q = Q(server_id=object_id)
198+
object_attribute_q = Q(server_id=server.server_id)
148199

149200
# TODO: Remove intern_ip.
150201
for d in Server.objects.filter(
151202
Q(
152-
servertype_intern_ip_q # Servertype
153-
& intern_ip_q # IP address
203+
Q(servertype=server.servertype_id) # Servertype
204+
& Q(intern_ip__net_overlaps=ip_interface) # IP address
154205
& Q(servertype__ip_addr_type__in=addr_types) # IP address type
155-
& ~Q(server_id=object_id) # Self-server
206+
& ~Q(server_id=server.server_id) # Self-server
156207
)
157208
):
158209
duplicates.append(f"{d.hostname} (intern_ip)")
159210

160211
for d in ServerInetAttribute.objects.filter(
161212
Q(
162-
servertype_inet_attr_q # Servertype
163-
& inet_attr_q # IP address
213+
Q(server__servertype=server.servertype_id) # Servertype
214+
& Q(value__net_overlaps=ip_interface) # IP address
164215
& Q(server__servertype__ip_addr_type__in=addr_types) # IP address type
165216
& ~object_attribute_q # Self-server
166217
)
@@ -495,10 +546,10 @@ def clean(self):
495546

496547
if ip_addr_type == "host":
497548
is_ip_address(self.intern_ip)
498-
is_unique_ip(self.intern_ip, self, ["host"], False)
549+
is_unique_ip(self.intern_ip, self, ["host"])
499550
elif ip_addr_type == "network":
500551
is_network(self.intern_ip)
501-
is_unique_ip(self.intern_ip, self, ["network"], True)
552+
network_overlaps(self.intern_ip, self, ["network"])
502553
elif ip_addr_type == "loadbalancer":
503554
is_ip_address(self.intern_ip)
504555

@@ -726,10 +777,10 @@ def clean(self):
726777
)
727778
elif ip_addr_type == "host":
728779
is_ip_address(self.value)
729-
is_unique_ip(self.value, self.server, ["host"], False, self.attribute_id)
780+
is_unique_ip(self.value, self.server, ["host"], self.attribute_id)
730781
elif ip_addr_type == "network":
731782
is_network(self.value)
732-
is_unique_ip(self.value, self.server, ["network"], True, self.attribute_id)
783+
network_overlaps(self.value, self.server, ["network"], self.attribute_id)
733784
elif ip_addr_type == "loadbalancer":
734785
is_ip_address(self.value)
735786

0 commit comments

Comments
 (0)