kvm-host: replace the "kvm-tools" package with scripts deployed by Ansible
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
e75eeb8c3f
commit
3d715bae35
@ -1,3 +1,4 @@
|
||||
---
|
||||
kvm_custom_libvirt_images_path: ''
|
||||
kvm_install_drbd: True
|
||||
kvm_scripts_dir: /usr/local/sbin
|
@ -0,0 +1,221 @@
|
||||
#!/bin/bash
|
||||
# Add-VM script to add a VM on evoKVM.
|
||||
# _ ____ ____ __ ____ __
|
||||
# / \ | _ \| _ \ \ \ / / \/ |
|
||||
# / _ \ | | | | | | |____\ \ / /| |\/| |
|
||||
# / ___ \| |_| | |_| |_____\ V / | | | |
|
||||
# /_/ \_\____/|____/ \_/ |_| |_|
|
||||
#
|
||||
# Need packages: dialog
|
||||
# Bash strict mode
|
||||
set -euo pipefail
|
||||
|
||||
dryRun() {
|
||||
|
||||
if ($doDryRun); then
|
||||
echo -e "\e[34mDoing:" $* "\e[39m"
|
||||
else
|
||||
echo -e "\e[34mDoing:" $* "\e[39m"
|
||||
$*
|
||||
fi
|
||||
}
|
||||
|
||||
critical() {
|
||||
echo -ne "\e[31m${1}\e[39m\n" && exit 1
|
||||
}
|
||||
|
||||
warn() {
|
||||
|
||||
echo -ne "\e[33m${1}\e[39m\n"
|
||||
}
|
||||
|
||||
[ -f "/etc/evolinux/add-vm.cnf" ] && . /etc/evolinux/add-vm.cnf
|
||||
masterKVMIP="${masterKVMIP:-127.0.0.1}"
|
||||
slaveKVMIP="${slaveKVMIP:-}"
|
||||
disks="${disks:-}"
|
||||
[ -n "${disks}" ] || disks=("ssd" "hdd")
|
||||
bridgeName="${bridgeName:-br0}"
|
||||
doDryRun=${doDryRun:-false}
|
||||
isoImagePath="${isoImagePath:-}"
|
||||
|
||||
export DIALOGOUT=$(mktemp --tmpdir=/tmp addvm.XXX)
|
||||
# TODO: How to replace _ with a space??
|
||||
export DIALOG="$(which dialog) --backtitle Add-VM_Press_F1_for_help"
|
||||
export DIALOGRC=.dialogrc
|
||||
export HELPFILE=$(mktemp --tmpdir=/tmp addvm.XXX)
|
||||
tmpResFile=$(mktemp --tmpdir=/tmp addvm.XXX)
|
||||
xmlVM=$(mktemp --tmpdir=/tmp addvm.XXX)
|
||||
masterKVM="$(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
|
||||
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)
|
||||
|
||||
[ -z "$vmName" ] && critical "You need a VM Name!!"
|
||||
|
||||
$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
|
||||
exit 1
|
||||
fi
|
||||
|
||||
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
|
||||
fi
|
||||
|
||||
if ! [[ "$volhome" =~ ([^-]+)-([0-9]+G) ]]; then
|
||||
warn "No volume for home device (/dev/vdb)... Okay, not doing it!"
|
||||
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
|
||||
fi
|
||||
|
||||
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
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Generates drbd resource file.
|
||||
|
||||
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)
|
||||
minorvol0=$((lastMinor+1))
|
||||
minorvol1=$((lastMinor+2))
|
||||
else
|
||||
drbdPort=7900
|
||||
minorvol0=0
|
||||
minorvol1=1
|
||||
fi
|
||||
|
||||
cat << EOT > $tmpResFile
|
||||
resource "${vmName}" {
|
||||
net {
|
||||
cram-hmac-alg "sha1";
|
||||
shared-secret "$(apg -n 1 -m 16 -M lcN)";
|
||||
# Si pas de lien dedié 10G, passer en protocol A
|
||||
# Et desactiver allow-two-primaries;
|
||||
protocol C;
|
||||
allow-two-primaries;
|
||||
# Tuning perf.
|
||||
max-buffers 8000;
|
||||
max-epoch-size 8000;
|
||||
sndbuf-size 0;
|
||||
}
|
||||
# A utiliser si RAID HW avec cache + batterie
|
||||
disk {
|
||||
disk-barrier no;
|
||||
disk-flushes no;
|
||||
}
|
||||
volume 0 {
|
||||
device minor ${minorvol0};
|
||||
disk /dev/${volrootDisk}/${vmName}_root;
|
||||
meta-disk internal;
|
||||
}
|
||||
EOT
|
||||
if [[ "$volhomeDisk" != "none" ]]; then
|
||||
cat << EOT >> $tmpResFile
|
||||
volume 1 {
|
||||
device minor ${minorvol1};
|
||||
disk /dev/${volhomeDisk}/${vmName}_home;
|
||||
meta-disk internal;
|
||||
}
|
||||
EOT
|
||||
fi
|
||||
cat << EOT >> $tmpResFile
|
||||
on $masterKVM {
|
||||
address ${masterKVMIP}:${drbdPort};
|
||||
}
|
||||
on $slaveKVM {
|
||||
address ${slaveKVMIP}:${drbdPort};
|
||||
}
|
||||
}
|
||||
EOT
|
||||
|
||||
# Create/Activate the new drbd resources.
|
||||
drbdadm="$(command -v drbdadm)"
|
||||
($doDryRun) && drbdadm="${drbdadm} --dry-run"
|
||||
|
||||
($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 !($doDryRun); 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
|
||||
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"
|
||||
[ -f "$isoImagePath" ] && bootMode="--cdrom=$isoImagePath"
|
||||
|
||||
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
|
||||
|
||||
if [ -x /usr/share/scripts/evomaintenance.sh ]; then
|
||||
($doDryRun) || echo "Install VM ${vmName} (add-vm.sh)" | /usr/share/scripts/evomaintenance.sh
|
||||
fi
|
||||
|
||||
echo -e "\e[32mDone! Now you can install your VM with virt-manager.\e[39m"
|
@ -0,0 +1,94 @@
|
||||
#!/bin/sh
|
||||
|
||||
# NOTE: kvmstats relies on the hxselect(1) command to parse virsh' xml
|
||||
# files. On Debian, this command is provided by the 'html-xml-utils'
|
||||
# package.
|
||||
|
||||
set -e -u
|
||||
|
||||
usage () {
|
||||
echo 'usage: kvmstats.sh [-a] [-u K|M|G]'
|
||||
exit 1
|
||||
}
|
||||
|
||||
for DEP in hxselect lvs tempfile bc
|
||||
do
|
||||
if [ -z "$(which $DEP)" ]
|
||||
then
|
||||
echo "kvmstats.sh: $DEP not found in \$PATH" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
POW=$(echo 1024 ^ 3 | bc)
|
||||
while [ $# -ne 0 ] && echo "$1" | grep -q '^-[[:alnum:]]'
|
||||
do
|
||||
case $1 in
|
||||
'-u')
|
||||
case $2 in
|
||||
'K')
|
||||
POW=$(echo 1024 ^ 1 | bc)
|
||||
;;
|
||||
'M')
|
||||
POW=$(echo 1024 ^ 2 | bc)
|
||||
;;
|
||||
'G')
|
||||
POW=$(echo 1024 ^ 3 | bc)
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
esac
|
||||
;;
|
||||
'-a')
|
||||
SHOW_AVAIL=y
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# since libvirt seems to store memoy in KiB, POW must be lowered by 1
|
||||
POW=$((POW / 1024))
|
||||
|
||||
TMPFILE=$(tempfile -s kvmstats)
|
||||
LVSOUT=$(tempfile -s kvmstats)
|
||||
|
||||
lvs --units b --nosuffix >"$LVSOUT"
|
||||
|
||||
for VM in $(virsh list --all --name)
|
||||
do
|
||||
VCPU=$(hxselect -c 'domain vcpu' </etc/libvirt/qemu/"$VM.xml")
|
||||
RAM_KIB=$(hxselect -c 'domain memory' </etc/libvirt/qemu/"$VM.xml")
|
||||
RAM=$((RAM_KIB / POW))
|
||||
for DEV in $(hxselect -s'\n' 'domain devices disk[device=disk] source' </etc/libvirt/qemu/"$VM.xml" | cut -d\" -f2)
|
||||
do
|
||||
case $DEV in
|
||||
/dev/drbd/*)
|
||||
DISK=$(awk "/$VM/ { ans += \$NF } END { print ans / 1024 ^ 3 }" <"$LVSOUT")
|
||||
break # avoid to compute DISK for each disk
|
||||
;;
|
||||
*.qcow2)
|
||||
DISK=$(du -sBG "$DEV" | awk '{ print substr($1, 0, length($1) - 1) }')
|
||||
;;
|
||||
*)
|
||||
DISK=0
|
||||
esac
|
||||
done
|
||||
RUNNING=$(virsh domstate "$VM" | grep -q '^running$' && echo yes || echo no)
|
||||
echo "$VM" "$VCPU" "$RAM" "$DISK" "$RUNNING"
|
||||
done >"$TMPFILE"
|
||||
|
||||
(
|
||||
echo vm vcpu ram disk running
|
||||
cat "$TMPFILE"
|
||||
awk '/yes$/ { vcpu += $2; ram += $3; disk += $4; running++ } END { print "TOTAL(running)", vcpu, ram, disk, running }' <"$TMPFILE"
|
||||
if [ $SHOW_AVAIL ]
|
||||
then
|
||||
AV_CPU=$(awk '/^processor/ { cpu++ } END { print cpu }' /proc/cpuinfo)
|
||||
AV_MEM=$(awk '/^MemTotal:/ { print int($2 / 1024 ^ 2) }' /proc/meminfo)
|
||||
echo AVAILABLE "$AV_CPU" "$AV_MEM"
|
||||
fi
|
||||
) | column -t
|
||||
|
||||
rm "$TMPFILE" "$LVSOUT"
|
@ -1,13 +1,52 @@
|
||||
---
|
||||
|
||||
- name: remove old package
|
||||
apt:
|
||||
name: kvm-tools
|
||||
purge: yes
|
||||
state: absent
|
||||
|
||||
- include_role:
|
||||
name: remount-usr
|
||||
when: kvm_scripts_dir is search ("/usr")
|
||||
|
||||
- name: add-vm script is present
|
||||
copy:
|
||||
src: add-vm.sh
|
||||
dest: "{{ kvm_scripts_dir }}/add-vm"
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
force: yes
|
||||
|
||||
- name: migrate-vm scripts is present
|
||||
- name: migrate-vm script is present
|
||||
copy:
|
||||
src: migrate-vm.sh
|
||||
dest: /usr/share/scripts/migrate-vm
|
||||
mode: "0755"
|
||||
dest: "{{ kvm_scripts_dir }}/migrate-vm"
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
force: yes
|
||||
|
||||
- name: kvmstats script is present
|
||||
copy:
|
||||
src: kvmstats.sh
|
||||
dest: "{{ kvm_scripts_dir }}/kvmstats"
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
force: yes
|
||||
force: yes
|
||||
|
||||
# backward compatibility
|
||||
|
||||
- name: remove old migrate-vm script
|
||||
file:
|
||||
path: /usr/share/scripts/migrate-vm
|
||||
state: absent
|
||||
when: "'/usr/share/scripts' not in kvm_scripts_dir"
|
||||
|
||||
- name: remove old kvmstats script
|
||||
file:
|
||||
path: /usr/share/scripts/kvmstats
|
||||
state: absent
|
||||
when: "'/usr/share/scripts' not in kvm_scripts_dir"
|
Loading…
Reference in new issue