lib/sysroot: Add API to get pending/rollback for given stateroot

This imports a function that is used in rpm-ostree, and it's also intended for
use by https://github.com/advancedtelematic/aktualizr to display
what deployment we're going to boot next after the reboot.

Updated-by: Colin Walters <walters@verbum.org>

Closes: #897
Approved by: OYTIS
This commit is contained in:
Anton Gerasimov 2017-06-01 12:43:50 +02:00 committed by Atomic Bot
parent 0635fcbfd9
commit 64ab8334b7
6 changed files with 84 additions and 15 deletions

View File

@ -496,6 +496,7 @@ ostree_sysroot_write_deployments_with_options
ostree_sysroot_write_origin_file ostree_sysroot_write_origin_file
ostree_sysroot_deploy_tree ostree_sysroot_deploy_tree
ostree_sysroot_get_merge_deployment ostree_sysroot_get_merge_deployment
ostree_sysroot_query_deployments_for
ostree_sysroot_origin_new_from_refspec ostree_sysroot_origin_new_from_refspec
OstreeSysrootSimpleWriteDeploymentFlags OstreeSysrootSimpleWriteDeploymentFlags
ostree_sysroot_simple_write_deployment ostree_sysroot_simple_write_deployment

View File

@ -405,6 +405,7 @@ global:
LIBOSTREE_2017.7 { LIBOSTREE_2017.7 {
global: global:
ostree_sysroot_repo; ostree_sysroot_repo;
ostree_sysroot_query_deployments_for;
} LIBOSTREE_2017.6; } LIBOSTREE_2017.6;
/* Stub section for the stable release *after* this development one; don't /* Stub section for the stable release *after* this development one; don't

View File

@ -1107,6 +1107,63 @@ find_booted_deployment (OstreeSysroot *self,
return TRUE; return TRUE;
} }
/**
* ostree_sysroot_query_deployments_for:
* @self: Sysroot
* @osname: (allow-none): "stateroot" name
* @out_pending: (out) (allow-none) (transfer full): The pending deployment
* @out_rollback: (out) (allow-none) (transfer full): The rollback deployment
*
* Find the pending and rollback deployments for @osname. Pass %NULL for @osname
* to use the booted deployment's osname. By default, pending deployment is the
* first deployment in the order that matches @osname, and @rollback will be the
* next one after the booted deployment, or the deployment after the pending if
* we're not looking at the booted deployment.
*
* Since: 2017.7
*/
void
ostree_sysroot_query_deployments_for (OstreeSysroot *self,
const char *osname,
OstreeDeployment **out_pending,
OstreeDeployment **out_rollback)
{
g_return_if_fail (osname != NULL || self->booted_deployment != NULL);
g_autoptr(OstreeDeployment) ret_pending = NULL;
g_autoptr(OstreeDeployment) ret_rollback = NULL;
if (osname == NULL)
osname = ostree_deployment_get_osname (self->booted_deployment);
gboolean found_booted = FALSE;
for (guint i = 0; i < self->deployments->len; i++)
{
OstreeDeployment *deployment = self->deployments->pdata[i];
/* Is this deployment booted? If so, note we're past the booted */
if (self->booted_deployment != NULL &&
ostree_deployment_equal (deployment, self->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);
else 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);
}
/** /**
* ostree_sysroot_get_merge_deployment: * ostree_sysroot_get_merge_deployment:
* @self: Sysroot * @self: Sysroot
@ -1132,23 +1189,13 @@ ostree_sysroot_get_merge_deployment (OstreeSysroot *self,
*/ */
if (self->booted_deployment && if (self->booted_deployment &&
g_strcmp0 (ostree_deployment_get_osname (self->booted_deployment), osname) == 0) g_strcmp0 (ostree_deployment_get_osname (self->booted_deployment), osname) == 0)
{
return g_object_ref (self->booted_deployment); return g_object_ref (self->booted_deployment);
}
else else
{ {
guint i; g_autoptr(OstreeDeployment) pending = NULL;
for (i = 0; i < self->deployments->len; i++) ostree_sysroot_query_deployments_for (self, osname, &pending, NULL);
{ return g_steal_pointer (&pending);
OstreeDeployment *deployment = self->deployments->pdata[i];
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
return g_object_ref (deployment);
} }
}
return NULL;
} }
/** /**

View File

@ -187,6 +187,12 @@ gboolean ostree_sysroot_deployment_unlock (OstreeSysroot *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
_OSTREE_PUBLIC
void ostree_sysroot_query_deployments_for (OstreeSysroot *self,
const char *osname,
OstreeDeployment **out_pending,
OstreeDeployment **out_rollback);
_OSTREE_PUBLIC _OSTREE_PUBLIC
OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot *self, OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot *self,
const char *osname); const char *osname);

View File

@ -88,6 +88,8 @@ ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GErro
gboolean ret = FALSE; gboolean ret = FALSE;
glnx_unref_object OstreeRepo *repo = NULL; glnx_unref_object OstreeRepo *repo = NULL;
OstreeDeployment *booted_deployment = NULL; OstreeDeployment *booted_deployment = NULL;
g_autoptr(OstreeDeployment) pending_deployment = NULL;
g_autoptr(OstreeDeployment) rollback_deployment = NULL;
g_autoptr(GPtrArray) deployments = NULL; g_autoptr(GPtrArray) deployments = NULL;
const int is_tty = isatty (1); const int is_tty = isatty (1);
const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : ""; const char *red_bold_prefix = is_tty ? "\x1b[31m\x1b[1m" : "";
@ -110,6 +112,10 @@ ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GErro
deployments = ostree_sysroot_get_deployments (sysroot); deployments = ostree_sysroot_get_deployments (sysroot);
booted_deployment = ostree_sysroot_get_booted_deployment (sysroot); booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
if (booted_deployment)
ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment,
&rollback_deployment);
if (deployments->len == 0) if (deployments->len == 0)
{ {
g_print ("No deployments.\n"); g_print ("No deployments.\n");
@ -129,11 +135,17 @@ ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GErro
origin = ostree_deployment_get_origin (deployment); origin = ostree_deployment_get_origin (deployment);
g_print ("%c %s %s.%d\n", const char *deployment_status = "";
if (deployment == pending_deployment)
deployment_status = " (pending)";
else if (deployment == rollback_deployment)
deployment_status = " (rollback)";
g_print ("%c %s %s.%d%s\n",
deployment == booted_deployment ? '*' : ' ', deployment == booted_deployment ? '*' : ' ',
ostree_deployment_get_osname (deployment), ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment), ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment)); ostree_deployment_get_deployserial (deployment),
deployment_status);
if (version) if (version)
g_print (" Version: %s\n", version); g_print (" Version: %s\n", version);
switch (unlocked) switch (unlocked)

View File

@ -42,6 +42,8 @@ ${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os=testos
new_mtime=$(stat -c '%.Y' sysroot/ostree/deploy) new_mtime=$(stat -c '%.Y' sysroot/ostree/deploy)
assert_not_streq "${orig_mtime}" "${new_mtime}" assert_not_streq "${orig_mtime}" "${new_mtime}"
${CMD_PREFIX} ostree admin status | tee status.txt ${CMD_PREFIX} ostree admin status | tee status.txt
assert_not_file_has_content status.txt "pending"
assert_not_file_has_content status.txt "rollback"
validate_bootloader validate_bootloader
echo "ok deploy command" echo "ok deploy command"