azure virtual machine

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

Advertisement

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 -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 !!

Azure – Configure Storage Spaces for Azure VM for increased disk performance

This blog will walk you through on how to configure Storage Spaces for Azure Virtual Machine (Windows). Finally, we get to see some IOPS benchmarks.

Each data disk (Standard Storage Account) has about 500 IOPS. In this example, we are going to create a Storage Space by attaching 4 data disks to a Standard A2 sized Azure VM. In theory, this should increase the IOPS to 2k. (500 x 4 = 2000)

 

Configuring Storage Spaces for Azure windows VM

Step 1: Attach four data disks to your virtual machine.

From the azure portal, select your virtual machine >> Click on “Disks” >> click on the “+ Add data disk” >> Fill out the details accordingly >> Save the disk.

1

Repeat this process 3 more times and we will have 4 data disks attached to our virtual machine as shown below:

4_disk_attached_azure_portal.PNG

 

Inside the VM, we can see the disks attached:

4_disk_not_initialized

 

 

Step 2: Login to the virtual machine and run the following PowerShell cmdlets. This will configure Storage Space and will create a drive for you.

 

In our example, we will configure one volume. Hence, only one storage pool. If you are implementing SQL Server or any other architecture, you may need more than one storage pool.

Create a new virtual disk using all the space available from the storage pool using a Simple configuration. The interleave is set to 256KB. We are also setting the number of columns to be equal to the number of disks in the pool

Format the disk with NTFS filesystem and a 64KB allocation unit size.

Below is a snippet of the PowerShell console after executing the above cmdlets.

create_storage_space.PNG

Finally, we can see the drive. A drive named “E” will be created with a free space of ~4TB.

e_drive_created.png

 

Benchmark Tests

Obviously, this works. However, I have run IOPS test to have a visual. You may choose any standard benchmark testing tools. To keep it simple, I have used a PowerShell script authored by Mikael Nystrom, Microsoft MVP. This script is a wrapper to the SQLIO.exe. You may download the PowerShell script and SQLIO.exe file, HERE.

 

Download the archive file to your local system and copy it to the server. Extract the contents to any folder.

 

Below is a sample script to estimate IOPS:

.\DiskPerformance.ps1 -TestFileName test.dat –TestFileSizeInGB 1 -TestFilepath F:\temp -TestMode Get-SmallIO -FastMode True -RemoveTestFile True -OutputFormat Out-GridView

Feel free to tweak the parameter values for different results.

Explaination of parameters:

-TestFileName test.dat

The name of the file, it will create the file using FSUTIL, but it checks if it exists and if it does it stops, you can override that with the –RemoveTestFile True

–TestFileSizeInGB 1

Size of the file, it has fixed values, use the TAB key to flip through them

-TestFilepath C:\VMs

The folder can also be an UNC path, it will create the folder so it does not need to exist.

-TestMode Get-SmallIO

There is too test modes Get-LargeIO or Get-SmallIO, you use Get-LargeIO to measure the transfer rate and you use Get-SmallIO to measure IOPS

-FastMode True

Fast mode true runs each test for just 10 seconds, it gives you a hint, if you don’t set it or set it to false it will run for 60 sec (it will take a break for 10 sec between each run)

-RemoveTestFile True

Removes the test file if it exists

-OutputFormat Out-GridView

Choose between Out-Gridview or Format-Table

 

IOPS for C drive on Azure VM [OS Disk]:

C_drive

 

IOPS for D drive on Azure VM [Temporary Disk]:

D_drive

 

IOPS for E drive on Azure VM [Standard data disk]:

E_drive

 

IOPS for F drive on Azure VM [Storage Spaces]:

F_drive

 

We can use this storage strategy when we have a small amount of data but the IOPS requirement is huge.

Example scenario:

You have 500GB of data, and the IOPS for that data exceeds 1K. Storing 500GB of data in one data disk will create IOPS problems since each data disk has a 500 IOPS limit. But, if we combine 4 disks and create a storage space, the IOPS will increase to ~2k [we have to consider latency etc., to have a correct figure]. Since we are using the same Standard A2 virtual machine and Azure charges for the overall data and not per disk, the pricing will be the same.

 

 

