From 1ed9df24d1060821854edebd223f17a86dc9ab4c Mon Sep 17 00:00:00 2001 From: hyaish Date: Tue, 19 Nov 2024 14:55:45 +0200 Subject: [PATCH] Promote the win_initialize_disk Module Updating documentation. validating module and tests Signed-off-by: hyaish --- plugins/modules/win_initialize_disk.ps1 | 163 ++++++++++++++++++ plugins/modules/win_initialize_disk.py | 75 ++++++++ .../targets/win_initialize_disk/aliases | 1 + .../win_initialize_disk/defaults/main.yml | 1 + .../win_initialize_disk/tasks/main.yml | 28 +++ .../win_initialize_disk/tasks/tests.yml | 104 +++++++++++ .../templates/vhdx_creation_script.j2 | 5 + .../templates/vhdx_deletion_script.j2 | 3 + 8 files changed, 380 insertions(+) create mode 100644 plugins/modules/win_initialize_disk.ps1 create mode 100644 plugins/modules/win_initialize_disk.py create mode 100644 tests/integration/targets/win_initialize_disk/aliases create mode 100644 tests/integration/targets/win_initialize_disk/defaults/main.yml create mode 100644 tests/integration/targets/win_initialize_disk/tasks/main.yml create mode 100644 tests/integration/targets/win_initialize_disk/tasks/tests.yml create mode 100644 tests/integration/targets/win_initialize_disk/templates/vhdx_creation_script.j2 create mode 100644 tests/integration/targets/win_initialize_disk/templates/vhdx_deletion_script.j2 diff --git a/plugins/modules/win_initialize_disk.ps1 b/plugins/modules/win_initialize_disk.ps1 new file mode 100644 index 00000000..21a6b980 --- /dev/null +++ b/plugins/modules/win_initialize_disk.ps1 @@ -0,0 +1,163 @@ +#!powershell + +# Copyright: (c) 2019, Brant Evans +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +#AnsibleRequires -CSharpUtil Ansible.Basic +#AnsibleRequires -OSVersion 6.2 + +Set-StrictMode -Version 2 + +$spec = @{ + options = @{ + disk_number = @{ type = "int" } + uniqueid = @{ type = "str" } + path = @{ type = "str" } + style = @{ type = "str"; choices = "gpt", "mbr"; default = "gpt" } + online = @{ type = "bool"; default = $true } + force = @{ type = "bool"; default = $false } + } + mutually_exclusive = @( + , @('disk_number', 'uniqueid', 'path') + ) + required_one_of = @( + , @('disk_number', 'uniqueid', 'path') + ) + supports_check_mode = $true +} + +$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) + +$disk_number = $module.Params.disk_number +$uniqueid = $module.Params.uniqueid +$path = $module.Params.path +$partition_style = $module.Params.style +$bring_online = $module.Params.online +$force_init = $module.Params.force + +function Get-AnsibleDisk { + param( + $DiskNumber, + $UniqueId, + $Path + ) + + if ($null -ne $DiskNumber) { + try { + $disk = Get-Disk -Number $DiskNumber + } + catch { + $module.FailJson("There was an error retrieving the disk using disk_number $($DiskNumber): $($_.Exception.Message)") + } + } + elseif ($null -ne $UniqueId) { + try { + $disk = Get-Disk -UniqueId $UniqueId + } + catch { + $module.FailJson("There was an error retrieving the disk using id $($UniqueId): $($_.Exception.Message)") + } + } + elseif ($null -ne $Path) { + try { + $disk = Get-Disk -Path $Path + } + catch { + $module.FailJson("There was an error retrieving the disk using path $($Path): $($_.Exception.Message)") + } + } + else { + $module.FailJson("Unable to retrieve disk: disk_number, id, or path was not specified") + } + + return $disk +} + +function Initialize-AnsibleDisk { + param( + $AnsibleDisk, + $PartitionStyle + ) + + if ($AnsibleDisk.IsReadOnly) { + $module.FailJson("Unable to initialize disk as it is read-only") + } + + $parameters = @{ + Number = $AnsibleDisk.Number + PartitionStyle = $PartitionStyle + } + + if (-Not $module.CheckMode) { + Initialize-Disk @parameters -Confirm:$false + } + + $module.Result.changed = $true +} + +function Clear-AnsibleDisk { + param( + $AnsibleDisk + ) + + $parameters = @{ + Number = $AnsibleDisk.Number + } + + if (-Not $module.CheckMode) { + Clear-Disk @parameters -RemoveData -RemoveOEM -Confirm:$false + } +} + +function Set-AnsibleDisk { + param( + $AnsibleDisk, + $BringOnline + ) + + $refresh_disk_status = $false + + if ($BringOnline) { + if (-Not $module.CheckMode) { + if ($AnsibleDisk.IsOffline) { + Set-Disk -Number $AnsibleDisk.Number -IsOffline:$false + $refresh_disk_status = $true + } + + if ($AnsibleDisk.IsReadOnly) { + Set-Disk -Number $AnsibleDisk.Number -IsReadOnly:$false + $refresh_disk_status = $true + } + } + } + + if ($refresh_disk_status) { + $AnsibleDisk = Get-AnsibleDisk -DiskNumber $AnsibleDisk.Number + } + + return $AnsibleDisk +} + +$ansible_disk = Get-AnsibleDisk -DiskNumber $disk_number -UniqueId $uniqueid -Path $path +$ansible_part_style = $ansible_disk.PartitionStyle + +if ("RAW" -eq $ansible_part_style) { + $ansible_disk = Set-AnsibleDisk -AnsibleDisk $ansible_disk -BringOnline $bring_online + Initialize-AnsibleDisk -AnsibleDisk $ansible_disk -PartitionStyle $partition_style +} +else { + if (($ansible_part_style -ne $partition_style.ToUpper()) -And -Not $force_init) { + $msg = -join @( + "Force initialization must be specified since the target partition style: $($partition_style.ToLower()) " + "is different from the current partition style: $($ansible_part_style.ToLower())" + ) + $module.FailJson($msg) + } + elseif ($force_init) { + $ansible_disk = Set-AnsibleDisk -AnsibleDisk $ansible_disk -BringOnline $bring_online + Clear-AnsibleDisk -AnsibleDisk $ansible_disk + if ( $bring_online ) { Initialize-AnsibleDisk -AnsibleDisk $ansible_disk -PartitionStyle $partition_style } + } +} + +$module.ExitJson() diff --git a/plugins/modules/win_initialize_disk.py b/plugins/modules/win_initialize_disk.py new file mode 100644 index 00000000..065fd8dc --- /dev/null +++ b/plugins/modules/win_initialize_disk.py @@ -0,0 +1,75 @@ +#!/usr/bin/python + +# Copyright: (c) 2019, Brant Evans +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = ''' +--- +module: win_initialize_disk +short_description: Initializes disks on Windows Server +description: + - "The M(community.windows.win_initialize_disk) module initializes disks" +options: + disk_number: + description: + - Used to specify the disk number of the disk to be initialized. + type: int + uniqueid: + description: + - Used to specify the uniqueid of the disk to be initialized. + type: str + path: + description: + - Used to specify the path to the disk to be initialized. + type: str + style: + description: + - The partition style to use for the disk. Valid options are mbr or gpt. + type: str + choices: [ gpt, mbr ] + default: gpt + online: + description: + - If the disk is offline and/or readonly update the disk to be online and not readonly. + type: bool + default: true + force: + description: + - Specify if initializing should be forced for disks that are already initialized. + type: bool + default: no + +notes: + - One of three parameters (I(disk_number), I(uniqueid), and I(path)) are mandatory to identify the target disk, but + more than one cannot be specified at the same time. + - A minimum Operating System Version of Server 2012 or Windows 8 is required to use this module. + - This module is idempotent if I(force) is not specified. + +seealso: + - module: community.windows.win_disk_facts + - module: community.windows.win_partition + - module: community.windows.win_format + +author: + - Brant Evans (@branic) +''' + +EXAMPLES = ''' +- name: Initialize a disk + community.windows.win_initialize_disk: + disk_number: 1 + +- name: Initialize a disk with an MBR partition style + community.windows.win_initialize_disk: + disk_number: 1 + style: mbr + +- name: Forcefully initialize a disk + community.windows.win_initialize_disk: + disk_number: 2 + force: true +''' + +RETURN = ''' +# +''' diff --git a/tests/integration/targets/win_initialize_disk/aliases b/tests/integration/targets/win_initialize_disk/aliases new file mode 100644 index 00000000..4f4664b6 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/aliases @@ -0,0 +1 @@ +shippable/windows/group5 diff --git a/tests/integration/targets/win_initialize_disk/defaults/main.yml b/tests/integration/targets/win_initialize_disk/defaults/main.yml new file mode 100644 index 00000000..9cb54a30 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/defaults/main.yml @@ -0,0 +1 @@ +AnsibleVhdx: C:\win_initialize_disk_tests\AnsiblePart.vhdx diff --git a/tests/integration/targets/win_initialize_disk/tasks/main.yml b/tests/integration/targets/win_initialize_disk/tasks/main.yml new file mode 100644 index 00000000..303723e9 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/tasks/main.yml @@ -0,0 +1,28 @@ +--- +- name: Create the temp directory + ansible.windows.win_file: + path: C:\win_initialize_disk_tests + state: directory + +- name: Copy VHDX scripts + ansible.windows.win_template: + src: "{{ item.src }}" + dest: C:\win_initialize_disk_tests\{{ item.dest }} + loop: + - { src: vhdx_creation_script.j2, dest: vhdx_creation_script.txt } + - { src: vhdx_deletion_script.j2, dest: vhdx_deletion_script.txt } + +- name: Create VHD + ansible.windows.win_command: diskpart.exe /s C:\win_initialize_disk_tests\vhdx_creation_script.txt + +- name: Run tests + block: + - import_tasks: tests.yml + always: + - name: Detach disk + ansible.windows.win_command: diskpart.exe /s C:\win_initialize_disk_tests\vhdx_deletion_script.txt + + - name: Cleanup files + ansible.windows.win_file: + path: C:\win_initialize_disk_tests + state: absent diff --git a/tests/integration/targets/win_initialize_disk/tasks/tests.yml b/tests/integration/targets/win_initialize_disk/tasks/tests.yml new file mode 100644 index 00000000..b9bc1d70 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/tasks/tests.yml @@ -0,0 +1,104 @@ +--- +- name: Initialize the disk with the default partition style (check mode) + win_initialize_disk: + disk_number: 1 + register: default_part_style_check + check_mode: yes + +- name: Get result of default initialization (check mode) + ansible.windows.win_command: powershell.exe "if ( (Get-Disk -Number 1).PartitionStyle -eq 'RAW' ) {'true'} else {'false'}" + register: default_part_style_actual_check + +- name: assert default initialization (check mode) + assert: + that: + - default_part_style_check is changed + - default_part_style_actual_check.stdout == 'true\r\n' + +- name: Initialize the disk with the default partition style + win_initialize_disk: + disk_number: 1 + register: default_part_style + +- name: Get result of default initialization + ansible.windows.win_command: powershell.exe "if ( (Get-Disk -Number 1).PartitionStyle -eq 'GPT' ) {'true'} else {'false'}" + register: default_part_style_actual + +- name: assert default initialization + assert: + that: + - default_part_style is changed + - default_part_style_actual.stdout == 'true\r\n' + +- name: Initialize the disk with the default partition style (idempotence) + win_initialize_disk: + disk_number: 1 + register: default_part_style_idempotence + +- name: Get result of default initialization (idempotence) + ansible.windows.win_command: powershell.exe "if ( (Get-Disk -Number 1).PartitionStyle -eq 'GPT' ) {'true'} else {'false'}" + register: default_part_style_actual_idempotence + +- name: assert default initialization (idempotence) + assert: + that: + - not default_part_style_idempotence is changed + - default_part_style_actual_idempotence.stdout == 'true\r\n' + +- name: Partition style change without force fails + win_initialize_disk: + disk_number: 1 + style: mbr + register: change_part_style + ignore_errors: True + +- name: assert failed partition style change + assert: + that: + - change_part_style is failed + +- name: Partition style change with force is successful (check mode) + win_initialize_disk: + disk_number: 1 + style: mbr + force: yes + register: change_part_style_forced_check + check_mode: yes + +- name: Get result of forced initialization (check mode) + ansible.windows.win_command: powershell.exe "if ( (Get-Disk -Number 1).PartitionStyle -eq 'GPT' ) {'true'} else {'false'}" + register: change_part_style_forced_actual_check + +- name: assert forced initialization (check mode) + assert: + that: + - change_part_style_forced_check is changed + - change_part_style_forced_actual_check.stdout == 'true\r\n' + +- name: Partition style change with force is successful + win_initialize_disk: + disk_number: 1 + style: mbr + force: yes + register: change_part_style_forced + +- name: Get result of forced initialization + ansible.windows.win_command: powershell.exe "if ( (Get-Disk -Number 1).PartitionStyle -eq 'MBR' ) {'true'} else {'false'}" + register: change_part_style_forced_actual + +- name: assert forced initialization + assert: + that: + - change_part_style_forced is changed + - change_part_style_forced_actual.stdout == 'true\r\n' + +- name: Unknown disk number fails + win_initialize_disk: + disk_number: 3 + register: unknown_disk_number + ignore_errors: True + +- name: assert unknown disk number fails + assert: + that: + - unknown_disk_number is failed diff --git a/tests/integration/targets/win_initialize_disk/templates/vhdx_creation_script.j2 b/tests/integration/targets/win_initialize_disk/templates/vhdx_creation_script.j2 new file mode 100644 index 00000000..4089bf37 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/templates/vhdx_creation_script.j2 @@ -0,0 +1,5 @@ +create vdisk file="{{ AnsibleVhdx }}" maximum=2000 type=fixed + +select vdisk file="{{ AnsibleVhdx }}" + +attach vdisk diff --git a/tests/integration/targets/win_initialize_disk/templates/vhdx_deletion_script.j2 b/tests/integration/targets/win_initialize_disk/templates/vhdx_deletion_script.j2 new file mode 100644 index 00000000..c2be9cd1 --- /dev/null +++ b/tests/integration/targets/win_initialize_disk/templates/vhdx_deletion_script.j2 @@ -0,0 +1,3 @@ +select vdisk file="{{ AnsibleVhdx }}" + +detach vdisk