aboutsummaryrefslogtreecommitdiff
path: root/kvm-promote-to-base
diff options
context:
space:
mode:
authorLukasz Kasprzak <lukasz.kasprzak@pm.me>2026-01-23 12:48:30 +0100
committerLukasz Kasprzak <lukasz.kasprzak@pm.me>2026-01-23 12:48:30 +0100
commit97f968a30e7dc28f6d99bfbaae8a4aeefb6ad525 (patch)
tree5a250224ab69a04f05be2f757af86bfee9a7fec0 /kvm-promote-to-base
parenta00f92fdb6062af011d98ba8af6ddf0713fa7b3e (diff)
downloadbin-97f968a30e7dc28f6d99bfbaae8a4aeefb6ad525.tar.gz
bin-97f968a30e7dc28f6d99bfbaae8a4aeefb6ad525.zip
added all of my scripts
Diffstat (limited to 'kvm-promote-to-base')
-rwxr-xr-xkvm-promote-to-base87
1 files changed, 87 insertions, 0 deletions
diff --git a/kvm-promote-to-base b/kvm-promote-to-base
new file mode 100755
index 0000000..93e703e
--- /dev/null
+++ b/kvm-promote-to-base
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+URI="qemu:///system"
+IMGROOT="/var/lib/libvirt/images"
+BASEDIR="$IMGROOT/base"
+SNAPROOT="$HOME/.backup/kvm-labs"
+
+usage() {
+ echo "Usage: kvm-promote-to-base <vm-name> [--disk vda]"
+ echo "Creates: $BASEDIR/<vm-name>-base-YYYY-MM-DD_HHMMSS.qcow2"
+ exit 1
+}
+
+VM="${1:-}"
+DISKTGT="vda"
+
+shift || true
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --disk)
+ DISKTGT="${2:-}"
+ shift 2
+ ;;
+ -h|--help)
+ usage
+ ;;
+ *)
+ echo "ERROR: Unknown arg: $1"
+ usage
+ ;;
+ esac
+done
+
+if [[ -z "$VM" ]]; then
+ usage
+fi
+
+if [[ ! -d "$BASEDIR" ]]; then
+ echo "ERROR: Base directory missing: $BASEDIR"
+ exit 1
+fi
+
+state="$(virsh -c "$URI" domstate "$VM" 2>/dev/null | tr -d '\r' || true)"
+if [[ "$state" != "shut off" ]]; then
+ echo "ERROR: VM must be shut off for consistent promotion."
+ echo "VM: $VM"
+ echo "State: ${state:-unknown}"
+ exit 1
+fi
+
+DISK="$(virsh -c "$URI" domblklist "$VM" --details | awk -v t="$DISKTGT" '$3==t{print $4}')"
+if [[ -z "$DISK" || ! -f "$DISK" ]]; then
+ echo "ERROR: Cannot locate disk for $VM target=$DISKTGT"
+ echo "Detected: '$DISK'"
+ exit 1
+fi
+
+TS="$(date +%F_%H%M%S)"
+SNAPDIR="$SNAPROOT/${TS}-promote-${VM}"
+NEWBASE="$BASEDIR/${VM}-base-${TS}.qcow2"
+
+mkdir -p "$SNAPDIR"
+
+# Snapshot metadata (read-only)
+virsh -c "$URI" dumpxml "$VM" > "$SNAPDIR/${VM}.xml"
+sudo qemu-img info --backing-chain "$DISK" > "$SNAPDIR/${VM}.${DISKTGT}.backing-chain.txt" || true
+sudo ls -l "$DISK" > "$SNAPDIR/${VM}.${DISKTGT}.ls.txt" || true
+
+echo "Creating base image:"
+echo " VM: $VM"
+echo " Disk: $DISK (target: $DISKTGT)"
+echo " Target: $NEWBASE"
+
+sudo qemu-img convert -O qcow2 "$DISK" "$NEWBASE"
+sudo chown libvirt-qemu:libvirt "$NEWBASE"
+sudo chmod 0660 "$NEWBASE"
+
+echo "Verifying new base has no backing file..."
+if sudo qemu-img info "$NEWBASE" | grep -q '^backing file:'; then
+ echo "ERROR: New base unexpectedly has a backing file. Aborting."
+ exit 1
+fi
+
+echo "SUCCESS: $NEWBASE"
+echo "Snapshot: $SNAPDIR"
+