Understanding SLA vs Downtime

Understanding SLA (Service Level Agreement) is very important after you choose to start from scratch OR migrate your application to Cloud.

You can find the SLA provided by Microsoft for its Azure services here.

Usually the SLAs will be 99.9 (three9s) to 99.999 (five 9s). At a first glance, you can think there is not a major difference in them. However when you are hosting a production application, it is very important to understand what the 9’s really mean w.r.t the downtime.

Here is a table for you to understand SLA vs Downtime

SLA percentageDowntime per weekDowntime per monthDowntime per year
991.68 hours7.2 hours3.65 days
99.910.1 minutes43.2 minutes8.76 hours
99.955 minutes21.6 minutes4.38 hours
99.991.01 minutes4.32 minutes52.56 minutes
99.9996 seconds25.9 seconds5.26 minutes

Know your Azure Quota Status

If you are using an Azure Pay-As-You-Go subscription, understanding the subscription limits and quotas are very important. Example, if your subscription has a vCPUs (cores) limit of 20, and if you have an automated pipeline to deploy Virtual machines, and if you have already used the provided quota, the pipelines will fail because there is no more vCPU quota available to you.

Hence it is mandatory as an Azure Consultant for you to understand the subscription limits. The subscription limits comes in two flavors – Soft and Hard. If you hit a SOFT limit, you can contact Azure Support to increase the limit by providing a valid business justification.

As a cloud provider, Azure offers many services and are tagged under ProviderNamespaces. Example, ‘Microsoft.Compute’, ‘Microsoft.Storage’, etc. Keeping track of your Subscription Capacity for each resources is difficult. And certainly very difficult to automate it.

However, Azure has introduced Quota API, which is generally available from Jan 19, 2021. You can use it for your automated Quota management. That is, you can query your current Subscription capacity consumption and order more quota using this API.

As an example, I will show you how to use this REST API using Powershell. We will query the ‘Microsoft.Compute’ provider to check what is the limit and current usage.

  1. First, you need to make sure your subscription is registered for the ‘Microsoft.Capacity’ provider.

  2. We need to authenticate to your Azure subscription. Hence create an App Registration and provide access to the subscription. Once this is done, grab the ‘ClientID’, ‘Client Secret’, and ‘Tenent ID’
    $TenantId = "<ENTER YOUR TENANT ID>"
    $ClientId = "<ENTER YOUR CLIENT ID>"
    $ClientSecret = "<ENTER YOUR CLIENT SECRET>"
    $Resource = "https://management.core.windows.net/"
    $SubscriptionId = "<ENTER YOUR SUBSCRIPTION ID>"


  3. Get access token by using the above credentials:
    $RequestAccessTokenUri = "https://login.microsoftonline.com/$TenantId/oauth2/token"
    $body = "grant_type=client_credentials&client_id=$ClientId&client_secret=$ClientSecret&resource=$Resource"
    $Token = Invoke-RestMethod -Method Post -Uri $RequestAccessTokenUri -Body $body -ContentType 'application/x-www-form-urlencoded'


  4. Now query the Quota API for ‘Microsoft.Compute’ provider. The result will show you how much capacity is already used and what is the limit.
    $location = 'westeurope'
    $resourceProvider = 'Microsoft.Compute'
    $uri = ("https://management.azure.com/subscriptions/{0}/providers/Microsoft.Capacity/resourceProviders/{1}/locations/{2}/serviceLimits?api-version=2020-10-25" -f $SubscriptionId, $resourceProvider, $location)
    $Headers = @{}
    $Headers.Add("Authorization","$($Token.token_type) "+ " " + "$($Token.access_token)")
    $Capacity = Invoke-RestMethod -Method Get -Uri $uri -Headers $Headers


  5. Now, we can query the ‘properties’ of the result to get the current value. I will query for results that have ‘currentValue’ more than 1. So, I can enhance further to create a report of the VM sizes that I am using and what is their capacity.
    $Capacity.value.properties | where {$_.currentValue -gt 1}

    Sample Output:

