From 8eb20d1fb0eb3a3b96d5e80e2e2617f893ef6986 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Thu, 20 Feb 2014 16:45:28 +0100 Subject: Add info about upgrade of core applications In ref man for appup and in system documentation, design prinsiples, add a warning related to upgrade when version of erts, kernel, stdlib or sasl is changed. This will cause an emulator restart where new version of emulator and core applications will startup together with old versions of other applications. Care must be taken to avoid problems due to backwards incompatibility. --- lib/sasl/doc/src/appup.xml | 23 ++++++++++++++++++++--- system/doc/design_principles/release_handling.xml | 17 +++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml index 85fcbed3ba..95f315d269 100644 --- a/lib/sasl/doc/src/appup.xml +++ b/lib/sasl/doc/src/appup.xml @@ -4,7 +4,7 @@
- 19972013 + 19972014 Ericsson AB. All Rights Reserved. @@ -84,6 +84,9 @@ version identifier must be specified as a binary, e.g.

<<"2\\.1\\.[0-9]+">>

will match all versions 2.1.x, where x is any number.

+

Note that the regular expression must match the complete + version string, so the above example will work for for + e.g. 2.1.1, but not for 2.1.1.1

@@ -339,7 +342,7 @@ restart_new_emulator version of erts, kernel, stdlib and sasl are used when the emulator restarts. Only one restart_new_emulator instruction is allowed in the relup, and it shall be placed - first. systools:make_relup3,4 + first. systools:make_relup/3,4 will ensure this when the relup is generated. The rest of the relup script is executed after the restart as a part of the boot script.

@@ -347,11 +350,25 @@ restart_new_emulator completed. To programatically find out if the upgrade is complete, call - release_handler:which_releases and check if the + release_handler:which_releases/0,1 and check if the expected release has status current.

The new release must still be made permanent after the upgrade is completed. Otherwise, the old emulator is started in case of an emulator restart.

+ +

As stated above, the restart_new_emulator + instruction causes the emulator to be restarted with new + versions of erts, kernel, stdlib and + sasl. All other applications, however, will at startup + be running their old versions in this new emulator. In most + cases this is no problem, but every now and then there will be + incompatible changes to the core applications which may cause + trouble in this setting. Such incompatible changes (when + functions are removed) are normally preceded by a deprecation + over two major releases. To make sure your application is not + crashed by an incompatible change, always remove any call to + deprecated functions as soon as possible.

+
 restart_emulator
     
diff --git a/system/doc/design_principles/release_handling.xml b/system/doc/design_principles/release_handling.xml index 2a5831b89f..ba8a88d1c2 100644 --- a/system/doc/design_principles/release_handling.xml +++ b/system/doc/design_principles/release_handling.xml @@ -4,7 +4,7 @@
- 20032013 + 20032014 Ericsson AB. All Rights Reserved. @@ -329,13 +329,26 @@ automatically ensured.

When the release handler encounters the instruction, it first generates a temporary boot file, which starts the new versions - of the emulator and the core applications. Then it shuts down + of the emulator and the core applications, and the old version + of all other applications. Then it shuts down the current emulator by calling init:reboot(), see init(3). All processes are terminated gracefully and the system is rebooted by the heart program, using the temporary boot file. After the reboot, the rest of the relup instructions are executed. This is done as a part of the temporary boot script.

+ +

Since this mechanism causes the new versions of the + emulator and core applications to run with the old version of + other applications during startup, extra care must be taken to + avoid incompatibility. Incompatible changes in the core + applications may in some situations be necessary. If possible, + such changes are preceded by deprecation over two major + releases before the actual change. To make sure your + application is not crashed by an incompatible change, always + remove any call to deprecated functions as soon as + possible.

+

