deploy: Write bootloader config even if just kernel arguments changed

The official way to add bootloader arguments to the current deployment
is to redeploy with --karg.  However, doing so tripped up an
optimization made inside the deployment code to just swap the
bootlinks if we're keeping the same "bootcsum".

Change this optimization to look at the pair of (bootcsum, options).
This commit is contained in:
Colin Walters 2014-01-15 08:46:05 -05:00
parent 211d9c7985
commit 54e58a51ca
3 changed files with 99 additions and 16 deletions

View File

@ -34,6 +34,7 @@ testfiles = test-basic \
test-gpg-signed-commit \ test-gpg-signed-commit \
test-admin-deploy-1 \ test-admin-deploy-1 \
test-admin-deploy-2 \ test-admin-deploy-2 \
test-admin-deploy-karg \
test-admin-deploy-etcmerge-cornercases \ test-admin-deploy-etcmerge-cornercases \
test-admin-deploy-uboot \ test-admin-deploy-uboot \
test-setuid \ test-setuid \

View File

@ -737,8 +737,7 @@ swap_bootloader (OstreeSysroot *sysroot,
} }
static GHashTable * static GHashTable *
bootcsum_counts_for_deployment_list (GPtrArray *deployments, assign_bootserials (GPtrArray *deployments)
gboolean set_bootserial)
{ {
guint i; guint i;
GHashTable *ret = GHashTable *ret =
@ -751,10 +750,47 @@ bootcsum_counts_for_deployment_list (GPtrArray *deployments,
guint count; guint count;
count = GPOINTER_TO_UINT (g_hash_table_lookup (ret, bootcsum)); count = GPOINTER_TO_UINT (g_hash_table_lookup (ret, bootcsum));
g_hash_table_replace (ret, (char*)bootcsum, GUINT_TO_POINTER (count + 1)); g_hash_table_replace (ret, (char*) bootcsum,
GUINT_TO_POINTER (count + 1));
if (set_bootserial) ostree_deployment_set_bootserial (deployment, count);
ostree_deployment_set_bootserial (deployment, count); }
return ret;
}
static GHashTable *
bootconfig_counts_for_deployment_list (GPtrArray *deployments)
{
guint i;
GHashTable *ret =
g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
const char *bootcsum = ostree_deployment_get_bootcsum (deployment);
OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (deployment);
const char *boot_options = ostree_bootconfig_parser_get (bootconfig, "options");
GChecksum *bootconfig_checksum = g_checksum_new (G_CHECKSUM_SHA256);
const char *bootconfig_checksum_str;
__attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL;
gs_free char *boot_options_without_ostree = NULL;
guint count;
/* We checksum the kernel arguments *except* ostree= */
ohash = _ostree_sysroot_parse_kernel_args (boot_options);
_ostree_ordered_hash_replace_key (ohash, "ostree", "");
boot_options_without_ostree = _ostree_sysroot_kernel_arg_string_serialize (ohash);
g_checksum_update (bootconfig_checksum, (guint8*)bootcsum, strlen (bootcsum));
g_checksum_update (bootconfig_checksum, (guint8*)boot_options_without_ostree,
strlen (boot_options_without_ostree));
bootconfig_checksum_str = g_checksum_get_string (bootconfig_checksum);
count = GPOINTER_TO_UINT (g_hash_table_lookup (ret, bootconfig_checksum_str));
g_hash_table_replace (ret, g_strdup (bootconfig_checksum_str),
GUINT_TO_POINTER (count + 1));
} }
return ret; return ret;
} }
@ -821,19 +857,17 @@ ostree_sysroot_write_deployments (OstreeSysroot *self,
guint i; guint i;
gboolean requires_new_bootversion = FALSE; gboolean requires_new_bootversion = FALSE;
gboolean found_booted_deployment = FALSE; gboolean found_booted_deployment = FALSE;
gs_unref_hashtable GHashTable *new_bootcsum_to_count = NULL;
g_assert (self->loaded); g_assert (self->loaded);
/* Calculate the total number of deployments per bootcsums; while we /* Assign a bootserial to each new deployment.
* are doing this, assign a bootserial to each new deployment.
*/ */
new_bootcsum_to_count = bootcsum_counts_for_deployment_list (new_deployments, TRUE); assign_bootserials (new_deployments);
/* Determine whether or not we need to touch the bootloader /* Determine whether or not we need to touch the bootloader
* configuration. If we have an equal number of deployments and * configuration. If we have an equal number of deployments with
* more strongly an equal number of deployments per bootcsum, then * matching bootloader configuration, then we can just swap the
* we can just swap the subbootversion bootlinks. * subbootversion bootlinks.
*/ */
if (new_deployments->len != self->deployments->len) if (new_deployments->len != self->deployments->len)
requires_new_bootversion = TRUE; requires_new_bootversion = TRUE;
@ -841,14 +875,16 @@ ostree_sysroot_write_deployments (OstreeSysroot *self,
{ {
GHashTableIter hashiter; GHashTableIter hashiter;
gpointer hkey, hvalue; gpointer hkey, hvalue;
gs_unref_hashtable GHashTable *orig_bootcsum_to_count gs_unref_hashtable GHashTable *new_bootconfig_to_count =
= bootcsum_counts_for_deployment_list (self->deployments, FALSE); bootconfig_counts_for_deployment_list (new_deployments);
gs_unref_hashtable GHashTable *orig_bootconfig_to_count
= bootconfig_counts_for_deployment_list (self->deployments);
g_hash_table_iter_init (&hashiter, orig_bootcsum_to_count); g_hash_table_iter_init (&hashiter, orig_bootconfig_to_count);
while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue)) while (g_hash_table_iter_next (&hashiter, &hkey, &hvalue))
{ {
guint orig_count = GPOINTER_TO_UINT (hvalue); guint orig_count = GPOINTER_TO_UINT (hvalue);
gpointer new_countp = g_hash_table_lookup (new_bootcsum_to_count, hkey); gpointer new_countp = g_hash_table_lookup (new_bootconfig_to_count, hkey);
guint new_count = GPOINTER_TO_UINT (new_countp); guint new_count = GPOINTER_TO_UINT (new_countp);
if (orig_count != new_count) if (orig_count != new_count)

View File

@ -0,0 +1,46 @@
#!/bin/bash
#
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
#
# 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 -e
. $(dirname $0)/libtest.sh
echo "1..1"
setup_os_repository "archive-z2" "syslinux"
echo "ok setup"
echo "1..1"
ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime
rev=$(ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime)
export rev
# This initial deployment gets kicked off with some kernel arguments
ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime
ostree admin --sysroot=sysroot deploy --karg=FOO=BAR --os=testos testos:testos/buildmaster/x86_64-runtime
ostree admin --sysroot=sysroot deploy --karg=TESTARG=TESTVALUE --os=testos testos:testos/buildmaster/x86_64-runtime
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-1.conf 'options.*FOO=BAR'
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*FOO=BAR'
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*TESTARG=TESTVALUE'
ostree admin --sysroot=sysroot deploy --karg=ANOTHERARG=ANOTHERVALUE --os=testos testos:testos/buildmaster/x86_64-runtime
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*TESTARG=TESTVALUE'
assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'options.*ANOTHERARG=ANOTHERVALUE'
echo "ok deploy with --karg, but same config"