Hope this helps. You can also look into other operations on how to request for quota increase.

Azure – Provision Azure Virtual Machine with UnManaged disks

Microsoft has introduced a new type of disk called “Managed” disk wherein Azure manages the disk and the underlying storage account overhead for you. And, Microsoft recommends you create Azure virtual machines with “managed” disks, which is straightforward.

However, you might come across scenarios where your organization/client may require creating an Azure virtual machine with “unmanaged” disks. Use the below code to create an Azure virtual machine with “unmanaged” disks.

$location = "EastUS2"
$rgname = "manjuResourceGroup"
New-AzureRmResourceGroup -Name manjuResourceGroup -Location $location

# Create a subnet configuration
$subnetConfig = New-AzureRmVirtualNetworkSubnetConfig -Name mySubnet -AddressPrefix 192.168.1.0/24

# Create a virtual network
$vnet = New-AzureRmVirtualNetwork -ResourceGroupName manjuResourceGroup -Location $location `
    -Name MYvNET -AddressPrefix 192.168.0.0/16 -Subnet $subnetConfig

# Create a public IP address and specify a DNS name
$pip = New-AzureRmPublicIpAddress -ResourceGroupName manjuResourceGroup -Location $location `

    -AllocationMethod Static -IdleTimeoutInMinutes 4 -Name "mypublicdns$(Get-Random)"

# Create an inbound network security group rule for port 3389
$nsgRuleRDP = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleRDP  -Protocol Tcp `
    -Direction Inbound -Priority 1000 -SourceAddressPrefix '125.16.236.160' -SourcePortRange * -DestinationAddressPrefix * `
    -DestinationPortRange 3389 -Access Allow

# Create an inbound network security group rule for port 80
$nsgRuleWeb = New-AzureRmNetworkSecurityRuleConfig -Name myNetworkSecurityGroupRuleWWW  -Protocol Tcp `
    -Direction Inbound -Priority 1001 -SourceAddressPrefix '125.16.236.160' -SourcePortRange * -DestinationAddressPrefix * `
    -DestinationPortRange 80 -Access Allow

# Create a network security group
$nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName manjuResourceGroup -Location $location `
    -Name myNetworkSecurityGroup -SecurityRules $nsgRuleRDP,$nsgRuleWeb

# Create a virtual network card and associate with public IP address and NSG
$nic = New-AzureRmNetworkInterface -Name myNic -ResourceGroupName manjuResourceGroup -Location $location `
    -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id -NetworkSecurityGroupId $nsg.Id

# Define a credential object
$cred = Get-Credential

#VM config
$vmsize = "Standard_DS2"
$vmName="myVM"
$vm = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize
$pubName = ”MicrosoftWindowsServer”
$offerName = ”WindowsServer”
$skuName = ”2016-Datacenter”
$vm = Set-AzureRmVMOperatingSystem -VM $vm -Windows -ComputerName $vmName -Credential $cred
$vm = Set-AzureRmVMSourceImage -VM $vm -PublisherName $pubName -Offer $offerName -Skus $skuName -Version "latest"
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $NIC.Id

# Create a new storage account
New-AzureRmStorageAccount -ResourceGroupName "manjuResourceGroup" -AccountName "manjustorageaccount" -Location $location -SkuName "Standard_LRS"

# Disk setup
$diskName = ”manju-disk”
$storageaccount = "manjustorageaccount"
$STA = Get-AzureRmStorageAccount -ResourceGroupName $rgName -Name $storageAccount
$OSDiskUri = $STA.PrimaryEndpoints.Blob.ToString() + "vhds/" + $diskName? + ".vhd"
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $diskName -VhdUri $OSDiskUri -CreateOption fromImage

# Create the virtual machine
New-AzureRmVM -ResourceGroupName manjuResourceGroup -Location $location -VM $vm

 

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Expand OS Drive for Azure Virtual Machine

