When you try to create multiple IP prefixes (in a hierarchy), and you create multiple IP prefix objects concurrently, it could lead to a scenario where the hierarchy of the prefixes is not correctly calculated.
A situation in which this can occur is when you have a generator/script that leverages the batches in the SDK.
In the example we want to create the following prefix hierarchy
10.0.0.0/8
10.0.0.0/16
10.0.0.0/24
10.0.1.0/24
10.0.2.0/24
10.0.3.0/24
10.1.0.0/16
10.1.0.0/24
10.1.1.0/24
10.1.2.0/24
10.1.3.0/24
10.2.0.0/16
10.2.0.0/24
10.2.1.0/24
10.2.2.0/24
10.2.3.0/24
10.3.0.0/16
10.3.0.0/24
10.3.1.0/24
10.3.2.0/24
10.3.3.0/24
....
10.255.0.0/16
10.255.0.0/24
10.255.1.0/24
10.255.2.0/24
10.255.3.0/24
We could do that with the following script:
import ipaddress
import logging
from infrahub_sdk import InfrahubClient
async def run(client: InfrahubClient, log: logging.Logger, branch: str, num_devices: int=30) -> None:
prefixes_batch = await client.create_batch()
network_8 = ipaddress.IPv4Network("10.0.0.0/8")
networks_16 = list(network_8.subnets(new_prefix=16))
networks_24 = []
for network in networks_16:
tmp = list(network.subnets(new_prefix=24))[:4]
networks_24.extend(tmp)
networks = [network_8] + networks_16 + networks_24
for network in networks:
prefix = await client.create("IpamIPPrefix", prefix=f"{network}")
prefixes_batch.add(task=prefix.save, node=prefix, allow_upsert=True)
log.info(f" Added prefix {network}")
async for node, result in prefixes_batch.execute():
print(f"prefix {node.prefix.value} was created in Infrahub succesfully")
The result will be that 10.0.0.0/16, 10.1.0.0/16 and 10.2.0.0/16 (and its children) will not have 10.0.0.0/8 as the parent prefix.
Starting with 10.3.0.0/16 (and the other /16's) will all correctly have 10.0.0.0/8 as the parent.
This issue doesn't happen when you don't leverage the batch functionality
Expected Behavior
The prefixes should have the correct parent
Steps to Reproduce
start instance of Infrahub and load the demo schema
run the following script
import ipaddress
import logging
from infrahub_sdk import InfrahubClient
networks_24 = []
for network in networks_16:
tmp = list(network.subnets(new_prefix=24))[:4]
networks_24.extend(tmp)
networks = [network_8] + networks_16 + networks_24
for network in networks:
prefix = await client.create("IpamIPPrefix", prefix=f"{network}")
prefixes_batch.add(task=prefix.save, node=prefix, allow_upsert=True)
log.info(f" Added prefix {network}")
async for node, result in prefixes_batch.execute():
print(f"prefix {node.prefix.value} was created in Infrahub succesfully")
- Navigate to the IP Prefixes in the frontend
### Additional Information
_No response_
Component
API Server / GraphQL
Infrahub version
0.16.2
Current Behavior
When you try to create multiple IP prefixes (in a hierarchy), and you create multiple IP prefix objects concurrently, it could lead to a scenario where the hierarchy of the prefixes is not correctly calculated.
A situation in which this can occur is when you have a generator/script that leverages the batches in the SDK.
In the example we want to create the following prefix hierarchy 10.0.0.0/8 10.0.0.0/16 10.0.0.0/24 10.0.1.0/24 10.0.2.0/24 10.0.3.0/24 10.1.0.0/16 10.1.0.0/24 10.1.1.0/24 10.1.2.0/24 10.1.3.0/24 10.2.0.0/16 10.2.0.0/24 10.2.1.0/24 10.2.2.0/24 10.2.3.0/24 10.3.0.0/16 10.3.0.0/24 10.3.1.0/24 10.3.2.0/24 10.3.3.0/24 .... 10.255.0.0/16 10.255.0.0/24 10.255.1.0/24 10.255.2.0/24 10.255.3.0/24
We could do that with the following script:
The result will be that 10.0.0.0/16, 10.1.0.0/16 and 10.2.0.0/16 (and its children) will not have 10.0.0.0/8 as the parent prefix. Starting with 10.3.0.0/16 (and the other /16's) will all correctly have 10.0.0.0/8 as the parent.
This issue doesn't happen when you don't leverage the batch functionality
Expected Behavior
The prefixes should have the correct parent
Steps to Reproduce
async def run(client: InfrahubClient, log: logging.Logger, branch: str, num_devices: int=30) -> None: prefixes_batch = await client.create_batch() network_8 = ipaddress.IPv4Network("10.0.0.0/8") networks_16 = list(network_8.subnets(new_prefix=16))