Scripts for managing KVM hypervisors used with DRBD and LVM.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

add-vm 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. #!/bin/bash
  2. # Add-VM script to add a VM on evoKVM.
  3. # _ ____ ____ __ ____ __
  4. # / \ | _ \| _ \ \ \ / / \/ |
  5. # / _ \ | | | | | | |____\ \ / /| |\/| |
  6. # / ___ \| |_| | |_| |_____\ V / | | | |
  7. # /_/ \_\____/|____/ \_/ |_| |_|
  8. #
  9. # Need packages: dialog
  10. # Bash strict mode
  11. set -euo pipefail
  12. dryRun() {
  13. if ($doDryRun); then
  14. echo -e "\e[34mDoing:" $* "\e[39m"
  15. else
  16. echo -e "\e[34mDoing:" $* "\e[39m"
  17. $*
  18. fi
  19. }
  20. critical() {
  21. echo -ne "\e[31m${1}\e[39m\n" && exit 1
  22. }
  23. warn() {
  24. echo -ne "\e[33m${1}\e[39m\n"
  25. }
  26. [ -f "/etc/evolinux/add-vm.cnf" ] && . /etc/evolinux/add-vm.cnf
  27. masterKVMIP="${masterKVMIP:-127.0.0.1}"
  28. slaveKVMIP="${slaveKVMIP:-}"
  29. disks="${disks:-}"
  30. [ -n "${disks}" ] || disks=("ssd" "hdd")
  31. bridgeName="${bridgeName:-br0}"
  32. doDryRun=${doDryRun:-false}
  33. isoImagePath="${isoImagePath:-}"
  34. debianVersion="${debianAuto:-stable}"
  35. preseedURL="${preseedURL:-}"
  36. export DIALOGOUT=$(mktemp --tmpdir=/tmp addvm.XXX)
  37. # TODO: How to replace _ with a space??
  38. export DIALOG="$(which dialog) --backtitle Add-VM_Press_F1_for_help"
  39. export DIALOGRC=.dialogrc
  40. export HELPFILE=$(mktemp --tmpdir=/tmp addvm.XXX)
  41. tmpResFile=$(mktemp --tmpdir=/tmp addvm.XXX)
  42. xmlVM=$(mktemp --tmpdir=/tmp addvm.XXX)
  43. masterKVM="$(hostname -s)"
  44. slaveKVM="$(ssh $slaveKVMIP hostname -s)"
  45. # Exit & Cleanup function.
  46. clean() {
  47. echo -e "\nBye! Cleaning..."
  48. [ -f $DIALOGOUT ] && rm $DIALOGOUT
  49. [ -f $HELPFILE ] && rm $HELPFILE
  50. # [ -f $tmpResFile ] && rm $tmpResFile
  51. # [ -f $xmlVM ] && rm $xmlVM
  52. exit
  53. }
  54. trap clean EXIT SIGINT
  55. $DIALOG --hfile $HELPFILE --title "KVM Config" --form "Set the right config. "\
  56. "If you do not want a type of disk, type none." 0 0 0 \
  57. "vCPU" 1 1 "2" 1 10 20 0 \
  58. "memory" 2 1 "4G" 2 10 20 0 \
  59. "volroot" 3 1 "${disks[0]}-20G" 3 10 20 0 \
  60. "volhome" 4 1 "${disks[1]}-40G" 4 10 20 0 \
  61. "vmName" 5 1 "" 5 10 20 0 \
  62. 2>$DIALOGOUT
  63. vCPU=$(sed 1'q;d' $DIALOGOUT)
  64. memory=$(sed 2'q;d' $DIALOGOUT|tr -d 'G')
  65. memory=$(($memory * 1024))
  66. volroot=$(sed 3'q;d' $DIALOGOUT)
  67. volhome=$(sed 4'q;d' $DIALOGOUT)
  68. vmName=$(sed 5'q;d' $DIALOGOUT)
  69. [ -z "$vmName" ] && critical "You need a VM Name!!"
  70. $DIALOG --title "Continue?" --clear "$@" \
  71. --yesno "Will create a VM named $vmName on $masterKVM with $vCPU vCPU, "\
  72. "$memory memory, $volroot for / (and /usr, ...) and $volhome for /home." 10 80
  73. if [[ $? -ne 0 ]]; then
  74. exit 1
  75. fi
  76. if ! [[ "$volroot" =~ ([^-]+)-([0-9]+G) ]]; then
  77. critical "No volume for root device (/dev/vda)?!!"
  78. else
  79. volrootDisk="${BASH_REMATCH[1]}"
  80. volrootSize="${BASH_REMATCH[2]}"
  81. [[ " ${disks[*]} " == *"$volrootDisk"* ]] || critical "Unknow disk $volrootDisk !"
  82. dryRun lvcreate -L$volrootSize -n${vmName}_root $volrootDisk
  83. dryRun ssh $slaveKVMIP lvcreate -L$volrootSize -n${vmName}_root $volrootDisk
  84. fi
  85. if ! [[ "$volhome" =~ ([^-]+)-([0-9]+G) ]]; then
  86. warn "No volume for home device (/dev/vdb)... Okay, not doing it!"
  87. volhomeDisk="none"
  88. else
  89. volhomeDisk="${BASH_REMATCH[1]}"
  90. volhomeSize="${BASH_REMATCH[2]}"
  91. [[ " ${disks[*]} " == *"$volhomeDisk"* ]] || critical "Unknow disk $volhomeDisk !"
  92. dryRun lvcreate -L$volhomeSize -n${vmName}_home $volhomeDisk
  93. dryRun ssh $slaveKVMIP lvcreate -L$volhomeSize -n${vmName}_home $volhomeDisk
  94. fi
  95. if [[ -f "/etc/drbd.d/${vmName}.res" ]]; then
  96. warn "The DRBD resource file ${vmName}.res is already present! Continue? [y/N]"
  97. read
  98. if ! [[ "$REPLY" =~ (Y|y) ]]; then
  99. exit 1
  100. fi
  101. fi
  102. # Generates drbd resource file.
  103. if [ $(ls /etc/drbd.d/|wc -l) -gt 1 ]; then
  104. lastdrbdPort=$(grep -hEo ':[0-9]{4}' /etc/drbd.d/*.res | sort | uniq | tail -1 | sed 's/://')
  105. drbdPort=$((lastdrbdPort+1))
  106. lastMinor=$(grep -hEo 'minor [0-9]{1,}' /etc/drbd.d/*.res | sed 's/minor //' | sort -n | tail -1)
  107. minorvol0=$((lastMinor+1))
  108. minorvol1=$((lastMinor+2))
  109. else
  110. drbdPort=7900
  111. minorvol0=0
  112. minorvol1=1
  113. fi
  114. cat << EOT > $tmpResFile
  115. resource "${vmName}" {
  116. net {
  117. cram-hmac-alg "sha1";
  118. shared-secret "$(apg -n 1 -m 16 -M lcN)";
  119. # Si pas de lien dedié 10G, passer en protocol A
  120. # Et desactiver allow-two-primaries;
  121. protocol C;
  122. allow-two-primaries;
  123. # Tuning perf.
  124. max-buffers 8000;
  125. max-epoch-size 8000;
  126. sndbuf-size 0;
  127. }
  128. # A utiliser si RAID HW avec cache + batterie
  129. disk {
  130. disk-barrier no;
  131. disk-flushes no;
  132. }
  133. volume 0 {
  134. device minor ${minorvol0};
  135. disk /dev/${volrootDisk}/${vmName}_root;
  136. meta-disk internal;
  137. }
  138. EOT
  139. if [[ "$volhomeDisk" != "none" ]]; then
  140. cat << EOT >> $tmpResFile
  141. volume 1 {
  142. device minor ${minorvol1};
  143. disk /dev/${volhomeDisk}/${vmName}_home;
  144. meta-disk internal;
  145. }
  146. EOT
  147. fi
  148. cat << EOT >> $tmpResFile
  149. on $masterKVM {
  150. address ${masterKVMIP}:${drbdPort};
  151. }
  152. on $slaveKVM {
  153. address ${slaveKVMIP}:${drbdPort};
  154. }
  155. }
  156. EOT
  157. # Create/Activate the new drbd resources.
  158. drbdadm="$(command -v drbdadm)"
  159. ($doDryRun) && drbdadm="${drbdadm} --dry-run"
  160. ($doDryRun) && trap "rm /etc/drbd.d/${vmName}.res && ssh ${slaveKVMIP} rm /etc/drbd.d/${vmName}.res" 0
  161. install -m 600 $tmpResFile /etc/drbd.d/${vmName}.res
  162. scp /etc/drbd.d/${vmName}.res ${slaveKVMIP}:/etc/drbd.d/
  163. ${drbdadm} create-md "$vmName"
  164. ssh $slaveKVMIP ${drbdadm} create-md "$vmName"
  165. ${drbdadm} adjust "$vmName"
  166. ssh $slaveKVMIP ${drbdadm} adjust "$vmName"
  167. ${drbdadm} -- --overwrite-data-of-peer primary "$vmName"
  168. if !($doDryRun); then
  169. sleep 5 && drbd-overview | tail -4
  170. drbdDiskPath="/dev/drbd/by-res/${vmName}/0"
  171. if ! [[ -b "$drbdDiskPath" ]]; then
  172. warn "$drbdDiskPath not found! Continue? [y/N]"
  173. read
  174. if ! [[ "$REPLY" =~ (Y|y) ]]; then
  175. exit 1
  176. fi
  177. fi
  178. fi
  179. virtHome=""
  180. [ "$volhomeDisk" != "none" ] && virtHome="--disk path=/dev/drbd/by-disk/${volhomeDisk}/${vmName}_home,bus=virtio,io=threads,cache=none,format=raw"
  181. bootMode="--pxe"
  182. [ -n "${preseedURL}" ] && bootMode="--location https://deb.debian.org/debian/dists/${debianVersion}/main/installer-amd64/ --extra-args \"auto=true priority=critical url=${preseedURL} hostname=${vmName}\""
  183. [ -f "$isoImagePath" ] && bootMode="--cdrom=$isoImagePath"
  184. dryRun virt-install --connect=qemu:///system \
  185. --name=${vmName} \
  186. --cpu mode=host-passthrough --vcpus=${vCPU} \
  187. --memory=${memory} \
  188. --disk path=/dev/drbd/by-disk/${volrootDisk}/${vmName}_root,bus=virtio,io=threads,cache=none,format=raw \
  189. $virtHome \
  190. $bootMode \
  191. --network=bridge:${bridgeName},model=virtio \
  192. --noautoconsole --graphics vnc,listen=127.0.0.1,keymap=fr \
  193. --rng /dev/random \
  194. --os-variant=none
  195. if [ -x /usr/share/scripts/evomaintenance.sh ]; then
  196. ($doDryRun) || echo "Install VM ${vmName} (add-vm.sh)" | /usr/share/scripts/evomaintenance.sh
  197. fi
  198. echo -e "\e[32mDone! Now you can install your VM with virt-manager.\e[39m"