You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将vmware_guest部署的VM变量传递给Ansible角色以完成配置

Ansible部署VM后变量传递失败问题解决

问题概述

使用vmware_guest模块成功部署新VM,通过add_host将VM加入清单后,执行后续角色配置时提示vm_info未定义。VM部署流程正常,但后续配置playbook报错。

原Playbook代码

---
- name: Deploy the VM
  hosts: localhost
  gather_facts: no

  tasks:
    - name: "Create VM from template"
      vmware_guest:
        validate_certs: false
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        datacenter: "{{ vcenter_datacenter }}"
        cluster: "{{ vm_cluster }}"
        template: "{{ vm_template }}"
        name: "{{ vm_name }}"
        folder: "{{ vm_folder }}"
        hardware:
          num_cpus: "{{ vm_hw_cpu_n }}"
          memory_mb: "{{ vm_hw_ram_mb }}"
        disk:
          - size_gb: "{{ vm_disk_gb }}"
            type: thin
            datastore: "{{ vm_datastore_cluster }}"
        networks:
          - name: "{{ vm_net_name }}"
            type: static
            device_type: vmxnet3
            ip: 172.16.100.123
            netmask: 255.255.255.0
            gateway: 172.16.100.1
            connected: true
            start_connected: true
        customization:
          hostname: "{{ vm_name }}.domain.invalid"
          domain: domain.invalid
          dns_servers:
            - 172.16.100.10
            - 172.16.100.11
          dns_suffix:
            - domain.invalid
        state: present
        wait_for_ip_address: true
      register: vm_info

    - name: Add host to inventory
      ansible.builtin.add_host:
        name: "{{ vm_info.instance.ipv4 }}"
        groups: vmware_vms
     

- name: Run Additional Configurations
  hosts: vmware_vms
  roles:
    - role: base
      vars:
        var_vm_name: "{{ vm_name }}"
        var_vm_ip: "{{ vm_info.instance.ipv4 }}"
        var_vm_domain: "{{ vm_info.customization.domain }}"
        var_vm_fqdn: "{{ vm_info.customization.hostname }}"
        var_vm_dnsservers: "{{ vm_info.customization.dns_servers }}"

错误信息

