AlaK4X
Linux lhjmq-records 5.15.0-118-generic #128-Ubuntu SMP Fri Jul 5 09:28:59 UTC 2024 x86_64



Your IP : 3.137.185.202


Current Path : /snap/lxd/31333/commands/
Upload File :
Current File : //snap/lxd/31333/commands/daemon.start

#!/bin/sh
set -eu

# Re-exec outside of apparmor confinement
if [ -d /sys/kernel/security/apparmor ] && [ "$(cat /proc/self/attr/current)" != "unconfined" ]; then
    exec aa-exec -p unconfined -- "$0" "$@"
fi

echo "=> Preparing the system (${SNAP_REVISION})"

# shellcheck disable=SC2155
export SNAP_CURRENT="$(realpath "${SNAP}/..")/current"

# shellcheck disable=SC2155
export ARCH="$(basename "$(readlink -f "${SNAP_CURRENT}"/lib/*-linux-gnu*/)")"

export HOME="/tmp/"
export LXD_DIR="${SNAP_COMMON}/lxd/"
export LXD_LXC_TEMPLATE_CONFIG="${SNAP_CURRENT}/lxc/config/"
export LXD_LXC_HOOK="${SNAP_CURRENT}/lxc/hooks/"
export LXD_EXEC_PATH="${SNAP_CURRENT}/bin/lxd"
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}:${SNAP_CURRENT}/lib:${SNAP_CURRENT}/lib/${ARCH}:${SNAP_CURRENT}/lib/${ARCH}/ceph"
export PATH="${PATH}:${SNAP_CURRENT}/bin"
export LXD_CLUSTER_UPDATE="${SNAP_CURRENT}/commands/refresh"
export LXD_OVMF_PATH="${SNAP_CURRENT}/share/qemu"
export PYTHONPATH=/snap/lxd/current/lib/python3/dist-packages/

# Detect model
SNAP_MODEL="$(nsenter -t 1 -m snap model --assertion | sed -n 's/^model: \(.\+\)/\1/p')"

# Wait for appliance configuration
if echo "${SNAP_MODEL}" | grep -q "^lxd-core"; then
    while :; do
        [ "$(nsenter -t 1 -m snap managed)" = "true" ] && break
        sleep 5
    done
fi

# Workaround for systemd nuking our cgroups on refreshes
nsenter -t 1 -m systemd-run -u snap."${SNAP_INSTANCE_NAME}".workaround -p Delegate=yes -r /bin/true >/dev/null 2>&1 || true

# Cleanup last state
true > "${SNAP_COMMON}/state"

# Load our configuration
if [ ! -e "${SNAP_COMMON}/config" ]; then
    echo "==> Creating missing snap configuration"
    "${SNAP_CURRENT}/meta/hooks/configure"
fi

echo "==> Loading snap configuration"
# shellcheck disable=SC1091
. "${SNAP_COMMON}/config"

# Create the main directory
if [ ! -d "${SNAP_COMMON}/lxd" ]; then
    echo "==> Creating ${SNAP_COMMON}/lxd"
    mkdir -p "${SNAP_COMMON}/lxd"
    chmod 0711 "${SNAP_COMMON}/lxd"
fi

if [ ! -d "${SNAP_COMMON}/lxd/logs" ]; then
    echo "==> Creating ${SNAP_COMMON}/lxd/logs"
    mkdir -p "${SNAP_COMMON}/lxd/logs"
    chmod 0700 "${SNAP_COMMON}/lxd/logs"
fi

if [ ! -d "${SNAP_COMMON}/global-conf" ]; then
    echo "==> Creating ${SNAP_COMMON}/global-conf"
    mkdir -p "${SNAP_COMMON}/global-conf"
    chmod 0755 "${SNAP_COMMON}/global-conf"
fi

# Setup mntns symlink
if [ ! -e "${SNAP_COMMON}/mntns" ] || [ -L "${SNAP_COMMON}/mntns" ]; then
    echo "==> Setting up mntns symlink ($(readlink /proc/self/ns/mnt))"
    rm -f "${SNAP_COMMON}/mntns"
    ln -s /proc/$$/root "${SNAP_COMMON}/mntns"
