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

1,117 views
Skip to first unread message

Marco Reale

unread,
May 22, 2019, 4:55:15 PM5/22/19
to Ansible Project

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: admini...@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 }}"  

---------------------------------


So....I changed my playbook as suggested:


# Deploy a guest from a template*
- hosts: 127.0.0.1
  vars:
    vcenter_hostname: virtvcsami1.virtlab.local
    vcenter_user: admini...@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

The error appears to have been in '/etc/ansible/testvmcdromiso/getvminfo.yml': line 22, column 4, but may be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

#loop: "{{ vm_guest_facts.virtual_machines|dict2items }}"
- debug: msg="{{ vm_guest_facts.virtual_machines['testvm'].mac_address }}"
^ here
We could be wrong, but this one looks like it might be an issue with missing quotes. >Always quote template expression brackets when they
start a value. For instance:

with_items:
- {{ foo }}

Should be written as:

with_items:
- "{{ foo }}"


Unfortunately the user on stackoverflow didn't reply anymore. This mailing list is last chance to get it working.


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 :(

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



Kai Stian Olstad

unread,
May 22, 2019, 5:48:33 PM5/22/19
to ansible...@googlegroups.com
On 22.05.2019 22:55, Marco Reale wrote:
> Problem 1)
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 :(
>
> 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 }}'


--
Kai Stian Olstad

Marco Reale

unread,
May 23, 2019, 3:38:47 AM5/23/19
to ansible...@googlegroups.com
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: admini...@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?


--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/c645873ce363abe78085cd72b468b178%40olstad.com.
For more options, visit https://groups.google.com/d/optout.

Marco Reale

unread,
Jun 5, 2019, 5:32:09 PM6/5/19
to Ansible Project
Hi guys

Is there someone that coul help on this? 

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To post to this group, send email to ansible...@googlegroups.com.

Indian Velumani

unread,
Jun 6, 2019, 3:28:34 AM6/6/19
to ansible...@googlegroups.com
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


Marco Reale

unread,
Jun 6, 2019, 3:06:49 PM6/6/19
to Ansible Project
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



Indian Velumani

unread,
Jun 6, 2019, 3:35:34 PM6/6/19
to ansible...@googlegroups.com
Hi Marco,

Use this below module I already used this. It is working for me.


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



Marco Reale

unread,
Jun 7, 2019, 5:24:47 AM6/7/19
to Ansible Project
Hi Indian

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

Indian Velumani

unread,
Jun 7, 2019, 5:36:20 AM6/7/19
to ansible...@googlegroups.com
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: admini...@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


Philip Isaac

unread,
Aug 28, 2019, 8:59:57 AM8/28/19
to Ansible Project
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.

---
#  Get facts of a VM.
- name: Get facts of "{{ vm_name }}"
  hosts: 127.0.0.1
  gather_facts: false
  connection: local
  become: False
  vars_files:
    - vcenter_vars.yml
  tasks:
    - set_fact:
        vm_name: "{{ vm_name }}"
        datacenter: "{{ datacenter }}"

    - name: Get facts VM
      vmware_vm_facts:
        hostname: "{{ vcenter_hostname }}"
        username: "{{ vcenter_username }}"
        password: "{{ vcenter_password }}"
        validate_certs: no
        vm_type: vm
      delegate_to: localhost
      register: vm_facts

    - debug:
        msg: "{{ item.ip_address }}"
      with_items:
        - "{{ vm_facts.virtual_machines | json_query(query) }}"
      vars:
        query: "[?guest_name== 'awxtest' ]"

To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages