Ansible playbook : How to get server up or down status - ansible

I'm designing a dashboard for displaying all servers status(up/down),free RAM,Kernel version,Processor type etc using ansible playbook. Using gather facts,I can get all server parameters easily,but not sure how to get server up/down using playbook. If server is down,ansible cannot connect to server hence 'ping' module cannot used. Please help me. IS there any way to catch the return value if playbook fails for any server ?
The order how ansible connects is 1. Make ssh connection 2.if ssh succeeds, gather facts 3. Execute playbook taks one by one. If ping is a task inside playbook, control wont even come to that place and ansible would have thrown connection error in step 1 itself. Please refer below https://docs.ansible.com/ansible/2.4/ping_module.html
Also,please note My inventory contains many servers and I need to get server status of each of them.

You could just use the result of the ping as per comment, or use the wait_for if you want to check a different port:
- hosts: all
tasks:
- wait_for: host=192.168.87.100 port=80 timeout=1
- debug: msg=ok

Related

Ansible host reachability should not determine overall playbook success

A playbook which is gathering uptimes from hosts supplied by an inventory plugin reports failure if any hosts are unreachable; I'd like the PB to stop trying to run tasks against unreachable server - ie the default behaviour - but not fail the playbook as a whole, since it is a likely condition that given the 100s of servers in the inventory, some may have been torn down before the inventory is updated.
The first task in the playbook is setup (aka gather_facts), which is where I want to put the error handling:
- name: get some info about the host
setup:
gather_subset: minimal
ignore_unreachable: true
...
- name: Do something with the facts
write_data:
blah
The intention is that the playbook runs gather_facts, taking note of unreachability, but not allowing that to cause the PB as a whole to be marked as a failure.

Ansible command to trigger registration on another server

I can't find any documentation on how to include a secondary server in a playbook.
If for instance, I want to install sssd on SERVERA and register with a FreeIPA server.
On the FreeIPA server (only), I need to:
get a Kerberos ticket (via kinit)
check if SERVERA is already in IPA instance
delete SERVERA from IPA if true
Since this is an installation playbook run against SERVERA, it doesn't seem right to include the IPA server in the hostlist...but nor can I see any "third party servers" module?
I presume you are searching for the delegate_to option, which allows you to delegate a task to a host that is not in the hostlist.
Often used to run things on the localhost (host running ansible), it can also be used to push a task to a host not in hostlist. The host has to be in the inventory file though.
Example:
- name: Ping the other host
ping:
delegate_to: otherhost.com # This is where you set it
More info: http://docs.ansible.com/ansible/latest/user_guide/playbooks_delegation.html#delegation

Ansible Delegate_to WinRM

I am using the ansible vsphere_guest module to spin up a base windows machine on a VMWare environment. In my playbook, to do this I set Hosts: 127.0.0.1 connection: local. The reason I am doing this is I beleive im not targeting this playbook at any particular host, as I dont have one yet. I instead want to run the playbook locally.
When this runs, I get a new shiny windows server VM. What I now want to do is rename that VM's computer name. To do this I am trying to upload and run a powershell script like so rename_host.ps1 $newHostname. As I understand, I need to use the script module to do this. However, this time I want to target my brand new VM, which I get the IP address of through a fact, {{ newvm_ipaddress }}.
However, when I try and run this script with delegate_to: "{{ newvm_ipaddress}}", its trying to run as SSH. SSH wont work, im targeting a windows machine with remote powershell.
is there any way to set the connection to use winRM in the context of delegate_to? Perhaps there is a better way of doing this?
Thank you for your help
I managed to work out how to solve it. The answer is the ansible module 'add_host'. I have a play under vsphere_guest as follows. This creates a new in memory host, which can then be accessed by a different play.
- add_host group=new_machine name={{ vm_ipaddress }} ansible_connection=winrm
After this, I then have a new play that can now target this host.
- host: new_machine
Also to note, variables do not span across different hosts. The solution was to use the set_fact module in play A, which can then be accessed from within play B
-set_fact:
vm_ipaddress: "{{ hw_eth0.ipaddresses[1] }}" #hw_eth0 is the fact returned from the vsphere_guest module
What about updating the inventory with the new hosts name and with ssh winrm connection params before using delegate_to, or perhaps setting some default catch-all naming scheme with these params?
For example:
[databases]
db-[a:f].example.com:5986 ansible_user=Administrator ansible_connection=winrm ansible_winrm_server_cert_validation=ignore

Ansible execute command locally and then on remote server

I am trying to start a server using ansible shell module with ipmitools and then do configuration change on that server once its up.
Server with ansible installed also has ipmitools.
On server with ansible i need to execute ipmitools to start target server and then execute playbooks on it.
Is there a way to execute local ipmi commands on server running ansible to start target server through ansible and then execute all playbooks over ssh on target server.
You can run any command locally by providing the delegate_to parameter.
- shell: ipmitools ...
delegate_to: localhost
If ansible complains about connecting to localhost via ssh, you need to add an entry in your inventory like this:
localhost ansible_connection=local
or in host_vars/localhost:
ansible_connection: local
See behavioral parameters.
Next, you're going to need to wait until the server is booted and accessible though ssh. Here is an article from Ansible covering this topic and this is the task they have listed:
- name: Wait for Server to Restart
local_action:
wait_for
host={{ inventory_hostname }}
port=22
delay=15
timeout=300
sudo: false
If that doesn't work (since it is an older article and I think I previously had issues with this solution) you can look into the answers of this SO question.

Checking which hosts failed a playbook in ansible

I have 2 playbooks running on ansible, one after another. After playbook 1 finishes, I want to run the second one on only the hosts for which the first playbook fully succeeded. Looking through the ansible docs, I can't find any accessible info on which hosts failed a specific playbook. How could this be done?
FYI I need separate playbooks because the second one must be run with in serial, which is only available at the playbook level
Where all hosts - successful hosts = failed hosts, you can use the following task to get the difference between the two special variables for all hosts in the play (including failed hosts) and all hosts that have not yet failed. Use of serial will affect the result.
- name: Print play hosts that failed
debug:
msg: "The hosts that failed are {{ ansible_play_hosts_all| difference(ansible_play_batch) |join('\n') }}"
Source: https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
Honestly, the best way is to have some queryable state on each host. A simple method is to check for a file's existence, which is created after your first playbook succeeds. You can then have a task which checks for that state and notifies a notify task that it has been "updated", which will get what you want.
In an aside, I stopped using ansible because it wasn't configurable enough; I also had issues getting the parallelism controls I wanted. You my try hitting up the Ansible Project Google Group to put in a feature suggestion or describe your use case.
There is a difference between a play and a playbook. The serial argument is available on the play level. A playbook may contain multiple plays.
---
- name: Play 1
hosts: some_hosts
tasks:
- debug:
- name: Play 2
hosts: some_hosts
serial: 1
tasks:
- debug:
...
Hosts which failed in play 1 will not be processed in play 2.
If your really want to have separate playbooks, I see two options:
Create a callback plugin. You can register a function which gets fired when a task or host fails. You can store this info then locally and use in the next playbook run.
Activate Ansible logging. It will log pretty much the same stuff you see as raw output when running ansible-playbook.
Second option is bit ugly, but easier than creating a callback plugin.
It both cases you then need to create a dynamic inventory script which checks previously saved data and returns valid hosts. Or return all hosts but set a property to mark those hosts. You then can use group_by to create an ad-hoc group.

Resources