🚀 Automation for Creating a VM in Azure via PowerShell 🖥️🔧
📌 Description
This script automates the process of creating an Azure Virtual Machine (VM), resource group, storage account, and more, using PowerShell. Choose between various options to customize your setup, and the script will take care of the rest!
🚀 Features
Create a resource group in Azure
Deploy a Virtual Machine with your preferred configuration
Set up storage accounts and associated resources
Choose between different VM configurations and sizes
Automate deployment with minimal manual intervention
🛠️ Prerequisites
1- PowerShell installed
2- Azure PowerShell module installed
3- Azure subscription
PowerShell Script
# Check if the user is logged into Azure
if (-not (Get-AzContext)) {
Write-Host "You must log in to Azure first!" -ForegroundColor Red
Connect-AzAccount -TenantId "0711aea7-8f00-4e7f-aad3-3320c2bd8b9e"
}
# Function to display the menu with completed options highlighted
function Show-Menu {
Clear-Host
Write-Host "=== Azure VM Creator ===" -ForegroundColor Green
if ($global:completedOptions["0"]) {
Write-Host "0. Select region" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "0. Select region" -ForegroundColor White
}
if ($global:completedOptions["1"]) {
Write-Host "1. Specify resource group and VM name" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "1. Specify resource group and VM name" -ForegroundColor White
}
if ($global:completedOptions["2"]) {
Write-Host "2. Select Windows version and SKU" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "2. Select Windows version and SKU" -ForegroundColor White
}
if ($global:completedOptions["3"]) {
Write-Host "3. Specify CPU and RAM" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "3. Specify CPU and RAM" -ForegroundColor White
}
if ($global:completedOptions["4"]) {
Write-Host "4. Specify VM SKU" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "4. Specify VM SKU" -ForegroundColor White
}
if ($global:completedOptions["5"]) {
Write-Host "5. Select VM size" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "5. Select VM size" -ForegroundColor White
}
if ($global:completedOptions["6"]) {
Write-Host "6. Select disk type" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "6. Select disk type" -ForegroundColor White
}
if ($global:completedOptions["7"]) {
Write-Host "7. Show summary and create VM" -ForegroundColor Black -BackgroundColor Green
} else {
Write-Host "7. Show summary and create VM" -ForegroundColor White
}
Write-Host "8. Exit" -ForegroundColor White
Write-Host "====================" -ForegroundColor Green
}
# Initial variables
$resourceGroupName = $null
$vmName = $null
$windowsVersion = $null
$selectedSku = $null
$cpuCores = $null
$ramGB = $null
$vmVariant = $null
$selectedSize = $null
$diskType = $null
$filteredSizes = $null
$location = $null # No default region, user must select
$global:completedOptions = @{} # Hash table to track completed options
# Main loop
while ($true) {
Show-Menu
$choice = Read-Host "Select an option (0-8)"
Write-Host "You selected: '$choice'" -ForegroundColor Yellow # Debugging
switch ($choice) {
"0" {
Write-Host "Running option 0" -ForegroundColor Yellow
Write-Host "`nAvailable Azure regions:" -ForegroundColor Cyan
$locations = Get-AzLocation | Sort-Object Location | Select-Object -Property Location
$index = 1
$locationList = @()
$locations | ForEach-Object {
Write-Host "$index. $($_.Location)"
$locationList += $_.Location
$index++
}
$locationChoice = Read-Host "Enter the number for the region you want to use (1-$($locationList.Count))"
if (-not [int]::TryParse($locationChoice, [ref]$null)) {
Write-Host "Invalid choice. Enter a number between 1 and $($locationList.Count)." -ForegroundColor Red
} else {
$locationChoiceInt = [int]$locationChoice
if ($locationChoiceInt -lt 1 -or $locationChoiceInt -gt $locationList.Count) {
Write-Host "Invalid choice. Enter a number between 1 and $($locationList.Count)." -ForegroundColor Red
} else {
$location = $locationList[$locationChoiceInt - 1]
Write-Host "Region set to: $location" -ForegroundColor Green
$global:completedOptions["0"] = $true
}
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"1" {
Write-Host "Running option 1" -ForegroundColor Yellow
if (-not $location) {
Write-Host "Select a region first (option 0)." -ForegroundColor Red
} else {
$resourceGroupName = Read-Host "Enter the name of an existing resource group or a new one to create"
$vmName = Read-Host "What should your Windows VM be called?"
$rgExists = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if (-not $rgExists) {
Write-Host "Resource group '$resourceGroupName' does not exist. Creating a new one in ${location}..." -ForegroundColor Yellow
New-AzResourceGroup -Name $resourceGroupName -Location $location -Force | Out-Null
Write-Host "Resource group '$resourceGroupName' has been created." -ForegroundColor Green
} else {
Write-Host "Resource group '$resourceGroupName' found in region $($rgExists.Location)." -ForegroundColor Yellow
}
if ($resourceGroupName -and $vmName) {
$global:completedOptions["1"] = $true
}
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"2" {
Write-Host "Running option 2" -ForegroundColor Yellow
if (-not $location) {
Write-Host "Select a region first (option 0)." -ForegroundColor Red
} else {
Write-Host "`nFetching available Windows versions from Microsoft in region ${location}..." -ForegroundColor Cyan
# List of approved Windows versions
$approvedOffers = @("Windows-10", "Windows-11", "WindowsServer")
# Fetch from MicrosoftWindowsDesktop
$pubNameDesktop = "MicrosoftWindowsDesktop"
$offersDesktop = Get-AzVMImageOffer -Location $location -PublisherName $pubNameDesktop |
Where-Object { $approvedOffers -contains $_.Offer } |
Select-Object -Property Offer
# Fetch from MicrosoftWindowsServer
$pubNameServer = "MicrosoftWindowsServer"
$offersServer = Get-AzVMImageOffer -Location $location -PublisherName $pubNameServer |
Where-Object { $_.Offer -eq "WindowsServer" } |
Select-Object -Property Offer
# Combine results
$offers = $offersDesktop + $offersServer
if (-not $offers) {
Write-Host "No approved Windows versions found in region ${location}." -ForegroundColor Red
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
continue
}
$index = 1
$offerList = @()
$pubList = @() # To keep track of publisher for each offer
$offers | ForEach-Object {
Write-Host "$index. $($_.Offer)"
$offerList += $_.Offer
if ($_.Offer -eq "WindowsServer") {
$pubList += $pubNameServer
} else {
$pubList += $pubNameDesktop
}
$index++
}
$offerChoice = Read-Host "Enter the number for the Windows version you want to use (1-$($offerList.Count))"
$offerChoiceInt = [int]$offerChoice
if ($offerChoiceInt -lt 1 -or $offerChoiceInt -gt $offerList.Count) {
Write-Host "Invalid choice. Enter a number between 1 and $($offerList.Count)." -ForegroundColor Red
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
continue
}
$offerName = $offerList[$offerChoiceInt - 1]
$pubName = $pubList[$offerChoiceInt - 1]
Write-Host "`nAvailable SKUs for $offerName from ${pubName}:" -ForegroundColor Cyan
$availableSkus = Get-AzVMImageSku -Location $location -PublisherName $pubName -Offer $offerName | Select-Object -Property Skus
if (-not $availableSkus) {
Write-Host "No SKUs found for $offerName in region ${location}." -ForegroundColor Red
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
continue
}
$index = 1
$skuList = @()
$availableSkus | ForEach-Object {
Write-Host "$index. $($_.Skus)"
$skuList += $_.Skus
$index++
}
$skuChoice = Read-Host "Enter the number for the SKU you want to use (1-$($skuList.Count))"
$skuChoiceInt = [int]$skuChoice
if ($skuChoiceInt -lt 1 -or $skuChoiceInt -gt $skuList.Count) {
Write-Host "Invalid choice. Enter a number between 1 and $($skuList.Count)." -ForegroundColor Red
} else {
$selectedSku = $skuList[$skuChoiceInt - 1]
$windowsVersion = $offerName
Write-Host "Selected version: $windowsVersion, SKU: $selectedSku from $pubName" -ForegroundColor Green
$global:completedOptions["2"] = $true
}
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"3" {
Write-Host "Running option 3" -ForegroundColor Yellow
$cpuCores = Read-Host "Enter the number of CPU cores (e.g., 2)"
$ramGB = Read-Host "Enter the RAM size in GB (e.g., 4)"
if (-not [int]::TryParse($cpuCores, [ref]$null) -or -not [int]::TryParse($ramGB, [ref]$null)) {
Write-Host "CPU and RAM must be numeric values. Try again." -ForegroundColor Red
} else {
Write-Host "CPU set to: $cpuCores, RAM set to: $ramGB GiB" -ForegroundColor Green
$global:completedOptions["3"] = $true
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"4" {
Write-Host "Running option 4" -ForegroundColor Yellow
$vmVariant = Read-Host "Enter VM SKU (Standard)"
if ($vmVariant -ne "Standard") {
Write-Host "Invalid VM SKU. Only 'Standard' is allowed. Try again." -ForegroundColor Red
} else {
Write-Host "VM SKU set to: $vmVariant" -ForegroundColor Green
$global:completedOptions["4"] = $true
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"5" {
Write-Host "Running option 5" -ForegroundColor Yellow
if (-not $location) {
Write-Host "Select a region first (option 0)." -ForegroundColor Red
} elseif (-not $cpuCores -or -not $ramGB -or -not $vmVariant -or -not $windowsVersion -or -not $selectedSku) {
Write-Host "Specify Windows version, SKU, CPU, RAM, and VM SKU first (options 2, 3, and 4)." -ForegroundColor Red
} else {
Write-Host "# Warning: Previous errors may have occurred if you selected an ARM64-based VM size (e.g., Standard_D4pls_v5) with an x64 image. This script uses x64 images (Windows 10, 11, Server) and now lists only x64-compatible sizes." -ForegroundColor Yellow
# Fetch available sizes, excluding ARM64
$availableSizes = Get-AzVMSize -Location $location | Where-Object {
$_.Name -like "Standard*" -and
$_.Name -notlike "*pl*" # Exclude ARM64-based sizes like Dplsv5
}
$sizeReference = $availableSizes | ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
CPU = $_.NumberOfCores
RAM_GB = [math]::Round($_.MemoryInMB / 1024, 2)
}
}
Write-Host "Total number of available sizes in ${location}: $($sizeReference.Count)" -ForegroundColor Yellow
# Filter sizes based on Gen1 or Gen2
if ($windowsVersion -eq "Windows-11" -or $selectedSku -match "gen2" -or $selectedSku -match "22h2") {
$filteredSizes = $sizeReference | Where-Object {
$_.CPU -eq $cpuCores -and $_.RAM_GB -eq $ramGB -and $_.Name -match "Standard_D.*s_v[2-5]"
} | Sort-Object -Property Name
Write-Host "Note: Selected SKU requires a Gen2-compatible size (e.g., Standard_D2s_v3)." -ForegroundColor Yellow
} else {
$filteredSizes = $sizeReference | Where-Object {
$_.CPU -eq $cpuCores -and $_.RAM_GB -eq $ramGB -and $_.Name -match "Standard_A[1-4]_v2"
} | Sort-Object -Property Name
}
Write-Host "Number of filtered sizes: $($filteredSizes.Count)" -ForegroundColor Yellow
if ($filteredSizes) {
Write-Host "Filtered sizes (raw data):" -ForegroundColor Yellow
$filteredSizes | ForEach-Object { Write-Host "- $($_.Name)" -ForegroundColor Yellow }
} else {
Write-Host "No filtered sizes found." -ForegroundColor Yellow
}
if (-not $filteredSizes -or $filteredSizes.Count -eq 0) {
Write-Host "No VM size found for $cpuCores vCPU and $ramGB GiB RAM in ${vmVariant}. Choose different values." -ForegroundColor Red
} else {
Write-Host "`nAvailable VM sizes in ${location}:" -ForegroundColor Cyan
$index = 1
$sizeList = @()
$filteredSizes | ForEach-Object {
Write-Host "$index. $($_.Name) - $($_.CPU) vCPUs, $($_.RAM_GB) GiB RAM"
$sizeList += $_
$index++
}
Write-Host "Number of items in sizeList: $($sizeList.Count)" -ForegroundColor Yellow
$sizeChoice = Read-Host "Enter the number for the VM size you want to use (1-$($sizeList.Count))"
if (-not [int]::TryParse($sizeChoice, [ref]$null)) {
Write-Host "Invalid choice. Enter a number between 1 and $($sizeList.Count)." -ForegroundColor Red
} else {
$sizeChoiceInt = [int]$sizeChoice
Write-Host "Selected number: $sizeChoiceInt" -ForegroundColor Yellow
if ($sizeChoiceInt -lt 1 -or $sizeChoiceInt -gt $sizeList.Count) {
Write-Host "Invalid choice. Enter a number between 1 and $($sizeList.Count)." -ForegroundColor Red
} else {
$selectedSize = $sizeList[$sizeChoiceInt - 1].Name
Write-Host "VM size set to: $selectedSize" -ForegroundColor Green
$global:completedOptions["5"] = $true
}
}
}
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"6" {
Write-Host "Running option 6" -ForegroundColor Yellow
Write-Host "`nSelect a disk type for the OS disk:" -ForegroundColor Cyan
Write-Host "1. Premium SSD (High performance)"
Write-Host "2. Standard SSD (Balanced cost and performance)"
Write-Host "3. Standard HDD (Low cost)"
$diskChoice = Read-Host "Enter the number for the disk type (1-3)"
switch ($diskChoice) {
"1" { $diskType = "Premium_LRS"; Write-Host "Disk type set to: Premium SSD" -ForegroundColor Green; $global:completedOptions["6"] = $true }
"2" { $diskType = "StandardSSD_LRS"; Write-Host "Disk type set to: Standard SSD" -ForegroundColor Green; $global:completedOptions["6"] = $true }
"3" { $diskType = "Standard_LRS"; Write-Host "Disk type set to: Standard HDD" -ForegroundColor Green; $global:completedOptions["6"] = $true }
default { Write-Host "Invalid disk type. Try again." -ForegroundColor Red }
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"7" {
Write-Host "Running option 7" -ForegroundColor Yellow
if (-not $location -or -not $resourceGroupName -or -not $vmName -or -not $windowsVersion -or -not $selectedSku -or -not $cpuCores -or -not $ramGB -or -not $vmVariant -or -not $selectedSize -or -not $diskType) {
Write-Host "All options must be specified first. Use options 0-6 to fill in the information." -ForegroundColor Red
} else {
Write-Host "Summary:" -ForegroundColor Cyan
Write-Host "Region: $location"
Write-Host "Resource group: $resourceGroupName"
Write-Host "VM name: $vmName"
Write-Host "Windows version: $windowsVersion (SKU: $selectedSku)"
Write-Host "CPU: $cpuCores vCPUs"
Write-Host "RAM: $ramGB GiB"
Write-Host "VM size: $selectedSize"
Write-Host "Disk type: $diskType"
$createVM = Read-Host "Do you want to create the VM? (y/n)"
if ($createVM -eq "y") {
Write-Host "Creating VM..." -ForegroundColor Green
$adminUser = Read-Host "Enter the administrator username for the VM"
$adminPassword = Read-Host "Enter the administrator password" -AsSecureString
$credential = New-Object System.Management.Automation.PSCredential ($adminUser, $adminPassword)
$publisher = if ($windowsVersion -eq "WindowsServer") { "MicrosoftWindowsServer" } else { "MicrosoftWindowsDesktop" }
$offer = $windowsVersion
if ($windowsVersion -eq "Windows-11") {
Write-Host "Warning: Windows 11 requires a Gen2-compatible VM size (e.g., Standard_D2s_v3)." -ForegroundColor Yellow
}
$vnetName = "$vmName-vnet"
$subnetName = "$vmName-subnet"
$vnet = Get-AzVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
if (-not $vnet) {
$subnetConfig = New-AzVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix "10.0.0.0/24"
$vnet = New-AzVirtualNetwork -ResourceGroupName $resourceGroupName -Location $location -Name $vnetName -AddressPrefix "10.0.0.0/16" -Subnet $subnetConfig
}
$subnet = Get-AzVirtualNetworkSubnetConfig -Name $subnetName -VirtualNetwork $vnet
$publicIpName = "$vmName-ip"
$publicIp = New-AzPublicIpAddress -ResourceGroupName $resourceGroupName -Location $location -Name $publicIpName -AllocationMethod Static -Sku Standard
$nicName = "$vmName-nic"
$nsgName = "$vmName-nsg"
$nsgRuleName = "AllowRDP"
# Create NSG and rule for RDP
$nsgRule = New-AzNetworkSecurityRuleConfig -Name $nsgRuleName -Protocol Tcp -Direction Inbound -Priority 100 -SourceAddressPrefix * -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange 3389 -Access Allow
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName $resourceGroupName -Location $location -Name $nsgName -SecurityRules $nsgRule
$nic = New-AzNetworkInterface -ResourceGroupName $resourceGroupName -Location $location -Name $nicName -SubnetId $subnet.Id -PublicIpAddressId $publicIp.Id -NetworkSecurityGroupId $nsg.Id
$vmConfig = New-AzVMConfig -VMName $vmName -VMSize $selectedSize |
Set-AzVMOperatingSystem -Windows -ComputerName $vmName -Credential $credential |
Set-AzVMSourceImage -PublisherName $publisher -Offer $offer -Skus $selectedSku -Version "latest" |
Add-AzVMNetworkInterface -Id $nic.Id |
Set-AzVMOSDisk -StorageAccountType $diskType -CreateOption FromImage
try {
New-AzVM -ResourceGroupName $resourceGroupName -Location $location -VM $vmConfig -ErrorAction Stop
Write-Host "VM '$vmName' has been created successfully!" -ForegroundColor Green
$global:completedOptions["7"] = $true
} catch {
Write-Host "Error creating VM: $_" -ForegroundColor Red
}
} else {
Write-Host "VM creation canceled." -ForegroundColor Yellow
}
}
Write-Host "Press Enter to continue..." -ForegroundColor Cyan
Read-Host
}
"8" {
exit
}
default {
Write-Host "Invalid choice registered: '$choice'" -ForegroundColor Red
}
}
}
Kommentarer
Skicka en kommentar