daemon: Add a separate OSExperimental interface

Just like `rpm-ostree ex`, for things like `ex livefs` that have DBus
interfaces, we should segregate these off so that people know they're unstable.
And conversely that they can test for the presence of the method on the main
interface for stability.

I initially tried having the same `RpmostreeOS` object implement both
but couldn't work out how to do that; see https://mail.gnome.org/archives/gtk-app-devel-list/2017-March/msg00161.html

Closes: #701
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-03-22 21:44:09 -04:00 committed by Atomic Bot
parent 1969b96f91
commit 3e833659b7
8 changed files with 228 additions and 13 deletions

View File

@ -43,6 +43,8 @@ librpmostreed_la_SOURCES = \
src/daemon/rpmostree-package-variants.c \
src/daemon/rpmostreed-os.h \
src/daemon/rpmostreed-os.c \
src/daemon/rpmostreed-os-experimental.h \
src/daemon/rpmostreed-os-experimental.c \
$(NULL)
librpmostreed_la_CFLAGS = \

View File

@ -223,6 +223,16 @@
</interface>
<interface name="org.projectatomic.rpmostree1.OSExperimental">
<!-- Just a test method -->
<method name="Moo">
<arg type="b" name="utf8" direction="in"/>
<arg type="s" name="result" direction="out"/>
</method>
</interface>
<interface name="org.projectatomic.rpmostree1.Transaction">
<!-- Yes, we can. -->

View File

@ -414,6 +414,7 @@ rpmostreed_daemon_publish (RpmostreedDaemon *self,
GDBusInterface *prev = NULL;
GDBusInterfaceInfo *info = NULL;
GDBusObjectSkeleton *object = NULL;
g_autoptr(GDBusObjectSkeleton) owned_object = NULL;
g_return_if_fail (RPMOSTREED_IS_DAEMON (self));
g_return_if_fail (path != NULL);
@ -440,7 +441,7 @@ rpmostreed_daemon_publish (RpmostreedDaemon *self,
}
if (object == NULL)
object = g_dbus_object_skeleton_new (path);
object = owned_object = g_dbus_object_skeleton_new (path);
g_dbus_object_skeleton_add_interface (object, thing);
}
@ -454,9 +455,6 @@ rpmostreed_daemon_publish (RpmostreedDaemon *self,
g_dbus_object_manager_server_export_uniquely (self->object_manager, object);
else
g_dbus_object_manager_server_export (self->object_manager, object);
if (object)
g_object_unref (object);
}
void