When you create an Azure Virtual Machine, it comes with an OS drive having a default size. The size is different for Windows and Linux machines. ~128GB and ~30GB for Windows and Linux machines respectively. The OS drive can be expanded to a maximum size of 2TB as of this writing. Use the below code to allocate space to your Azure VM’s OS drive. After executing the code, login to the virtual machine and expand (Disk Management for Windows) the drive using the newly allocated space.

Resize a Managed Disk:

## Resize OS disk size for Managed Disk

# Set Resource Group and Virtual Machine name
$resourceGroupName = 'my_resource_group_name'
$virtualMachineName = 'my_virtual_machine_name'

# Create VM reference object
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Stop the Virtual Machine
Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Create a reference to the Managed disk and set the size as required
$disk= Get-AzureRmDisk -ResourceGroupName $resourceGroupName -DiskName $vm.StorageProfile.OsDisk.Name
$disk.DiskSizeGB = 1023
Update-AzureRmDisk -ResourceGroupName $resourceGroupName -Disk $disk -DiskName $disk.Name

# Start the Azure Virtual Machine
Start-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

Resize an Unmanaged Disk:

## Resize OS disk size for Unmanaged Disk

# Set Resource Group and Virtual Machine name
$resourceGroupName = 'my-resource-group-name'
$virtualMachineName = 'my-vm-name'

# Create VM reference object
$vm = Get-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Stop the Virtual Machine
Stop-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

# Create a reference to the Unmanaged disk and set the size as required
$vm.StorageProfile.OSDisk.DiskSizeGB = 1023
Update-AzureRmVM -ResourceGroupName $resourceGroupName -VM $vm

# Start the Azure Virtual Machine
Start-AzureRmVM -ResourceGroupName $resourceGroupName -Name $virtualMachineName

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Attach and Initialize Data disk to Azure Virtual Machine

When you create an Azure windows virtual machine, it comes a default OS drive (C:\) and a temporary drive (D:\). An azure virtual machine allows you to attach a data disk to it to expand the storage. The number of data disks that can be attached to the VM depends on the Size and Family of the VM.

You can automate the process of attaching the data disk and initializing it using two scripts:

Script 1: initializePartition.ps1

This script contains the code to initialize the RAW partition.

Script 2: attachAndInstallCSE.ps1

This script will attach the data disk to the Azure windows virtual machine. It also installs the Custom Script Extension to the virtual machine.

initializePartition.ps1

$disks = Get-Disk | Where partitionstyle -eq 'raw' | sort number
    $letters = 70..89 | ForEach-Object { [char]$_ }
    $count = 0
    $labels = "data1","data2"

    foreach ($disk in $disks) {
        $driveLetter = $letters[$count].ToString()
        $disk |
        Initialize-Disk -PartitionStyle MBR -PassThru |
        New-Partition -UseMaximumSize -DriveLetter $driveLetter |
        Format-Volume -FileSystem NTFS -NewFileSystemLabel $labels[$count] -Confirm:$false -Force
    $count++
    }

attachAndInstallCSE.ps1

# Declaringvariables
$resourceGroupName = 'resourceGroupName'
$virtualMachineName = 'virtualMachineName'
$location = 'East US'
$storageType = 'Premium_LRS'
$dataDiskName = $virtualMachineName + '_datadisk1'

# Create a new managed data disk
$diskConfig = New-AzureRmDiskConfig -SkuName $storageType -Location $location -CreateOption Empty -DiskSizeGB 128
$dataDisk1 = New-AzureRmDisk -DiskName $dataDiskName -Disk $diskConfig -ResourceGroupName $resourceGroupName

# Get the virtual machine reference
$vm = Get-AzureRmVM -Name $virtualMachineName -ResourceGroupName $resourceGroupName

# Update the VM reference by adding the data disk
$vm = Add-AzureRmVMDataDisk -VM $vm -Name $dataDiskName -CreateOption Attach -ManagedDiskId $dataDisk1.Id -Lun 1