Azure – Create a windows VM from a generalized image

This blog shows you how to create a windows VM from a  generalized image. This uses un-managed Azure disks.

For this example, I will be using resources deployed on Azure. i.e., generalize an Azure VM, create a image out of it and then create a new Azure VM using the image.

Below are the steps:

  1. Generalize the VM
  2. Capture a VM image from a generalized Azure VM, that we obtain from Step 1
  3. Create a VM from a generalized VHD image in a storage account, that we obtained from step 2

Part 1: Generalize the VM

  1. Remote Desktop to the Azure virtual machine
  2. **Important** Before running the “Sysprep.exe”. Delete the “unattend.xml” file from the “C:\Windows\Panther” folder. If you do not do this, you will encounter “OS Provision time out” exception while creating the VM from this image.

    This is due to the fact that when an image is deployed the unattend.xml file must come from the ISO image that is attached to the Virtual Machine by Windows Azure as part of VM provisioning from an image.

    8.PNG

  3. From the command prompt / powershell, change the directory to: “C:\Windows\System32\Sysprep”
  4. Run “Sysprep.exe”
  5. In the System Preparation Tool, select the option, “Enter System Out-of-Box Experience (OOBE)”. Select the “Generalize” option from the check-box.
  6. Select “Shutdown” from the drop down list, in Shutdown Options.
    1
  7. Once the Sysprep process completes, the VM will shutdown.
  8. From the Azure portal, you can see the status of the VM as “Stopped (Shutdown)”. Use the below powershell cmdlet to fetch the VM status.

    (Get-AzureRmVM -ResourceGroupName manjug_test -Name windowsmachine -Status).Statuses

    2

Part 2: Capture a VM image from a generalized Azure Virtual Machine

  1. De-allocate the VM

    Stop-AzureRmVM -ResourceGroupName manjug_test -Name windowsmachine

    Confirm the status of the VM:

    (Get-AzureRmVM -ResourceGroupName manjug_test -Name windowsmachine -Status).Statuses

    3

  2. Set the status of the VM to “Generalized”

    Set-AzureRmVm -ResourceGroupName manjug_test -Name windowsmachine -Generalized

    4

    Confirm the status of the VM:

    (Get-AzureRmVM -ResourceGroupName manjug_test -Name windowsmachine -Status).Statuses

    5

  3. Create the image by running the below command:

    Save-AzureRmVMImage -ResourceGroupName manjug_test -Name windowsmachine ` -DestinationContainerName images -VHDNamePrefix windowsmachineimage ` -Path C:\Filename.json

    -DestinationContainerName, is the container name where the image will be stored.
    -VHDNamePrefix, is the prefix given to the image.
    -Path, is the path of json file that contains the details of the image that gets created.

    You can get the URL of your image from the JSON file template. Go to the resources > storageProfile > osDisk > image > uri section for the complete path of your image. The URL of the image looks like:

    https://<storageAccountName&gt;.blob.core.windows.net/system/Microsoft.Compute/Images/<imagesContainer>/<templatePrefix-osDisk>.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd

    You can also verify the URI in the portal. The image is copied to a container named system in your storage account.

