diff mbox series

[08/13] Introduce postfailure scripts

Message ID 20240221082221.11997-9-stefano.babic@swupdate.org
State Accepted
Delegated to: Stefano Babic
Headers show
Series Extend Lua Environemnt and post-failure scripts | expand

Commit Message

Stefano Babic Feb. 21, 2024, 8:22 a.m. UTC
These scripts run afet ran update fails. They can be used to restore the
system to a previous state before the Update was initiated. All scripts
will be executed, as it makes no sense to stop if one of them fails,
because the update state is already FAILURE.

Signed-off-by: Stefano Babic <stefano.babic@swupdate.org>
---
 core/stream_interface.c        | 13 +++++++++++++
 doc/source/sw-description.rst  | 20 +++++++++++++++++---
 handlers/lua_scripthandler.c   | 13 +++++++++++--
 handlers/shell_scripthandler.c |  3 +++
 4 files changed, 44 insertions(+), 5 deletions(-)

--
2.34.1
diff mbox series

Patch

diff --git a/core/stream_interface.c b/core/stream_interface.c
index b9bce6d7..5ebaca68 100644
--- a/core/stream_interface.c
+++ b/core/stream_interface.c
@@ -674,6 +674,19 @@  void *network_initializer(void *data)
 				update_transaction_state(software, STATE_FAILED);
 				notify(FAILURE, RECOVERY_ERROR, ERRORLEVEL, "Installation failed !");
 				inst.last_install = FAILURE;
+
+				/*
+				 * Try to run all POSTFAILURE scripts,
+				 * their result does not change the state that remains FAILURE
+				 * Goal is to restore to the state before update was started
+				 * if this is needed. This is a best case attempt, ERRORs
+				 * are just logged.
+				 */
+				if (!software->parms.dry_run) {
+					if (run_prepost_scripts(&software->scripts, POSTFAILURE)) {
+						WARN("execute POST FAILURE scripts return error, ignoring..");
+					}
+				}
 			} else {
 				/*
 				 * Clear the recovery variable to indicate to bootloader
diff --git a/doc/source/sw-description.rst b/doc/source/sw-description.rst
index b0363359..d4cb8971 100644
--- a/doc/source/sw-description.rst
+++ b/doc/source/sw-description.rst
@@ -759,7 +759,9 @@  with an error if the result is <> 0.
 They are copied into a temporary directory before execution and their name must
 be unique inside the same cpio archive.

-If no type is given, SWUpdate default to "lua".
+If no type is given, SWUpdate default to "lua". Please note that running a shell script
+opens a set of different security issues, check also chapter "Best practise".
+

 Lua
 ...
@@ -790,12 +792,24 @@  called before installing the images.

 	function postinst()

+
 SWUpdate scans for all scripts and check for a postinst function. It is
 called after installing the images.

+::
+
+	function postfailure()
+
+Only in case an update fails, SWUpdate scans for all scripts and check
+for a postfailure function. This could be useful in case it is necessary
+to restore a previous state, for example, in case the application was
+stop, it should run again.
+
 shellscript
 ...........

+SWUpdate will run the binary shell "/bin/sh" to execute the script.
+
 ::

 	scripts: (
@@ -805,9 +819,9 @@  shellscript
 		}
 	);

-Shell scripts are called via system command.
+Shell scripts are called by forking the process and running the shell as /bin/sh.
 SWUpdate scans for all scripts and calls them before and after installing
-the images. SWUpdate passes 'preinst' or 'postinst' as first argument to
+the images. SWUpdate passes 'preinst', 'postinst' or 'postfailure' as first argument to
 the script.
 If the data attribute is defined, its value is passed as the last argument(s)
 to the script.
diff --git a/handlers/lua_scripthandler.c b/handlers/lua_scripthandler.c
index 213099de..08479ef4 100644
--- a/handlers/lua_scripthandler.c
+++ b/handlers/lua_scripthandler.c
@@ -54,10 +54,19 @@  static int start_lua_script(struct img_type *img, void *data)

 	switch (script_data->scriptfn) {
 	case PREINSTALL:
-		fnname="preinst";
+		fnname = dict_get_value(&img->properties, "preinstall");
+		if (!fnname)
+			fnname="preinst";
 		break;
 	case POSTINSTALL:
-		fnname="postinst";
+		fnname = dict_get_value(&img->properties, "postinstall");
+		if (!fnname)
+			fnname="postinst";
+		break;
+	case POSTFAILURE:
+		fnname = dict_get_value(&img->properties, "postfailure");
+		if (!fnname)
+			fnname="postfailure";
 		break;
 	default:
 		/* no error, simply no call */
diff --git a/handlers/shell_scripthandler.c b/handlers/shell_scripthandler.c
index a85e8bb9..5602b98b 100644
--- a/handlers/shell_scripthandler.c
+++ b/handlers/shell_scripthandler.c
@@ -63,6 +63,9 @@  static int start_shell_script(struct img_type *img, void *data)
 	case POSTINSTALL:
 		fnname="postinst";
 		break;
+	case POSTFAILURE:
+		fnname="failure";
+		break;
 	default:
 		/* no error, simply no call */
 		return 0;