Allocate resources from pools
Object templates support automatic resource allocation. This guide extends the device and interface example from Use object templates to show how to wire a CoreIPAddressPool to the interface template so that IP addresses are allocated automatically on object creation.
Prerequisites​
- A running Infrahub instance with the schema from Use object templates already loaded
Schema extension used in this guide
Add the two IPAM nodes and an ip_address relationship to InfraInterface. Adapt the type names to match your own schema.
---
# yaml-language-server: $schema=https://schema.infrahub.app/infrahub/schema/latest.json
version: "1.0"
nodes:
- name: IPAddress
namespace: Ipam
label: "IP Address"
display_label: "{{ address__value }}"
inherit_from:
- BuiltinIPAddress
- name: IPPrefix
namespace: Ipam
label: "IP Prefix"
display_label: "{{ prefix__value }}"
inherit_from:
- BuiltinIPPrefix
- name: Interface
namespace: Infra
label: "Interface"
include_in_menu: true
icon: "mdi:ethernet"
display_label: "{{ name__value }}"
order_by:
- name__value
uniqueness_constraints:
- ["device", "name__value"]
human_friendly_id: ["device__name__value", "name__value"]
attributes:
- name: name
kind: Text
- name: description
kind: Text
optional: true
- name: enable
kind: Boolean
optional: false
default_value: false
relationships:
- name: device
peer: InfraDevice
optional: false
cardinality: one
kind: Parent
- name: ip_address
peer: IpamIPAddress
optional: true
cardinality: one
kind: Attribute
Once IpamIPAddress is in the schema, Infrahub automatically generates an ip_address_from_resource_pool field on TemplateInfraInterface — this is what connects the template to the pool.
Load the schema before continuing:
infrahubctl schema load /path/to/schema-extension.yml
Create the resource pool​
First create a prefix to draw addresses from, then create the pool backed by that prefix.
- Via the Web Interface
- Via the GraphQL Interface
- Via an Object File
- Via the Python SDK
Create the IP prefix:
- Navigate to
IPAM>Prefixes - Click
+ Add IP Prefix - Fill in:
- Prefix:
192.168.0.0/16 - Member Type:
address - Is Pool:
true
- Prefix:
- Save
Create the IP address pool:
- Navigate to
Resource Manager>IP Address Pool - Click
+ Add IP Address Pool - Fill in:
- Name:
Interface IP Pool - Default Address Type:
IpamIPAddress - IP Namespace:
default - Resources: select
192.168.0.0/16
- Name:
- Save
mutation CreatePrefix {
IpamIPPrefixCreate(
data: {prefix: {value: "192.168.0.0/16"}, member_type: {value: "address"}, is_pool: {value: true}}
) {
ok
object { id }
}
}
Then use the returned prefix ID to create the pool:
mutation CreatePool($prefixId: String!) {
CoreIPAddressPoolCreate(
data: {
name: {value: "Interface IP Pool"}
default_address_type: {value: "IpamIPAddress"}
ip_namespace: {hfid: ["default"]}
resources: [{id: $prefixId}]
}
) {
ok
}
}
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: CoreIPAddressPool
data:
- name: "Interface IP Pool"
default_address_type: IpamIPAddress
ip_namespace: default
resources:
kind: IpamIPPrefix
data:
- prefix: 192.168.0.0/16
member_type: address
is_pool: true
Load with: infrahubctl object load pools.yml
async def run(client: InfrahubClient, log: logging.Logger, branch: str) -> None:
prefix = await client.create(
kind="IpamIPPrefix",
data={"prefix": "192.168.0.0/16", "member_type": "address", "is_pool": True},
)
await prefix.save(allow_upsert=True)
pool = await client.create(
kind="CoreIPAddressPool",
data={
"name": "Interface IP Pool",
"default_address_type": "IpamIPAddress",
"ip_namespace": {"hfid": ["default"]},
"resources": [{"id": prefix.id}],
},
)
await pool.save(allow_upsert=True)
Assign the pool to the interface template​
With the pool created, update the interface template from the previous section to allocate an IP address from it whenever a new interface is created.
- Via the Web Interface
- Via the GraphQL Interface
- Via an Object File
- Via the Python SDK
- Navigate to
Object Management>Templates - Open
Template-SwitchModel123-Ethernet1(or any interface template) - On the
IP Addressfield, click the pool selector button and chooseInterface IP Pool - The field will show an
Allocated by poolbadge - Save
mutation {
TemplateInfraInterfaceUpdate(
data: {
hfid: ["Template-SwitchModel123", "Template-SwitchModel123-Ethernet1"]
ip_address_from_resource_pool: {hfid: ["Interface IP Pool"]}
}
) {
ok
}
}
---
apiVersion: infrahub.app/v1
kind: Object
spec:
kind: TemplateInfraInterface
data:
- template_name: "Template-SwitchModel123-Ethernet1"
device: "Template-SwitchModel123"
ip_address_from_resource_pool: "Interface IP Pool"
async def run(client: InfrahubClient, log: logging.Logger, branch: str) -> None:
pool = await client.get(kind="CoreIPAddressPool", hfid=["Interface IP Pool"])
iface_template = await client.get(
kind="TemplateInfraInterface",
hfid=["Template-SwitchModel123", "Template-SwitchModel123-Ethernet1"],
)
iface_template.ip_address_from_resource_pool = {"id": pool.id}
await iface_template.save(allow_upsert=True)
Create objects — IP addresses are allocated automatically​
Creating a device from the template works exactly as described in the Create object instances section. No additional steps are required — when the device is saved, Infrahub allocates an available IP address from Interface IP Pool and assigns it to each interface's ip_address field.
Resource allocation happens at object creation time, not at template creation time. Each new device gets its own unique address drawn from the pool.
For more information about resource pools, see:
- Managing resource pools - Guide for creating and using pools
- Resource Manager concepts - Deep dive into allocation behaviour