Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sysroot: Add concept of deployment "pinning" 📌 #1464

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile-man.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ ostree-admin-config-diff.1 ostree-admin-deploy.1 \
ostree-admin-init-fs.1 ostree-admin-instutil.1 ostree-admin-os-init.1 \
ostree-admin-status.1 ostree-admin-set-origin.1 ostree-admin-switch.1 \
ostree-admin-undeploy.1 ostree-admin-upgrade.1 ostree-admin-unlock.1 \
ostree-admin-pin.1 \
ostree-admin.1 ostree-cat.1 ostree-checkout.1 ostree-checksum.1 \
ostree-commit.1 ostree-export.1 ostree-gpg-sign.1 ostree-config.1 \
ostree-diff.1 ostree-fsck.1 ostree-init.1 ostree-log.1 ostree-ls.1 \
Expand Down
1 change: 1 addition & 0 deletions Makefile-ostree.am
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ostree_SOURCES += \
src/ostree/ot-admin-builtin-set-origin.c \
src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-switch.c \
src/ostree/ot-admin-builtin-pin.c \
src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtin-unlock.c \
src/ostree/ot-admin-builtins.h \
Expand Down
3 changes: 3 additions & 0 deletions apidoc/ostree-sections.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,12 @@ ostree_deployment_get_bootconfig
ostree_deployment_get_origin
ostree_deployment_get_origin_relpath
ostree_deployment_get_unlocked
ostree_deployment_is_pinned
ostree_deployment_set_index
ostree_deployment_set_bootserial
ostree_deployment_set_bootconfig
ostree_deployment_set_origin
ostree_deployment_origin_remove_transient_state
ostree_deployment_clone
ostree_deployment_unlocked_state_to_string
<SUBSECTION Standard>
Expand Down Expand Up @@ -508,6 +510,7 @@ ostree_sysroot_init_osname
ostree_sysroot_deployment_set_kargs
ostree_sysroot_deployment_set_mutable
ostree_sysroot_deployment_unlock
ostree_sysroot_deployment_set_pinned
ostree_sysroot_write_deployments
ostree_sysroot_write_deployments_with_options
ostree_sysroot_write_origin_file
Expand Down
31 changes: 31 additions & 0 deletions bash/ostree
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,37 @@ _ostree_admin_os_init() {
return 0
}

_ostree_admin_pin() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, we also need a pin entry in _ostree_admin().

local boolean_options="
$main_boolean_options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

--unpin ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I honestly don't grasp bash completion, I don't care too much about it myself at least for ostree admin. Let's not try to polish it for now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has to be someone out there who has implemented actually generating this stuff from the cli --help, as is it's an enormous maintenance pain doubled by the fact that we need to wrap it in rpm-ostree at least too.

"

local options_with_args="
--sysroot
"

local options_with_args_glob=$( __ostree_to_extglob "$options_with_args" )

case "$prev" in
--sysroot)
__ostree_compreply_dirs_only
return 0
;;
$options_with_args_glob )
return 0
;;
esac

case "$cur" in
-*)
local all_options="$boolean_options $options_with_args"
__ostree_compreply_all_options
;;
esac

return 0
}