# Update the virtual machine
Update-AzureRmVM -VM $vm -ResourceGroupName $resourceGroupName

## Install the Custom Script Extension that inturn calls the initializePartition.ps1
$location = "East US 2"

# The name you want to give for the CSE
$extensionName = "extensionName"

$fileName = "initializePartition.ps1"

# Storage Account where the initializePartition.ps1 is present
$storageAccountName = "<INSERT_STORAGE_ACCOUNT_NAME>"

# Primary Access Key of Storage Account where the initializePartition.ps1 is present
$storageAccountAccessPrimaryKey = "<INSERT_STORAGE_PRIMARY_ACCESS_KEY>"

# Storage Account container where the initializePartition.ps1 is present
$storageAccountContainerName = "<INSERT_STORAGE_ACCOUNT_CONTAINER_NAME>"

Set-AzureRmVMCustomScriptExtension -ResourceGroupName $resourceGroupName -Location $location -VMName $virtualMachineName -Name $extensionName -TypeHandlerVersion "1.4" -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountAccessPrimaryKey -FileName $fileName -ContainerName $storageAccountContainerName

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Understand your Azure resource utilization using Azure Metrics

Understanding resource utilization is very crucial in determining how your resources are performing. Using this data, you can them make decisions on cost optimization. From my experience, clients are very keen on having a scheduled Resource Utilization Report.

If you are working in an infrastructure team, then your report for a virtual machine may include, CPU utilization, memory, disk usage, network in/Out etc.,

You can use Azure PowerShell to download Azure Insight Metric Data.

As an example, below code shows you how to retrieve CPU Utilization data for an Azure virtual machine.

# Get the virtual machine object
$vm = get-azurermvm -ResourceGroupName "automationResourceGroup" -Name "hybridworker"

# Get the resource ID for the virtual machine
$resourceID = $vm.Id

# Retrieve Azure Insight metric definitions for virtual machines
Get-AzureRmMetricDefinition –ResourceId $resourceID -DetailedOutput

Output of the above cmdlet will fetch a lot of metrics. I have selected the “Percentage CPU”.

sourceId             : /subscriptions/aaaaaaa-bbbb-cccc-dddd-eeeeeeeee/resourceGroups/automation/providers/Microsoft.Compute/virtualMachines/hybridworker

Name                   :

                             LocalizedValue : Percentage CPU

                             Value          : Percentage CPU

                        

Unit                   : Percent

PrimaryAggregationType : Average

Id                     : /subscriptions/aaaaaaa-bbbb-cccc-dddd-eeeeeeeee/resourceGroups/automation/providers/Microsoft.Compute/virtualMachines/hybridworker/providers/microsoft.insights/metricdefinitions/Percentage CPU

The “Value” will give you the correct Metric Name.

Below code will pull the CPU utilization of the virtual machine for the last 40 minutes.

$endTime = Get-Date
$startTime = $endTime.AddMinutes(-40)
$timeGrain = '00:01:00'
$metricName = 'Percentage CPU'
$metricData = Get-AzureRmMetric -ResourceId $resourceID -TimeGrain $timeGrain -StartTime $startTime -EndTime $endTime -MetricNames $metricName
$metricData.Data

I have shown you how to fetch one such metric for an Azure resource (Azure virtual machine in this case). Similarly, you can fetch metrics for any Azure resource by obtaining the relevant “resourceID” and fetching the appropriate Azure Metric Definition.

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure -Forgot Azure Virtual machine password?

While troubleshooting RDP issues, one of the approaches is to connect to the Azure windows machine using its local admin credentials. What if you forgot the credentials? Use the below code to reset them using VMAccess extension and PowerShell:

$resourceGroupName = "<ENTER_RESOURCE_GROUP_NAME>"
$virtualMachineName = "<ENTER_VIRTUAL_MACHINE_NAME>"
$location = "<ENTER_VM_LOCATION>"
Set-AzureRmVMAccessExtension -ResourceGroupName $resourceGroupName -location $location -virtualMachineName $virtualMachineName -Credential (get-credential) -typeHandlerVersion "2.0" -Name VMAccessAgent

