Using community.vmware.vmware_guest module to create VM from template by ansible playbook and passing all variables in it as required.
But after creation of VM, it showing dynamic value for mac instead of static value passed and also taking only one ip from list for adapter 1. Remaining IP not getting assigned.
For this situation I can delete mac by using module vmware_guest_network module but still I'm not able to assign IP to it.
Question: Need to have static/dynamic mac with multiple ip on single NIC. Also as per need we can modify value.
Below code but it not working as expected.
(task)
==========
- name: Create VM
community.vmware.vmware_guest:
hostname: "{{ hostname }}"
username: "{{ username }}"
password: "{{ password }}"
datacenter: "{{ center }}"
validate_certs: False
folder: "/{{ center }}/vm"
name: VM1
template: "{{ template }}"
networks:
- name: "{{ network}}
mac: "{{ mac }}"
gateway: "{{ gateway }}"
ip: "{{ nics[0].ips }}"
netmask: "{{ netmask }}"
dns_servers: "{{ dns }}"
state: "{{ vm_state }}"
loop: "{{ nics }}"
delegate_to: localhost
(vars) Value below are for example only
===========================================
nics:
- name: Network Adapter 1
mac: 00:00:00:00:00:00
ips:
- 192.168.1.4
- 192.168.1.9
Related
So, I have a playbook using a hosts file template to update or revert hosts files on 18 specific Linux VMs. The entry which goes at the end of the file looks like:
10.x.x.66 fooconnect
This above example would be on the 1st of 18 VMs, the 18th VM would look like:
10.x.x.83 fooconnect
Normally, that hostname resolves to a VIP. However, we found during some load testing that it may be beneficial to point each front-end VM to a back-end VM directly. So, my goal is to have a playbook that can update what the hostname resolves to with the above mentioned range, or revert it back to the VIP (reverting back is done using a template only--this part works fine).
What I am unsure about is how to implement this in Ansible. Is there a way to loop through the IPs using jinja2 template "for loops?" Or maybe using lineinfile with some loop magic?
Here is my Ansible role example. For the moment I am using a dirty shell command to create my IP list...open to suggestions for a better way to implement this.
- name: Add a line to a hosts file using a template
template:
src: "{{ srcfile }}"
dest: "{{ destfile }}"
owner: "{{ own_var }}"
group: "{{ grp_var }}"
mode: "{{ mode_var }}"
backup: yes
- name: Get the IPs
shell: "COUNTER=66;for i in {66..83};do echo 10.x.x.$i;((COUNTER++));done"
register: pobs_ip
- name: Add a line
lineinfile:
path: /etc/hosts
line: "{{item}} fooconnect" #Ideally would want "item" to just be one IP and not
insertafter: EOF #the entire list as it would be like this.
loop: "{{pobsips}}"
VARs file:
pobsips:
- "{{pobs_ip.stdout}}"
Instead of using a shell task, we can improvise it and create the range of IP addresses using set_fact with range. Once we have the range of IP addresses in a "list", we can loop lineinfile with that and achieve this.
Example:
- name: create a range of IP addresses in a variable my_range
set_fact:
my_range: "{{ my_range|default([]) + [ '10.1.1.' ~ item ] }}"
loop: "{{ range(66, 84)|list }}"
- name: Add a line to /etc/hosts
lineinfile:
path: /etc/hosts
line: "{{ item }} fooconnect"
insertafter: EOF
loop: "{{ my_range }}"
Updated answer:
There is another approach if we want to append only 1 line into the /etc/hosts file of each host with incrementing IP addresses.
For this we can use the ipmath of ipaddr filter to get the next IP address for given IP address.
Use ansible_play_hosts to get the list of hosts on which play is running
Set an index variable index_var and when condition to update file only when the ansible_hostname or inventory_hostname matches.
Run playbook serially and only once on a host per run using serial and run_once flags.
Let's consider an example inventory file like:
[group_1]
host1
host2
host3
host4
...
Then in playbook:
- hosts: group_1
serial: 1
vars:
start_ip: 10.1.1.66
tasks:
- name: Add a line to /etc/hosts
lineinfile:
path: "/tmp/hosts"
line: "{{ start_ip|ipmath(my_idx) }} fooserver"
insertafter: EOF
loop: "{{ ansible_play_hosts }}"
loop_control:
index_var: my_idx
run_once: true
when: item == inventory_hostname
Can't seem to get my second play to catch the package and print that it is not installed. Here is my playbook:
---
- hosts: all
vars:
packages:
- httpd
- unzip
- yum
- nmap
tasks:
- name: getting package facts
package_facts:
manager: auto
- name: Check whether our packages are installed
debug:
msg: "{{ ansible_facts.packages[item][0].name }} {{ ansible_facts.packages[item][0].version }}"
loop: "{{ packages }}"
register: pkgcheck
- name: Display packages not installed
debug:
msg: "{{ pkgcheck }} is not installed"
when: '"pkgcheck" is not defined'
loop: "{{ packages }}"
Use filter difference, e.g.
pkg_not_installed: "{{ packages|difference(ansible_facts.packages.keys()) }}"
For example, use the list in the loop
- name: Display packages not installed
debug:
msg: "{{ item }} is not installed"
loop: "{{ packages|difference(ansible_facts.packages.keys()) }}"
Q: "Is there a way to get both tasks to print my list of installed and not installed?"
A: Use intersect to print installed packages, e.g.
- name: Display installed packages
debug:
msg: "{{ item }} is installed"
loop: "{{ packages|intersect(ansible_facts.packages.keys()) }}"
I have an ansible playbook that is reading in a list of files, and setting a register for those values. I want to then pass the list of files into an include_role task. Below is my current code.
- name: Get list of files
command: "sh -c 'find playbooks/vars/files/*.yml'"
register: find_files
- include_vars:
file: "{{ item }}"
loop: "{{ find_files.stdout_lines }}"
register: result
- name: call role
include_role:
name: myRole
loop: "{{ result.results }}"
When the playbook runs, its finds two files in the directory; file1.yml and file2.yml. But when it runs through the include_role loop, its passes file1.yml twice and never passes file2.yml. Trying to determine how I can ensure file2.yml gets passed to the role as well.
I was able to find the correct my issue by constructing an array and then feeding it into include_role and using the find module instead of shell.
- name: Recursively find yml files
find:
paths: ~/vars
recurse: yes
register: find_files
- name: Construct file array
set_fact:
file_arr: "{{ file_arr|default([]) + [file.path] }}"
with_items: "{{ find_files.files }}"
loop_control:
loop_var: file
- name: Topic Management
include_role:
name: kafkaTopicManagement
vars:
kafkaFiles: "{{ item }}"
with_items: "{{ file_arr }}"
This now feeds the the files into include_role.
Below is the playbook with import_tasks get_hosts.yml for building dynamic hosts in a nested loop. However, I get syntax error running the playbook.
{{ item.split('\t')[0] }} will have ip addresses separated by commas , and then a string seperated by /t
---
- name: "Play 1"
hosts: localhost
tasks:
- name: "Search database"
command: > mysql --user=root --password=p#ssword deployment
--host=localhost -Ns -e "SELECT dest_ip,file_dets FROM deploy_dets"
register: command_result
- name: Add hosts
include_tasks: "{{ playbook_dir }}/gethosts.yml"
dest_ip: "{{ item.split('\t')[0] }}"
groups: dest_nodes
file_dets: "{{ item.split('\t')[1] }}"
ansible_host: localhost
ansible_connection: local
with_items: "{{ command_result.stdout_lines }}"
And below is my get_hosts.yml file
add_host:
name: "{{ item }}"
with_items: "{{ dest_ip.split(',') }}"
Output:
$ ansible-playbook testinclude.yml
ERROR! Syntax Error while loading YAML. did not find expected key
The error appears to be in '/app/deployment/testinclude.yml': line 23, column 8, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
include_tasks: "{{ playbook_dir }}/gethosts.yml"
dest_ip: "{{ item.split('\t')[0] }}"
^ 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 }}"
Can you please suggest
Perhaps you forgot vars parameter, so:
include_tasks: "{{ playbook_dir }}/gethosts.yml"
vars: # <------------------------------------------- HERE
dest_ip: "{{ item.split('\t')[0] }}"
groups: dest_nodes
I have the below vars file and Ansible task which allows some ports for a specific source IPs on the firewall.
But for some reason, whenever I run the task I got this error:
FAILED! => {"msg": "The task includes an option with an undefined variable.
Even though I'm able to echo out these variables using debug Ansible module, so basically I'm just unable to use these variable specifically in this task.
Ansible Task:
---
- name:
firewalld:
permanent: yes
port: "{{ item.0 }}"
state: enabled
zone: public
source: "{{ item.1 }}"
with_nested:
- "{{ ports }}"
- "{{ ips }}"
Vars File:
ports:
- "8000/tcp"
- "9997/tcp"
- "8181/tcp"
- "8080/tcp"
- "8191/tcp"
- "8088/tcp"
- "8065/tcp"
ips:
- "192.168.210.30/32"
- "192.168.210.35/32"
- "192.168.210.40/32"
- "192.168.210.31/32"
- "192.168.210.36/32"
- "192.168.210.41/32"
- "192.168.210.42/32"
- "192.168.210.37/32"
The indentation of with_nested is wrong. Correct syntax is
- name:
firewalld:
permanent: yes
port: "{{ item.0 }}"
state: enabled
zone: public
source: "{{ item.1 }}"
with_nested:
- "{{ ports }}"
- "{{ ips }}"