我的 ansible 脚本用于在 virsh 中部署虚拟机并使用 cobbler 安装它们。使用固定在 mac 地址上的 IP 地址。要做到这一点,需要 mac 地址。但我很难让 grep 命令的输出注册为变量 mac_address。变量保持未定义状态。
当临时运行命令时,它运行良好:
[root@pxecobbler test]# ansible pirate.rum.local -m shell -a 'virsh
domiflist testvm3 | grep -o -E "([0-9a-f]{2}:){5}([0-9a-f]{2})"'
pirate.rum.local | SUCCESS | rc=0 >>
52:54:00:ec:a5:49
在 ansible 剧本中它失败了,变量保持未定义:
- name: get MAC adres new VM
shell: >
virsh domiflist {{ item.key }} | grep -o -E "([0-9a-f]{2}:){5}([0-9a-f]{2})"
with_dict: "{{ guests }}"
register: mac_address
- debug:
msg: "{{ mac_address }}"
错误信息:
fatal: [pirate.rum.local]: FAILED! => {"msg": "The task includes an
option with an undefined variable.
The error was: 'dict object' has no attribute 'stdout_lines'\n\nThe
error appears to have been in '/root/virsh-create-vm/virsh-create-
vm.yml': line 47, column 7,
but may\nbe elsewhere in the file depending on the exact syntax
problem.\n\nThe offending line appears to be:\n\n
register: mac_address\n - debug: var=\"{{ mac_address.stdout_lines }}\"\n
^ here\nWe could be wrong, but this one looks like it might be an issue with\nmissing quotes.
Always quote template expression brackets when they\nstart a value. For instance:\n\n with_items:\n
- {{ foo }}\n\nShould be written as:\n\n with_items:\n - \"{{ foo }}\"\n\nexception type:
<class 'ansible.errors.AnsibleUndefinedVariable'>\nexception: 'dict object' has no attribute 'stdout_lines'"}
to retry, use: --limit @/root/virsh-create-vm/virsh-create-vm.retry
整个脚本:
- name: create VMs
hosts: pirate.rum.local
become: true
vars_files:
- vms.yml
tasks:
- name: get VM disks
command: "ls {{ vm_location }}"
register: disks
changed_when: "disks.rc != 0"
- name: create disk
command: >
qemu-img create -f qcow2 -o preallocation=metadata {{ vm_location }}/{{ item.key }}.qcow2 10G
when: item.key not in disks.stdout
with_dict: "{{ guests }}"
- name: get list of VMs
virt:
command: "list_vms"
register: vms
- name: create vm
command: >
virt-install --name {{ item.key }}
--memory {{ item.value.mem }} --vcpus {{ item.value.cpus }}
--pxe --network network=nat,model=virtio \
--disk {{ vm_location }}/{{ item.key }}.qcow2
--noautoconsole --os-variant {{ item.value.os_type }}
when: item.key not in vms.list_vms
with_dict: "{{ guests }}"
- name: get MAC adres new VM
shell: >
virsh domiflist {{ item.key }} | grep -o -E "([0-9a-f]{2}:){5}([0-9a-f]{2})"
with_dict: "{{ guests }}"
register: mac_address
- debug:
msg: "{{ mac_address }}"
# new tasks sequence on PXECobbler
- name: Register new VM's on Cobbler PXE host
hosts: pxecobbler.rum.local
vars_files:
- vms.yml
tasks:
- name: register new VM on PXE cobbler host mac {{ mac_address.stdout }}
shell: >
cobbler system add --name={{ item.key }} --profile=CentOS-7-x86_64 --interface=eth0 --mac={{ mac_address.stdout }} --ip-address={{ item.value.ip }} --netboot-enabled=1 --static=1
with_dict: "{{ guests }}"
答案1
当你说它时with_dict
,意味着你正在循环。register: mac_address
你得到的不是一个简单的普通对象,而是一个由你的循环填充的数组。
尝试这样的操作:
# new tasks sequence on PXECobbler
- name: Register new VM's on Cobbler PXE host
hosts: pxecobbler.rum.local
vars_files:
- vms.yml
- shell: echo {{ item.changed }} {{ item.stdout }} # will print: True 00:11:22:33:44
with_items: "{{ mac_address.results }}"
register: b
- debug:
msg: "{{ b }}"
下次你输的时候,要特别注意把最基本的任务做对。你的问题是很多如果您按原样引用实际的 yml(它包含debug: var="{{ mac_address.stdout_lines }}"
您未引用的内容),则会更简单。