Ansible vmware_vm_facts: get mac address for a specific VM and write it to existing inventory

I have to goals with my plabook:

a) get mac address from a specific VM running on vsphere

b) add it to my inventory file

My test environment is:
-Vsphere 6.5
-Ansible 2.7 running on Centos 7.6

I have been able to make point a) following this post How retrieve the name of specific dictionary - Ansible

Playbook:

# Deploy a guest from a template*  
- hosts: 127.0.0.1  
  vars:
    vcenter_hostname: virtvcsami1.virtlab.local  
    vcenter_user: administrator@vsphere.local  
    vcenter_pass: Esxilab!1  
    vcenter_datastore: vsanDatastore  
    vcenter_datacenter: DatacenterMI  
  tasks:  
  - name: Gather VMware guest facts  
    vmware_vm_facts:  
      validate_certs: False  
      hostname: "{{ vcenter_hostname }}"  
      username: "{{ vcenter_user }}"  
      password: "{{ vcenter_pass }}"  
      vm_type: vm  
    delegate_to: localhost  
    register: vm_guest_facts  

  - debug: msg="{{ item.value.mac_address }}"  
    loop: "{{ vm_guest_facts.virtual_machines|dict2items }}"

but now I still have two problems to solve:

Problem 1)

Playbook gets ALL virtual machines while I need to get just a VM named “testvm”

[root@nlnxmi1 testvmcdromiso]# ansible-playbook getvminfo.yml

PLAY [127.0.0.1] ***********************************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************************
ok: [127.0.0.1]
TASK [Gather VMware guest facts] *******************************************************************************************************************************************************************************
ok: [127.0.0.1 → localhost]
TASK [debug] ***************************************************************************************************************************************************************************************************
ok: [127.0.0.1] => (item={‘key’: u’kubemst01’, ‘value’: {u’guest_fullname’: u’CentOS 7 (64-bit)‘, u’vm_network’: {u’00:50:56:be:de:b9’: {u’ipv4’: [u’192.168.40.31’], u’ipv6’: [u’fe80::250:56ff:febe:deb9’]}, u’52:54:00:62:fe:fe’: {u’ipv4’: [u’192.168.122.1’], u’ipv6’: }}, u’cluster’: u’VirtlabMI’, u’esxi_hostname’: u’virtesxmi3.virtlab.local’, u’mac_address’: [u’00:50:56:be:de:b9’], u’power_state’: u’poweredOn’, u’ip_address’: u’192.168.40.31’, u’uuid’: u’423e7580-1ca4-a6ca-5cb4-5b8fa963d527’}}) => { “msg”: [ “00:50:56:be:de:b9” ] }

ok: [127.0.0.1] => (item={‘key’: u’testvm’, ‘value’: {u’guest_fullname’: >u’CentOS 7 (64-bit)‘, u’vm_network’: {}, u’cluster’: u’VirtlabMI’, >u’esxi_hostname’: u’virtesxmi1.virtlab.local’, u’mac_address’: >[u’00:50:56:be:a3:a0’], u’power_state’: u’poweredOn’, u’ip_address’: u’‘, >u’uuid’: u’423e8645-ca2a-1097-2e1c-624810a461d1’}}) => { “msg”: [ “00:50:56:be:a3:a0” ] } …

Trying to solve this tedious problem I posted on stackoverflow (https://stackoverflow.com/questions/56243269/ansible-vmware-vm-facts-get-mac-address-for-a-specific-vm-and-write-it-to-exist/56245634#56245634) and a user gave me this suggestion:

-----from stackoverflow----

That’s not a problem. It looks like the vmware_vm_facts module returns a dictionary, so just ask for the vm you want:

  - debug: msg="{{ vm_guest_facts.virtual_machines['testvm'].mac_address }}"  

Problem 1)

# Deploy a guest from a template*
- hosts: 127.0.0.1
  vars:
    vcenter_hostname: virtvcsami1.virtlab.local
    vcenter_user: administrator@vsphere.local
    vcenter_pass: Esxilab!1
    vcenter_datastore: vsanDatastore
    vcenter_datacenter: DatacenterMI
  tasks:
  - name: Gather VMware guest facts
    vmware_vm_facts:
      validate_certs: False
      hostname: "{{ vcenter_hostname }}"
      username: "{{ vcenter_user }}"
      password: "{{ vcenter_pass }}"
      vm_type: vm
    delegate_to: localhost
    register: vm_guest_facts

# - debug: msg="{{ item.value.mac_address }}"
# loop: "{{ vm_guest_facts.virtual_machines|dict2items }}"
   - debug: msg="{{ vm_guest_facts.virtual_machines['testvm'].mac_address }}"

but is this way I get an error:

[root@nlnxmi1 testvmcdromiso]# ansible-playbook getvminfo.yml
ERROR! Syntax Error while loading YAML.
did not find expected key