fi

# Fix /dev/pts
if [ "$(grep -F "devpts /dev/pts " /proc/self/mountinfo)" = "2" ]; then
    echo "==> Setting up /dev/pts"
    umount -l /dev/ptmx
    umount -l /dev/pts
fi

# Setup rshared propagation on mount holding paths
for path in "${SNAP_COMMON}/lxd/storage-pools" "${SNAP_COMMON}/lxd/devices"; do
    if ! cut -d' ' -f5 /proc/self/mountinfo | grep -qF "${path}"; then
        echo "==> Setting up mount propagation on ${path}"
        if [ ! -e "${path}" ]; then
            mkdir -p "${path}"
            chmod 0711 "${path}"
        fi

        mount -o bind "${path}" "${path}"
        mount --make-rshared "${path}"
    fi
done

# Setup shmounts
if ! mountpoint -q "${SNAP_COMMON}/shmounts"; then
    echo "==> Setting up persistent shmounts path"
    if ! mountpoint -q /media || ! setup-shmounts; then
        echo "====> Failed to setup shmounts, continuing without"
        mkdir -p "${SNAP_COMMON}/shmounts"
        mount -t tmpfs tmpfs "${SNAP_COMMON}/shmounts" -o size=1M,mode=0711
    fi

    if ! mountpoint -q "${SNAP_COMMON}/lxd/shmounts"; then
        echo "====> Making LXD shmounts use the persistent path"
        mkdir -p "${SNAP_COMMON}/shmounts/instances"
        if [ ! -L "${SNAP_COMMON}/lxd/shmounts" ]; then
            mkdir -p "${SNAP_COMMON}/lxd/"
            rm -rf "${SNAP_COMMON}/lxd/shmounts"
        else
            rm "${SNAP_COMMON}/lxd/shmounts"
        fi
        ln -s "${SNAP_COMMON}/shmounts/instances" "${SNAP_COMMON}/lxd/shmounts"
    fi

    if ! mountpoint -q "${SNAP_COMMON}/var/lib/lxcfs"; then
        echo "====> Making LXCFS use the persistent path"
        mkdir -p "${SNAP_COMMON}/shmounts/lxcfs"
        if [ ! -L "${SNAP_COMMON}/var/lib/lxcfs" ]; then
            mkdir -p "${SNAP_COMMON}/var/lib/"
            rm -rf "${SNAP_COMMON}/var/lib/lxcfs"
            ln -s "${SNAP_COMMON}/shmounts/lxcfs" "${SNAP_COMMON}/var/lib/lxcfs"
        fi
    fi
fi

# Fix lsmod/modprobe
echo "==> Setting up kmod wrapper"
mountpoint -q /bin/kmod || mount -o ro,bind "${SNAP}/wrappers/kmod" "/bin/kmod"

# Setup /boot
if [ -e /var/lib/snapd/hostfs/boot ]; then
    echo "==> Preparing /boot"
    umount -l /boot >/dev/null 2>&1 || true
    mount -o ro,bind "/var/lib/snapd/hostfs/boot" "/boot"
fi

# Setup a functional /run
echo "==> Preparing a clean copy of /run"
if [ -e "/run/.lxd_generated" ]; then
    umount -l /run
fi
mount -t tmpfs tmpfs /run -o mode=0755,nosuid,nodev
touch /run/.lxd_generated
for entry in NetworkManager resolvconf netconfig snapd snapd.socket snapd-snap.socket systemd udev user; do
    [ -e "/var/lib/snapd/hostfs/run/${entry}" ] || [ -L "/var/lib/snapd/hostfs/run/${entry}" ] || continue
    ln -s "/var/lib/snapd/hostfs/run/${entry}" "/run/${entry}"
done

# Setup an additional bin directory
echo "==> Preparing /run/bin"
mkdir -p "/run/bin"
export PATH="/run/bin:${PATH}"

if [ "${ceph_external:-"false"}" = "true" ]; then
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/ceph"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/radosgw-admin"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/rbd"
fi

if [ "${openvswitch_external:-"false"}" = "true" ]; then
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/ovs-appctl"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/ovs-vsctl"
fi

