Search code examples
powershellif-statementpowerclivmware-tools

Foreach, last condition don't need "OK" for every vm it finds


I have a script that is supposed to have 3 different exit codes: OK 0 Warning 1 Critical 2

I want it to only write output for each of these depending on conditions and it works fine for 1 and 2 since I want to display the name of the vm's. The reason I use array is because I might want to display the VM's with "Warning" for other purposes.

The problem I have is that this script will write "OK" for each vm that doesn't meet the other criteria. I simply need one "OK", that nothing needs to be done if no other criteria is met. I need help with the overall logic of this script.

$old = @()
$noinstall = @()
$status = 0
$vmtools = Get-VM | select name, @{N = ”ToolsStatus”; E = { $_.Extensiondata.Summary.Guest.ToolsStatus } }

foreach ($vmtool in $vmtools) {
    if (($vmtool.ToolsStatus) -eq 'toolsOld') {
        $arraytest1 = Write-Output "CRITICAL: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        $old += , $arraytest1
        $Status = 2
        Write-output $old

    }
    elseif (($vmtool.Toolsstatus) -eq 'toolsNotInstalled' -And $status -ne 2) {
        Write-output "WARNING: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        $status = 1
    }
    elseif (($vmtool.Toolsstatus) -eq 'toolsNotInstalled' -And $status -eq 2) {
        $arraytest = Write-output "WARNING: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        $noinstall += , $arraytest
    }
    else {
        Write-Output "OK"
    }    
}
exit $status

Edit: I might as well just end with an elseif ($status -eq 0) right? It will still write "OK" for every single vm though.


Solution

  • You need to perform your overall status check outside of the foreach loop if you don't want to output for each iteration.

    $status = 0
    $vmtools = Get-VM | select name, @{N = ”ToolsStatus”; E = { $_.Extensiondata.Summary.Guest.ToolsStatus } }
    
    foreach ($vmtool in $vmtools) {
        if (($vmtool.ToolsStatus) -eq 'toolsOld') {
            Write-Output "CRITICAL: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
            $Status = 2
        }
        elseif (($vmtool.Toolsstatus) -eq 'toolsNotInstalled' -And $status -ne 2) {
            Write-output "WARNING: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
            $status = 1
        }
        elseif (($vmtool.Toolsstatus) -eq 'toolsNotInstalled' -And $status -eq 2) {
            Write-output "WARNING: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        } 
    }
    if ($status -eq 0) {
        Write-Output "OK"
    }
    

    Alternatively, you could collect the output of the foreach and then do a comparison afterwards.

    $vmtools = Get-VM | select name, @{N = ”ToolsStatus”; E = { $_.Extensiondata.Summary.Guest.ToolsStatus } }
    
    $output = foreach ($vmtool in $vmtools) {
        if (($vmtool.ToolsStatus) -eq 'toolsOld') {
            Write-Output "CRITICAL: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        }
        elseif (($vmtool.Toolsstatus) -eq 'toolsNotInstalled') {
            Write-output "WARNING: $($vmtool.Name) ------ $($vmtool.ToolsStatus)"
        }
    }
    if (!$output) {
        Write-Output "OK"
    }