Your debug is indented to far, remove one space.

Problem 2)

Add mac address to existing inventory file or, if not possible, at least in
some file

Just as a stupid test I tried adding the following code at the end:

- set_fact: vm_mac_address="prova"

  - name: Register host to Inventory
    lineinfile:
      path: /etc/ansible/testvmcdromiso/inventory
      regexp: '(testvm)'
      line: '\1 macaddres={{ vm_mac_address }}'
      backrefs: yes [root@nlnxmi1 testvmcdromiso]# cat inventory
  [testhost]
  testvm macaddress=prova

but as you can see I just used a "fixed" string instead I need to get the
mac address from the running vm but never figure it out even after 2 days
of attempts :frowning:

I'm just a beginner with ansible. Could you please help me?

Just remove the set_fact and use the variable directly

   line: '\1 macaddress={{ vm_guest_facts.virtual_machines["\1"].mac_address }}'

Hi Kai

sorry, I just did a bad copy and paste; in reality my playbook is correct about spaces and indentation in fact as I wrote (I posted the complete output) it works using the “loop” statement but, in this way, I’m not able to filter by vm name.
Instead using:

  • debug: msg=“{{
    vm_guest_facts.virtual_machines[‘testvm’].mac_address }}”

the playbook gives me an error.

This is my playbook:

Deploy a guest from a template*

  • hosts: 127.0.0.1
    vars:
    vcenter_hostname: virtvcsami1.virtlab.local
    vcenter_user: administrator@vsphere.local
    vcenter_pass: Esxilab!1
    vcenter_datastore: vsanDatastore
    vcenter_datacenter: DatacenterMI
    tasks:
  • name: Gather VMware guest facts
    vmware_vm_facts:
    validate_certs: False
    hostname: “{{ vcenter_hostname }}”
    username: “{{ vcenter_user }}”
    password: “{{ vcenter_pass }}”
    vm_type: vm
    delegate_to: localhost
    register: vm_guest_facts

- debug: msg=“{{ item.value.mac_address }}”

loop: “{{ vm_guest_facts.virtual_machines|dict2items }}”

  • debug: msg=“{{
    vm_guest_facts.virtual_machines[‘testvm’].mac_address }}”

Could someone test it against a vsphere environment?

Hi guys

Is there someone that coul help on this?

Hi Marco,

Correct if I am wrong.

Your base goal is to achieve adding a host based on the output of vmware_vm_facts in order to communicate or execute some
a function on that VM via ansible.

For that, you can use dynamic host configuration in Ansible. That will add a host dynamically and execute the module based on
your configuration.

If you want any further help regarding please let me know. I will help you.

Regards,
Indian Velumani

Hi indian

Before all thanks for your kind reply.
If you read my post (I hope it is clear enough), basically I need to get ONLY the mac address of a specific VM “testvm”, put it in a variable and, using the regex, add it in a file.
Do you have a vsphere to test my playbook?
Please note that i did lot of internet searches and it seems that the hard part is to make working the folowing code that should do the trick:

debug: msg="{{ vm_guest_facts.virtual_machines['testvm'].mac_address }}" 

Best
Marco

Hi Marco,

Use this below module I already used this. It is working for me.
https://docs.ansible.com/ansible/2.5/modules/vmware_guest_facts_module.html

- name: Gather facts from standalone ESXi server having datacenter as 'ha-datacenter'
  vmware_guest_facts:
    hostname: 192.168.1.209
    username: administrator@vsphere.local
    password: vmware
    datacenter: ha-datacenter
    validate_certs: no
    uuid: 421e4592-c069-924d-ce20-7e7533fab926
  delegate_to: localhost
  register: facts

Hi Indian

ok but do you have any chance to give me the working code about what I’m asking for?

Hi Marco,

Yeah, I can, But I need vm_guest_facts values.

Can you give me the output of below playbook?

Deploy a guest from a template*

  • hosts: 127.0.0.1
    vars:
    vcenter_hostname: virtvcsami1.virtlab.local
    vcenter_user: administrator@vsphere.local
    vcenter_pass: Esxilab!1
    vcenter_datastore: vsanDatastore
    vcenter_datacenter: DatacenterMI
    tasks:

  • name: Gather VMware guest facts
    vmware_vm_facts:
    validate_certs: False
    hostname: “{{ vcenter_hostname }}”
    username: “{{ vcenter_user }}”
    password: “{{ vcenter_pass }}”
    vm_type: vm
    delegate_to: localhost
    register: vm_guest_facts

  • debug: msg=“{{ vm_guest_facts }}”

Thanks,
Indian velumani

I am trying to accomplish a similar task but to add an IP address to the inventory instead of mac.
This works for me to get the IP address displayed in msg. How do you then take the result and send to inventory file? I see you setting fact for the MAC address.
I also am not having any luck passing a variable of vm_name to be used in the query. It can only take the hard coded name.