if [ "${lvm_external:-"false"}" = "true" ]; then
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvm"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/vgs"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvs"

    ln -s "${SNAP}/wrappers/run-host" "/run/bin/pvcreate"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/pvremove"

    ln -s "${SNAP}/wrappers/run-host" "/run/bin/vgcreate"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/vgchange"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/vgremove"

    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvcreate"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvchange"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvextend"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvrename"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvremove"
    ln -s "${SNAP}/wrappers/run-host" "/run/bin/lvresize"
fi

# Detect presence of sideloaded lxd-agent executable.
if [ -x "${SNAP_COMMON}/lxd-agent.debug" ]; then
    echo "==> WARNING: Using a custom debug lxd-agent binary!"
    ln -s "${SNAP_COMMON}/lxd-agent.debug" "/run/bin/lxd-agent"
fi

# Redirect getent to the host
ln -s "${SNAP}/wrappers/run-host" "/run/bin/getent"

# Avoid xtables talking to nft
ln -s "${SNAP}/bin/arptables-legacy" "/run/bin/arptables"
ln -s "${SNAP}/bin/ebtables-legacy" "/run/bin/ebtables"
ln -s /usr/sbin/xtables-legacy-multi "/run/bin/ip6tables"
ln -s /usr/sbin/xtables-legacy-multi "/run/bin/iptables"

# Setup a functional /etc
echo "==> Preparing a clean copy of /etc"

## Unmount and replace with an empty tmpfs
if [ -e "/etc/.lxd_generated" ]; then
    umount -l /etc
fi
mount -t tmpfs tmpfs /etc -o mode=0755
touch /etc/.lxd_generated

## Generate a new ld.so.cache
ldconfig

## Pass the bits we need from the host
for entry in hostid hostname hosts nsswitch.conf os-release passwd group localtime pki resolv.conf resolvconf timezone writable; do
    [ -e "/var/lib/snapd/hostfs/etc/${entry}" ] || [ -L "/var/lib/snapd/hostfs/etc/${entry}" ] || continue
    ln -s "/var/lib/snapd/hostfs/etc/${entry}" "/etc/${entry}"
done

## And the bits we need from the core snap
for entry in alternatives apparmor apparmor.d; do
    ln -s "/snap/core20/current/etc/${entry}" "/etc/${entry}"
done

## And those we directly ship in the snap
for entry in ethertypes protocols; do
    ln -s "${SNAP}/etc/${entry}" "/etc/${entry}"
done

## Setup mtab
ln -s "/proc/mounts" "/etc/mtab"

## Handle SSL certs
if [ -e "/var/lib/snapd/hostfs/etc/ssl" ] && [ -e "/var/lib/snapd/hostfs/usr/share/ca-certificates" ]; then
    ln -s "/var/lib/snapd/hostfs/etc/ssl" "/etc/ssl"
    mountpoint -q "/usr/share/ca-certificates" || mount -o ro,bind "/var/lib/snapd/hostfs/usr/share/ca-certificates" "/usr/share/ca-certificates"
else
    ln -s "/snap/core20/current/etc/ssl" "/etc/ssl"
fi

## Try to handle special /etc/resolv.conf setups
if [ -L /etc/resolv.conf ] && [ ! -e /etc/resolv.conf ]; then
    echo "====> Unusual /etc/resolv.conf detected, using workaround"
    rm -f /etc/resolv.conf
    # shellcheck disable=SC2094
    nsenter -t 1 -m cat /etc/resolv.conf > /etc/resolv.conf || true
fi

# Setup a functional /usr/share/misc
echo "==> Preparing a clean copy of /usr/share/misc"
if [ -e "/usr/share/misc/.lxd_generated" ]; then
    umount -l /usr/share/misc
fi
mount -t tmpfs tmpfs /usr/share/misc -o mode=0755
touch /usr/share/misc/.lxd_generated
ln -s "${SNAP_CURRENT}/share/misc/pci.ids" /usr/share/misc/
ln -s "${SNAP_CURRENT}/share/misc/usb.ids" /usr/share/misc/

