Skip to content

Commit

Permalink
Add register-driver option to UpdateDeployment D-Bus API
Browse files Browse the repository at this point in the history
Record the calling agent's systemd unit and serialize it into a
g-variant file at `/run/rpmostree/update-driver.gv`, along with the
human-readable name of the update driver provided as a string
argument.

Also add the companion `--register-driver` option to the `deploy`
CLI argument.

Closes coreos#1747.
  • Loading branch information
kelvinfan001 committed Jan 21, 2021
1 parent 7586503 commit bf02d33
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/app/rpmostree-builtin-deploy.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <libglnx.h>

static char *opt_osname;
static char *opt_register_driver;
static gboolean opt_reboot;
static gboolean opt_preview;
static gboolean opt_cache_only;
Expand All @@ -49,6 +50,7 @@ static GOptionEntry option_entries[] = {
{ "lock-finalization", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &opt_lock_finalization, "Prevent automatic deployment finalization on shutdown", NULL },
{ "disallow-downgrade", 0, 0, G_OPTION_ARG_NONE, &opt_disallow_downgrade, "Forbid deployment of chronologically older trees", NULL },
{ "unchanged-exit-77", 0, 0, G_OPTION_ARG_NONE, &opt_unchanged_exit_77, "If no new deployment made, exit 77", NULL },
{ "register-driver", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_register_driver, "Register the calling agent as the driver for updates. Takes a human-readable string as name for driver", "DRIVERNAME" },
{ NULL }
};

