Skip to content

Commit

Permalink
Add sysroot.bootloader repo config key
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Robert Fairley committed Feb 21, 2019
1 parent 5877371 commit d6ab97c
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 8 deletions.
1 change: 1 addition & 0 deletions Makefile-tests.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
1 change: 1 addition & 0 deletions src/libostree/ostree-repo-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
41 changes: 41 additions & 0 deletions src/libostree/ostree-repo.c
Original file line number Diff line number Diff line change
Expand Up @@ -3113,6 +3113,27 @@ 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;

if (bootloader == NULL)
return glnx_throw (error, "Invalid empty bootloader configuration");

self->bootloader = g_steal_pointer (&bootloader);
}

return TRUE;
}

/**
* ostree_repo_reload_config:
* @self: repo
Expand All @@ -3131,6 +3152,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;
}

Expand Down Expand Up @@ -6064,3 +6087,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;
}
3 changes: 3 additions & 0 deletions src/libostree/ostree-repo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
34 changes: 32 additions & 2 deletions src/libostree/ostree-sysroot-deploy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -2342,8 +2343,36 @@ 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. */
}
else
{
/* TODO: later add support for specifying a generic
* bootloader binary here (e.g. bootloader=x means
* run /usr/lib/ostree/bootloaders/x). Override
* with /etc/ostree/bootloaders/x possibly.
* See:
* https://github.com/ostreedev/ostree/issues/1719
* https://github.com/ostreedev/ostree/issues/1801
*/
return glnx_throw (error, "Unsupported bootloader option '%s'", bootloader_config);
}

bootloader_is_atomic = bootloader != NULL && _ostree_bootloader_is_atomic (bootloader);

/* Note equivalent of try/finally here */
Expand Down Expand Up @@ -2375,6 +2404,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,
Expand Down
8 changes: 8 additions & 0 deletions tests/libtest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,11 @@ setup_os_boot_grub2() {
esac
}

setup_os_boot_configured_bootloader() {
bootloader_keyval=$1
ostree --repo=sysroot/ostree/repo config set ${bootloader_keyval}
}

setup_os_repository () {
mode=$1
shift
Expand Down Expand Up @@ -448,6 +453,9 @@ EOF
*grub2*)
setup_os_boot_grub2 "${bootmode}"
;;
sysroot\.bootloader*)
setup_os_boot_configured_bootloader "${bootmode}"
;;
esac

cd ${test_tmpdir}
Expand Down
43 changes: 43 additions & 0 deletions tests/test-admin-deploy-none.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash
#
# Copyright (C) 2019 Robert Fairley <[email protected]>
#
# 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=1

. $(dirname $0)/admin-test.sh

# Test that the bootloader configuration "none" on first deployment
# generates BLS config snippets, see https://github.com/ostreedev/ostree/issues/1774.
mkdir sysroot-first-deploy && ostree admin init-fs sysroot-first-deploy
ostree config set sysroot.bootloader none --repo=sysroot-first-deploy/ostree/repo
ostree pull-local --repo=sysroot-first-deploy/ostree/repo --remote testos testos-repo testos/buildmaster/x86_64-runtime
ostree admin os-init testos --sysroot sysroot-first-deploy
ostree admin deploy testos/buildmaster/x86_64-runtime --sysroot sysroot-first-deploy --os testos -v > out.txt
assert_file_has_content out.txt "Bootloader updated.*"
# Check BLS config snippet was created.
assert_has_file sysroot-first-deploy/boot/loader/entries/ostree-1-testos.conf
echo "ok generate bls config on first deployment"
4 changes: 3 additions & 1 deletion tests/test-config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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/"
Expand Down
76 changes: 71 additions & 5 deletions tests/test-keyfile-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,76 @@ test_get_value_with_default (void)
g_clear_pointer (&out, g_free);

g_assert_false (ot_keyfile_get_value_with_default (g_keyfile,
"a_fake_section",
"a_value_true",
"no value",
&out,
&error));
"a_fake_section",
"a_value_true",
"no value",
&out,
&error));
g_clear_error (&error);
g_clear_pointer (&out, g_free);
}

static void
test_get_value_with_default_group_optional (void)
{
g_autoptr(GError) error = NULL;
g_autofree char *out = NULL;
GLogLevelFlags always_fatal_mask;
const char *section = "section";

/* Avoid that g_return_val_if_fail causes the test to fail. */
always_fatal_mask = g_log_set_always_fatal (0);


g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
NULL,
"value_foo",
"none",
&out,
&error));
g_clear_pointer (&out, g_free);
g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
section,
NULL,
"none",
&out,
&error));
g_clear_pointer (&out, g_free);
g_assert_false (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
section,
NULL,
"something",
&out,
&error));
g_clear_pointer (&out, g_free);

/* Restore the old mask. */
g_log_set_always_fatal (always_fatal_mask);

g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
section,
"value_foo",
"none",
&out,
&error));
g_assert_cmpstr (out, ==, "foo");
g_clear_pointer (&out, g_free);

g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
section,
"a_not_existing_value",
"correct",
&out,
&error));
g_assert_cmpstr (out, ==, "correct");
g_clear_pointer (&out, g_free);

g_assert (ot_keyfile_get_value_with_default_group_optional (g_keyfile,
"an_optional_section",
"a_value_true",
"no value",
&out,
&error));
g_clear_error (&error);
g_clear_pointer (&out, g_free);
}
Expand Down Expand Up @@ -191,6 +256,7 @@ int main (int argc, char **argv)

g_test_add_func ("/keyfile-utils/get-boolean-with-default", test_get_boolean_with_default);
g_test_add_func ("/keyfile-utils/get-value-with-default", test_get_value_with_default);
g_test_add_func ("/keyfile-utils/get-value-with-default-group-optional", test_get_value_with_default_group_optional);
g_test_add_func ("/keyfile-utils/copy-group", test_copy_group);

ret = g_test_run();
Expand Down

0 comments on commit d6ab97c

Please sign in to comment.