PageRenderTime 48ms CodeModel.GetById 10ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/ansible/modules/windows/win_wait_for_process.ps1

https://github.com/debfx/ansible
Powershell | 176 lines | 129 code | 33 blank | 14 comment | 39 complexity | a3879fa6e4893f3f6fdfa1fa79a40191 MD5 | raw file
  1#!powershell
  2
  3# Copyright: (c) 2017, Ansible Project
  4# Copyright: (c) 2018, Dag Wieers (@dagwieers) <dag@wieers.com>
  5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
  6
  7#AnsibleRequires -CSharpUtil Ansible.Basic
  8#Requires -Module Ansible.ModuleUtils.SID
  9
 10$spec = @{
 11    options = @{
 12        process_name_exact = @{ type='list' }
 13        process_name_pattern = @{ type='str' }
 14        pid = @{ type='int'; default=0 }
 15        owner = @{ type='str' }
 16        sleep = @{ type='int'; default=1 }
 17        pre_wait_delay = @{ type='int'; default=0 }
 18        post_wait_delay = @{ type='int'; default=0 }
 19        process_min_count = @{ type='int'; default=1 }
 20        state = @{ type='str'; default='present'; choices=@( 'absent', 'present' ) }
 21        timeout = @{ type='int'; default=300 }
 22    }
 23    mutually_exclusive = @(
 24        @( 'pid', 'process_name_exact' ),
 25        @( 'pid', 'process_name_pattern' ),
 26        @( 'process_name_exact', 'process_name_pattern' )
 27    )
 28    required_one_of = @(
 29        ,@( 'owner', 'pid', 'process_name_exact', 'process_name_pattern' )
 30    )
 31    supports_check_mode = $true
 32}
 33
 34$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
 35
 36$process_name_exact = $module.Params.process_name_exact
 37$process_name_pattern = $module.Params.process_name_pattern
 38$process_id = $module.Params.pid  # pid is a reserved variable in PowerShell, using process_id instead
 39$owner = $module.Params.owner
 40$sleep = $module.Params.sleep
 41$pre_wait_delay = $module.Params.pre_wait_delay
 42$post_wait_delay = $module.Params.post_wait_delay
 43$process_min_count = $module.Params.process_min_count
 44$state = $module.Params.state
 45$timeout = $module.Params.timeout
 46
 47$module.Result.changed = $false
 48$module.Result.elapsed = 0
 49$module.Result.matched_processes = @()
 50
 51# Validate the input
 52if ($state -eq "absent" -and $sleep -ne 1) {
 53    $module.Warn("Parameter 'sleep' has no effect when waiting for a process to stop.")
 54}
 55
 56if ($state -eq "absent" -and $process_min_count -ne 1) {
 57    $module.Warn("Parameter 'process_min_count' has no effect when waiting for a process to stop.")
 58}
 59
 60if ($owner -and ("IncludeUserName" -notin (Get-Command -Name Get-Process).Parameters.Keys)) {
 61    $module.FailJson("This version of Powershell does not support filtering processes by 'owner'.")
 62}
 63
 64Function Get-FilteredProcesses {
 65    [cmdletbinding()]
 66    Param(
 67        [String]
 68        $Owner,
 69        $ProcessNameExact,
 70        $ProcessNamePattern,
 71        [int]
 72        $ProcessId
 73    )
 74
 75    $FilteredProcesses = @()
 76
 77    try {
 78        $Processes = Get-Process -IncludeUserName
 79        $SupportsUserNames = $true
 80    } catch [System.Management.Automation.ParameterBindingException] {
 81        $Processes = Get-Process
 82        $SupportsUserNames = $false
 83    }
 84
 85    foreach ($Process in $Processes) {
 86
 87        # If a process name was specified in the filter, validate that here.
 88        if ($ProcessNamePattern) {
 89            if ($Process.ProcessName -notmatch $ProcessNamePattern) {
 90                continue
 91            }
 92        }
 93
 94        # If a process name was specified in the filter, validate that here.
 95        if ($ProcessNameExact -is [Array]) {
 96            if ($ProcessNameExact -notcontains $Process.ProcessName) {
 97                continue
 98            }
 99        } elseif ($ProcessNameExact) {
100            if ($ProcessNameExact -ne $Process.ProcessName) {
101                continue
102            }
103        }
104
105        # If a PID was specified in the filter, validate that here.
106        if ($ProcessId -and $ProcessId -ne 0) {
107            if ($ProcessId -ne $Process.Id) {
108                continue
109            }
110        }
111
112        # If an owner was specified in the filter, validate that here.
113        if ($Owner) {
114            if (-not $Process.UserName) {
115                continue
116            } elseif ((Convert-ToSID($Owner)) -ne (Convert-ToSID($Process.UserName))) {  # NOTE: This is rather expensive
117                continue
118            }
119        }
120
121        if ($SupportsUserNames -eq $true) {
122            $FilteredProcesses += @{ name = $Process.ProcessName; pid = $Process.Id; owner = $Process.UserName }
123        } else {
124            $FilteredProcesses += @{ name = $Process.ProcessName; pid = $Process.Id }
125        }
126    }
127
128    return ,$FilteredProcesses
129}
130
131$module_start = Get-Date
132Start-Sleep -Seconds $pre_wait_delay
133
134if ($state -eq "present" ) {
135
136    # Wait for a process to start
137    do {
138
139        $Processes = Get-FilteredProcesses -Owner $owner -ProcessNameExact $process_name_exact -ProcessNamePattern $process_name_pattern -ProcessId $process_id
140        $module.Result.matched_processes = $Processes
141
142        if ($Processes.count -ge $process_min_count) {
143            break
144        }
145
146        if (((Get-Date) - $module_start).TotalSeconds -gt $timeout) {
147            $module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
148            $module.FailJson("Timed out while waiting for process(es) to start")
149        }
150
151        Start-Sleep -Seconds $sleep
152
153    } while ($true)
154
155} elseif ($state -eq "absent") {
156
157    # Wait for a process to stop
158    $Processes = Get-FilteredProcesses -Owner $owner -ProcessNameExact $process_name_exact -ProcessNamePattern $process_name_pattern -ProcessId $process_id
159    $module.Result.matched_processes = $Processes
160
161    if ($Processes.count -gt 0 ) {
162        try {
163            # This may randomly fail when used on specially protected processes (think: svchost)
164            Wait-Process -Id $Processes.pid -Timeout $timeout
165        } catch [System.TimeoutException] {
166            $module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
167            $module.FailJson("Timeout while waiting for process(es) to stop")
168        }
169    }
170
171}
172
173Start-Sleep -Seconds $post_wait_delay
174$module.Result.elapsed = ((Get-Date) - $module_start).TotalSeconds
175
176$module.ExitJson()