systemd defined an /etc/machine-id file which is supposed to contain a
unique, unchanging ID for the host. This file is initially zero-sized
and is meant to be set by systemd on the first boot of the system.
In virt-builder Fedora templates, the file is empty.
Unfortunately the Fedora kernel %post script requires the machine-id
to have been set, else the script exits with an error:
Running scriptlet: kernel-core-4.12.13-300.fc26.x86_64 209/209
Could not determine your machine ID from /etc/machine-id.
Please run 'systemd-machine-id-setup' as root. See man:machine-id(5)
warning: %posttrans(kernel-core-4.12.13-300.fc26.x86_64) scriptlet failed, exit status
1
This also leaves the kernel package half-installed. The files are
present in the filesystem, but important initialization is not done,
in particular the vmlinuz file is not copied into /boot.
A simple reproducer for this problem is:
$ virt-builder fedora-26 --update
which will leave the system with a half-installed kernel.
This change makes virt-customize set /etc/machine-id to a random value
if it is zero sized. This is done unconditionally at the same time as
setting the random seed (a similar issue).
---
customize/customize_run.ml | 30 ++++++++++++++++++++++++++----
1 file changed, 26 insertions(+), 4 deletions(-)
diff --git a/customize/customize_run.ml b/customize/customize_run.ml
index 5564684b4..3dcf755eb 100644
--- a/customize/customize_run.ml
+++ b/customize/customize_run.ml
@@ -27,7 +27,9 @@ open Customize_cmdline
open Password
open Append_line
-let run (g : Guestfs.guestfs) root (ops : ops) =
+module G = Guestfs
+
+let run (g : G.guestfs) root (ops : ops) =
(* Is the host_cpu compatible with the guest arch? ie. Can we
* run commands in this guest?
*)
@@ -89,7 +91,7 @@ exec >>%s 2>&1
debug "running command:\n%s" cmd;
try ignore (g#sh cmd)
with
- Guestfs.Error msg ->
+ G.Error msg ->
debug_logfile ();
if warn_failed_no_network && not (g#get_network ()) then (
prerr_newline ();
@@ -194,6 +196,26 @@ exec >>%s 2>&1
if not (Random_seed.set_random_seed g root) then
warning (f_"random seed could not be set for this type of guest");
+ (* Set the systemd machine ID. This must be set before performing
+ * --install/--update since (at least in Fedora) the kernel %post
+ * script requires a machine ID and will fail if it is not set.
+ *)
+ let () =
+ let etc_machine_id = "/etc/machine-id" in
+ let statbuf =
+ try Some (g#lstatns etc_machine_id) with G.Error _ -> None in
+ (match statbuf with
+ | Some { G.st_size = 0L; G.st_mode = mode }
+ when (Int64.logand mode 0o170000_L) = 0o100000_L ->
+ message (f_"Setting the machine ID in %s") etc_machine_id;
+ let id = Urandom.urandom_bytes 16 in
+ let id = String.map_chars (fun c -> sprintf "%02x" (Char.code c)) id
in
+ let id = String.concat "" id in
+ let id = id ^ "\n" in
+ g#write etc_machine_id id
+ | _ -> ()
+ ) in
+
(* Store the passwords and set them all at the end. *)
let passwords = Hashtbl.create 13 in
let set_password user pw =
@@ -399,8 +421,8 @@ exec >>%s 2>&1
let uid, gid = statbuf.st_uid, statbuf.st_gid in
let chown () =
try g#chown uid gid dest
- with Guestfs.Error m as e ->
- if g#last_errno () = Guestfs.Errno.errno_EPERM
+ with G.Error m as e ->
+ if g#last_errno () = G.Errno.errno_EPERM
then warning "%s" m
else raise e in
chown ()
--
2.13.2