Current section

Files

Jump to
fifo_dt src ft_iprange.erl
Raw

src/ft_iprange.erl

%%% @author Heinz Nikolaus Gies <heinz@licenser.net>
%%% @copyright (C) 2012, Heinz Nikolaus Gies
%%% @doc
%%%
%%% @end
%%% Created : 23 Aug 2012 by Heinz Nikolaus Gies <heinz@licenser.net>
-module(ft_iprange).
-behaviour(fifo_dt).
-include("ft_iprange.hrl").
-define(OBJ, ?IPRANGE).
-include("ft_helper.hrl").
-define(G_SUB(N, F),
sub_getter(O, N) ->
F(O)).
-define(IS_IP, is_integer(V), V > 0, V < 16#FFFFFFFF).
-export([
is_a/1, new/1,
new/3, load/2, merge/2, to_json/1,
release_ip/3, claim_ip/3,
set/4,
to_bin/1,
parse_bin/1,
cidr_to_mask/1,
mask_to_cidr/1,
getter/2
]).
-export([
name/1, name/3,
uuid/1, uuid/3,
network/1, network/3,
netmask/1, netmask/3,
gateway/1, gateway/3,
metadata/1, set_metadata/3, set_metadata/4,
tag/1, tag/3,
vlan/1, vlan/3,
free/1, used/1
]).
-ignore_xref([
name/1, name/3,
uuid/1, uuid/3,
network/1, network/3,
netmask/1, netmask/3,
gateway/1, gateway/3,
metadata/1, set_metadata/3, set_metadata/4,
tag/1, tag/3,
vlan/1, vlan/3,
free/1, used/1,
release_ip/3, claim_ip/3,
merge/2
]).
-ignore_xref([load/2, name/1, set/4, getter/2, uuid/1]).
-type iprange() :: #?OBJ{}.
-export_type([iprange/0]).
?IS_A.
?G(uuid).
?S(uuid).
?G(name).
?S(name).
?G(network).
network({T, _ID}, V, H) when ?IS_IP ->
{ok, V1} = riak_dt_lwwreg:update({assign, V, T}, none, H#?IPRANGE.network),
H#?IPRANGE{network = V1}.
?G(netmask).
netmask({T, _ID}, V, H) when ?IS_IP ->
{ok, V1} = riak_dt_lwwreg:update({assign, V, T}, none, H#?IPRANGE.netmask),
H#?IPRANGE{netmask = V1}.
?G(gateway).
gateway({T, _ID}, V, H) when ?IS_IP ->
{ok, V1} = riak_dt_lwwreg:update({assign, V, T}, none, H#?IPRANGE.gateway),
H#?IPRANGE{gateway = V1}.
?G(tag).
tag({T, _ID}, V, H) when is_binary(V) ->
{ok, V1} = riak_dt_lwwreg:update({assign, V, T}, none, H#?IPRANGE.tag),
H#?IPRANGE{tag = V1}.
?G(vlan).
vlan({T, _ID}, V, H) when is_integer(V),
V >= 0, V < 4096 ->
{ok, V1} = riak_dt_lwwreg:update({assign, V, T}, none, H#?IPRANGE.vlan),
H#?IPRANGE{vlan = V1}.
free(H) ->
riak_dt_orswot:value(H#?IPRANGE.free).
used(H) ->
riak_dt_orswot:value(H#?IPRANGE.used).
-spec getter(ft_obj:obj() | iprange(), jsxd:key()) -> jsxd:value().
getter(#?OBJ{} = O, E) ->
sub_getter(O, E);
getter(O, E) ->
S0 = ft_obj:val(O),
sub_getter(S0, E).
-spec sub_getter(iprange(), jsxd:key()) -> jsxd:value().
?G_SUB(<<"uuid">>, uuid);
?G_SUB(<<"name">>, name);
?G_SUB(<<"network">>, network);
?G_SUB(<<"netmask">>, netmask);
?G_SUB(<<"gateway">>, gateway);
?G_SUB(<<"tag">>, tag);
?G_SUB(<<"vlan">>, vlan);
sub_getter(O, K) ->
lager:warning("[~s] Accessing unsupported getter ~p,"
" reverting to jsxd.", [?MODULE, K]),
jsxd:get(K, to_json(O)).
load(_, #?IPRANGE{} = I) ->
I;
load(TID, #iprange_0_1_0{
uuid = UUID,
name = Name,
network = Network,
netmask = Netmask,
gateway = Gateway,
tag = Tag,
vlan = VLan,
free = Free,
used = Used,
metadata = Metadata
}) ->
I = #iprange_0{
uuid = UUID,
name = Name,
network = Network,
netmask = Netmask,
gateway = Gateway,
tag = Tag,
vlan = VLan,
free = fifo_dt:update_set(Free),
used = fifo_dt:update_set(Used),
metadata = fifo_dt:update_map(Metadata)
},
load(TID, I).
new({_T, _ID}) ->
Free = riak_dt_orswot:new(),
#?IPRANGE{free=Free}.
new({_T, ID}, S, E) when S < E ->
{ok, Free} = riak_dt_orswot:update({add_all, lists:seq(S, E)}, ID,
riak_dt_orswot:new()),
#?IPRANGE{free=Free}.
claim_ip({_T, ID}, IP, I) when
is_integer(IP) ->
case riak_dt_orswot:update({remove, IP}, ID, I#?IPRANGE.free) of
{error, {precondition, {not_present, _}}} ->
{error, used};
{ok, Free} ->
{ok, Used} = riak_dt_orswot:update({add, IP}, ID, I#?IPRANGE.used),
{ok, I#?IPRANGE{free=Free, used=Used}}
end.
release_ip({_T, ID}, IP, I) when
is_integer(IP) ->
case riak_dt_orswot:update({remove, IP}, ID, I#?IPRANGE.used) of
{error, {precondition, {not_present, _}}} ->
{ok, I};
{ok, Used} ->
{ok, Free} = riak_dt_orswot:update({add, IP}, ID, I#?IPRANGE.free),
{ok, I#?IPRANGE{free=Free, used=Used}}
end.
set({T, ID}, <<"metadata">>, V, H) ->
H#?IPRANGE{metadata = fifo_map:from_orddict(V, ID, T)};
set(ID, K = <<"metadata.", _/binary>>, V, H) ->
set(ID, re:split(K, "\\."), V, H);
set(ID, [<<"metadata">> | R], V, H) ->
set_metadata(ID, R, V, H).
metadata(I) ->
fifo_map:value(I#?IPRANGE.metadata).
set_metadata(ID, [{K, V} | R] , Obj) ->
set_metadata(ID, R, set_metadata(ID, K, V, Obj));
set_metadata(_ID, _, Obj) ->
Obj.
set_metadata({T, ID}, P, Value, User) when is_binary(P) ->
set_metadata({T, ID}, fifo_map:split_path(P), Value, User);
set_metadata({_T, ID}, Attribute, delete, I) ->
{ok, M1} = fifo_map:remove(Attribute, ID, I#?IPRANGE.metadata),
I#?IPRANGE{metadata = M1};
set_metadata({T, ID}, Attribute, Value, I) ->
{ok, M1} = fifo_map:set(Attribute, Value, ID, T, I#?IPRANGE.metadata),
I#?IPRANGE{metadata = M1}.
to_json(I) ->
[
{<<"free">>, free(I)},
{<<"gateway">>, gateway(I)},
{<<"metadata">>, metadata(I)},
{<<"name">>, name(I)},
{<<"netmask">>, netmask(I)},
{<<"network">>, network(I)},
{<<"tag">>, tag(I)},
{<<"used">>, used(I)},
{<<"uuid">>, uuid(I)},
{<<"vlan">>, vlan(I)}
].
merge(#?IPRANGE{
uuid = UUID1,
name = Name1,
network = Network1,
netmask = Netmask1,
gateway = Gateway1,
tag = Tag1,
vlan = Vlan1,
free = Free1,
used = Used1,
metadata = Metadata1
},
#?IPRANGE{
uuid = UUID2,
name = Name2,
network = Network2,
netmask = Netmask2,
gateway = Gateway2,
tag = Tag2,
vlan = Vlan2,
free = Free2,
used = Used2,
metadata = Metadata2
}) ->
#?IPRANGE{
uuid = riak_dt_lwwreg:merge(UUID1, UUID2),
name = riak_dt_lwwreg:merge(Name1, Name2),
network = riak_dt_lwwreg:merge(Network1, Network2),
netmask = riak_dt_lwwreg:merge(Netmask1, Netmask2),
gateway = riak_dt_lwwreg:merge(Gateway1, Gateway2),
tag = riak_dt_lwwreg:merge(Tag1, Tag2),
vlan = riak_dt_lwwreg:merge(Vlan1, Vlan2),
free = riak_dt_orswot:merge(Free1, Free2),
used = riak_dt_orswot:merge(Used1, Used2),
metadata = fifo_map:merge(Metadata1, Metadata2)
}.
to_bin(IP) ->
<<A, B, C, D>> = <<IP:32>>,
list_to_binary(io_lib:format("~p.~p.~p.~p", [A, B, C, D])).
parse_bin(Bin) ->
[A, B, C, D] = [list_to_integer(binary_to_list(P))
|| P <- re:split(Bin, "[.]")],
<<IP:32>> = <<A:8, B:8, C:8, D:8>>,
IP.
mask_to_cidr(<<"255.255.255.255">>) -> 32;
mask_to_cidr(<<"255.255.255.254">>) -> 31;
mask_to_cidr(<<"255.255.255.252">>) -> 30;
mask_to_cidr(<<"255.255.255.248">>) -> 29;
mask_to_cidr(<<"255.255.255.240">>) -> 28;
mask_to_cidr(<<"255.255.255.224">>) -> 27;
mask_to_cidr(<<"255.255.255.192">>) -> 26;
mask_to_cidr(<<"255.255.255.128">>) -> 25;
mask_to_cidr(<<"255.255.255.0">>) -> 24;
mask_to_cidr(<<"255.255.254.0">>) -> 23;
mask_to_cidr(<<"255.255.252.0">>) -> 22;
mask_to_cidr(<<"255.255.248.0">>) -> 21;
mask_to_cidr(<<"255.255.240.0">>) -> 20;
mask_to_cidr(<<"255.255.224.0">>) -> 19;
mask_to_cidr(<<"255.255.192.0">>) -> 18;
mask_to_cidr(<<"255.255.128.0">>) -> 17;
mask_to_cidr(<<"255.255.0.0">>) -> 16;
mask_to_cidr(<<"255.254.0.0">>) -> 15;
mask_to_cidr(<<"255.252.0.0">>) -> 14;
mask_to_cidr(<<"255.248.0.0">>) -> 13;
mask_to_cidr(<<"255.240.0.0">>) -> 12;
mask_to_cidr(<<"255.224.0.0">>) -> 11;
mask_to_cidr(<<"255.192.0.0">>) -> 10;
mask_to_cidr(<<"255.128.0.0">>) -> 9;
mask_to_cidr(<<"255.0.0.0">>) -> 8;
mask_to_cidr(<<"254.0.0.0">>) -> 7;
mask_to_cidr(<<"252.0.0.0">>) -> 6;
mask_to_cidr(<<"248.0.0.0">>) -> 5;
mask_to_cidr(<<"240.0.0.0">>) -> 4;
mask_to_cidr(<<"224.0.0.0">>) -> 3;
mask_to_cidr(<<"192.0.0.0">>) -> 2;
mask_to_cidr(<<"128.0.0.0">>) -> 1;
mask_to_cidr(<<"0.0.0.0">>) -> 0.
cidr_to_mask(32) -> <<"255.255.255.255">>;
cidr_to_mask(31) -> <<"255.255.255.254">>;
cidr_to_mask(30) -> <<"255.255.255.252">>;
cidr_to_mask(29) -> <<"255.255.255.248">>;
cidr_to_mask(28) -> <<"255.255.255.240">>;
cidr_to_mask(27) -> <<"255.255.255.224">>;
cidr_to_mask(26) -> <<"255.255.255.192">>;
cidr_to_mask(25) -> <<"255.255.255.128">>;
cidr_to_mask(24) -> <<"255.255.255.0">>;
cidr_to_mask(23) -> <<"255.255.254.0">>;
cidr_to_mask(22) -> <<"255.255.252.0">>;
cidr_to_mask(21) -> <<"255.255.248.0">>;
cidr_to_mask(20) -> <<"255.255.240.0">>;
cidr_to_mask(19) -> <<"255.255.224.0">>;
cidr_to_mask(18) -> <<"255.255.192.0">>;
cidr_to_mask(17) -> <<"255.255.128.0">>;
cidr_to_mask(16) -> <<"255.255.0.0">>;
cidr_to_mask(15) -> <<"255.254.0.0">>;
cidr_to_mask(14) -> <<"255.252.0.0">>;
cidr_to_mask(13) -> <<"255.248.0.0">>;
cidr_to_mask(12) -> <<"255.240.0.0">>;
cidr_to_mask(11) -> <<"255.224.0.0">>;
cidr_to_mask(10) -> <<"255.192.0.0">>;
cidr_to_mask( 9) -> <<"255.128.0.0">>;
cidr_to_mask( 8) -> <<"255.0.0.0">>;
cidr_to_mask( 7) -> <<"254.0.0.0">>;
cidr_to_mask( 6) -> <<"252.0.0.0">>;
cidr_to_mask( 5) -> <<"248.0.0.0">>;
cidr_to_mask( 4) -> <<"240.0.0.0">>;
cidr_to_mask( 3) -> <<"224.0.0.0">>;
cidr_to_mask( 2) -> <<"192.0.0.0">>;
cidr_to_mask( 1) -> <<"128.0.0.0">>;
cidr_to_mask( 0) -> <<"0.0.0.0">>.