How do I check the succesfull retry with separate command in ansible? - ansible

Ansible 2.9.6
There is standard way to use retry in Ansible.
- name: run my command
register: result
retries: 5
delay: 60
until: result.rc == 0
shell:
cmd: >
mycommand.sh
until is a passive check here.
How can I do the check with the separate command? Like "retry command A several times until command B return 0"
Of cause I may put both commands inside shell execution "commandA ; commandB" and I will get exit status of the second one for the result.rc. But is any Ansible way to do this?

The ansible way would point towards retries over a block or include that contains a command task for each script. However, that's not supported. You can use a modified version of the workaround described here, though, but it starts to get complicated. Therefore, you may prefer to take Zeitounator's suggestion.

Related

How to run 1 playbook for the same group by multiple plays aka threaded

Current setup that we do have ~2000 servers (in 1 group)
I would like to know if there is a way to run x.yml on all the group (where all the 2k servers are in ) but with multiple plays (threaded , or something)
ansible-playbook -i prod.ini -l my_group[50%] x.yml
ansible-playbook -i prod.ini -l my_group[other 50%] x.yml
solutions with awx or ansible-tower are not relevant.
using even 500-1000 forks didn't gave any improvement
try to combine forks, and the free strategy.
the default behavior of Ansible is:
Ansible runs each task on all hosts affected by a play before starting the next task on any host, using 5 forks.
So event if your increase the forks number, the tasks on special forks will still wait any host finish to go ahead. The free strategy allows each host to run until the end of the play as fast as it can
- hosts: all
strategy: free
tasks:
# ...
ansible-playbook -i prod.ini -f 500 -l my_group x.yml
As mentioned above, you should preferably increase fork and set the strategy to free. Increasing fork will help you run the playbook on more server and setting the strategy to free would allow you to run a task for servers independently without waiting for others.
Please refer to below doc for more clarifaction.
docs
resolved by using patterns my_group[:1000] and my_group[999:]
forks didnt give any time decrease in my case.
also free strategy did multiplied the time which was pretty weird.
also debugging free strategy summary is free difficult when u have 2k servers and about 50 tasks in playbook .
thanks everyone for sharing
much appreciated

Ansible expect when command asks twice the same question

I'm trying to automate VirtualGL configuration using command vglserver_config. This script uses this menu :
1) Configure server for use with VirtualGL (GLX + EGL back ends)
2) Unconfigure server for use with VirtualGL (GLX + EGL back ends)
3) Configure server for use with VirtualGL (EGL back end only)
4) Unconfigure server for use with VirtualGL (EGL back end only)
X) Exit
Choose:
I need to feed two different answers to the "Choose:" question :
'1' first time, to configure VirtualGL, followed by actual responses of configuration script (see below)
'x' when exiting the command
Here's the task I've come to:
- name: configure VirtualGL (vglserver_config)
ansible.builtin.expect:
command: "{{ vglserver_config_cmd }}"
responses:
(.*)Choose:(.*): 1
(.*)Continue?(.*): y
(.*)Restrict 3D X server access to vglusers group (recommended)?(.*): y
(.*)Restrict framebuffer device access to vglusers group (recommended)?(.*): y
(.*)Disable XTEST extension (recommended)?(.*): y
(.*)Choose:(.*): x
This does not work: as the entry (.*)Choose!(.*): is duplicated (Ansible complains about that), the command is answered 'X' by expect module, and thus nothing happen.
I tried an alternative code:
- name: configure VirtualGL (vglserver_config)
ansible.builtin.expect:
command: "{{ vglserver_config_cmd }}"
responses:
Question:
- 1
- y
- y
- y
- y
- x
But this syntax is incorrect. Ansible throws an error.
How can I solve this issue ?
Thx !
Jose
PS. Edited the 2nd code example to reflect the exact one I also tested (same error raised by Ansible)
Ok...
Why would I want to use expect module for a command that has unattended mode parameters...
I'm so dumb.
I've changed the "expect" task to a "command" with proper parameters.

How to if/else properly in Ansible and registering variables parallelly