# Setup host access
## Make /var/lib/snapd/hostfs more useful to us
for entry in dev proc sys; do
    mountpoint -q "/var/lib/snapd/hostfs/${entry}" && continue
    mount -o bind "/${entry}" "/var/lib/snapd/hostfs/${entry}"
done

# FIXME: Setup the "lxd" user
if ! getent passwd lxd >/dev/null 2>&1; then
    echo "==> Creating \"lxd\" user"
    if grep -q "^passwd.*extrausers" /etc/nsswitch.conf; then
        nsenter -t 1 -m useradd --system -M -N --home /var/snap/lxd/common/lxd --shell /bin/false --extrausers lxd || true
    else
        nsenter -t 1 -m useradd --system -M -N --home /var/snap/lxd/common/lxd --shell /bin/false lxd || true
    fi
fi

# FIXME: Setup the "lxd" group
if [ "${daemon_group:-"lxd"}" = "lxd" ] && ! getent group lxd >/dev/null 2>&1; then
    echo "==> Creating \"lxd\" group"
    if grep -q "^group.*extrausers" /etc/nsswitch.conf; then
        nsenter -t 1 -m groupadd --system --extrausers lxd || true
    else
        nsenter -t 1 -m groupadd --system lxd || true
    fi
fi

# Setup for ceph
echo "==> Setting up ceph configuration"
if [ "${ceph_builtin:-"false"}" = "true" ]; then
    mkdir -p "${SNAP_COMMON}/ceph"
    ln -s "${SNAP_COMMON}/ceph" /etc/ceph
elif [ -e "/var/snap/microceph" ]; then
    ln -s /var/snap/microceph/current/conf/ /etc/ceph
else
    ln -s /var/lib/snapd/hostfs/etc/ceph /etc/ceph
fi

# Setup for LVM
echo "==> Setting up LVM configuration"
mkdir -p /etc/lvm/
sed \
    -e "s#obtain_device_list_from_udev = 1#obtain_device_list_from_udev = 0#g" \
    -e "s#cache_file_prefix = \"\"#cache_file_prefix = \"lxd\"#g" \
    -e "s#udev_sync = 1#udev_sync = 0#g" \
    -e "s#udev_rules = 1#udev_rules = 0#g" \
    -e "s#use_lvmetad = 1#use_lvmetad = 0#g" \
    -e "s#monitoring = 1#monitoring = 0#g" \
    -e "s%# executable = \"/sbin/dmeventd\"%executable = \"${SNAP}/bin/dmeventd\"%g" \
    -e "/# .*_executable =/s/# //g" \
    -e "s#/usr/sbin/#${SNAP}/bin/#g" \
    "${SNAP}/etc/lvm/lvm.conf" > /etc/lvm/lvm.conf

# Setup for OVN
echo "==> Setting up OVN configuration"
if [ "${ovn_builtin:-"false"}" = "true" ]; then
    mkdir -p "${SNAP_COMMON}/ovn"
    ln -s "${SNAP_COMMON}/ovn" /etc/ovn
else
    ln -s /var/lib/snapd/hostfs/etc/ovn /etc/ovn
fi

# Rotate logs
echo "==> Rotating logs"
logrotate -f "${SNAP}/etc/logrotate.conf" -s "/etc/logrotate.status" || true

# Setup for ZFS
if [ -e /sys/module/zfs/version ]; then
    read -r VERSION < /sys/module/zfs/version
else
    VERSION=$(nsenter -t 1 -m modinfo -F version zfs 2>/dev/null || true)
fi

if echo "${VERSION}" | grep -q ^2\.2; then
    echo "==> Setting up ZFS (2.2)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-2.2/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-2.2/bin:${PATH}"
elif echo "${VERSION}" | grep -q ^2\.1; then
    echo "==> Setting up ZFS (2.1)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-2.1/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-2.1/bin:${PATH}"
elif echo "${VERSION}" | grep -q ^2\.0; then
    echo "==> Setting up ZFS (2.0)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-2.0/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-2.0/bin:${PATH}"
elif echo "${VERSION}" | grep -q ^0\.8; then
    echo "==> Setting up ZFS (0.8)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-0.8/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-0.8/bin:${PATH}"
