Integrate a dictionary to all tasks and loop through it in Ansible - ansible

Hey still kind of new with Ansible.
I made a playbook(test) that will perform a rolling update for a Mariadb galera-cluster that uses a HAproxy as lb.
I have no idea how to use the dictionary(bottom of the code) for all my tasks in the play. Also it has to loop like first server 1 then server 3 then server 2 and then server 4. Idea is that if the host or ip changed that you'll only have to change it in the dictionary.
For example task1 needs to use the key.value of host1 same for task2 and when its done loop to the next host.
I tried to use the vars module but it only worked task
specific. Was thinking of using the Vars folder but I'm not using the roles architecture.
- hosts: DBserver
become: yes
tasks:
- name: disable the haproxy server
replace:
path: /etc/haproxy/haproxy.cfg
regexp: "{{ item }}"
replace: 'server "{{}}" "{{}}" check weight 0'
with_items:
- 'server "{{}}" "{{}}" check weight 1'
- hosts: "{{}}"
become: yes
tasks:
- name: stop the mariadb
service:
name: mariadb
state: stopped
- hosts: DBserver
become: yes
tasks:
replace:
path: /etc/haproxy/haproxy.cfg
regexp: "{{ item }}"
replace: 'server "{{}}}" "{{}}" check weight 1'
with_items:
- 'server "{{}}" "{{}}" check weight 0'
dictionary:
{ 'name': 'host1', 'key': 'ipxxx' }, { 'name': 'host2', 'key': 'ipxxxx' }, { 'name': 'host3', 'key': 'ipxxx' }, { 'name': 'host4', 'key': 'ipxxx' }

I solved my problem with this play.
---
- hosts: clients
become: yes
serial: 1
tasks:
- name: disable the haproxy server
replace:
path: /etc/haproxy/haproxy.cfg
regexp: "{{ item }}"
replace: 'server {{ name }} {{ ip }} check weight 0'
with_items:
- 'server {{ name }} {{ ip }} check weight 1'
delegate_to: deploy
- name: stop the mariadb
service:
name: mariadb
state: stopped
- name: update mariadb
apt:
name: "{{ packages }}"
state: latest
update_cache: yes
vars:
packages:
- mariadb-server
- mariadb-client
- mariadb-common
- name: start the mariadb
service:
name: mariadb
state: started
- name: status mariadb
shell: systemctl status mariadb
register: server_status
- name: debug
debug:
msg: "{{ server_status['stdout_lines'] }}"
- name: enable proxy
replace:
path: /etc/haproxy/haproxy.cfg
regexp: "{{ item }}"
replace: 'server {{ name }} {{ ip }} check weight 1'
with_items:
- 'server {{ name }} {{ ip }} check weight 0'
delegate_to: deploy
I used the host_vars and that did the trick in combination with delegate_to.

Related

How to stop VM and Validate that VM is stoped using Ansible?

For my Project, I need to create an Ansible script that does the following:
Shut down VM
Checks that vm are not reachable
Create messages that say what VM is still up and what vm is still down.
I wrote the following script for this:
---
# tasks file for start-stop-vm
- name: Stop all VM
community.general.shutdown:
# delay: 60
when: ('webservers' in group_names)
- name: check what vm is still up
ansible.builtin.ping:
register: result
# - name: Output result
# debug:
# var: result
- name: Return the vm that still running
debug:
msg: "Following VM are still up {{ inventory_hostname }}"
when: (result.failed == false)
- name: Return the vm that still running
debug:
msg: "Following VM are down {{ inventory_hostname }}"
when: (result.failed != false)
My question is, is there any better way to do this?
Is this a VMware-based VM? if that's the case, you can use the vmware modules:
- name: "Shuting down using guest tools"
vmware_guest_powerstate:
hostname: "{{ vcenter_ip }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: False
uuid: "{{ vm_facts.instance.hw_product_uuid }}"
state: shutdown-guest
state_change_timeout: 240
force: yes
delegate_to: "localhost"
register: newState
ignore_errors: yes
when: vm_facts.instance.guest_tools_status == "guestToolsRunning"
- name: "Power off from vCenter"
vmware_guest_powerstate:
hostname: "{{ vcenter_ip }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
validate_certs: False
uuid: "{{ vm_facts.instance.hw_product_uuid }}"
state: powered-off
force: yes
delegate_to: "localhost"
ignore_errors: yes
register: newState
First task tries to poweroff the VM using guest tools
Second task tries to poweroff the VM using the poweroff option from VMWare.
After this two steps, you can get current status for the VM to confirm that the actual state is powered off.

Ansible playbook to check connectivity to windows host and report status

