Skip to content

Commit

Permalink
daemon: Add new write_deployments() function and bump_mtime()
Browse files Browse the repository at this point in the history
This is prep for livefs.  We need to tweak the logic from what
core libostree has in `ostree_sysroot_simple_write_deployment()`,
and while we could land improved logic there, I think it makes
sense to carry this here until we're confident enough in the logic
to make it ABI.

This does depend on a [new libostree API](ostreedev/ostree#745)
that allows writing deployments without doing cleanup.

The `bump_mtime()` bit is also prep for livefs, carrying in this patch to avoid
splitting things too much.
  • Loading branch information
cgwalters committed Mar 27, 2017
1 parent fe693e9 commit 1b8f03d
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 42 deletions.
53 changes: 11 additions & 42 deletions src/daemon/rpmostree-sysroot-upgrader.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,31 +109,6 @@ parse_origin_deployment (RpmOstreeSysrootUpgrader *self,
return TRUE;
}

/* This is like ostree_sysroot_get_merge_deployment() except we explicitly
* ignore the magical "booted" behavior. For rpm-ostree we're trying something
* different now where we are a bit more stateful and pick up changes from the
* pending root. This allows users to chain operations together naturally.
*/
static OstreeDeployment *
get_origin_merge_deployment (OstreeSysroot *self,
const char *osname)
{
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (self);
guint i;

for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];

if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;

return g_object_ref (deployment);
}

return NULL;
}

static gboolean
rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
GCancellable *cancellable,
Expand Down Expand Up @@ -169,7 +144,7 @@ rpmostree_sysroot_upgrader_initable_init (GInitable *initable,
goto out;

self->cfg_merge_deployment = ostree_sysroot_get_merge_deployment (self->sysroot, self->osname);
self->origin_merge_deployment = get_origin_merge_deployment (self->sysroot, self->osname);
self->origin_merge_deployment = rpmostreed_get_origin_merge_deployment (self->sysroot, self->osname);
if (self->cfg_merge_deployment == NULL || self->origin_merge_deployment == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
Expand Down Expand Up @@ -1130,7 +1105,6 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
glnx_unref_object OstreeDeployment *new_deployment = NULL;
const char *target_revision;
g_autoptr(GKeyFile) origin = NULL;
Expand All @@ -1141,16 +1115,15 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
g_hash_table_size (rpmostree_origin_get_local_packages (self->origin)) > 0)
{
if (!do_local_assembly (self, cancellable, error))
goto out;
return FALSE;
}
else
g_clear_pointer (&self->final_revision, g_free);

if (self->flags & RPMOSTREE_SYSROOT_UPGRADER_FLAGS_PKGOVERLAY_DRY_RUN)
{
/* we already printed the transaction in do_final_local_assembly() */
ret = TRUE;
goto out;
return TRUE;
}

/* make sure we have a known target to deploy */
Expand All @@ -1164,7 +1137,7 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
NULL,
&new_deployment,
cancellable, error))
goto out;
return FALSE;

if (self->final_revision)
{
Expand All @@ -1174,22 +1147,18 @@ rpmostree_sysroot_upgrader_deploy (RpmOstreeSysrootUpgrader *self,
if (!ostree_repo_set_ref_immediate (self->repo, NULL, RPMOSTREE_TMP_BASE_REF,
self->base_revision,
cancellable, error))
goto out;
return FALSE;
}

if (!ostree_sysroot_simple_write_deployment (self->sysroot, self->osname,
new_deployment,
self->cfg_merge_deployment,
OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_NO_CLEAN,
cancellable, error))
goto out;
if (!rpmostree_write_deployment (self->sysroot, new_deployment,
self->cfg_merge_deployment, FALSE,
cancellable, error))
return FALSE;

if (!rpmostree_sysroot_upgrader_cleanup (self->sysroot, self->repo, cancellable, error))
goto out;
return FALSE;

ret = TRUE;
out:
return ret;
return TRUE;
}

GType
Expand Down
114 changes: 114 additions & 0 deletions src/daemon/rpmostreed-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
#include "libglnx.h"

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