elif echo "${VERSION}" | grep -q ^0\.7; then
    echo "==> Setting up ZFS (0.7)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-0.7/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-0.7/bin:${PATH}"
elif echo "${VERSION}" | grep -q ^0\.6; then
    echo "==> Setting up ZFS (0.6)"
    export LD_LIBRARY_PATH="${SNAP_CURRENT}/zfs-0.6/lib/:${LD_LIBRARY_PATH}"
    export PATH="${SNAP_CURRENT}/zfs-0.6/bin:${PATH}"
fi

# Escape resource limits
echo "==> Escaping the systemd cgroups"
if [ -e "/sys/fs/cgroup/cgroup.procs" ]; then
    echo "====> Detected cgroup V2"

    # Try to escape to the root (V2 hosts)
    if ! echo "$$" > "/sys/fs/cgroup/cgroup.procs" 2>/dev/null; then
        # Create a .lxc cgroup if missing
        if [ ! -d "/sys/fs/cgroup/.lxc" ]; then
            mkdir /sys/fs/cgroup/.lxc
        fi

        # Use .lxc as the cgroup
        echo "$$" > "/sys/fs/cgroup/.lxc/cgroup.procs"
    fi
else
    echo "====> Detected cgroup V1"
    for ctr in /sys/fs/cgroup/*; do
        [ -e "${ctr}/cgroup.procs" ] || continue
        echo "$$" > "${ctr}/cgroup.procs"
    done

    # Fix common cgroup issues
    if [ -e /sys/fs/cgroup/cpuset/cgroup.clone_children ]; then
        # Attempt to enable clone_children behavior (ignore failures)
        echo 1 > /sys/fs/cgroup/cpuset/cgroup.clone_children 2>/dev/null || true
    fi
fi

# Update system limits
if [ "$(stat -c '%u' /proc)" = 0 ]; then
    ## prlimits
    echo "==> Escaping the systemd process resource limits"
    prlimit -p $$ --nofile=1048576:1048576 || true
    prlimit -p $$ --nproc=unlimited:unlimited || true

    ## Handle sysctls
    if [ -e /proc/sys/fs/inotify/max_user_instances ]; then
        if [ "$(cat /proc/sys/fs/inotify/max_user_instances)" -lt "1024" ]; then
            echo "==> Increasing the number of inotify user instances"
            echo 1024 > /proc/sys/fs/inotify/max_user_instances || true
        fi
    fi

    if [ -e /proc/sys/kernel/keys/maxkeys ]; then
        if [ "$(cat /proc/sys/kernel/keys/maxkeys)" -lt "2000" ]; then
            echo "==> Increasing the number of keys for a nonroot user"
            echo 2000 > /proc/sys/kernel/keys/maxkeys || true
        fi
    fi

    if [ -e /proc/sys/kernel/keys/maxbytes ]; then
        if [ "$(cat /proc/sys/kernel/keys/maxbytes)" -lt "2000000" ]; then
            echo "==> Increasing the number of bytes for a nonroot user"
            echo 2000000 > /proc/sys/kernel/keys/maxbytes || true
        fi
    fi

    if [ -e /proc/sys/kernel/unprivileged_userns_clone ]; then
        if [ "$(cat /proc/sys/kernel/unprivileged_userns_clone)" = "0" ]; then
            echo "==> Enabling unprivileged containers kernel support"
            echo 1 > /proc/sys/kernel/unprivileged_userns_clone || true
        fi
    fi

    if [ -e /proc/sys/kernel/apparmor_restrict_unprivileged_userns ]; then
        if [ "$(cat /proc/sys/kernel/apparmor_restrict_unprivileged_userns)" = "1" ]; then
            echo "==> Disabling Apparmor unprivileged userns mediation"
            echo 0 > /proc/sys/kernel/apparmor_restrict_unprivileged_userns || true
        fi
    fi

    if [ -e /proc/sys/kernel/apparmor_restrict_unprivileged_unconfined ]; then
        if [ "$(cat /proc/sys/kernel/apparmor_restrict_unprivileged_unconfined)" = "1" ]; then
            echo "==> Disabling Apparmor unprivileged unconfined mediation"
            echo 0 > /proc/sys/kernel/apparmor_restrict_unprivileged_unconfined || true
        fi
    fi
fi

# Setup CRIU
if [ "${criu_enable:-"false"}" = "true" ]; then
    echo "==> Enabling CRIU"
    export PATH="${SNAP_CURRENT}/criu:${PATH}"
fi

# Setup UI
if [ "${ui_enable:-"false"}" = "true" ]; then
    echo "==> Enabling LXD UI"
    export LXD_UI="${SNAP_CURRENT}/share/lxd-ui/"
fi

# Setup shiftfs
if [ "${shiftfs_enable:-"auto"}" = "auto" ]; then
    echo "==> Disabling shiftfs on this kernel (auto)"
    shiftfs_enable="false"
elif [ "${shiftfs_enable:-"auto"}" = "false" ]; then
    echo "==> Disabling shiftfs at user request"
fi

if [ "${shiftfs_enable:-"auto"}" = "false" ]; then
    export LXD_SHIFTFS_DISABLE=true
fi

# LXC
## Host specific overrides
mkdir -p "${SNAP_COMMON}/lxc"
touch "${SNAP_COMMON}/lxc/local.conf"
if [ -d /sys/kernel/security/apparmor ] && ! grep -qF -- "-Ubuntu" /proc/version; then
    echo "==> Detected kernel with partial AppArmor support"
    echo "lxc.apparmor.allow_incomplete = 1" > "${SNAP_COMMON}/lxc/local.conf"
else
    true > "${SNAP_COMMON}/lxc/local.conf"
fi

# Open vSwitch
if [ "${openvswitch_builtin:-"false"}" = "true" ]; then
    echo "=> Starting Open vSwitch"
    export OVS_RUNDIR="${SNAP_COMMON}/openvswitch/run/"
    (
        set -e
        export OVS_LOGDIR="${SNAP_COMMON}/openvswitch/logs/"
        export OVS_DBDIR="${SNAP_COMMON}/openvswitch/db/"
        export OVS_SYSCONFDIR="${SNAP_COMMON}/openvswitch/conf/"
        export OVS_PKGDATADIR="${SNAP}/share/openvswitch/"
        export OVS_BINDIR="${SNAP}/bin/"
        export OVS_SBINDIR="${SNAP}/bin/"

        mkdir -p "${OVS_SYSCONFDIR}/openvswitch"
        (
            # Close socket activation fd
            exec 3<&- || true

           "${SNAP}/share/openvswitch/scripts/ovs-ctl" start --system-id=random
        )
    )
else
    ln -s /var/lib/snapd/hostfs/run/openvswitch /run/openvswitch
fi

# LXCFS
if [ -e "${SNAP_COMMON}/var/lib/lxcfs/cgroup" ]; then
    echo "=> Re-using existing LXCFS"
    NEW_FUSE=$(ldd "${SNAP_CURRENT}/bin/lxcfs" | grep libfuse | sed -e "s/.*libfuse.so.//g" -e "s/ .*//g")
    CURRENT_FUSE="${NEW_FUSE}"

    if [ -e "${SNAP_COMMON}/lxcfs.pid" ]; then
        read -r CURRENT_PID < "${SNAP_COMMON}/lxcfs.pid"
        if [ -e "/proc/${CURRENT_PID}" ]; then
            CURRENT_FUSE=$(ldd "/proc/${CURRENT_PID}/exe" | grep libfuse | sed -e "s/.*libfuse.so.//g" -e "s/ .*//g")
        fi
    fi

    if [ "${CURRENT_FUSE}" != "${NEW_FUSE}" ]; then
        echo "==> FUSE version mismatch, restart system to upgrade LXCFS"
    elif [ -n "${CURRENT_PID:-}" ]; then
        echo "==> Reloading LXCFS"
        kill -USR1 "${CURRENT_PID}" || true
    fi
