Wednesday, November 2, 2016

Azure Automation: Using PowerShell workflow

In my previous blog, I discussed about getting started with Azure automation and how to do basic tasks like starting/stopping VMs at a given time using Graphical runbooks. You can find  the blog post here :

In this blog, we will look into a little bit more complex  way of creating runbooks, ie using PowerShell workflows. You can also write simple PowerShell code and create runbooks using that. However, if you have to parameterize your inputs and change them each time you run, then you will have to use the PowerShell workflow based format. For creating a new PowerShell workflow based runbook, go to your  Azure Automation account-> Runbooks->Add a runbook. You can select the quick create option and runbook type as PowerShell workflow

Sample Usecase:

The usecase that I am going to discuss here is automated provisioning of VMs with the number of Data disks that you define. You can also specify the size of the data disks to be provisioned. We didn't have any runboook readily available in the gallery to do this task. Hence an Azure PowerShell script to create a new Azure VM in ARM portal was tweaked to achieve this:

The tweaks include:
  • Converted the PowerShell script to workflow to allow input parameters
  • Minor changes to use existing storage and network
  • Commands to add datadisk
  • Had to introduce InlineScript in the workflow so that the PowerShell commands are executed independently. If this is not done, it will throw errors due to issues in data conversion
  • Introduced basic For loop to add datadisks based on provisioning requirements


The runbook that I created is given below for reference. Feel free to give it a spin !!

workflow dynamicDDwithparamter
        param (
        # If you do not enter anything, the default values will be taken
        # VM name, availability set and NIC card name
        ## Compute - Name of VM to be created,Vm size, datadiskname
        ## Storage - Name of existing storage
        [String]$StorageName = "testsql295p",
        ## Global - Uses an existing resourcegroup
        [String]$ResourceGroupName = "autotest",
        [String]$Location = "WestEurope",
        ## Network - Name of existing network. This should match the network settings of others VMs in the target availability set
        [String]$Subnet1Name = "Subnet1",
        [String]$VNetName = "VNet10",
        [Int]$Disknumber ,
        [Int]$DisksizeinGB ,
        ## Compute - Vm size
        [String]$VMSize = "Standard_A2"

        $VMName =$Using:VMName
        $StorageName = $Using:StorageName
        $ResourceGroupName = $Using:ResourceGroupName
        $Location = $Using:Location
        $InterfaceName = $Using:InterfaceName
        $Subnet1Name = $Using:Subnet1Name
        $VNetName = $Using:VNetName
        $ComputerName = $Using:ComputerName
        $VMSize = $Using:VMSize
        $AvailabilitySetname = $Using:AvailabilitySetname
        $UserName = $Using:UserName
        $Password = $Using:Password
        $Disknumber = $Using:Disknumber
        $DisksizeinGB =$Using:DisksizeinGB

$connectionName = "AzureRunAsConnection"
    # Get the connection "AzureRunAsConnection "
    $servicePrincipalConnection=Get-AutomationConnection -Name $connectionName     
    "Logging in to Azure..."
    Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint

#$StorageType = "Standard_GRS"

#$VNetAddressPrefix = ""
#$VNetSubnetAddressPrefix = ""
$OSDiskName = $VMName + "OSDisk"
$dataDiskName = $VMName + "DataDisk"
# Resource Group
#New-AzureRmResourceGroup -Name $ResourceGroupName -Location $Location
# Storage - Creates Storage account
"Get storage account..."
#$StorageAccount = New-AzureRmStorageAccount -ResourceGroupName $ResourceGroupName -Name $StorageName -Type $StorageType -Location $Location
$StorageAccount = Get-AzureRmStorageAccount -ResourceGroupName $ResourceGroupName -AccountName $StorageName
"Collected storage account details ..."
# Network - Creates Public IP,Vnet and NIC card
"configure NIC..."
$PIp = New-AzureRmPublicIpAddress -Name $InterfaceName -ResourceGroupName $ResourceGroupName -Location $Location -AllocationMethod Dynamic -Force
#$SubnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name $Subnet1Name -AddressPrefix $VNetSubnetAddressPrefix
#$VNet = New-AzureRmVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName -Location $Location -AddressPrefix $VNetAddressPrefix -Subnet $SubnetConfig
$vnet = Get-AzureRmVirtualNetwork -Name $VNetName -ResourceGroupName $ResourceGroupName
$subnetconfig = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $vnet
#$subnetconfig = Get-AzureRmVirtualNetworkSubnetConfig -VirtualNetwork $Using:vnet
$Interface = New-AzureRmNetworkInterface -Name $InterfaceName -ResourceGroupName $ResourceGroupName -Location $Location -SubnetId $VNet.Subnets[0].Id -PublicIpAddressId $PIp.Id -Force
#$Interface = New-AzureRmNetworkInterface -Name $Using:InterfaceName -ResourceGroupName $Using:ResourceGroupName -Location $Using:Location -SubnetId $Using:VNet.Subnets[0].Id -PublicIpAddressId $Using:PIp.Id -Force
"configured NIC..."
# Compute
## Setup local VM object
"creating VM object properties..."
$secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($UserName, $secpasswd)
$AvailabilitySet = Get-AzureRmAvailabilitySet -ResourceGroupName $resourcegroupName -Name $AvailabilitySetname
$VirtualMachine = New-AzureRmVMConfig -VMName $VMName -VMSize $VMSize -availabilitysetID $
$VirtualMachine = Set-AzureRmVMOperatingSystem -VM $VirtualMachine -Windows -ComputerName $ComputerName -Credential $mycreds -ProvisionVMAgent -EnableAutoUpdate
$VirtualMachine = Set-AzureRmVMSourceImage -VM $VirtualMachine -PublisherName MicrosoftWindowsServer -Offer WindowsServer -Skus 2012-R2-Datacenter -Version "latest"
$VirtualMachine = Add-AzureRmVMNetworkInterface -VM $VirtualMachine -Id $Interface.Id
$OSDiskUri = $StorageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/" + $OSDiskName + ".vhd"
#$DataDiskVhdUri01 = $StorageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/" + $dataDiskName + ".vhd"
$VirtualMachine = Set-AzureRmVMOSDisk -VM $VirtualMachine -Name $OSDiskName -VhdUri $OSDiskUri -CreateOption FromImage
For ($i=1; $i -le $Disknumber; $i++) {
    $dataDiskName = $dataDiskName + $i  
   $DataDiskVhdUri01 = $StorageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/" + $dataDiskName + ".vhd"
   $VirtualMachine = Add-AzureRmVMDataDisk -VM $VirtualMachine -Name $dataDiskName -Caching 'ReadOnly' -DiskSizeInGB $DisksizeinGB -Lun $i -VhdUri $DataDiskVhdUri01 -CreateOption Empty
   $dataDiskName = $VMName + "DataDisk"
#$VirtualMachine = Add-AzureRmVMDataDisk -VM $VirtualMachine -Name $dataDiskName -Caching 'ReadOnly' -DiskSizeInGB 10 -Lun 0 -VhdUri $DataDiskVhdUri01 -CreateOption Empty
"created VM object properties..."
## Create the VM in Azure
"creating Virtual machine..."
New-AzureRmVM -ResourceGroupName $ResourceGroupName -Location $Location -VM $VirtualMachine
"created Virtual machine..."

No comments:

Post a Comment