mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-22 07:03:38 +00:00
When the daemon starts up it creates a fresh (empty) LVM configuration and starts up lvmetad (which depends on the LVM configuration). However this appears to cause problems: Some types of PV seem to require lvmetad and don't work without it (https://bugzilla.redhat.com/show_bug.cgi?id=1581810). If we don't start lvmetad earlier, the device nodes are not created. Therefore move the whole initialization step into appliance/init. Two further changes had to be made: Now we are using lvmetad all the time, using vgchange is incorrect. With lvmetad activated early we must use ‘pvscan --cache --activate ay’ to scan all disks for PVs and activate any VGs on them (although the documentation is complex, confusing and contradictory so I'm not completely sure about this). The ‘lvm_system_dir’ local variable in ‘daemon/lvm-filter.c’ previously contained the path of the directory above $LVM_SYSTEM_DIR (eg. $LVM_SYSTEM_DIR = "/etc/lvm", lvm_system_dir = "/etc"). As this was highly confusing, I have changed it so the local variable and the environment variable have identical contents. This involved removing the ‘lvm/’ component from a couple of paths since it is now included in the local variable.
264 lines
7.0 KiB
Bash
Executable File
264 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
echo Starting /init script ...
|
||
|
||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||
export PATH
|
||
|
||
# Debian bug 606622.
|
||
RUNLEVEL=S
|
||
PREVLEVEL=N
|
||
export RUNLEVEL PREVLEVEL
|
||
|
||
# Make sure /tmp /var/tmp are real directories, not symlinks.
|
||
if [ ! -d /tmp ] || [ ! -d /var/tmp ]; then
|
||
rm -f /tmp /var/tmp
|
||
mkdir /tmp /var/tmp
|
||
chmod 1777 /tmp /var/tmp
|
||
fi
|
||
|
||
# Try to print a stack trace for segfaults inside the appliance.
|
||
for d in /lib64 /lib; do
|
||
f=$d/libSegFault.so
|
||
if [ -f "$f" ]; then
|
||
LD_PRELOAD=$f
|
||
export LD_PRELOAD
|
||
break
|
||
fi
|
||
done
|
||
|
||
mkdir -p /sysroot
|
||
|
||
# Mount /proc.
|
||
if [ ! -d /proc ]; then rm -f /proc; fi
|
||
mkdir -p /proc
|
||
mount -t proc /proc /proc
|
||
|
||
# Parse the kernel command line early (must be after /proc is mounted).
|
||
cmdline=$(</proc/cmdline)
|
||
|
||
if [[ $cmdline == *guestfs_verbose=1* ]]; then
|
||
guestfs_verbose=1
|
||
set -x
|
||
fi
|
||
if [[ $cmdline == *guestfs_network=1* ]]; then
|
||
guestfs_network=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_rescue=1* ]]; then
|
||
guestfs_rescue=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_noreboot=1* ]]; then
|
||
guestfs_noreboot=1
|
||
fi
|
||
if [[ $cmdline == *guestfs_boot_analysis=1* ]]; then
|
||
guestfs_boot_analysis=1
|
||
fi
|
||
|
||
# Mount the other special filesystems.
|
||
if [ ! -d /sys ]; then rm -f /sys; fi
|
||
mkdir -p /sys
|
||
mount -t sysfs /sys /sys
|
||
# taken from initramfs-tools/init --Hilko Bengen
|
||
mkdir -p /run
|
||
mount -t tmpfs -o "nosuid,size=20%,mode=0755" tmpfs /run
|
||
mkdir -p /run/lock
|
||
ln -s ../run/lock /var/lock
|
||
|
||
# On Fedora 23, util-linux creates /etc/mtab in %post .. stupid
|
||
# and e2fsprogs fails if the link doesn't exist .. stupid stupid
|
||
if ! test -e /etc/mtab; then
|
||
ln -s /proc/mounts /etc/mtab
|
||
fi
|
||
|
||
# devtmpfs is required since udev 176
|
||
mount -t devtmpfs /dev /dev
|
||
mkdir -p /dev/pts
|
||
mount -t devpts /dev/pts /dev/pts
|
||
mkdir -p /dev/shm
|
||
mount -t tmpfs -o mode=1777 shmfs /dev/shm
|
||
|
||
if [[ $cmdline == *selinux=1* ]]; then
|
||
mount -t selinuxfs none /sys/fs/selinux
|
||
fi
|
||
|
||
# Static nodes must happen before udev is started.
|
||
|
||
# Set up kmod static-nodes (RHBZ#1011907).
|
||
mkdir -p /run/tmpfiles.d
|
||
kmod static-nodes --format=tmpfiles --output=/run/tmpfiles.d/kmod.conf
|
||
|
||
# Create a machine-id with a random UUID
|
||
machine_id=$(dd if=/dev/urandom bs=16 count=1 status=none | od -x -A n)
|
||
echo "${machine_id// /}" > /etc/machine-id
|
||
|
||
# Set up tmpfiles (must run after kmod.conf is created above).
|
||
systemd-tmpfiles --prefix=/dev --prefix=/run --prefix=/var/run --create --boot
|
||
|
||
# Find udevd and run it directly.
|
||
for f in /lib/systemd/systemd-udevd /usr/lib/systemd/systemd-udevd \
|
||
/sbin/udevd /lib/udev/udevd \
|
||
/usr/lib/udev/udevd; do
|
||
if [ -x "$f" ]; then UDEVD="$f"; break; fi
|
||
done
|
||
if [ -z "$UDEVD" ]; then
|
||
echo "error: udev not found! Things will probably not work ..."
|
||
fi
|
||
|
||
$UDEVD --daemon #--debug
|
||
udevadm trigger
|
||
udevadm settle --timeout=600
|
||
|
||
# Disk optimizations.
|
||
# Increase the SCSI timeout so we can read remote images.
|
||
shopt -s nullglob
|
||
for f in /sys/block/sd*/device/timeout; do echo 300 > $f; done
|
||
# https://access.redhat.com/site/solutions/5427
|
||
for f in /sys/block/{h,s,ub,v}d*/queue/scheduler; do echo noop > $f; done
|
||
shopt -u nullglob
|
||
|
||
# Set up the network.
|
||
ip addr add 127.0.0.1/8 brd + dev lo scope host
|
||
ip link set dev lo up
|
||
|
||
if test "$guestfs_network" = 1; then
|
||
iface=$(ls -I all -I default -I lo /proc/sys/net/ipv4/conf)
|
||
touch /etc/fstab # Workaround for Ubuntu.
|
||
if dhclient --version >/dev/null 2>&1; then
|
||
dhclient $iface
|
||
else
|
||
dhcpcd $iface
|
||
fi
|
||
fi
|
||
|
||
# Scan for MDs but don't run arrays unless all expected drives are present
|
||
mdadm -As --auto=yes --no-degraded
|
||
|
||
# Set up a clean LVM environment.
|
||
# Empty LVM configuration file means "all defaults".
|
||
mkdir -p /tmp/lvm
|
||
touch /tmp/lvm/lvm.conf
|
||
LVM_SYSTEM_DIR=/tmp/lvm
|
||
export LVM_SYSTEM_DIR
|
||
lvmetad
|
||
|
||
# Scan for LVM.
|
||
modprobe dm_mod ||:
|
||
lvm pvscan --cache --activate ay
|
||
|
||
# Scan for MDs and run all found arrays even they are in degraded state
|
||
mdadm -As --auto=yes --run
|
||
|
||
# Scan for Windows dynamic disks.
|
||
ldmtool create all
|
||
|
||
# These are useful when debugging.
|
||
if test "$guestfs_verbose" = 1 && test "$guestfs_boot_analysis" != 1; then
|
||
uname -a
|
||
ls -lR /dev
|
||
cat /proc/mounts
|
||
cat /proc/mdstat
|
||
lvm config
|
||
lvm pvs
|
||
lvm vgs
|
||
lvm lvs
|
||
ip a
|
||
ip r
|
||
cat /etc/resolv.conf
|
||
lsmod
|
||
#hwclock -r
|
||
date
|
||
echo -n "clocksource: "
|
||
cat /sys/devices/system/clocksource/clocksource0/current_clocksource
|
||
#ping -n -v -c 5 8.8.8.8
|
||
|
||
echo -n "uptime: "; cat /proc/uptime
|
||
fi
|
||
|
||
# Run the daemon.
|
||
cmd="guestfsd"
|
||
eval `grep -Eo 'guestfs_channel=[^[:space:]]+' /proc/cmdline`
|
||
if test "x$guestfs_channel" != "x"; then
|
||
cmd="$cmd --channel $guestfs_channel"
|
||
fi
|
||
if test "$guestfs_verbose" = 1; then
|
||
cmd="$cmd --verbose"
|
||
fi
|
||
if test "$guestfs_network" = 1; then
|
||
cmd="$cmd --network"
|
||
fi
|
||
if false; then
|
||
# To get a stack trace if the daemon crashes:
|
||
# (1) change this section to 'if true'
|
||
# (2) add 'gdb' to 'appliance/packagelist.in'
|
||
unset LD_PRELOAD
|
||
echo set pagination off > /tmp/gdb-script
|
||
echo run >> /tmp/gdb-script
|
||
echo info registers >> /tmp/gdb-script
|
||
echo 'x/16i $pc' >> /tmp/gdb-script
|
||
echo t a a bt >> /tmp/gdb-script
|
||
echo quit >> /tmp/gdb-script
|
||
cmd="gdb -batch -x /tmp/gdb-script --args $cmd"
|
||
fi
|
||
if ! test "$guestfs_rescue" = 1; then
|
||
echo $cmd
|
||
$cmd
|
||
else
|
||
# Run virt-rescue shell.
|
||
|
||
# We need a daemon, even in virt-rescue.
|
||
$cmd &
|
||
|
||
# XXX This gives a bit of time for virt-rescue to connect to the
|
||
# daemon and mount any filesystems.
|
||
sleep 2
|
||
|
||
# Get name of the serial port, from console= passed by libguestfs.
|
||
# XXX Consider using /proc/consoles
|
||
guestfs_serial=$(grep -Eo 'console=[^[:space:]]+' /proc/cmdline |
|
||
sed s/console=//)
|
||
|
||
# Remove LD_PRELOAD=libSegFault set above.
|
||
unset LD_PRELOAD
|
||
|
||
:> $HOME/.bashrc
|
||
grep -Eo 'TERM=[^[:space:]]+' /proc/cmdline >> $HOME/.bashrc
|
||
echo "PS1='><rescue> '" >> $HOME/.bashrc
|
||
echo "export TERM PS1" >> $HOME/.bashrc
|
||
|
||
# The shell is opened by default on /dev/console, which (on Linux)
|
||
# is not a controlling terminal, causing job control to fail. For
|
||
# how we work around this, see:
|
||
# https://busybox.net/FAQ.html#job_control
|
||
run_bash_with_ctty ()
|
||
{
|
||
setsid bash -c \
|
||
"exec bash </dev/$guestfs_serial >/dev/$guestfs_serial 2>&1"
|
||
}
|
||
|
||
echo
|
||
echo "------------------------------------------------------------"
|
||
echo
|
||
echo "Welcome to virt-rescue, the libguestfs rescue shell."
|
||
echo
|
||
echo "Note: The contents of / (root) are the rescue appliance."
|
||
if ! test -d "/sysroot/dev"; then
|
||
echo "You have to mount the guest’s partitions under /sysroot"
|
||
echo "before you can examine them."
|
||
else
|
||
echo "Use 'cd /sysroot' or 'chroot /sysroot' to see guest filesystems."
|
||
fi
|
||
echo
|
||
run_bash_with_ctty
|
||
echo
|
||
echo "virt-rescue: Syncing the disk now before exiting ..."
|
||
echo
|
||
fi
|
||
|
||
sync
|
||
|
||
if ! test "$guestfs_noreboot" = 1; then
|
||
# qemu has the -no-reboot flag, so issuing a reboot here actually
|
||
# causes qemu to exit gracefully.
|
||
reboot -f
|
||
fi
|