View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "ostree.h"
#include <libglnx.h>
#include "rpmostreed-sysroot.h"
#include "rpmostreed-daemon.h"
#include "rpmostreed-deployment-utils.h"
#include "rpmostree-package-variants.h"
#include "rpmostreed-errors.h"
#include "rpmostree-origin.h"
#include "rpmostreed-os-experimental.h"
#include "rpmostreed-utils.h"
#include "rpmostree-util.h"
#include "rpmostreed-transaction.h"
#include "rpmostreed-transaction-monitor.h"
#include "rpmostreed-transaction-types.h"
typedef struct _RpmostreedOSExperimentalClass RpmostreedOSExperimentalClass;
struct _RpmostreedOSExperimental
{
RPMOSTreeOSSkeleton parent_instance;
RpmostreedTransactionMonitor *transaction_monitor;
};
struct _RpmostreedOSExperimentalClass
{
RPMOSTreeOSSkeletonClass parent_class;
};
static void rpmostreed_osexperimental_iface_init (RPMOSTreeOSExperimentalIface *iface);
G_DEFINE_TYPE_WITH_CODE (RpmostreedOSExperimental,
rpmostreed_osexperimental,
RPMOSTREE_TYPE_OSEXPERIMENTAL_SKELETON,
G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_OSEXPERIMENTAL,
rpmostreed_osexperimental_iface_init)
);
/* ---------------------------------------------------------------------------------------------------- */
static void
os_dispose (GObject *object)
{
RpmostreedOSExperimental *self = RPMOSTREED_OSEXPERIMENTAL (object);
const gchar *object_path;
object_path = g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON(self));
if (object_path != NULL)
{
rpmostreed_daemon_unpublish (rpmostreed_daemon_get (),
object_path, object);
}
g_clear_object (&self->transaction_monitor);
G_OBJECT_CLASS (rpmostreed_osexperimental_parent_class)->dispose (object);
}
static void
os_constructed (GObject *object)
{
G_GNUC_UNUSED RpmostreedOSExperimental *self = RPMOSTREED_OSEXPERIMENTAL (object);
/* TODO Integrate with PolicyKit via the "g-authorize-method" signal. */
G_OBJECT_CLASS (rpmostreed_osexperimental_parent_class)->constructed (object);
}
static void
rpmostreed_osexperimental_class_init (RpmostreedOSExperimentalClass *klass)
{
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = os_dispose;
gobject_class->constructed = os_constructed;
}
static void
rpmostreed_osexperimental_init (RpmostreedOSExperimental *self)
{
}
static gboolean
osexperimental_handle_moo (RPMOSTreeOSExperimental *interface,
GDBusMethodInvocation *invocation,
gboolean is_utf8)
{
static const char ascii_cow[] = "\n" \
" (__)\n" \
" (oo)\n" \
" /------\\/\n" \
" / | ||\n" \
" * /\\---/\\\n" \
" ~~ ~~\n";
const char *result = is_utf8 ? "🐄\n" : ascii_cow;
rpmostree_osexperimental_complete_moo (interface, invocation, result);
return TRUE;
}
static void
rpmostreed_osexperimental_iface_init (RPMOSTreeOSExperimentalIface *iface)
{
iface->handle_moo = osexperimental_handle_moo;
}
/* ---------------------------------------------------------------------------------------------------- */
RPMOSTreeOSExperimental *
rpmostreed_osexperimental_new (OstreeSysroot *sysroot,
OstreeRepo *repo,
const char *name,
RpmostreedTransactionMonitor *monitor)
{
RpmostreedOSExperimental *obj = NULL;
g_autofree char *path = NULL;
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (RPMOSTREED_IS_TRANSACTION_MONITOR (monitor), NULL);
path = rpmostreed_generate_object_path (BASE_DBUS_PATH, name, NULL);
obj = g_object_new (RPMOSTREED_TYPE_OSEXPERIMENTAL, NULL);
/* FIXME Make this a construct-only property? */
obj->transaction_monitor = g_object_ref (monitor);
rpmostreed_daemon_publish (rpmostreed_daemon_get (), path, FALSE, obj);
return RPMOSTREE_OSEXPERIMENTAL (obj);
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "rpmostreed-types.h"
#define RPMOSTREED_TYPE_OSEXPERIMENTAL (rpmostreed_osexperimental_get_type ())
#define RPMOSTREED_OSEXPERIMENTAL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), RPMOSTREED_TYPE_OSEXPERIMENTAL, RpmostreedOSExperimental))
#define RPMOSTREED_IS_OSEXPERIMENTAL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), RPMOSTREED_TYPE_OSEXPERIMENTAL))
GType rpmostreed_osexperimental_get_type (void) G_GNUC_CONST;
RPMOSTreeOSExperimental * rpmostreed_osexperimental_new (OstreeSysroot *sysroot,
OstreeRepo *repo,
const char *name,
RpmostreedTransactionMonitor *monitor);

View File

@ -22,6 +22,7 @@
#include "rpmostreed-daemon.h"
#include "rpmostreed-sysroot.h"
#include "rpmostreed-os.h"
#include "rpmostreed-os-experimental.h"
#include "rpmostree-util.h"
#include "rpmostreed-utils.h"
#include "rpmostreed-deployment-utils.h"
@ -62,6 +63,7 @@ struct _RpmostreedSysroot {
RpmostreedTransactionMonitor *transaction_monitor;
GHashTable *os_interfaces;
GHashTable *osexperimental_interfaces;
/* The OS interface's various diff methods can run concurrently with
* transactions, which is safe except when the transaction is writing
@ -504,12 +506,18 @@ sysroot_populate_deployments_unlocked (RpmostreedSysroot *self,
* now.
*/
if (!g_hash_table_contains (self->os_interfaces, deployment_os))
{
RPMOSTreeOS *obj = rpmostreed_os_new (self->ot_sysroot, self->repo,
deployment_os,
{
RPMOSTreeOS *obj = rpmostreed_os_new (self->ot_sysroot, self->repo,
deployment_os,
self->transaction_monitor);
g_hash_table_insert (self->os_interfaces, g_strdup (deployment_os), obj);
}
RPMOSTreeOSExperimental *eobj = rpmostreed_osexperimental_new (self->ot_sysroot, self->repo,
deployment_os,
self->transaction_monitor);
g_hash_table_insert (self->osexperimental_interfaces, g_strdup (deployment_os), eobj);
}
/* Owned by deployment, hash lifetime is smaller */
g_hash_table_add (seen_osnames, (char*)deployment_os);
}
@ -522,6 +530,8 @@ sysroot_populate_deployments_unlocked (RpmostreedSysroot *self,
{
g_object_run_dispose (G_OBJECT (value));
g_hash_table_iter_remove (&iter);
g_hash_table_remove (self->osexperimental_interfaces, hashkey);
}
}
@ -591,8 +601,6 @@ static void
sysroot_dispose (GObject *object)
{
RpmostreedSysroot *self = RPMOSTREED_SYSROOT (object);
GHashTableIter iter;
gpointer value;
gint tries;
g_cancellable_cancel (self->cancellable);
@ -623,10 +631,13 @@ sysroot_dispose (GObject *object)
}
/* Tracked os paths are responsible to unpublish themselves */
GHashTableIter iter;
g_hash_table_iter_init (&iter, self->os_interfaces);
while (g_hash_table_iter_next (&iter, NULL, &value))
gpointer key, value;
while (g_hash_table_iter_next (&iter, &key, &value))
g_object_run_dispose (value);
g_hash_table_remove_all (self->os_interfaces);
g_hash_table_remove_all (self->osexperimental_interfaces);
g_clear_object (&self->transaction_monitor);
@ -640,6 +651,7 @@ sysroot_finalize (GObject *object)
_sysroot_instance = NULL;
g_hash_table_unref (self->os_interfaces);
g_hash_table_unref (self->osexperimental_interfaces);
g_clear_object (&self->cancellable);
g_clear_object (&self->monitor);
@ -661,7 +673,9 @@ rpmostreed_sysroot_init (RpmostreedSysroot *self)
self->cancellable = g_cancellable_new ();
self->os_interfaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) g_object_unref);
(GDestroyNotify) g_object_unref);
self->osexperimental_interfaces = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) g_object_unref);
self->monitor = NULL;

View File

@ -34,6 +34,8 @@ typedef struct _RpmostreedSysroot RpmostreedSysroot;
struct _RpmostreedOS;
typedef struct _RpmostreedOS RpmostreedOS;
struct _RpmostreedOSExperimental;
typedef struct _RpmostreedOSExperimental RpmostreedOSExperimental;
struct _RpmostreedTransaction;
typedef struct _RpmostreedTransaction RpmostreedTransaction;

View File

@ -24,7 +24,7 @@ export RPMOSTREE_SUPPRESS_REQUIRES_ROOT_CHECK=yes
ensure_dbus
echo "1..17"
echo "1..18"
setup_os_repository "archive-z2" "syslinux"
@ -49,6 +49,10 @@ ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=te
assert_status_jq '.deployments[0].version == "1.0.10"'
echo "ok status shows right version"
dbus-send --session --dest=org.projectatomic.rpmostree1 --print-reply=literal /org/projectatomic/rpmostree1/testos org.projectatomic.rpmostree1.OSExperimental.Moo boolean:true > moo.txt
assert_file_has_content moo.txt '🐄'
echo "ok experimental"
os_repository_new_commit
rpm-ostree upgrade --os=testos