Skip to content

Commit

Permalink
[Windows] Add new test case windows_online_updates_install (#594)
Browse files Browse the repository at this point in the history
Signed-off-by: Diane Wang <dianew@vmware.com>
  • Loading branch information
Tomorrow9 authored Jul 3, 2024
1 parent 6bce8ed commit 816f89d
Show file tree
Hide file tree
Showing 13 changed files with 474 additions and 124 deletions.
14 changes: 13 additions & 1 deletion vars/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -382,11 +382,23 @@ windows_nfs_msu_path: ''
# The use name and password for accessing above Windows shared folder.
# windows_nfs_username: "CHANGEME"
# windows_nfs_password: "CHANGEME"

# A list of update titles or KB numbers that can be used to specify which updates are to be excluded from
# online Windows Updates installation. Online Windows Updates is executed before offline .msu file installation.
# The list is comma separated string. E.g. "KB12344, KB2343, kB567"
# The list is comma separated string. E.g. "KB12344, KB2343, kB567".
# This paramter can also be used in below test case "windows_online_updates_install".
windows_updates_reject_list: ''

# 8. windows_online_updates_install
# For Windows testing only.
# The expected build number of guest OS after installing Windows online updates.
# When this paramter is set to a valid build number, then after installing Windows updates, will check
# if guest OS build number is the same as or newer than this expected one. If this parameter is not set,
# will not check guest OS build number after installing Windows online updates in this test case.
# It must be set as a major build numner or a major build number with a minor build number,
# e.g., '22000', '22000.1', '22000.1234'.
# windows_updated_build_num: ''

#####################################
# GOS related parameters
#####################################
Expand Down
1 change: 1 addition & 0 deletions windows/gosv_testcase_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-2-Clause
---
- import_playbook: deploy_vm/deploy_vm.yml
- import_playbook: windows_online_updates_install/windows_online_updates_install.yml
- import_playbook: check_inbox_driver/check_inbox_driver.yml
- import_playbook: wintools_complete_install_verify/wintools_complete_install_verify.yml
- import_playbook: windows_update_install/windows_update_install.yml
Expand Down
6 changes: 5 additions & 1 deletion windows/setup/test_setup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@
- name: "Print VM guest IP address"
ansible.builtin.debug: var=vm_guest_ip

# Windows Update will cause OS poweroff or restart taking a long time,
# or GOSC test cases failure, here try to pause Windows Update 7 days
- name: "Pause Windows Update"
include_tasks: ../utils/win_pause_windows_update.yml
include_tasks: ../utils/win_pause_resume_win_update.yml
vars:
win_update_ops: 'pause'
when: not base_snapshot_exists

- name: "Get VMware Tools status"
Expand Down
41 changes: 41 additions & 0 deletions windows/utils/scripts/resume_windows_update.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Copyright 2024 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
#
# Script to remove pausing Windows Update config from registry
#
$win_pause_update_reg_path = "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings"
$win_exclude_driver_update = 'ExcludeWUDriversInQualityUpdate'
$win_policy_current = "HKLM:\SOFTWARE\Microsoft\PolicyManager\current\device\Update"
$win_policy_update = "HKLM:\SOFTWARE\Microsoft\PolicyManager\default\Update"
$win_policy_windows_update = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
$win_pause_config = @('PauseUpdatesStartTime', 'PauseUpdatesExpiryTime', 'PauseFeatureUpdatesStartTime', 'PauseFeatureUpdatesEndTime', 'PauseQualityUpdatesStartTime', 'PauseQualityUpdatesEndTime', $win_exclude_driver_update)

If (Test-Path -Path $win_pause_update_reg_path)
{
foreach ($item in $win_pause_config)
{
if ((Get-Item -Path $win_pause_update_reg_path).Property -contains $item)
{
Write-Host "Remove $win_pause_update_reg_path\$item"
Remove-ItemProperty -Path $win_pause_update_reg_path -Name $item -Force
}
}
}
If ((Test-Path -Path $win_policy_current) -and `
((Get-Item -Path $win_policy_current).Property -contains $win_exclude_driver_update))
{
Write-Host "Remove $win_policy_current\$win_exclude_driver_update"
Remove-ItemProperty -Path $win_policy_current -Name $win_exclude_driver_update -Force
}
If ((Test-Path -Path $win_policy_update) -and `
((Get-Item -Path $win_policy_update).Property -contains $win_exclude_driver_update))
{
Write-Host "Remove $win_policy_update\$win_exclude_driver_update"
Remove-ItemProperty -Path $win_policy_update -Name $win_exclude_driver_update -Force
}
If ((Test-Path -Path $win_policy_windows_update) -and `
((Get-Item -Path $win_policy_windows_update).Property -contains $win_exclude_driver_update))
{
Write-Host "Remove $win_policy_windows_update\$win_exclude_driver_update"
Remove-ItemProperty -Path $win_policy_windows_update -Name $win_exclude_driver_update -Force
}
64 changes: 64 additions & 0 deletions windows/utils/win_get_online_updates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright 2024 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
---
# Search and list the online Windows Updates in all or specified categories.
# Parameters:
# win_updates_categories (optional): a list of categories to get updates from.
# Some possible categories are: Application, Connectors, Critical Updates, Definition Updates, Developer Kits,
# Feature Packs, Guidance, Security Updates, Service Packs, Tools, Update Rollups, Updates and Upgrades.
# Default value is '*', means matching all categories.
# win_updates_categories_expect (optional): a list of expected update categories. If configured,
# searched online updates must contain at least one of the category in this list.
# Default value is '['']'.
# win_get_updates_retries (optional): the retry times to get expected update categories.
# Default value is 1.
# win_updates_ignore_errors (optional): whether to ignore errors in searching and checking
# Windows online updates, default is false.
# win_updates_log_file (optional): the log file path for Windows Update in guest OS.
# Default is 'C:\win_updates_log.txt'.
#
- name: "Initialize the facts of getting Windows online updates"
ansible.builtin.set_fact:
win_updates_categories: "{{ win_updates_categories | default('*') }}"
win_updates_categories_expect: "{{ win_updates_categories_expect | default(['']) }}"
win_updates_ignore_errors: "{{ win_updates_ignore_errors | default(false) }}"
win_updates_log_file: "{{ win_updates_log_file | default('C:\\win_updates_log.txt') }}"

- name: "Set 'win_get_updates_retries' to 1 by default"
ansible.builtin.set_fact:
win_get_updates_retries: 1
when: win_get_updates_retries is undefined

- name: "Get the list of available Windows online updates"
ansible.windows.win_updates:
server_selection: "windows_update"
category_names: "{{ win_updates_categories }}"
log_path: "{{ win_updates_log_file }}"
skip_optional: true
state: "searched"
delegate_to: "{{ vm_guest_ip }}"
register: win_get_updates_result
ignore_errors: true
retries: "{{ win_get_updates_retries | int }}"
delay: 10
until:
- win_get_updates_result.found_update_count is defined
- win_get_updates_result.found_update_count | int != 0
- win_get_updates_result.updates is defined
- win_get_updates_result.updates | length != 0
- (win_get_updates_result.updates.values() | map(attribute='categories') | flatten | unique + ['']) | intersect(win_updates_categories_expect) | length != 0

- name: "Print the result of searching Windows online updates"
ansible.builtin.debug: var=win_get_updates_result
when: enable_debug

- name: "Check getting Windows online updates result"
ansible.builtin.fail:
msg: >-
Failed to search Windows online updates containing specified categories:
{{ win_updates_categories_expect }} after {{ win_get_updates_retries }} retries,
with errors: {{ win_get_updates_result.stderr | default('') }}
when:
- not win_updates_ignore_errors
- win_get_updates_result.failed is defined
- win_get_updates_result.failed
103 changes: 38 additions & 65 deletions windows/utils/win_install_online_updates.yml
Original file line number Diff line number Diff line change
@@ -1,82 +1,55 @@
# Copyright 2023-2024 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
---
# Search and install Windows Updates in specified categories,
# and skip optional ones in Windows guest OS.
# Parameter:
# win_updates_category_names(optional): A list of categories to install updates from.
# Some possible categories are: Application, Connectors, Critical Updates, Definition Updates, Developer Kits,
# Feature Packs, Guidance, Security Updates, Service Packs, Tools, Update Rollups, Updates, and Upgrades.
# Default value is *. The value * will match all categories
# win_updates_reject_list(optional): A list of update titles or KB numbers that can be used to specify
# which updates are to be excluded from installation.
# win_updates_ignore_errors: Ignore errors when checking and installing Windows Updates. Default is false.
# Install Windows online updates in specified categories, skip optional
# ones or in a reject list in Windows guest OS.
# Parameters:
# win_updates_categories (optional): A list of categories to install updates from.
# Some possible categories are: Application, Connectors, Critical Updates,
# Definition Updates, Developer Kits, Feature Packs, Guidance, Security Updates,
# Service Packs, Tools, Update Rollups, Updates and Upgrades.
# Default value is '*', which matches all categories.
# win_updates_reject_list (optional): A list of update titles or KB numbers that
# can be used to specify which updates are to be excluded from installation.
# win_updates_ignore_errors (optional): Whether to ignore errors when installing
# Windows updates. Default is false.
# win_updates_log_file (optional): The log file path for Windows Update in guest OS.
# Default is 'C:\win_updates_log.txt'.
# Return:
# win_updates_log_file: Windows Updates install log file path.
# win_online_updates_succeed: Windows Updates install result indicator.
# win_online_updates_installed: Indicates if there are Windows online updates
# installed and the installed count is the same as the found count.
#
- name: "Set fact of Windows Updates install log path and initialize online update status"
- name: "Set fact and initialize Windows online updates install parameters"
ansible.builtin.set_fact:
win_updates_log_file: "C:\\win_updates_log.txt"
win_online_updates_succeed: false
win_updates_log_file: "{{ win_updates_log_file | default('C:\\win_updates_log.txt') }}"
win_online_updates_installed: false

- name: "Get the list of available Windows Updates"
- name: "Install Windows online updates"
ansible.windows.win_updates:
server_selection: "windows_update"
category_names: "{{ win_updates_category_names | default('*') }}"
category_names: "{{ win_updates_categories | default('*') }}"
reject_list: "{{ win_updates_reject_list | default('') }}"
log_path: "{{ win_updates_log_file }}"
skip_optional: true
state: "searched"
state: "installed"
reboot: true
reboot_timeout: 2700
delegate_to: "{{ vm_guest_ip }}"
register: win_updates_list
register: win_updates_install_result
ignore_errors: "{{ win_updates_ignore_errors | default(false) }}"
- name: "Print the list of Windows Updates"
ansible.builtin.debug: var=win_updates_list

- name: "Install Windows Updates when updates found"
when:
- win_updates_list.failed is defined
- not win_updates_list.failed
- win_updates_list.found_update_count is defined
- win_updates_list.found_update_count | int != 0
- win_updates_list.updates is defined
- win_updates_list.updates | length != 0
block:
- name: "Install Windows Updates"
ansible.windows.win_updates:
server_selection: "windows_update"
category_names: "{{ win_updates_category_names | default('*') }}"
reject_list: "{{ win_updates_reject_list | default('') }}"
log_path: "{{ win_updates_log_file }}"
skip_optional: true
state: "installed"
reboot: true
reboot_timeout: 2700
delegate_to: "{{ vm_guest_ip }}"
register: win_updates_install_result
ignore_errors: "{{ win_updates_ignore_errors | default(false) }}"
- name: "Print Windows Updates install result"
debug: var=win_updates_install_result

- name: "No need to install Windows Updates"
ansible.builtin.debug:
msg: "Will not execute Windows Updates installation task due to no update found or search failed."
when: >
(win_updates_list.found_update_count is undefined) or
(win_updates_list.found_update_count | int == 0)
- name: "Print Windows online updates install result"
debug: var=win_updates_install_result
when: enable_debug

- name: "Set Windows Updates installation status"
- name: "Set fact of Windows online updates install status"
ansible.builtin.set_fact:
win_online_updates_succeed: |-
{%- if win_updates_list.failed is defined and not win_updates_list.failed and
win_updates_list.found_update_count | int == 0 -%}
true
{%- elif win_updates_install_result is defined and win_updates_install_result.installed_update_count is defined and
win_updates_install_result.found_update_count | int == win_updates_install_result.installed_update_count | int -%}
true
{%- else -%}
false
{%- endif -%}
win_online_updates_installed: true
when:
- win_updates_install_result.found_update_count is defined
- win_updates_install_result.found_update_count | int != 0
- win_updates_install_result.installed_update_count is defined
- win_updates_install_result.found_update_count | int == win_updates_install_result.installed_update_count | int

- name: "Display Windows Updates installation status"
ansible.builtin.debug: var=win_online_updates_succeed
- name: "Display Windows online updates install status"
ansible.builtin.debug: var=win_online_updates_installed
53 changes: 53 additions & 0 deletions windows/utils/win_pause_resume_win_update.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2024 VMware, Inc.
# SPDX-License-Identifier: BSD-2-Clause
---
# Disable Windows auto update and pause Windows Update 7 days,
# or delete this pauing Windows Update config in registry to
# resume Windows Update.
# Paramters:
# win_update_ops: valid values are 'pause' or 'resume'.
#
- name: "Check required parameter"
ansible.builtin.assert:
that:
- win_update_ops is defined
- win_update_ops in ['pause', 'resume']
fail_msg: >-
Parameter 'win_update_ops': {{ win_update_ops | default('') }} is not set correctly,
valid value is 'pause' or 'resume'.
- name: "Set fact of the PowerShell script name"
ansible.builtin.set_fact:
win_update_script: "{{ win_update_ops }}_windows_update.ps1"

- name: "Set fact of the PowerShell script local and remote paths"
ansible.builtin.set_fact:
local_ps_file: "scripts/{{ win_update_script }}"
remote_ps_file: "C:\\{{ win_update_script }}"

- name: "Copy PowerShell script from local to guest OS"
include_tasks: win_copy_file_from_local.yml
vars:
src_path_local: "{{ local_ps_file }}"
dest_path_remote: "C:\\"

- name: "Get PowerShell script existence state in guest OS"
include_tasks: win_check_file_exist.yml
vars:
win_check_file_exist_file: "{{ remote_ps_file }}"
- name: "Make sure PowerShell script exists in guest OS"
ansible.builtin.assert:
that:
- win_check_file_exist_result is defined
- win_check_file_exist_result | bool
fail_msg: "PowerShell script is not found in guest OS in this path: {{ remote_ps_file }}"

# Pause Windows Update is not a demand task, so ignore errors
- name: "Execute {{ win_update_ops }} Windows Update PowerShell script in guest OS"
ansible.windows.win_command: "powershell.exe -ExecutionPolicy bypass -File {{ remote_ps_file }}"
delegate_to: "{{ vm_guest_ip }}"
ignore_errors: "{{ win_update_ops == 'pause' }}"
register: win_update_ops_result
- name: "Display the PowerShell script execute result"
ansible.builtin.debug: var=win_update_ops_result
when: enable_debug
36 changes: 0 additions & 36 deletions windows/utils/win_pause_windows_update.yml

This file was deleted.

Loading

0 comments on commit 816f89d

Please sign in to comment.