From 9d0bfec87eeef17e97c0ae071904631a07b788e1 Mon Sep 17 00:00:00 2001 From: Jeremy Lecour Date: Thu, 10 Jun 2021 21:22:38 +0200 Subject: [PATCH] =?UTF-8?q?kvm-host:=20add-vm:=20shellcheck=20(quotes,=20b?= =?UTF-8?q?races=E2=80=A6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kvm-host/files/add-vm.sh | 217 +++++++++++++++++++++++---------------- 1 file changed, 130 insertions(+), 87 deletions(-) diff --git a/kvm-host/files/add-vm.sh b/kvm-host/files/add-vm.sh index b929fb96..51ad1850 100755 --- a/kvm-host/files/add-vm.sh +++ b/kvm-host/files/add-vm.sh @@ -10,9 +10,13 @@ # Bash strict mode set -euo pipefail +isDryRun() { + test "${doDryRun}" = "true" +} + dryRun() { - if ($doDryRun); then + if isDryRun; then echo -e "\e[34mDoing:" "$*" "\e[39m" else echo -e "\e[34mDoing:" "$*" "\e[39m" @@ -29,6 +33,7 @@ warn() { echo -ne "\e[33m${1}\e[39m\n" } +# shellcheck disable=SC1091 [ -f "/etc/evolinux/add-vm.cnf" ] && . /etc/evolinux/add-vm.cnf masterKVMIP="${masterKVMIP:-127.0.0.1}" slaveKVMIP="${slaveKVMIP:-}" @@ -39,89 +44,102 @@ doDryRun=${doDryRun:-false} isoImagePath="${isoImagePath:-}" debianVersion="${debianAuto:-stable}" preseedURL="${preseedURL:-}" +defaultVCPU="${defaultVCPU:-"2"}" +defaultRAM="${defaultRAM:-"4G"}" +defaultRootSize="${defaultRootSize:-"20G"}" +defaultHomeSize="${defaultHomeSize:-"40G"}" DIALOGOUT=$(mktemp --tmpdir=/tmp addvm.XXX) export DIALOGOUT # TODO: How to replace _ with a space?? -DIALOG="$(which dialog) --backtitle Add-VM_Press_F1_for_help" +DIALOG="$(command -v dialog) --backtitle Add-VM_Press_F1_for_help" export DIALOG DIALOGRC=.dialogrc export DIALOGRC HELPFILE=$(mktemp --tmpdir=/tmp addvm.XXX) export HELPFILE tmpResFile=$(mktemp --tmpdir=/tmp addvm.XXX) -xmlVM=$(mktemp --tmpdir=/tmp addvm.XXX) masterKVM="$(hostname -s)" -slaveKVM="$(ssh $slaveKVMIP hostname -s)" +slaveKVM="$(ssh "${slaveKVMIP}" hostname -s)" # Exit & Cleanup function. clean() { - echo -e "\nBye! Cleaning..." - [ -f $DIALOGOUT ] && rm $DIALOGOUT - [ -f $HELPFILE ] && rm $HELPFILE -# [ -f $tmpResFile ] && rm $tmpResFile -# [ -f $xmlVM ] && rm $xmlVM + rm -f "${DIALOGOUT}" + rm -f "${HELPFILE}" exit } trap clean EXIT SIGINT -$DIALOG --hfile $HELPFILE --title "KVM Config" --form "Set the right config. "\ -"If you do not want a type of disk, type none." 0 0 0 \ - "vCPU" 1 1 "2" 1 10 20 0 \ - "memory" 2 1 "4G" 2 10 20 0 \ - "volroot" 3 1 "${disks[0]}-20G" 3 10 20 0 \ - "volhome" 4 1 "${disks[1]}-40G" 4 10 20 0 \ - "vmName" 5 1 "" 5 10 20 0 \ - 2>$DIALOGOUT -vCPU=$(sed 1'q;d' $DIALOGOUT) -memory=$(sed 2'q;d' $DIALOGOUT|tr -d 'G') -memory=$(($memory * 1024)) -volroot=$(sed 3'q;d' $DIALOGOUT) -volhome=$(sed 4'q;d' $DIALOGOUT) -vmName=$(sed 5'q;d' $DIALOGOUT) +${DIALOG} \ + --hfile "${HELPFILE}" \ + --title "KVM Config" \ + --form "Set the right config. If you do not want a type of disk, type none." 0 0 0 \ + "vCPU" 1 1 "${defaultVCPU}" 1 10 20 0 \ + "memory" 2 1 "${defaultRAM}" 2 10 20 0 \ + "volRoot" 3 1 "${disks[0]}-${defaultRootSize}" 3 10 20 0 \ + "volHome" 4 1 "${disks[1]}-${defaultHomeSize}" 4 10 20 0 \ + "vmName" 5 1 "" 5 10 20 0 \ + 2> "${DIALOGOUT}" -[ -z "$vmName" ] && critical "You need a VM Name!!" +vCPU=$(sed 1'q;d' "${DIALOGOUT}") +memory=$(sed 2'q;d' "${DIALOGOUT}" | tr -d 'G') +memory=$((memory * 1024 )) +volRoot=$(sed 3'q;d' "${DIALOGOUT}") +volHome=$(sed 4'q;d' "${DIALOGOUT}") +vmName=$(sed 5'q;d' "${DIALOGOUT}") -$DIALOG --title "Continue?" --clear "$@" \ - --yesno "Will create a VM named $vmName on $masterKVM with $vCPU vCPU, "\ -"$memory memory, $volroot for / (and /usr, ...) and $volhome for /home." 10 80 -if [[ $? -ne 0 ]]; then +if [ -z "${vmName}" ]; then + critical "You need a VM Name!!" +fi + +${DIALOG} \ + --title "Continue?" \ + --clear "$@" \ + --yesno "Will create a VM named ${vmName} on ${masterKVM} with ${vCPU} vCPU, ${memory} memory, ${volRoot} for / (and /usr, ...) and ${volHome} for /home." 10 80 +dialog_rc=$? + +if [[ ${dialog_rc} -ne 0 ]]; then exit 1 fi -if ! [[ "$volroot" =~ ([^-]+)-([0-9]+G) ]]; then +if ! [[ "${volRoot}" =~ ([^-]+)-([0-9]+G) ]]; then critical "No volume for root device (/dev/vda)?!!" else - volrootDisk="${BASH_REMATCH[1]}" - volrootSize="${BASH_REMATCH[2]}" - [[ " ${disks[*]} " == *"$volrootDisk"* ]] || critical "Unknow disk $volrootDisk !" - dryRun lvcreate -L$volrootSize -n${vmName}_root $volrootDisk - dryRun ssh $slaveKVMIP lvcreate -L$volrootSize -n${vmName}_root $volrootDisk + volRootDisk="${BASH_REMATCH[1]}" + volRootSize="${BASH_REMATCH[2]}" + if [[ " ${disks[*]} " != *"${volRootDisk}"* ]]; then + critical "Unknow disk ${volRootDisk} !" + fi + dryRun lvcreate -L"${volRootSize}" -n"${vmName}_root" "${volRootDisk}" + dryRun ssh "${slaveKVMIP}" "lvcreate -L$volRootSize -n${vmName}_root ${volRootDisk}" fi -if ! [[ "$volhome" =~ ([^-]+)-([0-9]+G) ]]; then +if ! [[ "${volHome}" =~ ([^-]+)-([0-9]+G) ]]; then warn "No volume for home device (/dev/vdb)... Okay, not doing it!" - volhomeDisk="none" + volHomeDisk="none" else - volhomeDisk="${BASH_REMATCH[1]}" - volhomeSize="${BASH_REMATCH[2]}" - [[ " ${disks[*]} " == *"$volhomeDisk"* ]] || critical "Unknow disk $volhomeDisk !" - dryRun lvcreate -L$volhomeSize -n${vmName}_home $volhomeDisk - dryRun ssh $slaveKVMIP lvcreate -L$volhomeSize -n${vmName}_home $volhomeDisk + volHomeDisk="${BASH_REMATCH[1]}" + volHomeSize="${BASH_REMATCH[2]}" + if [[ " ${disks[*]} " != *"${volHomeDisk}"* ]]; then + critical "Unknow disk ${volHomeDisk} !" + fi + dryRun lvcreate -L"${volHomeSize}" -n"${vmName}_home" "${volHomeDisk}" + dryRun ssh "${slaveKVMIP}" "lvcreate -L$volHomeSize -n${vmName}_home ${volHomeDisk}" fi -if [[ -f "/etc/drbd.d/${vmName}.res" ]]; then +if [ -f "/etc/drbd.d/${vmName}.res" ]; then warn "The DRBD resource file ${vmName}.res is already present! Continue? [y/N]" - read - if ! [[ "$REPLY" =~ (Y|y) ]]; then + read -r + if ! [[ "${REPLY}" =~ (Y|y) ]]; then exit 1 fi fi # Generates drbd resource file. -if [ $(ls /etc/drbd.d/|wc -l) -gt 1 ]; then +# shellcheck disable=SC2012 +if [ "$(ls /etc/drbd.d/ | wc -l)" -gt 1 ]; then lastdrbdPort=$(grep -hEo ':[0-9]{4}' /etc/drbd.d/*.res | sort | uniq | tail -1 | sed 's/://') drbdPort=$((lastdrbdPort+1)) lastMinor=$(grep -hEo 'minor [0-9]{1,}' /etc/drbd.d/*.res | sed 's/minor //' | sort -n | tail -1) @@ -133,7 +151,7 @@ else minorvol1=1 fi -cat << EOT > $tmpResFile +cat << EOT > "${tmpResFile}" resource "${vmName}" { net { cram-hmac-alg "sha1"; @@ -154,24 +172,24 @@ resource "${vmName}" { } volume 0 { device minor ${minorvol0}; - disk /dev/${volrootDisk}/${vmName}_root; + disk /dev/${volRootDisk}/${vmName}_root; meta-disk internal; } EOT -if [[ "$volhomeDisk" != "none" ]]; then - cat << EOT >> $tmpResFile +if [[ "${volHomeDisk}" != "none" ]]; then + cat << EOT >> "${tmpResFile}" volume 1 { device minor ${minorvol1}; - disk /dev/${volhomeDisk}/${vmName}_home; + disk /dev/${volHomeDisk}/${vmName}_home; meta-disk internal; } EOT fi -cat << EOT >> $tmpResFile - on $masterKVM { +cat << EOT >> "${tmpResFile}" + on ${masterKVM} { address ${masterKVMIP}:${drbdPort}; } - on $slaveKVM { + on ${slaveKVM} { address ${slaveKVMIP}:${drbdPort}; } } @@ -179,50 +197,75 @@ EOT # Create/Activate the new drbd resources. drbdadm="$(command -v drbdadm)" -($doDryRun) && drbdadm="${drbdadm} --dry-run" +if isDryRun; then + drbdadm="${drbdadm} --dry-run" +fi -($doDryRun) && trap "rm /etc/drbd.d/${vmName}.res && ssh ${slaveKVMIP} rm /etc/drbd.d/${vmName}.res" 0 -install -m 600 $tmpResFile /etc/drbd.d/${vmName}.res -scp /etc/drbd.d/${vmName}.res ${slaveKVMIP}:/etc/drbd.d/ -${drbdadm} create-md "$vmName" -ssh $slaveKVMIP ${drbdadm} create-md "$vmName" -${drbdadm} adjust "$vmName" -ssh $slaveKVMIP ${drbdadm} adjust "$vmName" -${drbdadm} -- --overwrite-data-of-peer primary "$vmName" +if isDryRun; then + # shellcheck disable=SC2064 + trap "rm /etc/drbd.d/${vmName}.res && ssh ${slaveKVMIP} rm /etc/drbd.d/${vmName}.res" 0 +fi +install -m 600 "${tmpResFile}" "/etc/drbd.d/${vmName}.res" +scp "/etc/drbd.d/${vmName}.res" "${slaveKVMIP}:/etc/drbd.d/" +${drbdadm} create-md "${vmName}" +# shellcheck disable=SC2029 +ssh "${slaveKVMIP}" "${drbdadm} create-md ${vmName}" +${drbdadm} adjust "${vmName}" +# shellcheck disable=SC2029 +ssh "${slaveKVMIP}" "${drbdadm} adjust ${vmName}" +${drbdadm} -- --overwrite-data-of-peer primary "${vmName}" -if ! ($doDryRun); then - sleep 5 && drbd-overview | tail -4 +if ! isDryRun; then + sleep 5 + drbd-overview | tail -4 drbdDiskPath="/dev/drbd/by-res/${vmName}/0" - if ! [[ -b "$drbdDiskPath" ]]; then - warn "$drbdDiskPath not found! Continue? [y/N]" - read - if ! [[ "$REPLY" =~ (Y|y) ]]; then + if ! [ -b "${drbdDiskPath}" ]; then + warn "${drbdDiskPath} not found! Continue? [y/N]" + read -r + if ! [[ "${REPLY}" =~ (Y|y) ]]; then exit 1 fi fi fi -virtHome="" -[ "$volhomeDisk" != "none" ] && virtHome="--disk path=/dev/drbd/by-disk/${volhomeDisk}/${vmName}_home,bus=virtio,io=threads,cache=none,format=raw" -bootMode="--pxe" -[ -n "${preseedURL}" ] && bootMode="--location https://deb.debian.org/debian/dists/${debianVersion}/main/installer-amd64/ --extra-args \"auto=true priority=critical url=${preseedURL} hostname=${vmName}\"" -[ -f "$isoImagePath" ] && bootMode="--cdrom=$isoImagePath" +virtRootDisk="--disk path=/dev/drbd/by-disk/${volRootDisk}/${vmName}_root,bus=virtio,io=threads,cache=none,format=raw" +virtHomeDisk="" +if [ "${volHomeDisk}" != "none" ]; then + virtHomeDisk="--disk path=/dev/drbd/by-disk/${volHomeDisk}/${vmName}_home,bus=virtio,io=threads,cache=none,format=raw" +fi +if [ -n "${preseedURL}" ]; then + bootMode="--location https://deb.debian.org/debian/dists/${debianVersion}/main/installer-amd64/ --extra-args auto=true priority=critical url=${preseedURL} hostname=${vmName}" +fi +if [ -f "${isoImagePath}" ]; then + bootMode="--cdrom=${isoImagePath}" +fi +bootMode=${bootMode:-"--pxe"} -dryRun virt-install --connect=qemu:///system \ - --name=${vmName} \ - --cpu mode=host-passthrough --vcpus=${vCPU} \ - --memory=${memory} \ - --disk path=/dev/drbd/by-disk/${volrootDisk}/${vmName}_root,bus=virtio,io=threads,cache=none,format=raw \ - $virtHome \ - $bootMode \ - --network=bridge:${bridgeName},model=virtio \ - --noautoconsole --graphics vnc,listen=127.0.0.1,keymap=fr \ - --rng /dev/random \ - --os-variant=none +dryRun virt-install \ + --connect=qemu:///system \ + --name="${vmName}" \ + --cpu "mode=host-passthrough" \ + --vcpus="${vCPU}" \ + --memory="${memory}" \ + "${virtRootDisk}" \ + "${virtHomeDisk}" \ + "${bootMode}" \ + --network="bridge:${bridgeName},model=virtio" \ + --noautoconsole \ + --graphics "vnc,listen=127.0.0.1,keymap=fr" \ + --rng /dev/random \ + --os-variant=none +virst_install_rc=$? -if [ -x /usr/share/scripts/evomaintenance.sh ]; then - ($doDryRun) || echo "Install VM ${vmName} (add-vm.sh)" | /usr/share/scripts/evomaintenance.sh +if [ "${virt_install_rc}" = "0" ]; then + echo -e "\e[32mDone! Now you can install your VM with virt-manager.\e[39m" +else + echo -e "\e[31mError! VM couldn't be created.\e[39m" fi -echo -e "\e[32mDone! Now you can install your VM with virt-manager.\e[39m" +if ! isDryRun && [ -x /usr/share/scripts/evomaintenance.sh ]; then + echo "Install VM ${vmName} (add-vm.sh)" | /usr/share/scripts/evomaintenance.sh +fi + +