Can ansible create a dict using the common values from a list and a dict? - ansible

In ansible, the vmware_guest_info module will give us a list of the tags on a vm, but does not include any information about those tags:
"tags": [
"10.16.3",
"dicky",
"develop"
],
The vmware_tag_info module gives us a dict withinfo on those tags, including description and Id, but NOT the tags name:
"10.16.3": {
"tag_category_id": "urn:vmomi:InventoryServiceCategory:6eb9d643-8fa3-42a1-8b50-78a1c6e99867:GLOBAL",
"tag_description": "10.16.3",
"tag_id": "urn:vmomi:InventoryServiceTag:ca46ab80-be91-4c3a-8f9f-019d163dd954:GLOBAL",
"tag_used_by": []
},
The vmware_category_info module gives us a list that includes ID and name of a tag.
"tag_category_info": [
{
"category_associable_types": [],
"category_cardinality": "SINGLE",
"category_description": "nodeVersion",
"category_id": "urn:vmomi:InventoryServiceCategory:6eb9d643-8fa3-42a1-8b50-78a1c6e99867:GLOBAL",
"category_name": "nodeVersion",
"category_used_by": []
},
]
So it seems I need to combine the output of three different lists to get the tag value, tag name and tag ID.
I really hope that someone has already done this. If not, can anyone shed some light on how to iterate over the output of vmware_tag_info and vmware_category_info, and find when tag_category_id matches category_id?

How about this?
---
- name: Example playbook
hosts: localhost
gather_facts: no
vars:
vcenter_hostname: change me
vcenter_username: administrator#vsphere.local
vcenter_password: change me
dc1: change me
vm_name: change me
tasks:
- name: Gather tags information
vmware_tag_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
register: tags_info_result
- name: Gather tags category information
vmware_category_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
register: tags_category_info_result
- name: Set tags_information variable
set_fact:
tags_information: >-
{{ tags_information | default({})
| combine({
item.key: tags_category_info_result.tag_category_info
| selectattr('category_id', '==', item.value.tag_category_id)
| list
| first
| combine(item.value)
| combine({'tag_name': item.key})
})
}}
with_dict: "{{ tags_info_result.tag_facts }}"
- name: Gather VM information
vmware_guest_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
datacenter: "{{ dc1 }}"
name: "{{ vm_name }}"
tags: true
register: vm_info_result
- name: Display VM tags information
debug:
msg:
- "tags information about {{ vm_name }}"
- "{{ tags_information[item] }}"
loop: "{{ vm_info_result.instance.tags }}"
when:
- "'tags' in vm_info_result.instance"

Related

Ansible variables question from output and filtered with json_query

I am trying to get the pertinent fields from a vmware module output, I am filtering with json, but the says my variable target_vm_name is undefined. how do I get a variable with only the matching criteria which is filtered by the ip address of the list of hosts I want to iterate through?
code is below:
- name: Loop thru hosts and get IPs
hosts: rpa_test
vars:
ip_addr:
"{{ lookup('dig', ansible_host) }}"
tasks:
- debug:
msg: "System {{ inventory_hostname }} has ip address of {{ ip_addr }}"
- name: get vm info based on ip
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vault_vcenter_admin_name }}"
password: "{{ vault_vcenter_admin_password }}"
validate_certs: False
delegate_to: localhost
register: vm_info
vars:
target_vm_name: "{{ vm_info.virtual_machines | json_query(query) }}"
query: "[?ip_address=={{ ip_addr }}]"
- debug:
msg: "{{ target_vm_name.virtual_machines.guest_name }}"
vars is not at the right place inside the community.vmware.vmware_vm_info task ,
you should put it in the debug task:
tasks:
- debug:
msg: "System {{ inventory_hostname }} has ip address of {{ ip_addr }}"
- name: get vm info based on ip
community.vmware.vmware_vm_info:
hostname: "{{ vcenter_hostname }}"
username: "{{ vault_vcenter_admin_name }}"
password: "{{ vault_vcenter_admin_password }}"
validate_certs: False
delegate_to: localhost
register: vm_info
- debug:
msg: "{{ target_vm_name.virtual_machines.guest_name }}"
vars:
target_vm_name: "{{ vm_info.virtual_machines | json_query(query) }}"
query: "[?ip_address=={{ ip_addr }}]"

Ansible VMWare not clean datastore

I wrote 2 Ansible playbooks to create and destroy a vm inside an ESXi instance.
The create task is:
- name: Clone the template
delegate_to: localhost
community.vmware.vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
cluster: "{{ vcenter_cluster_name }}"
datacenter: "{{ vcenter_datacenter_name }}"
folder: "{{ vcenter_datacenter_folder }}"
datastore: "{{ vcenter_datastore }}"
validate_certs: False
name: "{{ inventory_hostname }}"
template: "{{ vm_template }}"
state: poweredon
wait_for_ip_address: yes
networks:
- name: "DSwitch_Dati-VM Network 869"
ip: "{{ ansible_host }}"
netmask: "{{ vm_netmask }}"
gateway: "{{ vm_gateway }}"
start_connected: yes
The delete playbook is:
- name: TMS Cleaner
hosts: all
remote_user: tms
tasks:
- name: Set powerstate of virtual machine to poweroff
delegate_to: localhost
community.vmware.vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: False
name: "{{ inventory_hostname }}"
state: poweredoff
- name: Remove virtual machine from inventory
delegate_to: localhost
community.vmware.vmware_guest:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
folder: "{{ vcenter_datacenter_folder }}"
datastore: "{{ vcenter_datastore }}"
validate_certs: False
name: "{{ inventory_hostname }}"
delete_from_inventory: True
state: absent
The creation is correct, while deletion can correctly stop and remove the vm BUT it doeas not remove the folder from the datastore.
What should I do to have a full deletion of all files related to a vm?
If you want to have the files deleted also from datastore you need to remove the following line:
delete_from_inventory: True
The ansible documentation for this module says:
delete_from_inventory:
Choices: Whether to delete Virtual machine from inventory or delete from disk.
no | yes
Only remove that line and files will be deleted from datastore.