Part 3: Create a VM from a generalized VHD image in a storage account

  1. Obtain the image uri, from the json file (Part 2, step 3). Or you can fetch this from the Azure portal.

    From the portal:

    9.PNG

    From the JSON file:

    6

  2. Set the VHD uri to a variable. Example:

    $imageURI = “https://manjugtestdisks.blob.core.windows.net/system/Microsoft.Compute/Images/images/windowsmachineimage-osDisk.04a4f0cb-268a-49ea-a0d9-a203c8fa8c51.vhd&#8221;

  3. Create a Virtual Network
    Create the subnet. The following sample creates a subnet named mySubnet in the resource group myResourceGroup with the address prefix of 10.0.0.0/24.

    $rgName = “manjug_test”
    $subnetName = “mySubnet”
    $singleSubnet = New-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -AddressPrefix 10.0.0.0/24

    Create the virtual network. The following sample creates a virtual network named myVnet in the West US location with the address prefix of 10.0.0.0/16.

    $location = “Southeast Asia”
    $vnetName = “myVnet”
    $vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location `
    -AddressPrefix 10.0.0.0/16 -Subnet $singleSubnet

  4. Create a public IP address and network interface

    Create a public IP address. This example creates a public IP address named myPip.

    $ipName = “myPip”
    $pip = New-AzureRmPublicIpAddress -Name $ipName -ResourceGroupName $rgName -Location $location `
    -AllocationMethod Dynamic

    Create the NIC. This example creates a NIC named myNic.

    $nicName = “myNic”
    $nic = New-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName -Location $location `
    -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id

  5. Create the network security group and an RDP rule

    To be able to log in to your VM using RDP, you need to have a security rule that allows RDP access on port 3389

    This example creates an NSG named myNsg that contains a rule called myRdpRule that allows RDP traffic over port 3389.

    $nsgName = “myNsg”

    $rdpRule = New-AzureRmNetworkSecurityRuleConfig -Name myRdpRule -Description “Allow RDP” `
    -Access Allow -Protocol Tcp -Direction Inbound -Priority 110 `
    -SourceAddressPrefix Internet -SourcePortRange * `
    -DestinationAddressPrefix * -DestinationPortRange 3389

    $nsg = New-AzureRmNetworkSecurityGroup -ResourceGroupName $rgName -Location $location `
    -Name $nsgName -SecurityRules $rdpRule

  6. Create a variable for the virtual network

    $vnet = Get-AzureRmVirtualNetwork -ResourceGroupName $rgName -Name $vnetName

  7. Create the Virtual Machine

    The following PowerShell script shows how to set up the virtual machine configurations and use the uploaded VM image as the source for the new installation.

    # Enter a new user name and password to use as the local administrator account
    # for remotely accessing the VM.
    $cred = Get-Credential

    # Name of the storage account where the VHD is located. This example sets the
    # storage account name as “myStorageAccount”
    $storageAccName = “manjugtestdisks”

    # Name of the virtual machine. This example sets the VM name as “myVM”.
    $vmName = “winmachimage”

    # Size of the virtual machine. This example creates “Standard_D2_v2” sized VM.
    # See the VM sizes documentation for more information:
    # https://azure.microsoft.com/documentation/articles/virtual-machines-windows-sizes/
    $vmSize = “Standard_D2_v2”

    # Computer name for the VM. This examples sets the computer name as “myComputer”.
    $computerName = “winmachimage”

    # Name of the disk that holds the OS. This example sets the
    # OS disk name as “myOsDisk”
    $osDiskName = “myOsDisk”

    # Assign a SKU name. This example sets the SKU name as “Standard_LRS”
    # Valid values for -SkuName are: Standard_LRS – locally redundant storage, Standard_ZRS – zone redundant
    # storage, Standard_GRS – geo redundant storage, Standard_RAGRS – read access geo redundant storage,
    # Premium_LRS – premium locally redundant storage.
    $skuName = “Standard_LRS”

    # Get the storage account where the uploaded image is stored
    $storageAcc = Get-AzureRmStorageAccount -ResourceGroupName $rgName -AccountName $storageAccName

    # Set the VM name and size
    $vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize

    #Set the Windows operating system configuration and add the NIC
    $vm = Set-AzureRmVMOperatingSystem -VM $vmConfig -Windows -ComputerName $computerName `
    -Credential $cred -ProvisionVMAgent -EnableAutoUpdate
    $vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id

    # Create the OS disk URI
    $osDiskUri = ‘{0}vhds/{1}-{2}.vhd’ `
    -f $storageAcc.PrimaryEndpoints.Blob.ToString(), $vmName.ToLower(), $osDiskName

    # Configure the OS disk to be created from the existing VHD image (-CreateOption fromImage).
    $vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri `
    -CreateOption fromImage -SourceImageUri $imageURI -Windows

    # Create the new VM
    New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm

  8. Verify that the Virtual Machine was created.

~ If this post helps at-least one person. The purpose is served. ~