Skip to content

Instantly share code, notes, and snippets.

@stylefish
Last active February 7, 2024 16:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stylefish/d337d787e9a643d3a8cd6b520aae0259 to your computer and use it in GitHub Desktop.
Save stylefish/d337d787e9a643d3a8cd6b520aae0259 to your computer and use it in GitHub Desktop.
automatic memory for kvm balooning guests using virsh
#!/bin/bash
# can be intsalled as a systemd service via
# sudo systemctl edit --full --force virshautomem
#
# [Unit]
# Description=virsh auto memory allocation for ballooning vms
#
# [Service]
# ExecStart=/usr/local/bin/virshautomem.sh -d
# Restart=always
# RestartSec=15s
#
# [Install]
# WantedBy=default.target
# memory step size in MB to increase/decrease
STEP_MB=512
# minimum memory to assign
MIN_MEMORY=$((2 * 1024 * 1024))
# lower and upper threshold in percent of complete assigned memory
LOWTHRES=12
UPTHRES=17
# Retrieve the connection URI
# uri=$(virsh uri)
uri="qemu:///system"
daemon=0
if [[ "$1" == "-d" ]]; then
daemon=1;
echo "running as daemon"
fi
while
# Retrieve a list of running VMs
running_vms=$(virsh --connect "$uri" list --name --state-running)
# echo "checking running vms: $running_vms"
# Iterate over each VM
for vm_name in $running_vms; do
# Retrieve VM XML configuration
vm_xml=$(virsh --connect "$uri" dumpxml "$vm_name")
# echo "checking $vm_name"
# echo "$vm_xml"
# Check if the VM has ballooning support
if echo "$vm_xml" | grep -q '<memballoon'; then
echo -n "adjusting memory for VM: $vm_name: "
virsh --connect "$uri" dommemstat --domain "$vm_name" --period 5 > /dev/null
# Extract maximum memory from VM info using xmllint and XPath
max_memory_value=$(echo "$vm_xml" | xmllint --xpath 'string(/domain/memory)' -)
max_memory_unit=$(echo "$vm_xml" | xmllint --xpath 'string(/domain/memory/@unit)' -)
# Convert max_memory_value to kilobytes
case $max_memory_unit in
k | kb | KiB)
MAX_MEMORY=$max_memory_value
;;
m | mb | MiB)
MAX_MEMORY=$(($max_memory_value * 1024))
;;
g | gb | GiB)
MAX_MEMORY=$(($max_memory_value * 1024 * 1024))
;;
t | tb)
MAX_MEMORY=$(($max_memory_value * 1024 * 1024 * 1024))
;;
*)
echo "Unsupported memory unit: $max_memory_unit"
continue
;;
esac
# Retrieve memory statistics
mem_stat=$(virsh --connect "$uri" dommemstat "$vm_name")
current_memory=$(echo "$mem_stat" | awk '/actual/ { print $2 }')
available_memory=$(echo "$mem_stat" | awk '/usable/ { print $2 }')
if [ "$available_memory" = "" ]; then
echo "unable to detect available memory, ensure balloning driver installed and set up"
continue
fi
# Calculate memory thresholds
lower_threshold=$(($MAX_MEMORY * $LOWTHRES / 100))
upper_threshold=$(($MAX_MEMORY * $UPTHRES / 100))
# Adjust memory allocation
if ((available_memory < lower_threshold)); then
echo -n "increase "
new_memory=$(($current_memory + ($STEP_MB * 1024)))
elif ((available_memory > upper_threshold)); then
echo -n "decrease "
new_memory=$(($current_memory - ($STEP_MB * 1024)))
else
echo "keeping current $(($current_memory / 1024 ))M avail: $(($available_memory / 1024))M | lowt: $(($lower_threshold / 1024 ))M | upt: $(($upper_threshold / 1024 ))M"
continue
fi
# echo "NEW $new_memory"
# Ensure the new memory does not exceed the maximum
if (($new_memory > $MAX_MEMORY)); then
new_memory=$MAX_MEMORY
# echo "assigning MAX $new_memory"
fi
# Ensure the new memory does not fall below the minimum
if (($new_memory < $MIN_MEMORY)); then
new_memory=$MIN_MEMORY
# echo "assigning MIN $new_memory"
fi
#echo "c $current_memory, a: $available_memory, lt: $lower_threshold, ut: $upper_threshold, new: $new_memory"
echo "max: $(($MAX_MEMORY / 1024 ))M | cur: $(($current_memory / 1024 ))M | avail: $(($available_memory / 1024 ))M | lowt: $(($lower_threshold / 1024 ))M | upt: $(($upper_threshold / 1024 ))M => $(($new_memory / 1024 ))M"
# Apply the new memory allocation
virsh --connect "$uri" setmem "$vm_name" "$new_memory"
fi
done
# echo "waiting for next execution"
[[ "$daemon" == "1" ]] && sleep 7
do true; done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment