我正在尝试用 Python 编写脚本libvirt 库,但我目前坚持一件事。
我可以成功创建虚拟机,按照我想要的方式设置它,启动它,访问它,然后关闭它。我什至可以在不再需要它后再次删除它。
但我还没有弄清楚如何摆脱虚拟机的磁盘。
在我的 Bash“原型”中,我可以直接调用virsh undefine <name> --remove-all-storage
.但在所有的文档中,我还没有找到在Python中触发这个的方法。
当然我可以这样做,os.system("virsh undefine ...")
但那是A)一个可怕的黑客和B)它需要安装virsh。
.undefine()
对域的调用会留下虚拟磁盘。我发现了.undefineFlags()
,但我发现的标志似乎都不相关(1=删除保存、2=删除快照、4=删除 NVRAM;其中没有一个会删除虚拟磁盘)。
我可以.XMLDesc()
调用域并获取完整的 XML、查找定义的磁盘并获取文件路径。如果我的 Python 脚本与虚拟机在同一台机器上运行,我就可以调用os.remove()
- 但事实并非如此,它运行在远程机器上。
该virsh
命令能够通过 libvirt 远程连接删除磁盘,所以我知道它必须以某种方式实现。但即使查看了 virsh--remove-all-storage
定义的源代码,我仍然感到困惑。
该应用程序似乎要求virStorageVolWipe
安全删除,或virStorageVolDelete
仅删除磁盘。这需要我获得一个PythonvirStorageVol
对象才能调用它的delete()
方法。
但是我如何获得这个对象呢?我发现了大量对“存储池”的引用,我可以遍历这些引用来查找路径,或者我什至可以从虚拟机的 XML 中获取存储磁盘的路径;但这并没有给我那个对象,所以我可以调用delete()
它。
我是否真的需要循环遍历所有存储池,然后循环遍历所述池中的所有卷,然后以某种方式手动找出每个卷是否连接到我要删除的虚拟机,以便能够完全删除虚拟机当我用完它时?另外,我相信理论上可能有一个不在任何存储池中的卷,所以这也没有帮助......
为什么没有virDomainGetVolumes
?我发现virDomainGetBlockInfo
但这只是返回路径和类型,而不是对象virStorageVol
。我错过了什么吗?
答案1
看来我想得太复杂了。
我可以通过解析返回的 XML 来获取主机到 VM 磁盘的路径.XMLDesc()
,然后我可以调用.storageVolLookupByPath()
(我显然之前错过了)来获取storageVol
要删除的对象:
domain = conn.lookupByName("my-vm-name")
domain_xml = domain.XMLDesc()
for disk_xml_element in ElementTree.fromstring(domain_xml).findall("devices/disk"):
for src in disk_xml_element.findall("source"):
disk = virt_conn.storageVolLookupByPath(src.get("file"))
disk.delete()