Async/Poll & Notify: Ansible Long running process

Saurabh Sharma

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_lines

In 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 | changed

In 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.sh

In 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

Leave a Reply

Your email address will not be published. Required fields are marked *