_ostree_admin_set_origin() {
local boolean_options="
$main_boolean_options
Expand Down
82 changes: 82 additions & 0 deletions man/ostree-admin-pin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version='1.0'?> <!--*-nxml-*-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<!--
Copyright 2018 Red Hat

SPDX-License-Identifier: LGPL-2.0+

This library 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 License, 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.
-->

<refentry id="ostree">

<refentryinfo>
<title>ostree admin pin</title>
<productname>OSTree</productname>

<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Colin</firstname>
<surname>Walters</surname>
<email>[email protected]</email>
</author>
</authorgroup>
</refentryinfo>

<refmeta>
<refentrytitle>ostree admin pin</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>

<refnamediv>
<refname>ostree-admin-pin</refname>
<refpurpose>Explicitly retain deployment at a given index</refpurpose>
</refnamediv>

<refsynopsisdiv>
<cmdsynopsis>
<command>ostree admin pin</command> <arg choice="req">INDEX</arg>
</cmdsynopsis>
</refsynopsisdiv>

<refsect1>
<title>Description</title>

<para>
Ensures the deployment at <literal>INDEX</literal>, will not be garbage
collected by default. This is termed "pinning". If the
<literal>-u</literal> option is provided, undoes a pinning operation.
</para>
</refsect1>

<refsect1>
<title>Options</title>

<variablelist>
<varlistentry>
<term><option>--unpin</option>,<option>-u</option></term>

<listitem><para>
Undoes a pinning operation.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>

</refentry>
3 changes: 3 additions & 0 deletions src/libostree/libostree-devel.sym
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@

/* Add new symbols here. Release commits should copy this section into -released.sym. */
LIBOSTREE_2018.3 {
ostree_deployment_origin_remove_transient_state;
ostree_sysroot_deployment_set_pinned;
ostree_deployment_is_pinned;
} LIBOSTREE_2018.2;

/* Stub section for the stable release *after* this development one; don't
Expand Down
46 changes: 46 additions & 0 deletions src/libostree/ostree-deployment.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,35 @@ ostree_deployment_set_origin (OstreeDeployment *self, GKeyFile *origin)
self->origin = g_key_file_ref (origin);
}

/**
* ostree_deployment_origin_remove_transient_state:
* @origin: An origin
*
* The intention of an origin file is primarily describe the "inputs" that
* resulted in a deployment, and it's commonly used to derive the new state. For
* example, a key value (in pure libostree mode) is the "refspec". However,
* libostree (or other applications) may want to store "transient" state that
* should not be carried across upgrades.
*
* This function just removes all members of the `libostree-transient` group.
* The name of that group is available to all libostree users; best practice
* would be to prefix values underneath there with a short identifier for your
* software.
*
* Additionally, this function will remove the `origin/unlocked` and
* `origin/override-commit` members; these should be considered transient state
* that should have been under an explicit group.
*
* Since: 2018.3
*/
void
ostree_deployment_origin_remove_transient_state (GKeyFile *origin)
{
g_key_file_remove_group (origin, OSTREE_ORIGIN_TRANSIENT_GROUP, NULL);
g_key_file_remove_key (origin, "origin", "override-commit", NULL);
g_key_file_remove_key (origin, "origin", "unlocked", NULL);
}

void
_ostree_deployment_set_bootcsum (OstreeDeployment *self,
const char *bootcsum)
Expand Down Expand Up @@ -293,3 +322,20 @@ ostree_deployment_get_unlocked (OstreeDeployment *self)
{
return self->unlocked;
}

/**
* ostree_deployment_is_pinned:
* @self: Deployment
*
* See ostree_sysroot_deployment_set_pinned().
*
* Returns: `TRUE` if deployment will not be subject to GC
* Since: 2018.3
*/
gboolean
ostree_deployment_is_pinned (OstreeDeployment *self)
{
if (!self->origin)
return FALSE;
return g_key_file_get_boolean (self->origin, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", NULL);
}
18 changes: 18 additions & 0 deletions src/libostree/ostree-deployment.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ G_BEGIN_DECLS
#define OSTREE_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), OSTREE_TYPE_DEPLOYMENT, OstreeDeployment))
#define OSTREE_IS_DEPLOYMENT(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), OSTREE_TYPE_DEPLOYMENT))

/**
* OSTREE_ORIGIN_TRANSIENT_GROUP:
*
* The name of a `GKeyFile` group for data that should not
* be carried across upgrades. For more information,
* see ostree_deployment_origin_remove_transient_state().
*
* Since: 2018.3
*/
#define OSTREE_ORIGIN_TRANSIENT_GROUP "libostree-transient"

typedef struct _OstreeDeployment OstreeDeployment;

_OSTREE_PUBLIC
Expand Down Expand Up @@ -62,6 +73,10 @@ OstreeBootconfigParser *ostree_deployment_get_bootconfig (OstreeDeployment *self
_OSTREE_PUBLIC
GKeyFile *ostree_deployment_get_origin (OstreeDeployment *self);


_OSTREE_PUBLIC
gboolean ostree_deployment_is_pinned (OstreeDeployment *self);

_OSTREE_PUBLIC
void ostree_deployment_set_index (OstreeDeployment *self, int index);
_OSTREE_PUBLIC
Expand All @@ -71,6 +86,9 @@ void ostree_deployment_set_bootconfig (OstreeDeployment *self, OstreeBootconfigP
_OSTREE_PUBLIC
void ostree_deployment_set_origin (OstreeDeployment *self, GKeyFile *origin);

_OSTREE_PUBLIC
void ostree_deployment_origin_remove_transient_state (GKeyFile *origin);

_OSTREE_PUBLIC
OstreeDeployment *ostree_deployment_clone (OstreeDeployment *self);

Expand Down
16 changes: 12 additions & 4 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,9 @@ merge_configuration (OstreeSysroot *sysroot,
return TRUE;
}

/* Write the origin file for a deployment. */
/* Write the origin file for a deployment; this does not bump the mtime, under
* the assumption the caller may be writing multiple.
*/
static gboolean
write_origin_file_internal (OstreeSysroot *sysroot,
OstreeDeployment *deployment,
Expand Down Expand Up @@ -903,9 +905,15 @@ ostree_sysroot_write_origin_file (OstreeSysroot *sysroot,
GCancellable *cancellable,
GError **error)
{
return write_origin_file_internal (sysroot, deployment, new_origin,
GLNX_FILE_REPLACE_DATASYNC_NEW,
cancellable, error);
if (!write_origin_file_internal (sysroot, deployment, new_origin,
GLNX_FILE_REPLACE_DATASYNC_NEW,
cancellable, error))
return FALSE;

if (!_ostree_sysroot_bump_mtime (sysroot, error))
return FALSE;

return TRUE;
}

typedef struct {
Expand Down
44 changes: 44 additions & 0 deletions src/libostree/ostree-sysroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1572,12 +1572,14 @@ ostree_sysroot_simple_write_deployment (OstreeSysroot *sysroot,

/* Retain deployment if:
* - we're explicitly asked to, or
* - it's pinned
* - the deployment is for another osname, or
* - we're keeping pending deployments and this is a pending deployment, or
* - this is the merge or boot deployment, or
* - we're keeping rollback deployments and this is a rollback deployment
*/
if (retain
|| ostree_deployment_is_pinned (deployment)
|| !osname_matches
|| (retain_pending && !passed_crossover)
|| (is_booted || is_merge)
Expand Down Expand Up @@ -1832,3 +1834,45 @@ ostree_sysroot_deployment_unlock (OstreeSysroot *self,

return TRUE;
}

/**
* ostree_sysroot_deployment_set_pinned:
* @self: Sysroot
* @deployment: A deployment
* @is_pinned: Whether or not deployment will be automatically GC'd
* @error: Error
*
* By default, deployments may be subject to garbage collection. Typical uses of
* libostree only retain at most 2 deployments. If @is_pinned is `TRUE`, a
* metadata bit will be set causing libostree to avoid automatic GC of the
* deployment. However, this is really an "advisory" note; it's still possible
* for e.g. older versions of libostree unaware of pinning to GC the deployment.
*
* This function does nothing and returns successfully if the deployment
* is already in the desired pinning state.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since: ?

*
* Since: 2018.3
*/
gboolean
ostree_sysroot_deployment_set_pinned (OstreeSysroot *self,
OstreeDeployment *deployment,
gboolean is_pinned,
GError **error)
{
const gboolean current_pin = ostree_deployment_is_pinned (deployment);
if (is_pinned == current_pin)
return TRUE;

g_autoptr(OstreeDeployment) deployment_clone = ostree_deployment_clone (deployment);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused here. Why do we need ostree_deployment_clone? Can't we just ostree_deployment_get_origin and modify that? (Actually, shouldn't we do that so that the sysroot deployment array is up to date?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the sysroot array should be immutable. That actually reveals a bug, we need to bump the mtime so e.g. rpm-ostree will do a reload.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh got it, that makes sense.

GKeyFile *origin_clone = ostree_deployment_get_origin (deployment_clone);

if (is_pinned)
g_key_file_set_boolean (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", TRUE);
else
g_key_file_remove_key (origin_clone, OSTREE_ORIGIN_TRANSIENT_GROUP, "pinned", NULL);

if (!ostree_sysroot_write_origin_file (self, deployment, origin_clone, NULL, error))
return FALSE;

return TRUE;
}
6 changes: 6 additions & 0 deletions src/libostree/ostree-sysroot.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@ gboolean ostree_sysroot_deployment_set_mutable (OstreeSysroot *self,
GCancellable *cancellable,
GError **error);

_OSTREE_PUBLIC
gboolean ostree_sysroot_deployment_set_pinned (OstreeSysroot *self,
OstreeDeployment *deployment,
gboolean is_pinned,
GError **error);

_OSTREE_PUBLIC
gboolean ostree_sysroot_deployment_unlock (OstreeSysroot *self,
OstreeDeployment *deployment,
Expand Down
Loading