diff --git a/lib/ansible/modules/windows/win_pagefile.ps1 b/lib/ansible/modules/windows/win_pagefile.ps1 new file mode 100644 index 0000000000..1d82404c7a --- /dev/null +++ b/lib/ansible/modules/windows/win_pagefile.ps1 @@ -0,0 +1,171 @@ +#!powershell +# This file is part of Ansible +# +# Copyright 2017, Liran Nisanov +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# WANT_JSON +# POWERSHELL_COMMON + +######## + +Function Remove-Pagefile($path, $whatif) +{ + Get-WmiObject Win32_PageFileSetting | WHERE { $_.Name -eq $path } | Remove-WmiObject -WhatIf:$whatif +} + +Function Get-Pagefile($path) +{ + Get-WmiObject Win32_PageFileSetting | WHERE { $_.Name -eq $path } +} + +######## + +$params = Parse-Args $args -supports_check_mode $true +$check_mode = Get-AnsibleParam -obj $params -name '_ansible_check_mode' -type 'bool' -default $false + +$automatic = Get-AnsibleParam -obj $params -name "automatic" -type "bool" +$drive = Get-AnsibleParam -obj $params -name "drive" -type "str" +$fullPath = $drive + ":\pagefile.sys" +$initialSize = Get-AnsibleParam -obj $params -name "initial_size" -type "int" +$maximumSize = Get-AnsibleParam -obj $params -name "maximum_size" -type "int" +$override = Get-AnsibleParam -obj $params -name "override" -type "bool" -default $true +$removeAll = Get-AnsibleParam -obj $params -name "remove_all" -type "bool" -default $false +$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "query" -validateset "present","absent","query" +$systemManaged = Get-AnsibleParam -obj $params -name "system_managed" -type "bool" -default $false +$testPath = Get-AnsibleParam -obj $params -name "test_path" -type "bool" -default $true + +$result = @{ + changed = $false +} + +if ($removeAll) { + $currentPageFiles = Get-WmiObject Win32_PageFileSetting + if ($currentPageFiles -ne $null) { + $currentPageFiles | Remove-WmiObject -WhatIf:$check_mode | Out-Null + $result.changed = $true + } +} + +if ($automatic -ne $null) { + # change autmoatic managed pagefile + try { + $computerSystem = Get-WmiObject -Class win32_computersystem -EnableAllPrivileges + } catch { + Fail-Json $result "Failed to query WMI computer system object $($_.Exception.Message)" + } + if ($computerSystem.AutomaticManagedPagefile -ne $automatic) { + $computerSystem.AutomaticManagedPagefile = $automatic + if (-not $check_mode) { + try { + $computerSystem.Put() | Out-Null + } catch { + Fail-Json $result "Failed to set AutomaticManagedPagefile $($_.Exception.Message)" + } + } + $result.changed = $true + } +} + +if ($state -eq "absent") { + # Remove pagefile + if ((Get-Pagefile $fullPath) -ne $null) + { + try { + Remove-Pagefile $fullPath -whatif:$check_mode + } catch { + Fail-Json $result "Failed to remove pagefile $($_.Exception.Message)" + } + $result.changed = $true + } +} elseif ($state -eq "present") { + # Remove current pagefile + if ($override) { + if ((Get-Pagefile $fullPath) -ne $null) + { + try { + Remove-Pagefile $fullPath -whatif:$check_mode + } catch { + Fail-Json $result "Failed to remove current pagefile $($_.Exception.Message)" + } + $result.changed = $true + } + } + + # Make sure drive is accessible + if (($test_path) -and (-not (Test-Path "${drive}:"))) { + Fail-Json $result "Unable to access '${drive}:' drive" + } + + # Set pagefile + if ((Get-Pagefile $fullPath) -eq $null) { + try { + $pagefile = Set-WmiInstance -Class Win32_PageFileSetting -Arguments @{name = $fullPath; InitialSize = 0; MaximumSize = 0} -WhatIf:$check_mode + } catch { + Fail-Json $result "Failed to create pagefile $($_.Exception.Message)" + } + if (-not ($systemManaged -or $check_mode)) { + $pagefile.InitialSize = $initialSize + $pagefile.MaximumSize = $maximumSize + try { + $pagefile.Put() | out-null + } catch { + $originalExceptionMessage = $($_.Exception.Message) + # Try workaround before failing + try { + Remove-Pagefile $fullPath -whatif:$check_mode + } catch { + Fail-Json $result "Failed to remove pagefile before workaround $($_.Exception.Message) Original exception: $originalExceptionMessage" + } + try { + $pagingFilesValues = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management").PagingFiles + } catch { + Fail-Json $result "Failed to get pagefile settings from the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage" + } + $pagingFilesValues += "$fullPath $initialSize $maximumSize" + try { + Set-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" "PagingFiles" $pagingFilesValues + } catch { + Fail-Json $result "Failed to set pagefile settings to the registry for workaround $($_.Exception.Message) Original exception: $originalExceptionMessage" + } + } + } + $result.changed = $true + } +} elseif ($state -eq "query") { + $result.pagefiles = @() + + if ($drive -eq $null) { + try { + $pagefiles = Get-WmiObject Win32_PageFileSetting + } catch { + Fail-Json $result "Failed to query all pagefiles $($_.Exception.Message)" + } + } else { + try { + $pagefiles = Get-Pagefile $fullPath + } catch { + Fail-Json $result "Failed to query specific pagefile $($_.Exception.Message)" + } + } + + # Get all pagefiles + foreach ($currentPagefile in $pagefiles) { + $currentPagefileObject = @{ + name = $currentPagefile.Name + initial_size = $currentPagefile.InitialSize + maximum_size = $currentPagefile.MaximumSize + caption = $currentPagefile.Caption + description = $currentPagefile.Description + } + $result.pagefiles += $currentPagefileObject + } + + # Get automatic managed pagefile state + try { + $result.automatic_managed_pagefiles = (Get-WmiObject -Class win32_computersystem).AutomaticManagedPagefile + } catch { + Fail-Json $result "Failed to query automatic managed pagefile state $($_.Exception.Message)" + } +} +Exit-Json $result diff --git a/lib/ansible/modules/windows/win_pagefile.py b/lib/ansible/modules/windows/win_pagefile.py new file mode 100644 index 0000000000..08263495d0 --- /dev/null +++ b/lib/ansible/modules/windows/win_pagefile.py @@ -0,0 +1,139 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright 2017, Liran Nisanov +# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) + +# this is a windows documentation stub. actual code lives in the .ps1 +# file of the same name + +ANSIBLE_METADATA = {'metadata_version': '1.0', + 'status': ['preview'], + 'supported_by': 'community'} + + +DOCUMENTATION = r''' +--- +module: win_pagefile +version_added: "2.4" +short_description: Query or change pagefile configuration +description: + - Query current pagefile configuration. + - Enable/Disable AutomaticManagedPagefile. + - Create new or override pagefile configuration. +options: + drive: + description: + - The drive of the pagefile. + initial_size: + description: + - The initial size of the pagefile in megabytes. + maximum_size: + description: + - The maximum size of the pagefile in megabytes. + override: + description: + - Override the current pagefile on the drive. + type: bool + default: 'yes' + system_managed: + description: + - Configures current pagefile to be managed by the system. + type: bool + default: 'no' + automatic: + description: + - Configures AutomaticManagedPagefile for the entire system. + type: bool + remove_all: + description: + - Remove all pagefiles in the system, not including automatic managed. + type: bool + default: 'no' + test_path: + description: + - Use Test-Path on the drive to make sure the drive is accessible before creating the pagefile. + type: bool + default: 'yes' + state: + description: + - State of the pagefile. + choices: + - present + - absent + - query + default: query +notes: +- There is difference between automatic managed pagefiles that configured once for the entire system and system managed pagefile that configured per pagefile. +- InitialSize 0 and MaximumSize 0 means the pagefile is managed by the system. +- Value out of range exception may be caused by several different issues, two common problems - No such drive, Pagefile size is too small. +- Setting a pagefile when AutomaticManagedPagefile is on will disable the AutomaticManagedPagefile. +author: +- Liran Nisanov (@LiranNis) +''' + +EXAMPLES = r''' +- name: Query pagefiles configuration + win_pagefile: + +- name: Query C pagefile + win_pagefile: + drive: C + +- name: Set C pagefile, don't override if exists + win_pagefile: + drive: C + initial_size: 1024 + maximum_size: 1024 + override: no + state: present + +- name: Set C pagefile, override if exists + win_pagefile: + drive: C + initial_size: 1024 + maximum_size: 1024 + state: present + +- name: Remove C pagefile + win_pagefile: + drive: C + state: absent + +- name: Remove all current pagefiles, enable AutomaticManagedPagefile and query at the end + win_pagefile: + remove_all: yes + automatic: yes + +- name: Remove all pagefiles disable AutomaticManagedPagefile and set C pagefile + win_pagefile: + drive: C + initial_size: 2048 + maximum_size: 2048 + remove_all: yes + automatic: no + state: present + +- name: Set D pagefile, override if exists + win_pagefile: + drive: d + initial_size: 1024 + maximum_size: 1024 + state: present +''' + +RETURN = r''' +automatic_managed_pagefiles: + description: Whether the pagefiles is automatically managed. + returned: When state is query. + type: boolean + sample: true +pagefiles: + description: Contains caption, description, initial_size, maximum_size and name for each pagefile in the system. + returned: When state is query. + type: list + sample: + [{"caption": "c:\\ 'pagefile.sys'", "description": "'pagefile.sys' @ c:\\", "initial_size": 2048, "maximum_size": 2048, "name": "c:\\pagefile.sys"}, + {"caption": "d:\\ 'pagefile.sys'", "description": "'pagefile.sys' @ d:\\", "initial_size": 1024, "maximum_size": 1024, "name": "d:\\pagefile.sys"}] + +''' diff --git a/test/integration/targets/win_pagefile/aliases b/test/integration/targets/win_pagefile/aliases new file mode 100644 index 0000000000..ee0ed5974e --- /dev/null +++ b/test/integration/targets/win_pagefile/aliases @@ -0,0 +1 @@ +windows/ci/group2 diff --git a/test/integration/targets/win_pagefile/tasks/main.yml b/test/integration/targets/win_pagefile/tasks/main.yml new file mode 100644 index 0000000000..8e9555f555 --- /dev/null +++ b/test/integration/targets/win_pagefile/tasks/main.yml @@ -0,0 +1,220 @@ +--- +# Get current pagefiles status +- name: Get original pagefile settings + win_pagefile: + state: query + register: original_pagefile_settings + +# Test 1: Set c pagefile with inital and maximum size +- name: Set C pagefile as 1024-2048MB + win_pagefile: + remove_all: yes + drive: C + initial_size: 1024 + maximum_size: 2048 + override: yes + state: present + register: c_pagefile + +- name: Test set c pagefile + assert: + that: + - c_pagefile.changed == true + +- name: Query all pagefiles + win_pagefile: + state: query + register: pagefiles_query + +- name: Set fact for pagefile expected result + set_fact: + expected: + pagefiles: + - caption: "C:\\ 'pagefile.sys'" + description: "'pagefile.sys' @ C:\\" + initial_size: 1024 + maximum_size: 2048 + name: "C:\\pagefile.sys" + +- name: Test query - c pagefile 1024-2048 + assert: + that: + - pagefiles_query.changed == false + - pagefiles_query.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + + +# Test 2: Remove c pagefile +- name: Remove C pagefile + win_pagefile: + drive: C + state: absent + register: delete_c_pagefile + +- name: Test removal of c pagefile + assert: + that: + - delete_c_pagefile.changed == true + +- name: Query all pagefiles + win_pagefile: + state: query + register: pagefiles_query + +- name: Set fact for pagefile expected result + set_fact: + expected: + pagefiles: [] + +- name: Test query - no c pagefile + assert: + that: + - pagefiles_query.changed == false + - pagefiles_query.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + + +# Test 3: Set automatic managed pagefile as true +- name: Set automatic managed pagefiles as true + win_pagefile: + automatic: yes + register: set_automatic_true + +- name: Test removal of c pagefile + assert: + that: + - set_automatic_true.changed == true + - set_automatic_true.automatic_managed_pagefiles == true + + +# Test 4: Set c pagefile as system managed pagefile +- name: Set c pagefile as system managed pagefile + win_pagefile: + drive: C + system_managed: yes + state: present + register: c_pagefile_system_managed + +- name: Test set c pagefile as system managed + assert: + that: + - c_pagefile_system_managed.changed == true + +- name: Query all pagefiles + win_pagefile: + state: query + register: pagefiles_query + +- name: Set fact for pagefile expected result + set_fact: + expected: + pagefiles: + - caption: "C:\\ 'pagefile.sys'" + description: "'pagefile.sys' @ C:\\" + initial_size: 0 + maximum_size: 0 + name: "C:\\pagefile.sys" + +- name: Test query - c pagefile 0-0 (system managed) + assert: + that: + - pagefiles_query.changed == false + - pagefiles_query.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + +# Test 5: Test no override +- name: Set c pagefile 1024-1024, no override + win_pagefile: + drive: C + initial_size: 1024 + maximum_size: 1024 + override: no + state: present + register: c_pagefile_no_override + +- name: Test set c pagefile no override + assert: + that: + - c_pagefile_no_override.changed == false + +- name: Query all pagefiles + win_pagefile: + state: query + register: pagefiles_query + +- name: Test query - c pagefile unchanged + assert: + that: + - pagefiles_query.changed == false + - pagefiles_query.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + + +# Test 6: Test override +- name: Set c pagefile 1024-1024, override + win_pagefile: + drive: C + initial_size: 1024 + maximum_size: 1024 + state: present + register: c_pagefile_override + +- name: Test set c pagefile no override + assert: + that: + - c_pagefile_override.changed == true + +- name: Query all pagefiles + win_pagefile: + state: query + register: pagefiles_query + +- name: Set fact for pagefile expected result + set_fact: + expected: + pagefiles: + - caption: "C:\\ 'pagefile.sys'" + description: "'pagefile.sys' @ C:\\" + initial_size: 1024 + maximum_size: 1024 + name: "C:\\pagefile.sys" + +- name: Test query - c pagefile 1024-1024 + assert: + that: + - pagefiles_query.changed == false + - pagefiles_query.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + +# Test 7: Remove all pagefiles +- name: Remove all pagefiles + win_pagefile: + remove_all: true + register: remove_all_pagefiles + +- name: Set fact for pagefile expected result + set_fact: + expected: + pagefiles: [] + +- name: Test query - no pagefiles + assert: + that: + - remove_all_pagefiles.changed == true + - remove_all_pagefiles.pagefiles == expected.pagefiles + - pagefiles_query.automatic_managed_pagefiles == false + +# Return all pagefile settings to its original state +- name: Remove all pagefiles and return automatic to its original state + win_pagefile: + remove_all: yes + automatic: "{{ original_pagefile_settings.automatic_managed_pagefiles }}" + +- name: Return all previous pagefiles settings + win_pagefile: + drive: "{{ item.name[0] }}" + initial_size: "{{ item.initial_size }}" + maximum_size: "{{ item.maximum_size }}" + test_path: no + state: present + with_items: "{{ original_pagefile_settings.pagefiles }}"