else
    ## Undo any existing mount
    umount -l "${SNAP_COMMON}/var/lib/lxcfs" >/dev/null 2>&1 || true
    fusermount -u "${SNAP_COMMON}/var/lib/lxcfs" >/dev/null 2>&1 || true

    ## Create the mount point
    mkdir -p "${SNAP_COMMON}/var/lib/lxcfs"

    ## Cleanup any leftover
    rm -f "${SNAP_COMMON}/lxcfs.pid"

    ## Start lxcfs
    echo "=> Starting LXCFS"
    (
        # Close socket activation fd
        exec 3<&- || true

        # Spawn lxcfs
        export LD_LIBRARY_PATH="${SNAP_CURRENT}/lib:${SNAP_CURRENT}/lib/${ARCH}"
        lxcfs_args=
        [ "${lxcfs_loadavg:-"false"}" = "true" ] && lxcfs_args="${lxcfs_args} --enable-loadavg"
        [ "${lxcfs_pidfd:-"false"}" = "true" ] && lxcfs_args="${lxcfs_args} --enable-pidfd"
        [ "${lxcfs_cfs:-"false"}" = "true" ] && lxcfs_args="${lxcfs_args} --enable-cfs"
        [ "${lxcfs_debug:-"false"}" = "true" ] && lxcfs_args="${lxcfs_args} -d"

        # Preload libSegFault.so to catch crashes
        export LD_PRELOAD="${LD_PRELOAD:+${LD_PRELOAD}:}/lib/${ARCH}/libSegFault.so"
        export SEGFAULT_USE_ALTSTACK=1
        export SEGFAULT_SIGNALS="all"

        if [ -n "${lxcfs_args}" ]; then
            # shellcheck disable=SC2086
            lxcfs ${lxcfs_args} "${SNAP_COMMON}/var/lib/lxcfs" -p "${SNAP_COMMON}/lxcfs.pid" &
        else
            lxcfs "${SNAP_COMMON}/var/lib/lxcfs" -p "${SNAP_COMMON}/lxcfs.pid" &
        fi

        # Wait for PID file
        sleep 1
    )
