Merge pull request #2296 from cgwalters/commit-os

Add an API+CLI to inject metadata for bootable OSTree commits
This commit is contained in:
OpenShift Merge Robot 2021-03-12 17:22:45 -05:00 committed by GitHub
commit d522f261db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 185 additions and 9 deletions

View File

@ -28,6 +28,7 @@ libostree_public_headers = \
src/libostree/ostree-dummy-enumtypes.h \
src/libostree/ostree-mutable-tree.h \
src/libostree/ostree-repo.h \
src/libostree/ostree-repo-os.h \
src/libostree/ostree-types.h \
src/libostree/ostree-repo-file.h \
src/libostree/ostree-diff.h \

View File

@ -92,6 +92,7 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-ref.c \
src/libostree/ostree-remote.c \
src/libostree/ostree-remote-private.h \
src/libostree/ostree-repo-os.c \
src/libostree/ostree-repo.c \
src/libostree/ostree-repo-checkout.c \
src/libostree/ostree-repo-commit.c \
@ -186,10 +187,10 @@ endif # USE_GPGME
symbol_files = $(top_srcdir)/src/libostree/libostree-released.sym
## Uncomment this include when adding new development symbols.
#if BUILDOPT_IS_DEVEL_BUILD
#symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
#endif
# Uncomment this include when adding new development symbols.
if BUILDOPT_IS_DEVEL_BUILD
symbol_files += $(top_srcdir)/src/libostree/libostree-devel.sym
endif
# http://blog.jgc.org/2007/06/escaping-comma-and-space-in-gnu-make.html
wl_versionscript_arg = -Wl,--version-script=

View File

@ -152,6 +152,7 @@ ostree_validate_structureof_dirtree
ostree_validate_structureof_dirmeta
ostree_commit_get_parent
ostree_commit_get_timestamp
ostree_commit_metadata_for_bootable
ostree_commit_get_content_checksum
ostree_commit_get_object_sizes
OstreeCommitSizesEntry

View File