I am trying to put together a playbook that will connect to hosts and report back if the connection was successful or not. The result of the connection check should be stored in a variable. I had a crack at this by using the ansible facts, however I cannot workout how to handle unsuccessful connections to hosts.
---
- name: Set Facts variables
set_fact:
server_domain: "{{ ansible_domain}}"
server_ip: "{{ ansible_ip_addresses[1] }}"
- name: Set PowerShell parameters
set_fact:
ps_params: '-server_ip "{{ ansible_ip_addresses[1] }}" -server_domain "{{ ansible_domain }}"'
- name: Execute Script
win_shell: "powershell.exe -file \\PSfile.ps1 {{ps_params}}"
Try this:
---
- hosts: all
gather_facts: yes
ignore_errors: true
ignore_unreachable: true
vars:
# email_file The filename to attach to the email
# email_recipient email address to send the email to
# email_subject text to appear in the subject line
email_subject: "Windows Server Connection Report for {{ awx_inventory_name }}"
email_file: ./failed_connect_report.csv
ansible_port: 5985
tasks:
- name: Write header and ensure the email file exists
lineinfile:
path: "{{ email_file }}"
line: 'VM Name,IP Address,Distribution,Port,Note,Port,Note'
state: present
mode: '0774'
create: yes
insertafter: EOF
become: no
delegate_to: localhost
run_once: True
when: email_recipient != ''
- name: Test connectivity to port {{ ansible_port }}
win_ping:
register: result
- name: Did we fail to talk to this host?
block:
- set_fact:
ip_addresses: "unknown"
- set_fact:
distribution: "unknown"
- name: Did we fail to talk to this host?
set_fact:
line1: "{{ inventory_hostname }},{{ ip_addresses }},{{ distribution }},{{ ansible_port }},FAILED - {{ result.msg | replace(',',' ') }}"
delegate_to: localhost
- set_fact:
failed1: "True"
when: ((result.unreachable is defined and
result.unreachable == True) or
(result.failed is defined and
result.failed == True)) and
email_recipient != ''
- name: Log the success
set_fact:
line1: "{{ inventory_hostname }},{{ ansible_facts.ip_addresses.0 }},{{ ansible_facts.distribution }},{{ ansible_port }},SUCCESS"
delegate_to: localhost
when: (failed1 is not defined) and
email_recipient != ''

How to change and use a global variable for each host in Ansible?

