Skip to content

Commit

Permalink
admin/pin: Add commands to pin booted, pending and rollbacks deployments
Browse files Browse the repository at this point in the history
Add new commands to pin the current, staged and previous deployment for
use in automation and scripting. Right now, it's difficult to pin the
current deployment without needing to look into the output of some other
tooling (like rpm-ostree) to get the index of each deployment. This
index also is not consistent - the current deployment could be 0 when
you first boot the system then 1 shortly after. This change makes it
easy to pin the current or future deployment.

Signed-off-by: Eric Curtin <[email protected]>
  • Loading branch information
ericcurtin committed Jan 24, 2024
1 parent 15b64c2 commit 48a03c7
Showing 1 changed file with 78 additions and 20 deletions.
98 changes: 78 additions & 20 deletions src/ostree/ot-admin-builtin-pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,76 @@
#include "otutil.h"

static gboolean opt_unpin;
static gboolean opt_booted;
static gboolean opt_pending;
static gboolean opt_rollback;

static GOptionEntry options[]
= { { "unpin", 'u', 0, G_OPTION_ARG_NONE, &opt_unpin, "Unset pin", NULL }, { NULL } };
= { { "unpin", 'u', 0, G_OPTION_ARG_NONE, &opt_unpin, "Unset pin", NULL },
{ "booted", 'b', 0, G_OPTION_ARG_NONE, &opt_booted,
"Use the index of the booted deployment", NULL },
{ "pending", 'p', 0, G_OPTION_ARG_NONE, &opt_pending,
"Use the index of the pending deployment", NULL },
{ "rollback", 'r', 0, G_OPTION_ARG_NONE, &opt_rollback,
"Use the index of the rollback deployment", NULL },
{ NULL } };

static gint
get_deployment_index (const OstreeDeployment *target_deployment, const GPtrArray *deployments)
{
for (gint i = 0; i < deployments->len; ++i)
if (deployments->pdata[i] == target_deployment)
return i;

return -1;
}

static gint64
get_deployment_index_for_target (OstreeSysroot *sysroot)
{
g_autoptr (GPtrArray) deployments = ostree_sysroot_get_deployments (sysroot);
const OstreeDeployment *booted_deployment = ostree_sysroot_get_booted_deployment (sysroot);
if (opt_booted)
return get_deployment_index (booted_deployment, deployments);

g_autoptr (OstreeDeployment) pending_deployment = NULL;
g_autoptr (OstreeDeployment) rollback_deployment = NULL;
if (booted_deployment)
ostree_sysroot_query_deployments_for (sysroot, NULL, &pending_deployment, &rollback_deployment);

if (opt_pending)
return get_deployment_index (pending_deployment, deployments);
else if (opt_rollback)
return get_deployment_index (rollback_deployment, deployments);

return -1;
}

static gboolean
do_pinning (OstreeSysroot *sysroot, const gint64 deploy_index, GError **error)
{
g_autoptr (OstreeDeployment) target_deployment
= ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
if (!target_deployment)
return FALSE;

gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
const gboolean desired_pin = !opt_unpin;
if (current_pin == desired_pin)
{
g_print ("Deployment %lld is already %s\n", (long long int)deploy_index,
current_pin ? "pinned" : "unpinned");
}
else
{
if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin, error))
return FALSE;
g_print ("Deployment %lld is now %s\n", (long long int)deploy_index,
desired_pin ? "pinned" : "unpinned");
}

return TRUE;
}

gboolean
ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation,
Expand All @@ -42,6 +109,15 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation
cancellable, error))
return FALSE;

if (opt_booted || opt_pending || opt_rollback)
{
const gint64 deploy_index = get_deployment_index_for_target (sysroot);
if (deploy_index < 0)
return glnx_throw (error, "Unable to get valid index: %lld", (long long int)deploy_index);

return do_pinning (sysroot, deploy_index, error);
}

if (argc < 2)
{
ot_util_usage_error (context, "INDEX must be specified", error);
Expand All @@ -60,26 +136,8 @@ ot_admin_builtin_pin (int argc, char **argv, OstreeCommandInvocation *invocation
if (errno == ERANGE)
return glnx_throw (error, "Index too large: %s", deploy_index_str);

g_autoptr (OstreeDeployment) target_deployment
= ot_admin_get_indexed_deployment (sysroot, deploy_index, error);
if (!target_deployment)
if (!do_pinning (sysroot, deploy_index, error))
return FALSE;

gboolean current_pin = ostree_deployment_is_pinned (target_deployment);
const gboolean desired_pin = !opt_unpin;
if (current_pin == desired_pin)
{
g_print ("Deployment %s is already %s\n", deploy_index_str,
current_pin ? "pinned" : "unpinned");
}
else
{
if (!ostree_sysroot_deployment_set_pinned (sysroot, target_deployment, desired_pin,
error))
return FALSE;
g_print ("Deployment %s is now %s\n", deploy_index_str,
desired_pin ? "pinned" : "unpinned");
}
}

return TRUE;
Expand Down

0 comments on commit 48a03c7

Please sign in to comment.