如何在關閉主機時優雅地關閉我的 kvm 虛擬機器?

如何在關閉主機時優雅地關閉我的 kvm 虛擬機器?

直接提出這個問題從這裡

我正在運行 archlinux,並且我有一個經常與系統一起運行的虛擬機器。實際上大多數時候。

我的目標是產生以下行為:

  • 關閉/斷電/重新啟動/停止訊號傳送到系統
  • 除了嘗試正常關閉虛擬機器之外沒有任何其他操作
  • 如果虛擬機器在 X 秒後正常關閉,也繼續關閉主機系統。
  • 如果沒有,則執行不同的命令

請給我一個關於該做什麼的好主意,因為我甚至不知道從哪裡開始。我猜想有一個對內核的呼叫可以看一下。

讓我知道。


我目前的程式碼

目前我正在使用這些腳本來正常關閉我的 kvm 虛擬機,而且它有效!但只要我的用戶啟動關閉或一個重啟使用他的外殼。任何其他情況都行不通。

這些別名:

alias sudocheck="/bin/bash /home/damiano/.script/sudocheck"
alias sudo="sudocheck "

正在觸發此功能:

#!/bin/bash

# This script checks for what is being passed to sudo.
# If the command passed is poweroff or reboot, it
# launches a custom script instead, that also looks
# fur currently running virtual machines and shuts them.

sudocheck() {
    if [ $1 == "poweroff" ] || [ $1 == "reboot" ]; then
        eval "sudo /home/damiano/.script/graceful $@"
    else
        eval "sudo $@"
    fi
}
sudocheck $@

如果需要的話會啟動這個腳本:

#!/bin/bash
i=0
e=0
## if virsh finds VMs running
virsh -c qemu:///system list | awk '{ print $3}' | \
if grep running > /dev/null ; then
    virsh -c qemu:///system list --all | grep running | awk '{print "-c qemu:///system shutdown "$2}' | \
## shuts them dow gracefully
    xargs -L1 virsh
## wait 30 seconds for them to go down
    until (( i >= 30 || e == 1 )) ; do
## check every second for their status
        virsh -c qemu:///system list --all | awk '{ print $3}' | \
        if grep -E '(running|shutdown)' > /dev/null ; then
## keep waiting if still running
            if (( i <= 30 )) ; then
                sleep 1 && let i++ && echo $i
            else
                e=1 && notify-send 'Shutdown has been canceled' 'Please check the status of your virtual machines: seems like even though a stop signal has been sent, some are still running.' --urgency=critical
            fi
        else
## if no machine is running anymore, original power command can be executed
            e=1 && eval $@
        fi
    done
fi

系統單元

我還制定了以下草案來管理虛擬機器的執行:

[電子郵件受保護]

[Unit]
Description=This service manages the execution of the %i virtual machine
Documentation=https://libvirt.org/manpages/virsh.html

[Service]
ExecStartPre=virsh -c qemu:///system
ExecStart=virsh start %i
ExecStop=virsh -c qemu:///system
ExecStop=virsh shutdown %i 
TimeoutStopSec=30
KillMode=none

[Install]
WantedBy=multi-user.target

但我怎麼告訴系統不要關閉桌面環境,保持原樣直到VM已成功關閉?因為如果系統無法關閉虛擬機,我想在我的桌面環境中關閉虛擬機。我不希望電腦開始停止所有服務並保持掛起狀態,直到強制關閉為止。

答案1

控制虛擬機器的奇怪方式。好方法-使用systemd自動啟動和停止VM。例如:

/etc/systemd/系統/[電子郵件受保護]

[Unit]
Description=QEMU virtual machine

[Service]
Environment="type=system-x86_64" "haltcmd=kill -INT $MAINPID"
EnvironmentFile=/etc/conf.d/qemu.d/%i
ExecStart=/usr/bin/qemu-${type} -name %i -nographic $args
ExecStop=/bin/sh -c ${haltcmd}
TimeoutStopSec=30
KillMode=none

[Install]
WantedBy=multi-user.target

……當然還有運作虛擬機器的配置:

/etc/conf.d/qemu.d/one

type="system-x86_64"

args="-enable-kvm -m 512 -hda /dev/vg0/vm1 -net nic,macaddr=DE:AD:BE:EF:E0:00 \
 -net tap,ifname=tap0 -serial telnet:localhost:7000,server,nowait,nodelay \
 -monitor telnet:localhost:7100,server,nowait,nodelay -vnc :0"

haltcmd="echo 'system_powerdown' | nc localhost 7100" # or netcat/ncat

# You can use other ways to shut down your VM correctly
#haltcmd="ssh powermanager@vm1 sudo poweroff"

...以及另一個虛擬機器配置:

/etc/conf.d/qemu.d/two

args="-enable-kvm -m 512 -hda /srv/kvm/vm2.img -net nic,macaddr=DE:AD:BE:EF:E0:01 \
 -net tap,ifname=tap1 -serial telnet:localhost:7001,server,nowait,nodelay \
 -monitor telnet:localhost:7101,server,nowait,nodelay -vnc :1"

haltcmd="echo 'system_powerdown' | nc localhost 7101"

等等。感謝 ArchWiki 貢獻者對於這篇文章

答案2

當您需要單獨控制每個虛擬機器時,原始貼文的草稿和@Oxyd 的答案非常有用。

但是,如果需要關閉/啟動所有虛擬機可以使用 libvirt 來賓,如上提到的Libvirt 文檔

  • 編輯文件/etc/conf.d/libvirt-guests,或/etc/sysconfig/libvirt-guests對於 CentOS,然後ON_SHUTDOWN=shutdown設定SHUTDOWN_TIMEOUT=0
  • 我認為還需要啟動該libvirt-guests服務,例如systemctl enable libvirt-guestssystemctl start libvirt-guests

相關內容