qemu-img commit 的链必须是完整的,虽然 commit 的是 head,看起来和底层几级镜像没关系,但实际还是需要。commit 链的关系还可以是临时的,-d 参数决定 commit 后是否清空文件。
现象
qemu-img commit 的链,必须是完整的。
虽然你 commit 的是 head,看起来和底层几级的镜像没有关系,但实际还是需要的:
root@host:~/tmp# qemu-img commit -f qcow2 /root/tmp/vm-example_tmp.img
qemu-img: Could not open '/root/tmp/vm-example_tmp.img': Could not open backing file: Could not open backing file: Could not open '/root/tmp/focal1x64a': No such file or directory
排查
commit 链的关系还可以是临时的
下面命令不会改变 /dev/vg2/vm-example_lss-sjjgi703 的 backing file,但是确可以提交数据到其他链上,非常方便:
qemu-img commit --image-opts file.filename=/dev/vg2/vm-example_lss-sjjgi703,backing.file.filename=/root/tmp/vm-example.img
底层链有 nbd 镜像也会失败
如果底层的链中有 nbd 镜像,那么即便 commit 没到 nbd img,也会失败:
2024-12-09 18:08:26,809 INFO -139636383823616- commit_snap command is [qemu-img commit -f qcow2 -d /data/container/vm-example/vm-example.resize_tmp.img] ret is [(1, '', u"qemu-img: Block format 'nbd' used by node '#block817' does not support reopening files")]
如果底层的链中有 nbd 镜像,那么即便 commit 没到 nbd img,也会失败。
所以,如果镜像是 nbd 的,一些包含 commit 的功能会失败。
上面的链是这样:
/data/container/vm-example/vm-example.resize_tmp.img -> /vm-example.img -> nbd:img
根因
-d 参数非常重要
qemu-img commit -d
-d 参数非常重要:
The image FILENAME is emptied after the operation has succeeded. If you do not need FILENAME afterwards and intend to drop it, you may skip emptying FILENAME by specifying the -d flag.
也就是说:
- 不加
-d,那么 commit 后,filename 里的数据会被清空; - 加了
-d,就可以保留。
libvirt 8 之后检查加强了
libvirt 8 之后,很多检查都加强了。ubuntu22 上是 libvirt8。
典型的是:
qemu-img createqemu-img convertqemu-img rebase
如果存在 backing file,就必须要加 -F 显式指定 type。
所以时刻举一反三。
小结
qemu-img commit的链必须是完整的,虽然 commit 的是 head,但底层镜像还是需要;- commit 链的关系还可以是临时的,用
--image-opts指定 backing 即可; - 底层链中有 nbd 镜像,即便 commit 没到 nbd img 也会失败;
-d参数决定 commit 后是否清空文件,不加-d会清空,加了保留;- libvirt 8 之后,有 backing file 的命令必须加
-F显式指定 type。