diff --git a/config.conf.example b/config.conf.example index 42acfec7..8223613d 100644 --- a/config.conf.example +++ b/config.conf.example @@ -44,6 +44,10 @@ low_speed_rate = 0 # reboot after a successful update post_update_reboot = false + +# close(finish) update action after a successful update +post_update_close = true + # debug, info, message, critical, error, fatal log_level = message diff --git a/docs/reference.rst b/docs/reference.rst index feff426d..cf7bc855 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -140,6 +140,11 @@ Optional options: manager and without terminating any processes or unmounting any file systems. This may result in data loss. +``post_update_close=`` + Whether to close/finish update action after a successful update. + Disabling allows an external program to determine if update is finish. + Defaults to ``true``. + ``log_level=`` Log level to print, where ``level`` is a string of diff --git a/include/config-file.h b/include/config-file.h index a2df87fe..8e7b914d 100644 --- a/include/config-file.h +++ b/include/config-file.h @@ -16,6 +16,7 @@ typedef struct Config_ { gboolean ssl; /**< use https or http */ gboolean ssl_verify; /**< verify https certificate */ gboolean post_update_reboot; /**< reboot system after successful update */ + gboolean post_update_close; /**< close(finish) update action after a successful update */ gboolean resume_downloads; /**< resume downloads or not */ gboolean stream_bundle; /**< streaming installation or not */ gchar* auth_token; /**< hawkBit target security token */ diff --git a/src/config-file.c b/src/config-file.c index d09aebca..0a16e16e 100644 --- a/src/config-file.c +++ b/src/config-file.c @@ -18,6 +18,7 @@ static const gint DEFAULT_RETRY_WAIT = 5 * 60; // 5 min. static const gboolean DEFAULT_SSL = TRUE; static const gboolean DEFAULT_SSL_VERIFY = TRUE; static const gboolean DEFAULT_REBOOT = FALSE; +static const gboolean DEFAULT_CLOSE = TRUE; static const gchar* DEFAULT_LOG_LEVEL = "message"; /** @@ -309,6 +310,9 @@ Config* load_config_file(const gchar *config_file, GError **error) if (!get_key_bool(ini_file, "client", "post_update_reboot", &config->post_update_reboot, DEFAULT_REBOOT, error)) return NULL; + if (!get_key_bool(ini_file, "client", "post_update_close", + &config->post_update_close, DEFAULT_CLOSE, error)) + return NULL; if (config->timeout > 0 && config->connect_timeout > 0 && config->timeout < config->connect_timeout) { diff --git a/src/hawkbit-client.c b/src/hawkbit-client.c index dca518bf..79e38db1 100644 --- a/src/hawkbit-client.c +++ b/src/hawkbit-client.c @@ -798,17 +798,22 @@ gboolean install_complete_cb(gpointer ptr) g_mutex_lock(&active_action->mutex); - active_action->state = result->install_success ? ACTION_STATE_SUCCESS : ACTION_STATE_ERROR; - feedback_url = build_api_url("deploymentBase/%s/feedback", active_action->id); - res = feedback( - feedback_url, active_action->id, - result->install_success ? "Software bundle installed successfully." - : "Failed to install software bundle.", - result->install_success ? "success" : "failure", - "closed", &error); - - if (!res) - g_warning("%s", error->message); + if (hawkbit_config->post_update_close || !result->install_success) { + active_action->state = result->install_success ? ACTION_STATE_SUCCESS : ACTION_STATE_ERROR; + feedback_url = build_api_url("deploymentBase/%s/feedback", active_action->id); + res = feedback( + feedback_url, active_action->id, + result->install_success ? "Software bundle installed successfully." + : "Failed to install software bundle.", + result->install_success ? "success" : "failure", + "closed", &error); + + if (!res) + g_warning("%s", error->message); + } + else { + g_message("%s", "Software bundle installed successfully."); + } process_deployment_cleanup(); g_mutex_unlock(&active_action->mutex); diff --git a/test/test_install.py b/test/test_install.py index 7f449fe0..2e7bfce4 100644 --- a/test/test_install.py +++ b/test/test_install.py @@ -69,6 +69,34 @@ def test_install_success(hawkbit, install_config, bundle_assigned, rauc_dbus_ins status = hawkbit.get_action_status() assert status[0]['type'] == 'finished' +@pytest.mark.parametrize('mode', ('download', 'streaming')) +def test_install_success_without_close(hawkbit, adjust_config, bundle_assigned, rauc_dbus_install_success, mode): + """ + Assign bundle to target and test successful download and installation. Make sure installation + result is received correctly by hawkBit. + """ + + if mode == "streaming": + config = adjust_config( + {'client': {'stream_bundle': 'true', 'post_update_close': "false"}}, + remove={'client': 'bundle_download_location'}, + ) + else: + config = adjust_config({'client': {'post_update_close': "false"}}) + out, err, exitcode = run(f'rauc-hawkbit-updater -c "{config}" -r') + + assert 'New software ready for download' in out + + if mode == 'download': + assert 'Download complete' in out + + assert 'Software bundle installed successfully.' in out + assert err == '' + assert exitcode == 0 + + status = hawkbit.get_action_status() + assert status[0]['type'] == 'running' + @pytest.mark.parametrize('mode', ('download', 'streaming')) def test_install_failure(hawkbit, install_config, bundle_assigned, rauc_dbus_install_failure, mode): """