daemon: Rework API for rollback deployment lookup

Before this commit, in the case where we have 3 deployments, the rollback code
would pick the merge/pending deployment. This is understandable since that logic
predates us potentially creating 3 deployments.

For livefs, I want rollback to actually go to the rollback, not the pending.

Add an API to find the pending/rollback, and put it in syscore, since we have
other similar functions to this there. (Perhaps in the future we'll figure out a
way to dedup the deployment walking/filtering logic a bit).

Port the two callers to it.

Closes: #767
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-05-07 21:18:13 -04:00 committed by Atomic Bot
parent 3f3090ee7e
commit b7cf58efc1
6 changed files with 78 additions and 95 deletions

View File

@ -384,6 +384,48 @@ rpmostree_syscore_add_deployment (OstreeSysroot *sysroot,
return g_steal_pointer (&new_deployments);
}
/* Find the pending and rollback deployments (if any) for @osname. */
void
rpmostree_syscore_query_deployments (OstreeSysroot *sysroot,
const char *osname,
OstreeDeployment **out_pending,
OstreeDeployment **out_rollback)
{
g_autoptr(GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
g_autoptr(OstreeDeployment) ret_pending = NULL;
g_autoptr(OstreeDeployment) ret_rollback = NULL;
gboolean found_booted = FALSE;
for (guint i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
/* Is this deployment booted? If so, note we're past the booted */
if (booted_deployment != NULL &&
ostree_deployment_equal (deployment, booted_deployment))
{
found_booted = TRUE;
continue;
}
/* Ignore deployments not for this osname */
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
if (!found_booted && !ret_pending)
ret_pending = g_object_ref (deployment);
if (found_booted && !ret_rollback)
ret_rollback = g_object_ref (deployment);
}
if (out_pending)
*out_pending = g_steal_pointer (&ret_pending);
if (out_rollback)
*out_rollback = g_steal_pointer (&ret_rollback);
}
/* Also a variant of ostree_sysroot_simple_write_deployment(), but here we are
* just trying to remove a pending and/or rollback.
*/

View File

@ -42,6 +42,11 @@ GPtrArray *rpmostree_syscore_add_deployment (OstreeSysroot *sysroot,
OstreeDeployment *merge_deployment,
gboolean pushing_rollback);
void rpmostree_syscore_query_deployments (OstreeSysroot *sysroot,
const char *osname,
OstreeDeployment **out_pending,
OstreeDeployment **out_rollback);
GPtrArray *rpmostree_syscore_filter_deployments (OstreeSysroot *sysroot,
const char *osname,
gboolean remove_pending,

View File

@ -346,60 +346,3 @@ rpmostreed_commit_generate_cached_details_variant (OstreeDeployment *deployment,
g_variant_dict_insert (&dict, "gpg-enabled", "b", gpg_enabled);
return g_variant_dict_end (&dict);
}
gint
rpmostreed_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;
}

View File

@ -40,7 +40,3 @@ GVariant * rpmostreed_commit_generate_cached_details_variant (OstreeDeploym
OstreeRepo *repo,
const gchar *refspec,
GError **error);
gint rpmostreed_rollback_deployment_index (const gchar *name,
OstreeSysroot *ot_sysroot,
GError **error);

View File

@ -27,6 +27,7 @@
#include "rpmostree-package-variants.h"
#include "rpmostreed-errors.h"
#include "rpmostree-origin.h"
#include "rpmostree-sysroot-core.h"
#include "rpmostreed-os.h"
#include "rpmostreed-utils.h"
#include "rpmostree-util.h"
@ -1172,9 +1173,6 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error)
GVariant *cached_update = NULL;
gboolean has_cached_updates = FALSE;
gint rollback_index;
guint i;
name = rpmostree_os_get_name (RPMOSTREE_OS (self));
g_debug ("loading %s", name);
@ -1192,7 +1190,7 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error)
}
deployments = ostree_sysroot_get_deployments (ot_sysroot);
for (i=0; i<deployments->len; i++)
for (guint i=0; i<deployments->len; i++)
{
if (g_strcmp0 (ostree_deployment_get_osname (deployments->pdata[i]), name) == 0)
{
@ -1206,17 +1204,21 @@ rpmostreed_os_load_internals (RpmostreedOS *self, GError **error)
}
}
if (deployments->len >= 2)
if (booted)
{
rollback_index = rpmostreed_rollback_deployment_index (name, ot_sysroot, NULL);
if (rollback_index >= 0)
{
rollback_variant = rpmostreed_deployment_generate_variant (ot_sysroot,
deployments->pdata[rollback_index], booted_id,
ot_repo, error);
if (!rollback_variant)
return FALSE;
}
g_autoptr(OstreeDeployment) pending = NULL;
g_autoptr(OstreeDeployment) rollback = NULL;
rpmostree_syscore_query_deployments (ot_sysroot, ostree_deployment_get_osname (booted),
NULL, &rollback);
if (rollback)
{
rollback_variant = rpmostreed_deployment_generate_variant (ot_sysroot, rollback, booted_id,
ot_repo, error);
if (!rollback_variant)
return FALSE;
}
}
merge_deployment = ostree_sysroot_get_merge_deployment (ot_sysroot, name);

View File

@ -344,42 +344,38 @@ rollback_transaction_execute (RpmostreedTransaction *transaction,
{
RollbackTransaction *self;
OstreeSysroot *sysroot;
OstreeDeployment *deployment;
g_autoptr(GPtrArray) old_deployments = NULL;
g_autoptr(GPtrArray) new_deployments = NULL;
gint rollback_index;
guint i;
g_autoptr(OstreeDeployment) rollback_deployment = NULL;
gboolean ret = FALSE;
self = (RollbackTransaction *) transaction;
sysroot = rpmostreed_transaction_get_sysroot (transaction);
rollback_index = rpmostreed_rollback_deployment_index (self->osname, sysroot, error);
if (rollback_index < 0)
goto out;
rpmostree_syscore_query_deployments (sysroot, self->osname, NULL, &rollback_deployment);
if (!rollback_deployment)
{
(void) glnx_throw (error, "No rollback deployment found");
goto out;
}
old_deployments = ostree_sysroot_get_deployments (sysroot);
new_deployments = g_ptr_array_new_with_free_func (g_object_unref);
/* build out the reordered array */
deployment = old_deployments->pdata[rollback_index];
g_ptr_array_add (new_deployments, g_object_ref (deployment));
/* build out the reordered array; rollback is first now */
g_ptr_array_add (new_deployments, g_object_ref (rollback_deployment));
rpmostreed_transaction_emit_message_printf (transaction,
"Moving '%s.%d' to be first deployment",
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
ostree_deployment_get_csum (rollback_deployment),
ostree_deployment_get_deployserial (rollback_deployment));
for (i = 0; i < old_deployments->len; i++)
for (guint i = 0; i < old_deployments->len; i++)
{
if (i == rollback_index)
continue;
deployment = old_deployments->pdata[i];
g_ptr_array_add (new_deployments, g_object_ref (deployment));
OstreeDeployment *deployment = old_deployments->pdata[i];
if (deployment != rollback_deployment)
g_ptr_array_add (new_deployments, g_object_ref (deployment));
}
/* if default changed write it */
@ -396,7 +392,6 @@ rollback_transaction_execute (RpmostreedTransaction *transaction,
rpmostreed_reboot (cancellable, error);
ret = TRUE;
out:
return ret;
}