-
Notifications
You must be signed in to change notification settings - Fork 0
/
TurnOnVMs.ps1
150 lines (128 loc) · 6.14 KB
/
TurnOnVMs.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#requires -Modules ThreadJob
<#
.SYNOPSIS
Start VMs as part of an Update Management deployment
.DESCRIPTION
This is an update of the Updatemanagement scripts found in runbook gallery. This script is intended to be run as a part of Update Management Pre/Post scripts.
It requires a RunAs account.
This script will ensure all Azure VMs in the Update Deployment are running so they recieve updates.
This script will store the names of machines that were started in an Automation variable so only those machines
are turned back off when the deployment is finished (UpdateManagement-TurnOffVMs.ps1)
If the VM is a WVD Spring 2020 Release session host and the Hostpool object is in the same resource group, it will also enable the drain mode set by the Turn on VM Script
.PARAMETER SoftwareUpdateConfigurationRunContext
This is a system variable which is automatically passed in by Update Management during a deployment.
#>
param(
[string]$SoftwareUpdateConfigurationRunContext
)
#region BoilerplateAuthentication
#This requires a RunAs account
$ServicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'
Add-AzAccount `
-ServicePrincipal `
-TenantId $ServicePrincipalConnection.TenantId `
-ApplicationId $ServicePrincipalConnection.ApplicationId `
-CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint
$AzureContext = Select-AzSubscription -SubscriptionId $ServicePrincipalConnection.SubscriptionID
#endregion BoilerplateAuthentication
#If you wish to use the run context, it must be converted from JSON
$context = ConvertFrom-Json $SoftwareUpdateConfigurationRunContext
$vmIds = $context.SoftwareUpdateConfigurationSettings.AzureVirtualMachines
$runId = "PrescriptContext" + $context.SoftwareUpdateConfigurationRunId
Write-Output " context : $($context.Value)"
if (!$vmIds)
{
#Workaround: Had to change JSON formatting
$Settings = ConvertFrom-Json $context.SoftwareUpdateConfigurationSettings
#Write-Output "List of settings: $Settings"
$VmIds = $Settings.AzureVirtualMachines
#Write-Output "Azure VMs: $VmIds"
if (!$vmIds)
{
Write-Output "No Azure VMs found"
return
}
}
#https://github.com/azureautomation/runbooks/blob/master/Utility/ARM/Find-WhoAmI
# In order to prevent asking for an Automation Account name and the resource group of that AA,
# search through all the automation accounts in the subscription
# to find the one with a job which matches our job ID
$AutomationResource = Get-AzResource -ResourceType Microsoft.Automation/AutomationAccounts
foreach ($Automation in $AutomationResource)
{
$Job = Get-AzAutomationJob -ResourceGroupName $Automation.ResourceGroupName -AutomationAccountName $Automation.Name -Id $PSPrivateMetadata.JobId.Guid -ErrorAction SilentlyContinue
if (!([string]::IsNullOrEmpty($Job)))
{
$ResourceGroup = $Job.ResourceGroupName
$AutomationAccount = $Job.AutomationAccountName
break;
}
}
#This is used to store the state of VMs
New-AzAutomationVariable -ResourceGroupName $ResourceGroup -AutomationAccountName $AutomationAccount -Name $runId -Value "" -Encrypted $false
$updatedMachines = @()
$startableStates = "stopped" , "stopping", "deallocated", "deallocating"
$jobIDs= New-Object System.Collections.Generic.List[System.Object]
#Parse the list of VMs and start those which are stopped
#Azure VMs are expressed by:
# subscription/$subscriptionID/resourcegroups/$resourceGroup/providers/microsoft.compute/virtualmachines/$name
$vmIds | ForEach-Object {
$vmId = $_
$split = $vmId -split "/";
$subscriptionId = $split[2];
$rg = $split[4];
$name = $split[8];
Write-Output ("Subscription Id: " + $subscriptionId)
$mute = Select-AzSubscription -Subscription $subscriptionId
$vm = Get-AzVM -ResourceGroupName $rg -Name $name -Status
#Query the state of the VM to see if it's already running or if it's already started
$state = ($vm.Statuses[1].DisplayStatus -split " ")[1]
if($state -in $startableStates) {
Write-Output "Starting '$($name)' ..."
#Store the VM we started so we remember to shut it down later
$updatedMachines += $vmId
try {
$HostPool = Get-AzWvdHostPool -ResourceGroupName $rg
Write-Output " Host Pools found : $($HostPool.ToJsonString())"
$HostPool | ForEach-Object {
$SessionHost = Get-AzWvdSessionHost -ResourceGroupName $rg -HostPoolName $_.Name
Write-Output " Session Host Found : $($SessionHost.ToJsonString())"
foreach( $sh in $SessionHost ){
$SessionHostName = $sh.Name.Split('/')[1]
Write-Output " Session Host Name : $($SessionHostName)"
$VMName = $SessionHostName.Split(".")[0]
if( $SessionHostName.ToLower().Contains($name.ToLower()) ) {
$DrainMode = Update-AzWvdSessionHost -Name $SessionHostName -HostPoolName $_.Name -ResourceGroupName $rg -AllowNewSession:$false
Write-Output " Drain mode successful: $($DrainMode.ToJsonString())"
}
}
}
}
catch {
Write-Output "Exception processing WVD Session hosts: $($_.exception.message)"
}
$newJob = Start-ThreadJob -ScriptBlock { param($resource, $vmname) Start-AzVM -ResourceGroupName $resource -Name $vmname} -ArgumentList $rg,$name
$jobIDs.Add($newJob.Id)
}else {
Write-Output ($name + ": no action taken. State: " + $state)
}
}
$updatedMachinesCommaSeperated = $updatedMachines -join ","
#Wait until all machines have finished starting before proceeding to the Update Deployment
$jobsList = $jobIDs.ToArray()
if ($jobsList)
{
Write-Output "Waiting for machines to finish starting..."
Wait-Job -Id $jobsList
}
foreach($id in $jobsList)
{
$job = Get-Job -Id $id
if ($job.Error)
{
Write-Output $job.Error
}
}
Write-output $updatedMachinesCommaSeperated
#Store output in the automation variable
Set-AzAutomationVariable -Name $runId -Value $updatedMachinesCommaSeperated -Encrypted $false -ResourceGroupName $rg -AutomationAccountName $AutomationAccount