I am trying to write a playbook to setup mysql master-slave replication with multiple slave servers. For each slave server, I need access to a variable called next_id that should be incremented before use for each host. For example, for the first slave server, next_id should be 2 and for the second slave server it should be 3 and so on. What is the way to achieve this in Ansible?
This is the yaml file I use to run my role.
- name: Setup the environment
hosts: master , slave_hosts
serial: 1
roles:
- setup-master-slave
vars:
master_ip_address : "188.66.192.11"
slave_ip_list :
- "188.66.192.17"
- "188.66.192.22"
This is the yaml file where I use the variable.
- name: Replace conf file with template
template:
src: masterslave.j2
dest: /etc/mysql/mariadb.conf.d/50-server.cnf
when: inventory_hostname != 'master'
vars:
- ip_address : "{{ master_ip_address }}"
- server_id : "{{ next_id }}"
I can suggest a way which will work according to you requirement for any number of slave servers but it is not based on any any module but self conscience.
Here my master_ip_address is 10.x.x.x and input is any value of next_id you want to increment for every slave server
- hosts: master,slave1,slave2,slave3,slave4
serial: 1
gather_facts: no
tasks:
- shell: echo "{{ input }}" > yes.txt
delegate_to: localhost
when: inventory_hostname == '10.x.x.x'
- shell: cat yes.txt
register: var
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- shell: echo "$(({{var.stdout}}+1))"
register: next_id
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- shell: echo "{{ next_id.stdout }}" > yes.txt
delegate_to: localhost
when: inventory_hostname != '10.x.x.x'
- name: Replace conf file with template
template:
src: masterslave.j2
dest: 50-server.cnf
when: inventory_hostname != '10.x.x.x'
vars:
- ip_address : "{{ master_ip_address }}"
- server_id : "{{ next_id.stdout }}"
[ansibleserver#172 test_increment]$ cat masterslave.j2
- {{ ip_address }}
- {{ server_id }}
Now, if you run
ansible-playbook increment.yml -e 'master_ip_address=10.x.x.x input=1'
slave1 server
[root#slave1 ~]# cat 50-server.cnf
- 10.x.x.x
- 2
slave2 server
[root#slave2 ~]# cat 50-server.cnf
- 10.x.x.x
- 3
slave3 server
[root#slave3 ~]# cat 50-server.cnf
- 10.x.x.x
- 4
and so on
"serial" is available in a playbooks only and not working in roles
therefore, for fully automatic generation of server_id for MySQL in Ansible roles, you can use the following:
roles/my_role/defaults/main.yml
---
cluster_alias: test_cluster
mysql_server_id_config: "settings/mysql/{{ cluster_alias }}/server_id.ini"
roles/my_role/tasks/server-id.yml
---
- name: Ensures '{{ mysql_server_id_config | dirname }}' dir exists
file:
path: '{{ mysql_server_id_config | dirname }}'
state: directory
owner: root
group: root
mode: 0755
delegate_to: localhost
- name: Ensure mysql server id config file exists
copy:
content: "0"
dest: "{{ mysql_server_id_config }}"
force: no
owner: root
mode: '0755'
delegate_to: localhost
- name: server-id
include_tasks: server-id-tasks.yml
when: inventory_hostname == item
with_items: "{{ ansible_play_hosts }}"
tags:
- server-id
roles/my_role/tasks/server-id-tasks.yml
# tasks file
---
- name: get last server id
shell: >
cat "{{ mysql_server_id_config }}"
register: _last_mysql_server_id
check_mode: no
delegate_to: localhost
tags:
- server-id
- name: get new server id
shell: >
echo "$(({{_last_mysql_server_id.stdout}}+1))"
register: _new_mysql_server_id
check_mode: no
delegate_to: localhost
tags:
- server-id
- name: save new server id
shell: >
echo -n "{{ _new_mysql_server_id.stdout }}" > "{{ mysql_server_id_config }}"
check_mode: no
delegate_to: localhost
tags:
- server-id
- debug:
var: _new_mysql_server_id.stdout
tags:
- server-id
- name: Replace conf file with template
template:
src: server-id.j2
dest: server-id.cnf

saving variables from playbook run to ansible host local file

I'm sort of trying to build an inventory file from an ansible playbook run.
I'm trying to list out all the kvm hosts and the guests running on them, by running both service libvirtd status and if successful, virsh list --all, and to store the values in a file on the ansible host.
Ive tried a few different playbook structures but none have been successful in writing the file (using local_action wrote the ansible_hostname from just one host).
Please can someone guide me on what I'm doing wrong?
This is what I'm running:
- name: Determine KVM hosts
hosts: all
become: yes
#gather_facts: false
tasks:
- name: Check if libvirtd service exists
shell: "service libvirtd status"
register: libvirtd_status
failed_when: not(libvirtd_status.rc == 0)
ignore_errors: true
- name: List KVM guests
shell: "virsh list --all"
register: list_vms
when: libvirtd_status.rc == 0
ignore_errors: true
- name: Write hostname to file
lineinfile:
path: /tmp/libvirtd_hosts
line: "{{ ansible_hostname }} kvm guests: "
create: true
#local_action: copy content="{{ item.value }}" dest="/tmp/libvirtd_hosts"
with_items:
- variable: ansible_hostname
value: "{{ ansible_hostname }}"
- variable: list_vms
value: "{{ list_vms }}"
when: libvirtd_status.rc == 0 or list_vms.rc == 0
Was able to cobble something that's mostly working:
- name: Check if libvirtd service exists
shell: "service libvirtd status"
register: libvirtd_status
failed_when: libvirtd_status.rc not in [0, 1]
- name: List KVM guests
#shell: "virsh list --all"
virt:
command: list_vms
register: all_vms
when: libvirtd_status.rc == 0
---
- name: List all KVM hosts
hosts: production, admin_hosts, kvm_hosts
become: yes
tasks:
- name: create file
file:
dest: /tmp/libvirtd_hosts
state: touch
delegate_to: localhost
- name: Copy VMs list
include_tasks: run_libvirtd_commands.yaml
- name: saving cumulative result
lineinfile:
line: '{{ ansible_hostname }} has {{ all_vms }}'
dest: /tmp/libvirtd_hosts
insertafter: EOF
delegate_to: localhost
when: groups["list_vms"] is defined and (groups["list_vms"] | length > 0)
Now if only I could clean up the output to filter out false positives (machines that don't have libvirtd status, and have an empty/no list of VMs, because the above doesn't really work.
But at least there is output from all the KVM hosts!

How set ansible function to when modeule?

I want install one of Filebit prospectors only if service redis is running on the host. For that i create default list of prospectors ( redis, aerospike, postgress ) with {{ item.id }}. But right now i want put some expression to "when:" which will install prospector for redis only if it running - how can i do it ?
- name: Configure Filebeat prospectors
template: src=filebeat_conf.yml.j2 dest=/etc/filebeat/conf.d/{{ item.id }}.yml
notify: restart filebeat
with_items: prospectors
when: { " service: " }
Split your task in two: collect facts, act depending on facts.
In your case, you can list installed services first, then configure only existing ones.
For example:
- hosts: test-host
vars:
services:
- name: apache2
id: 1
- name: nginx
id: 2
- name: openvpn
id: 3
tasks:
- name: get list of services
shell: "service --status-all 2>&1 | awk {'print $4'}"
args:
warn: false
register: services_list
- name: process only existing services
debug: msg="service {{ item.name }} with id={{ item.id }} exists"
with_items: "{{ services }}"
when: item.name in services_list.stdout_lines

Resources