aboutsummaryrefslogtreecommitdiffstats
path: root/src/rlx_prv_assembler.erl
diff options
context:
space:
mode:
authorRJ <[email protected]>2013-09-20 10:22:07 +0000
committerTristan Sloughter <[email protected]>2013-09-20 20:07:38 -0500
commit963909d6a3793a4b0aec71d282f9246f605070ef (patch)
tree0f4c915328bf2a79e9c3bc252a847680bc763e8c /src/rlx_prv_assembler.erl
parenta9cf1124f7d8d1333c79d542b900d3d0e12552c3 (diff)
downloadrelx-963909d6a3793a4b0aec71d282f9246f605070ef.tar.gz
relx-963909d6a3793a4b0aec71d282f9246f605070ef.tar.bz2
relx-963909d6a3793a4b0aec71d282f9246f605070ef.zip
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.
Diffstat (limited to 'src/rlx_prv_assembler.erl')
-rw-r--r--src/rlx_prv_assembler.erl109
1 files changed, 83 insertions, 26 deletions
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) ->