Post troubleshooting, you conclude that by resetting the RDP configuration, the RDP issue will get resolved. How do you reset the RDP configuration, when you are not able to RDP? You may cause service disruption if you decide to restart or redeploy the VM to reset the RDP configuration.

Azure allows you to reset the RDP configuration without logging into the Azure windows virtual machine.

Use the below code to reset the Remote Desktop Services Configuration:

The code resets the access extension named “myVMAccess” on the VM named “myVM” in the “myResourceGroup” resource group:

Set-AzureRmVMAccessExtension -ResourceGroupName "myResoureGroup" -VMName "myVM" -Name "myVMAccess" -Location WestUS -typeHandlerVersion "2.0" -ForceRerun

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – TAG Azure Virtual Machines?

In a cloud environment, the effective way to organize and manage your infrastructure is by tagging your resources. Example, if your client has multiple silos like marketing, sales etc., and your cost model is different to each silo, tagging the resources provides an effective way to measure and manage the cost for your client.

Use the below code to TAG your Azure virtual machine:

$resource_group = "resourceGroupName"
$vm_name = "virtualMachineName"
$tags = (Get-AzureRmResource -ResourceGroupName $resource_group -Name $vm_name).Tags
$tags += @{toolsinstalled="true"}
Set-AzureRmResource -ResourceGroupName $resource_group -Name $vm_name -ResourceType "Microsoft.Compute/VirtualMachines" -Tag $tags -Force

You may tag other resources (Storage Account, Virtual Network etc.,) by providing the correct values to “-ResourceType” parameter.

If you have a set of standard tags and you want to tag all virtual machines in a resource group, then use the code below as a template:

Param(

  ## Parameter declaration

  [string]$resource_group,


  # Tag values passed as a parameter

  [string]$rtb_status_tag_value,

  [string]$os_type_tag_value,

  [string]$environment_tag_value,

  [string]$build_date_tag_value,

  [string]$project_name_tag_value,

  [string]$support_type_tag_value

)


$azure_vm_list = get-azurermvm -ResourceGroupName $resource_group

foreach($azure_vm_list_iterator in $azure_vm_list){

$tags = (Get-AzureRmResource -ResourceGroupName $resource_group -Name $azure_vm_list_iterator.name).Tags

# Creating a hash table with tag name and value

$tags += @{"RTB status"=$rtb_status_tag_value}

$tags += @{"OS Type"=$os_type_tag_value}

$tags += @{"Environment"=$environment_tag_value}

$tags += @{"Built Date"=$build_date_tag_value}

$tags += @{"Project Name"=$project_name_tag_value}

$tags += @{"Support Type"=$support_type_tag_value}


"Setting tags"| write-output

Set-AzureRmResource -ResourceGroupName $resource_group -Name $azure_vm_list_iterator.name -ResourceType "Microsoft.Compute/VirtualMachines" -Tag $tags -ApiVersion '2017-12-01' -force

}

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Install software on Azure Virtual Machine using Azure Custom Script Extension (CSE)

You may need to install a software (exe, MSI etc..) on your Azure virtual machines as per the on-boarding process. The traditional way of doing this is to RDP to your virtual machine and then install the software.

Azure and PowerShell make this task simple by introducing “Custom Script Extension (CSE)” for Azure Virtual machines. Using CSE you can install the executables without login into the servers. The process also reduces human effort by a lot, hence increasing the ROI for your team.

As an example, let us see how to deploy a BigFix client into an Azure Windows Virtual Machine:

The process requires two scripts:

Script 1: installAgent.ps1

This script does the silent installation of the agents. This script must be uploaded into Azure Storage Account along with the exe/MSI.

Script 2: triggerCSE.ps1

