Compare commits
4 Commits
5e06ba6b61
...
c5f0a86886
Author | SHA1 | Date |
---|---|---|
Gibheer | c5f0a86886 | |
Gibheer | 08808fe984 | |
Gibheer | d746ad7ac0 | |
Gibheer | c2bf09fd9e |
6
main.go
6
main.go
|
@ -68,7 +68,11 @@ func main() {
|
||||||
s.Register("layer3domain_list", layer3DomainList)
|
s.Register("layer3domain_list", layer3DomainList)
|
||||||
s.Register("layer3domain_get_attr", layer3DomainGetAttr)
|
s.Register("layer3domain_get_attr", layer3DomainGetAttr)
|
||||||
s.Register("layer3domain_set_attr", layer3DomainSetAttr)
|
s.Register("layer3domain_set_attr", layer3DomainSetAttr)
|
||||||
s.Register("ipblock_create", ipblockCreate)
|
s.Register("ipblock_create", containerCreate)
|
||||||
|
s.Register("ipblock_remove", containerDelete)
|
||||||
|
s.Register("ipblock_list", containerList)
|
||||||
|
s.Register("ipblock_set_attr", containerSetAttr)
|
||||||
|
s.Register("ipblock_get_attr", containerGetAttr)
|
||||||
s.Register("ippool_create", PoolCreate)
|
s.Register("ippool_create", PoolCreate)
|
||||||
s.Register("ippool_delete", PoolDelete)
|
s.Register("ippool_delete", PoolDelete)
|
||||||
s.Register("ippool_list", PoolList)
|
s.Register("ippool_list", PoolList)
|
||||||
|
|
|
@ -20,19 +20,31 @@ create table if not exists pools(
|
||||||
primary key(layer3domain_id, id)
|
primary key(layer3domain_id, id)
|
||||||
);
|
);
|
||||||
|
|
||||||
create table if not exists containers(
|
create table containers(
|
||||||
layer3domain_id integer not null references layer3domains(id),
|
layer3domain_id integer not null references layer3domains(id),
|
||||||
network cidr not null,
|
subnet cidr not null,
|
||||||
pool_id integer,
|
pool_id integer,
|
||||||
|
attributes jsonb not null default '{}'::jsonb,
|
||||||
created_at timestamptz not null default now(),
|
created_at timestamptz not null default now(),
|
||||||
created_by varchar(128) not null,
|
created_by varchar(128) not null,
|
||||||
modified_at timestamptz not null default now(),
|
modified_at timestamptz not null default now(),
|
||||||
modified_by varchar(128) not null,
|
modified_by varchar(128) not null,
|
||||||
attributes jsonb not null default '{}'::jsonb,
|
unique(layer3domain_id, subnet),
|
||||||
unique(layer3domain_id, network),
|
|
||||||
foreign key (layer3domain_id, pool_id) references pools(layer3domain_id, id)
|
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(
|
create table if not exists ips(
|
||||||
layer3domain_id integer not null,
|
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 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 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.';
|
||||||
|
|
16
types/ip.go
16
types/ip.go
|
@ -5,6 +5,7 @@ import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -12,6 +13,8 @@ type (
|
||||||
Subnet net.IPNet
|
Subnet net.IPNet
|
||||||
// IP is used to parse an IP parameter.
|
// IP is used to parse an IP parameter.
|
||||||
IP net.IP
|
IP net.IP
|
||||||
|
// IPVersion represents the two IP versions currently in use.
|
||||||
|
IPVersion int
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnmarshalJSON parses a value into a subnet.
|
// UnmarshalJSON parses a value into a subnet.
|
||||||
|
@ -69,3 +72,16 @@ func (i *IP) UnmarshalJSON(in []byte) error {
|
||||||
*i = IP(ip)
|
*i = IP(ip)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON parses the incoming version from json.
|
||||||
|
func (v *IPVersion) UnmarshalJSON(in []byte) error {
|
||||||
|
raw, err := strconv.Atoi(string(in))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("can't parse ip version: %#v", err)
|
||||||
|
}
|
||||||
|
if raw != 4 && raw != 6 {
|
||||||
|
return fmt.Errorf("only version 4 and 6 are supported")
|
||||||
|
}
|
||||||
|
*v = IPVersion(raw)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue