diff --git a/lib/ansible/modules/windows/win_data_deduplication.ps1 b/lib/ansible/modules/windows/win_data_deduplication.ps1 new file mode 100644 index 00000000000..593ee763815 --- /dev/null +++ b/lib/ansible/modules/windows/win_data_deduplication.ps1 @@ -0,0 +1,129 @@ +#!powershell + +# Copyright: 2019, rnsc(@rnsc) +# 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.3 + +$spec = @{ + options = @{ + drive_letter = @{ type = "str"; required = $true } + state = @{ type = "str"; choices = "absent", "present"; default = "present"; } + settings = @{ + type = "dict" + required = $false + options = @{ + minimum_file_size = @{ type = "int"; default = 32768 } + minimum_file_age_days = @{ type = "int"; default = 2 } + no_compress = @{ type = "bool"; required = $false; default = $false } + optimize_in_use_files = @{ type = "bool"; required = $false; default = $false } + verify = @{ type = "bool"; required = $false; default = $false } + } + } + } + supports_check_mode = $true +} + +$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec) + +$drive_letter = $module.Params.drive_letter +$state = $module.Params.state +$settings = $module.Params.settings + +$module.Result.changed = $false +$module.Result.reboot_required = $false +$module.Result.msg = "" + +function Set-DataDeduplication($volume, $state, $settings, $dedup_job) { + + $current_state = 'absent' + + try { + $dedup_info = Get-DedupVolume -Volume "$($volume.DriveLetter):" + } catch { + $dedup_info = $null + } + + if ($dedup_info.Enabled) { + $current_state = 'present' + } + + if ( $state -ne $current_state ) { + if( -not $module.CheckMode) { + if($state -eq 'present') { + # Enable-DedupVolume -Volume + Enable-DedupVolume -Volume "$($volume.DriveLetter):" + } elseif ($state -eq 'absent') { + Disable-DedupVolume -Volume "$($volume.DriveLetter):" + } + } + $module.Result.changed = $true + } + + if ($state -eq 'present') { + if ($null -ne $settings) { + Set-DataDedupJobSettings -volume $volume -settings $settings + } + } +} + +function Set-DataDedupJobSettings ($volume, $settings) { + + try { + $dedup_info = Get-DedupVolume -Volume "$($volume.DriveLetter):" + } catch { + $dedup_info = $null + } + + ForEach ($key in $settings.keys) { + + # See Microsoft documentation: + # https://docs.microsoft.com/en-us/powershell/module/deduplication/set-dedupvolume?view=win10-ps + + $update_key = $key + $update_value = $settings.$($key) + # Transform Ansible style options to Powershell params + $update_key = $update_key -replace('_', '') + + if ($update_key -eq "MinimumFileSize" -and $update_value -lt 32768) { + $update_value = 32768 + } + + $current_value = ($dedup_info | Select-Object -ExpandProperty $update_key) + + if ($update_value -ne $current_value) { + $command_param = @{ + $($update_key) = $update_value + } + + # Set-DedupVolume -Volume ` + # -NoCompress ` + # -MinimumFileAgeDays ` + # -MinimumFileSize (minimum 32768) + if( -not $module.CheckMode ) { + Set-DedupVolume -Volume "$($volume.DriveLetter):" @command_param + } + + $module.Result.changed = $true + } + } + +} + +# Install required feature +$feature_name = "FS-Data-Deduplication" +if( -not $module.CheckMode) { + $feature = Install-WindowsFeature -Name $feature_name + + if ($feature.RestartNeeded -eq 'Yes') { + $module.Result.reboot_required = $true + $module.FailJson("$feature_name was installed but requires Windows to be rebooted to work.") + } +} + +$volume = Get-Volume -DriveLetter $drive_letter + +Set-DataDeduplication -volume $volume -state $state -settings $settings -dedup_job $dedup_job + +$module.ExitJson() diff --git a/lib/ansible/modules/windows/win_data_deduplication.py b/lib/ansible/modules/windows/win_data_deduplication.py new file mode 100644 index 00000000000..d320b9f7c2b --- /dev/null +++ b/lib/ansible/modules/windows/win_data_deduplication.py @@ -0,0 +1,87 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: 2019, rnsc(@rnsc) +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +ANSIBLE_METADATA = {'metadata_version': '1.1', + 'status': ['preview'], + 'supported_by': 'community'} + +DOCUMENTATION = r''' +--- +module: win_data_deduplication +version_added: "2.10" +short_description: Module to enable Data Deduplication on a volume. +description: +- This module can be used to enable Data Deduplication on a Windows volume. +- The module will install the FS-Data-Deduplication feature (a reboot will be necessary). +options: + drive_letter: + description: + - Windows drive letter on which to enable data deduplication. + required: yes + type: str + state: + description: + - Wether to enable or disable data deduplication on the selected volume. + default: present + type: str + choices: [ present, absent ] + settings: + description: + - Dictionary of settings to pass to the Set-DedupVolume powershell command. + type: dict + suboptions: + minimum_file_size: + description: + - Minimum file size you want to target for deduplication. + - It will default to 32768 if not defined or if the value is less than 32768. + type: int + default: 32768 + minimum_file_age_days: + description: + - Minimum file age you want to target for deduplication. + type: int + default: 2 + no_compress: + description: + - Wether you want to enabled filesystem compression or not. + type: bool + default: no + optimize_in_use_files: + description: + - Indicates that the server attempts to optimize currently open files. + type: bool + default: no + verify: + description: + - Indicates whether the deduplication engine performs a byte-for-byte verification for each duplicate chunk + that optimization creates, rather than relying on a cryptographically strong hash. + - This option is not recommend. + - Setting this parameter to True can degrade optimization performance. + type: bool + default: no +author: +- rnsc (@rnsc) +''' + +EXAMPLES = r''' +- name: Enable Data Deduplication on D + win_data_deduplication: + drive_letter: 'D' + state: present + +- name: Enable Data Deduplication on D + win_data_deduplication: + drive_letter: 'D' + state: present + settings: + no_compress: true + minimum_file_age_days: 1 + minimum_file_size: 0 +''' + +RETURN = r''' +# +''' diff --git a/test/integration/targets/win_data_deduplication/aliases b/test/integration/targets/win_data_deduplication/aliases new file mode 100644 index 00000000000..5f7ed526d63 --- /dev/null +++ b/test/integration/targets/win_data_deduplication/aliases @@ -0,0 +1,4 @@ +shippable/windows/group4 +skip/windows/2008 +skip/windows/2008-R2 +skip/windows/2012 diff --git a/test/integration/targets/win_data_deduplication/meta/main.yml b/test/integration/targets/win_data_deduplication/meta/main.yml new file mode 100644 index 00000000000..9f37e96cd90 --- /dev/null +++ b/test/integration/targets/win_data_deduplication/meta/main.yml @@ -0,0 +1,2 @@ +dependencies: +- setup_remote_tmp_dir diff --git a/test/integration/targets/win_data_deduplication/tasks/main.yml b/test/integration/targets/win_data_deduplication/tasks/main.yml new file mode 100644 index 00000000000..ae6be90ecb9 --- /dev/null +++ b/test/integration/targets/win_data_deduplication/tasks/main.yml @@ -0,0 +1,2 @@ +--- +- include: pre_test.yml diff --git a/test/integration/targets/win_data_deduplication/tasks/pre_test.yml b/test/integration/targets/win_data_deduplication/tasks/pre_test.yml new file mode 100644 index 00000000000..f72955e46bf --- /dev/null +++ b/test/integration/targets/win_data_deduplication/tasks/pre_test.yml @@ -0,0 +1,40 @@ +--- +- set_fact: + AnsibleVhdx: '{{ remote_tmp_dir }}\AnsiblePart.vhdx' + +- name: Install FS-Data-Deduplication + win_feature: + name: FS-Data-Deduplication + include_sub_features: true + state: present + register: data_dedup_feat_reg + +- name: Reboot windows after the feature has been installed + win_reboot: + reboot_timeout: 3600 + when: + - data_dedup_feat_reg.success + - data_dedup_feat_reg.reboot_required + +- name: Copy VHDX scripts + win_template: + src: "{{ item.src }}" + dest: '{{ remote_tmp_dir }}\{{ item.dest }}' + loop: + - { src: partition_creation_script.j2, dest: partition_creation_script.txt } + - { src: partition_deletion_script.j2, dest: partition_deletion_script.txt } + +- name: Create partition + win_command: diskpart.exe /s {{ remote_tmp_dir }}\partition_creation_script.txt + +- name: Format T with NTFS + win_format: + drive_letter: T + file_system: ntfs + +- name: Run tests + block: + - include: tests.yml + always: + - name: Detach disk + win_command: diskpart.exe /s {{ remote_tmp_dir }}\partition_deletion_script.txt diff --git a/test/integration/targets/win_data_deduplication/tasks/tests.yml b/test/integration/targets/win_data_deduplication/tasks/tests.yml new file mode 100644 index 00000000000..64a42927130 --- /dev/null +++ b/test/integration/targets/win_data_deduplication/tasks/tests.yml @@ -0,0 +1,47 @@ +--- + +- name: Enable Data Deduplication on the T drive - check mode + win_data_deduplication: + drive_letter: "T" + state: present + settings: + no_compress: true + minimum_file_age_days: 2 + minimum_file_size: 0 + check_mode: yes + register: win_data_deduplication_enable_check_mode + +- name: Check that it was successful with a change - check mode + assert: + that: + - win_data_deduplication_enable_check_mode is changed + +- name: Enable Data Deduplication on the T drive + win_data_deduplication: + drive_letter: "T" + state: present + settings: + no_compress: true + minimum_file_age_days: 2 + minimum_file_size: 0 + register: win_data_deduplication_enable + +- name: Check that it was successful with a change + assert: + that: + - win_data_deduplication_enable is changed + +- name: Enable Data Deduplication on the T drive + win_data_deduplication: + drive_letter: "T" + state: present + settings: + no_compress: true + minimum_file_age_days: 2 + minimum_file_size: 0 + register: win_data_deduplication_enable_again + +- name: Check that it was successful without a change + assert: + that: + - win_data_deduplication_enable_again is not changed diff --git a/test/integration/targets/win_data_deduplication/templates/partition_creation_script.j2 b/test/integration/targets/win_data_deduplication/templates/partition_creation_script.j2 new file mode 100644 index 00000000000..8e47fda95ba --- /dev/null +++ b/test/integration/targets/win_data_deduplication/templates/partition_creation_script.j2 @@ -0,0 +1,11 @@ +create vdisk file="{{ AnsibleVhdx }}" maximum=2000 type=fixed + +select vdisk file="{{ AnsibleVhdx }}" + +attach vdisk + +convert mbr + +create partition primary + +assign letter="T" diff --git a/test/integration/targets/win_data_deduplication/templates/partition_deletion_script.j2 b/test/integration/targets/win_data_deduplication/templates/partition_deletion_script.j2 new file mode 100644 index 00000000000..c2be9cd1446 --- /dev/null +++ b/test/integration/targets/win_data_deduplication/templates/partition_deletion_script.j2 @@ -0,0 +1,3 @@ +select vdisk file="{{ AnsibleVhdx }}" + +detach vdisk