Compare commits

...

2 Commits

Author SHA1 Message Date
Gibheer 5e06ba6b61 add function to get subnets to schema
This also adds a view to get a list of all containers and their free
space in between.
This is needed for ippool_list to get a nice overview over everything.
2021-05-21 17:42:10 +02:00
Gibheer efecc60e9c add view to get container hierarchy 2021-05-18 15:04:57 +02:00
1 changed files with 67 additions and 8 deletions

View File

@ -20,19 +20,31 @@ create table if not exists pools(
primary key(layer3domain_id, id)
);
create table if not exists containers(
layer3domain_id integer not null references layer3domains(id),
network cidr not null,
pool_id integer,
create table containers(
layer3domain_id integer not null references layer3domains(id),
subnet cidr not null,
pool_id integer,
attributes jsonb not null default '{}'::jsonb,
created_at timestamptz not null default now(),
created_by varchar(128) not null,
modified_at timestamptz not null default now(),
modified_by varchar(128) not null,
attributes jsonb not null default '{}'::jsonb,
unique(layer3domain_id, network),
foreign key (layer3domain_id, pool_id) references pools(layer3domain_id, id)
unique(layer3domain_id, subnet),
foreign key (layer3domain_id, pool_id) references pools(layer3domain_id, id)
);
create index if not exists container_reference_key on containers(layer3domain_id, pool_id, network);
create or replace view containers_tree as
select
c.layer3domain_id,
c.subnet,
array_agg(p.subnet order by p.subnet) filter (where p.subnet is not null) as parents
from containers c
left join containers p
on c.subnet << p.subnet
and c.layer3domain_id = p.layer3domain_id
group by c.layer3domain_id, c.subnet
order by c.layer3domain_id, c.subnet;
comment on view containers_tree is 'This returns a tree of all containers so that sub trees can be shown.';
create table if not exists ips(
layer3domain_id integer not null,
@ -184,3 +196,50 @@ create trigger trg_zones before insert or update or delete on zones for each row
create trigger trg_zoneviews before insert or update or delete on zoneviews for each row execute function record();
create trigger trg_zoneviews_outputgroups before insert or update or delete on zoneviews_outputgroups for each row execute function record();
create or replace function subnets_between(net_start inet, net_end inet) returns setof cidr as $$
declare
common cidr;
mask int;
begin
net_start := host(net_start)::inet;
net_end := host(net_end)::inet;
-- check if net_start and net_end are in the same subnet
common := inet_merge(host(net_start)::inet, host(net_end)::inet);
mask := masklen(common);
if set_masklen(net_start, mask) = common and broadcast(common) = set_masklen(net_end, mask) then
return next common;
return;
end if;
-- subnet is too big, so make it smaller
return query select * from subnets_between(net_start, broadcast(set_masklen(net_start, mask + 1)));
return query select * from subnets_between(network(set_masklen(net_end, mask + 1)), net_end);
end;
$$ language plpgsql;
comment on function subnets_between(inet, inet) is 'get a list of subnets between two IPs.';
create or replace view containers_free_list as
with subnets as (
select
c.layer3domain_id,
c.subnet,
ct.subnet child,
lag(ct.subnet) over (partition by c.subnet order by ct.subnet) has_before,
lead(ct.subnet) over (partition by c.subnet order by ct.subnet) has_after,
parents
from containers c
join containers_tree ct on c.layer3domain_id = ct.layer3domain_id and c.subnet = ct.parents[array_length(ct.parents, 1)]
where host(c.subnet) != host(ct.subnet) and host(broadcast(c.subnet)) != host(broadcast(ct.subnet))
)
select * from (
select layer3domain_id, parents, 'available' state, ls as subnet
from subnets, lateral subnets_between(subnet, child - 1) ls
where has_before is null
union all
select layer3domain_id, parents, 'available', ls
from subnets, lateral subnets_between(broadcast(child) + 1, broadcast(subnet)) ls
where has_after is null
union all
select layer3domain_id, parents, 'container', subnet
from containers_tree
) freelist order by layer3domain_id, subnet;
comment on view containers_free_list is 'Creates a list of free space between other containers.';