简体   繁体   中英

Unable to retrieve Azure Virtual Machine status from within a workflow

I am trying to check whether or not my Azure virtual machines are running before deploying CodedUI tests to them. This is all done within an Azure DevOps pipeline.

The script was running fine when outside of a workflow. We wanted to convert the ForEach loop to run in parallel, so we decided to try putting it into a workflow (we do this for multiple VMs at the same time).

For some reason, I can't seem to get the list of Statuses for the VM when this is done in a workflow.

I realize that I can just use the Test-Connection to see if the VM is running, but it's really bothering me that this method isn't working.


$context = Get-AzSubscription -SubscriptionId 'Subscription GUID'
Set-AzContext $context

workflow Check-VM-Status {

    Param ([string[]]$VMNames)

    if($VMNames.Count -eq 0)
    {
        Write-Output "You must provide one or more VM names."
    }
    else
    {
        #Start-Sleep -Seconds 120
        $VMListJSON = Get-AzVM -Name MyVM* | ConvertTo-Json
        $VMList = $VMListJSON | ConvertFrom-Json

        ForEach -Parallel ($VMName in $VMNames)
        {
            Write-Output "Checking VM status for $VMName."

            $VM = $VMList | where { $_.Name -eq $VMName }

            $VM = Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Status
            $attempts = 0

            $statuses = $VM.Statuses
            $code = $statuses[1].Code

            if($code -ne 'PowerState/running')
            {
                do
                {
                    Write-Output -InputObject "Check #$attempts. $($VM.Name) is not yet running. Re-checking in 120 seconds..."
                    Start-Sleep -Seconds 120
                    $VM = Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Status 

                    $attempts++
                }
                while ($($VM.Statuses[1].Code) -ne 'PowerState/running' -and $attempts -lt 11)

                if ($($VM.Statuses[1].Code) -eq 'PowerState/running')
                {
                    Write-Output "$($VM.Name) is running. Allow VM to finish the start up process (120 seconds) before continuing."
                    Start-Sleep -Seconds 120
                    $Ping = Test-Connection -ComputerName $VMName -Delay 5 -Quiet
                    if ($Ping)
                    {
                       Write-Output "$($VM.Name) is started and running."
                    }
                    else
                    {
                       Write-Output "$($VM.Name) failed to respond."
                    }
                }
                else
                {
                    Write-Error "$($VM.Name) is still not running after 10 attempts to check status (20 minutes). Status is $($VM.Statuses[1].Code)."
                }
            }
            else
            {
                Write-Output "$($VM.Name) is already running. Allow VM to finish the start up process (120 seconds) before continuing."
                Start-Sleep -Seconds 120
                $Ping = Test-Connection -ComputerName $VMName -Delay 5 -Quiet
                if ($Ping)
                {
                  Write-Output "$($VM.Name) is started and running."
                }
                else
                {
                  Write-Output "$($VM.Name) failed to respond."
                }
            }
        }
    }
}

Check-VM-Status ('MyVM01')

Based on my test, while running Parallelly in workflow, the following command does not work appropriately:

$VM = Get-AzVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Status
$VM.Statuses[1].Code # The value is always empty, so all the following scripts fails 

My solution is to use PowerShell runspace:

function Get-VM-Status([string[]] $VMNames, [int] $ThrottleLimit){

    $SessionState = [system.management.automation.runspaces.initialsessionstate]::CreateDefault()
    $Pool = [runspacefactory]::CreateRunspacePool(1, $ThrottleLimit, $SessionState, $Host)
    $Pool.Open()

    $ScriptBlock = {
        param($Current_VMName,$All_VMs)
        $Current_VM = $All_VMs | where { $_.Name -eq $Current_VMName }
        $Current_VM = Get-AzVM -ResourceGroupName $Current_VM.ResourceGroupName -Name $Current_VM.Name -Status
        Write-Output ("Checking VM status for $Current_VMName -> " + $Current_VM.Statuses[1].Code)
    }

    $threads = New-Object System.Collections.ArrayList

    $VMs = Get-AzVM
    $handles = foreach ($VMName in $VMNames) {
        $powershell = [powershell]::Create().AddScript($ScriptBlock).AddArgument($VMName).AddArgument($VMs)
        $powershell.RunspacePool = $Pool
        $powershell.BeginInvoke()
        $threads += $powershell
    }

    do {
      $i = 0
      $done = $true
      foreach ($handle in $handles) {
        if ($handle -ne $null) {
          if ($handle.IsCompleted) {
            $threads[$i].EndInvoke($handle)
            $threads[$i].Dispose()
            $handles[$i] = $null
          } else {
            $done = $false
          }
        }
        $i++
      }
      if (-not $done) { Start-Sleep -Milliseconds 500 }
    } until ($done)
    $Pool.Close()
    $Pool.Dispose()
}

$vms = Get-AzVM | %{$_.Name} 

Get-VM-Status -VMNames $vms -ThrottleLimit 20

With the above script, I can get 13 VMs' statuses in several seconds:

PS C:\WINDOWS\system32> Get-VM-Status -VMNames $vms -ThrottleLimit 20
Checking VM status for test-sql -> PowerState/running
Checking VM status for winsvr-2016 -> PowerState/running
Checking VM status for vs2019 -> PowerState/running
Checking VM status for dc-ericm -> PowerState/running
Checking VM status for ericmex13 -> PowerState/deallocated
Checking VM status for win2016-ericm -> PowerState/running
Checking VM status for testvm -> PowerState/running
Checking VM status for StanLinuxTest -> PowerState/running
Checking VM status for win2012 -> PowerState/running
Checking VM status for testvm2 -> PowerState/running
Checking VM status for CXPCMT -> PowerState/running
Checking VM status for win2019DC -> PowerState/running
Checking VM status for test -> PowerState/running

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM