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).