lib/sysroot: Add API to get pending/rollback for given stateroot
authorAnton Gerasimov <anton@advancedtelematic.com>
Thu, 1 Jun 2017 10:43:50 +0000 (12:43 +0200)
committerAtomic Bot <atomic-devel@projectatomic.io>
Wed, 14 Jun 2017 09:56:01 +0000 (09:56 +0000)
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

apidoc/ostree-sections.txt
src/libostree/libostree.sym
src/libostree/ostree-sysroot.c
src/libostree/ostree-sysroot.h
src/ostree/ot-admin-builtin-status.c
tests/admin-test.sh

index 5e111a966a8921b192fda1d0249b92d00dc324d7..116c50e83dcda6ff2fbd09caf25caf4556b96cad 100644 (file)
@@ -496,6 +496,7 @@ ostree_sysroot_write_deployments_with_options
 ostree_sysroot_write_origin_file
 ostree_sysroot_deploy_tree
 ostree_sysroot_get_merge_deployment
+ostree_sysroot_query_deployments_for
 ostree_sysroot_origin_new_from_refspec
 OstreeSysrootSimpleWriteDeploymentFlags
 ostree_sysroot_simple_write_deployment
index 612eb8acdfc59e2b7718f0f7266ec435b8bc3a26..b307548dd612ddbafbfc4f21935dbf9e6a0af38a 100644 (file)
@@ -405,6 +405,7 @@ global:
 LIBOSTREE_2017.7 {
 global:
   ostree_sysroot_repo;
+  ostree_sysroot_query_deployments_for;
 } LIBOSTREE_2017.6;
 
 /* Stub section for the stable release *after* this development one; don't
index a3e9e75d20f3e75081d3bee99f139c9f918932cf..90868aae93fdb0cee985a682b32eea166514704a 100644 (file)
@@ -1107,6 +1107,63 @@ find_booted_deployment (OstreeSysroot       *self,
   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:
  * @self: Sysroot
@@ -1132,23 +1189,13 @@ ostree_sysroot_get_merge_deployment (OstreeSysroot     *self,
    */
   if (self->booted_deployment &&
       g_strcmp0 (ostree_deployment_get_osname (self->booted_deployment), osname) == 0)
-    {
       return g_object_ref (self->booted_deployment);
-    }
   else
     {
-      guint i;
-      for (i = 0; i < self->deployments->len; i++)
-        {
-          OstreeDeployment *deployment = self->deployments->pdata[i];
-
-          if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
-            continue;
-
-          return g_object_ref (deployment);
-        }
+      g_autoptr(OstreeDeployment) pending = NULL;
+      ostree_sysroot_query_deployments_for (self, osname, &pending, NULL);
+      return g_steal_pointer (&pending);
     }
-  return NULL;
 }
 
 /**
index e5969e9e2795a90e0929cec784e9ce35b7b25bad..3d2446f97b3e348bfe62961f69559534486718b6 100644 (file)
@@ -187,6 +187,12 @@ gboolean ostree_sysroot_deployment_unlock (OstreeSysroot     *self,
                                            GCancellable      *cancellable,
                                            GError           **error);
 
+_OSTREE_PUBLIC
+void ostree_sysroot_query_deployments_for (OstreeSysroot     *self,
+                                           const char        *osname,
+                                           OstreeDeployment  **out_pending,
+                                           OstreeDeployment  **out_rollback);
+
 _OSTREE_PUBLIC
 OstreeDeployment *ostree_sysroot_get_merge_deployment (OstreeSysroot     *self,
                                                        const char        *osname);
index 79621a1d141265e1b1afd402f37d16359f34468b..a437e7cfe5186a837f44d4f14febd739de35b4a0 100644 (file)
@@ -88,6 +88,8 @@ ot_admin_builtin_status (int argc, char **argv, GCancellable *cancellable, GErro
   gboolean ret = FALSE;
   glnx_unref_object OstreeRepo *repo = NULL;
   OstreeDeployment *booted_deployment = NULL;
+  g_autoptr(OstreeDeployment) pending_deployment = NULL;
+  g_autoptr(OstreeDeployment) rollback_deployment = NULL;
   g_autoptr(GPtrArray) deployments = NULL;
   const int is_tty = isatty (1);
   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);
   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)
     {
       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);
 
-          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 ? '*' : ' ',
                    ostree_deployment_get_osname (deployment),
                    ostree_deployment_get_csum (deployment),
-                   ostree_deployment_get_deployserial (deployment));
+                   ostree_deployment_get_deployserial (deployment),
+                   deployment_status);
           if (version)
             g_print ("    Version: %s\n", version);
           switch (unlocked)
index cc06fe6f0c73dbd3383939bad1820c8ab91eaa5a..671fd905aebcc71bfd2de3e332ea94dbfa41cfe4 100644 (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)
 assert_not_streq "${orig_mtime}" "${new_mtime}"
 ${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
 
 echo "ok deploy command"