daemon: OS properties and property updates

This commit is contained in:
petervo 2015-06-09 15:57:32 -07:00 committed by Matthew Barnes
parent c6548ace61
commit a140c26200
7 changed files with 302 additions and 146 deletions

View File

@ -21,7 +21,8 @@
#include "auth.h"
#include "errors.h"
#include "daemon.h"
#include "libgsystem.h"
#include <libglnx.h>
/**
* auth_check_root_or_access_denied:
@ -38,7 +39,7 @@ auth_check_root_or_access_denied (GDBusInterfaceSkeleton *instance,
const gchar *sender;
gboolean ret = FALSE;
gs_unref_variant GVariant *value = NULL;
g_autoptr (GVariant) value = NULL;
GError *error = NULL;
GDBusConnection *connection = NULL;
guint32 uid = UINT32_MAX;

View File

@ -23,7 +23,7 @@
#include "types.h"
#include "utils.h"
#include "libgsystem.h"
#include <libglnx.h>
/**
* SECTION:daemon
@ -186,7 +186,7 @@ daemon_constructed (GObject *_object)
{
Daemon *self;
GError *error = NULL;
gs_free gchar *path = NULL;
g_autofree gchar *path = NULL;
self = DAEMON (_object);
self->object_manager = g_dbus_object_manager_server_new (BASE_DBUS_PATH);
@ -198,7 +198,7 @@ daemon_constructed (GObject *_object)
g_dbus_connection_start_message_processing (self->connection);
path = utils_generate_object_path(BASE_DBUS_PATH, "Sysroot", NULL);
path = utils_generate_object_path (BASE_DBUS_PATH, "Sysroot", NULL);
self->sysroot = g_object_new (TYPE_SYSROOT,
"sysroot-path", self->sysroot_path,
NULL);

View File

@ -137,7 +137,7 @@ deployment_generate_variant (OstreeDeployment *deployment,
}
if (!sigs)
sigs = g_variant_new("av", NULL);
sigs = g_variant_new ("av", NULL);
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
g_variant_builder_add (&builder, "s", id);

View File

@ -34,10 +34,9 @@
</interface>
<interface name="org.projectatomic.rpmostree1.OS">
<property name="BootedDeployment" type="o" access="read"/>
<property name="DefaultDeployment" type="o" access="read"/>
<property name="RollbackDeployment" type="o" access="read"/>
<property name="Deployments" type="as" access="read"/>
<property name="BootedDeployment" type="(ssisstsav)" access="read"/>
<property name="DefaultDeployment" type="(ssisstsav)" access="read"/>
<property name="RollbackDeployment" type="(ssisstsav)" access="read"/>
<property name="HasCachedUpdateRpmDiff" type="b" access="read"/>
<!-- NONE, DIFF, PREPARE, REBOOT -->
<property name="AutomaticUpdatePolicy" type="s" access="read"/>

View File

@ -19,9 +19,15 @@
#include "config.h"
#include "ostree.h"
#include "libglnx.h"
#include <libglnx.h>
#include "sysroot.h"
#include "daemon.h"
#include "deployment-utils.h"
#include "rpmostree-package-variants.h"
#include "types.h"
#include "errors.h"
#include "auth.h"
#include "os.h"
#include "utils.h"
@ -31,8 +37,7 @@ typedef struct _TaskData TaskData;
struct _OSStub
{
RPMOSTreeOSSkeleton parent_instance;
GWeakRef sysroot;
guint signal_id;
};
struct _OSStubClass
@ -55,6 +60,8 @@ enum {
static void osstub_iface_init (RPMOSTreeOSIface *iface);
static void osstub_load_internals (OSStub *self,
OstreeSysroot *ot_sysroot);
G_DEFINE_TYPE_WITH_CODE (OSStub, osstub, RPMOSTREE_TYPE_OS_SKELETON,
G_IMPLEMENT_INTERFACE (RPMOSTREE_TYPE_OS,
@ -73,67 +80,53 @@ task_data_free (TaskData *data)
g_clear_pointer (&data->options, (GDestroyNotify) g_variant_dict_unref);
}
static void
osstub_set_sysroot (OSStub *self,
OstreeSysroot *sysroot)
{
g_weak_ref_set (&self->sysroot, sysroot);
}
static void
osstub_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
sysroot_changed (Sysroot *sysroot,
OstreeSysroot *ot_sysroot,
gpointer user_data)
{
OSStub *self = OSSTUB (object);
OSStub *self = OSSTUB (user_data);
g_return_val_if_fail (OSTREE_IS_SYSROOT (ot_sysroot), NULL);
switch (property_id)
{
case PROP_SYSROOT:
osstub_set_sysroot (self, g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
osstub_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
OSStub *self = OSSTUB (object);
switch (property_id)
{
case PROP_SYSROOT:
g_value_take_object (value, osstub_ref_sysroot (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
osstub_load_internals (self, ot_sysroot);
}
static void
osstub_dispose (GObject *object)
{
OSStub *self = OSSTUB (object);
const gchar *object_path;
object_path = g_dbus_interface_skeleton_get_object_path (self);
if (object_path)
{
daemon_unpublish (daemon_get (),
object_path,
object);
}
g_weak_ref_clear (&self->sysroot);
if (self->signal_id > 0)
g_signal_handler_disconnect (sysroot_get (), self->signal_id);
self->signal_id = 0;
G_OBJECT_CLASS (osstub_parent_class)->dispose (object);
}
static void
osstub_init (OSStub *self)
{
g_weak_ref_init (&self->sysroot, NULL);
}
static void
osstub_constructed (GObject *object)
{
OSStub *self = OSSTUB (object);
g_signal_connect (RPMOSTREE_OS(self), "g-authorize-method",
G_CALLBACK (auth_check_root_or_access_denied), NULL);
self->signal_id = g_signal_connect (sysroot_get (), "sysroot-updated",
G_CALLBACK (sysroot_changed), self);
G_OBJECT_CLASS (osstub_parent_class)->constructed (object);
}
static void
@ -142,23 +135,70 @@ osstub_class_init (OSStubClass *klass)
GObjectClass *gobject_class;
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = osstub_set_property;
gobject_class->get_property = osstub_get_property;
gobject_class->dispose = osstub_dispose;
gobject_class->constructed = osstub_constructed;
g_object_class_install_property (gobject_class,
PROP_SYSROOT,
g_param_spec_object ("sysroot",
NULL,
NULL,
OSTREE_TYPE_SYSROOT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
/* ---------------------------------------------------------------------------------------------------- */
static gint
rollback_deployment_index (const gchar *name,
OstreeSysroot *ot_sysroot,
GError **error)
{
g_autoptr (GPtrArray) deployments = NULL;
glnx_unref_object OstreeDeployment *merge_deployment = NULL;
gint index_to_prepend = -1;
gint merge_index = -1;
gint previous_index = -1;
guint i;
merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
if (merge_deployment == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No deployments found for os %s", name);
goto out;
}
deployments = ostree_sysroot_get_deployments (ot_sysroot);
if (deployments->len < 2)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Found %u deployments, at least 2 required for rollback",
deployments->len);
goto out;
}
g_assert (merge_deployment != NULL);
for (i = 0; i < deployments->len; i++)
{
if (deployments->pdata[i] == merge_deployment)
merge_index = i;
if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0 &&
deployments->pdata[i] != merge_deployment &&
previous_index < 0)
{
previous_index = i;
}
}
g_assert (merge_index < deployments->len);
g_assert (deployments->pdata[merge_index] == merge_deployment);
/* If merge deployment is not booted assume we are using it. */
if (merge_index == 0 && previous_index > 0)
index_to_prepend = previous_index;
else
index_to_prepend = merge_index;
out:
return index_to_prepend;
}
static void
osstub_upgrade_thread (GTask *task,
gpointer source_object,
@ -294,14 +334,20 @@ osstub_handle_upgrade (RPMOSTreeOS *interface,
glnx_unref_object OstreeSysroot *sysroot = NULL;
glnx_unref_object OstreeAsyncProgress *progress = NULL;
glnx_unref_object RPMOSTreeTransaction *transaction = NULL;
g_autoptr(GTask) task = NULL;
g_autoptr (GTask) task = NULL;
TaskData *data;
gboolean lock_acquired = FALSE;
GError *local_error = NULL;
cancellable = g_cancellable_new ();
sysroot = osstub_ref_sysroot (OSSTUB (interface));
if (!utils_load_sysroot_and_repo (sysroot_get_sysroot_path ( sysroot_get ()),
cancellable,
&sysroot,
NULL,
&local_error))
goto out;
g_return_val_if_fail (sysroot != NULL, FALSE);
if (!ostree_sysroot_try_lock (sysroot, &lock_acquired, &local_error))
@ -469,10 +515,112 @@ osstub_handle_download_rebase_rpm_diff (RPMOSTreeOS *interface,
return TRUE;
}
static void
osstub_load_internals (OSStub *self,
OstreeSysroot *ot_sysroot)
{
const gchar *name;
OstreeDeployment *booted = NULL; // owned by sysroot
glnx_unref_object OstreeDeployment *merge_deployment = NULL; // transfered
glnx_unref_object OstreeRepo *ot_repo = NULL;
g_autoptr (GPtrArray) deployments = NULL;
GError *error = NULL;
GVariant *booted_variant = NULL;
GVariant *default_variant = NULL;
GVariant *rollback_variant = NULL;
gboolean has_cached_updates = FALSE;
gint rollback_index;
guint i;
name = rpmostree_os_get_name (RPMOSTREE_OS (self));
if (!ostree_sysroot_get_repo (ot_sysroot,
&ot_repo,
NULL,
&error))
goto out;
deployments = ostree_sysroot_get_deployments (ot_sysroot);
if (deployments == NULL)
goto out;
for (i=0; i<deployments->len; i++)
{
if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0)
{
default_variant = deployment_generate_variant (deployments->pdata[i],
ot_repo);
break;
}
}
booted = ostree_sysroot_get_booted_deployment (ot_sysroot);
if (booted && g_strcmp0 (ostree_deployment_get_osname (booted),
name) == 0)
{
booted_variant = deployment_generate_variant (booted,
ot_repo);
}
rollback_index = rollback_deployment_index (name, ot_sysroot, &error);
if (error == NULL)
{
rollback_variant = deployment_generate_variant (deployments->pdata[rollback_index],
ot_repo);
}
merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);
if (merge_deployment)
{
g_autofree gchar *head = NULL;
g_autofree gchar *origin_refspec = NULL;
origin_refspec = deployment_get_refspec (merge_deployment);
if (!origin_refspec)
goto out;
if (!ostree_repo_resolve_rev (ot_repo, origin_refspec,
FALSE, &head, NULL))
goto out;
has_cached_updates = g_strcmp0 (ostree_deployment_get_csum(merge_deployment),
head) != 0;
}
out:
g_clear_error (&error);
if (!booted_variant)
booted_variant = deployment_generate_blank_variant ();
rpmostree_os_set_booted_deployment (RPMOSTREE_OS (self),
booted_variant);
if (!default_variant)
default_variant = deployment_generate_blank_variant ();
rpmostree_os_set_default_deployment (RPMOSTREE_OS (self),
default_variant);
if (!rollback_variant)
rollback_variant = deployment_generate_blank_variant ();
rpmostree_os_set_rollback_deployment (RPMOSTREE_OS (self),
rollback_variant);
rpmostree_os_set_has_cached_update_rpm_diff (RPMOSTREE_OS (self),
has_cached_updates);
rpmostree_os_set_has_cached_update_rpm_diff (RPMOSTREE_OS (self),
has_cached_updates);
}
static void
osstub_iface_init (RPMOSTreeOSIface *iface)
{
iface->handle_get_cached_update_rpm_diff = osstub_handle_get_cached_update_rpm_diff;
iface->handle_get_deployments_rpm_diff = handle_get_deployments_rpm_diff;
iface->handle_download_update_rpm_diff = osstub_handle_download_update_rpm_diff;
iface->handle_upgrade = osstub_handle_upgrade;
iface->handle_rollback = osstub_handle_rollback;
@ -488,16 +636,17 @@ RPMOSTreeOS *
osstub_new (OstreeSysroot *sysroot,
const char *name)
{
const gchar *path;
OSStub *obj = NULL;
g_return_val_if_fail (OSTREE_IS_SYSROOT (sysroot), NULL);
g_return_val_if_fail (name != NULL, NULL);
return g_object_new (TYPE_OSSTUB, "sysroot", sysroot, "name", name, NULL);
}
path = utils_generate_object_path (BASE_DBUS_PATH,
name, NULL);
OstreeSysroot *
osstub_ref_sysroot (OSStub *self)
{
g_return_val_if_fail (IS_OSSTUB (self), NULL);
return g_weak_ref_get (&self->sysroot);
obj = g_object_new (TYPE_OSSTUB, "name", name, NULL);
osstub_load_internals (obj, sysroot);
daemon_publish (daemon_get (), path, FALSE, obj);
return RPMOSTREE_OS (obj);
}

View File

@ -55,9 +55,12 @@ struct _Sysroot
gchar *sysroot_path;
OstreeSysroot *ot_sysroot;
GHashTable *os_interfaces;
GRWLock children_lock;
GFileMonitor *monitor;
guint sig_changed;
guint64 last_monitor_event;
@ -98,8 +101,8 @@ _build_file (const char *first, ...)
{
va_list args;
const gchar *arg;
gs_free gchar *path = NULL;
g_autoptr(GPtrArray) parts = NULL;
g_autofree gchar *path = NULL;
g_autoptr (GPtrArray) parts = NULL;
va_start (args, first);
parts = g_ptr_array_new ();
@ -121,29 +124,21 @@ handle_create_osname (RPMOSTreeSysroot *object,
GDBusMethodInvocation *invocation,
const gchar *osname)
{
gs_unref_object OstreeSysroot *ot_sysroot = NULL;
g_autoptr(GFile) dir = NULL;
gs_free gchar *deploy_dir = NULL;
gs_free gchar *base_name = NULL;
g_autoptr (GFile) dir = NULL;
g_autofree gchar *deploy_dir = NULL;
g_autofree gchar *base_name = NULL;
GError *error = NULL;
gs_free gchar *dbus_path = NULL;
g_autofree gchar *dbus_path = NULL;
Sysroot *self = SYSROOT (object);
if (!utils_load_sysroot_and_repo (self->sysroot_path,
self->cancellable,
&ot_sysroot,
NULL,
&error))
goto out;
if (!ostree_sysroot_ensure_initialized (ot_sysroot,
if (!ostree_sysroot_ensure_initialized (self->ot_sysroot,
self->cancellable,
&error))
goto out;
base_name = g_path_get_basename(osname);
base_name = g_path_get_basename (osname);
if (g_strcmp0 (base_name, osname) != 0)
{
g_set_error_literal (&error,
@ -289,6 +284,7 @@ sysroot_dispose (GObject *object)
g_rw_lock_writer_unlock (&self->children_lock);
g_object_unref (self->ot_sysroot);
G_OBJECT_CLASS (sysroot_parent_class)->dispose (object);
}
@ -389,7 +385,9 @@ sysroot_class_init (SysrootClass *klass)
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE, 0);
G_TYPE_NONE,
1,
OSTREE_TYPE_SYSROOT);
}
@ -398,7 +396,7 @@ sysroot_populate_deployments (Sysroot *self,
OstreeSysroot *ot_sysroot,
OstreeRepo *ot_repo)
{
gs_unref_object OstreeDeployment *booted = NULL;
OstreeDeployment *booted = NULL; // owned by sysroot
g_autoptr (GPtrArray) deployments = NULL;
GVariantBuilder builder;
@ -425,7 +423,7 @@ sysroot_populate_deployments (Sysroot *self,
if (booted)
{
const gchar *os = ostree_deployment_get_osname (booted);
gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH,
g_autofree gchar *path = utils_generate_object_path (BASE_DBUS_PATH,
os, NULL);
rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), path);
}
@ -434,7 +432,6 @@ sysroot_populate_deployments (Sysroot *self,
rpmostree_sysroot_set_booted (RPMOSTREE_SYSROOT (self), "/");
}
g_debug ("we think we are here");
rpmostree_sysroot_set_deployments (RPMOSTREE_SYSROOT (self),
g_variant_builder_end (&builder));
g_debug ("finished deployments");
@ -442,17 +439,16 @@ sysroot_populate_deployments (Sysroot *self,
out:
return ret;
}
static gboolean
sysroot_load_internals (Sysroot *self,
OstreeSysroot **out_sysroot,
OstreeRepo **out_repo,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeSysroot *ot_sysroot = NULL;
gs_unref_object OstreeRepo *ot_repo = NULL;
glnx_unref_object OstreeRepo *ot_repo = NULL;
g_autoptr (GHashTable) seen = NULL;
gs_free gchar *os_path = NULL;
g_autofree gchar *os_path = NULL;
GDir *os_dir = NULL;
GHashTableIter iter;
@ -460,12 +456,6 @@ sysroot_load_internals (Sysroot *self,
gpointer value;
g_rw_lock_writer_lock (&self->children_lock);
if (!utils_load_sysroot_and_repo (self->sysroot_path,
self->cancellable,
&ot_sysroot,
&ot_repo,
error))
goto out;
os_path = g_build_filename (self->sysroot_path, "ostree",
"deploy", NULL);
@ -475,10 +465,21 @@ sysroot_load_internals (Sysroot *self,
if (!os_dir)
goto out;
if (!ostree_sysroot_load (self->ot_sysroot,
NULL,
error))
goto out;
if (!ostree_sysroot_get_repo (self->ot_sysroot,
&ot_repo,
NULL,
error))
goto out;
while (TRUE)
{
const gchar *os = g_dir_read_name (os_dir);
gs_free gchar *full_path = NULL;
g_autofree gchar *full_path = NULL;
if (os == NULL) {
if (errno && errno != ENOENT)
@ -494,17 +495,13 @@ sysroot_load_internals (Sysroot *self,
if (g_hash_table_contains (self->os_interfaces, os))
continue;
full_path = g_build_filename(os_path, os, NULL);
full_path = g_build_filename (os_path, os, NULL);
if (g_file_test (full_path, G_FILE_TEST_IS_DIR))
{
gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH,
os, NULL);
//TODO: stub for real OS implementation
RPMOSTreeOS *obj = osstub_new (ot_sysroot, os);
g_hash_table_insert(self->os_interfaces,
g_strdup (os),
obj);
daemon_publish (daemon_get (), path, FALSE, obj);
RPMOSTreeOS *obj = osstub_new (self->ot_sysroot, os);
g_hash_table_insert (self->os_interfaces,
g_strdup (os),
obj);
}
}
@ -514,23 +511,13 @@ sysroot_load_internals (Sysroot *self,
{
if (!g_hash_table_contains (seen, hashkey))
{
//TODO: stub for real implementation
gs_free gchar *path = utils_generate_object_path (BASE_DBUS_PATH,
hashkey, NULL);
daemon_unpublish (daemon_get (),
path,
G_OBJECT (value));
g_object_run_dispose (G_OBJECT (value));
g_hash_table_iter_remove (&iter);
}
}
// update deployments
sysroot_populate_deployments (self, ot_sysroot, ot_repo);
gs_transfer_out_value (out_sysroot, &ot_sysroot);
if (out_repo != NULL)
*out_repo = g_object_ref (ot_repo);
sysroot_populate_deployments (self, self->ot_sysroot, ot_repo);
ret = TRUE;
@ -538,7 +525,7 @@ out:
g_rw_lock_writer_unlock (&self->children_lock);
if (os_dir)
g_dir_close(os_dir);
g_dir_close (os_dir);
return ret;
}
@ -555,16 +542,11 @@ _do_reload_data (GTask *task,
GError *error = NULL;
Sysroot *self = SYSROOT (object);
g_debug ("reloading");
if (!sysroot_load_internals (self, &error))
g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
// this was valid once, make sure it is tried again
// TODO, should we bail at some point?
if (!sysroot_load_internals (self, NULL, NULL, &error)) {
g_message ("Error refreshing sysroot data: %s", error->message);
g_timeout_add_seconds (UPDATED_THROTTLE_SECONDS,
_throttle_refresh,
self);
}
g_clear_error (&error);
}
@ -576,9 +558,25 @@ _reload_callback (GObject *source_object,
{
Sysroot *self = SYSROOT (user_data);
GTask *task = G_TASK (res);
GError *error = NULL;
g_task_propagate_boolean (task, &error);
if (error)
{
// this was valid once, make sure it is tried again
// TODO, should we bail at some point?
g_message ("Error refreshing sysroot data: %s", error->message);
g_timeout_add_seconds (UPDATED_THROTTLE_SECONDS,
_throttle_refresh,
self);
}
else
{
g_signal_emit (self, sysroot_signals[UPDATED], 0, self->ot_sysroot);
}
g_signal_emit (self, sysroot_signals[UPDATED], 0);
g_object_unref (task);
g_clear_error (&error);
}
@ -667,10 +665,17 @@ sysroot_populate (Sysroot *self,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeRepo *ot_repo = NULL;
glnx_unref_object OstreeRepo *ot_repo = NULL;
g_return_val_if_fail (self != NULL, FALSE);
if (!sysroot_load_internals (self, NULL, &ot_repo, error))
if (!utils_load_sysroot_and_repo (self->sysroot_path,
NULL,
&self->ot_sysroot,
&ot_repo,
error))
goto out;
if (!sysroot_load_internals (self, error))
goto out;
if (self->monitor == NULL)

View File

@ -16,9 +16,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include "utils.h"
#include "libgsystem.h"
#include <libglnx.h>
static gboolean
handle_cancel_cb (RPMOSTreeTransaction *transaction,
@ -230,8 +232,8 @@ utils_generate_object_path (const gchar *base,
gchar *
utils_generate_object_path_from_va (const gchar *base,
const gchar *part,
va_list va)
const gchar *part,
va_list va)
{
GString *path;
@ -276,8 +278,8 @@ utils_load_sysroot_and_repo (gchar *path,
OstreeRepo **out_repo,
GError **error)
{
gs_unref_object GFile *sysroot_path = NULL;
gs_unref_object OstreeSysroot *ot_sysroot = NULL;
glnx_unref_object GFile *sysroot_path = NULL;
glnx_unref_object OstreeSysroot *ot_sysroot = NULL;
gboolean ret = FALSE;
sysroot_path = g_file_new_for_path (path);