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?

4 Answers 4

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

2
  • 1
    From the author when asked about maturity: It's not particularly mature, it lacks things like logging, and has only really been properly tested under Gentoo Linux. I've been using it for a development environment for about 9 months and it's been completely stable so far, but as far as I know nobody has used in a production environment.
    – user130356
    Feb 2, 2013 at 22:41
  • 1
    I made this: gitlab.com/-/snippets/2183494
    – Gotschi
    Oct 1, 2021 at 13:05
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
1
  • Could use some comments, like which packets it acts on (udp/9) and which mac address it will wake up (not just those sent repeatedly, right?)
    – anx
    Oct 1, 2021 at 13:20
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
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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.