fi

PID=""
[ -e "${SNAP_COMMON}/lxcfs.pid" ] && read -r PID < "${SNAP_COMMON}/lxcfs.pid"
if [ -n "${PID}" ] && [ "$(readlink "/proc/self/ns/mnt")" != "$(readlink "/proc/${PID}/ns/mnt")" ]; then
    echo "==> Cleaning up existing LXCFS namespace"

    cut -d' ' -f5 "/proc/${PID}/mountinfo" | while read -r line; do
        if echo "${line}" | grep -q "^${SNAP_COMMON}/shmounts/storage-pools/"; then
            nsenter -t "${PID}" -m umount -l "${line}" || true
        fi

        if echo "${line}" | grep -q "^${SNAP_COMMON}/lxd/storage-pools/"; then
            nsenter -t "${PID}" -m umount -l "${line}" || true
        fi
    done
fi

# LXD
## Check for existing LXDs
for pid in $(pgrep -f "lxd --logfile" ; pgrep -f "lxd.debug --logfile"); do
    grep -qF "SNAP_NAME=lxd" "/proc/${pid}/environ" || continue

    rm -f "/var/snap/lxd/common/lxd/.validate"
    touch "/proc/${pid}/root/var/snap/lxd/common/lxd/.validate" 2>/dev/null || true
    if [ -e "/var/snap/lxd/common/lxd/.validate" ]; then
        echo "=> Killing conflicting LXD (pid=${pid})"
        kill -9 "${pid}" || true
        rm -f "/var/snap/lxd/common/lxd/.validate"
    fi
done

## Move the database out of the versioned path if present
if [ -L "${SNAP_COMMON}/lxd/lxd.db" ]; then
    echo "=> Moving database from versioned path to common"
    rm "${SNAP_COMMON}/lxd/lxd.db"
    mv "${SNAP_DATA}/lxd/lxd.db" "${SNAP_COMMON}/lxd/lxd.db"
fi

## Start lxd
echo "=> Starting LXD"

LXD="lxd"
if [ -x "${SNAP_COMMON}/lxd.debug" ]; then
    LXD="${SNAP_COMMON}/lxd.debug"
    export LXD_EXEC_PATH="${LXD}"
    echo "==> WARNING: Using a custom debug LXD binary!"
fi

