#!/usr/bin/env bash # Provision the dedicated storage VM from a Debian 13 cloud image driven by a # cloud-init NoCloud seed. It comes up serving NFS (/srv/nfs) and an iSCSI LUN. set -euo pipefail source "$(dirname "$0")/lab.env" sudo -v # prompt for the sudo password once, up front PUBKEY="$(cat "$SSH_PUB")" BASE_IMG="${LIB_DIR}/${DEBIAN_IMG}" OS_DISK="${LIB_DIR}/${STORE_NAME}.qcow2" DATA_DISK="${LIB_DIR}/${STORE_NAME}-data.qcow2" SEED_ISO="${LIB_DIR}/${STORE_NAME}-seed.iso" echo "==> Fetching Debian cloud image (if needed)" if ! sudo test -f "$BASE_IMG"; then sudo curl -fL --progress-bar -o "$BASE_IMG" "$DEBIAN_URL" fi echo "==> Building cloud-init seed ISO" SEED_SRC="${BUILD_DIR}/cloud-init" mkdir -p "$SEED_SRC" sed -e "s|@@ROOT_PASSWORD@@|${ROOT_PASSWORD}|g" \ -e "s|@@SSH_PUBKEY@@|${PUBKEY}|g" \ -e "s|@@ISCSI_IQN@@|${ISCSI_IQN}|g" \ -e "s|@@ISCSI_LUN_GB@@|${ISCSI_LUN_GB}|g" \ "${SCRIPT_DIR}/cloud-init/user-data" > "${SEED_SRC}/user-data" cp "${SCRIPT_DIR}/cloud-init/meta-data" "${SEED_SRC}/meta-data" genisoimage -quiet -output "${BUILD_DIR}/${STORE_NAME}-seed.iso" \ -volid cidata -joliet -rock "${SEED_SRC}/user-data" "${SEED_SRC}/meta-data" sudo cp -f "${BUILD_DIR}/${STORE_NAME}-seed.iso" "$SEED_ISO" echo "==> Preparing disks" if sudo virsh dominfo "$STORE_NAME" >/dev/null 2>&1; then echo " $STORE_NAME already defined; destroying + undefining first" sudo virsh destroy "$STORE_NAME" 2>/dev/null || true sudo virsh undefine "$STORE_NAME" --remove-all-storage 2>/dev/null || true fi sudo cp -f "$BASE_IMG" "$OS_DISK" sudo qemu-img resize "$OS_DISK" 12G sudo qemu-img create -f qcow2 "$DATA_DISK" "${STORE_DATA_DISK_GB}G" >/dev/null command -v restorecon >/dev/null && sudo restorecon -R "$LIB_DIR" || true echo "==> Creating storage VM" sudo virt-install \ --connect qemu:///system \ --name "$STORE_NAME" \ --memory "$STORE_RAM_MB" \ --vcpus "$STORE_VCPU" \ --cpu host-passthrough \ --machine q35 \ --osinfo detect=on,name=debian12 \ --import \ --disk "path=${OS_DISK},format=qcow2,bus=virtio" \ --disk "path=${DATA_DISK},format=qcow2,bus=virtio" \ --disk "path=${SEED_ISO},device=cdrom" \ --network "network=${NET_NAME},mac=${STORE_MAC},model=virtio" \ --graphics vnc,listen=127.0.0.1 \ --noautoconsole echo "==> Waiting for storage VM ($STORE_IP) over SSH" tries=0 while ! lab_ssh "$STORE_IP" true >/dev/null 2>&1; do sleep 10; tries=$((tries+1)) if (( tries % 6 == 0 )); then echo " still waiting ... (${tries}0s)"; fi if (( tries > 90 )); then echo "ERROR: storage VM not reachable after 15m"; exit 1; fi done # count helper: emit a single integer, never fail (grep -c exits 1 on zero match) remote_count() { lab_ssh "$STORE_IP" "$1 2>/dev/null | grep -c -- '$2'; true" 2>/dev/null | tr -dc '0-9' | tail -c1; } echo "==> Verifying services (cloud-init may still be finishing; retrying)" nfs_ok=0; iscsi_ok=0 for i in $(seq 1 30); do nfs_ok=$(remote_count "exportfs -v" "/srv/nfs"); nfs_ok=${nfs_ok:-0} iscsi_ok=$(remote_count "tgtadm --mode target --op show" "${ISCSI_IQN}"); iscsi_ok=${iscsi_ok:-0} if (( nfs_ok >= 1 && iscsi_ok >= 1 )); then break; fi sleep 10 done echo " NFS export present: ${nfs_ok}, iSCSI target present: ${iscsi_ok}" (( nfs_ok >= 1 && iscsi_ok >= 1 )) || { echo "WARN: storage services not confirmed. Check that the VM has internet (apt) and" echo " 'cloud-init status --long' on ${STORE_IP}. See README troubleshooting."; } echo echo "Storage VM ready. Next: ./06-form-cluster.sh"