diff --git a/SOURCES/PR116.patch b/SOURCES/PR116.patch new file mode 100644 index 0000000..b7a895f --- /dev/null +++ b/SOURCES/PR116.patch @@ -0,0 +1,446 @@ +From 2a4952da6c5b9739a56201662d05841185420484 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Sat, 30 May 2015 11:19:53 -0400 +Subject: [PATCH] Rebase PR116 + +--- + Makefile-tests.am | 4 ++ + src/libostree/ostree-sysroot.c | 47 ++++++++++----- + tests/admin-test.sh | 24 ++++++-- + tests/grub2-entries-crosscheck.py | 105 ++++++++++++++++++++++++++++++++++ + tests/syslinux-entries-crosscheck.py | 107 +++++++++++++++++++++++++++++++++++ + 5 files changed, 269 insertions(+), 18 deletions(-) + create mode 100644 tests/grub2-entries-crosscheck.py + create mode 100644 tests/syslinux-entries-crosscheck.py + +diff --git a/Makefile-tests.am b/Makefile-tests.am +index 46bf499..06db55b 100644 +--- a/Makefile-tests.am ++++ b/Makefile-tests.am +@@ -72,6 +72,10 @@ insttest_DATA = tests/archive-test.sh \ + tests/corrupt-repo-ref.js \ + $(NULL) + ++insttest_SCRIPTS += \ ++ tests/syslinux-entries-crosscheck.py \ ++ $(NULL) ++ + gpginsttestdir = $(pkglibexecdir)/installed-tests/gpghome + gpginsttest_DATA = tests/gpghome/secring.gpg \ + tests/gpghome/trustdb.gpg +diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c +index 6255803..b15ddf5 100644 +--- a/src/libostree/ostree-sysroot.c ++++ b/src/libostree/ostree-sysroot.c +@@ -355,6 +355,35 @@ _ostree_sysroot_read_current_subbootversion (OstreeSysroot *self, + return ret; + } + ++static gint ++compare_boot_loader_configs (OstreeBootconfigParser *a, ++ OstreeBootconfigParser *b) ++{ ++ const char *a_version = ostree_bootconfig_parser_get (a, "version"); ++ const char *b_version = ostree_bootconfig_parser_get (b, "version"); ++ ++ if (a_version && b_version) ++ { ++ int r = strverscmp (a_version, b_version); ++ /* Reverse */ ++ return -r; ++ } ++ else if (a_version) ++ return -1; ++ else ++ return 1; ++} ++ ++static int ++compare_loader_configs_for_sorting (gconstpointer a_pp, ++ gconstpointer b_pp) ++{ ++ OstreeBootconfigParser *a = *((OstreeBootconfigParser**)a_pp); ++ OstreeBootconfigParser *b = *((OstreeBootconfigParser**)b_pp); ++ ++ return compare_boot_loader_configs (a, b); ++} ++ + gboolean + _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, + int bootversion, +@@ -421,6 +450,9 @@ _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, + } + } + ++ /* Callers expect us to give them a sorted array */ ++ g_ptr_array_sort (ret_loader_configs, compare_loader_configs_for_sorting); ++ + done: + gs_transfer_out_value (out_loader_configs, &ret_loader_configs); + ret = TRUE; +@@ -700,19 +732,8 @@ compare_deployments_by_boot_loader_version_reversed (gconstpointer a_pp, + OstreeDeployment *b = *((OstreeDeployment**)b_pp); + OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a); + OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b); +- const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version"); +- const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version"); +- +- if (a_version && b_version) +- { +- int r = strverscmp (a_version, b_version); +- /* Reverse */ +- return -r; +- } +- else if (a_version) +- return -1; +- else +- return 1; ++ ++ return compare_boot_loader_configs (a_bootconfig, b_bootconfig); + } + + /** +diff --git a/tests/admin-test.sh b/tests/admin-test.sh +index 4278e01..f7fbb92 100755 +--- a/tests/admin-test.sh ++++ b/tests/admin-test.sh +@@ -20,17 +20,20 @@ set -e + + echo "1..10" + ++function validate_bootloader() { ++ (cd ${test_tmpdir}; ++ if test -f sysroot/boot/syslinux/syslinux.cfg; then ++ $(dirname $0)/syslinux-entries-crosscheck.py sysroot ++ fi) ++} ++ + ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo pull-local --remote=testos testos-repo testos/buildmaster/x86_64-runtime + rev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) + export rev + # This initial deployment gets kicked off with some kernel arguments + ${CMD_PREFIX} ostree admin --sysroot=sysroot deploy --karg=root=LABEL=MOO --karg=quiet --os=testos testos:testos/buildmaster/x86_64-runtime + ${CMD_PREFIX} ostree admin --sysroot=sysroot status | tee status.txt +- +-assert_file_has_content status.txt 'Version: 1.0.10' +-if test -f sysroot/boot/loader/syslinux.cfg; then +- assert_file_has_content sysroot/boot/loader/syslinux.cfg 'TestOS 42 1.0.10' +-fi ++validate_bootloader + + echo "ok deploy command" + +@@ -66,6 +69,7 @@ assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'option + assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.1/etc/os-release 'NAME=TestOS' + assert_file_has_content sysroot/ostree/boot.0/testos/${bootcsum}/0/etc/os-release 'NAME=TestOS' + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok second deploy" + +@@ -77,6 +81,7 @@ assert_not_has_dir sysroot/boot/loader.1 + assert_has_dir sysroot/ostree/boot.0.0 + assert_not_has_dir sysroot/ostree/boot.0.1 + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok third deploy (swap)" + +@@ -90,6 +95,7 @@ assert_has_file sysroot/boot/loader/entries/ostree-otheros-0.conf + assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.1/etc/os-release 'NAME=TestOS' + assert_file_has_content sysroot/ostree/deploy/otheros/deploy/${rev}.0/etc/os-release 'NAME=TestOS' + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok independent deploy" + +@@ -101,6 +107,7 @@ assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.2/etc/os-rele + assert_has_file sysroot/boot/loader/entries/ostree-testos-2.conf + assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/os-release 'NAME=TestOS' + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok fourth deploy (retain)" + +@@ -116,6 +123,7 @@ assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/os-rele + assert_file_has_content sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/a-new-config-file 'a new local config file' + assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.4/etc/aconfigfile + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok deploy with modified /etc" + +@@ -133,6 +141,7 @@ assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/new- + # And persist /etc changes from before + assert_not_has_file sysroot/ostree/deploy/testos/deploy/${rev}.3/etc/aconfigfile + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok upgrade bare" + +@@ -145,6 +154,7 @@ newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildm + assert_not_streq ${rev} ${newrev} + assert_file_has_content sysroot/ostree/deploy/testos/deploy/${newrev}.0/etc/os-release 'NAME=TestOS' + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok upgrade" + +@@ -155,6 +165,7 @@ assert_file_has_content "${originfile}" "bacon:testos/buildmaster/x86_64-runtime + ${CMD_PREFIX} ostree --repo=sysroot/ostree/repo remote list -u > remotes.txt + assert_file_has_content remotes.txt 'bacon.*http://tasty.com' + cp saved-origin ${originfile} ++validate_bootloader + + echo "ok set-origin" + +@@ -167,6 +178,7 @@ assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${rev}.0 + ${CMD_PREFIX} ostree admin --sysroot=sysroot undeploy 0 + assert_not_has_dir sysroot/ostree/deploy/testos/deploy/${newrev}.0 + ${CMD_PREFIX} ostree admin --sysroot=sysroot status ++validate_bootloader + + echo "ok undeploy" + +@@ -178,6 +190,7 @@ echo "ok deploy with unknown OS" + ${CMD_PREFIX} ostree admin --sysroot=sysroot deploy --os=testos --karg-append=console=/dev/foo --karg-append=console=/dev/bar testos:testos/buildmaster/x86_64-runtime + ${CMD_PREFIX} ostree admin --sysroot=sysroot deploy --os=testos testos:testos/buildmaster/x86_64-runtime + assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'console=/dev/foo.*console=/dev/bar' ++validate_bootloader + + echo "ok deploy with multiple kernel args" + +@@ -187,5 +200,6 @@ ${CMD_PREFIX} ostree admin --sysroot=sysroot upgrade --os=testos + newrev=$(${CMD_PREFIX} ostree --repo=sysroot/ostree/repo rev-parse testos/buildmaster/x86_64-runtime) + assert_not_streq ${origrev} ${newrev} + assert_file_has_content sysroot/boot/loader/entries/ostree-testos-0.conf 'console=/dev/foo.*console=/dev/bar' ++validate_bootloader + + echo "ok upgrade with multiple kernel args" +diff --git a/tests/grub2-entries-crosscheck.py b/tests/grub2-entries-crosscheck.py +new file mode 100644 +index 0000000..d68394d +--- /dev/null ++++ b/tests/grub2-entries-crosscheck.py +@@ -0,0 +1,105 @@ ++#!/usr/bin/python ++# ++# Copyright (C) 2015 Red Hat ++# ++# 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. ++ ++import os ++import sys ++ ++if len(sys.argv) == 1: ++ loaderpath = '/boot/loader/entries' ++ grub2path = '/boot/grub2/grub.cfg' ++else: ++ loaderpath = sys.argv[1] ++ grub2path = sys.argv[2] ++ ++def fatal(msg): ++ sys.stderr.write(msg) ++ sys.stderr.write('\n') ++ sys.exit(1) ++ ++def compare_entries_descending(a, b): ++ return int(b['version']) - int(a['version']) ++ ++def get_ostree_option(optionstring): ++ for o in optionstring.split(): ++ if o.startswith('ostree='): ++ return o[8:] ++ raise ValueError('ostree= not found') ++ ++entries = [] ++grub2_entries = [] ++ ++# Parse loader configs ++for fname in os.listdir(loaderpath): ++ path = os.path.join(loaderpath, fname) ++ with open(path) as f: ++ entry = {} ++ for line in f: ++ line = line.strip() ++ if (line == '' or line.startswith('#')): ++ continue ++ s = line.find(' ') ++ assert s > 0 ++ k = line[0:s] ++ v = line[s+1:] ++ entry[k] = v ++ entries.append(entry) ++ entries.sort(compare_entries_descending) ++ ++# Parse GRUB2 config ++with open(grub2path) as f: ++ in_ostree_config = False ++ grub2_entry = None ++ for line in f: ++ if line.startswith('### BEGIN /etc/grub.d/15_ostree ###'): ++ in_ostree_config = True ++ elif line.startswith('### END /etc/grub.d/15_ostree ###'): ++ in_ostree_config = False ++ if grub2_entry is not None: ++ grub2_entries.append(grub2_entry) ++ elif in_ostree_config: ++ if line.startswith('menuentry '): ++ if grub2_entry is not None: ++ grub2_entries.append(grub2_entry) ++ grub2_entry = {} ++ elif line.startswith('linux'): ++ parts = line.split() ++ grub2_entry['linux'] = parts[1] ++ grub2_entry['options'] = ' '.join(parts[2:]) ++ elif line.startswith('initrd'): ++ grub2_entry['initrd'] = line.split()[1] ++ ++if len(entries) != len(grub2_entries): ++ fatal("Found {0} loader entries, but {1} GRUB2 entries\n".format(len(entries), len(grub2_entries))) ++ ++def assert_matches_key(a, b, key): ++ aval = a[key] ++ bval = b[key] ++ if aval != bval: ++ fatal("Mismatch on {0}: {1} != {2}".format(key, aval, bval)) ++ ++for i,(entry,grub2entry) in enumerate(zip(entries, grub2_entries)): ++ assert_matches_key(entry, grub2entry, 'linux') ++ assert_matches_key(entry, grub2entry, 'initrd') ++ entry_ostree = get_ostree_option(entry['options']) ++ grub2_ostree = get_ostree_option(grub2entry['options']) ++ if entry_ostree != grub2_ostree: ++ fatal("Mismatch on ostree option: {0} != {1}".format(entry_ostree, grub2_ostree)) ++ ++sys.stdout.write('GRUB2 configuration validated\n') ++sys.exit(0) +diff --git a/tests/syslinux-entries-crosscheck.py b/tests/syslinux-entries-crosscheck.py +new file mode 100644 +index 0000000..8b58ed4 +--- /dev/null ++++ b/tests/syslinux-entries-crosscheck.py +@@ -0,0 +1,107 @@ ++#!/usr/bin/python ++# ++# Copyright (C) 2015 Red Hat ++# ++# 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. ++ ++import os ++import sys ++ ++if len(sys.argv) == 1: ++ sysroot = '' ++else: ++ sysroot = sys.argv[1] ++ ++loaderpath = sysroot + '/boot/loader/entries' ++syslinuxpath = sysroot + '/boot/syslinux/syslinux.cfg' ++ ++def fatal(msg): ++ sys.stderr.write(msg) ++ sys.stderr.write('\n') ++ sys.exit(1) ++ ++def compare_entries_descending(a, b): ++ return int(b['version']) - int(a['version']) ++ ++def get_ostree_option(optionstring): ++ for o in optionstring.split(): ++ if o.startswith('ostree='): ++ return o[8:] ++ raise ValueError('ostree= not found') ++ ++entries = [] ++syslinux_entries = [] ++ ++# Parse loader configs ++for fname in os.listdir(loaderpath): ++ path = os.path.join(loaderpath, fname) ++ with open(path) as f: ++ entry = {} ++ for line in f: ++ line = line.strip() ++ if (line == '' or line.startswith('#')): ++ continue ++ s = line.find(' ') ++ assert s > 0 ++ k = line[0:s] ++ v = line[s+1:] ++ entry[k] = v ++ entries.append(entry) ++ entries.sort(compare_entries_descending) ++ ++# Parse SYSLINUX config ++with open(syslinuxpath) as f: ++ in_ostree_config = False ++ syslinux_entry = None ++ syslinux_default = None ++ for line in f: ++ line = line.strip() ++ if line.startswith('DEFAULT '): ++ if syslinux_entry is not None: ++ syslinux_default = line.split(' ', 1)[1] ++ elif line.startswith('LABEL '): ++ if syslinux_entry is not None: ++ syslinux_entries.append(syslinux_entry) ++ syslinux_entry = {} ++ syslinux_entry['title'] = line.split(' ', 1)[1] ++ elif line.startswith('KERNEL '): ++ syslinux_entry['linux'] = line.split(' ', 1)[1] ++ elif line.startswith('INITRD '): ++ syslinux_entry['initrd'] = line.split(' ', 1)[1] ++ elif line.startswith('APPEND '): ++ syslinux_entry['options'] = line.split(' ', 1)[1] ++ if syslinux_entry is not None: ++ syslinux_entries.append(syslinux_entry) ++ ++if len(entries) != len(syslinux_entries): ++ fatal("Found {0} loader entries, but {1} SYSLINUX entries\n".format(len(entries), len(syslinux_entries))) ++ ++def assert_matches_key(a, b, key): ++ aval = a[key] ++ bval = b[key] ++ if aval != bval: ++ fatal("Mismatch on {0}: {1} != {2}".format(key, aval, bval)) ++ ++for i,(entry,syslinuxentry) in enumerate(zip(entries, syslinux_entries)): ++ assert_matches_key(entry, syslinuxentry, 'linux') ++ assert_matches_key(entry, syslinuxentry, 'initrd') ++ entry_ostree = get_ostree_option(entry['options']) ++ syslinux_ostree = get_ostree_option(syslinuxentry['options']) ++ if entry_ostree != syslinux_ostree: ++ fatal("Mismatch on ostree option: {0} != {1}".format(entry_ostree, syslinux_ostree)) ++ ++sys.stdout.write('SYSLINUX configuration validated\n') ++sys.exit(0) +-- +1.8.3.1 + diff --git a/SOURCES/sysroot-sort-returned-bootloader-configs.patch b/SOURCES/sysroot-sort-returned-bootloader-configs.patch deleted file mode 100644 index 57fa308..0000000 --- a/SOURCES/sysroot-sort-returned-bootloader-configs.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 3300ee6259d191199f96b5f4e04ccfded3d11b86 Mon Sep 17 00:00:00 2001 -From: Colin Walters -Date: Tue, 26 May 2015 18:46:47 -0400 -Subject: sysroot: Sort returned boot loader configs - -I haven't done a full dig through the history, but it seems quite -possible right now we've been relying on inode enumeration -order for generating bootloader configuration. - -Most of the time, newer inodes (i.e. later written files) will win. -But that's obviously not reliable. - -Fix this by sorting the returned configuration internally. - -diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c -index ebcb632..f12ebc5 100644 ---- a/src/libostree/ostree-sysroot.c -+++ b/src/libostree/ostree-sysroot.c -@@ -361,6 +361,35 @@ _ostree_sysroot_read_current_subbootversion (OstreeSysroot *self, - return ret; - } - -+static gint -+compare_boot_loader_configs (OstreeBootconfigParser *a, -+ OstreeBootconfigParser *b) -+{ -+ const char *a_version = ostree_bootconfig_parser_get (a, "version"); -+ const char *b_version = ostree_bootconfig_parser_get (b, "version"); -+ -+ if (a_version && b_version) -+ { -+ int r = strverscmp (a_version, b_version); -+ /* Reverse */ -+ return -r; -+ } -+ else if (a_version) -+ return -1; -+ else -+ return 1; -+} -+ -+static int -+compare_loader_configs_for_sorting (gconstpointer a_pp, -+ gconstpointer b_pp) -+{ -+ OstreeBootconfigParser *a = *((OstreeBootconfigParser**)a_pp); -+ OstreeBootconfigParser *b = *((OstreeBootconfigParser**)b_pp); -+ -+ return compare_boot_loader_configs (a, b); -+} -+ - gboolean - _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, - int bootversion, -@@ -427,6 +456,9 @@ _ostree_sysroot_read_boot_loader_configs (OstreeSysroot *self, - } - } - -+ /* Callers expect us to give them a sorted array */ -+ g_ptr_array_sort (ret_loader_configs, compare_loader_configs_for_sorting); -+ - done: - gs_transfer_out_value (out_loader_configs, &ret_loader_configs); - ret = TRUE; -@@ -706,19 +738,8 @@ compare_deployments_by_boot_loader_version_reversed (gconstpointer a_pp, - OstreeDeployment *b = *((OstreeDeployment**)b_pp); - OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a); - OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b); -- const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version"); -- const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version"); -- -- if (a_version && b_version) -- { -- int r = strverscmp (a_version, b_version); -- /* Reverse */ -- return -r; -- } -- else if (a_version) -- return -1; -- else -- return 1; -+ -+ return compare_boot_loader_configs (a_bootconfig, b_bootconfig); - } - - /** --- -cgit v0.10.2 - diff --git a/SPECS/ostree.spec b/SPECS/ostree.spec index caf3f79..76b4df8 100644 --- a/SPECS/ostree.spec +++ b/SPECS/ostree.spec @@ -1,18 +1,12 @@ Summary: Tool for managing bootable, immutable filesystem trees Name: ostree Version: 2015.6 -Release: 2.atomic%{?dist}.2 +Release: 4.atomic%{?dist} #VCS: git:git://git.gnome.org/ostree Source0: http://ftp.gnome.org/pub/GNOME/sources/ostree/%{version}/ostree-%{version}.tar.xz Source1: 91-ostree.preset -### CentOS specific patches -# We carry this one as it's a critical bug in upstream -Patch0: sysroot-sort-returned-bootloader-configs.patch -# This one is necessary - also a bug in upstream that -# we hit but upstream didn't because they haven't rebuilt anaconda -# with a newer ostree -Patch1: 0001-sysroot-Close-sysroot-fd-in-finalize.patch -### +Patch0: 0001-sysroot-Close-sysroot-fd-in-finalize.patch +Patch1: PR116.patch License: LGPLv2+ URL: http://live.gnome.org/OSTree @@ -122,8 +116,13 @@ rm -rf $RPM_BUILD_ROOT %{_libexecdir}/ostree/grub2* %changelog -* Wed Jun 17 2015 Karanbir Singh - 2015.6-2.atomic.centos.2 -- Roll in upstream fix patches and ostree backport +* Sun May 31 2015 Colin Walters - 2015.6-4.atomic +- Backport complete patch: Resolves: #1225088 + +* Fri May 29 2015 Colin Walters - 2015.6-3.atomic +- Backport patches from Fedora rawhide + Ensure bootloader ordering: Resolves: #1225088 + Close sysroot FD (would affect RHEL if we respun the installer) * Fri Apr 17 2015 Colin Walters - 2015.6-2.atomic - New upstream release