通过网络唤醒来使用 kvm 和 libvirt 触发虚拟机

通过网络唤醒来使用 kvm 和 libvirt 触发虚拟机

我正在使用 KVM 进行虚拟化并通过 Libvirt 守护程序对其进行管理。

如何配置 Libvirt 或 KVM 来监听发送到虚拟机 NIC 的 MAC 地址的网络唤醒数据包,并在收到此类数据包时启动虚拟机?

答案1

我发现 Libvirt-wakeonlan 似乎可以做到这一点。我不知道它有多成熟,效果如何。这种方法似乎是正确的。https://github.com/simoncadman/libvirt-wakeonlan

答案2

您可以使用我的脚本,它本质上与 libvirt-wakeonlan 相同,我这样做是因为我无法让 libvirt-wakeonlan 工作......这只是一个简单的脚本,您可以将它放入启动脚本并让它在启动时运行。

它监听 udp 端口​​ 9(据我所知有时也会使用端口 7,但我使用的远程 vnc/rdp guacamole 会在端口 9 发送信息),并在看到魔术包时检查 MAC 地址。如果 virsh 中有一个具有此 MAC 地址的虚拟机,它将唤醒该机器。

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

答案3

由于我目前无法对 Gotschi 的回答发表评论https://serverfault.com/a/1079289/962574(目前还没有声誉),我将在这里添加我的调整:

我自己修改了脚本。不确定不同的 netcat 版本是否适用,但在 Fedora 上需要进行一些调整。

#!/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

答案4

非常好的脚本。如果 libvirt 机器有多个网卡,我会用循环来增强它

#!/bin/bash

virshCmd="ssh [email protected] 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

相关内容