目标:使代码自动化,使其与ovf无关。构建一个剧本,以允许在不更改YAML剧本的情况下部署具有任何自定义ovf属性和网络接口名称的任何OVF模板。
环境: Ansible 2.8.7 python版本= 3.6.8
代码示例:
**Dicts: cust-ovf-answer.yml**
custovfnetworkanswers:
Management: "vmportgroup"
custovfanswers:
fqdn: "s0u1tst.dmn.local"
dns1: "10.100.0.14"
dns2: "10.100.0.17"
ntp1: "ntp1.dmn.local"
ntp2: "ntp2.dmn.local"
ipv4.how: "Manual"
ipv4.addr: "10.100.0.135"
ipv4.mask: "255.255.255.224"
ipv4.gw: "10.100.0.158"
**Playbook: Deploy_OVF_to_System.yml**
... MAGIC STUFF GOING ON UP HERE ...
- name: Get Unqiue OVF Answers
include_vars:
file: ".../cust-ovf-answers.yml"
- name: Deploy Appliance OVF
vmware_deploy_ovf:
hostname: "{{ inventory_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
name: "r{{ custVMName }}"
datacenter: "TEST"
folder: "/test/vm/aas"
datastore: "{{ targetDatastore }}"
allow_duplicates: no
disk_provisioning: "thick"
networks:
args: "{{ custovfnetworkanswers | to_json }}"
# "Management": "{{ vmportgroup }}"
power_on: no
wait: no
ovf: "{{ custOvfFile.files[0].path }}"
fail_on_spec_warnings: no
inject_ovf_env: yes
properties:
args: "{{ custovfanswers | to_json }}"
# fqdn: "{{ item.value.fdqn }}"
# dns1: "{{ item.value.dns1 }}"
# dns2: "{{ item.value.dns2 }}"
# ntp1: "ntp1.dmn.local"
# ntp2: "ntp2.dmn.local"
# ipv4.how: "Manual"
# ipv4.addr: "10.100.0.135"
# ipv4.mask: "255.255.255.224"
# ipv4.gw: "10.100.0.158"
delegate_to: localhost
when:
#- custovfanswers is defined
#- custovfnetworkanswers is defined
**输出1:**
使用args:“ {{ custom_dict | to_json}}”定义网络和属性时的错误。
{
"hosts": {
"vCenter Host": {
"_ansible_no_log": false,
"action": "set_fact",
"ansible_facts": {
"buildvmCustomConfigFileLoc": ".../cust-ovf-answer.yml"
},
"changed": false
}
},
"task": {
"duration": {
"end": "2019-11-22T18:05:50.616891Z",
"start": "2019-11-22T18:05:50.544148Z"
},
"id": "005056a7-5f58-135f-6306-000000000a39",
"name": "set_fact"
}
},
{
"hosts": {
"vCenter Host": {
"_ansible_no_log": false,
"action": "include_vars",
"ansible_facts": {
"custovfanswers": {
"dns1": "10.100.0.14",
"dns2": "10.100.0.17",
"fqdn": "s0u1tst.dmn.local",
"ipv4.addr": "10.100.0.135",
"ipv4.gw": "10.100.0.158",
"ipv4.how": "Manual",
"ipv4.mask": "255.255.255.224",
"ntp1": "ntp1.dmn.local",
"ntp2": "ntp2.dmn.local",
},
"custovfnetworkanswers": {
"Management": "VMTraffic_test"
}
},
"ansible_included_var_files": [
".../cust-ovf-answer.yml"
],
"changed": false
}
},
"task": {
"duration": {
"end": "2019-11-22T18:05:50.741706Z",
"start": "2019-11-22T18:05:50.653958Z"
},
"id": "005056a7-5f58-135f-6306-000000000a3a",
"name": "Get Unqiue OVF Answers"
}
},
{
"hosts": {
"vCenter Host": {
"_ansible_delegated_vars": {
"ansible_host": "localhost"
},
"_ansible_no_log": false,
"action": "vmware_deploy_ovf",
"changed": false,
"exception": "Traceback (most recent call last):\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 114, in <module>\n _ansiballz_main()\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 106, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 49, in invoke_module\n imp.load_module('__main__', mod, module, MOD_DESC)\n File \"/usr/lib/python3.6/imp.py\", line 235, in load_module\n return load_source(name, filename, file)\n File \"/usr/lib/python3.6/imp.py\", line 170, in load_source\n module = _exec(spec, sys.modules[name])\n File \"<frozen importlib._bootstrap>\", line 618, in _exec\n File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 685, in <module>\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 677, in main\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 465, in upload\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 372, in get_lease\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 344, in get_objects\nKeyError: 'network'\n",
"failed": true,
"module_stderr": "Traceback (most recent call last):\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 114, in <module>\n _ansiballz_main()\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 106, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/home/swelsch/.ansible/tmp/ansible-tmp-1574445950.872407-14317549312709/AnsiballZ_vmware_deploy_ovf.py\", line 49, in invoke_module\n imp.load_module('__main__', mod, module, MOD_DESC)\n File \"/usr/lib/python3.6/imp.py\", line 235, in load_module\n return load_source(name, filename, file)\n File \"/usr/lib/python3.6/imp.py\", line 170, in load_source\n module = _exec(spec, sys.modules[name])\n File \"<frozen importlib._bootstrap>\", line 618, in _exec\n File \"<frozen importlib._bootstrap_external>\", line 678, in exec_module\n File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 685, in <module>\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 677, in main\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 465, in upload\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 372, in get_lease\n File \"/tmp/ansible_vmware_deploy_ovf_payload_9pywu9rd/__main__.py\", line 344, in get_objects\nKeyError: 'network'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
},
"task": {
"duration": {
"end": "2019-11-22T18:05:53.288639Z",
"start": "2019-11-22T18:05:50.791547Z"
},
"id": "005056a7-5f58-135f-6306-000000000a3b",
"name": "Deploy Appliance OVF"
}
}
**输出2:** 在使用args定义属性:时出错:“ {{ custom_dict | to_json}}”。网络:通过对其进行硬编码来定义。
{
"hosts": {
"vCenter Host": {
"_ansible_no_log": false,
"action": "include_vars",
"ansible_facts": {
"custovfanswers": {
"dns1": "10.100.0.14",
"dns2": "10.100.0.17",
"fqdn": "s0u1tst.dmn.local",
"ipv4.addr": "10.100.0.135",
"ipv4.gw": "10.100.0.158",
"ipv4.how": "Manual",
"ipv4.mask": "255.255.255.224",
"ntp1": "ntp1.dmn.local",
"ntp2": "ntp2.dmn.local",
},
"custovfnetworkanswers": {
"Management": "vmportgroup"
}
},
"ansible_included_var_files": [
".../cust-ovf-answer.yml"
],
"changed": false
}
},
"task": {
"duration": {
"end": "2019-11-22T18:42:33.098663Z",
"start": "2019-11-22T18:42:33.001653Z"
},
"id": "005056a7-5f58-c3eb-25e1-000000000a3a",
"name": "Get Unqiue OVF Answers"
}
},
{
"hosts": {
"vCenter Host": {
"_ansible_delegated_vars": {
"ansible_host": "localhost"
},
"_ansible_no_log": false,
"action": "vmware_deploy_ovf",
"changed": true,
"instance": {
"annotation": "xxxx",
"current_snapshot": null,
"customvalues": {},
"guest_consolidation_needed": false,
"guest_question": null,
"guest_tools_status": "guestToolsNotRunning",
"guest_tools_version": "0",
"hw_cluster": null,
"hw_cores_per_socket": 1,
"hw_datastores": [
"s0u1aas-nlsas"
],
"hw_esxi_host": "s0u1aas.dmn.local",
"hw_eth0": {
"addresstype": "assigned",
"ipaddresses": null,
"label": "Network adapter 1",
"macaddress": "00:50:56:a7:ae:20",
"macaddress_dash": "00-50-56-a7-ae-20",
"portgroup_key": null,
"portgroup_portkey": null,
"summary": "vmportgroup"
},
"hw_files": [
"[s0u1aas-nlsas] r10s0u1tst/r10s0u1tst.vmx",
"[s0u1aas-nlsas] r10s0u1tst/r10s0u1tst.vmsd",
"[s0u1aas-nlsas] r10s0u1tst/r10s0u1tst.vmdk"
],
"hw_folder": "/test/vm/AAS",
"hw_guest_full_name": null,
"hw_guest_ha_state": null,
"hw_guest_id": null,
"hw_interfaces": [
"eth0"
],
"hw_is_template": false,
"hw_memtotal_mb": 32768,
"hw_name": "r10s0u1tst",
"hw_power_status": "poweredOff",
"hw_processor_count": 4,
"hw_product_uuid": "4227ef4b-0d98-e254-f9e7-b798bbee43fc",
"hw_version": "vmx-13",
"instance_uuid": "50271468-256d-9c69-7154-cfbdd26fc900",
"ipv4": null,
"ipv6": null,
"module_hw": true,
"snapshots": [],
"vnc": {}
},
"invocation": {
"module_args": {
"allow_duplicates": false,
"cluster": null,
"datacenter": "TEST",
"datastore": "s0u1aas-nlsas",
"deployment_option": null,
"disk_provisioning": "thin",
"fail_on_spec_warnings": false,
"folder": "/test/vm/aas",
"hostname": "vCenter Host",
"inject_ovf_env": true,
"name": "r10s0u1tst",
"networks": {
"Management": "vmportgroup "
},
"ovf": "xxx.ovf",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"power_on": false,
"properties": {
"args": "{\"fqdn\": \"s0u1tst.dmn.local\", \"dns1\": \"10.100.0.14\", \"dns2\": \"10.100.0.17\", \"ntp1\": \"ntp1.dmn.local\", \"ntp2\": \"ntp2.dmn.local\", \"ipv4.how\": \"Manual\", \"ipv4.addr\": \"10.100.0.135\", \"ipv4.mask\": \"255.255.255.224\", \"ipv4.gw\": \"10.100.0.158\"}"
},
"resource_pool": "Resources",
"username": "xxxx",
"validate_certs": false,
"wait": false,
"wait_for_ip_address": false
}
}
}
},
"task": {
"duration": {
"end": "2019-11-22T18:43:35.923602Z",
"start": "2019-11-22T18:42:33.148318Z"
},
"id": "005056a7-5f58-c3eb-25e1-000000000a3b",
"name": "Deploy Appliance OVF"
}
如果我全部硬编码,则所有内容都会按预期导入。
答案 0 :(得分:0)
我认为您的问题是 args:
。您可以直接注入 dict 变量。顺便说一句,您不需要使用 to_json
转换过滤器,因为 Ansible 会处理它。
[…]
disk_provisioning: "thick"
networks: "{{ custovfnetworkanswers }}"
power_on: no
[…]
inject_ovf_env: yes
properties: "{{ custovfanswers }}"
delegate_to: localhost
[…]
在某些情况下,您必须提供的键需要是动态的(不可预测的键名或列表长度)。要解决这个问题,您可以使用 jinja2 将变量伪造为 json 字符串。
dict 样本动态列表:
vars:
custom_networks: >
[ {% for nic in nics %}
{ 'name':'{{ nic.id }}',
'mac':'{{ nic.mac }}',
'ip': '{{ nic.ip }}'
}{% if not loop.last %},{% endif %}
{% endfor %}
]
动态键名:
vars:
custom_ovf_input: "{ '{{ network_name }}': '{{ network_address }}' }"
然后你可以直接使用那个伪造的变量(不需要使用任何过滤器将其转换为 yaml Ansible 会处理它)。