An info report is written when the upgrade is completed. To programatically find out if the upgrade is complete, call release_handler:which_releases(current) and check -- cgit v1.2.3 From c65821b677b4ebbc05192da9b8a48d32e53b3cfe Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Wed, 19 Feb 2014 17:24:27 +0100 Subject: Add documentation about upgrade The example of how to create a first target system, which is located in the System Principles document, is now extended to also include an example of code upgrade. A new chapter is added to System Principles explaining different issues when upgrade includes new versions applications within Erlang/OTP. --- lib/sasl/examples/src/target_system.erl | 16 +- system/doc/system_principles/create_target.xmlsrc | 248 +++++++++++++++++++--- system/doc/system_principles/part.xml | 4 +- system/doc/system_principles/upgrade.xml | 118 ++++++++++ system/doc/system_principles/xmlfiles.mk | 3 +- 5 files changed, 359 insertions(+), 30 deletions(-) create mode 100644 system/doc/system_principles/upgrade.xml diff --git a/lib/sasl/examples/src/target_system.erl b/lib/sasl/examples/src/target_system.erl index fb9e9aaaaf..a0ae016791 100644 --- a/lib/sasl/examples/src/target_system.erl +++ b/lib/sasl/examples/src/target_system.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2013. All Rights Reserved. +%% Copyright Ericsson AB 2011-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -65,7 +65,7 @@ create(RelFileName,SystoolsOpts) -> [RelFileName, RelFileName]), make_script(RelFileName,SystoolsOpts), - TarFileName = filename:join(Dir,RelFileName ++ ".tar.gz"), + TarFileName = RelFileName ++ ".tar.gz", io:fwrite("Creating tar file ~tp ...~n", [TarFileName]), make_tar(RelFileName,SystoolsOpts), @@ -100,6 +100,12 @@ create(RelFileName,SystoolsOpts) -> copy_file(filename:join([ErtsBinDir, "to_erl"]), filename:join([TmpBinDir, "to_erl"]), [preserve]), + %% This is needed if 'start' script created from 'start.src' shall + %% be used as it points out this directory as log dir for 'run_erl' + TmpLogDir = filename:join([TmpDir, "log"]), + io:fwrite("Creating temporary directory ~tp ...~n", [TmpLogDir]), + ok = file:make_dir(TmpLogDir), + StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]), io:fwrite("Creating ~tp ...~n", [StartErlDataFile]), StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]), @@ -115,6 +121,7 @@ create(RelFileName,SystoolsOpts) -> erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []), erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []), erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []), + erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []), erl_tar:close(Tar), %% file:set_cwd(Cwd), io:fwrite("Removing directory ~tp ...~n",[TmpDir]), @@ -136,6 +143,11 @@ install(RelFileName, RootDir) -> subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir, [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}], [preserve]), + %%! Workaround for pre OTP 17.0: start.src and start_erl.src did + %%! not have correct permissions, so the above 'preserve' option did not help + ok = file:change_mode(filename:join(BinDir,"start"),8#0755), + ok = file:change_mode(filename:join(BinDir,"start_erl"),8#0755), + io:fwrite("Creating the RELEASES file ...\n"), create_RELEASES(RootDir, filename:join([RootDir, "releases", filename:basename(RelFileName)])). diff --git a/system/doc/system_principles/create_target.xmlsrc b/system/doc/system_principles/create_target.xmlsrc index fbc935d708..b5f8d8ac4d 100644 --- a/system/doc/system_principles/create_target.xmlsrc +++ b/system/doc/system_principles/create_target.xmlsrc @@ -4,7 +4,7 @@

- 20022013 + 20022014 Ericsson AB. All Rights Reserved. @@ -21,7 +21,7 @@ - Creating a First Target System + Creating and Upgrading a Target System Peter Högfeldt @@ -71,23 +71,24 @@
+ Creating a Target System

It is assumed that you have a working Erlang/OTP system structured according to the OTP Design Principles.

-

Step 1. First create a .rel file (see - rel(4)) that specifies the erts version - and lists all applications that should be included in the new - basic target system. An example is the following +

Step 1. First create a .rel file (see rel(4)) that specifies the erts + version and lists all applications that should be included in the + new basic target system. An example is the following mysystem.rel file:

%% mysystem.rel {release, {"MYSYSTEM", "FIRST"}, - {erts, "5.1"}, - [{kernel, "2.7"}, - {stdlib, "1.10"}, - {sasl, "1.9.3"}, - {pea, "1.0"}]}. + {erts, "5.10.4"}, + [{kernel, "2.16.4"}, + {stdlib, "1.19.4"}, + {sasl, "2.3.4"}, + {pea, "1.0"}]}.

