diff --git a/Makefile-tests.am b/Makefile-tests.am index c51b1144..87ae8d05 100644 --- a/Makefile-tests.am +++ b/Makefile-tests.am @@ -34,6 +34,7 @@ testfiles = test-basic \ test-gpg-signed-commit \ test-admin-deploy-1 \ test-admin-deploy-2 \ + test-admin-deploy-karg \ test-admin-deploy-etcmerge-cornercases \ test-admin-deploy-uboot \ test-setuid \ diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c index b14b2b71..749a375a 100644 --- a/src/libostree/ostree-sysroot-deploy.c +++ b/src/libostree/ostree-sysroot-deploy.c @@ -737,8 +737,7 @@ swap_bootloader (OstreeSysroot *sysroot, } static GHashTable * -bootcsum_counts_for_deployment_list (GPtrArray *deployments, - gboolean set_bootserial) +assign_bootserials (GPtrArray *deployments) { guint i; GHashTable *ret = @@ -751,10 +750,47 @@ bootcsum_counts_for_deployment_list (GPtrArray *deployments, guint count; 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; } @@ -821,19 +857,17 @@ ostree_sysroot_write_deployments (OstreeSysroot *self, guint i; gboolean requires_new_bootversion = FALSE; gboolean found_booted_deployment = FALSE; - gs_unref_hashtable GHashTable *new_bootcsum_to_count = NULL; g_assert (self->loaded); - /* Calculate the total number of deployments per bootcsums; while we - * are doing this, assign a bootserial to each new deployment. + /* 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 - * configuration. If we have an equal number of deployments and - * more strongly an equal number of deployments per bootcsum, then - * we can just swap the subbootversion bootlinks. + * configuration. If we have an equal number of deployments with + * matching bootloader configuration, then we can just swap the + * subbootversion bootlinks. */ if (new_deployments->len != self->deployments->len) requires_new_bootversion = TRUE; @@ -841,14 +875,16 @@ ostree_sysroot_write_deployments (OstreeSysroot *self, { GHashTableIter hashiter; gpointer hkey, hvalue; - gs_unref_hashtable GHashTable *orig_bootcsum_to_count - = bootcsum_counts_for_deployment_list (self->deployments, FALSE); + gs_unref_hashtable GHashTable *new_bootconfig_to_count = + 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)) { 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); if (orig_count != new_count) diff --git a/tests/test-admin-deploy-karg.sh b/tests/test-admin-deploy-karg.sh new file mode 100644 index 00000000..1f0b9c7e --- /dev/null +++ b/tests/test-admin-deploy-karg.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# Copyright (C) 2011 Colin Walters +# +# 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"