Execute a required reboot, with Ansible (Debian/Ubuntu)

Posted by ads' corner on Wednesday, 2016-08-10
Posted in [Ansible][Linux]

After updating Linux packages, it sometimes is required to reboot the host. Debian and Ubuntu provide this information by the presence of a special file: /var/run/reboot-required. Ansible makes it easy to reboot a host, but there are a few aspects which need attention.

First of all, you must ensure that this task runs last in your Playbook. Else subsequent tasks will not be executed. But you also must ensure that Ansible can finish the current task, and that the reboot is not killing the network connection while the play is still running. And finally it would be nice to get feedback if the host comes up again.

The first item is easy to handle, just make the reboot task the last one in your Playbook. The second one, making sure that the task can finish, can be handled by delaying the reboot.

Unfortunately the shutdown command in Linux can only handle delays in minute steps - and we don’t want to wait a minute for the reboot. On the other hand, the Ansible task must finish. Therefore, send the entire task into the background:

1
( /bin/sleep 5 ; shutdown -r now "Ansible updates triggered" ) &

This will wait 5 seconds, and then immediately reboot the host. The outer brackets will make sure that the entire task is sent to the background, using the &. The full play:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# make this the last play, it might reboot the server
- hosts: all
  become: yes
  tasks:
    - name: Reboot required
      shell: ( /bin/sleep 5 ; shutdown -r now "Ansible updates triggered" ) &
            removes=/var/run/reboot-required
      async: 30
      poll: 0
      ignore_errors: true
      notify:
        - waiting for server to come back

This play starts a handler, which will wait a few seconds (to make sure the reboot is in progress) and then wait for the host to come back online:

1
2
3
4
  handlers:
    - name: waiting for server to come back
      local_action: wait_for host={{ inventory_hostname }} port=22 state=started delay=10 timeout=60
      become: no

Categories: [Ansible] [Linux]