Kvm-Virtualization

熱交換物理磁碟通過 qemu VM

  • June 4, 2020

我有一個在 proxmox 上的 qemu 中執行的虛擬伺服器。它有兩個物理磁碟使用 virtio: 101.cfg 中的指令連接到主機,如下所示

virtio2: /dev/disk/by-id/ata-vol1,backup=0 
virtio3: /dev/disk/by-id/ata-vol2,backup=0

這些包含一個鏡像 ZFS 卷,我的文件使用 nextcloud 提供。這一切都很好,因為這些磁碟永遠不會從來賓中刪除。

我還輪換了我備份到的其他三個物理磁碟(物理控制器是 JBOD 配置中的 LSI RAID 控制器,物理硬體是 HP Proiliant DL380e Gen8)。我通過 zfs 將更新的快照從儲存陣列發送到系統上存在的任何備份磁碟來做到這一點。我已將這些添加到 VM 中,如下所示:

virtio4: /dev/disk/by-id/ata-backup1-volname,backup=0
virtio5: /dev/disk/by-id/ata-backup2-volname,backup=0
virtio6: /dev/disk/by-id/ata-backup3-volname,backup=0

這種方法可行,但問題是這些磁碟都不是可熱插拔的,因此如果我輪流移除和插入磁碟,來賓將無法看到它們。我在我的 qemu 配置中啟用了磁碟熱插拔。

我的問題是在插入和刪除這些磁碟時動態地將這些磁碟附加和分離到我的 VM 的正確方法是什麼?

我已經能夠使用“qm monitor”通過附加和分離 virtio-scsi“pci 卡”來附加和分離我取出的磁碟,如下所示:

附上

qm> drive_add 0 file=/dev/disk/by-id/ata-<disk-id>,if=none,id=backup_vol,cache=none,detect-zeroes=on
qm> device_add virtio-blk-pci,drive=backup_vol,id=backup_scsi_controller

分離

qm> device_del backup_scsi_controller

(來源:https ://blog.chrishowie.com/2019/09/19/hot-swapping-virtio-disks-on-qemu/通過Google記憶體)

我在想我可以將這些添加到我的備份腳本中,但是似乎不可能從 shell 腳本執行 qm 監視器命令,並且 qm 監視器不會從標準輸入獲取參數或輸入。通過閱讀,可以在客戶機上創建一個到 qemu-agent 的套接字並使用 JSON 注入它,但我對 JSON 一無所知,我真的希望有一種更簡單的方法。

我已經在這個房子周圍轉了一圈,確實已經到了能夠通過 UNIX 套接字向來賓發送 QMP 命令的地步。預設 Proxmox 配置使用 /var/run/qemu-server/<server-id>.qmp 處的套接字支持這一點。然後我可以使用互動方式發送 QMP JSON 消息

rlwrap -C qmp socat - UNIX:/var/run/qemu-server/101.qmp

(預設不安裝rlwrap,但可以使用“apt install rlwrap”安裝)

然而,QMP 消息格式與我想像的一樣不透明,並且出於意識形態純潔性的原因,它沒有直接等同於“drive_add”(這可能是可以理解的,但在我目前的困難的情況下卻非常無益)。假設我可以計算出正確的語法,那麼有一個“blockdev_add”命令可能已經完成了我想要的操作。

因此,我後退了一步,得出的結論是,“qm 監視器”可能由於 readline 支持而沒有接受來自 stdin 的輸入。這讓我想到了“期待”。稍後快速“apt install expect”,我能夠創建腳本來連接和分離驅動器,如下所示:

qemu-drive-attach &lt;vm-id&gt; &lt;device-name&gt; &lt;path-to-block-device&gt;

使用 qemu-drive-attach 腳本(設備名稱是任意的 - 我使用“virtio8”以與 Proxmox 命名方案保持一致)

!/usr/bin/expect
set vm_id               [lindex $argv 0];
set device_name         [lindex $argv 1];
set device_file         [lindex $argv 2];

spawn qm monitor $vm_id
expect "qm&gt; "
send "drive_add 0 file=$device_file,if=none,id=drive-$device_name,cache=none,detect-zeroes=on\r"

expect "OK" {
   expect "qm&gt; "
   send "device_add virtio-blk-pci,drive=drive-$device_name,id=$device_name\r"
}

expect "qm&gt; "
send "quit\r"

send_user "\n"

並用於分離

qemu-drive-detach &lt;vm-id&gt; &lt;device-name&gt;

使用 qemu-drive-detach 腳本

#!/usr/bin/expect
set vm_id               [lindex $argv 0];
set device_name         [lindex $argv 1];

spawn qm monitor $vm_id
expect "qm&gt; "
send "device_del $device_name\r"

expect "qm&gt; "
send "quit\r"

send_user "\n"

使用這些腳本進行錯誤檢查會留下一些不足之處,特別是當 device_add 和 device_del 對成功保持沉默時,但這將使外部塊設備驅動器能夠從腳本熱交換到 VM 中。

引用自:https://serverfault.com/questions/1017754