From e5d8ebca88f8369f0a3f40d3b159ed37097cdebd Mon Sep 17 00:00:00 2001 From: Robert Fairley Date: Thu, 14 Feb 2019 16:18:01 -0500 Subject: [PATCH] Add sysroot.bootloader repo config key The sysroot.bootloader key is used to configure the bootloader that OSTree uses when deploying a sysroot. Having this key allows specifying behavior not to use the default bootloader backend code, which is preferable when creating a first deployment from the sysroot (#1774). As of now, the key can take the values "auto" or "none". If the key is not given, the value defaults to "auto". "auto" causes _ostree_sysroot_query_bootloader() to be used when writing a new deployment, which is the original behavior that dynamically detects which bootloader to use. "none" avoids querying the bootloader dynamically. The BLS config fragments are still written to sysroot/boot/loader/entries for use by higher-level software. More values can be supported in future to specify a single bootloader, different behavior for the bootloader code, or a list of bootloaders to try. Resolves: #1774 --- Makefile-tests.am | 1 + man/ostree.repo-config.xml | 68 ++++++++++++++++++++------- src/libostree/ostree-repo-private.h | 1 + src/libostree/ostree-repo.c | 46 ++++++++++++++++++ src/libostree/ostree-repo.h | 3 ++ src/libostree/ostree-sysroot-deploy.c | 22 ++++++++- tests/libtest.sh | 8 ++++ tests/test-admin-deploy-none.sh | 49 +++++++++++++++++++ tests/test-config.sh | 4 +- 9 files changed, 183 insertions(+), 19 deletions(-) create mode 100755 tests/test-admin-deploy-none.sh diff --git a/Makefile-tests.am b/Makefile-tests.am index 417a304a42..2c0916f620 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -102,6 +102,7 @@ _installed_or_uninstalled_test_scripts = \ tests/test-admin-deploy-etcmerge-cornercases.sh \ tests/test-admin-deploy-uboot.sh \ tests/test-admin-deploy-grub2.sh \ + tests/test-admin-deploy-none.sh \ tests/test-admin-deploy-bootid-gc.sh \ tests/test-admin-instutil-set-kargs.sh \ tests/test-admin-upgrade-not-backwards.sh \ diff --git a/man/ostree.repo-config.xml b/man/ostree.repo-config.xml index 618b524b69..90ac908399 100644 --- a/man/ostree.repo-config.xml +++ b/man/ostree.repo-config.xml @@ -109,22 +109,22 @@ Boston, MA 02111-1307, USA. ensure files are on stable storage when performing operations such as commits, pulls, and checkouts. Defaults to true. - - If you disable fsync, OSTree will no longer be robust - against kernel crashes or power loss. - - - You might choose to disable this for local development - repositories, under the assumption they can be recreated from - source. Similarly, you could disable for a mirror where you could - re-pull. - - - For the system repository, you might choose to disable fsync - if you have uninterruptable power supplies and a well tested - kernel. - - + + If you disable fsync, OSTree will no longer be robust + against kernel crashes or power loss. + + + You might choose to disable this for local development + repositories, under the assumption they can be recreated from + source. Similarly, you could disable for a mirror where you could + re-pull. + + + For the system repository, you might choose to disable fsync + if you have uninterruptable power supplies and a well tested + kernel. + + @@ -333,6 +333,42 @@ Boston, MA 02111-1307, USA. + + [sysroot] Section Options + + + Options for the sysroot, which contains the OSTree repository, + deployments, and stateroots. The following entries are defined: + + + + + + bootloader + Configure the bootloader that OSTree uses when + deploying the sysroot. This may take the values + bootloader=none or bootloader=auto. + Default is auto. + + + If none, then OSTree will generate only BLS (Boot + Loader Specification) fragments in sysroot/boot/loader/entries/ + for the deployment. + + + If auto, then in addition to generating BLS + fragments, OSTree will dynamically check for the existence of grub2, + uboot, and syslinux bootloaders. If one of the bootloaders is found, + then OSTree will generate a config for the bootloader found. For + example, grub2-mkconfig is run for the grub2 case. + + + + + + + + /etc/ostree/remotes.d diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 40be72633d..6bc74c2d23 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -169,6 +169,7 @@ struct OstreeRepo { guint64 payload_link_threshold; gint fs_support_reflink; /* The underlying filesystem has support for ioctl (FICLONE..) */ gchar **repo_finders; + gchar *bootloader; /* Configure which bootloader to use. */ OstreeRepo *parent_repo; }; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index a71f3bdaff..003365031c 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -3113,6 +3113,32 @@ reload_remote_config (OstreeRepo *self, return TRUE; } +static gboolean +reload_sysroot_config (OstreeRepo *self, + GCancellable *cancellable, + GError **error) +{ + { g_autofree char *bootloader = NULL; + + if (!ot_keyfile_get_value_with_default_group_optional (self->config, "sysroot", + "bootloader", "auto", + &bootloader, error)) + return FALSE; + + /* TODO: possibly later add support for specifying a generic bootloader + * binary "x" in /usr/lib/ostree/bootloaders/x). See: + * https://github.com/ostreedev/ostree/issues/1719 + * https://github.com/ostreedev/ostree/issues/1801 + */ + if (!(g_str_equal (bootloader, "auto") || g_str_equal (bootloader, "none"))) + return glnx_throw (error, "Invalid bootloader configuration: '%s'", bootloader); + + self->bootloader = g_steal_pointer (&bootloader); + } + + return TRUE; +} + /** * ostree_repo_reload_config: * @self: repo @@ -3131,6 +3157,8 @@ ostree_repo_reload_config (OstreeRepo *self, return FALSE; if (!reload_remote_config (self, cancellable, error)) return FALSE; + if (!reload_sysroot_config (self, cancellable, error)) + return FALSE; return TRUE; } @@ -6064,3 +6092,21 @@ ostree_repo_get_default_repo_finders (OstreeRepo *self) return (const gchar * const *)self->repo_finders; } + +/** + * ostree_repo_get_bootloader: + * @self: an #OstreeRepo + * + * Get the bootloader configured. See the documentation for the + * "sysroot.bootloader" config key. + * + * Returns: bootloader configuration for the sysroot + * Since: 2019.2 + */ +const gchar * +ostree_repo_get_bootloader (OstreeRepo *self) +{ + g_return_val_if_fail (OSTREE_IS_REPO (self), NULL); + + return self->bootloader; +} diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index 6e325b8b30..7eb983cfa0 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -115,6 +115,9 @@ gboolean ostree_repo_set_collection_id (OstreeRepo *self, _OSTREE_PUBLIC const gchar * const * ostree_repo_get_default_repo_finders (OstreeRepo *self); +_OSTREE_PUBLIC +const gchar * ostree_repo_get_bootloader (OstreeRepo *self); + _OSTREE_PUBLIC GFile * ostree_repo_get_path (OstreeRepo *self); diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index b16f65b334..5712991834 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -2310,6 +2310,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, gboolean bootloader_is_atomic = FALSE; SyncStats syncstats = { 0, }; g_autoptr(OstreeBootloader) bootloader = NULL; + const char *bootloader_config = NULL; if (!requires_new_bootversion) { if (!create_new_bootlinks (self, self->bootversion, @@ -2342,8 +2343,24 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, return glnx_throw_errno_prefix (error, "Remounting /boot read-write"); } - if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error)) - return FALSE; + g_autoptr(OstreeRepo) repo = NULL; + if (!ostree_sysroot_get_repo (self, &repo, cancellable, error)) + return glnx_throw (error, "Loading repo config"); + + bootloader_config = ostree_repo_get_bootloader (repo); + + g_debug ("Using bootloader configuration: %s", bootloader_config); + + if (g_str_equal (bootloader_config, "auto")) + { + if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error)) + return FALSE; + } + else if (g_str_equal (bootloader_config, "none")) + { + /* No bootloader specified; do not query bootloaders to run. */ + } + bootloader_is_atomic = bootloader != NULL && _ostree_bootloader_is_atomic (bootloader); /* Note equivalent of try/finally here */ @@ -2375,6 +2392,7 @@ ostree_sysroot_write_deployments_with_options (OstreeSysroot *self, sd_journal_send ("MESSAGE_ID=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(OSTREE_DEPLOYMENT_COMPLETE_ID), "MESSAGE=%s", msg, "OSTREE_BOOTLOADER=%s", bootloader ? _ostree_bootloader_get_name (bootloader) : "none", + "OSTREE_BOOTLOADER_CONFIG=%s", bootloader_config, "OSTREE_BOOTLOADER_ATOMIC=%s", bootloader_is_atomic ? "yes" : "no", "OSTREE_DID_BOOTSWAP=%s", requires_new_bootversion ? "yes" : "no", "OSTREE_N_DEPLOYMENTS=%u", new_deployments->len, diff --git a/tests/libtest.sh b/tests/libtest.sh index f09f4a2c52..a737a9bb5a 100755 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -355,6 +355,11 @@ setup_os_boot_grub2() { esac } +setup_os_boot_configured_bootloader() { + bootloader_keyval=$1 + ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo config set ${bootloader_keyval} +} + setup_os_repository () { mode=$1 shift @@ -448,6 +453,9 @@ EOF *grub2*) setup_os_boot_grub2 "${bootmode}" ;; + sysroot\.bootloader*) + setup_os_boot_configured_bootloader "${bootmode}" + ;; esac cd ${test_tmpdir} diff --git a/tests/test-admin-deploy-none.sh b/tests/test-admin-deploy-none.sh new file mode 100755 index 0000000000..66b60c9639 --- /dev/null +++ b/tests/test-admin-deploy-none.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# Copyright (C) 2019 Robert Fairley +# +# 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. + +set -euo pipefail + +. $(dirname $0)/libtest.sh + +# Exports OSTREE_SYSROOT so --sysroot not needed. +setup_os_repository "archive" "sysroot.bootloader none" + +extra_admin_tests=2 + +. $(dirname $0)/admin-test.sh + +# Test that the bootloader configuration "none" generates BLS config snippets. +cd ${test_tmpdir} +rm httpd osdata testos-repo sysroot -rf +setup_os_repository "archive" "sysroot.bootloader none" +${CMD_PREFIX} ostree pull-local --repo=sysroot/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime +# Test grub2 does not get detected with bootloader configuration "none" +# (see https://github.com/ostreedev/ostree/issues/1774) +mkdir -p sysroot/boot/grub2 && touch sysroot/boot/grub2/grub.cfg +${CMD_PREFIX} ostree admin deploy --karg=root=LABEL=MOO --karg=quiet --os testos testos/buildmaster/x86_64-runtime > out.txt +assert_file_has_content out.txt "Bootloader updated.*" +assert_file_has_content sysroot/boot/loader/entries/ostree-1-testos.conf 'options.* root=LABEL=MOO' +assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/vmlinuz-3.6.0 'a kernel' +assert_file_has_content sysroot/boot/ostree/testos-${bootcsum}/initramfs-3.6.0.img 'an initramfs' +echo "ok generate bls config on first deployment" + +# TODO: add tests to try setting with an unsupported bootloader config, +# once https://github.com/ostreedev/ostree/issues/1827 is solved. diff --git a/tests/test-config.sh b/tests/test-config.sh index b1ea3e5e35..e5be75fd3c 100755 --- a/tests/test-config.sh +++ b/tests/test-config.sh @@ -34,7 +34,7 @@ ${CMD_PREFIX} ostree config --repo=repo get --group=core repo_version >> list.tx ${CMD_PREFIX} ostree config --repo=repo get --group='remote "flathub"' 'xa.title' >> list.txt ${CMD_PREFIX} ostree config --repo=repo get --group='remote "flathub"' 'xa.title-is-set' >> list.txt ${CMD_PREFIX} ostree config --repo=repo get --group='remote "org.mozilla.FirefoxRepo"' url >> list.txt -${CMD_PREFIX} cat list.txt +${CMD_PREFIX} cat list.txt assert_file_has_content list.txt "bare" assert_file_has_content list.txt "1" @@ -44,11 +44,13 @@ assert_file_has_content list.txt "http://example.com/ostree/repo/" echo "ok config get" ${CMD_PREFIX} ostree config --repo=repo set core.mode bare-user-only +${CMD_PREFIX} ostree config --repo=repo set sysroot.bootloader some_bootloader ${CMD_PREFIX} ostree config --repo=repo set --group='remote "flathub"' 'xa.title' 'Nightly Flathub' ${CMD_PREFIX} ostree config --repo=repo set --group='remote "flathub"' 'xa.title-is-set' 'false' ${CMD_PREFIX} ostree config --repo=repo set --group='remote "org.mozilla.FirefoxRepo"' url http://example.com/ostree/ assert_file_has_content repo/config "bare-user-only" +assert_file_has_content repo/config "some_bootloader" assert_file_has_content repo/config "Nightly Flathub" assert_file_has_content repo/config "false" assert_file_has_content repo/config "http://example.com/ostree/"