--- - name: update over multiple reboots block: - block: - name: set reject list set_fact: _reject_list: "{{ (win_update_reject_list | default([])) + (failed_kb | default([])) }}" when: (win_update_reject_list | length) or (failed_kb | length) - name: install all windows updates win_updates: server_selection: "{{ win_update_server_selection }}" category_names: "{{ win_update_category_names }}" reject_list: "{{ _reject_list | default(omit) }}" accept_list: "{{ win_update_accept_list | default(omit) }}" reboot: false async: 7200 poll: 0 register: installed_updates_async - name: wait for updates to finish async_status: jid: "{{ installed_updates_async.ansible_job_id }}" register: installed_updates until: installed_updates.finished retries: "{{ install_updates_retry_limit }}" delay: 30 - name: reboot the system if required win_reboot: reboot_timeout: 7200 when: installed_updates.reboot_required rescue: - name: ensure there is connection wait_for_connection: delay: 60 sleep: 10 timeout: 600 # see https://learn.microsoft.com/en-us/sharepoint/troubleshoot/administration/800703fa-illegal-operation-error # error code 0x800703FA happens with some updates when user is not logged in # add the registry key to disable forcefully unloading users registry at user logoff - include_tasks: force_user_registry.yml vars: task_state: present when: - installed_updates is defined - installed_updates is failed - installed_updates.msg is defined - ('0x800703FA' in installed_updates.msg) - name: reboot the system to recover from a failed update win_reboot: reboot_timeout: 7200 - name: set failed KB to skip set_fact: failed_kb: "{{ failed_kb|default([]) + [installed_updates.msg | regex_replace('^.*\\((KB.*)\\).*','\\1')] }}" when: - installed_updates.msg is defined - ('Failed' in installed_updates.msg) - ('KB' in installed_updates.msg) - name: fail to retry fail: msg: "There are failed updates: {{ failed_kb | join(' ') }}" when: - failed_kb is defined - failed_kb | length > 0 - name: wait for system to be responsive after update wait_for_connection: delay: 60 sleep: 10 timeout: 600 - block: - name: work on any skipped KB win_updates: server_selection: "{{ win_update_server_selection }}" category_names: "{{ win_update_category_names }}" reject_list: "{{ win_update_reject_list | default(omit) }}" accept_list: "{{ failed_kb | default(omit) }}" reboot: false async: 7200 poll: 0 register: installed_updates_retry_skipped_async - name: wait for updates to finish async_status: jid: "{{ installed_updates_retry_skipped_async.ansible_job_id }}" register: installed_updates_retry_skipped until: installed_updates_retry_skipped.finished retries: "{{ install_updates_retry_limit }}" delay: 30 - name: reboot the system if required win_reboot: reboot_timeout: 7200 when: installed_updates_retry_skipped.reboot_required when: - failed_kb is defined - failed_kb | length > 0 - name: check for missing updates win_updates: server_selection: "{{ win_update_server_selection }}" category_names: "{{ win_update_category_names }}" reject_list: "{{ win_update_reject_list | default(omit) }}" state: searched register: missing_updates - debug: msg: "{{ _msg.split('\n')[:-1] }}" vars: _msg: | {{ inventory_hostname }} has {{ missing_updates.found_update_count }} updates still missing. {% for update in updates %} - {{ update.title }} {% endfor %} updates: "{{ (missing_updates.updates.values() | list) if (missing_updates.updates is mapping) else (missing_updates.updates) }}" when: missing_updates.updates is defined - name: still more updates - need to retry fail: msg: > '{{ inventory_hostname }} has {{ missing_updates.found_update_count }} updates still missing. {{ (update_retry_limit | int) - (update_retry_count | int) }} more retries left' when: - missing_updates.found_update_count > 0 - ((update_retry_limit | int) - (update_retry_count | int) > 0) rescue: - name: set update count set_fact: update_retry_count: '{{ update_retry_count | default(0) | int + 1 }}' - debug: msg: "Still more updates ({{ current_update_count }}) remaining - retrying... ({{ update_retry_count }}/{{ update_retry_limit }})" vars: current_update_count: "{{ missing_updates.found_update_count | default(installed_updates.found_update_count) | default('-') }}" - name: ensure system is reachable wait_for_connection: sleep: 10 timeout: 600 - include_tasks: updates-with-retry.yml when: ((update_retry_limit | int) - (update_retry_count | int) > 0)