Disclaimer
This is my personal blog. The opinions and views I express are my own. The information I provide is on an as-is basis. I make no representations as to accuracy, completeness, currentness, suitability, or validity of any information on this blog and will not be liable for any errors, omissions, or delays in this information or any losses, injuries or damages arising from its use.

Automate Creating Lab Virtual Machines in Azure with PowerShell

As you may or may not know, I recently decommissioned my old Dell PowerEdge 1950 server that I used for a few Lab virtual machines. While experimenting with PowerShell on these Virtual Machines, I have found myself in the situation where it would be easier to delete the Virtual Machines and re-create them instead of troubleshooting something I fouled up in the Registry. After the 2nd time rebuilding the lab VMs using the Azure website, I decided to script the process.

The script below will take input from a CSV file and create a virtual machine in your Azure subscription for each row in the CSV file. My example creates 2 virtual machines but you can obviously add as many as you need.

For a production environment in Azure, I would suggest Snapshotting the Virtual Machines. There is a good write-up of the process here: http://www.coreazure.com/snapshot-vms-in-azure-resource-manager/. In my case, for a Lab, snapshots use more storage which costs more $$.

 

Function New-AzureLab {
  <#
    .SYNOPSIS
    New-AzureLab will create 1 or multiple VMs in Azure based on input parameters from a CSV

    .DESCRIPTION
    Create a CSV file like below:
    VMName,Location,InterfaceName,ResourceGroupName,VMSize,ComputerName
    SP,EastUS,SP_Int,SignalWarrant_RG,Basic_A2,SP

    The function will read the input from the CSV file and create VMs in an Azure Resource Group
    
    .PARAMETER csvpath
    The full path to your CSV file (eg c:\scripts\VMs.csv)

    .EXAMPLE
    New-AzureLab -csvpath c:\scripts\VMs.csv
    Imports the applicable values from the CSV file

    .NOTES
    1. I already had a Resource Group in Azure therefore I put all the VMs in the same group.
    2. I already had a VM network created, all my VMs are in the same network.

    .LINK
    URLs to related sites
    A good writeup on the process - https://docs.microsoft.com/en-us/azure/virtual-machines/windows/quick-create-powershell
    Azure VM size values - https://docs.microsoft.com/en-us/azure/virtual-machines/windows/sizes-general
    Azure VM Publisher, Offer, SKUs, Version info for various VM types - https://docs.microsoft.com/en-us/azure/virtual-machines/windows/cli-ps-findimage

    .INPUTS
    CSV file path

    .OUTPUTS
    None

    .EXAMPLES
    New-AzureLab -csvpath c:\scripts\VMs.csv
  #>

    Param(
        [Parameter(Mandatory=$True,HelpMessage='Enter the Path to your CSV')]
        [string]$csvpath
        )
    # Lets make sure the CSV file is actually there
    $testpath = Test-Path -Path $csvpath
    If (!$testpath){
        clear-host
        write-host -ForegroundColor Red '***** Invalid CSV Path *****' -ErrorAction Stop
    } else {

        # This will the be local username and password for each VM
        $Credential = Get-Credential

        # Import the information from my CSV
        Import-Csv -Path "$csvPath" | ForEach-Object {
        
        # Get the Storage Account Informaiton
        $StorageAccount = Get-AzureRmStorageAccount

        # This is the naming convention for the OS Disk
        $OSDiskName = $_.'VMName' + '_OSDisk'

        # Network Information
        $PublicIP = New-AzureRmPublicIpAddress -Name $_.'InterfaceName' -ResourceGroupName $_.'ResourceGroupName' -Location $_.'Location' -AllocationMethod Dynamic
        $VMNetwork = Get-AzureRmVirtualNetwork
        $Interface = New-AzureRmNetworkInterface -Name $_.'InterfaceName' -ResourceGroupName $_.'ResourceGroupName' -Location $_.'Location' -SubnetId $VMNetwork.Subnets[0].Id -PublicIpAddressId $PublicIP.Id

        ## Setup local VM object
        $VirtualMachine = New-AzureRmVMConfig -VMName $_.'VMName' -VMSize $_.'VMSize'
        $VirtualMachine = Set-AzureRmVMOperatingSystem -VM $VirtualMachine -Windows -ComputerName $_.'ComputerName' -Credential $Credential -ProvisionVMAgent -EnableAutoUpdate
        $VirtualMachine = Set-AzureRmVMSourceImage -VM $VirtualMachine -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2016-Datacenter -Version 'latest'
        $VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $Interface.Id
        $OSDiskUri = $StorageAccount.PrimaryEndpoints.Blob.ToString() + 'vhds/' + $OSDiskName + '.vhd'
        $VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -Name $OSDiskName -VhdUri $OSDiskUri -CreateOption FromImage

        ## Create the VM in Azure
        New-AzureRmVM -ResourceGroupName $_.'ResourceGroupName' -Location $_.'Location' -VM $VirtualMachine -Verbose

        }
    }
}

 

1 Comment

  1. Diego S | | Reply

    Hola no me funciona, me arroja el siguiente error :

    New-AzureLab : El término ‘New-AzureLab’ no se reconoce como nombre de un cmdlet, función, archivo de script o
    programa ejecutable. Compruebe si escribió correctamente el nombre o, si incluyó una ruta de acceso, compruebe que
    dicha ruta es correcta e inténtelo de nuevo.
    En línea: 1 Carácter: 1
    + New-AzureLab -csvpath c:\scripts\VMs.csv
    + ~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (New-AzureLab:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Suggestion [3,General]: No se encontró el comando New-AzureLab, pero existe en la ubicación actual. Windows PowerShell no carga comandos de la ubicación actual de forma predeterminada. Si confía en este comando, escriba “.\New-AzureLab”. Vea “get-help about_Command_Precedence” para obtener información más detallada.

Leave a Reply to Diego S Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.