CMD="${LXD} --logfile ${SNAP_COMMON}/lxd/logs/lxd.log"

if getent group "${daemon_group}" >/dev/null 2>&1; then
    CMD="${CMD} --group ${daemon_group}"
    if [ -e "/var/snap/lxd/common/lxd/unix.socket" ]; then
        chgrp "${daemon_group}" /var/snap/lxd/common/lxd/unix.socket
    fi
else
    echo "==> No \"${daemon_group}\" group found, only root will be able to use LXD."
fi

if [ "${daemon_debug:-"false"}" = "true" ]; then
    CMD="${CMD} --debug"
fi

if [ "${daemon_syslog:-"false"}" = "true" ]; then
    CMD="${CMD} --syslog"
fi

if [ "${daemon_verbose:-"false"}" = "true" ]; then
    CMD="${CMD} --verbose"
fi

# Check if this is the first time LXD is started.
FIRSTRUN="false"
if [ ! -d "${SNAP_COMMON}/lxd/database" ]; then
    FIRSTRUN="true"
fi

# We deal with errors ourselves from this point on
set +e

# Spawn LXD
(
    read -r sbpid _ < /proc/self/stat
    export LISTEN_PID="${sbpid}"

    # shellcheck disable=SC2086
    exec ${CMD}
)&
PID=$!
echo ${PID} > "${SNAP_COMMON}/lxd.pid"

## Wait for it to be ready
"${LXD}" waitready &
WAIT_PID=$!

## Monitor LXD and waitready
(
    while :; do
        sleep 1

        if ! kill -0 "${WAIT_PID}" >/dev/null 2>&1; then
            # "lxd waitready" exited
            break
        fi

        if ! kill -0 "${PID}" >/dev/null 2>&1; then
            # "lxd" exited
            kill -9 "${WAIT_PID}"
        fi
    done
) &

## Wait for waitready to be done
wait "${WAIT_PID}"
RET=$?

if [ "${RET}" -gt "0" ]; then
    echo "=> LXD failed to start"
    echo "crashed" > "${SNAP_COMMON}/state"
    exit 1
fi

## Process preseed if present
if [ "${FIRSTRUN}" = "true" ]; then
    set -e
    echo "=> First LXD execution on this system"

    if [ -e "${SNAP_COMMON}/init.yaml" ]; then
        echo "==> Running LXD preseed file"
        ${LXD} init --preseed < "${SNAP_COMMON}/init.yaml"
        mv "${SNAP_COMMON}/init.yaml" "${SNAP_COMMON}/init.yaml.applied"
    elif echo "${SNAP_MODEL}" | grep -q "^lxd-core"; then
        echo "==> Initializing LXD appliance"

        # Network (NIC with the default gateway)
        NIC="$(ip -4 -o route get 0.0.0.1 | cut -d' ' -f5)"
        lxc --force-local --quiet profile device add default eth0 nic nictype=macvlan parent="${NIC}" name=eth0

        # Storage (80% of free space)
        AVAIL="$(($(df --output=avail "${SNAP_COMMON}" | tail -1)*1024*80/100))"
        for fs in zfs btrfs; do
            lxc --force-local --quiet storage create local "${fs}" size="${AVAIL}" && break
        done
        lxc --force-local --quiet profile device add default root disk pool=local path=/

        # Network access
        lxc --force-local --quiet config set core.https_address :8443
    fi
    set +e
fi

## Wait for the daemon to die
echo "=> LXD is ready"
wait "$PID"
RET=$?

if [ "${RET}" -gt "0" ]; then
    echo "crashed" > "${SNAP_COMMON}/state"
    echo "=> LXD failed with return code ${RET}"
    exit 1
else
    STATE=""
    [ -e "${SNAP_COMMON}/state" ] && read -r STATE < "${SNAP_COMMON}/state"

    if [ "${STATE}" = "reload" ]; then
        echo "=> LXD is reloading"
        exit 1
    fi

    if [ "${STATE}" = "host-shutdown" ]; then
        true > "${SNAP_COMMON}/state"
    else
        echo shutdown > "${SNAP_COMMON}/state"
    fi

    echo "=> LXD exited cleanly"
fi

exit 0