public/Stop-UnraidArray.ps1
|
function Stop-UnraidArray { <# .SYNOPSIS Stops the Unraid array. .DESCRIPTION Initiates a stop of the Unraid array. Handles API reporting lag where state remains STARTED despite stop command. .PARAMETER Array An object representing the current array state. .PARAMETER Session The active Unraid session. .PARAMETER WaitTimeout Seconds to wait for the array to stop - default is 600. .PARAMETER Force Sends the stop command even if the API reports the array is already stopped. .EXAMPLE Stop-UnraidArray -Force #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] [OutputType('void')] param( [Parameter(ValueFromPipeline)] [psobject]$Array, [Parameter()] [UnraidSession]$Session = $script:DefaultUnraidSession, [Parameter()] [int]$WaitTimeout = 600, [Parameter()] [switch]$Force ) process { if (!$Array) { Write-Verbose "Checking status..." $Array = Get-UnraidArray -Session $Session } if ($Array.State -eq "STOPPED" -and !$Force) { Write-Warning "Array is already stopped. Use -Force to override." return } if ($PSCmdlet.ShouldProcess("Unraid Array", "Stop array")) { $gqlQuery = @" mutation SetArrayState { array { setState(input: { desiredState: STOP }) { state } } } "@ $commandSent = $false try { Write-Verbose "Sending stop command..." $result = Invoke-UnraidQuery -Query $gqlQuery -Session $Session $commandSent = $true $currentState = $result.array.setState.state } catch { $ex = $_.Exception # Check for "already stopped" if ($ex.Message -match "already STOPPED") { Write-Information "Array is already STOPPED." -InformationAction Continue return } # The API seems to return 504 timeouts pretty often when stopping the array # This happenes regardless of a failure or success - so don't neccessary treat it as an error elseif ($ex.Message -match "504" -or ($ex.Response -and $ex.Response.StatusCode -eq 504)) { Write-Warning "Server timed out (504) waiting for disks to unmount. Starting timer-based stop monitoring..." $commandSent = $true $currentState = "UNKNOWN" } else { $PSCmdlet.ThrowTerminatingError($_) } } if ($commandSent) { $timer = [System.Diagnostics.Stopwatch]::StartNew() while ($currentState -ne "STOPPED" -and $timer.Elapsed.TotalSeconds -lt $WaitTimeout) { $remaining = $WaitTimeout - [int]$timer.Elapsed.TotalSeconds Write-Progress -Activity "Stopping Unraid Array" -Status "Current State: $currentState" -SecondsRemaining $remaining Start-Sleep -Seconds 5 try { $statusCheck = Get-UnraidArray -Session $Session $currentState = $statusCheck.State # If we see the specialized Unmounted state, it might mean the Stop worked partially? if ($statusCheck.State -like "*UNMOUNTED*") { $currentState = "STOPPING (API UNSYNCED)" } } catch { Write-Verbose "Poll failed: $($_.Exception.Message)" } } $timer.Stop() Write-Progress -Activity "Stopping Unraid Array" -Completed if ($currentState -eq "STOPPED") { Write-Information "Array stopped." -InformationAction Continue } else { # Likely that the command worked, but the API didn't update? Write-Warning "Timed out waiting for state update. The Stop command was sent and likely succeeded, but the API is still reporting $($currentState).`nThe API is likely not synced to the current server state. You likely need to run 'Restart-UnraidApi' to reset the state, then rerun this command or Get-UnraidArray to verify status." } } } } } |