How to start a service by checking host group in inventory by using when statement - ansible

Can some one help me to achieve below.
I have different groups in my inventory file of ansible. I need to execute few commands for one group and few for other group in a single playbook.
I have written playbook like below for single group execution and it is fine but i need to merge everything into single playbook.
---
- name: chekcing Service status
hosts: hari
tasks:
- name : service status
shell: systemctl status "{{item}}"
with_items:
- 'jboss_prod'
Can you please suggest.

For Different task on different group, you can write as below.
---
- hosts: host1
tasks:
- name : service status
shell: systemctl status "{{item}}"
with_items:
- 'jboss_prod'
- hosts: host2
tasks:
- name : service status
shell: systemctl status "{{item}}"
with_items:
- 'apache_prod'
As mentioned in the comments, you can use the systemd module as well for checking the service status. for eg: (from the ansible docs)
- name: Make sure a service is running
systemd:
state: started
name: httpd

Related

Access hosts in play filtered by task

I have a task that checks the redis service status on the host list below
- hosts: 192.168.0.1, 192.168.0.2, 192.168.0.3
tasks:
- command:
cmd: service redis-server status
register: result
- debug:
var: result
After checking I need to access hosts where service does not exist.
And they should be accessible as variable to proceed with them in the next tasks.
Can someone please help?
Similar to Ansible facts it is also possible to gather service_facts. In example
- name: Set facts SERVICE
set_fact:
SERVICE: "redis-server.service"
- name: Gathering Service Facts
service_facts:
- name: Show ansible_facts.services
debug:
msg:
- "{{ ansible_facts.services[SERVICE].status }}"
If you like to perform tasks after on a service of which you don't the status, with Conditionals you can check the state.
If the service is not installed at that time, the specific variable (key) would not be defined. You would perform Conditionals based on variables then
when: ansible_facts.services[SERVICE] is defined
when: ansible_facts.services['redis-server.service'] is defined
Also it is recommend to use the Ansible service module to perform tasks on the service
- name: Start redis-server, if not started
service:
name: redis-server
state: started
instead of using the command module.
Further services related Q&A
How to check service exists and is not installed in the server using service_facts module in an Ansible playbook?
Ansible: How to start stopped services?
Ansible: How to get disabled but running services?
How to list only the running services with ansible_facts?
Finally found the solution that perfectly matches.
- name: Check that redis service exists
systemd:
name: "redis"
register: redis_status
changed_when: redis_status.status.ActiveState == "inactive"
- set_fact:
_dict: "{{ dict(ansible_play_hosts|zip(
ansible_play_hosts|map('extract', hostvars, 'redis_status'))) }}"
run_once: true
- set_fact:
_changed: "{{ (_dict|dict2items|json_query('[?value.changed].key'))| join(',') }}"
run_once: true

Ansible: Failed to restart apache2.service: Connection timed out

I am using Ansible AWX to issue a restart command to restart an apache2 service on a host. The restart command is contained in a playbook.
---
- name: Manage Linux Services
hosts: all
tasks:
- name: Restart a linux service
command: systemctl restart '{{ service_name }}'
register: result
ignore_errors: yes
- name: Show result of task
debug:
var: result
OR
---
- name: Manage Linux Services
hosts: all
tasks:
- name: Restart a linux service
ansible.builtin.service:
name: '{{ service_name }}'
state: restarted
register: result
ignore_errors: yes
- name: Show result of task
debug:
var: result
However, when I run the command, I get the error below:
"Failed to restart apache2.service: Connection timed out",
"See system logs and 'systemctl status apache2.service' for details."
I have tried to figure out the issue, but no luck yet.
I later figured the cause of the issue.
Here's how I fixed it:
The restart command requires sudo access to run which was missing in my command.
All I have to do was to add the become: true command so that I can execute the command with root privileges.
So my playbook looked like this thereafter:
---
- name: Manage Linux Services
hosts: all
tasks:
- name: Restart a linux service
command: systemctl restart '{{ service_name }}'
become: true
register: result
ignore_errors: yes
- name: Show result of task
debug:
var: result
OR
---
- name: Manage Linux Services
hosts: all
tasks:
- name: Restart a linux service
ansible.builtin.service:
name: '{{ service_name }}'
state: restarted
become: true
register: result
ignore_errors: yes
- name: Show result of task
debug:
var: result
Another way if you want to achieve this on Ansible AWX is to tick the Privilege Escalation option in the job template.
If enabled, this runs the selected playbook in the job template as an administrator.
That's all.
I hope this helps
Restarting a service requires sudo privileges. Besides adding the 'become' directive, if you would like to prompt for the password, you can do so by passing the -K flag (note: uppercase K)
$ ansible-playbook myplay.yml -i hosts -u myname --ask-pass -K