This script installs the CSE on the Windows Azure virtual machine. Checks if the Virtual Machine is STOPPED. If it is stopped, it will start the virtual machine, install the CSE, and then it will stop the virtual machine.

Steps to be followed

  1. Upload all the necessary files (BigFix installation files) into Azure Storage account and provide Anonymous access to the container.
  2. Upload the installAgent.ps1 PowerShell script into Azure Storage account and provide Anonymous access to the container.
  3. Execute the triggerCSE.ps1 from your laptop or you can completely automate the solution using Azure Automation Account.

installAgent.ps1

# Script to install Big Fix agents in Singapore region

# Create a directory to hold BigFix files

new-item 'c:\bigfix' -ItemType directory -force


# Copy BigFix files from Azure storage to local directory

Invoke-WebRequest -Uri https://manjutool.blob.core.windows.net/wpbigfixupdatedsingapore/clientsettings.cfg -outfile 'c:\bigfix\clientsettings.cfg'

Invoke-WebRequest -Uri https://manjutool.blob.core.windows.net/wpbigfixupdatedsingapore/masthead.afxm -outfile 'c:\bigfix\masthead.afxm'

Invoke-WebRequest -Uri https://manjutool.blob.core.windows.net/wpbigfixupdatedsingapore/BigFix-BES-Client-9.5.7.94.exe -outfile 'c:\bigfix\setup.exe'


# Execute the setup file

$arguments = "/S /v/qn"

$filepath = "c:\bigfix\setup.exe"

Start-Process $filepath $arguments -wait


triggerCSE.ps1

##### Installing BigFix client on virtual machine #####




        # Declaring variables




        # storage account name where the custom script is stored

        $storage_account_name = "<INSTERT_STORAGE_ACCOUNT_NAME>"

        # storage account key of where the custom script is stored

        $storage_account_key = "<INSERT_STORAGE_ACCOUNT_KEY>"

        # custom script file name

        $bigfix_file_name = "installAgent.ps1"

        # container name where the custom script is stored

        $bigfix_container_name_singapore = "<INSERT_AZURE_STORAGE_CONTAINER_NAME>"

        # Assuming the state of the virtual machine is not de-allocated

        $is_dellocated = $false


        $resource_group = "<INSERT_AZURE_VIRTUAL_MACHINE_RESOURCE_GROUP_NAME>"

        $vm_name = "<INSERT_AZURE_VIRTUAL_MACHINE_NAME>"




        # Checking if the Webhook data has the Resource Group and Virtual Machine.

        if($resource_group -eq $null -or $vm_name -eq $null){

            "Either Resource Group or Virtual Machine name, not present. This could be because the input variables could be misspelled. Make sure the input names are - 'ResourceGroup' and 'VirtualMachine'. " | write-output

            exit

        }

      
        #### Checking if the Virtual Machine is a Windows machine ########

        # Obtaining the Virtual Machine object

        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name




        # Obtaining the Virtual Machine status object

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status




        "Displaying the status of Virtual machine...." | write-output

        $vm_status.Statuses[1].DisplayStatus | write-output

        "" | write-output

        "" | write-output

        "Checking if the VM is Windows or not. Expect some output below if the Virtual machine is Windows... If you DONOT GET ANY OUTPUT, STOP EXECUTING..." | write-output

        $vm.OSProfile.WindowsConfiguration | write-output

       

        if($vm.OSProfile.WindowsConfiguration -eq $null){

            "The Virtual machine is either a custom image or is not Windows Virtual Machine. Cannot proceed with installing Custom Script Extenstion.. " | write-output

            exit

        }


<#




NOTE: IF THE VIRTUAL MACHINE IS STOPPED-DEALLOCATED, THIS SCRIPT WILL START THE VIRTUAL MACHINE, INSTALL AGENTS AND WILL DE-ALLOCATE IT