what I am trying to do is to register variables accordingdly. I am pinging an interface and then I try to verify if the ping was successful or not. However my code is not working the way I have imagined. I simplify it to following sample:
- name: Verify ping
ansible.builtin.shell: echo "yes it is online"
register: tmp
when: ping_output is search("5/5")
- name: Verify ping
ansible.builtin.shell: echo "no it is offline"
register: tmp
when: ping_output is search("0/5")
The variable ping_output was registered before in the previous tasks. Well what I have observed during my tests is that when I want to evaluate my variable tmp it is not set sometimes. This happens when the first conditional is true. Then tmp.stdout is set to "yes its online". Even if ansible is skipping the next conditional ("the else statement"), however it unsets the variable tmp.stdout and at some point I receive tmp.stdout is not defined. Do you have better suggestions how to solve it?
Thanks in advance
EDIT:
Hi, thanks for the review. I'm trying to store information into variables and yes right, later I reference to tmp.stdout. I actually ping from a Cisco device and save the output. There are several pings, so several outputs. Then there are tasks which evaluate these outputs. The goal is to prepare an appropriate description which I send via JSON as an API call. What the enduser sees in the end, is a description in an external trouble ticketing system with information like which interfaces were pingable, which were not etc

How to check a log for a string and verify app status?

I am a newbie to Ansible and I want to verify if an application (non service) is running, if not, start it. So basically look for the output of "splunkd is running".
Output of 'status' command is
splunkd is running (PID: 15111).
splunk helpers are running (PIDs: 15214 15420 15431 15500).
Also want to check said app's log file for a string "does not exists!" and if it exists restart app (until that string no longer exists in log - the log currently does rotate upon restart). The servers in question only exists in Production and I don't feel too comfortable executing code there for the 1st time. Below is what I have so far, I feel like the 1st block and 3rd block need editing. Thanks for any assistance and feedback!
- name: Splunk status
command: sudo /splunk/bin/splunk status
changed_when: false
- name: Read log
shell: cat /splunk/log/splunkd.log
register: splunk_log
- name: Restart if "does not exists!", exists
command: sudo /splunk/bin/splunk restart
until: splunk_log.stdout.find('does not exists!') == 0
#when: splunk_log.stdout.find('does not exists!') != -1
debug: msg="does not exists! exists, restarting"
retries: 5
delay: 60
I don't understand the first task but I think you're trying to do something like this example of changed_when. Also, for task three follow this when-statement.

Use ansible for manual staged rollout using `serial` and unknown inventory size

Consider an Ansible inventory with an unknown number of servers in a nodes key.
The script I'm writing should be usable with different inventories that should be as simple as possible and are out of my control, so I don't know the number of nodes ahead of time.
My command to run the playbook is pretty vanilla and I can freely change it. There could be two separate commands for both rollout stages.
ansible-playbook -i $INVENTORY_PATH playbooks/example.yml
And the playbook is pretty standard as well and can be adjusted:
- hosts: nodes
vars:
...
remote_user: '{{ sudo_user }}'
gather_facts: no
tasks:
...
How would I go about implementing a staged execution without changing the inventory?
I'd like to run one command to execute the playbook for 50% of the inventory first. Here the result needs to be checked manually by a human. Then I'd like to use another command to execute the playbook for the other half. The author of the inventory should not have to worry about this. All machines below the nodes key are the same.
I've looked into the serial keyword, but it doesn't seem like I could automatically end execution after one batch and then later come back to continue with the second half.
Maybe something creative could be done with variables passed to ansible-playbook? I'm just wondering, shouldn't this be a common use-case? Are all staged rollouts supposed to be fully automated?
Without even using serial here is a possible very simple scenario.
First get a calculation of $half of the inventory by inspecting the inventory itself. The following is enabling the json callback plugin for the ad hoc command and making sure it is the only plugin enabled. It is also using jq to parse the result. You can adapt to any other json parser (or even use the yaml callback with a yaml parser if your prefer). Anyway, adapt to your own needs.
half=$( \
ANSIBLE_LOAD_CALLBACK_PLUGINS=1 \
ANSIBLE_STDOUT_CALLBACK=json \
ANSIBLE_CALLBACK_WHITELIST=json \
ansible localhost -i yourinventory.yml -m debug -a "msg={{ (groups['nodes'] | length / 2) | round(0, 'ceil') | int }}" \
| jq -r ".plays[0].tasks[0].hosts.localhost.msg" \
)
Then launch your playbook limiting to the first $half nodes with whatever vars are needed for human check, and launch it again for the remainder nodes without check.
ansible-playbook -i yourinventory.yml example_playbook.yml -l nodes[0:$(($half-1))] -e human_check=true
ansible-playbook -i yourinventory.yml example_playbook.yml -l nodes[$half:] -e human_check=false

Resources