The listed applications are not only original Erlang/OTP applications but possibly also new applications that you have written yourself (here examplified by the application @@ -116,13 +117,13 @@ os> erl -pa /home/user/target_system/myapps/pea-1.0/ebin systools:make_tar/2. That file has the following contents:

-erts-5.1/bin/ +erts-5.10.4/bin/ releases/FIRST/start.boot releases/FIRST/mysystem.rel releases/mysystem.rel -lib/kernel-2.7/ -lib/stdlib-1.10/ -lib/sasl-1.9.3/ +lib/kernel-2.16.4/ +lib/stdlib-1.19.4/ +lib/sasl-2.3.4/ lib/pea-1.0/

The file releases/FIRST/start.boot is a copy of our mysystem.boot

@@ -142,16 +143,19 @@ lib/pea-1.0/ Creates the temporary directory tmp and extracts the tar file mysystem.tar.gz into that directory. Deletes the erl and start files from - tmp/erts-5.1/bin. These files will be created again from + tmp/erts-5.10.4/bin. These files will be created again from source when installing the release. Creates the directory tmp/bin. Copies the previously created file plain.boot to tmp/bin/start.boot. Copies the files epmd, run_erl, and - to_erl from the directory tmp/erts-5.1/bin to + to_erl from the directory tmp/erts-5.10.4/bin to the directory tmp/bin. + Creates the directory tmp/log, which will be used + if the system is started as embedded with the bin/start + script. Creates the file tmp/releases/start_erl.data with - the contents "5.1 FIRST". This file is to be passed as data + the contents "5.10.4 FIRST". This file is to be passed as data file to the start_erl script. Recreates the file mysystem.tar.gz from the directories @@ -171,11 +175,11 @@ lib/pea-1.0/ Extracts the tar file mysystem.tar.gz into the target directory /usr/local/erl-target. In the target directory reads the file releases/start_erl.data - in order to find the Erlang runtime system version ("5.1"). + in order to find the Erlang runtime system version ("5.10.4"). Substitutes %FINAL_ROOTDIR% and %EMU% for /usr/local/erl-target and beam, respectively, in the files erl.src, start.src, and - start_erl.src of the target erts-5.1/bin + start_erl.src of the target erts-5.10.4/bin directory, and puts the resulting files erl, start, and run_erl in the target bin directory. @@ -185,6 +189,7 @@ lib/pea-1.0/
+ Starting a Target System

Now we have a target system that can be started in various ways.

We start it as a basic target system by invoking

@@ -193,7 +198,7 @@ os> /usr/local/erl-target/bin/erl

where only the kernel and stdlib applications are started, i.e. the system is started as an ordinary development system. There are only two files needed for all this to work: - bin/erl file (obtained from erts-5.1/bin/erl.src) + bin/erl file (obtained from erts-5.10.4/bin/erl.src) and the bin/start.boot file (a copy of plain.boot).

We can also start a distributed system (requires bin/epmd).

To start all applications specified in the original @@ -208,9 +213,10 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI bin/run_erl, which in turn calls bin/start_erl (roughly, start_erl is an embedded variant of erl).

-

The shell script start is only an example. You should - edit it to suite your needs. Typically it is executed when the - UNIX system boots.

+

The shell script start, which is generated from + erts-5.10.4/bin/start.src during installation, is only an + example. You should edit it to suite your needs. Typically it is + executed when the UNIX system boots.

run_erl is a wrapper that provides logging of output from the run-time system to file. It also provides a simple mechanism for attaching to the Erlang shell (to_erl).

@@ -218,7 +224,7 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI ("/usr/local/erl-target"), the releases directory ("/usr/local/erl-target/releases"), and the location of the start_erl.data file. It reads the run-time system - version ("5.1") and release version ("FIRST") from + version ("5.10.4") and release version ("FIRST") from the start_erl.data file, starts the run-time system of the version found, and provides -boot flag specifying the boot file of the release version found @@ -257,6 +263,198 @@ os> /usr/local/erl-target/bin/erl -boot /usr/local/erl-target/releases/FI dependent files.

+
+ Creating the Next Version + +

+ In this example the pea application has been changed, and + so are erts, kernel, stdlib and + sasl. +

+ +

+ Step 1. Create the .rel file: +

+ +%% mysystem2.rel +{release, + {"MYSYSTEM", "SECOND"}, + {erts, "6.0"}, + [{kernel, "3.0"}, + {stdlib, "2.0"}, + {sasl, "2.4"}, + {pea, "2.0"}]}. +

+ Step 2. Create the application upgrade file (see + appup(4)) for pea, + for example: +

+ +%% pea.appup +{"2.0", + [{"1.0",[{load_module,pea_lib}]}], + [{"1.0",[{load_module,pea_lib}]}]}. +

+ Step 3. From the directory where the + mysystem2.rel file reside, start the Erlang/OTP system: +

+
+os> erl -pa /home/user/target_system/myapps/pea-2.0/ebin
+

giving the path to the new version of pea.

+ +

+ Step 4. Create the release upgrade file (see relup(4)): +

+
+1> systools:make_relup("mysystem2",["mysystem"],["mysystem"],[{path,["/home/user/target_system/myapps/pea-1.0/ebin","/my/old/erlang/lib/*/ebin"]}]).
+

+ where "mysystem" is the base release and + "mysystem2" is the release to upgrade to. +

+

+ Note that the path option is used for pointing out the + old version of all applications. (The new versions are already + in the code path - assuming of course that the erlang node on + which this is executed is running the correct version of + Erlang/OTP.) +

+

+ Step 5. Create the new release: +

+
+2> target_system:create("mysystem2").
+

+ Given that the relup file generated in step 4 above is + now located in the current directory, it will automatically be + included in the release package. +

+
+ +
+ Upgrading the Target System +

+ This part is done on the target node, and for this example we + want the node to be running as an embedded system with the + -heart option, allowing automatic restart of the + node. See Starting a Target + System above for more information. +

+

+ We add -heart to bin/start: +

+ +#!/bin/sh +ROOTDIR=/usr/local/erl-target/ + +if [ -z "$RELDIR" ] +then + RELDIR=$ROOTDIR/releases +fi + +START_ERL_DATA=${1:-$RELDIR/start_erl.data} + +$ROOTDIR/bin/run_erl -daemon /tmp/ $ROOTDIR/log "exec $ROOTDIR/bin/start_erl $ROOTDIR $RELDIR $START_ERL_DATA -heart +

+ And we use the simplest possible sys.config, which we + store in releases/FIRST: +

+ +%% sys.config +[]. +

+ Finally, in order to prepare the upgrade, we need to put the new + release package in the releases directory of the first + target system: +

+
+os> cp mysystem2.tar.gz /usr/local/erl-target/releases
+

+ And assuming that the node has been started like this: +

+
+os> /usr/local/erl-target/bin/start
+

+ it can be accessed like this: +

+
+os> /usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.1
+

+ Also note that logs can be found in + /usr/local/erl-target/log. This directory is specified as + an argument to run_erlin the start script listed above. +

+

+ Step 1. Unpack the release: +

+
+1> {ok,Vsn} = release_handler:unpack_release("mysystem2").
+

+ Step 2. Install the release: +

+
+2> release_handler:install_release(Vsn).
+{continue_after_restart,"FIRST",[]}
+heart: Tue Apr  1 12:15:10 2014: Erlang has closed.
+heart: Tue Apr  1 12:15:11 2014: Executed "/usr/local/erl-target/bin/start /usr/local/erl-target/releases/new_start_erl.data" -> 0. Terminating.
+[End]
+

+ The above return value and output after the call to + release_handler:install_release/1 means that the + release_handler has restarted the node by using + heart. This will always be done when the upgrade involves + a change of erts, kernel, stdlib or + sasl. See Upgrade when + Erlang/OTP has Changed for more infomation about this. +

+

+ The node will be accessable via a new pipe: +

+
+os> /usr/local/erl-target/bin/to_erl /tmp/erlang.pipe.2
+

+ Let's see which releases we have in our system: +

+
+1> release_handler:which_releases().
+[{"MYSYSTEM","SECOND",
+  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
+  current},
+ {"MYSYSTEM","FIRST",
+  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
+  permanent}]
+

+ Our new release, "SECOND", is now the current release, but we + can also see that our "FIRST" release is still permanent. This + means that if the node would be restarted at this point, it + would come up running the "FIRST" release again. +

+

+ Step 3. Make the new release permanent: +

+
+2> release_handler:make_permanent("SECOND").
+ +

+ Now look at the releases again: +

+ +
+3> release_handler:which_releases().
+[{"MYSYSTEM","SECOND",
+  ["kernel-3.0","stdlib-2.0","sasl-2.4","pea-2.0"],
+  permanent},
+ {"MYSYSTEM","FIRST",
+  ["kernel-2.16.4","stdlib-1.19.4","sasl-2.3.4","pea-1.0"],
+  old}]
+ +

+ Here we see that the new release version is permanent, so + it would be safe to restart the node. +

+ +
+
Listing of target_system.erl

This module can also be found in the examples directory diff --git a/system/doc/system_principles/part.xml b/system/doc/system_principles/part.xml index 811428baae..d05c89fde8 100644 --- a/system/doc/system_principles/part.xml +++ b/system/doc/system_principles/part.xml @@ -4,7 +4,7 @@

- 19972013 + 19972014 Ericsson AB. All Rights Reserved. @@ -31,6 +31,6 @@ + - diff --git a/system/doc/system_principles/upgrade.xml b/system/doc/system_principles/upgrade.xml new file mode 100644 index 0000000000..68e48da0b8 --- /dev/null +++ b/system/doc/system_principles/upgrade.xml @@ -0,0 +1,118 @@ + + + + +
+ + 2014 + Ericsson AB. All Rights Reserved. + + + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + + + Upgrade when Erlang/OTP has Changed + + + + + + 2014-02-19 + + upgrade.xml +
+ +
+ Introduction +

+ As of Erlang/OTP 17, most applications deliver a valid + application upgrade (appup) file. In earlier releases, a + majority of the applications in Erlang/OTP did not support + upgrade at all. Many of the applications use the + restart_application instruction. These are applications + for which it is not crucial to support real soft upgrade, for + instance tools and library applications. The + restart_application instruction + ensures that all modules in the application are reloaded and + thereby running the new code. +

+
+ +
+ Upgrade of core applications +

+ The core applications ERTS, Kernel, STDLIB + and SASL never allow real soft upgrade, but require the + Erlang emulator to be restarted. This is indicated to the + release_handler by the upgrade instruction + restart_new_emulator. This instruction will always be the + very first instruction executed, and it will restart the + emulator with the new versions of the above mentioned core + applications and the old versions of all other + applications. When the node is back up all other upgrade instructions are + executed, making sure each application is finally running its + new version. +

+ +

+ It might seem strange to do a two-step upgrade instead of + just restarting the emulator with the new version of all + applications. The reason for this design decision is to allow + code_change functions to have side effects, for example changing + data on disk. It also makes sure that the upgrade mechanism for + non-core applications does not differ depending on whether or not + core applications are changed at the same time. +

+ +

+ If, however, the more brutal variant is preferred, it is + possible to handwrite the release upgrade file using only the + single upgrade instruction restart_emulator. This + instruction, in contrast to restart_new_emulator, will + cause the emulator to restart with the new versions of + all applications. +

+ +

+ Note that if other instructions are included before + restart_emulator in the handwritten relup file, + they will be executed in the old emulator. This is a big risk + since there is no guarantee that new beam code can be loaded + into the old emulator. Adding instructions after + restart_emulator has no effect as the + release_handler will not do any attempt at executing + them. +

+ +

+ See relup(4) for + information about the release upgrade file, and appup(4) for further information + about upgrade instructions. +

+
+ +
+ Applications that still do not allow code upgrade +

+ A few applications, for instance HiPE do not support + upgrade at all. This is indicated by an application upgrade file + containing only {Vsn,[],[]}. Any attempt at creating a release + upgrade file with such input will fail. + The only way to force an upgrade involving applications like this is to + handwrite the relup file, preferably as described above + with only the restart_emulator instruction. +

+ +
+
diff --git a/system/doc/system_principles/xmlfiles.mk b/system/doc/system_principles/xmlfiles.mk index 9743949798..c60ffbad28 100644 --- a/system/doc/system_principles/xmlfiles.mk +++ b/system/doc/system_principles/xmlfiles.mk @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009. All Rights Reserved. +# Copyright Ericsson AB 2009-2014. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -20,4 +20,5 @@ SYSTEM_PRINCIPLES_CHAPTER_FILES = \ system_principles.xml \ error_logging.xml \ create_target.xml \ + upgrade.xml \ versions.xml -- cgit v1.2.3