我认为我对 Python 和 Ansible findall 感到困惑。我可以在 Ansible 中使用捕获组吗?例如,如何捕获组 1 和组 2,然后在结果列表中反转位置?
例如,我从 KVM 主机中提取虚拟机的一些块设备信息。XML 中的部分如下所示。我试图获取设备名称vda
和底层文件win01.qcow2
<disk type='file' device='disk'>\n
<driver name='qemu' type='qcow2'/>\n
<source file='/var/lib/libvirt/images/win01.qcow2' index='2'/>\n
<backingStore/>\n <target dev='vda' bus='virtio'/>\n
<alias name='virtio-disk0'/>\n
<address type='pci' domain='0x0000' bus='0x05' slot='0x00' function='0x0'/>\n
我使用virt
模块提取 XML,然后删除换行符,认为使用正则表达式更容易处理。结果设置为事实,例如cleanxml
我做了以下事情并得到一个清单。
- name: Get list of block device
set_fact:
listblockdev: "{{ cleanxml | regex_findall(_q) }}"
vars:
_q: "<disk type='file' device='disk'>.*?source file='(.+?)'.*?<target dev='(\\w+)'"
结果是
ok: [testhost] => {
"msg": [
[
"/var/lib/libvirt/images/win01.qcow2",
"vda"
],
[
"/var/lib/libvirt/images/win01-1.qcow2",
"vdb"
]
]
}
有没有办法让“vda”出现在列表中的 qcow2 文件前面?或者列表的顺序不是固定的?
理想情况下,我可以尝试做类似的事情
cleanxml | regex_findall(_q, '\\2', '\\1')
结果类似于
[['vda','/var/lib/libvirt/images/win01.qcow2'], ['vdb','/var/lib/libvirt/images/win01-1.qcow2', 'vdb']]
答案1
XML 很麻烦,在 XML 上用正则表达式开始是错误的。答案并不是 regex_findall。它更多的是关于如何处理 libvirt XML
我从错误的轨道开始,删除了 XML 中的所有 \n。实际数据中的某些 XML 标签之间可能存在 \n
我找到了这个问题其中 libvirt XML 通过管道传输到 ansible.utils.from_xml。我可以从 libvirt 输出中获取设备和文件信息。
例如
- name: Get XML
set_fact:
xmldict: "{{ lookup('file','./test.xml') | ansible.utils.from_xml }}"
- name: debug
debug:
msg: "{{ item['target']['@dev'] }} {{ item['source']['@file'] }}"
with_items: "{{ xmldict.domain.devices.disk }}"
when: item['@device'] == "disk"