Async/Poll & Notify: Ansible Long running process

ASYNC & Poll
Recently during our discussion with a client a problem was raised how to show progress for a long running Ansible playbook task & this blog is just an outcome of the things I tried and delivered.
Ansible is a powerful automation tool that allows you to automate tasks across multiple hosts. However, some tasks can take a long time to complete, which can leave users wondering if the task is still running or if it has completed successfully. To provide feedback during long running tasks, Ansible provides several modules, including async, poll, and notify.
async and poll Options in Ansible:
The async option allows you to run a task asynchronously, which means that it will run in the background and Ansible will not wait for it to complete before moving on to the next task. This can be useful for long running tasks, as it allows Ansible to continue running other tasks while the long running task is in progress.
The poll option specifies how often Ansible should check the status of the asynchronous task. By default, Ansible will check the status every 10 seconds. You can adjust this value to suit your needs.
Here’s an example playbook that uses the async and poll options to provide feedback during a long running task:
- name: Long Running Task
command: /path/to/long_running_task.sh
async: 300
poll: 60
register: task_result
- name: Check Task Status
async_status:
jid: "{{ task_result.ansible_job_id }}"
register: task_status
until: task_status.finished
- name: Task Output
debug:
var: task_status.stdout_linesIn this example, the command module is used to run a long running task. The async option is set to 300, which means that the task will run asynchronously for up to 300 seconds (5 minutes). The poll option is set to 60, which means that Ansible will check the status of the task every 60 seconds.
The register keyword is used to capture the output of the command module in a variable called task_result.
After the task has been started, the async_status module is used to check the status of the task. The jid option is set to the ansible_job_id of the long running task. The until keyword is used to keep checking the status of the task until it has finished.
Finally, the stdout_lines of the task output are printed using the debug module.
With this playbook, users will be able to see the progress of the long running task and know when it has completed successfully.
notify Module in Ansible:
The notify module in Ansible allows you to send a notification to a handler at the end of a task. This can be useful for providing real-time feedback during long running tasks.
Here’s an example playbook that uses the notify module to provide feedback during a long running task:
- name: Long Running Task
command: /path/to/long_running_task.sh
async: 300
poll: 60
register: task_result
notify: Update Status
- name: Wait for Task to Complete
async_status:
jid: "{{ task_result.ansible_job_id }}"
register: task_status
until: task_status.finished
- name: Task Output
debug:
var: task_status.stdout_lines
- name: Update Status
debug:
msg: "Task is still running"
run_once: true
when: task_result | changedIn this example, the notify module is used to call a task named Update Status for every poll. The run_once option is set to true, which means that the task will only be run once.
Example
Let’s consider the following scenario: We have a web application running on a remote server. The application requires a database to function properly. We want to automate the process of creating a new database, configuring it, and starting the application. This process can take several minutes to complete. We want to provide feedback to the user about the status of the task during the process.
To solve this problem, we can use the async, poll, and notify modules in Ansible.
First, we create a playbook that contains the following tasks:
- name: Create database
command: create_database.sh
async: 3600
poll: 30
register: db_task
notify: Update Status
- name: Configure database
command: configure_database.sh
async: 3600
poll: 30
register: config_task
notify: Update Status
- name: Start application
command: start_application.sh
async: 3600
poll: 30
register: app_task
notify: Update Status
- name: Check database status
command: check_database_status.shIn this playbook, we have three tasks that create a database, configure it, and start the application. We have set the async option to 3600 seconds (1 hour), which means that the task will run asynchronously for up to 1 hour. We have set the poll option to 30 seconds, which means that Ansible will check the status of the task every 30 seconds.
We have also registered the output of each task in a variable (i.e., db_task, config_task, and app_task). This will allow us to check the status of each task later.
Finally, we have a task that checks the status of the database.
Next, we create a handler that will be called by the notify module:
- name: Update Status
debug:
msg: "{{ ansible_job_id }}: {{ lookup('pipe', 'tail -1 /proc/' + ansible_job_id + '/stat') }}"
run_once: true
when: db_task | changed or config_task | changed or app_task | changed
This handler will print a message to the console every time one of the tasks changes status. The message will contain the Ansible job ID and the status of the task. We have set the run_once option to true, which means that the handler will only be run once even if there are multiple hosts.
Finally, we have used the when keyword to run the Update Status task only if one of the tasks has changed since the last poll. This means that the task will only be run if there is new progress to report.
Explanation
When we run this playbook, Ansible will execute each task asynchronously. This means that Ansible will not wait for the task to complete before moving on to the next task.
The poll option specifies how often Ansible should check the status of the asynchronous task. In our example, Ansible will check the status every 30 seconds.
The notify module is used to call a handler named Update Status for every poll. The when keyword is used to run the Update Status task only if one
Help
- Ansible ASYNC