How to wait for ssh to become available on a host before installing a role?

Is there a way to wait for ssh to become available on a host before installing a role? There's wait_for_connection but I only figured out how to use it with tasks.
This particular playbook spin up servers on a cloud provider before attempting to install roles. But fails since the ssh service on the hosts isn't available yet.
How should I fix this?
---
- hosts: localhost
connection: local
tasks:
- name: Deploy vultr servers
include_tasks: create_vultr_server.yml
loop: "{{ groups['vultr_servers'] }}"
- hosts: all
gather_facts: no
become: true
tasks:
- name: wait_for_connection # This one works
wait_for_connection:
delay: 5
timeout: 600
- name: Gather facts for first time
setup:
- name: Install curl
package:
name: "curl"
state: present
roles: # How to NOT install roles UNLESS the current host is available ?
- role: apache2
vars:
doc_root: /var/www/example
message: 'Hello world!'
- common-tools
Ansible play actions start with pre_tasks, then roles, followed by tasks and finally post_tasks. Move your wait_for_connection task as the first pre_tasks and it will block everything until connection is available:
- hosts: all
gather_facts: no
become: true
pre_tasks:
- name: wait_for_connection # This one works
wait_for_connection:
delay: 5
timeout: 600
roles: ...
tasks: ...
For more info on execution order, see this title in role's documentation (paragraph just above the notes).
Note: you probably want to move all your current example tasks in that section too so that facts are gathered and curl installed prior to do anything else.

Ansible playbook example code fail to run

I'm started to try Ansible, and using example code from Ansible Documentation. After I try several examples, I get error at the beginning of the code. It says
- name: Change the hostname to Windows_Ansible
^ here(Point at name)"
Any advice would be appreciate.
I tried this one
https://docs.ansible.com/ansible/latest/modules/win_hostname_module.html#win-hostname-module
---
- name: Change the hostname to Windows_Ansible
win_hostname:
name: "Windows_Ansible"
register: res
- name: Reboot
win_reboot:
when: res.reboot_required
The below task will change the hostname of the server. Make sure you run on a test server so that it wont create issues. If you just wanted to test some playbook, use the second playbook with win_command
---
- hosts: <remote server name which needs to be added in the inventory>
tasks:
- name: Change the hostname to Windows_Ansible
win_hostname:
name: "Windows_Ansible"
register: res
- name: Reboot
win_reboot:
when: res.reboot_required
---
- hosts: <remote server name which needs to be added in the inventory>
tasks:
- name: Test
win_command: whoami
register: res

Ansible: Start service in next host after service finished starting on previous host

I have three hosts in which I want to start a service in a rolling fashion. The host 2 needs to wait for the service to finish starting on host 1, and host 3 needs to wait for service on the host 2.
Host 1 has finished starting the service when a line with an instruction like:
Starting listening for CQL clients
is written to a file.
How can I instruct Ansible (service module preferably) only to start the following host, when the service on the previous host writes the line to that file?
you'll probably need to break your playbook down a bit, for example
Your restart.yml contents:
- service:
name: foobar
state: restarted
- wait_for:
search_regex: "Starting listening for CQL clients"
path: /tmp/foo
and then your main.yml contents:
- include_tasks: restart.yml
with_items:
- host1
- host2
- host3
https://docs.ansible.com/ansible/latest/modules/wait_for_module.html
It seems it's not possible to serialize at a task level. So I had to build another playbook specific to start the service and used serial: 1 in the playbook yaml.
My files now look like this:
roles/start-cluster/tasks/main.yaml
- name: Start Cassandra
become: yes
service:
name: cassandra
state: started
- name: Wait for node to join cluster
wait_for:
search_regex: "Starting listening for CQL clients"
path: /var/log/cassandra/system.log
start-cluster.yaml
- hosts: all
serial: 1
gather_facts: False
roles:
- start-cluster

Resources