热插拔物理磁盘传递到 qemu VM

热插拔物理磁盘传递到 qemu VM

我在 proxmox 上的 qemu 中运行了一个虚拟服务器。它有两个物理磁盘,使用 101.cfg 中的 virtio: 指令连接到主机,如下所示

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 配置中启用了磁盘热插拔。

我的问题是,在插入和移除这些磁盘时,将这些磁盘动态地附加到我的虚拟机和从虚拟机中分离的正确方法是什么?

我已经能够使用“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 monitor 命令,而且 qm monitor 不会从 stdin 接受参数或输入。从阅读中得知,可能可以在客户机上创建一个套接字到 qemu-agent 并使用 JSON 将其注入,但我对 JSON 一无所知,真心希望有更简单的方法。

答案1

我已经尝试过很多次了,确实能够通过 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 monitor”可能由于 readline 支持而无法接受来自 stdin 的输入。这让我想到了“expect”。稍后快速“apt install expect”,我能够创建脚本来连接和分离驱动器,如下所示:

qemu-drive-attach <vm-id> <device-name> <path-to-block-device>

使用 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> "
send "drive_add 0 file=$device_file,if=none,id=drive-$device_name,cache=none,detect-zeroes=on\r"

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

expect "qm> "
send "quit\r"

send_user "\n"

拆卸

qemu-drive-detach <vm-id> <device-name>

使用 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> "
send "device_del $device_name\r"

expect "qm> "
send "quit\r"

send_user "\n"

使用这些脚本进行错误检查还有待改进,特别是因为 device_add 和 device_del 在成功时没有任何提示,但这将允许外部块设备驱动器从脚本热交换到 VM 中。

答案2

virtio-blk不支持热插拔。

要使用热插拔磁盘,您需要使用具有此类支持的驱动程序,如 SATA 或virtio-scsi(实现 SCSI 协议)。然后,您可以使用诸如virsh(编辑:正如您正确指出的那样,它在 Proxmox 上不受支持)或 Qemu HMP(普遍支持,但可能更容易出错)之类的东西来热添加/删除磁盘。

相关内容