Expand Down Expand Up @@ -125,6 +127,8 @@ rpmostree_builtin_deploy (int argc,
g_variant_dict_insert (&dict, "download-only", "b", opt_download_only);
g_variant_dict_insert (&dict, "lock-finalization", "b", opt_lock_finalization);
g_variant_dict_insert (&dict, "initiating-command-line", "s", invocation->command_line);
if (opt_register_driver)
g_variant_dict_insert (&dict, "register-driver", "s", opt_register_driver);
g_autoptr(GVariant) options = g_variant_ref_sink (g_variant_dict_end (&dict));

/* Use newer D-Bus API only if we have to so we maintain coverage. */
Expand Down
3 changes: 3 additions & 0 deletions src/daemon/org.projectatomic.rpmostree1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@
Stop short of deploying the new tree. If layering packages,
the pkg diff is printed but packages are not downloaded or
imported.
"register-driver" (type 's')
Register the calling agent as the driver for updates. Takes
a human-readable string as the name for the update driver.
"no-layering" (type 'b')
Remove all package requests. Requests in "install-packages"
are still subsequently processed if specified.
Expand Down
6 changes: 6 additions & 0 deletions src/daemon/rpmostreed-daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ G_BEGIN_DECLS
#define DBUS_NAME "org.projectatomic.rpmostree1"
#define BASE_DBUS_PATH "/org/projectatomic/rpmostree1"

/* Update driver info */
#define RPMOSTREE_RUN_DIR "/run/rpm-ostree/"
#define RPMOSTREE_DRIVER_STATE RPMOSTREE_RUN_DIR "update-driver.gv"
#define RPMOSTREE_DRIVER_SD_UNIT "driver-sd-unit"
#define RPMOSTREE_DRIVER_NAME "driver-name"

GType rpmostreed_daemon_get_type (void) G_GNUC_CONST;
RpmostreedDaemon * rpmostreed_daemon_get (void);
gboolean rpmostreed_get_client_uid (RpmostreedDaemon *self,
Expand Down
122 changes: 122 additions & 0 deletions src/daemon/rpmostreed-transaction-types.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
#include "config.h"
#include "ostree.h"

#include <json-glib/json-glib.h>
#include <gio/gunixoutputstream.h>
#include <libglnx.h>
#include <systemd/sd-journal.h>

#include "rpmostreed-transaction-types.h"
#include "rpmostreed-transaction.h"
#include "rpmostreed-deployment-utils.h"
#include "rpmostreed-sysroot.h"
#include "rpmostreed-daemon.h"
#include "rpmostreed-errors.h"
#include "rpmostree-sysroot-upgrader.h"
#include "rpmostree-sysroot-core.h"
#include "rpmostree-rpm-util.h"
Expand Down Expand Up @@ -787,6 +791,117 @@ deploy_has_bool_option (DeployTransaction *self,
return vardict_lookup_bool (self->options, option, FALSE);
}

static const char *
deploy_has_string_option (DeployTransaction *self,
const char *option)
{
return static_cast<const char*>(vardict_lookup_ptr (self->options, option, "s"));
}

/* Write a state file which records information about the agent that is "driving" updates */
static gboolean
record_driver_info (RpmostreedTransaction *transaction,
const gchar *update_driver,
GCancellable *cancellable,
GError **error)
{
g_auto(GVariantBuilder) caller_info_builder;
g_variant_builder_init (&caller_info_builder, G_VARIANT_TYPE ("a{sv}"));

const char *sd_unit = rpmostreed_transaction_get_sd_unit (transaction);
if (!update_driver)
{
g_set_error (error, RPM_OSTREED_ERROR,
RPM_OSTREED_ERROR_FAILED, "update driver name not provided");
return FALSE;
}
g_variant_builder_add (&caller_info_builder, "{sv}", RPMOSTREE_DRIVER_NAME,
g_variant_new_string (update_driver));
if (!sd_unit)
{
g_set_error (error, RPM_OSTREED_ERROR,
RPM_OSTREED_ERROR_FAILED, "could not find caller systemd unit");
return FALSE;
}
g_variant_builder_add (&caller_info_builder, "{sv}", RPMOSTREE_DRIVER_SD_UNIT,
g_variant_new_string (sd_unit));

g_autoptr(GVariant) driver_info =
g_variant_ref_sink (g_variant_builder_end (&caller_info_builder));

if (!glnx_shutil_mkdir_p_at (AT_FDCWD, RPMOSTREE_RUN_DIR, 0755, cancellable, error))
return FALSE;
if (!glnx_file_replace_contents_at (AT_FDCWD, RPMOSTREE_DRIVER_STATE,
static_cast<const guint8*>(g_variant_get_data (driver_info)),
g_variant_get_size (driver_info),
static_cast<GLnxFileReplaceFlags>(0), cancellable, error))
return FALSE;

return TRUE;
}

gboolean
get_driver_g_variant (GVariant **driver_g_variant,
GError **error)
{
glnx_autofd int fd = -1;
g_autoptr(GError) local_error = NULL;
if (!glnx_openat_rdonly (AT_FDCWD, RPMOSTREE_DRIVER_STATE, TRUE, &fd,
&local_error))
{
if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
return g_propagate_error (error, util::move_nullify (local_error)), FALSE;
return TRUE;
}

g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, NULL, error);
if (!data)
return FALSE;

*driver_g_variant =
g_variant_ref_sink (g_variant_new_from_bytes (G_VARIANT_TYPE_VARDICT, data, FALSE));

return TRUE;
}

/* Read from state file that records information about the agent that is "driving" updates */
gboolean
get_driver_info (char **name,
char **sd_unit,
GError **error)
{
g_autoptr(GVariant) driver_g_variant = NULL;
if (!get_driver_g_variant (&driver_g_variant, error))
return FALSE;
if (!driver_g_variant)
return TRUE; // driver state file not found, return early.

g_auto(GVariantDict) driver_info_dict;
g_variant_dict_init (&driver_info_dict, driver_g_variant);
auto v = static_cast<char*>(vardict_lookup_ptr (&driver_info_dict,
RPMOSTREE_DRIVER_NAME, "s"));
if (!v)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"could not find update driver name in %s",
RPMOSTREE_DRIVER_STATE);
return FALSE;
}
*name = v;
v = static_cast<char*>(vardict_lookup_ptr (&driver_info_dict,
RPMOSTREE_DRIVER_SD_UNIT, "s"));
if (!v)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"could not find update driver systemd unit in %s",
RPMOSTREE_DRIVER_STATE);
return FALSE;
}
*sd_unit = v;

return TRUE;
}

static gboolean
deploy_transaction_execute (RpmostreedTransaction *transaction,
GCancellable *cancellable,
Expand All @@ -812,6 +927,7 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
const gboolean download_metadata_only =
((self->flags & RPMOSTREE_TRANSACTION_DEPLOY_FLAG_DOWNLOAD_METADATA_ONLY) > 0);
const gboolean allow_inactive = deploy_has_bool_option (self, "allow-inactive");
g_autofree const char *update_driver = deploy_has_string_option (self, "register-driver");

gboolean is_install = FALSE;
gboolean is_uninstall = FALSE;
Expand Down Expand Up @@ -1332,6 +1448,12 @@ deploy_transaction_execute (RpmostreedTransaction *transaction,
return FALSE;
changed = changed || layering_changed;

if (update_driver)
{
if (!record_driver_info (transaction, update_driver, cancellable, error))
return FALSE;
}

if (dry_run)
/* Note early return here; we printed the transaction already */
return TRUE;
Expand Down
9 changes: 9 additions & 0 deletions src/daemon/rpmostreed-transaction-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,12 @@ rpmostreed_transaction_new_kernel_arg (GDBusMethodInvocation *invocation,
GError **error);

G_END_DECLS

gboolean
get_driver_info (char **name,
char **sd_unit,
GError **error);

gboolean
get_driver_g_variant (GVariant **driver_g_variant,
GError **error);

0 comments on commit bf02d33

Please sign in to comment.