无法从工作流中检索Azure虚拟机状态

时间:2020-03-09 23:05:03

标签: azure powershell

我试图在将CodedUI测试部署到我的Azure虚拟机之前检查它们是否正在运行。这些都是在Azure DevOps管道中完成的。

在工作流程之外,脚本运行良好。我们想将ForEach循环转换为并行运行,因此我们决定尝试将其放入工作流中(我们同时对多个VM执行此操作)。

由于某种原因,在工作流程中完成此操作后,我似乎无法获得VM的状态列表。

我意识到我只能使用Test-Connection来查看VM是否正在运行,但是让我感到困扰的是该方法不起作用。


$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')

1 个答案:

答案 0 :(得分:0)

根据我的测试,在工作流中并行运行时,以下命令无法正常工作:

$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 

我的解决方案是使用PowerShell运行空间:

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

使用上述脚本,我可以在几秒钟内获得13个虚拟机的状态:

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
相关问题