我正在构建一个旨在在 vCenter 虚拟机上运行的 ansible playbook。 它在启动时由 ansible-pull 运行。 我的目标是使用 ansible 读取虚拟机上的标签,然后根据这些标签对来宾系统进行一些配置更改。
困难在于我需要从客人内部读取客人上的标签。 vmware_guest_facts 模块可以让我执行此操作,但它需要来宾的名称或 uuid。
目前我能想到的唯一方法是使用 vmware_vm_facts 获取所有虚拟机的事实,然后找到 ansible_default_ipv4.address 与 IP 地址匹配的虚拟机,将其设置为事实,然后使用 vmware_guest_facts 读取标签通过 UUID 来自该 VM。 看起来有点过分了。
有没有一种简单的方法可以让虚拟机读取我忽略的自己的标签?
这是我现在要做的:
- hosts: localhost
connection: local
vars_files:
- vars.yaml
pre_tasks:
- name: Read VMware vm facts
vmware_vm_facts:
hostname: "{{vc_host}}"
password: "{{vc_pass}}"
username: "{{vc_user}}"
validate_certs: no
vm_type: vm
delegate_to: localhost
register: vmfacts
- name: scan for ip
set_fact:
vm_uuid: "{{ item.uuid }}"
vm_name: "{{ item.guest_name }}"
with_items: "{{ vmfacts.virtual_machines }}"
when:
- item.ip_address is defined
- ansible_default_ipv4.address == item.ip_address
- name: Read VMware guest facts
vmware_guest_facts:
datacenter: ASDC
hostname: "{{vc_host}}"
uuid: "{{vm_uuid}}"
password: "{{vc_pass}}"
username: "{{vc_user}}"
tags: yes
validate_certs: no
register: vmguestfacts
- name: set up tags var
set_fact:
vm_tags: "{{ vmguestfacts.instance.tags }}"
- debug:
msg: "{{ vm_tags }}"
- name: Get Tags from given VM Name
block:
- name: Get virtual machine facts
community.vmware.vmware_vm_info:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
folder: "/datacenter/vm/folder"
show_tag: True
delegate_to: localhost
register: vm_facts
- debug:
msg: "{{ item.tags }}"
with_items:
- "{{ vm_facts.virtual_machines | json_query(query) }}"
vars:
query: "[?guest_name=='DC0_H0_VM0']"
我上面发布的版本需要 37 秒才能运行,因为它请求有关 vCenter 上所有虚拟机的信息。 我发现
dmidecode -s system-serial-number
会给出与十六进制格式的虚拟机 uuid 相匹配的系统序列 Serial Number: VMware-xx xx xx xx xx xx xx xx-xx xx xx xx xx xx xx xx
以下运行时间约为 7 秒:
- hosts: localhost
connection: local
vars_files:
- vars.yaml
pre_tasks:
- name: get uuid
shell: |
sudo /usr/sbin/dmidecode -s system-serial-number
register: dmiout
- set_fact:
singleuuid: "{{ dmiout.stdout | regex_replace('.*VMware-(.*)$', '\\1') | replace(' ','') | replace('-','') }}"
- set_fact:
localuuid: "{{singleuuid[0:8]}}-{{singleuuid[8:12]}}-{{singleuuid[12:16]}}-{{singleuuid[16:20]}}-{{singleuuid[20:32]}}"
- name: Read VMware guest facts
vmware_guest_facts:
datacenter: ASDC
hostname: "{{vc_host}}"
uuid: "{{localuuid}}"
password: "{{vc_pass}}"
username: "{{vc_user}}"
tags: yes
validate_certs: no
register: vmguestfacts
- name: set up tags var
set_fact:
vm_tags: "{{ vmguestfacts.instance.tags }}"
- debug:
msg: "{{ vm_tags }}"
唯一的问题是 dmidecode 需要 root 访问权限才能运行。 由于这是作为普通用户 foouser 运行的,因此我必须将此行添加到 sudoers:
foouser ALL=(ALL) NOPASSWD:/usr/sbin/dmidecode
这整件事比我想要的更笨重,所以在下一次迭代中我可能会将剧本更改为以 root 身份运行,这样我就可以删除 sudo 需求。
编辑:
有人问正则表达式是做什么的,所以这里有一些解释。 我们从
sudo /usr/sbin/dmidecode -s system-serial-number
返回
VMware-24 25 26 27 76 15 29 9d-0e 56 e5 b3 52 9f 41 a2
第一个 regex_replace 将 VMware- 替换为空,给我们
24 25 26 27 76 15 29 9d-0e 56 e5 b3 52 9f 41 a2
第二次替换将空格替换为空,给我们
242526277615299d-0e56e5b3529f41a2
第三次替换将破折号替换为空,给我们
242526277615299d0e56e5b3529f41a2
下一行在正确的位置添加破折号,将其转换为有效的 uuid。
快速更新,我使用 Ansible fact 而不是
shell
模块:
- set_fact:
singleuuid: "{{ ansible_product_serial | regex_replace('.*VMware-(.*)$', '\\1') | replace(' ','') | replace('-','') }}"