From 787a678a793f97d6b8aeea01d341fa014f086f16 Mon Sep 17 00:00:00 2001 From: selfhoster1312 Date: Tue, 6 Jun 2023 12:28:58 +0200 Subject: [PATCH] Add `editvm.sh TEMPLATE CMD` command --- README.md | 12 ++++ bin/editvm.sh | 120 +++++++++++++++++++++++++++++++++++ bin/mkvm.sh | 2 + setup.sh | 1 + templates/archlinux.template | 3 +- templates/bullseye.template | 3 +- 6 files changed, 139 insertions(+), 2 deletions(-) create mode 100755 bin/editvm.sh diff --git a/README.md b/README.md index d353b8d..c4a8069 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,18 @@ The `mkvm.sh` script takes the type of container to run as first argument. That Unless the `--keep` argument is passed, the container is also destroyed after running. +## Edit the template filesystem + +If you need to change a template's rootfs, for running updates or adding packages, you can use the `editvm.sh` script: + +``` +editvm.sh archlinux bash +``` + +This will fail if the ramdisk service is still running, so first stop all your containers, stop the ramdisk service, and try again. Don't forget to restart the ramdisk service after you're done. + +If the LXC you want to use does not use a rootfs with its own name in the `/ramdisk/persist/` folder, the script will also error out. + ## License GNU aGPL v3 diff --git a/bin/editvm.sh b/bin/editvm.sh new file mode 100755 index 0000000..26d661a --- /dev/null +++ b/bin/editvm.sh @@ -0,0 +1,120 @@ +#! /usr/bin/env bash + +help() { + echo "editvm.sh DISTRO [CMD] [ARGS]" + echo " Stops the ramdisk and start editing a VM template" + echo " --copy PATHSRC PATHDEST: copy PATHSRC into the container as PATHDEST" +} + +KEEP=0 + +SYSDIR="/ramdisk/sys" +TMPDIR="/ramdisk/tmp" + +if [ $# -lt 2 ]; then + help + exit 0 +fi + +# Files to copy into container +COPY=() +COPYDEST=() + +while true; do + case "$1" in + "-h"|"--help") + help + exit 0 + ;; + "--copy") + shift + PATHSRC="$1" + if [ ! -e "$PATHSRC" ]; then + echo "COPY ERROR: File/Folder "$PATHSRC" does not exist." + exit 1 + fi + shift + PATHDEST="$1" + COPY+=("$PATHSRC") + COPYDEST+=("$PATHDEST") + shift + ;; + *) + # Optional args processing finished + # If no first argument is passed, syntax error + if [[ "$1" = "" ]]; then + help + exit 1 + fi + TYPE="$1" + shift + break + ;; + esac +done + +if systemctl is-active ramdisk; then + echo "ERROR: Please stop ramdisk.service first" + exit 1 +fi + +TEMPLATE=/var/lib/lxc/"$TYPE".template + +if [ ! -f "$TEMPLATE" ]; then + echo "ERROR: No such VM type "$TYPE"" + exit 1 +fi + +export VMNAME="$TYPE-TEMPLATE" +echo "$VMNAME" + +export LXCROOTFS=/ramdisk/persist/$TYPE +# Check if the rootfs exists... maybe the template actually calls another rootfs +if [ ! -d "$LXCROOTFS" ]; then + echo "ERROR: The container template "$TYPE" does not have its own rootfs. Maybe it's using another rootfs?" + echo "Check the lxc.rootfs.path line in "$TEMPLATE" file to be sure." + exit 1 +fi + +LXCDIR=/var/lib/lxc/"$VMNAME" +mkdir "$LXCDIR" +envsubst < "$TEMPLATE" > "$LXCDIR"/config + +ROOTFS="$LXCROOTFS" +echo "template" > "$ROOTFS"/etc/hostname + +# Copy files into the VM +for fileIndex in ${!COPY[@]}; do + PATHSRC="${COPY[$fileIndex]}" + PATHDEST="$ROOTFS""${COPYDEST[$fileIndex]}" + # Create parent dirs + PARENTPATHDEST="$(dirname "$PATHDEST")" + mkdir -p "$PARENTPATHDEST" + cp --dereference -r "$PATHSRC" "$PATHDEST" +done + +CMD="$1" +shift + +if [[ "$CMD" != "" ]]; then + #lxc-execute -n "$VMNAME" -- "$CMD" "$@" + lxc-start -n "$VMNAME" + lxc-attach -n "$VMNAME" -- "$CMD" "$@" + if [ $KEEP -eq 0 ]; then + lxc-stop --kill "$VMNAME" + # Don't destroy VM because we want to keep the rootfs + # (we are just editing it live) + # lxc-destroy -n "$VMNAME" + rm -R /var/lib/lxc/"$VMNAME" + fi +else + lxc-start -n "$VMNAME" + lxc-attach -n "$VMNAME" bash + if [ $KEEP -eq 0 ]; then + lxc-stop --kill "$VMNAME" + # Don't destroy VM because we want to keep the rootfs + # (we are just editing it live) + #lxc-destroy -n "$VMNAME" + rm -R /var/lib/lxc/"$VMNAME" + fi +fi diff --git a/bin/mkvm.sh b/bin/mkvm.sh index e31c573..0d52da9 100755 --- a/bin/mkvm.sh +++ b/bin/mkvm.sh @@ -67,6 +67,8 @@ fi export VMNAME="$TYPE-$RANDOM" echo "$VMNAME" +export LXCROOTFS="overlayfs:/ramdisk/sys/$TYPE:/ramdisk/tmp/$VMNAME" +echo "$LXCROOTFS" LXCDIR=/var/lib/lxc/"$VMNAME" mkdir "$LXCDIR" envsubst < "$TEMPLATE" > "$LXCDIR"/config diff --git a/setup.sh b/setup.sh index 6d80cb0..10e692a 100755 --- a/setup.sh +++ b/setup.sh @@ -9,6 +9,7 @@ mkdir -p /ramdisk/persist ln -sf "$(pwd)"/bin/ramdisk.sh /usr/sbin/ ln -sf "$(pwd)"/bin/mkvm.sh /usr/sbin/ +ln -sf "$(pwd)"/bin/editvm.sh /usr/sbin/ ln -sf "$(pwd)"/ramdisk.service /etc/systemd/system/ systemctl daemon-reload diff --git a/templates/archlinux.template b/templates/archlinux.template index 8b9b85d..f991387 100644 --- a/templates/archlinux.template +++ b/templates/archlinux.template @@ -12,7 +12,8 @@ lxc.net.0.link = lxcbr0 lxc.net.0.flags = up lxc.apparmor.profile = generated lxc.apparmor.allow_nesting = 1 -lxc.rootfs.path = overlayfs:/ramdisk/sys/archlinux:/ramdisk/tmp/$VMNAME +# Use $LXCROOTFS variable which is different between mkvm.sh/editvm.sh +lxc.rootfs.path = $LXCROOTFS # Common configuration lxc.include = /usr/share/lxc/config/archlinux.common.conf diff --git a/templates/bullseye.template b/templates/bullseye.template index e657dc4..5b98d34 100644 --- a/templates/bullseye.template +++ b/templates/bullseye.template @@ -12,7 +12,8 @@ lxc.net.0.link = lxcbr0 lxc.net.0.flags = up lxc.apparmor.profile = generated lxc.apparmor.allow_nesting = 1 -lxc.rootfs.path = overlayfs:/ramdisk/sys/bullseye:/ramdisk/tmp/$VMNAME +# Use $LXCROOTFS variable which is different between mkvm.sh/editvm.sh +lxc.rootfs.path = $LXCROOTFS # Common configuration lxc.include = /usr/share/lxc/config/debian.common.conf