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

Upgrade agent #1368

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/app/rpmostree-dbus-helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
#include "rpmostree-util.h"
#include "rpmostree-rpm-util.h"

#define RPMOSTREE_CLI_ID "cli"

void
rpmostree_cleanup_peer (GPid *peer_pid)
{
Expand Down Expand Up @@ -211,6 +213,8 @@ rpmostree_load_sysroot (gchar *sysroot,
g_autoptr(GError) local_error = NULL;
g_autoptr(GVariantBuilder) options_builder =
g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (options_builder, "{sv}", "id",
g_variant_new_string (RPMOSTREE_CLI_ID));
g_autoptr(GVariant) res =
g_dbus_connection_call_sync (connection, bus_name, sysroot_objpath,
"org.projectatomic.rpmostree1.Sysroot",
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/org.projectatomic.rpmostree1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
to either invoke methods on the daemon, or monitor status.
If no clients are registered, the daemon may exit.

No options are currently defined.
'id (type 's') - Package/component name (e.g. `cockpit`, `gnome-software`)
-->
<method name="RegisterClient">
<arg type="a{sv}" name="options" direction="in"/>
Expand Down
93 changes: 82 additions & 11 deletions src/daemon/rpmostreed-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <libglnx.h>
#include <systemd/sd-journal.h>
#include <systemd/sd-login.h>
#include <systemd/sd-daemon.h>
#include <stdio.h>

Expand All @@ -35,6 +36,9 @@
#define DAEMON_CONFIG_GROUP "Daemon"
#define EXPERIMENTAL_CONFIG_GROUP "Experimental"

struct RpmOstreeClient;
static struct RpmOstreeClient *client_new (RpmostreedDaemon *self, const char *address, const char *id);

/**
* SECTION: daemon
* @title: RpmostreedDaemon
Expand Down Expand Up @@ -94,28 +98,46 @@ G_DEFINE_TYPE_WITH_CODE (RpmostreedDaemon, rpmostreed_daemon, G_TYPE_OBJECT,
rpmostreed_daemon_initable_iface_init))

struct RpmOstreeClient {
char *id;
char *address;
guint name_watch_id;
/* In Rust this'd be Option<uid_t> etc. */
gboolean uid_valid;
uid_t uid;
gboolean pid_valid;
pid_t pid;
char *sd_unit;
};

static void
rpmostree_client_free (struct RpmOstreeClient *client)
{
if (!client)
return;
g_free (client->id);
g_free (client->address);
g_free (client->sd_unit);
g_free (client);
}

static char *
rpmostree_client_to_string (struct RpmOstreeClient *client)
{
g_autoptr(GString) buf = g_string_new ("client ");
g_autoptr(GString) buf = g_string_new ("client(");
if (client->id)
g_string_append_printf (buf, "id:%s ", client->id);
/* Since DBus addresses have a leading ':', let's avoid another. Yeah it's not
* symmetric, but it does read better.
*/
g_string_append (buf, "dbus");
g_string_append (buf, client->address);
if (client->sd_unit)
g_string_append_printf (buf, " unit:%s", client->sd_unit);
if (client->uid_valid)
g_string_append_printf (buf, " (uid %lu)", (unsigned long) client->uid);
g_string_append_printf (buf, " uid:%lu", (unsigned long) client->uid);
else
g_string_append (buf, " (unknown uid)");
g_string_append (buf, " uid:<unknown>");
g_string_append_c (buf, ')');
return g_string_free (g_steal_pointer (&buf), FALSE);
}

Expand Down Expand Up @@ -223,16 +245,24 @@ on_active_txn_changed (GObject *object,
g_variant_get (active_txn, "(&s&s&s)", &method, &sender, &path);
if (*method)
{
g_autofree char *client_str = rpmostreed_daemon_client_get_string (self, sender);
struct RpmOstreeClient *clientdata = g_hash_table_lookup (self->bus_clients, sender);
struct RpmOstreeClient *clientdata_owned = NULL;
/* If the caller didn't register (e.g. Cockpit doesn't today),
* then let's gather the relevant client info now.
*/
if (!clientdata)
clientdata = clientdata_owned = client_new (self, sender, NULL);
g_autofree char *client_str = rpmostree_client_to_string (clientdata);
g_autofree char *client_data_msg = NULL;
if (clientdata && clientdata->uid_valid)
if (clientdata->uid_valid)
client_data_msg = g_strdup_printf ("CLIENT_UID=%u", clientdata->uid);
/* TODO: convert other client fields to structured log */
sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(RPMOSTREE_MESSAGE_TRANSACTION_STARTED),
"MESSAGE=Initiated txn %s for %s: %s", method, client_str, path,
"BUS_ADDRESS=%s", sender,
client_data_msg ?: NULL,
NULL);
rpmostree_client_free (clientdata_owned);
}
}

Expand Down Expand Up @@ -616,15 +646,59 @@ rpmostreed_get_client_uid (RpmostreedDaemon *self,
return TRUE;
}

static gboolean
get_client_pid (RpmostreedDaemon *self,
const char *client,
pid_t *out_pid)
{
g_autoptr(GError) local_error = NULL;
g_autoptr(GVariant) all = g_dbus_proxy_call_sync (self->bus_proxy,
"GetConnectionUnixProcessID",
g_variant_new ("(s)", client),
G_DBUS_CALL_FLAGS_NONE,
2000, NULL, &local_error);
if (!all)
{
sd_journal_print (LOG_WARNING, "Failed to GetConnectionUnixProcessID for client %s: %s",
client, local_error->message);
return FALSE;
}

g_variant_get (all, "(u)", out_pid);
return TRUE;
}

/* Given a DBus address, load metadata for it */
static struct RpmOstreeClient *
client_new (RpmostreedDaemon *self, const char *address,
const char *client_id)
{
struct RpmOstreeClient *client = g_new0 (struct RpmOstreeClient, 1);
client->address = g_strdup (address);
client->id = g_strdup (client_id);
if (rpmostreed_get_client_uid (self, address, &client->uid))
client->uid_valid = TRUE;
if (get_client_pid (self, address, &client->pid))
{
client->pid_valid = TRUE;
if (sd_pid_get_user_unit (client->pid, &client->sd_unit) == 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in your example, this returned session-1.scope for the cli. Would it (or the following call) return e.g. rpm-ostreed-automatic.service for the automatic updates timer?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep with this it looks like:

May 16 16:18:56 localhost.localdomain rpm-ostree[3390]: client(id:cli dbus:1.47 unit:rpm-ostreed-automatic.service uid:0) vanished; remaining=0

And now checked in a test ⬇️

{}
else if (sd_pid_get_unit (client->pid, &client->sd_unit) == 0)
{}
}

return g_steal_pointer (&client);
}

void
rpmostreed_daemon_add_client (RpmostreedDaemon *self,
const char *client)
const char *client,
const char *client_id)
{
if (g_hash_table_lookup (self->bus_clients, client))
return;

struct RpmOstreeClient *clientdata = g_new0 (struct RpmOstreeClient, 1);
clientdata->address = g_strdup (client);
struct RpmOstreeClient *clientdata = client_new (self, client, client_id);
clientdata->name_watch_id =
g_dbus_connection_signal_subscribe (self->connection,
"org.freedesktop.DBus",
Expand All @@ -637,9 +711,6 @@ rpmostreed_daemon_add_client (RpmostreedDaemon *self,
g_object_ref (self),
g_object_unref);

if (rpmostreed_get_client_uid (self, client, &clientdata->uid))
clientdata->uid_valid = TRUE;

g_hash_table_insert (self->bus_clients, (char*)clientdata->address, clientdata);
g_autofree char *clientstr = rpmostree_client_to_string (clientdata);
sd_journal_print (LOG_INFO, "%s added; new total=%u", clientstr, g_hash_table_size (self->bus_clients));
Expand Down
3 changes: 2 additions & 1 deletion src/daemon/rpmostreed-daemon.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ gboolean rpmostreed_get_client_uid (RpmostreedDaemon *self,
const char *client,
uid_t *out_uid);
void rpmostreed_daemon_add_client (RpmostreedDaemon *self,
const char *client);
const char *client,
const char *client_id);
void rpmostreed_daemon_remove_client (RpmostreedDaemon *self,
const char *client);
char * rpmostreed_daemon_client_get_string (RpmostreedDaemon *self,
Expand Down
9 changes: 6 additions & 3 deletions src/daemon/rpmostreed-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,11 +391,14 @@ handle_register_client (RPMOSTreeSysroot *object,
GDBusMethodInvocation *invocation,
GVariant *arg_options)
{
const char *sender;
sender = g_dbus_method_invocation_get_sender (invocation);
const char *sender = g_dbus_method_invocation_get_sender (invocation);
g_assert (sender);

rpmostreed_daemon_add_client (rpmostreed_daemon_get (), sender);
g_autoptr(GVariantDict) optdict = g_variant_dict_new (arg_options);
const char *client_id = NULL;
g_variant_dict_lookup (optdict, "id", "&s", &client_id);

rpmostreed_daemon_add_client (rpmostreed_daemon_get (), sender, client_id);
rpmostree_sysroot_complete_register_client (object, invocation);

return TRUE;
Expand Down
8 changes: 7 additions & 1 deletion tests/vmcheck/test-autoupdate-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,15 @@ vm_rpmostree status | grep 'auto updates enabled (check'

# build an *older version* and check that we don't report an update
vm_build_rpm layered-cake version 2.1 release 2
vm_rpmostree upgrade --trigger-automatic-update-policy
cursor=$(vm_get_journal_cursor)
vm_cmd systemctl start rpm-ostree-automatic.service
vm_wait_content_after_cursor $cursor 'Txn AutomaticUpdateTrigger.*successful'
vm_rpmostree status -v > out.txt
assert_not_file_has_content out.txt "Available update"
# And check the unit name https://github.com/projectatomic/rpm-ostree/pull/1368
vm_cmd journalctl -u rpm-ostreed --after-cursor ${cursor} > journal.txt
assert_file_has_content journal.txt 'client(id:cli.*unit:rpm-ostreed-automatic.service'
rm -f journal.txt

# build a *newer version* and check that we report an update
vm_build_rpm layered-cake version 2.1 release 4
Expand Down