static void
append_to_object_path (GString *str,
Expand Down Expand Up @@ -214,6 +217,117 @@ rpmostreed_refspec_parse_partial (const gchar *new_provided_refspec,
return ret;
}

/* This is like ostree_sysroot_get_merge_deployment() except we explicitly
* ignore the magical "booted" behavior. For rpm-ostree we're trying something
* different now where we are a bit more stateful and pick up changes from the
* pending root. This allows users to chain operations together naturally.
*/
OstreeDeployment *
rpmostreed_get_origin_merge_deployment (OstreeSysroot *self, const char *osname)
{
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (self);
guint i;

for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];

if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;

return g_object_ref (deployment);
}

return NULL;
}


/* Copy of currently private _ostree_sysroot_bump_mtime()
* until we decide to either formalize that, or have a method
* to notify of changes to e.g. live replaced xattrs.
*/
gboolean
rpmostree_sysroot_bump_mtime (OstreeSysroot *sysroot,
GError **error)
{
if (utimensat (ostree_sysroot_get_fd (sysroot), "ostree/deploy", NULL, 0) < 0)
{
glnx_set_prefix_error_from_errno (error, "%s", "futimens");
return FALSE;
}
return TRUE;
}

/* A version of ostree_sysroot_simple_write_deployment() but with
* a few changes:
*
* - There's just @pushing_rollback, which if true makes the deployment not-default
* as well as retaining the pending deployment
* - osname logic is based on new deployment
* - Fix insertion of deployment to be after booted (patch pending for ostree upstream)
*/
gboolean
rpmostree_write_deployment (OstreeSysroot *sysroot,
OstreeDeployment *new_deployment,
OstreeDeployment *merge_deployment,
gboolean pushing_rollback,
GCancellable *cancellable,
GError **error)
{
OstreeDeployment *booted_deployment = NULL;
OstreeSysrootWriteDeploymentsOpts write_opts = { .do_postclean = FALSE };
g_autoptr(GPtrArray) deployments = NULL;
g_autoptr(GPtrArray) new_deployments = g_ptr_array_new_with_free_func (g_object_unref);
const char *osname = ostree_deployment_get_osname (new_deployment);
/* Whether or not we added @new_deployment to the list yet */
gboolean added_new = FALSE;
/* Keep track of whether we're looking at a deployment before or after the booted */
gboolean before_booted = TRUE;

deployments = ostree_sysroot_get_deployments (sysroot);
booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);

if (!pushing_rollback)
{
g_ptr_array_add (new_deployments, g_object_ref (new_deployment));
added_new = TRUE;
}

for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
const gboolean osname_matches = (strcmp (ostree_deployment_get_osname (deployment), osname) == 0);
const gboolean is_booted = ostree_deployment_equal (deployment, booted_deployment);
const gboolean is_merge_or_booted = is_booted ||
ostree_deployment_equal (deployment, merge_deployment);
const gboolean is_last = i == (deployments->len - 1);

if (is_booted)
before_booted = FALSE;

/* Retain deployment if:
* - The deployment is for another osname
* - We're pushing a rollback and this is a pending deployment
* - It's the merge or booted deployment
*/
if (!osname_matches || (pushing_rollback && before_booted) || is_merge_or_booted)
g_ptr_array_add (new_deployments, g_object_ref (deployment));

/* Insert new rollback right after the booted */
if (!added_new && (!before_booted || is_last))
{
g_ptr_array_add (new_deployments, g_object_ref (new_deployment));
added_new = TRUE;
}
}

if (!ostree_sysroot_write_deployments_with_options (sysroot, new_deployments,
&write_opts, cancellable, error))
return FALSE;

return TRUE;
}

void
rpmostreed_reboot (GCancellable *cancellable, GError **error)
{
Expand Down
12 changes: 12 additions & 0 deletions src/daemon/rpmostreed-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ gboolean rpmostreed_refspec_parse_partial (const gchar *new_provided_refspec,
const gchar *base_refspec,
gchar **out_refspec,
GError **error);

OstreeDeployment *rpmostreed_get_origin_merge_deployment (OstreeSysroot *self, const char *osname);

gboolean rpmostree_sysroot_bump_mtime (OstreeSysroot *self, GError **error);

gboolean rpmostree_write_deployment (OstreeSysroot *sysroot,
OstreeDeployment *new_deployment,
OstreeDeployment *merge_deployment,
gboolean make_default,
GCancellable *cancellable,
GError **error);

void
rpmostreed_reboot (GCancellable *cancellable, GError **error);

Expand Down

0 comments on commit 1b8f03d

Please sign in to comment.