Configure FLUs and chains with "rc.d" style configuration #56

Merged
slfritchie merged 43 commits from slf/flu-config-rcd-style into master 2015-12-18 06:46:05 +00:00
3 changed files with 61 additions and 38 deletions
Showing only changes of commit 6b7d871ada - Show all commits

View file

@ -82,7 +82,7 @@
mode :: pv1_consistency_mode(), mode :: pv1_consistency_mode(),
full = [] :: [p_srvr()], full = [] :: [p_srvr()],
witnesses = [] :: [p_srvr()], witnesses = [] :: [p_srvr()],
old_all = [] :: [pv1_server()], % guard against some races old_full = [] :: [pv1_server()], % guard against some races
old_witnesses=[] :: [pv1_server()], % guard against some races old_witnesses=[] :: [pv1_server()], % guard against some races
local_run = [] :: [pv1_server()], % must be tailored to each machine! local_run = [] :: [pv1_server()], % must be tailored to each machine!
local_stop = [] :: [pv1_server()], % must be tailored to each machine! local_stop = [] :: [pv1_server()], % must be tailored to each machine!

View file

@ -355,7 +355,8 @@ bootstrap_chain2(CD, FLU, 0) ->
failed; failed;
bootstrap_chain2(#chain_def_v1{name=NewChainName, mode=NewCMode, bootstrap_chain2(#chain_def_v1{name=NewChainName, mode=NewCMode,
full=Full, witnesses=Witnesses, full=Full, witnesses=Witnesses,
old_all=ReqOldAll, old_witnesses=ReqOldWitnesses, old_full=ReqOldFull,
old_witnesses=ReqOldWitnesses,
props=_Props}=CD, props=_Props}=CD,
FLU, N) -> FLU, N) ->
All_p_srvrs = Witnesses ++ Full, All_p_srvrs = Witnesses ++ Full,
@ -371,7 +372,7 @@ bootstrap_chain2(#chain_def_v1{name=NewChainName, mode=NewCMode,
all_members=OldAll_list, witnesses=OldWitnesses}} = all_members=OldAll_list, witnesses=OldWitnesses}} =
machi_projection_store:read_latest_projection(PStore, private), machi_projection_store:read_latest_projection(PStore, private),
case set_chain_members(OldChainName, NewChainName, OldCMode, case set_chain_members(OldChainName, NewChainName, OldCMode,
ReqOldAll, ReqOldWitnesses, ReqOldFull, ReqOldWitnesses,
OldAll_list, OldWitnesses, OldAll_list, OldWitnesses,
NewAll_list, Witnesses, NewAll_list, Witnesses,
Mgr, NewChainName, OldEpoch, Mgr, NewChainName, OldEpoch,
@ -396,18 +397,18 @@ bootstrap_chain2(#chain_def_v1{name=NewChainName, mode=NewCMode,
end. end.
set_chain_members(OldChainName, NewChainName, OldCMode, set_chain_members(OldChainName, NewChainName, OldCMode,
ReqOldAll, ReqOldWitnesses, ReqOldFull, ReqOldWitnesses,
OldAll_list, OldWitnesses, NewAll_list, NewWitnesses, OldFull_list, OldWitnesses, NewAll_list, NewWitnesses,
Mgr, ChainName, OldEpoch, NewCMode, MembersDict, _Props) -> Mgr, ChainName, OldEpoch, NewCMode, MembersDict, _Props) ->
if OldChainName == NewChainName, OldCMode == NewCMode, if OldChainName == NewChainName, OldCMode == NewCMode,
OldAll_list == NewAll_list, OldWitnesses == NewWitnesses -> OldFull_list == NewAll_list, OldWitnesses == NewWitnesses ->
%% The chain's current definition at this FLU is already what we %% The chain's current definition at this FLU is already what we
%% want. Let's pretend that we sent the command and that it was %% want. Let's pretend that we sent the command and that it was
%% successful. %% successful.
ok; ok;
OldEpoch == 0 orelse (OldChainName == NewChainName andalso OldEpoch == 0 orelse (OldChainName == NewChainName andalso
OldCMode == NewCMode andalso OldCMode == NewCMode andalso
ReqOldAll == OldAll_list andalso ReqOldFull == OldFull_list andalso
ReqOldWitnesses == OldWitnesses) -> ReqOldWitnesses == OldWitnesses) ->
%% The old epoch is 0 (no chain defined) or else the prerequisites %% The old epoch is 0 (no chain defined) or else the prerequisites
%% for our chain change request are indeed matched by the FLU's %% for our chain change request are indeed matched by the FLU's
@ -641,14 +642,14 @@ check_an_ast_tuple({host, Name, AdminI, ClientI, Props}) ->
check_an_ast_tuple({flu, Name, HostName, Port, Props}) -> check_an_ast_tuple({flu, Name, HostName, Port, Props}) ->
is_stringy(Name) andalso is_stringy(HostName) andalso is_stringy(Name) andalso is_stringy(HostName) andalso
is_porty(Port) andalso is_proplisty(Props); is_porty(Port) andalso is_proplisty(Props);
check_an_ast_tuple({chain, Name, AllList, Props}) -> check_an_ast_tuple({chain, Name, FullList, Props}) ->
is_stringy(Name) andalso is_stringy(Name) andalso
lists:all(fun is_stringy/1, AllList) andalso lists:all(fun is_stringy/1, FullList) andalso
is_proplisty(Props); is_proplisty(Props);
check_an_ast_tuple({chain, Name, CMode, AllList, Witnesses, Props}) -> check_an_ast_tuple({chain, Name, CMode, FullList, Witnesses, Props}) ->
is_stringy(Name) andalso is_stringy(Name) andalso
(CMode == ap_mode orelse CMode == cp_mode) andalso (CMode == ap_mode orelse CMode == cp_mode) andalso
lists:all(fun is_stringy/1, AllList) andalso lists:all(fun is_stringy/1, FullList) andalso
lists:all(fun is_stringy/1, Witnesses) andalso lists:all(fun is_stringy/1, Witnesses) andalso
is_proplisty(Props); is_proplisty(Props);
check_an_ast_tuple(switch_old_and_new) -> check_an_ast_tuple(switch_old_and_new) ->
@ -673,10 +674,10 @@ normalize_an_ast_tuple({host, Name, AdminI, ClientI, Props}) ->
{host, Name, AdminI, ClientI, n(Props2)}; {host, Name, AdminI, ClientI, n(Props2)};
normalize_an_ast_tuple({flu, Name, HostName, Port, Props}) -> normalize_an_ast_tuple({flu, Name, HostName, Port, Props}) ->
{flu, Name, HostName, Port, n(Props)}; {flu, Name, HostName, Port, n(Props)};
normalize_an_ast_tuple({chain, Name, AllList, Props}) -> normalize_an_ast_tuple({chain, Name, FullList, Props}) ->
{chain, Name, ap_mode, n(AllList), [], n(Props)}; {chain, Name, ap_mode, n(FullList), [], n(Props)};
normalize_an_ast_tuple({chain, Name, CMode, AllList, Witnesses, Props}) -> normalize_an_ast_tuple({chain, Name, CMode, FullList, Witnesses, Props}) ->
{chain, Name, CMode, n(AllList), n(Witnesses), n(Props)}; {chain, Name, CMode, n(FullList), n(Witnesses), n(Props)};
normalize_an_ast_tuple(A=switch_old_and_new) -> normalize_an_ast_tuple(A=switch_old_and_new) ->
A. A.
@ -701,14 +702,16 @@ run_ast(Ts) ->
%% Mutable: no. %% Mutable: no.
%% Reference KV store for X. Variations of X are: %% Reference KV store for X. Variations of X are:
%% {host, Name} | {flu, Name} | {chain, Name} %% {host, Name} | {flu, Name} | {chain, Name}
%% Value is a {host,...} or {flu,...}, or {chain,...} AST tuple.
%% %%
%% {tmp, X}
%% Mutable: yes.
%% Tmp scratch for X. Variations of X are:
%% {p_srvr, Name} %% {p_srvr, Name}
%% #p_srvr{} record for FLU Name, for cache/convenience purposes. %% #p_srvr{} record for FLU Name, for cache/convenience purposes.
%% If a FLU has been defined via {kv,_}, this key must also exist. %% If a FLU has been defined via {kv,_}, this key must also exist.
%% %%
%%
%% {tmp, X}
%% Mutable: yes.
%% Tmp scratch for X. Variations of X are:
%% {flu_assigned_to, ChainName} %% {flu_assigned_to, ChainName}
%% If a FLU is currently assigned to a chain, map to ChainName. %% If a FLU is currently assigned to a chain, map to ChainName.
%% If a FLU is not currently assigned to a chain, key does not exist. %% If a FLU is not currently assigned to a chain, key does not exist.
@ -732,7 +735,7 @@ run_ast_cmd({flu, Name, HostName, Port, Props}=T, E) ->
{ok, ClientI} = get_host_client_interface(HostName, E), {ok, ClientI} = get_host_client_interface(HostName, E),
Mod = proplists:get_value( Mod = proplists:get_value(
proto_mod, Props, 'machi_flu1_client'), proto_mod, Props, 'machi_flu1_client'),
Val_p = #p_srvr{name=Name, proto_mod=Mod, Val_p = #p_srvr{name=list_to_atom(Name), proto_mod=Mod,
address=ClientI, port=Port, props=Props}, address=ClientI, port=Port, props=Props},
d_store(Key, T, d_store(Key, T,
d_store(Key_p, Val_p, E)); d_store(Key_p, Val_p, E));
@ -745,9 +748,9 @@ run_ast_cmd({flu, Name, HostName, Port, Props}=T, E) ->
{ok, _} -> {ok, _} ->
err("Duplicate flu ~p", [Name], T) err("Duplicate flu ~p", [Name], T)
end; end;
run_ast_cmd({chain, Name, CMode, AllList, Witnesses, _Props}=T, E) -> run_ast_cmd({chain, Name, CMode, FullList, Witnesses, _Props}=T, E) ->
Key = {kv,{chain,Name}}, Key = {kv,{chain,Name}},
AllFLUs = AllList ++ Witnesses, AllFLUs = FullList ++ Witnesses,
%% All FLUs must exist. %% All FLUs must exist.
case lists:sort(AllFLUs) == lists:usort(AllFLUs) of case lists:sort(AllFLUs) == lists:usort(AllFLUs) of
@ -858,6 +861,7 @@ d_find(Key, {KV_old, KV_new, IsNew}) ->
d_get(Key, {KV_old, KV_new, IsNew}) -> d_get(Key, {KV_old, KV_new, IsNew}) ->
%% Bah, use 'dict' return value convention. %% Bah, use 'dict' return value convention.
%% Assume key exists, fail if not found.
case gb_trees:lookup(Key, KV_new) of case gb_trees:lookup(Key, KV_new) of
{value, Val} when IsNew -> {value, Val} when IsNew ->
Val; Val;
@ -924,12 +928,12 @@ diff_env({KV_old, KV_new, _IsNew}=E, RelativeHost) ->
end end
end, end,
DiffD = lists:foldl(fun(K, D) -> %% DiffD = lists:foldl(fun(K, D) ->
gb_trees:enter(K, [], D) %% gb_trees:enter(K, [], D)
end, gb_trees:empty(), lists:usort(Keys_old++Keys_new)), %% end, gb_trees:empty(), lists:usort(Keys_old++Keys_new)),
DiffD2 = lists:foldl(Append(old), DiffD, Keys_old), %% DiffD2 = lists:foldl(Append(old), DiffD, Keys_old),
DiffD3 = lists:foldl(Append(new), DiffD2, Keys_new), %% DiffD3 = lists:foldl(Append(new), DiffD2, Keys_new),
%% DiffD3 values will be exactly one of: [old], [old,new], [new] %% %% DiffD3 values will be exactly one of: [old], [old,new], [new]
put(final, []), put(final, []),
Add = fun(X) -> put(final, [X|get(final)]) end, Add = fun(X) -> put(final, [X|get(final)]) end,
@ -946,23 +950,42 @@ diff_env({KV_old, KV_new, _IsNew}=E, RelativeHost) ->
%% Find new chains on this host and define them. %% Find new chains on this host and define them.
%% Find modified chains on this host and re-define them. %% Find modified chains on this host and re-define them.
[begin [begin
{chain, Name, CMode, AllList, Witnesses, Props} = V, {chain, Name, CMode, FullList, Witnesses, Props} = V,
FLUsA = [d_get({kv,{flu,FLU}}, E) || FLU <- AllList], FLUsF = [d_get({kv,{flu,FLU}}, E) || FLU <- FullList],
FLUsW = [d_get({kv,{flu,FLU}}, E) || FLU <- Witnesses], FLUsW = [d_get({kv,{flu,FLU}}, E) || FLU <- Witnesses],
TheFLU_Hosts = TheFLU_Hosts = [{list_to_atom(FLU_str), Host} ||
[Host || {flu, _Name, Host, _Port, _Ps} <- FLUsA ++ FLUsW], {flu, FLU_str, Host, _Port, _Ps} <- FLUsF ++ FLUsW],
case (lists:member(RelativeHost, TheFLU_Hosts) case (lists:keymember(RelativeHost, 2, TheFLU_Hosts)
orelse RelativeHost == all) of orelse RelativeHost == all) of
true -> true ->
Ps_F = [d_get({kv,{p_srvr,FLU}}, E) || FLU <- FullList],
Ps_W = [d_get({kv,{p_srvr,FLU}}, E) || FLU <- Witnesses],
case gb_trees:lookup({kv,{chain,Name}}, KV_old) of case gb_trees:lookup({kv,{chain,Name}}, KV_old) of
{value, OldT} -> {value, OldT} ->
Add({yo,change,Name}); {chain, _, _, OldFull_ss, OldWitnesses_ss, _} = OldT,
OldFull = [Str || Str <- OldFull_ss],
OldWitnesses = [Str || Str <- OldWitnesses_ss],
io:format(user, "\nOldT: ~p\n", [OldT]),
Run = [FLU || {FLU, Hst} <- TheFLU_Hosts,
Hst == RelativeHost
orelse RelativeHost == all,
not lists:member(FLU,
OldFull++OldWitnesses)],
Stop = [yolo];
none -> none ->
Add({yo,new,Name}) OldFull = [],
end; OldWitnesses = [],
Run = [derp,derp],
Stop = []
end,
Add(#chain_def_v1{name=list_to_atom(Name),
mode=CMode, full=Ps_F, witnesses=Ps_W,
old_full=OldFull, old_witnesses=OldWitnesses,
local_run=Run, local_stop=Stop});
false -> false ->
ok ok
end end
end || {{kv,{chain,Name}}, V} <- New_list], end || {{kv,{chain,Name}}, V} <- New_list],
{DiffD3, lists:reverse(get(final))}. {gb_trees:empty(), lists:reverse(get(final))}.

