1
votes

I have a powershell script that stops/starts VM in parallel at specific time using Jenkins. This script uses the -AsJob powershell cmdlet, this way the VMs show they are stopped in Jenkins output but really they are in process of deallocating in the Azure portal.

I also have a sleep timer for 5 minutes to get the Get-AzureRmVM -Status command.

Question:- Is there a way to loop it where I can check for the status of the VMs and if the VMs are NOT in Deallocated or Running state, the Script checks back in another minute or so. Once the VMs are finally in deallocated or running state, the script/job exits with success.

Code snippet

$JobList = @()

foreach ($VM in $vms)
{
    if ($env:OPTION -eq "start") 
    {
        Write-Output "Starting :- $($VM.Name) in $($VM.ResourceGroupName)"

        $JobList += Start-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -AsJob -Verbose

        Write-Output "$($VM.Name) has started successfully `n"
        Write-Output "--------------------------------------------------"
    }

    elseif ($env:OPTION -eq "stop") 
    {
        Write-Output "Deallocating :- $($VM.Name) in $($VM.ResourceGroupName)"

        $JobList += Stop-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Force -AsJob -Verbose

        Write-Output "$($VM.Name) has been deallocated successfully `n"
        Write-Output "--------------------------------------------------"
    }

    else
    {
        Write-Output "ERROR!!! No option selected, select an option"
    }

}

sleep 300

Write-Output "`n##############################################"
Write-Output "###   Writing Status of VMs to Workspace   ###"
Write-Output "##############################################"
Get-AzureRmVM -Status | Where-Object {($_.tags.ManagedBy -eq "blaah") -And ($_.tags.Environment -eq "stage")}

EDIT - This code checks the status of the VM to see if it is deallocated. I cannot get it to run the loop over again because the VMs are in Running state.screenshot

$vms = (Get-AzureRmResource | Where-Object {($_.tags.ManagedBy -eq "blaah") -And ($_.tags.Environment -eq "Stage")}

foreach ($VM in $VMs) {

    $vmDetail = Get-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status

        foreach ($vmDetail in $vmDetail.Statuses[1]) {

            $VMStatusDetail = $vmDetail.DisplayStatus

            if ($VMStatusDetail -ne "Stopped") {      

                Write-Output "Waiting for $($VM.Name) to deallocate"
                Write-Output "State:- $($VM.Name) is $VMStatusDetail"

                start-sleep -s 5
            }
            else {
                    Write-Output "State:- $($VM.Name) is $VMStatusDetail"
            }

       }
}
1

1 Answers

2
votes

If you throw the Stop-AzureRMVM as Jobs and keep the output in array of Jobs called $JobList, once all jobs have started, at the end and outside the loop you can add the following command to wait the jobs finish.

Write-Host $JobList
$JobList| Get-Job | Wait-Job |  Receive-Job |  Format-Table -AutoSize