5

I'm doing virtualization with KVM and managing it via the Libvirt daemon.

How do I configure Libvirt or KVM to listen for Wake-On-Lan packets sent the the Virtual Machine's NIC's MAC address and to start the Virtual Machine when such a packet is received?

Azendale
  • 1,585

4 Answers4

4

I've found Libvirt-wakeonlan which seems to do it. I have no idea how mature it is and how well it works. The approach seems right. https://github.com/simoncadman/libvirt-wakeonlan

3

you can use my script which essentialy does the same as libvirt-wakeonlan, I made it because I could not get libvirt-wakeonlan to work... this is just a simple script which you can put in a startup script and have it running on boot.

It listens to udp port 9 (port 7 is also used sometimes afaik but guacamole - the remote vnc/rdp I use - sends at port 9) and checks the MAC adress when it sees a magic packet. If there is a vm in virsh with this MAC adress it will wake the machine up.

https://gitlab.com/-/snippets/2183494

#!/bin/bash

nc -dknl -p 9 -u | # listen to udp port 9 for packets, check if it is a magic packet stdbuf -o0 xxd -c 6 -p | stdbuf -o0 uniq | stdbuf -o0 grep -v 'ffffffffffff' | while read ; do mac="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}" # parse mac found in magic packet for i in $(virsh list --all --name); do # loop through libvirt machines vmmac=$(virsh dumpxml $i | grep "mac address" | awk -F' '{ print $2}') # get each machines MAC if [ $vmmac = $mac ]; then # compare MACs, if match do; echo $mac; echo $i; virsh start $i virsh resume $i fi done done

Gotschi
  • 131
1

As I can't comment yet on Gotschi's answer https://serverfault.com/a/1079289/962574 (no reputation so far), I will add my adjustment here:

I modified the script for myself. Not sure about different netcat versions, but on Fedora some adjustments were necessary.

#!/bin/bash

listen to udp port 9 for packets, check if it is a magic packet

netcat -dkn -l 9 -u | stdbuf -o0 xxd -c 6 -p | stdbuf -o0 uniq | stdbuf -o0 grep -v 'ffffffffffff' | while read do echo "Got triggered with $REPLY" mac="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"

# loop through libvirt machines
for vm in $(virsh list --all --name)
do
    # Get the MAC address and compare with the magic packet
    vmmac=$(virsh dumpxml $vm | grep "mac address" | awk -F\' '{ print $2}')
    if [ $vmmac = $mac ]
    then
        state=$(virsh list --all|awk -v vm=$vm '{ if ($2 == vm ) print $3 }')
        echo "Found $vm with $mac in $state state"

        # Dependent on the state, resume or start
        [ $state == "paused" ] && virsh -q resume $vm && virsh domtime --domain $vm --now
        [ $state == "shut" ] && virsh -q start $vm
    fi
done

done

mbo77
  • 11
  • 3
0

Very good script. I enhanced it with a loop if a libvirt machine have more than one network card

#!/bin/bash

virshCmd="ssh root@192.168.xxx.xxx virsh"

listen to udp port 9 for packets, check if it is a magic packet

netcat -dkn -l 9 -u | stdbuf -o0 xxd -c 6 -p | stdbuf -o0 uniq | stdbuf -o0 grep -v 'ffffffffffff' | while read; do

echo "Got triggered with $REPLY"

mac="${REPLY:0:2}:${REPLY:2:2}:${REPLY:4:2}:${REPLY:6:2}:${REPLY:8:2}:${REPLY:10:2}"

echo "Got wol-package. Requested mac-addr: ${mac}"

# loop through libvirt machines
for vm in $( ${virshCmd} list --all --name); do
    # Get the MAC address and compare with the magic packet
    vmmacs=$( ${virshCmd} dumpxml $vm | grep "mac address" | awk -F\' '{ print $2}')
    echo "VM: ${vm}"
    for vmmac in ${vmmacs//\\n/

}; do echo " MAC-Addr: $vmmac" if [ $vmmac = $mac ]; then state=$( ${virshCmd} list --all|awk -v vm=$vm '{ if ($2 == vm ) print $3 }') echo "Found $vm with $mac in $state state"

                    # Dependent on the state, resume or start
                    [ $state == "paused" ]   && ${virshCmd} -q resume $vm && ${virshCmd} domtime --domain $vm --now
                    [ $state == "pausiert" ] && ${virshCmd} -q resume $vm && ${virshCmd} domtime --domain $vm --now
                    [ $state == "shut" ]        && ${virshCmd} -q start $vm
                    [ $state == "ausschalten" ] && ${virshCmd} -q start $vm
            fi
    done
done
echo ""

done

Birger
  • 1
  • 1