热交换物理磁盘传递到 qemu VM

Chr*_*sti 5 qemu proxmox kvm-virtualization

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

virtio2: /dev/disk/by-id/ata-vol1,backup=0 
virtio3: /dev/disk/by-id/ata-vol2,backup=0
Run Code Online (Sandbox Code Playgroud)

这些包含一个镜像的 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
Run Code Online (Sandbox Code Playgroud)

这种工作,但问题是这些磁盘都不是可热插拔的,所以如果我轮流移除和插入磁盘,来宾将无法看到它们。我的 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
Run Code Online (Sandbox Code Playgroud)

分离

qm> device_del backup_scsi_controller
Run Code Online (Sandbox Code Playgroud)

(来源:https : //blog.chrishowie.com/2019/09/19/hot-swapping-virtio-disks-on-qemu/通过谷歌缓存)

我想我可以将这些添加到我的备份脚本中,但是似乎不可能从 shell 脚本运行 qm monitor 命令,并且 qm monitor 不会从 stdin 获取参数或输入。通过阅读,可能可以在来宾上的 qemu-agent 中创建一个套接字并使用 JSON 注入它,但我对 JSON 一无所知,我真的希望有一种更简单的方法。

Chr*_*sti 2

我已经在这方面进行了一些研究,确实达到了能够通过 UNIX 套接字向来宾发送 QMP 命令的地步。默认 Proxmox 配置使用 /var/run/qemu-server/<server-id>.qmp 处的套接字支持此功能。然后我可以使用交互方式发送 QMP JSON 消息

rlwrap -C qmp socat - UNIX:/var/run/qemu-server/101.qmp
Run Code Online (Sandbox Code Playgroud)

(rlwrap默认不安装,但可以使用“apt install rlwrap”安装)

然而,QMP 消息格式与我想象的一样不透明,并且出于意识形态纯洁性的原因没有与“drive_add”直接等效的内容(这也许是可以理解的,但在我目前遇到的困难的情况下却毫无帮助)。有一个“blockdev_add”命令很可能已经完成了我想要的事情,假设我可以计算出正确的语法。

因此,我后退了一步,得出的结论是,由于 readline 支持,“qm 监视器”可能不接受来自 stdin 的输入。这让我想到了“期待”。稍后快速“apt install Expect”,我能够创建脚本来附加和分离驱动器,如下所示:

qemu-drive-attach <vm-id> <device-name> <path-to-block-device>
Run Code Online (Sandbox Code Playgroud)

使用 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"
Run Code Online (Sandbox Code Playgroud)

并用于分离

qemu-drive-detach <vm-id> <device-name>
Run Code Online (Sandbox Code Playgroud)

使用 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"
Run Code Online (Sandbox Code Playgroud)

使用这些脚本进行错误检查还有一些不足之处,特别是因为 device_add 和 device_del 在成功时保持沉默,但这将使外部块设备驱动器能够从脚本热交换到虚拟机中。