Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial confirmationBase implementation #165

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions config.conf.example
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ post_update_reboot = false
# debug, info, message, critical, error, fatal
log_level = message

# Enable user-based confirmation (via DBus interface)
require_confirmation = true

# Every key / value under [device] is sent to HawkBit (target attributes),
# and can be used in target filter.
[device]
Expand Down
15 changes: 15 additions & 0 deletions data/de.pengutronix.rauc.InstallConfirmation.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<!-- This config allows anyone to control rauc -->
<!-- It is usually installed to /usr/share/dbus-1/system.d -->

<policy context="default">
<allow send_destination="de.pengutronix.rauc.InstallConfirmation"/>
</policy>

<policy user="root">
<allow own="de.pengutronix.rauc.InstallConfirmation"/>
</policy>
</busconfig>
6 changes: 6 additions & 0 deletions data/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
rauc_dbus_policy = configure_file(
input : 'de.pengutronix.rauc.InstallConfirmation.conf',
output : 'de.pengutronix.rauc.InstallConfirmation.conf',
copy : true
)
install_data(rauc_dbus_policy, install_dir : dbuspolicydir)
1 change: 1 addition & 0 deletions include/config-file.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ typedef struct Config_ {
gboolean post_update_reboot; /**< reboot system after successful update */
gboolean resume_downloads; /**< resume downloads or not */
gboolean stream_bundle; /**< streaming installation or not */
gboolean require_confirmation; /**< Use confirmationBase end point instead of deploymentBase */
gchar* auth_token; /**< hawkBit target security token */
gchar* gateway_token; /**< hawkBit gateway security token */
gchar* tenant_id; /**< hawkBit tenant id */
Expand Down
57 changes: 56 additions & 1 deletion include/hawkbit-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ enum ActionState {
ACTION_STATE_CANCEL_REQUESTED,
};

enum ConfirmationState {
CONFIRMATION_STATE_NONE,
CONFIRMATION_STATE_REQUESTED,
CONFIRMATION_STATE_CONFIRMED,
CONFIRMATION_STATE_DENIED,
};

/**
* @brief struct that contains the context of an HawkBit action.
*/
Expand All @@ -72,6 +79,16 @@ struct HawkbitAction {
GCond cond; /**< condition on state */
};

/**
* @brief struct that contains the context of a confirmation action.
*/
struct ConfirmationAction {
gchar *id; /**< HawkBit action id */
GMutex mutex; /**< mutex used for synchronization of the state */
GCond cond; /**< condition on confirmation */
enum ConfirmationState state; /**< current confirmation state */
};

/**
* @brief struct containing the payload and size of REST body.
*/
Expand All @@ -94,6 +111,14 @@ typedef struct Artifact_ {
gboolean do_install; /**< whether the installation should be started or not */
} Artifact;

/**
* @brief struct used to store active confirmation info
*/
typedef struct Confirmation_ {
gchar *action_id; /**< Hawkbit's ID of the request */
gchar *version; /**< software version */
} Confirmation;

/**
* @brief struct containing the new downloaded file.
*/
Expand All @@ -113,15 +138,37 @@ struct on_install_complete_userdata {
gboolean install_success; /**< status of installation */
};

/**
* @brief struct containing a confirmation request.
*/
struct on_install_confirmation_request_userdata {
GSourceFunc response_callback; /**< callback function to be called when response is received */
gchar *action_id; /**< Hawkbit's ID of the request */
gchar *version; /**< software version */
};

/**
* @brief struct containing a confirmation response from a user software
*/
struct on_install_confirmed_userdata {
gchar *action_id; /**< Hawkbit's ID of the request */
gboolean confirmed; /**< True - confirmed, False - denied */
gchar *details; /**< Explanation about confirmation status (if any) */
gint error_code; /**< Code to be returned to Hawkbit */
};

/**
* @brief Pass config, callback for installation ready and initialize libcurl.
* Intended to be called from program's main().
*
* @param[in] config Config* to make global
* @param[in] on_install_ready GSourceFunc to call after artifact download, to
* trigger RAUC installation
* @param[in] on_install_confirm GSourceFunc to call when confirmation status
* is received from a user
*/
void hawkbit_init(Config *config, GSourceFunc on_install_ready);
void hawkbit_init(Config *config, GSourceFunc on_install_ready,
GSourceFunc on_install_confirmed);

/**
* @brief Sets up timeout and event sources, initializes and runs main loop.
Expand Down Expand Up @@ -161,7 +208,15 @@ void rest_payload_free(RestPayload *payload);
*/
void artifact_free(Artifact *artifact);

/**
* @brief Frees the memory allocated by a Confirmation
*
* @param[in] confirmation Confirmation to free
*/
void confirmation_free(Confirmation *confirmation);

G_DEFINE_AUTOPTR_CLEANUP_FUNC(RestPayload, rest_payload_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Artifact, artifact_free)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(Confirmation, confirmation_free)

#endif // __HAWKBIT_CLIENT_H__
36 changes: 36 additions & 0 deletions include/rauc-install-confirmation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* SPDX-License-Identifier: LGPL-2.1-only
* SPDX-FileCopyrightText: 2023 Vyacheslav Yurkov <[email protected]>
*/

#ifndef __RAUC_INSTALL_CONFIRMATION_H__
#define __RAUC_INSTALL_CONFIRMATION_H__

#include <glib.h>

/**
* @brief struct that contains the context of an confirmation request.
*/
struct confirm_context {
GSourceFunc notify_confirm; /**< Callback function */
GMutex status_mutex; /**< Mutex used for accessing status_messages */
GMainLoop *mainloop; /**< Request's GMainLoop */
GMainContext *loop_context; /**< GMainContext for the GMainLoop */
gboolean confirmed; /**< Confirmation status: True - confirmed, False - denied */
gchar *action_id; /**< Hawkbit's Action ID */
gchar *new_version; /**< Version string requested to be installed */
gchar *details; /**< Optional detailed string explaining confirmation status */
gint error_code; /**< Optional error code */
};

/**
* @brief Request a confirmation about installation of a new version
*
* @param[in] action_id Internal action ID of the installation request. Response should use the same ID
* @param[in] version Version string of a new bundle. The client should have own rules how to compare
* different version strings.
* @param[in] on_confirm Callback function to be called when confirmation is issued
*/
void rauc_installation_confirm(const gchar *action_id, const gchar *version, GSourceFunc on_confirm);

#endif // __RAUC_INSTALL_CONFIRMATION_H__
19 changes: 19 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ incdir = include_directories('include')
sources_updater = [
'src/rauc-hawkbit-updater.c',
'src/rauc-installer.c',
'src/rauc-install-confirmation.c',
'src/config-file.c',
'src/hawkbit-client.c',
'src/json-helper.c',
Expand Down Expand Up @@ -52,6 +53,13 @@ if systemddep.found()
install_data('script/rauc-hawkbit-updater.service', install_dir : systemdsystemunitdir)
endif

datadir = get_option('datadir')

dbuspolicydir = get_option('dbuspolicydir')
if dbuspolicydir == ''
dbuspolicydir = datadir / 'dbus-1' / 'system.d'
endif

gnome = import('gnome')
dbus = 'rauc-installer-gen'
dbus_ifaces = files('src/rauc-installer.xml')
Expand All @@ -62,6 +70,15 @@ dbus_sources = gnome.gdbus_codegen(
namespace: 'R',
)

dbus_confirm_output = 'rauc-install-confirmation-gen'
dbus_confirm_iface = files('src/rauc-install-confirmation.xml')
dbus_confirm_sources = gnome.gdbus_codegen(
dbus_confirm_output,
sources : dbus_confirm_iface,
interface_prefix : 'de.pengutronix.rauc.',
namespace: 'R',
)

config_h = configure_file(
output : 'config.h',
configuration : conf
Expand All @@ -88,11 +105,13 @@ if doxygen.found()
)
endif

subdir('data')
subdir('docs')

executable('rauc-hawkbit-updater',
sources_updater,
dbus_sources,
dbus_confirm_sources,
config_h,
dependencies : [libcurldep, giodep, giounixdep, jsonglibdep, libsystemddep],
include_directories : incdir,
Expand Down
5 changes: 5 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ option(
type : 'string',
value : '',
description : 'Directory for systemd service files')
option(
'dbuspolicydir',
type : 'string',
value : '',
description : 'D-Bus policy directory')
3 changes: 3 additions & 0 deletions src/config-file.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,9 @@ Config* load_config_file(const gchar *config_file, GError **error)
return NULL;
if (!get_key_string(ini_file, "client", "log_level", &val, DEFAULT_LOG_LEVEL, error))
return NULL;
if (!get_key_bool(ini_file, "client", "require_confirmation", &config->require_confirmation, FALSE,
error))
return NULL;
config->log_level = log_level_from_string(val);

if (!get_key_bool(ini_file, "client", "post_update_reboot", &config->post_update_reboot, DEFAULT_REBOOT, error))
Expand Down
Loading
Loading