"msg": "AnsibleUndefinedVariable: 127.0.0.1       localhost
127.0.1.1       {{ var_vm_name }}
{{ var_vm_ip }} {{ var_vm_fqdn }} {{ var_vm_name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
: {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. 127.0.0.1       localhost
127.0.1.1       {{ var_vm_name }}
{{ var_vm_ip }} {{ var_vm_fqdn }} {{ var_vm_name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
: {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined",
  "exception": "Traceback (most recent call last):
  File \"/usr/lib/python3.9/site-packages/ansible/template/__init__.py\", line 1004, in do_template
    res = myenv.concat(rf)
  File \"/usr/lib/python3.9/site-packages/ansible/template/native_helpers.py\", line 83, in ansible_concat
    return ''.join([to_text(v) for v in nodes])
  File \"/usr/lib/python3.9/site-packages/ansible/template/native_helpers.py\", line 83, in <listcomp>
    return ''.join([to_text(v) for v in nodes])
  File \"<template>\", line 12, in root
  File \"/usr/lib/python3.9/site-packages/ansible/template/__init__.py\", line 295, in wrapper
    ret = func(*args, **kwargs)
  File \"/usr/lib/python3.9/site-packages/ansible/template/__init__.py\", line 547, in _ansible_finalize
    return thing if _fail_on_undefined(thing) is not None else ''
  File \"/usr/lib/python3.9/site-packages/ansible/template/__init__.py\", line 519, in _fail_on_undefined
    elif is_sequence(data):
  File \"/usr/lib/python3.9/site-packages/ansible/module_utils/common/collections.py\", line 94, in is_sequence
    if not include_strings and is_string(seq):
  File \"/usr/lib/python3.9/site-packages/jinja2/runtime.py\", line 852, in _fail_with_undefined_error
    raise self._undefined_exception(self._undefined_message)
ansible.errors.AnsibleUndefinedVariable: 127.0.0.1       localhost
127.0.1.1       {{ var_vm_name }}
{{ var_vm_ip }} {{ var_vm_fqdn }} {{ var_vm_name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
: {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File \"/usr/lib/python3.9/site-packages/ansible/plugins/action/template.py\", line 152, in run
    resultant = templar.do_template(template_data, preserve_trailing_newlines=True, escape_backslashes=False, overrides=overrides)
  File \"/usr/lib/python3.9/site-packages/ansible/template/__init__.py\", line 1038, in do_template
    raise AnsibleUndefinedVariable(e, orig_exc=e)
ansible.errors.AnsibleUndefinedVariable: 127.0.0.1       localhost
127.0.1.1       {{ var_vm_name }}
{{ var_vm_ip }} {{ var_vm_fqdn }} {{ var_vm_name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
: {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. 127.0.0.1       localhost
127.0.1.1       {{ var_vm_name }}
{{ var_vm_ip }} {{ var_vm_fqdn }} {{ var_vm_name }}

# The following lines are desirable for IPv6 capable hosts
::1     localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
: {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined. {{ vm_info.instance.ipv4 }}: 'vm_info' is undefined. 'vm_info' is undefined
",
  "_ansible_no_log": null,
  "changed": false

错误原因

Ansible的不同Play之间变量是隔离的:vm_info是在第一个针对localhost的Play中注册的变量,仅存在于该Play的执行上下文;第二个针对vmware_vms组的Play无法直接访问这个变量,导致报错。同时,base角色的模板中可能直接引用了vm_info,而非传递过来的变量。

解决方案

方法一:通过add_host传递主机变量(推荐)

修改add_host任务,将需要的变量直接附加到新添加的主机上,作为该主机的专属变量:

- name: Add host to inventory
  ansible.builtin.add_host:
    name: "{{ vm_info.instance.ipv4 }}"
    groups: vmware_vms
    # 直接传递需要的变量到新主机
    var_vm_name: "{{ vm_name }}"
    var_vm_ip: "{{ vm_info.instance.ipv4 }}"
    var_vm_domain: "{{ vm_info.customization.domain }}"
    var_vm_fqdn: "{{ vm_info.customization.hostname }}"
    var_vm_dnsservers: "{{ vm_info.customization.dns_servers }}"

然后修改第二个Play,直接使用主机变量,无需再引用vm_info:

- name: Run Additional Configurations
  hosts: vmware_vms
  roles:
    - role: base
      # 这里无需重复定义vars,主机变量会自动传递到角色中

同时检查base角色的模板,确保模板中使用{{ var_vm_ip }}这类传递过来的变量,而非直接引用{{ vm_info.instance.ipv4 }}。

方法二:全局持久化变量(不推荐,仅特殊场景使用)

如果需要跨Play共享变量,可使用set_fact结合persist=True将变量保存到本地facts缓存:

- name: Save VM info as global fact
  ansible.builtin.set_fact:
    global_vm_info: "{{ vm_info }}"
    persist: true

然后在第二个Play中引用全局变量:

- name: Run Additional Configurations
  hosts: vmware_vms
  roles:
    - role: base
      vars:
        var_vm_name: "{{ vm_name }}"
        var_vm_ip: "{{ global_vm_info.instance.ipv4 }}"
        var_vm_domain: "{{ global_vm_info.customization.domain }}"
        var_vm_fqdn: "{{ global_vm_info.customization.hostname }}"
        var_vm_dnsservers: "{{ global_vm_info.customization.dns_servers }}"

注意:此方法会将变量持久化到本地,可能影响后续Playbook执行,优先使用方法一。

内容的提问来源于stack exchange,提问作者slekkus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:35:55