{"id":2542,"date":"2023-03-24T18:28:38","date_gmt":"2023-03-24T18:28:38","guid":{"rendered":"https:\/\/blog.samarthya.me\/wps\/?p=2542"},"modified":"2023-03-24T18:28:40","modified_gmt":"2023-03-24T18:28:40","slug":"async-poll-notify-ansible-long-running-process","status":"publish","type":"post","link":"https:\/\/blog.samarthya.me\/wps\/2023\/03\/24\/async-poll-notify-ansible-long-running-process\/","title":{"rendered":"Async\/Poll &#038; Notify: Ansible Long running process"},"content":{"rendered":"\n<div class=\"wp-block-cover is-light\"><span aria-hidden=\"true\" class=\"wp-block-cover__background has-background-dim\"><\/span><img fetchpriority=\"high\" decoding=\"async\" width=\"408\" height=\"131\" class=\"wp-block-cover__image-background wp-image-2543\" alt=\"\" src=\"https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2023\/03\/as-async.png\" data-object-fit=\"cover\" srcset=\"https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2023\/03\/as-async.png 408w, https:\/\/blog.samarthya.me\/wps\/wp-content\/uploads\/2023\/03\/as-async-300x96.png 300w\" sizes=\"(max-width: 408px) 100vw, 408px\" \/><div class=\"wp-block-cover__inner-container is-layout-flow wp-block-cover-is-layout-flow\">\n<p class=\"has-text-align-center has-white-color has-text-color has-x-large-font-size\">ASYNC &amp; Poll<\/p>\n<\/div><\/div>\n\n\n\n<p>Recently during our discussion with a client a problem was raised how to show progress for a long running <code>Ansible<\/code> playbook task &amp; this blog is just an outcome of the things I tried and delivered.<\/p>\n\n\n\n<p><code>Ansible<\/code> 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 <code>async<\/code>, <code>poll<\/code>, and <code>notify<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>async<\/code> and <code>poll<\/code> Options in <code>Ansible<\/code>:<\/h2>\n\n\n\n<p>The <code>async<\/code> option allows you to run a task asynchronously, which means that it will run in the background and <code>Ansible<\/code> 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.<\/p>\n\n\n\n<p class=\"has-medium-font-size\">The <code>poll<\/code> 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.<\/p>\n\n\n\n<p>Here&#8217;s an example playbook that uses the <code>async<\/code> and <code>poll<\/code> options to provide feedback during a long running task:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>- name: Long Running Task\n  command: \/path\/to\/long_running_task.sh\n  async: 300\n  poll: 60\n  register: task_result\n\n- name: Check Task Status\n  async_status:\n    jid: \"{{ task_result.ansible_job_id }}\"\n  register: task_status\n  until: task_status.finished\n\n- name: Task Output\n  debug:\n    var: task_status.stdout_lines<\/code><\/pre>\n\n\n\n<p>In this example, the <code>command<\/code> module is used to run a long running task. The <code>async<\/code> option is set to 300, which means that the task will run asynchronously for up to 300 seconds (5 minutes). The <code>poll<\/code> option is set to 60, which means that Ansible will check the status of the task every 60 seconds.<\/p>\n\n\n\n<p>The <code>register<\/code> keyword is used to capture the output of the <code>command<\/code> module in a variable called <code>task_result<\/code>.<\/p>\n\n\n\n<p>After the task has been started, the <code>async_status<\/code> module is used to check the status of the task. The <code>jid<\/code> option is set to the <code>ansible_job_id<\/code> of the long running task. The <code>until<\/code> keyword is used to keep checking the status of the task until it has finished.<\/p>\n\n\n\n<p>Finally, the <code>stdout_lines<\/code> of the task output are printed using the <code>debug<\/code> module.<\/p>\n\n\n\n<p>With this playbook, users will be able to see the progress of the long running task and know when it has completed successfully.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>notify<\/code> Module in <code>Ansible<\/code>:<\/h2>\n\n\n\n<p>The <code>notify<\/code> 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.<\/p>\n\n\n\n<p>Here&#8217;s an example playbook that uses the <code>notify<\/code> module to provide feedback during a long running task:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>- name: Long Running Task\n  command: \/path\/to\/long_running_task.sh\n  async: 300\n  poll: 60\n  register: task_result\n  notify: Update Status\n\n- name: Wait for Task to Complete\n  async_status:\n    jid: \"{{ task_result.ansible_job_id }}\"\n  register: task_status\n  until: task_status.finished\n\n- name: Task Output\n  debug:\n    var: task_status.stdout_lines\n\n- name: Update Status\n  debug:\n    msg: \"Task is still running\"\n  run_once: true\n  when: task_result | changed<\/code><\/pre>\n\n\n\n<p>In this example, the <code>notify<\/code> module is used to call a task named <code>Update Status<\/code> for every poll. The <code>run_once<\/code> option is set to true, which means that the task will only be run once.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p>Let&#8217;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.<\/p>\n\n\n\n<p>To solve this problem, we can use the <code>async<\/code>, <code>poll<\/code>, and <code>notify<\/code> modules in Ansible.<\/p>\n\n\n\n<p>First, we create a playbook that contains the following tasks:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>- name: Create database\n  command: create_database.sh\n  async: 3600\n  poll: 30\n  register: db_task\n  notify: Update Status\n\n- name: Configure database\n  command: configure_database.sh\n  async: 3600\n  poll: 30\n  register: config_task\n  notify: Update Status\n\n- name: Start application\n  command: start_application.sh\n  async: 3600\n  poll: 30\n  register: app_task\n  notify: Update Status\n\n- name: Check database status\n  command: check_database_status.sh<\/code><\/pre>\n\n\n\n<p>In this playbook, we have three tasks that create a database, configure it, and start the application. We have set the <code>async<\/code> option to 3600 seconds (1 hour), which means that the task will run asynchronously for up to 1 hour. We have set the <code>poll<\/code> option to 30 seconds, which means that Ansible will check the status of the task every 30 seconds.<\/p>\n\n\n\n<p>We have also registered the output of each task in a variable (i.e., <code>db_task<\/code>, <code>config_task<\/code>, and <code>app_task<\/code>). This will allow us to check the status of each task later.<\/p>\n\n\n\n<p>Finally, we have a task that checks the status of the database.<\/p>\n\n\n\n<p>Next, we create a handler that will be called by the <code>notify<\/code> module:<\/p>\n\n\n\n<pre class=\"wp-block-code has-white-color has-black-background-color has-text-color has-background has-small-font-size\"><code>- name: Update Status\n  debug:\n    msg: \"{{ ansible_job_id }}: {{ lookup('pipe', 'tail -1 \/proc\/' + ansible_job_id + '\/stat') }}\"\n  run_once: true\n  when: db_task | changed or config_task | changed or app_task | changed\n<\/code><\/pre>\n\n\n\n<p>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 <code>run_once<\/code> option to true, which means that the handler will only be run once even if there are multiple hosts.<\/p>\n\n\n\n<p>Finally, we have used the <code>when<\/code> keyword to run the <code>Update Status<\/code> 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.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Explanation<\/h3>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>The <code>poll<\/code> option specifies how often Ansible should check the status of the asynchronous task. In our example, Ansible will check the status every 30 seconds.<\/p>\n\n\n\n<p>The <code>notify<\/code> module is used to call a handler named <code>Update Status<\/code> for every poll. The <code>when<\/code> keyword is used to run the <code>Update Status<\/code> task only if one<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Help<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ansible <a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/playbook_guide\/playbooks_async.html\" target=\"_blank\" rel=\"noreferrer noopener\">ASYNC<\/a><\/li>\n\n\n\n<li><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Recently during our discussion with a client a problem was raised how to show progress for a long running Ansible playbook task &amp; 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 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":2543,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[299,34],"tags":[278,300,301],"class_list":["post-2542","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ansible","category-technical","tag-ansible","tag-async","tag-poll"],"_links":{"self":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2542","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/comments?post=2542"}],"version-history":[{"count":1,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2542\/revisions"}],"predecessor-version":[{"id":2544,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/posts\/2542\/revisions\/2544"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/media\/2543"}],"wp:attachment":[{"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/media?parent=2542"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/categories?post=2542"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.samarthya.me\/wps\/wp-json\/wp\/v2\/tags?post=2542"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}