#>

        ######## Checking the status of the Virtual Machine ########

        <#

            VM Generalized --> Do not take any action. Exit Execution

            VM Deallocated --> Start the Virtual Machine

            VM Running --> Do not take any action, Proceed with Execution

        #>


        if($vm_status.Statuses[1].DisplayStatus -eq "VM Generalized"){

            "Virtual Machine is in the GENERALIZED state. Do not proceed further... " | write-output

            "" | write-output

            "" | write-output

exit

        }


        if($vm_status.Statuses[1].DisplayStatus -eq "VM deallocated"){

            "Virtual Machine is STOPPED. Starting the virtual machine... " | write-output

            $is_dellocated = $true

            $vm | Start-AzureRmVM

            "Successfully started Virtual Machine.." | write-output

            ""| write-output

            "" | write-output

        }


        if($vm_status.Statuses[1].DisplayStatus -eq "VM running"){

            "Virtual Machine is already RUNNING. Proceeding with agents installation" | write-output

            "" | write-output

            "" | write-output

        }


      

        # Checking if the virtual machine already has a Custom Script Extension




        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status

        $vm_extensions = $vm.Extensions


        foreach($vm_extensions_iterator in $vm_extensions){

            if($vm_extensions_iterator.VirtualMachineExtensionType -eq "CustomScriptExtension"){

                "Removing the CSE..." | write-output

                Remove-AzureRmVMCustomScriptExtension -Name $vm_extensions_iterator.Name -ResourceGroupName $resource_group -VMName $vm_name -force

                "Removed  the CSE " | write-output

                "" | write-output

                "" | write-output

            }




        }


        # Re-creating the Virtual Machine object, since one of the above condition - starts the virtual machine

        $vm = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name

        $vm_status = get-azurermvm -ResourceGroupName $resource_group -Name $vm_name -Status


        ########### Installing BIGFIX client via Azure Custom Script Extension ###########

        if($vm_status.Statuses[1].DisplayStatus -eq "VM running" -and $vm.OSProfile.WindowsConfiguration -ne $null){

            "Installing BigFix extension..." | write-output

            # azure powershell cmdlet to execute add the custom script extension and to execute the powershell file

            Set-AzureRmVMCustomScriptExtension -ResourceGroupName $resource_group -Location $vm.Location -VMName $vm_name -Name "ibm_bigfix_agent_install_extension" -TypeHandlerVersion "1.1" -StorageAccountName $storage_account_name -StorageAccountKey $storage_account_key -FileName $bigfix_file_name -ContainerName $bigfix_container_name_singapore

        }


        "waiting for 10 seconds..." | write-output

        "" | write-output

        "" | write-output


        Start-Sleep -s 10


        ######## Stopping the Virtual machine that we had started ########



        if($is_dellocated -eq $true){

            "We had started the virtual machine before installing the BigFix agent. STOPPING the virtual machine to preserve the initial state..." | write-output


            $vm | Stop-AzureRmVM -force

            "Successfully stopped the virtual machine" | write-output

            "" | write-output

            "" | write-output

        }

As an enhancement, you can add additional checks, create a log file and have it uploaded to another Storage Account. Or, create an Azure Storage Table, and write the updates to it tracking how many virtual machines the CSE is installed.

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!

Azure – Copy Data disk from one Azure virtual machine to another

 

Just like any other computer, virtual machines in Azure use disks as a place to store an operating system, applications, and data. All Azure virtual machines have at least two disks – a Windows operating system disk and a temporary disk. The operating system disk is created from an image, and both the operating system disk and the image are virtual hard disks (VHDs) stored in an Azure storage account. Virtual machines also can have one or more data disks, that are also stored as VHDs.

Consider a case where you have configured an Azure virtual machine that hosts applications and you have saved an application data in multiple data disks. Now you want to create multiple virtual machines or copy all those data disks to other virtual machines.

You can now perform a copy Data Disk operation from one Azure virtual machine to another Azure virtual machine by using a PowerShell script.

Download the script

Click here to download my PowerShell scripts for Free !!

Click here for Azure tutorial videos !!