View file

@ -107,7 +107,7 @@ smoke_test2() ->
io:format("\nSTEP: Reset chain = [b,c]\n", []), io:format("\nSTEP: Reset chain = [b,c]\n", []),
C2 = #chain_def_v1{name=cx, mode=ap_mode, full=[Pb,Pc], C2 = #chain_def_v1{name=cx, mode=ap_mode, full=[Pb,Pc],
old_all=[a,b,c], old_witnesses=[], old_full=[a,b,c], old_witnesses=[],
local_stop=[a], local_run=[b,c]}, local_stop=[a], local_run=[b,c]},
make_pending_config(C2), make_pending_config(C2),
{[],[_]} = machi_lifecycle_mgr:process_pending(), {[],[_]} = machi_lifecycle_mgr:process_pending(),
@ -123,7 +123,7 @@ smoke_test2() ->
io:format("\nSTEP: Reset chain = []\n", []), io:format("\nSTEP: Reset chain = []\n", []),
C3 = #chain_def_v1{name=cx, mode=ap_mode, full=[], C3 = #chain_def_v1{name=cx, mode=ap_mode, full=[],
old_all=[b,c], old_witnesses=[], old_full=[b,c], old_witnesses=[],
local_stop=[b,c], local_run=[]}, local_stop=[b,c], local_run=[]},
make_pending_config(C3), make_pending_config(C3),
{[],[_]} = machi_lifecycle_mgr:process_pending(), {[],[_]} = machi_lifecycle_mgr:process_pending(),