From a9cf1124f7d8d1333c79d542b900d3d0e12552c3 Mon Sep 17 00:00:00 2001 From: Tristan Sloughter Date: Thu, 19 Sep 2013 21:40:49 -0500 Subject: create RELEASES file and include tarball so downgrade to initial release works --- src/rlx_prv_assembler.erl | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/rlx_prv_assembler.erl') diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl index 08d7325..2ba1786 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -382,12 +382,14 @@ make_boot_script(State, Release, OutputDir, RelDir) -> ok -> rlx_log:error(rlx_state:log(State), "release successfully created!"), + create_RELEASES(OutputDir, ReleaseFile), {ok, State}; error -> ?RLX_ERROR({release_script_generation_error, ReleaseFile}); {ok, _, []} -> rlx_log:error(rlx_state:log(State), "release successfully created!"), + create_RELEASES(OutputDir, ReleaseFile), {ok, State}; {ok,Module,Warnings} -> ?RLX_ERROR({release_script_generation_warn, Module, Warnings}); @@ -462,6 +464,8 @@ update_tar(State, TempDir, OutputDir, Name, Vsn, ErtsVersion) -> hd(install_upgrade_escript_contents())}, {"lib", filename:join(TempDir, "lib")}, {"releases", filename:join(TempDir, "releases")}, + {filename:join(["releases", "RELEASES"]) + ,filename:join([OutputDir, "releases", "RELEASES"])}, {filename:join(["releases", Vsn, "vm.args"]), filename:join([OutputDir, "releases", Vsn, "vm.args"])}, {"bin", filename:join([OutputDir, "bin"])}], [compressed]), @@ -470,6 +474,15 @@ update_tar(State, TempDir, OutputDir, Name, Vsn, ErtsVersion) -> ec_file:remove(TempDir, [recursive]), {ok, State}. +create_RELEASES(OutputDir, ReleaseFile) -> + {ok, OldCWD} = file:get_cwd(), + file:set_cwd(OutputDir), + release_handler:create_RELEASES("./", + "releases", + ReleaseFile, + []), + file:set_cwd(OldCWD). + make_upfrom_script(State, Release, UpFrom) -> OutputDir = rlx_state:output_dir(State), Options = [{outdir, OutputDir}, -- cgit v1.2.3 From 963909d6a3793a4b0aec71d282f9246f605070ef Mon Sep 17 00:00:00 2001 From: RJ Date: Fri, 20 Sep 2013 10:22:07 +0000 Subject: Support upgrade and downgrade between versions The "bin/RELNAME install" command now handles upgrading and downgrading. It unpacks and installs new versions as needed, or just sets existing releases as current/permanent as needed. I renamed from "bin/RELNAME upgrade" because it handles downgrades too. "upgrade" and "downgrade" are now synonyms for "install" Additionally, when installing a new to-be-unpacked version, you can say: bin/RELNAME install 0.1.1/beat OR just: bin/RELNAME install 0.1.1 in which case the /RELNAME part is added automatically. This is to keep the version spec for downgrades the same as for new upgrades. This is fully backwards compatible with the existing "upgrade" command. --- src/rlx_prv_assembler.erl | 109 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 26 deletions(-) (limited to 'src/rlx_prv_assembler.erl') diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl index 2ba1786..4834591 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -459,15 +459,15 @@ update_tar(State, TempDir, OutputDir, Name, Vsn, ErtsVersion) -> ok = erl_tar:create(TarFile, [{"erts-"++ErtsVersion, filename:join(TempDir, "erts-"++ErtsVersion)}, {filename:join(["erts-"++ErtsVersion, "bin", "nodetool"]), - hd(nodetool_contents())}, + hd(nodetool_contents())}, {filename:join(["erts-"++ErtsVersion, "bin", "install_upgrade.escript"]), - hd(install_upgrade_escript_contents())}, + hd(install_upgrade_escript_contents())}, {"lib", filename:join(TempDir, "lib")}, {"releases", filename:join(TempDir, "releases")}, - {filename:join(["releases", "RELEASES"]) - ,filename:join([OutputDir, "releases", "RELEASES"])}, + {filename:join(["releases", "RELEASES"]), + filename:join([OutputDir, "releases", "RELEASES"])}, {filename:join(["releases", Vsn, "vm.args"]), - filename:join([OutputDir, "releases", Vsn, "vm.args"])}, + filename:join([OutputDir, "releases", Vsn, "vm.args"])}, {"bin", filename:join([OutputDir, "bin"])}], [compressed]), rlx_log:info(rlx_state:log(State), "tarball ~s successfully created!~n", [TarFile]), @@ -855,10 +855,10 @@ case \"$1\" in exec $REMSH ;; - upgrade) + upgrade|downgrade|install) if [ -z \"$2\" ]; then - echo \"Missing upgrade package argument\" - echo \"Usage: $REL_NAME upgrade {package base name}\" + echo \"Missing package argument\" + echo \"Usage: $REL_NAME $1 {package base name}\" echo \"NOTE {package base name} MUST NOT include the .tar.gz suffix\" exit 1 fi @@ -874,7 +874,7 @@ case \"$1\" in node_name=`echo $NAME_ARG | awk '{print $2}'` erlang_cookie=`echo $COOKIE_ARG | awk '{print $2}'` - $ERTS_DIR/bin/escript $ERTS_DIR/bin/install_upgrade.escript $node_name $erlang_cookie $2 + $ERTS_DIR/bin/escript $ERTS_DIR/bin/install_upgrade.escript $REL_NAME $node_name $erlang_cookie $2 ;; console|console_clean|console_boot) @@ -946,27 +946,82 @@ install_upgrade_escript_contents() -> -define(TIMEOUT, 60000). -define(INFO(Fmt,Args), io:format(Fmt,Args)). -main([NodeName, Cookie, ReleasePackage]) ->TargetNode = start_distribution(NodeName, Cookie), - {ok, Cwd} = file:get_cwd(), - ok = rpc:call(TargetNode, file, set_cwd, - [Cwd], ?TIMEOUT), - case rpc:call(TargetNode, release_handler, unpack_release, - [ReleasePackage], ?TIMEOUT) of - {ok, Vsn} -> - ?INFO(\"Unpacked Release ~p~n\", [Vsn]), - {ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler, - check_install_release, [Vsn], ?TIMEOUT), - {ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler, - install_release, [Vsn], ?TIMEOUT), - ?INFO(\"Installed Release ~p~n\", [Vsn]), - ok = rpc:call(TargetNode, release_handler, make_permanent, [Vsn], ?TIMEOUT), - ?INFO(\"Made Release ~p Permanent~n\", [Vsn]); - {error, {existing_release, Vsn}} -> - ?INFO(\"Release ~s already installed~n\", [Vsn]) +%% Upgrades, to a new tar.gz release +main([RelName, NodeName, Cookie, VersionArg]) -> + TargetNode = start_distribution(NodeName, Cookie), + WhichReleases = which_releases(TargetNode), + Version = parse_version(VersionArg), + case proplists:get_value(Version, WhichReleases) of + undefined -> + %% not installed, so unpack tarball: + ?INFO(\"Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n\",[Version,Version,RelName]), + ReleasePackage = Version ++ \"/\" ++ RelName, + case rpc:call(TargetNode, release_handler, unpack_release, + [ReleasePackage], ?TIMEOUT) of + {ok, Vsn} -> + ?INFO(\"Unpacked successfully: ~p~n\", [Vsn]), + install_and_permafy(TargetNode, Vsn); + {error, UnpackReason} -> + print_existing_versions(TargetNode), + ?INFO(\"Unpack failed: ~p~n\",[UnpackReason]), + init:stop(2) + end; + old -> + %% no need to unpack, has been installed previously + ?INFO(\"Release ~s is marked old, switching to it.~n\",[Version]), + install_and_permafy(TargetNode, Version); + unpacked -> + ?INFO(\"Release ~s is already unpacked, now installing.~n\",[Version]), + install_and_permafy(TargetNode, Version); + current -> %% installed and in-use, just needs to be permanent + ?INFO(\"Release ~s is already installed and current. Making permanent.~n\",[Version]), + permafy(TargetNode, Version); + permanent -> + ?INFO(\"Release ~s is already installed, and set permanent.~n\",[Version]) end; main(_) -> init:stop(1). +parse_version(V) when is_list(V) -> + hd(string:tokens(V,\"/\")). + +install_and_permafy(TargetNode, Vsn) -> + case rpc:call(TargetNode, release_handler, check_install_release, [Vsn], ?TIMEOUT) of + {ok, _OtherVsn, _Desc} -> + ok; + {error, Reason} -> + ?INFO(\"ERROR: release_handler:check_install_release failed: ~p~n\",[Reason]), + init:stop(3) + end, + case rpc:call(TargetNode, release_handler, install_release, [Vsn], ?TIMEOUT) of + {ok, _, _} -> + ?INFO(\"Installed Release: ~s~n\", [Vsn]), + permafy(TargetNode, Vsn), + ok; + {error, {no_such_release, Vsn}} -> + VerList = + iolist_to_binary( + [io_lib:format(\"* ~s\t~s~n\",[V,S]) || {V,S} <- which_releases(TargetNode)]), + ?INFO(\"Installed versions:~n~s\", [VerList]), + ?INFO(\"ERROR: Unable to revert to '~s' - not installed.~n\", [Vsn]), + init:stop(2) + end. + +permafy(TargetNode, Vsn) -> + ok = rpc:call(TargetNode, release_handler, make_permanent, [Vsn], ?TIMEOUT), + ?INFO(\"Made release permanent: ~p~n\", [Vsn]), + ok. + +which_releases(TargetNode) -> + R = rpc:call(TargetNode, release_handler, which_releases, [], ?TIMEOUT), + [ {V, S} || {_,V,_, S} <- R ]. + +print_existing_versions(TargetNode) -> + VerList = iolist_to_binary([ + io_lib:format(\"* ~s\t~s~n\",[V,S]) + || {V,S} <- which_releases(TargetNode) ]), + ?INFO(\"Installed versions:~n~s\", [VerList]). + start_distribution(NodeName, Cookie) -> MyNode = make_script_node(NodeName), {ok, _Pid} = net_kernel:start([MyNode, longnames]), @@ -980,6 +1035,8 @@ start_distribution(NodeName, Cookie) -> io:format(\"Node ~p not responding to pings.\n\", [TargetNode]), init:stop(1) end, + {ok, Cwd} = file:get_cwd(), + ok = rpc:call(TargetNode, file, set_cwd, [Cwd], ?TIMEOUT), TargetNode. make_script_node(Node) -> -- cgit v1.2.3 From 5aed98f9dd5be82afce965987f815f45909ec000 Mon Sep 17 00:00:00 2001 From: RJ Date: Fri, 20 Sep 2013 15:30:00 +0100 Subject: Ensure exit codes propagate properly during upgrades --- src/rlx_prv_assembler.erl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/rlx_prv_assembler.erl') diff --git a/src/rlx_prv_assembler.erl b/src/rlx_prv_assembler.erl index 4834591..a61d557 100644 --- a/src/rlx_prv_assembler.erl +++ b/src/rlx_prv_assembler.erl @@ -874,7 +874,7 @@ case \"$1\" in node_name=`echo $NAME_ARG | awk '{print $2}'` erlang_cookie=`echo $COOKIE_ARG | awk '{print $2}'` - $ERTS_DIR/bin/escript $ERTS_DIR/bin/install_upgrade.escript $REL_NAME $node_name $erlang_cookie $2 + exec $ERTS_DIR/bin/escript $ERTS_DIR/bin/install_upgrade.escript $REL_NAME $node_name $erlang_cookie $2 ;; console|console_clean|console_boot) @@ -964,7 +964,7 @@ main([RelName, NodeName, Cookie, VersionArg]) -> {error, UnpackReason} -> print_existing_versions(TargetNode), ?INFO(\"Unpack failed: ~p~n\",[UnpackReason]), - init:stop(2) + erlang:halt(2) end; old -> %% no need to unpack, has been installed previously @@ -980,7 +980,7 @@ main([RelName, NodeName, Cookie, VersionArg]) -> ?INFO(\"Release ~s is already installed, and set permanent.~n\",[Version]) end; main(_) -> - init:stop(1). + erlang:halt(1). parse_version(V) when is_list(V) -> hd(string:tokens(V,\"/\")). @@ -991,7 +991,7 @@ install_and_permafy(TargetNode, Vsn) -> ok; {error, Reason} -> ?INFO(\"ERROR: release_handler:check_install_release failed: ~p~n\",[Reason]), - init:stop(3) + erlang:halt(3) end, case rpc:call(TargetNode, release_handler, install_release, [Vsn], ?TIMEOUT) of {ok, _, _} -> @@ -1004,7 +1004,7 @@ install_and_permafy(TargetNode, Vsn) -> [io_lib:format(\"* ~s\t~s~n\",[V,S]) || {V,S} <- which_releases(TargetNode)]), ?INFO(\"Installed versions:~n~s\", [VerList]), ?INFO(\"ERROR: Unable to revert to '~s' - not installed.~n\", [Vsn]), - init:stop(2) + erlang:halt(2) end. permafy(TargetNode, Vsn) -> @@ -1033,7 +1033,7 @@ start_distribution(NodeName, Cookie) -> ok; {_, pang} -> io:format(\"Node ~p not responding to pings.\n\", [TargetNode]), - init:stop(1) + erlang:halt(1) end, {ok, Cwd} = file:get_cwd(), ok = rpc:call(TargetNode, file, set_cwd, [Cwd], ?TIMEOUT), -- cgit v1.2.3