status: New builtin for system administrators to see deployments

This allows administrators to configure between deployments and easily see which deployment
they are booted into as well as indicating which is chronologically most recent.  This makes
the process more user-friendly, rather than requiring the user to remember which deployment
checksum corresponds to the most recent upgrade.
This commit is contained in:
Anne LoVerso 2014-06-11 13:47:10 -04:00 committed by Colin Walters
parent 227137ed41
commit 489b2e301f
5 changed files with 172 additions and 0 deletions

View File

@ -46,6 +46,7 @@ rpm_ostree_SOURCES = src/main.c \
src/rpmostree-builtin-upgrade.c \
src/rpmostree-builtin-rollback.c \
src/rpmostree-builtin-rebase.c \
src/rpmostree-builtin-status.c \
src/rpmostree-compose-builtin-tree.c \
src/rpmostree-compose-builtin-sign.c \
$(NULL)

View File

@ -149,6 +149,18 @@ Boston, MA 02111-1307, USA.
<literal>tree</literal> and
<literal>sign</literal>.</para></listitem>
</varlistentry>
<varlistentry>
<term><command>status</command></term>
<listitem>
<para>
Gives information pertaining to the current deployment in use. Lists the names and refspecs of all possible deployments in order, such that the first deployment in the list is the default upon boot. The deployment marked with * is the current booted deployment, and marking with 'r' indicates the most recent upgrade (the newest deployment version).
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -36,6 +36,7 @@ static RpmOstreeCommand commands[] = {
{ "upgrade", rpmostree_builtin_upgrade, 0 },
{ "rebase", rpmostree_builtin_rebase, 0 },
{ "rollback", rpmostree_builtin_rollback, 0 },
{ "status", rpmostree_builtin_status, 0 },
{ NULL }
};

View File

@ -0,0 +1,157 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2014 Colin Walters <walters@verbum.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <glib-unix.h>
#include "rpmostree-builtins.h"
#include "rpmostree-treepkgdiff.h"
#include "libgsystem.h"
gboolean
rpmostree_builtin_status (int argc,
char **argv,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeSysroot *sysroot = NULL;
gs_unref_ptrarray GPtrArray *deployments = NULL; // list of all depoyments
OstreeDeployment *booted_deployment = NULL; // current booted deployment
GOptionContext *context = g_option_context_new ("- Get the version of the booted system");
char *default_boot_message = NULL; // is this deployment default? either "" or " not"
char *default_instruct = NULL; // how to use rollback to change defauly; depending on state
char *version_message = NULL; // is this the most recent version? either "" or " not"
OstreeDeployment *most_recent = NULL; // most recent deployment
guint i;
guint j;
if (!g_option_context_parse (context, &argc, &argv, error))
goto out;
sysroot = ostree_sysroot_new_default ();
if (!ostree_sysroot_load (sysroot, cancellable, error))
goto out;
booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
if (booted_deployment == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Not currently booted into an OSTree system");
goto out;
}
deployments = ostree_sysroot_get_deployments (sysroot);
g_assert (booted_deployment != NULL);
if (deployments->len < 2)
{
g_print ("Note: Fewer than two versions found\n");
default_boot_message = default_instruct = version_message = "";
goto print;
}
// determine most recent version
for (i=0; i<deployments->len; i++)
{
if (most_recent == NULL)
most_recent = deployments->pdata[i];
else
{
gs_unref_variant GVariant *version = NULL;
gs_unref_variant GVariant *recent_version = NULL;
gs_unref_object OstreeRepo *repo = NULL;
const char *csum = ostree_deployment_get_csum(deployments->pdata[i]);
const char *recent_csum = ostree_deployment_get_csum(most_recent);
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
goto out;
if (!ostree_repo_load_variant (repo,
OSTREE_OBJECT_TYPE_COMMIT,
csum,
&version,
error))
goto out;
if (!ostree_repo_load_variant (repo,
OSTREE_OBJECT_TYPE_COMMIT,
recent_csum,
&recent_version,
error))
goto out;
// the newer (most recent) version will have a larger timestamp
// i.e. if a > b then a is newer than b
if (ostree_commit_get_timestamp (version) > ostree_commit_get_timestamp(recent_version))
most_recent = deployments->pdata[i];
}
}
if (deployments->pdata[0] == booted_deployment) // if current deployment is default
{
default_boot_message = "";
default_instruct = "Use command 'rpm-ostree rollback' to switch defaults\n";
}
else // current boot not default
{
default_boot_message = " not";
default_instruct = "Use command 'rpm-ostree rollback' to make it default\n";
}
version_message = (booted_deployment == most_recent) ? "" : " not";
print:
for (j=0; j<deployments->len; j++)
{
OstreeDeployment *deployment = deployments->pdata[j];
GKeyFile *origin;
g_print ("%c %c %s %s.%d\n",
deployment == most_recent ? 'r' : ' ',
deployment == booted_deployment ? '*' : ' ',
ostree_deployment_get_osname (deployment),
ostree_deployment_get_csum (deployment),
ostree_deployment_get_deployserial (deployment));
origin = ostree_deployment_get_origin (deployment);
if (!origin)
g_print (" origin: none\n");
else
{
gs_free char *origin_refspec = g_key_file_get_string (origin, "origin", "refspec", NULL);
if (!origin_refspec)
g_print (" origin: <unknown origin type>\n");
else
g_print (" origin refspec: %s\n", origin_refspec);
}
}
g_print ("\nThe current booted deployment is%s the most recent upgrade\n", version_message);
g_print ("The current booted deployment is%s the default\n", default_boot_message);
g_print ("%s", default_instruct);
ret = TRUE;
out:
return ret;
}

View File

@ -36,6 +36,7 @@ BUILTINPROTO(compose);
BUILTINPROTO(upgrade);
BUILTINPROTO(rebase);
BUILTINPROTO(rollback);
BUILTINPROTO(status);
#undef BUILTINPROTO