Start-AzureRMVMAllRunbook.ps1
<#PSScriptInfo .VERSION 1.1.0 .GUID f886e06d-323d-4eb1-a3ca-bd9e66524ec9 .AUTHOR Arjun Bahree .COMPANYNAME .COPYRIGHT (c) 2018 Arjun Bahree. All rights reserved. .TAGS Windows PowerShell Azure AzureAutomation Runbooks AzureVM .LICENSEURI https://github.com/bahreex/Bahree-PowerShell-Library/blob/master/LICENSE .PROJECTURI https://github.com/bahreex/Bahree-PowerShell-Library/tree/master/Azure%20Automation%20Runbooks .ICONURI .EXTERNALMODULEDEPENDENCIES AzureRM .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> <# .DESCRIPTION Asynchronously Starts all or specific Azure RM VMs in an Azure Subscription as a Runbook from within an Azure Automation Account #> <# .SYNOPSIS Asynchronously Starts all or specific Azure RM VMs in an Azure Subscription as a Runbook from within an Azure Automation Account .DESCRIPTION This Runbook asynchronously Starts either all Azure RM VMs in an Azure Subscription, or all Azure RM VMs in one or more specified Resource Groups, or one or more VMs in a specific Resource Group, or any number of Random VMs in a Subscription. You can specify one or more Resource Groups to exclude, wherein all VMs in those Resource Groups will not be started. You can specify one or more VMs to exclude, wherein all those VMs will not be started. The choice around which VMs to start depends on the combination and values of the parameters provided. You need to execute this Runbook through a 'Azure Run As account (service principal)' Identity from an Azure Automation account. .PARAMETER ResourceGroupName Name of the Resource Group containing the VMs you want to Start. Specifying just the Resource Group without the "VMName" parameter will consider all VMs in that specified Resource Group. You can specify an array of Resource Group names without "VMname" parameter, and all VMs withihn the specified Resource Groups in the array will be started. You can specify just a single Resource Group Name in this parameter, along with one or more VM names in the "VMName" parameter, wherein all the VMs specified will be started in that specific Resource Group. You cannot specify more than one Resource Group Names when combined with the "VMName" parameter. .PARAMETER VMName Name of the VM you want to Start. This parameter when specified alone, without the "ResourceGroupName" parameter, can Include one or more VM Names to be started across any resource groups in the Azure Subscription. When specified with the "ResourceGroupName" parameter, you need to Include one or more VMs in the specified Resource Group only. .PARAMETER ExcludedResourceGroupName Name of the Resource Group(s) containing the VMs you want excluded from being Started. It cannot be combined with "ResourceGroupName" and "VMName" parameters. .PARAMETER ExcludedVMName Name of the VM(s) you want excluded from being Started. It cannot be combined with "VMName" parameter. .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1,RG2,RG3 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1 -VMName VM01 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1 -VMName VM01,VM02,VM05 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -VMName VM01,VM011,VM23,VM35 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ExcludedResourceGroupName RG5,RG6,RG7 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ExcludedResourceGroupName RG5,RG6,RG7 -ExludedVMName VM5,VM6,VM7 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1 -ExcludedVMName VM5,VM6,VM7 .EXAMPLE .\Start-AzureRMVMAllRunbook.ps1 -ResourceGroupName RG1,RG2,RG3 -ExcludedVMName VM5,VM6,VM7 .Notes Author: Arjun Bahree E-mail: arjun.bahree@gmail.com Creation Date: 10/Jan/2018 Last Revision Date: 15/Jan/2018 Development Environment: Azure Automation Runbook Editor and VS Code IDE PS Version: 5.1 Platform: Windows #> param( [Parameter(Mandatory = $false)] [String[]]$ResourceGroupName, [Parameter(Mandatory = $false)] [String[]]$VMName, [Parameter(Mandatory=$false)] [String[]]$ExcludedResourceGroupName, [Parameter(Mandatory=$false)] [String[]]$ExcludedVMName ) if (!(Get-AzureRmContext).Account) { $connectionName = "AzureRunAsConnection" try { # Get the connection "AzureRunAsConnection " $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName Add-AzureRmAccount ` -ServicePrincipal ` -TenantId $servicePrincipalConnection.TenantId ` -ApplicationId $servicePrincipalConnection.ApplicationId ` -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint > $null } catch { if (!$servicePrincipalConnection) { $ErrorMessage = "Connection $connectionName not found." throw $ErrorMessage } else { Write-Error -Message $_.Exception throw $_.Exception } } } # Create Stopwatch and Start the Timer $StopWatch = New-Object -TypeName System.Diagnostics.Stopwatch $StopWatch.Start() [System.Collections.ArrayList]$jobQ = @() # Check if both Resource Groups and VM Name params are not passed If (!$PSBoundParameters.ContainsKey('ResourceGroupName') -And !$PSBoundParameters.ContainsKey('VMName')) { # Get a list of all the VMs across all Resource Groups in the Subscription $VMs = Get-AzureRmVm # Check if one or more VMs were discovered across Subscription if ($VMs) { # Iterate through all the VMs discovered within the Subscription foreach ($vmx in $VMs) { If ($PSBoundParameters.ContainsKey('ExcludedResourceGroupName')) { if ($ExcludedResourceGroupName -contains $vmx.ResourceGroupName) { Write-Output "Skipping VM {$($vmx.Name)} since the Resource Group {$($vmx.ResourceGroupName)} containing it is specified as Excluded..." continue } } If ($PSBoundParameters.ContainsKey('ExcludedVMName')) { if ($ExcludedVMName -Contains $vmx.Name) { Write-Output "Skipping VM {$($vmx.Name)} since it is specified as Excluded..." continue } } # Get reference to the specific VM for this Iteration $vm = Get-AzureRmVM -ResourceGroupName $vmx.ResourceGroupName -Name $vmx.Name $VMBaseName = $vm.Name $RGBaseName = $vm.ResourceGroupName # Get current status of the VM $vmstatus = Get-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -Status # Extract current Power State of the VM $VMState = $vmstatus.Statuses[1].Code.Split('/')[1] # Check PowerState Level of the VM, and start it only if it is in a "Running" or "Starting" state if ($VMState) { if ($VMState -in "deallocated","stopped") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is currently Deallocated/Stopped. Starting..." $retval = Start-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -AsJob $jobQ.Add($retval) > $null } elseif ($VMState -in "running","starting") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is either already Started or Starting. Skipping." continue } elseif ($VMState -in "stopping","deallocating") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is in a transient state of Stopping or Deallocating. Skipping." continue } } else { Write-Output "Unable to determine PowerState of the VM {$VMBaseName} in Resource Group {$RGBaseName}. Hence, cannot start the VM. Skipping to next VM..." continue } } } else { Write-Output "There are no VMs in the Azure Subscription." continue } } # Check if only Resource Group param is passed, but not the VM Name param Elseif ($PSBoundParameters.ContainsKey('ResourceGroupName') -And !$PSBoundParameters.ContainsKey('VMName')) { If ($PSBoundParameters.ContainsKey('ExcludedResourceGroupName')) { Write-Output "You cannot specify Parameters 'ExcludedResourceGroupName' together with 'ResourceGroupName'" return } foreach ($rg in $ResourceGroupName) { # Get a list of all the VMs in the specific Resource Group $VMs = Get-AzureRmVm -ResourceGroupName $rg -ErrorAction SilentlyContinue if(!$?) { Write-Output "The Resource Group {$rg} does not exist. Skipping." continue } if ($VMs) { # Iterate through all the VMs within the specific Resource Group for this Iteration foreach ($vm in $VMs) { If ($PSBoundParameters.ContainsKey('ExcludedVMName')) { if ($ExcludedVMName -Contains $vm.Name) { Write-Output "Skipping VM {$($vm.Name)} from Resource Group {$rg} since it is specified as Excluded..." continue } } $VMBaseName = $vm.Name # Get current status of the VM $vmstatus = Get-AzureRmVM -ResourceGroupName $rg -Name $VMBaseName -Status # Extract current Power State of the VM $VMState = $vmstatus.Statuses[1].Code.Split('/')[1] if ($VMState) { if ($VMState -in "deallocated", "stopped") { Write-Output "The VM {$VMBaseName} in Resource Group {$rg} is currently Deallocated/Stopped. Starting..." $retval = Start-AzureRmVM -ResourceGroupName $rg -Name $VMBaseName -AsJob $jobQ.Add($retval) > $null } elseif ($VMState -in "running","starting") { Write-Output "The VM {$VMBaseName} in Resource Group {$rg} is either already Started or Starting. Skipping." continue } elseif ($VMState -in "stopping","deallocating") { Write-Output "The VM {$VMBaseName} in Resource Group {$rg} is in a transient state of Stopping or Deallocating. Skipping." continue } } else { Write-Output "Unable to determine PowerState of the VM {$VMBaseName} in Resource Group {$rg}. Hence, cannot start the VM. Skipping to next VM..." continue } } } else { Write-Output "There are no Virtual Machines in Resource Group {$rg}. Skipping to next Resource Group" continue } } } # Check if both Resource Group and VM Name params are passed Elseif ($PSBoundParameters.ContainsKey('ResourceGroupName') -And $PSBoundParameters.ContainsKey('VMName')) { # You cannot specify Resource Groups more than 1 when both ResourceGroupName and VMName parameters are specified if ($ResourceGroupName.Count -gt 1) { Write-Output "You can only specify a single Resource Group Name value when using both 'ResourceGroupName' and 'VMName' parameters together." return } If ($PSBoundParameters.ContainsKey('ExcludedResourceGroupName')) { Write-Output "You cannot specify Parameters 'ExcludedResourceGroupName' together with 'ResourceGroupName'" return } If ($PSBoundParameters.ContainsKey('ExcludedVMName')) { Write-Output "You cannot specify Parameters 'ExcludedVMName' together with 'ResourceGroupName' and 'VMName'" return } # Check if Resource Group exists $testRG = Get-AzureRmResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue if (!$testRG) { Write-Output "The Resource Group {$ResourceGroupName} does not exist. Skipping." continue } # Iterate through all VM's specified foreach ($vms in $VMName) { # Get the specified VM in the specific Resource Group $vm = Get-AzureRmVm -ResourceGroupName $ResourceGroupName -Name $vms -ErrorAction SilentlyContinue if ($vm) { $VMBaseName = $vm.Name $RGBaseName = $vm.ResourceGroupName # Get current status of the VM $vmstatus = Get-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -Status # Extract current Power State of the VM $VMState = $vmstatus.Statuses[1].Code.Split('/')[1] if ($VMState) { if ($VMState -in "deallocated","stopped") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is currently Deallocated/Stopped. Starting..." $retval = Start-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -AsJob $jobQ.Add($retval) > $null } elseif ($VMState -in "running","starting") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is either already Started or Starting. Skipping" continue } elseif ($VMState -in "stopping","deallocating") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is in a transient state of Stopping or Deallocating. Skipping." continue } } else { Write-Output "Unable to determine PowerState of the VM {$VMBaseName} in Resource Group {$RGBaseName}. Hence, cannot start the VM. Skipping to next VM..." continue } } else { Write-Error "There is no Virtual Machine named {$vms} in Resource Group {$ResourceGroupName}. Aborting..." return } } } # Check if Resource Group param is not passed, but VM Name param is passed Elseif (!$PSBoundParameters.ContainsKey('ResourceGroupName') -And $PSBoundParameters.ContainsKey('VMName')) { If ($PSBoundParameters.ContainsKey('ExcludedResourceGroupName')) { Write-Output "You cannot specify Parameters 'ExcludedResourceGroupName' and 'VMName' together" return } If ($PSBoundParameters.ContainsKey('ExcludedVMName')) { Write-Output "You cannot specify Parameters 'ExcludedVMName' and 'VMName' together" return } foreach ($vms in $VMName) { # Find the specific VM resource $vmFind = Find-AzureRmResource -ResourceNameEquals $vms # If the VM resource is found in the Subscription if ($vmFind) { # Extract the Resource Group Name of the VM $RGBaseName = $vmFind.ResourceGroupName # Get reference object of the VM $vm = Get-AzureRmVm -ResourceGroupName $RGBaseName -Name $vms if ($vm) { $VMBaseName = $vm.Name # Get current status of the VM $vmstatus = Get-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -Status # Extract current Power State of the VM $VMState = $vmstatus.Statuses[1].Code.Split('/')[1] if ($VMState) { if ($VMState -in "deallocated","stopped") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is currently Deallocated/Stopped. Starting..." $retval = Start-AzureRmVM -ResourceGroupName $RGBaseName -Name $VMBaseName -AsJob $jobQ.Add($retval) > $null } elseif ($VMState -in "running","starting") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is either already Started or Starting. Skipping." continue } elseif ($VMState -in "stopping","deallocating") { Write-Output "The VM {$VMBaseName} in Resource Group {$RGBaseName} is in a transient state of Stopping or Deallocating. Skipping." continue } } else { Write-Output "Unable to determine PowerState of the VM {$VMBaseName} in Resource Group {$RGBaseName}. Hence, cannot start the VM. Skipping to next VM..." continue } } else { Write-Error "There is no Virtual Machine named {$vms} in the Azure Subscription. Aborting..." return } } else { Write-Output "Could not find Virtual Machine {$vms} in the Azure Subscription." continue } } } Get-Job | Wait-Job | Receive-Job > $null # Stop the Timer $StopWatch.Stop() # Display the Elapsed Time Write-Output "Total Execution Time for Starting All Target VMs:" + $StopWatch.Elapsed.ToString() Write-Output "All Target VM's which were stopped/deallocated, have been Started Successfully!" |