@ -321,6 +321,7 @@ _ostree_commit() {
--canonical-permissions
--editor -e
--generate-sizes
--bootable
--link-checkout-speedup
--no-xattrs
--orphan

View File

@ -186,6 +186,13 @@ Boston, MA 02111-1307, USA.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--bootable</option></term>
<listitem><para>
Inject standard metadata for a bootable Linux filesystem tree.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--link-checkout-speedup</option></term>

View File

@ -22,6 +22,11 @@
- uncomment the include in Makefile-libostree.am
*/
LIBOSTREE_2021.1 {
global:
ostree_commit_metadata_for_bootable;
} LIBOSTREE_2020.8;
/* Stub section for the stable release *after* this development one; don't
* edit this other than to update the year. This is just a copy/paste
* source. Replace $LASTSTABLE with the last stable version, and $NEWVERSION

View File

@ -0,0 +1,83 @@
/*
* 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.
*/
#include "config.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <gio/gfiledescriptorbased.h>
#include <gio/gunixinputstream.h>
#include "libglnx.h"
#include "ostree.h"
#include "ostree-core-private.h"
#include "ostree-repo-os.h"
#include "otutil.h"
/**
* ostree_commit_metadata_for_bootable:
* @root: Root filesystem to be committed
* @dict: Dictionary to update
*
* Update provided @dict with standard metadata for bootable OSTree commits.
* Since: 2021.1
*/
_OSTREE_PUBLIC
gboolean
ostree_commit_metadata_for_bootable (GFile *root, GVariantDict *dict, GCancellable *cancellable, GError **error)
{
g_autoptr(GFile) modules = g_file_resolve_relative_path (root, "usr/lib/modules");
g_autoptr(GFileEnumerator) dir_enum
= g_file_enumerate_children (modules, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error);
if (!dir_enum)
return glnx_prefix_error (error, "Opening usr/lib/modules");
g_autofree char *linux_release = NULL;
while (TRUE)
{
GFileInfo *child_info;
GFile *child_path;
if (!g_file_enumerator_iterate (dir_enum, &child_info, &child_path,
cancellable, error))
return FALSE;
if (child_info == NULL)
break;
if (g_file_info_get_file_type (child_info) != G_FILE_TYPE_DIRECTORY)
continue;
g_autoptr(GFile) kernel_path = g_file_resolve_relative_path (child_path, "vmlinuz");
if (!g_file_query_exists (kernel_path, NULL))
continue;
if (linux_release != NULL)
return glnx_throw (error, "Multiple kernels found in /usr/lib/modules");
linux_release = g_strdup (g_file_info_get_name (child_info));
}
if (linux_release)
{
g_variant_dict_insert (dict, OSTREE_METADATA_KEY_BOOTABLE, "b", TRUE);
g_variant_dict_insert (dict, OSTREE_METADATA_KEY_LINUX, "s", linux_release);
return TRUE;
}
return glnx_throw (error, "No kernel found in /usr/lib/modules");
}

View File

@ -0,0 +1,47 @@
/*
* 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.
*/
#pragma once
#include <sys/stat.h>
#include <gio/gio.h>
#include <ostree-types.h>
G_BEGIN_DECLS
/**
* OSTREE_METADATA_KEY_BOOTABLE:
*
* GVariant type `b`: Set if this commit is intended to be bootable
* Since: 2021.1
*/
#define OSTREE_METADATA_KEY_BOOTABLE "ostree.bootable"
/**
* OSTREE_METADATA_KEY_LINUX:
*
* GVariant type `s`: Contains the Linux kernel release (i.e. `uname -r`)
* Since: 2021.1
*/
#define OSTREE_METADATA_KEY_LINUX "ostree.linux"
_OSTREE_PUBLIC
gboolean
ostree_commit_metadata_for_bootable (GFile *root, GVariantDict *dict, GCancellable *cancellable, GError **error);
G_END_DECLS

View File

@ -24,6 +24,7 @@
#include <ostree-async-progress.h>
#include <ostree-core.h>
#include <ostree-repo.h>
#include <ostree-repo-os.h>
#include <ostree-mutable-tree.h>
#include <ostree-remote.h>
#include <ostree-repo-file.h>

View File

@ -35,6 +35,7 @@
static char *opt_subject;
static char *opt_body;
static char *opt_bootable;
static char *opt_body_file;
static gboolean opt_editor;
static char *opt_parent;
@ -112,6 +113,7 @@ static GOptionEntry options[] = {
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &opt_owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &opt_owner_gid, "Set file ownership group id", "GID" },
{ "canonical-permissions", 0, 0, G_OPTION_ARG_NONE, &opt_canonical_permissions, "Canonicalize permissions in the same way bare-user does for hardlinked files", NULL },
{ "bootable", 0, 0, G_OPTION_ARG_NONE, &opt_bootable, "Flag this commit as a bootable OSTree (e.g. contains a Linux kernel)", NULL },
{ "mode-ro-executables", 0, 0, G_OPTION_ARG_NONE, &opt_ro_executables, "Ensure executable files are not writable", NULL },
{ "no-xattrs", 0, 0, G_OPTION_ARG_NONE, &opt_no_xattrs, "Do not import extended attributes", NULL },
{ "selinux-policy", 0, 0, G_OPTION_ARG_FILENAME, &opt_selinux_policy, "Set SELinux labels based on policy in root filesystem PATH (may be /)", "PATH" },
@ -501,7 +503,7 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
goto out;
}
if (opt_metadata_strings || opt_metadata_variants || opt_metadata_keep)
if (opt_metadata_strings || opt_metadata_variants || opt_metadata_keep || opt_bootable)
{
g_autoptr(GVariantBuilder) builder =
g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
@ -841,6 +843,17 @@ ostree_builtin_commit (int argc, char **argv, OstreeCommandInvocation *invocatio
fill_bindings (repo, old_metadata, &metadata);
}
if (opt_bootable)
{
g_autoptr(GVariant) old_metadata = g_steal_pointer (&metadata);
g_auto(GVariantDict) bootmeta;
g_variant_dict_init (&bootmeta, old_metadata);
if (!ostree_commit_metadata_for_bootable (root, &bootmeta, cancellable, error))
goto out;
metadata = g_variant_ref_sink (g_variant_dict_end (&bootmeta));
}
if (!opt_timestamp)
{
if (!ostree_repo_write_commit (repo, parent, opt_subject, commit_body, metadata,

View File

@ -65,6 +65,12 @@ assert_not_file_has_content status.txt "pending"
assert_not_file_has_content status.txt "rollback"
validate_bootloader
# Test the bootable and linux keys
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo --print-metadata-key=ostree.linux show testos:testos/buildmaster/x86_64-runtime >out.txt
assert_file_has_content_literal out.txt 3.6.0
${CMD_PREFIX} ostree --repo=sysroot/ostree/repo --print-metadata-key=ostree.bootable show testos:testos/buildmaster/x86_64-runtime >out.txt
assert_file_has_content_literal out.txt true
echo "ok deploy command"
${CMD_PREFIX} ostree admin --print-current-dir > curdir

View File

@ -21,7 +21,7 @@
set -euo pipefail
echo "1..$((86 + ${extra_basic_tests:-0}))"
echo "1..$((87 + ${extra_basic_tests:-0}))"
CHECKOUT_U_ARG=""
CHECKOUT_H_ARGS="-H"
@ -226,6 +226,13 @@ $OSTREE commit ${COMMIT_ARGS} -b test2-no-parent -s '' --parent=none $test_tmpdi
assert_streq $($OSTREE log test2-no-parent |grep '^commit' | wc -l) "1"
echo "ok commit no parent"
cd ${test_tmpdir}
if $OSTREE commit ${COMMIT_ARGS} -b test-bootable --bootable $test_tmpdir/checkout-test2-4 2>err.txt; then
fatal "committed non-bootable tree"
fi
assert_file_has_content err.txt "error: .*No such file or directory"
echo "ok commit fails bootable if no kernel"
cd ${test_tmpdir}
# Do the --bind-ref=<the other test branch>, so we store both branches sorted
# in metadata and thus the checksums remain the same.

View File

@ -415,11 +415,14 @@ setup_os_repository () {
echo "an hmac file" > ${hmac_path}
bootcsum=$(cat ${kernel_path} ${initramfs_path} | sha256sum | cut -f 1 -d ' ')
export bootcsum
bootable_flag=""
# Add the checksum for legacy dirs (/boot, /usr/lib/ostree-boot), but not
# /usr/lib/modules.
if [[ $bootdir != usr/lib/modules/* ]]; then
mv ${kernel_path}{,-${bootcsum}}
mv ${initramfs_path}{,-${bootcsum}}
else
bootable_flag="--bootable"
fi
echo "an executable" > usr/bin/sh
@ -439,12 +442,12 @@ EOF
mkdir -p usr/etc/testdirectory
echo "a default daemon file" > usr/etc/testdirectory/test
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit ${bootable_flag} --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-runtime -s "Build"
# Ensure these commits have distinct second timestamps
sleep 2
echo "a new executable" > usr/bin/sh
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.10 -b testos/buildmaster/x86_64-runtime -s "Build"
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit ${bootable_flag} --add-metadata-string version=1.0.10 -b testos/buildmaster/x86_64-runtime -s "Build"
cd ${test_tmpdir}
rm -rf osdata-devel
@ -453,7 +456,7 @@ EOF
cd osdata-devel
mkdir -p usr/include
echo "a development header" > usr/include/foo.h
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-devel -s "Build"
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo commit ${bootable_flag} --add-metadata-string version=1.0.9 -b testos/buildmaster/x86_64-devel -s "Build"
${CMD_PREFIX} ostree --repo=${test_tmpdir}/testos-repo fsck -q