NVMe-Preflight-Check/azure-nvme-VM-update.ps1 (243 lines of code) (raw):
<#
.SYNOPSIS
SAP on Azure NVMe conversion
.DESCRIPTION
The script converts a VM from SCSI to NVMe controller
.LINK
https://github.com/Azure/SAP-on-Azure-Scripts-and-Utilities
#>
<#
Copyright (c) Microsoft Corporation.
Licensed under the MIT license.
#>
#Requires -Version 7.1
[CmdletBinding()]
param (
# Subscription ID
[Parameter(Mandatory=$true)][string]$subscription_id,
# Resource Group
[Parameter(Mandatory=$true)][string]$resource_group_name,
# VM Name
[Parameter(Mandatory=$true)][string]$vm_name,
# Disk Controller Type
[ValidateSet("NVMe", "SCSI")][string]$disk_controller_change_to="NVMe",
# New VM Size
[Parameter(Mandatory=$true)][string]$vm_size_change_to,
# Start VM after update
[bool]$start_vm_after_update = $false,
# Write Log File
[bool]$write_logfile = $false,
# Ignore VM availability check
[switch]$ignore_vmsku_check
)
# RunLog function for more detailed data during execution
function WriteRunLog {
[CmdletBinding()]
param (
[string]$message,
[string]$category="INFO"
)
switch ($category) {
"INFO" { $_prestring = "INFO - "
$_color = "Green" }
"WARNING" { $_prestring = "WARNING - "
$_color = "Yellow" }
"ERROR" { $_prestring = "ERROR - "
$_color = "Red" }
}
$_runlog_row = "" | Select-Object "Log"
$_runlog_row.Log = [string]$_prestring + [string]$message
$script:_runlog += $_runlog_row
if (-not $RunLocally) {
Write-Host ($_prestring + $message) -ForegroundColor $_color
}
}
################################################################################################
#
# script start
#
################################################################################################
# create variable for log
$script:_runlog = @()
$breakingchangewarning = Get-AzConfig -DisplayBreakingChangeWarning
if ($breakingchangewarning.Value -eq $true) {
Update-AzConfig -DisplayBreakingChangeWarning $false
}
# check if connected to Azure
$_SubscriptionInfo = Get-AzSubscription -SubscriptionId $subscription_id
# if $_SubscritpionInfo then it got subscriptions
if ($_SubscriptionInfo)
{
$_ContextInfo = Get-AzContext
if ($_ContextInfo.Subscription -eq $subscription_id) {
# connected to correct context
WriteRunLog -category "INFO" -message "Already connected to correct Azure context"
}
else {
# setting context to correct subscription
Set-AzContext -Subscription $subscription_id
}
}
else {
WriteRunLog -category "ERROR" -message "Please connect to Azure using the Connect-AzAccount command, if you are connected use the Select-AzSubscription command to set the correct context"
exit
}
# Getting OS disk name
$os_disk_name = (Get-AzVM -ResourceGroupName $resource_group_name -Name $vm_name).StorageProfile.OsDisk.Name
if ($os_disk_name) {
# found OS Disk
WriteRunLog -category "INFO" -message "OS Disk found"
}
else
{
WriteRunLog -category "ERROR" -message "Please check the OS Disk"
}
# gettting Access Token for Web ARM request
$access_token = (Get-AzAccessToken).Token
if ($access_token) {
# Access token valid
WriteRunLog -category "INFO" -message "Access token generated"
}
else {
WriteRunLog -category "ERROR" -message "Problems creating access token"
}
# generating URI for the OS disk update
$uri = 'https://management.azure.com/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/disks/{2}?api-version=2023-04-02' -f $subscription_id, $resource_group_name, $os_disk_name
# auth header for web request
$auth_header = @{
'Content-Type' = 'application/json'
'Authorization' = 'Bearer ' + $access_token
}
# body for SCSI/NVMe enabled OS Disk
$body_nvmescsi = @'
{
"properties": {
"supportedCapabilities": {
"diskControllerTypes":"SCSI, NVMe"
}
}
}
'@
# body for SCSI enabled OS Disk
$body_scsi = @'
{
"properties": {
"supportedCapabilities": {
"diskControllerTypes":"SCSI"
}
}
}
'@
$_continue = 0
WriteRunLog -category "INFO" -message "Getting VM info"
$_vm = Get-AzVM -ResourceGroupName $resource_group_name -Name $vm_name
$_vminfo = Get-AzVM -ResourceGroupName $resource_group_name -Name $vm_name -Status
# checking VM capabilities
WriteRunLog -category "INFO" -message ("Getting all VM SKUs available in Region " + $_vm.Location)
WriteRunLog -category "INFO" -message ("This will take about a minute ...")
if (-not $ignore_vmsku_check) {
$_VMSKUs = Get-AzComputeResourceSku | Where-Object { $_.Locations -contains $_vm.Location -and $_.ResourceType.Contains("virtualMachines") }
$_VMSKU = $_VMSKUs | Where-Object { $_.Name -eq $vm_size_change_to }
if ($_VMSKU) {
WriteRunLog -category "INFO" -message "Found VM SKU - Checking for Capabilities"
$_supported_controller = ($_VMSKU.Capabilities | Where-Object { $_.Name -eq "DiskControllerTypes" }).Value
if ([string]::IsNullOrEmpty($_supported_controller)) {
WriteRunLog -category "ERROR" -message "VM SKU doesn't have supported capabilities"
$_continue -= 100
}
else {
WriteRunLog -category "INFO" -message "VM SKU has supported capabilities"
if ($disk_controller_change_to -eq "NVMe") {
# NVMe destination
if ($_supported_controller.Contains("NVMe") ) {
WriteRunLog -category "INFO" -message "VM supports NVMe"
$_continue += 1
}
else {
WriteRunLog -category "ERROR" -message "VM doesn't support NVMe"
$_continue -= 100
}
}
else {
# SCSI destination
$_continue += 1 # all VMs support SCSI
}
}
}
else {
WriteRunLog -category "ERROR" -message ("VM SKU doesn't exist, please check your input: " + $vm_size_change_to )
$_continue -= 100
}
}
else {
$_continue = 1
}
WriteRunLog -category "INFO" -message "Checking for TrustedLaunch"
if ($_vm.SecurityProfile.SecurityType -eq "TrustedLaunch") {
WriteRunLog -category "ERROR" -message "The VM is configured with Trusted Launch, NVMe doesn't support trusted launch."
$_continue -= 100
}
# checking if the $_continue variable is positive or negative
# for any case where it is negative a pre-requisit hasn't been met
if ($_continue -gt 0) {
WriteRunLog -category "INFO" -message "Checking if VM is stopped and deallocated"
if ($_vminfo.Statuses[1].Code -eq "PowerState/deallocated") {
# VM is already stopped
WriteRunLog -category "INFO" -message "VM is stopped and deallocated"
}
else {
#Stop and deallocate the VM
WriteRunLog -category "INFO" -message "Stopping VM"
Stop-AzVM -ResourceGroupName $resource_group_name -Name $vm_name -Force
}
if ($disk_controller_change_to -eq "NVMe") {
#Add NVMe supported capabilities to the OS disk
WriteRunLog -category "INFO" -message "Setting OS Disk to SCSI/NVMe"
$Update_Supported_Capabilities = (Invoke-WebRequest -uri $uri -Method PATCH -body $body_nvmescsi -Headers $auth_header | ConvertFrom-Json)
}
else {
#Add NVMe supported capabilities to the OS disk
WriteRunLog -category "INFO" -message "Setting OS Disk to SCSI"
$Update_Supported_Capabilities = (Invoke-WebRequest -uri $uri -Method PATCH -body $body_scsi -Headers $auth_header | ConvertFrom-Json)
}
# Get VM configuration
WriteRunLog -category "INFO" -message "Getting VM config to prepare new config"
$vm = Get-AzVM -ResourceGroupName $resource_group_name -Name $vm_name
# Set new VM size
WriteRunLog -category "INFO" -message "Setting new VM size"
$vm.HardwareProfile.VmSize = $vm_size_change_to
# Set new Controller type for VM
WriteRunLog -category "INFO" -message "Setting disk controller for VM"
$vm.StorageProfile.DiskControllerType = $disk_controller_change_to
# Update the VM
WriteRunLog -category "INFO" -message "Updating the VM configuration"
Update-AzVM -ResourceGroupName $resource_group_name -VM $vm
if ($start_vm_after_update) {
# Start the VM
WriteRunLog -category "INFO" -message "Waiting for 1 min before starting up"
Start-Sleep 60
WriteRunLog -category "INFO" -message "Starting VM"
Start-AzVM -ResourceGroupName $resource_group_name -Name $vm_name
}
else {
# Do not start VM
WriteRunLog -category "INFO" -message "Not starting VM"
}
}
else {
WriteRunLog -category "ERROR" -message "Pre-requisits check failed"
}
if ($write_logfile)
{
WriteRunLog -category "INFO" -message "Writing logfile"
$_filename = ".\" + $vm_name + "_" + (Get-Date -Format "yyyyMMdd-HHmm") + ".txt"
$script:_runlog | Out-File -FilePath $_filename -Append
}
if ($breakingchangewarning.Value -eq $true) {
Update-AzConfig -DisplayBreakingChangeWarning $true
}
################################################################################################
#
# script end
#
################################################################################################