YAML: “Unsupported parameters for ansible module"

i get the below error when try this as below:
"msg": "Unsupported parameters for (vmware_vm_vm_drs_rule) module: delegate_to Supported parameters include: affinity_rule, cluster_name, drs_rule_name, enabled, hostname, mandatory, password, port, proxy_host, proxy_port, state, username, validate_certs, vms".
I dont want my module to execute when the final_list is empty or less than one object. Only if its more than 2 object in final_list i would want it to execute. Could someone help me with the correct condition
"ansible_facts": {"final_list": [ "NPSY7ADFS01"]}
"ansible_facts": {"final_list": []}
- name: Create DRS Anti Affinity Rule for VM-VM
vmware_vm_vm_drs_rule:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
cluster_name: "{{ datacenter_name }}-{{ cluster_name }}"
validate_certs: no
vms: "{{ final_list }}"
drs_rule_name: "{{ rule_name }}"
enabled: True
mandatory: True
affinity_rule: "{{ action_type }}"
delegate_to: localhost
register: rule_creation
when: final_list is defined
Q: "Unsupported parameters for (vmware_vm_vm_drs_rule) module: delegate_to ... "
A: The error message is clear: "delegate_to is not a parameter of vmware_vm_vm_drs_rule". The indentation of delegate_to is wrong. This is the reason why delegate_to has been considered a parameter of the module. Fix the indentation of delegate_to
- name: Create DRS Anti Affinity Rule for VM-VM
vmware_vm_vm_drs_rule:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
cluster_name: "{{ datacenter_name }}-{{ cluster_name }}"
validate_certs: no
vms: "{{ final_list }}"
drs_rule_name: "{{ rule_name }}"
enabled: True
mandatory: True
affinity_rule: "{{ action_type }}"
delegate_to: localhost
register: rule_creation
when: final_list is defined
FWIW. Use ansible-lint to validate the syntax.
Q: "I don't want the module to execute when the final_list is empty."
A: Try this
when: final_list|default([])|length > 0

VMWare Authentication with Ansible module

Do I have to call hostname,Username and password field for all the individual task that I use with VMware module for Eg: if I call a task for Finding folder of VM and next for snapshot. Do we have an option to get authenticated and then parse token like we do with uri module ?
- name: Find Guest's Folder using name
vmware_guest_find:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: no
name: "{{ inventory_hostname }}"
delegate_to: localhost
register: vm_folder
You can use module_defaults to achieve what you want.
For instance:
- hosts: localhost
module_defaults:
vmware_guest_find:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
tasks:
- name: Find Guest's Folder using name
vmware_guest_find:
validate_certs: no
name: "{{ inventory_hostname }}"

Looping in hostvars

I'm wondering if it is possible to perform a loop in the hostvars folder when using Ansible?
Here is what I've tried but haven't had success in making it work - or is it just not possible to do?
---
list_pool: 'list ltm pool {{ items }}'
with_items:
- 'abc123'
- 'def456'
I would use the "list_pool" variable in a playbook afterward:
- name: List pool
bigip_command:
server: "{{ some_server }}"
user: "{{ some_user }}"
password: "{{ some_password }}"
commands:
- "{{ list_pool }}"
validate_certs: no
delegate_to: localhost
Not sure what you mean when you say you want to loop over hostvars folder.
From what I can interpret from your tasks is: "You need to execute big-ip command list ltm <pool-name> for multiple pools in the list list_pool"
If that's what you're after, this should work:
- name: Set list_pool fact
set_fact:
list_pool: "{{ list_pool | default([]) + [item] }}"
with_items:
- 'abc123'
- 'def456'
- name: List pool
bigip_command:
server: "{{ some_server }}"
user: "{{ some_user }}"
password: "{{ some_password }}"
commands:
- "list ltm {{ item }}"
validate_certs: no
delegate_to: localhost
with_items: "{{ list_pool }}"
I got this working with the following solution:
hostvars file would look like this:
---
pre_checks:
checks:
pool:
- name: "pool_123"
- name: "pool_456"
...
And the play would look like this:
--output truncated---
- name: Fetch device host_vars
set_fact:
device_config: "{{ ((lookup('file','{{playbook_dir}}/host_vars/{{inventory_hostname}}.yml')) | from_yaml) }}"
- name: Check pool
bigip_command:
server: "{{ inventory_hostname }}"
user: "{{ remote_username }}"
password: "{{ remote_passwd }}"
commands:
- "list ltm pool {{ item }}"
validate_certs: no
with_items:
- "{{ device_config.pre_checks | json_query('checks.pool[*].name') }}"
delegate_to: localhost
when: "'active' in Active_LTM['stdout'][0]"
register: Pre_Checks
- name: Verify pool
debug: var=item
with_items: "{{ Pre_Checks.results | map(attribute='stdout_lines') | list }}"

Resources