-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathSet-AzVMState.ps1
More file actions
81 lines (65 loc) · 3.45 KB
/
Set-AzVMState.ps1
File metadata and controls
81 lines (65 loc) · 3.45 KB
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
Param(
[psobject[]]$Calendars,
[string]$ApplicationId,
[string]$ApplicationSecret
)
write-output "$(Get-Date) Script started"
# Setup variables
$startVMs = @()
$stopVMs = @()
# Ensures you do not inherit an AzureRMContext in your runbook
$null = Disable-AzureRmContextAutosave –Scope Process
# Set up an AzureRMContext using the Run As account
$connection = Get-AutomationConnection -Name AzureRunAsConnection
$null = Connect-AzureRmAccount -ServicePrincipal -Tenant $connection.TenantID -ApplicationID $connection.ApplicationID -CertificateThumbprint $connection.CertificateThumbprint
$null = Select-AzureRmSubscription -SubscriptionId $connection.SubscriptionID
# grab all VMs (where Tag "AutomatedStopStart" exists)
$azureVMs = Get-AzureRmVM -Status | Where-Object {$_.Tags.ContainsKey("AutomatedStopStart")}
write-output "Working with the following VMs:"
$azureVMs | Select-Object Name, PowerState
# Set up the Graph connection using the registered application identity
$uri = "https://login.microsoftonline.com/$($connection.TenantID)/oauth2/v2.0/token"
$body = @{
client_id = $ApplicationId
scope = "https://graph.microsoft.com/.default"
client_secret = $ApplicationSecret
grant_type = "client_credentials"
}
# Obtain an OAuth 2.0 Access Token
$tokenRequest = Invoke-WebRequest -Method Post -Uri $uri -ContentType "application/x-www-form-urlencoded" -Body $body -UseBasicParsing
$token = ($tokenRequest.Content | ConvertFrom-Json).access_token
# process all Calendars
foreach($calendar in $Calendars) {
write-output "`nWorking with calendar '$($calendar)'"
# scope VMs to process to this Calendar
$calendarVMs = $azureVMs | Where-Object {$_.Tags["AutomatedStopStart"] -like $Calendar}
# only work if there are VMs for this Calendar
if($calendarVMs) {
# Specify Graph query URI to call
$uri = "https://graph.microsoft.com/v1.0/users/$($calendar)/calendar/calendarView?StartDateTime=$([DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ss'))&EndDateTime=$([DateTime]::UtcNow.ToString('yyyy-MM-ddTHH:mm:ss'))"
# Run Graph API query
$query = Invoke-RestMethod -Method Get -Uri $uri -ErrorAction Stop -Headers @{
Authorization = "Bearer $token"
'Content-Type' = "application/json"
}
# Create an array of VMs based on the subjects in the returned Calendar events
$processVMs = @()
foreach($calendarItem in $query.Value) {
$processVMs += "$($calendarItem.Subject.ToLower())"
write-output " -- $($calendarItem.Subject) should be running ($(Get-Date ($calendarItem.start.dateTime)) -> $(Get-Date ($calendarItem.end.dateTime)))"
}
# arrays for VMs that need to be turned on and of
$startVMs += $calendarVMs | Where-Object {$_.Powerstate -like "VM deallocated" -and $processVMs.Contains("$($_.Name.ToLower())")}
$stopVMs += $calendarVMs | Where-Object {$_.Powerstate -like "VM running" -and -not $processVMs.Contains("$($_.Name.ToLower())")}
}
}
# process arrays of VMs
$startVMs | ForEach-Object {
write-output "Starting: $($_.Name)"
$null = $_ | Start-AzureRmVM -AsJob -ErrorAction SilentlyContinue
}
$stopVMs | ForEach-Object {
write-output "Deallocating: $($_.Name)"
$null = $_ | Stop-AzureRmVM -AsJob -Force -ErrorAction SilentlyContinue
}
write-output "`n$(Get-Date) Script ended"