Richard W.M. Jones
2016-Sep-01 13:01 UTC
[Libguestfs] [PATCH 0/2] customize: Fix hostname setting in Debian/Ubuntu.
https://bugzilla.redhat.com/show_bug.cgi?id=1372269 It was fairly broken. This fixes it -- except on Ubuntu 10.04 -- and adds a slow test. Rich.
Richard W.M. Jones
2016-Sep-01 13:01 UTC
[Libguestfs] [PATCH 1/2] customize: Update "unassigned-hostname" etc in Debian/Ubuntu /etc/hosts (RHBZ#1372269).
Commit ab2df2e6598d421067d600f89a3d225162424d9b attempted to rewrite /etc/hosts if it contained the old hostname. However this wasn't done reliably for a couple of reasons: (1) Certain Debian/Ubuntu /etc/hostname contains "localhost.localdomain" but still has "unassigned-hostname" or "unassigned-hostname.unassigned-domain" in /etc/hosts. (2) Even if (1) doesn't apply, you still need to split out the hostname and domainname parts and deal with them separately. --- customize/hostname.ml | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/customize/hostname.ml b/customize/hostname.ml index d7bb54b..073604d 100644 --- a/customize/hostname.ml +++ b/customize/hostname.ml @@ -44,10 +44,7 @@ let rec set_hostname (g : Guestfs.guestfs) root hostname | "linux", ("debian"|"ubuntu"), _ -> let old_hostname = read_etc_hostname g in update_etc_hostname g hostname; - (match old_hostname with - | Some old_hostname -> replace_host_in_etc_hosts g old_hostname hostname - | None -> () - ); + replace_host_in_etc_hosts g old_hostname hostname; true | "linux", ("fedora"|"rhel"|"centos"|"scientificlinux"|"redhat-based"), _ -> @@ -94,17 +91,44 @@ and read_etc_hostname g ) else None +and aug_hosts_expr + (* Matches everything in /etc/hosts except the IP address and comments. *) + "/files/etc/hosts/*[label() != '#comment']/*[label() != 'ipaddr']" + and replace_host_in_etc_hosts g oldhost newhost if g#is_file "/etc/hosts" then ( - let expr = "/files/etc/hosts/*[label() != '#comment']/*[label() != 'ipaddr']" in + let oldshortname, olddomainname + match oldhost with + | None -> None, None + | Some oldhost -> + let s, d = String.split "." oldhost in Some s, Some d in + let newshortname, newdomainname = String.split "." newhost in + g#aug_init "/" 0; - let matches = Array.to_list (g#aug_match expr) in + let matches = Array.to_list (g#aug_match aug_hosts_expr) in + List.iter ( fun m -> let value = g#aug_get m in - if value = oldhost then ( + + (* Replace either "oldhostname" or "oldhostname.olddomainname". *) + if oldhost = Some value then + g#aug_set m newhost + + else if oldshortname = Some value then + g#aug_set m newshortname + + (* On Debian/Ubuntu we also may find "unassigned-hostname" + * which has to be replaced with the short hostname. + *) + else if value = "unassigned-hostname" then + g#aug_set m newshortname + + (* Or we may find "unassigned-hostname.unassigned-domain". *) + else if value = "unassigned-hostname.unassigned-domain" && + newdomainname <> "" then g#aug_set m newhost - ) ) matches; + g#aug_save () ) -- 2.9.3
Richard W.M. Jones
2016-Sep-01 13:01 UTC
[Libguestfs] [PATCH 2/2] customize: Add a slow test of --hostname and --timezone settings.
Run these in real guests to ensure they really work. --- .gitignore | 1 + customize/Makefile.am | 36 ++++++++++- customize/test-settings.sh | 152 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 3 deletions(-) create mode 100755 customize/test-settings.sh diff --git a/.gitignore b/.gitignore index 87e8d3c..fc0d065 100644 --- a/.gitignore +++ b/.gitignore @@ -129,6 +129,7 @@ Makefile.in /customize/customize-synopsis.pod /customize/stamp-virt-customize.pod /customize/test-firstboot-*.sh +/customize/test-settings-*.sh /customize/virt-customize /customize/virt-customize.1 /daemon/actions.h diff --git a/customize/Makefile.am b/customize/Makefile.am index 183166c..78a7b96 100644 --- a/customize/Makefile.am +++ b/customize/Makefile.am @@ -22,6 +22,7 @@ EXTRA_DIST = \ $(SOURCES_MLI) $(SOURCES_ML) $(SOURCES_C) \ customize_main.ml \ test-firstboot.sh \ + test-settings.sh \ test-virt-customize.sh \ test-virt-customize-docs.sh \ virt-customize.pod @@ -200,10 +201,11 @@ endif check-valgrind: $(MAKE) VG="$(top_builddir)/run @VG@" check -# Slow tests of firstboot functionality in real guests. +# Slow tests of virt-customize functionality in real guests. SLOW_TESTS = \ - $(firstboot_test_scripts) + $(firstboot_test_scripts) \ + $(settings_test_scripts) check-slow: $(MAKE) check TESTS="$(SLOW_TESTS)" SLOW=1 @@ -231,9 +233,37 @@ test-firstboot-%.sh: chmod 0755 $@-t mv $@-t $@ +settings_test_scripts := \ + test-settings-rhel-4.9.sh \ + test-settings-rhel-5.11.sh \ + test-settings-rhel-6.8.sh \ + test-settings-rhel-7.2.sh \ + test-settings-debian-6.sh \ + test-settings-debian-7.sh \ + test-settings-debian-8.sh \ + test-settings-fedora-24.sh \ + test-settings-ubuntu-12.04.sh \ + test-settings-ubuntu-14.04.sh \ + test-settings-ubuntu-16.04.sh +# Ubuntu 10.04 hostname setting is known broken, because hostname -f +# doesn't read the FQDN from either /etc/hostname or /etc/hosts even +# though we appear to be setting it correctly. +# test-settings-ubuntu-10.04.sh +# Since firstboot is broken, we cannot test settings in RHEL 3: +# test-settings-rhel-3.9.sh + +test-settings-%.sh: + rm -f $@ $@-t + f=`echo "$@" | $(SED) 's/test-settings-\(.*\).sh/\1/'`; \ + echo 'exec $$srcdir/test-settings.sh' "$$f" > $@-t + chmod 0755 $@-t + mv $@-t $@ + CLEANFILES += \ $(firstboot_test_scripts) \ - firstboot-*.img + $(settings_test_scripts) \ + firstboot-*.img \ + settings-*.img # Dependencies. depend: .depend diff --git a/customize/test-settings.sh b/customize/test-settings.sh new file mode 100755 index 0000000..20ca69b --- /dev/null +++ b/customize/test-settings.sh @@ -0,0 +1,152 @@ +#!/bin/bash - +# Test various virt-customize settings. +# Copyright (C) 2016 Red Hat Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# This slow test checks that settings such as hostname, timezone work. +# +# NB. 'test-settings.sh' runs the tests, but the various tests are +# run via the 'test-settings-GUESTNAME.sh' wrappers. + +export LANG=C +set -e +set -x + +if [ -z "$SLOW" ]; then + echo "$0: use 'make check-slow' to run this test" + exit 77 +fi + +if [ -n "$SKIP_TEST_SETTINGS_SH" ]; then + echo "$0: test skipped because environment variable is set." + exit 77 +fi + +guestname="$1" +if [ -z "$guestname" ]; then + echo "$0: guestname parameter not set, don't run this test directly." + exit 1 +fi + +disk="settings-$guestname.img" +rm -f "$disk" "$disk.firstboot.sh" "$disk.firstboot.out" + +# If the guest doesn't exist in virt-builder, skip. This is because +# we test some RHEL guests which most users won't have access to. +if ! virt-builder -l "$guestname" >/dev/null 2>&1; then + echo "$0: test skipped because \"$guestname\" not known to virt-builder." + exit 77 +fi + +# We can only run the tests on x86_64. +if [ "$(uname -m)" != "x86_64" ]; then + echo "$0: test skipped because !x86_64." + exit 77 +fi + +# Check qemu is installed. +qemu=qemu-system-x86_64 +if ! $qemu -help >/dev/null 2>&1; then + echo "$0: test skipped because $qemu not found." + exit 77 +fi + +# Some guests need special virt-builder parameters. +# See virt-builder --notes "$guestname" +declare -a extra +case "$guestname" in + debian-6|debian-7) + extra[${#extra[*]}]='--edit' + extra[${#extra[*]}]='/etc/inittab: + s,^#([1-9].*respawn.*/sbin/getty.*),$1,' + ;; + fedora*|rhel*|centos*) + extra[${#extra[*]}]='--selinux-relabel' + ;; + *) + ;; +esac + +# Create a firstboot script. Broadly the same across all distros, but +# could be different in future if we support non-Linux (XXX). +fb="$disk.firstboot.sh" +case "$guestname" in + centos*|debian*|fedora*|rhel*|ubuntu*) + echo '#!/bin/sh' > "$fb" + echo 'exec > /firstboot.out 2> /firstboot.err' >> "$fb" + echo 'echo -n HOSTNAME=' >> "$fb" + echo 'hostname -f' >> "$fb" + echo 'echo -n TIMEZONE=' >> "$fb" + echo 'date +%:z' >> "$fb" + echo 'sync' >> "$fb" + echo 'poweroff' >> "$fb" + ;; + *) + echo "$0: don't know how to write a firstboot script for $guestname" + exit 1 + ;; +esac + +# Build a guest (using virt-builder) with some virt-customize setting +# parameters. +# +# Note we choose a timezone that doesn't have daylight savings, so +# that the output of the date command should always be the same. +virt-builder "$guestname" \ + --quiet \ + -o "$disk" \ + --hostname test-set.example.com \ + --timezone Japan \ + --firstboot "$fb" \ + "${extra[@]}" + +# Boot the guest in qemu and wait for the firstboot scripts to run. +# +# Use IDE because some ancient guests don't support anything else. +# +# Adding a network device is not strictly necessary, but makes +# the Debian 7 guest happier. +$qemu \ + -nodefconfig \ + -display none \ + -machine accel=kvm:tcg \ + -m 2048 \ + -boot c \ + -drive file="$disk",format=raw,if=ide \ + -netdev user,id=usernet \ + -device rtl8139,netdev=usernet \ + -serial stdio ||: + +# Get the output of the firstboot script. +fbout="$disk.firstboot.out" +guestfish --ro -a "$disk" -i <<EOF +download /firstboot.out "$fbout" +# For information only. +echo === /firstboot.out ==+-cat /firstboot.out +echo === /firstboot.err ==+-cat /firstboot.err +echo === /etc/hosts ==+-cat /etc/hosts +echo === /etc/hostname ==+-cat /etc/hostname +EOF + +# Check the output of the firstboot script. +grep "^HOSTNAME=test-set.example.com" "$fbout" +grep "^TIMEZONE=+09:00" "$fbout" + +rm "$disk" "$disk.firstboot.sh" "$disk.firstboot.out" -- 2.9.3
Apparently Analagous Threads
- Re: [PATCH] mllib: hostname: replace the hostname on Debian also in /etc/hosts (RHBZ#953907).
- [PATCH] customize: Test that the --root-password parameter works.
- [PATCH 1/2] mllib: hostname: replace the hostname on Debian also in /etc/hosts (RHBZ#953907).
- [PATCH] customize: allow missing SELINUXTYPE in SELinux config
- [PATCH 1/2] customize: Fix firstboot scripts on Debian 6 & 7 (RHBZ#1019388).