-
Notifications
You must be signed in to change notification settings - Fork 7
/
make-physical-machine.sh
executable file
·125 lines (108 loc) · 3.84 KB
/
make-physical-machine.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/bash -
# Copyright (C) 2022 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, see <https://www.gnu.org/licenses/>.
set -e -u -C
base_image=fedora-41
# The array below open-codes the partition:filesystem layout of the
# virt-builder disk template used above. Whenever you bump the Fedora
# version, update the array below as needed.
#
# We cannot use inspection either before or after the filesystem UUID
# changes:
#
# - the UUID of a mounted filesystem cannot be changed (at least with
# - XFS);
#
# - right after the UUID changes, inspection does not work correctly,
# as the new fs UUIDs are out of sync with the UUID references in
# those config files that inspection relies upon.
#
# Note that the order of entries is important too: the mount points
# must be listed in dependency order (put the dependees first, the
# dependants last).
fsdevs=(/dev/sda3:/ /dev/sda2:/boot)
GUESTFISH_PID=
disk=
cleanup()
{
set +e
if test -n "$GUESTFISH_PID"; then
guestfish --remote -- exit >/dev/null 2>&1
GUESTFISH_PID=
fi
if test -n "$disk"; then
rm -f -- "$disk"
disk=
fi
}
trap cleanup EXIT
output=$1
outdir=$(dirname -- "$output")
disk=$(mktemp -p "$outdir" physical-machine.tmp.XXXXXXXXXX)
# Delay the SELinux relabeling.
virt-builder --format raw -o "$disk" --root-password password:p2v-phys \
--no-selinux-relabel $base_image
# Start a guestfish server on the disk image, so that each of the
# several UUID-manipulation commands below not need a separate
# guestfish launch.
guestfish_set_pid=$(guestfish --listen --format=raw --add "$disk")
eval "$guestfish_set_pid"
guestfish --remote -- run
# For each filesystem:
#
# - regenerate the UUID,
#
# - produce a sed command (scriptlet) that performs the same UUID
# replacement in a text file,
#
# - mount the filesystem.
#
# Note that later we're going to rely on the fact that the generated
# sed commands *require no quoting* on the shell command line.
declare -a sed_script
sed_idx=0
for fsdev in "${fsdevs[@]}"; do
device=${fsdev%:*}
mountpoint=${fsdev#*:}
old_uuid=$(guestfish --remote -- get-uuid "$device")
guestfish --remote -- set-uuid-random "$device"
new_uuid=$(guestfish --remote -- get-uuid "$device")
sed_script[sed_idx++]=-e
sed_script[sed_idx++]=s/$old_uuid/$new_uuid/ig
guestfish --remote -- mount "$device" "$mountpoint"
done
# Prepare the UUID replacement shell command for the appliance.
refresh_uuid_refs=(find /boot /etc -type f -print0 '|'
xargs -0 -r -- sed -i "${sed_script[@]}" --)
# Passing the shell command to the appliance is where we rely on the
# fact that the sed commands for replacing UUIDs require no quoting.
guestfish --remote -- sh "${refresh_uuid_refs[*]}"
# Tear down the guestfish server before we use virt-customize.
waitpid=$GUESTFISH_PID
guestfish --remote -- exit
GUESTFISH_PID=
while kill -s 0 -- "$waitpid" 2>/dev/null; do
sleep 1
done
# Reapply the SELinux labels now. Use virt-customize for this, rather
# than guestfish's "selinux-relabel", as virt-customize contains some
# heavy logic related to "specfile". Inspection does work here,
# because the config files are in sync again with the filesystem
# UUIDs.
virt-customize --format raw --add "$disk" --selinux-relabel
# We're done; rename the temporary disk image to the expected output
# file.
mv -- "$disk" "$output"
disk=