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 74 additions and 32 deletions
Showing only changes of commit f98b4da45b - Show all commits

View file

@ -22,23 +22,41 @@ cd $RUNNER_BASE_DIR
SCRIPT=`basename $0` SCRIPT=`basename $0`
usage() { usage() {
echo "Usage: $SCRIPT { test | " echo "Usage: $SCRIPT { quick-admin-check | quick-admin-apply | "
echo " top }" echo " top }"
} }
case "$1" in case "$1" in
test) quick-admin-check)
# Make sure the local node IS running # Make sure the local node IS running
node_up_check node_up_check
shift shift
# Parse out the node name to pass to the client NODE_NAME=${NAME_ARG#* } # target machi server node name
NODE_NAME=${NAME_ARG#* } IN_FILE="$1"
$ERTS_PATH/erl -noshell $NAME_PARAM machi_test$NAME_HOST $COOKIE_ARG \ $ERTS_PATH/erl -noshell -noinput $NAME_PARAM machi_test$NAME_HOST $COOKIE_ARG \
-pa $RUNNER_LIB_DIR/basho-patches \ -remsh $NODE_NAME \
-eval "case catch(machi:client_test(\"$NODE_NAME\")) of \ -eval "Me = self(), spawn('"$NODE_NAME"', fun() -> X = (catch(machi_lifecycle_mgr:quick_admin_sanity_check(\"$IN_FILE\"))), Me ! {res, X} end), XX = receive {res, Res} -> Res after 10*1000 -> timeout end, io:format(user, \"Result: ~p\n\", [XX]), case XX of \
ok -> init:stop(); \
_ -> init:stop(1) \
end."
;;
quick-admin-apply)
# Make sure the local node IS running
node_up_check
shift
NODE_NAME=${NAME_ARG#* } # target machi server node name
IN_FILE="$1"
RELATIVE_HOST="$2"
$ERTS_PATH/erl -noshell -noinput $NAME_PARAM machi_test$NAME_HOST $COOKIE_ARG \
-remsh $NODE_NAME \
-eval "Me = self(), spawn('"$NODE_NAME"', fun() -> X = (catch(machi_lifecycle_mgr:quick_admin_apply(\"$IN_FILE\", \"$RELATIVE_HOST\"))), Me ! {res, X} end), XX = receive {res, Res} -> Res after 10*1000 -> timeout end, io:format(user, \"Result: ~p\n\", [XX]), case XX of \
ok -> init:stop(); \ ok -> init:stop(); \
_ -> init:stop(1) \ _ -> init:stop(1) \
end." end."

View file

@ -100,7 +100,7 @@
{mkdir, "etc/rejected"}, {mkdir, "etc/rejected"},
%% Experiment: quick-admin %% Experiment: quick-admin
{mkdir, "etc/quick-admin"}, {mkdir, "etc/quick-admin-archive"},
{mkdir, "priv"}, {mkdir, "priv"},
{mkdir, "priv/quick-admin-examples"}, {mkdir, "priv/quick-admin-examples"},
{copy, "../priv/quick-admin-examples/000", "priv/quick-admin-examples"}, {copy, "../priv/quick-admin-examples/000", "priv/quick-admin-examples"},

View file

@ -207,7 +207,7 @@
process_pending/0]). process_pending/0]).
-export([get_pending_dir/0, get_rejected_dir/0, get_flu_config_dir/0, -export([get_pending_dir/0, get_rejected_dir/0, get_flu_config_dir/0,
get_flu_data_dir/0, get_chain_config_dir/0, get_data_dir/0]). get_flu_data_dir/0, get_chain_config_dir/0, get_data_dir/0]).
-export([quick_admin_sanity_check/0, quick_admin_apply/1]). -export([quick_admin_sanity_check/1, quick_admin_apply/2]).
-export([make_pending_config/1, run_ast/1, diff_env/2]). -export([make_pending_config/1, run_ast/1, diff_env/2]).
-ifdef(TEST). -ifdef(TEST).
-compile(export_all). -compile(export_all).
@ -323,6 +323,8 @@ sanitize_chain_def_rec(Whole, {Acc, D}) ->
perhaps_bootstrap_chains([], LocalFLUs_at_zero, LocalFLUs) -> perhaps_bootstrap_chains([], LocalFLUs_at_zero, LocalFLUs) ->
if LocalFLUs == [] -> if LocalFLUs == [] ->
ok; ok;
LocalFLUs_at_zero == [] ->
ok;
true -> true ->
lager:warning("The following FLUs are defined but are not also " lager:warning("The following FLUs are defined but are not also "
"members of a defined chain: ~w\n", "members of a defined chain: ~w\n",
@ -420,6 +422,7 @@ set_chain_members(OldChainName, NewChainName, OldCMode,
do_process_pending(S) -> do_process_pending(S) ->
PendingDir = get_pending_dir(), PendingDir = get_pending_dir(),
PendingParsed = machi_flu_sup:load_rc_d_files_from_dir(PendingDir), PendingParsed = machi_flu_sup:load_rc_d_files_from_dir(PendingDir),
%% A pending file has exactly one record (#p_srvr{} or #chain_def_v1{}).
P_FLUs = [X || {_File, #p_srvr{}}=X <- PendingParsed], P_FLUs = [X || {_File, #p_srvr{}}=X <- PendingParsed],
P_Chains = [X || {_File, #chain_def_v1{}}=X <- PendingParsed], P_Chains = [X || {_File, #chain_def_v1{}}=X <- PendingParsed],
BadFiles = [File || {File, []} <- PendingParsed], BadFiles = [File || {File, []} <- PendingParsed],
@ -466,7 +469,7 @@ get_preserve_dir() ->
get_quick_admin_dir() -> get_quick_admin_dir() ->
{ok, EtcDir} = application:get_env(machi, platform_etc_dir), {ok, EtcDir} = application:get_env(machi, platform_etc_dir),
EtcDir ++ "/quick-admin". EtcDir ++ "/quick-admin-archive".
process_pending_flus(P_FLUs, S) -> process_pending_flus(P_FLUs, S) ->
lists:foldl(fun process_pending_flu/2, S, P_FLUs). lists:foldl(fun process_pending_flu/2, S, P_FLUs).
@ -600,7 +603,7 @@ move_to_rejected(File, S) ->
S. S.
make_ts_suffix() -> make_ts_suffix() ->
lists:flatten(io_lib:format("~w,~w,~w", tuple_to_list(os:timestamp()))). str("~w,~w,~w", tuple_to_list(os:timestamp())).
move_to_flu_config(FLU, File, S) -> move_to_flu_config(FLU, File, S) ->
lager:info("Creating FLU config file ~w\n", [FLU]), lager:info("Creating FLU config file ~w\n", [FLU]),
@ -890,7 +893,10 @@ n(L) ->
lists:sort(L). lists:sort(L).
err(Fmt, Args, AST) -> err(Fmt, Args, AST) ->
throw({lists:flatten(io_lib:format(Fmt, Args)), AST}). throw({str(Fmt, Args), AST}).
str(Fmt, Args) ->
lists:flatten(io_lib:format(Fmt, Args)).
%% We won't allow 'atom' style proplist members: too difficult to normalize. %% We won't allow 'atom' style proplist members: too difficult to normalize.
%% Also, no duplicates, again because normalizing useful for checksums but %% Also, no duplicates, again because normalizing useful for checksums but
@ -991,7 +997,7 @@ make_pending_config(Term) ->
Dir = get_pending_dir(), Dir = get_pending_dir(),
Blob = io_lib:format("~p.\n", [Term]), Blob = io_lib:format("~p.\n", [Term]),
{A,B,C} = os:timestamp(), {A,B,C} = os:timestamp(),
Path = lists:flatten(io_lib:format("~s/~w.~6..0w",[Dir, A*1000000+B, C])), Path = str("~s/~w.~6..0w",[Dir, A*1000000+B, C]),
ok = file:write_file(Path, Blob). ok = file:write_file(Path, Blob).
%% @doc Check a "quick admin" directory's for sanity %% @doc Check a "quick admin" directory's for sanity
@ -1013,28 +1019,29 @@ make_pending_config(Term) ->
%% files were actually safe &amp; sane, therefore any sanity problem can only %% files were actually safe &amp; sane, therefore any sanity problem can only
%% be caused by the contents of the largest numbered file. %% be caused by the contents of the largest numbered file.
quick_admin_sanity_check() -> quick_admin_sanity_check(File) ->
try try
{ok, Env} = quick_admin_run_ast(), {ok, Env} = quick_admin_run_ast(File),
{true, diff_env(Env, all)} ok
catch X:Y -> catch X:Y ->
{false, {X,Y}} {error, {X,Y, erlang:get_stacktrace()}}
end. end.
quick_admin_apply(HostName) -> quick_admin_apply(File, HostName) ->
try try
{ok, Env} = quick_admin_run_ast(), {ok, Env} = quick_admin_run_ast(File),
{_, Cs} = diff_env(Env, HostName), {_, Cs} = diff_env(Env, HostName),
[ok = make_pending_config(C) || C <- Cs], [ok = make_pending_config(C) || C <- Cs],
{PassFLUs, PassChains} = machi_lifecycle_mgr:process_pending(), {PassFLUs, PassChains} = machi_lifecycle_mgr:process_pending(),
case length(PassFLUs) + length(PassChains) of case length(PassFLUs) + length(PassChains) of
N when N == length(Cs) -> N when N == length(Cs) ->
yay; ok = quick_admin_add_archive_file(File),
ok;
_ -> _ ->
{sad, expected, length(Cs), Cs, got, PassFLUs, PassChains} {error, {expected, length(Cs), Cs, got, PassFLUs, PassChains}}
end end
catch X:Y -> catch X:Y ->
{false, {X,Y}, erlang:get_stacktrace()} {error, {X,Y, erlang:get_stacktrace()}}
end. end.
@ -1042,14 +1049,31 @@ quick_admin_parse_quick(F) ->
{ok, Terms} = file:consult(F), {ok, Terms} = file:consult(F),
Terms. Terms.
quick_admin_run_ast() -> quick_admin_run_ast(File) ->
case filelib:wildcard(get_quick_admin_dir() ++ "/*") of Prevs = quick_admin_list_archive_files(),
[] -> PrevASTs = lists:append([quick_admin_parse_quick(F) || F <- Prevs]),
PrevASTs = LatestASTs = []; LatestASTs = quick_admin_parse_quick(File),
Quicks ->
LatestQuick = lists:last(Quicks),
Prev = Quicks -- [LatestQuick],
PrevASTs = lists:append([quick_admin_parse_quick(F) || F <- Prev]),
LatestASTs = quick_admin_parse_quick(LatestQuick)
end,
{ok, _Env} = run_ast(PrevASTs ++ [switch_old_and_new] ++ LatestASTs). {ok, _Env} = run_ast(PrevASTs ++ [switch_old_and_new] ++ LatestASTs).
quick_admin_list_archive_files() ->
Prevs0 = filelib:wildcard(get_quick_admin_dir() ++ "/*"),
[Fn || Fn <- Prevs0, base_fn_all_digits(Fn)].
base_fn_all_digits(Path) ->
Base = filename:basename(Path),
lists:all(fun is_ascii_digit/1, Base).
is_ascii_digit(X) when $0 =< X, X =< $9 ->
true;
is_ascii_digit(_) ->
false.
quick_admin_add_archive_file(File) ->
Prevs = quick_admin_list_archive_files(),
N = case [list_to_integer(filename:basename(Fn)) || Fn <- Prevs] of
[] -> 0;
Ns -> lists:max(Ns)
end,
Dir = get_quick_admin_dir(),
NewName = str("~s/~6..0w", [Dir, N + 1]),
ok = file:rename(File, NewName).