Skip to content
Snippets Groups Projects
Commit 16268c46 authored by Benjamin Bertrand's avatar Benjamin Bertrand
Browse files

Prevent supernet overlapping

JIRA INFRA-1627
parent 5c99e075
No related branches found
No related tags found
No related merge requests found
......@@ -1615,6 +1615,18 @@ class NetworkScope(CreatedMixin, db.Model):
def __str__(self):
return str(self.name)
@validates("supernet")
def validate_supernet(self, key, supernet):
"""Ensure the supernet doesn't overlap existing supernets"""
supernet_address = ipaddress.ip_network(supernet)
existing_scopes = NetworkScope.query.all()
for existing_scope in existing_scopes:
if supernet_address.overlaps(existing_scope.supernet_ip):
raise ValidationError(
f"{supernet} overlaps {existing_scope} ({existing_scope.supernet_ip})"
)
return supernet
@validates("networks")
def validate_networks(self, key, network):
"""Ensure the network is included in the supernet and doesn't overlap
......
......@@ -588,14 +588,20 @@ def view_scope(name):
def create_scope():
form = NetworkScopeForm()
if form.validate_on_submit():
scope = models.NetworkScope(
name=form.name.data,
description=form.description.data or None,
first_vlan=form.first_vlan.data,
last_vlan=form.last_vlan.data,
supernet=form.supernet.data,
domain=models.Domain.query.get(form.domain_id.data),
)
try:
scope = models.NetworkScope(
name=form.name.data,
description=form.description.data or None,
first_vlan=form.first_vlan.data,
last_vlan=form.last_vlan.data,
supernet=form.supernet.data,
domain=models.Domain.query.get(form.domain_id.data),
)
except ValidationError as e:
# Check for error raised by model validation (not implemented in form vaildation)
current_app.logger.warning(f"{e}")
flash(f"{e}", "error")
return render_template("network/create_scope.html", form=form)
current_app.logger.debug(f"Trying to create: {scope!r}")
db.session.add(scope)
try:
......
......@@ -919,3 +919,15 @@ def test_scope_available_subnets(network_scope_factory, network_factory):
network_factory(vlan_id=3802, address="172.30.238.64/26", scope=scope)
expected3 = [subnet for subnet in expected2 if subnet != "172.30.238.0/24"]
assert scope.available_subnets(24) == expected3
@pytest.mark.parametrize("address", ("172.30.0.0/22", "172.30.244.0/22"))
def test_network_scope_overlapping(address, network_scope_factory):
scope = network_scope_factory(
first_vlan=3800, last_vlan=4000, supernet="172.30.0.0/16"
)
with pytest.raises(ValidationError) as excinfo:
network_scope_factory(first_vlan=2000, last_vlan=2200, supernet=address)
assert f"{address} overlaps {scope.name} ({scope.supernet_ip})" in str(
excinfo.value
)
......@@ -788,3 +788,19 @@ def test_create_network_overlapping(
response = logged_admin_client.post("/network/networks/create", data=form)
assert response.status_code == 200
assert b"172.30.1.0/24 overlaps network1 (172.30.0.0/23)" in response.data
def test_create_network_scope_overlapping(network_scope_factory, logged_admin_client):
scope1 = network_scope_factory(
name="scope1", first_vlan=3800, last_vlan=4000, supernet="172.30.0.0/16"
)
form = {
"name": "scope2",
"first_vlan": 200,
"last_vlan": 500,
"supernet": "172.30.200.0/22",
"domain_id": scope1.domain_id,
}
response = logged_admin_client.post("/network/scopes/create", data=form)
assert response.status_code == 200
assert b"172.30.200.0/22 overlaps scope1 (172.30.0.0/16)" in response.data
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment