Creating a VM from an Azure Image | Azure – Existing Network

I recently created a script to create a VM from an existing disk in Azure, using the v2 or ARM model.

This script created a new network but in most instances a network will already exist and although you will create a new NIC you will want to place this VM into an existing subnet.

The extract below can be used to create a new NIC but add this to a named vNet and Subnet.
When you define the VM configuration you would use this to be the NIC.
Finally make sure this (if the first NIC) is set as -Primary


#Networking
$NicName = $vmName + "NIC-Prod"
$Vnet = Get-AzureRmVirtualNetwork -Name "hubsydvnet" -ResourceGroupName $RGName
$SubnetProduction = Get-AzureRmVirtualNetworkSubnetConfig -Name "Sub-1" -VirtualNetwork $Vnet
$Nic = New-AzureRmNetworkInterface -ResourceGroupName $RGName -Name $NicName -Subnet $SubnetProduction -Location $Location

#Define VM Configuration
$VMConfig = New-AzureRmVMConfig -VMName $vmName -VMSize "Standard_DS2_v2" |
Set-AzureRmVMOperatingSystem -Windows -ComputerName $vmName -Credential $Cred -ProvisionVMAgent -EnableAutoUpdate |
Set-AzureRmVMOSDisk -Name $OSDiskName -VhdUri $OSDiskUri -CreateOption FromImage -SourceImageUri $URIofuploadedImage -Windows |
Add-AzureRmVMNetworkInterface -Id $Nic.ID -Primary

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Tag Azure VMs and Resources

Tagging in Azure is a massively useful feature.  I have customers who are interested in identifying resources for billing but they are also a very useful tool for control.  Resources can be grouped by tag and then a script can be used to apply a function to all machines or services with the same tag.

In the example below I call a variable that looks for Azure resources where the type is identified as a Microsoft virtual machine.  Calling this function enables me to extract a range of information. (I fact this script then goes on and uses the ResourceId too)

As referenced in Using tags to organize your Azure resources tags are updated as a whole so if you want to add additional tags you first have to call the existing tags.  In the example below I am adding the new tag to my existing tags.

Finally we are looping this for each vm and applying via a set command.

Hope this is of use to you, happy tagging :-)!


$FindVMs = Find-AzureRmResource | where {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}
$Tags = (Get-AzureRmResource -ResourceId $ResourceId).Tags
$Tags += @{ Owner = "wade" }

Foreach ($vm in $Findvms)
{
$ResourceId = $VM.ResourceId
Set-AzureRmResource -Tag $Tags -ResourceId $ResourceId -Force
}

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Auto Shutdown ASM Virtual Machines in Azure | Azure Automation

I put together a quick script to auto shutdown tagged ARM VMs.

There are many people still running ASM VMs and why wouldn’t you they are still supported (as of 9/2016).

The process is not much different and in fact now Azure Automation enables a RunAs account at set up its much easier to configure.

In the example below I have tacked on changes to the Azure Automation Team’s sample script, one of four created for you when you enable the feature.

<# .DESCRIPTION An example runbook which gets all the Classic VMs in a subscription using the Classic Run As Account (certificate) and then shuts down running VMs .NOTES AUTHOR: Azure Automation Team + Jonathan Wade LASTEDIT: 28-08-2016 #>

$ConnectionAssetName = "AzureClassicRunAsConnection"
$ServiceName = "wadeclassiv01"
	
# Get the connection
$connection = Get-AutomationConnection -Name $connectionAssetName        

# Authenticate to Azure with certificate
Write-Verbose "Get connection asset: $ConnectionAssetName" -Verbose
$Conn = Get-AutomationConnection -Name $ConnectionAssetName
if ($Conn -eq $null)
{
    throw "Could not retrieve connection asset: $ConnectionAssetName. Assure that this asset exists in the Automation account."
}

$CertificateAssetName = $Conn.CertificateAssetName
Write-Verbose "Getting the certificate: $CertificateAssetName" -Verbose
$AzureCert = Get-AutomationCertificate -Name $CertificateAssetName
if ($AzureCert -eq $null)
{
    throw "Could not retrieve certificate asset: $CertificateAssetName. Assure that this asset exists in the Automation account."
}

Write-Verbose "Authenticating to Azure with certificate." -Verbose
Set-AzureSubscription -SubscriptionName $Conn.SubscriptionName -SubscriptionId $Conn.SubscriptionID -Certificate $AzureCert 
Select-AzureSubscription -SubscriptionId $Conn.SubscriptionID

# Get cloud service
    
$VMs = Get-AzureVM -ServiceName $ServiceName

    # Stop each of the started VMs
    foreach ($VM in $VMs)
    {
		if ($VM.PowerState -eq "Stopped")
		{
			# The VM is already stopped, so send notice
			Write-Output ($VM.InstanceName + " is already stopped")
		}
		else
		{
			# The VM needs to be stopped
        	$StopRtn = Stop-AzureVM -Name $VM.Name -ServiceName $VM.ServiceName -Force -ErrorAction Continue

	        if ($StopRtn.OperationStatus -ne 'Succeeded')
	        {
				# The VM failed to stop, so send notice
                Write-Output ($VM.InstanceName + " failed to stop")
	        }
			else
			{
				# The VM stopped, so send notice
				Write-Output ($VM.InstanceName + " has been stopped")
			}
		}
    }


Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

PowerShell to list ASM VMs, Size and CloudService | Azure

I’ve been asked several times now to help customers running IaaS VMs in the Classic mode (ASM Mode) analyse their resources.

The following will list your classic VMs out by CloudService, VMName and VMSize to a CSV file.

You’ll need to edit the location of the file.

Please note this is not meant to be a very sophisticated script just to get you to the answer.

Happy hunting!


Add-AzureAccount
$services = Get-AzureVM | Group-Object -Property ServiceName
foreach ($service in $services)
{
   $out = @()
foreach ($VM in $service.Group)
{ 
$VMSizes = $VM.InstanceSize 

    $props = @{
        Cloudservice = $service.Name        
        VMName = $VM.Name
        VMSizes = $VMSizes
        }
    
    $out += New-Object PsObject -Property $props
}
   $out | Format-Table -AutoSize -Wrap CloudService, VMName, VMSizes
   $out | Export-Csv c:\scripts\test.csv -append
} 
 

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Creating a VM from an Azure Image | Azure

Working with Azure in the enterprise means you will quickly want to create your own custom images.  In this introductory article I will show you an example of how to create an image from an existing generalized imaged.

Please note:

  • This is utilising the ARM model and does not apply to Classic.
  • This assumes you have created a generalized image in Azure and know where it is!
  • This process is not considering on premises VMs.
  • This process uses Windows images.

The following documents and articles were used to create the script below.  Many thanks to the efforts and hard work of the authors.

Create a Virtual Machine from a User Image by Philo

Upload a Windows VM image to Azure for Resource Manager deployments by Cynthia Nottingham

Cynthia shows how to create the image and find the URL of the uploaded image.  She also gives detailed examples of the PowerShell scripts required to create the new VM.

Philo uses variables for existing networks which I found very useful and just comment out the pieces I do not need, e.g. when the vnet already exists.

Happy VM creating!


$cred = Get-Credential
$rgName = "ResourceGroupName"
$location = "Azure Location"
$pipName = "Public IP address Name"
$pip = New-AzureRmPublicIpAddress -Name $pipName -ResourceGroupName $rgName -Location $location -AllocationMethod Dynamic
$subnet1Name = "Subnet Name"
$vnetSubnetAddressPrefix = "Subnet address e.g. 10.1.0.0/24"
$vnetAddressPrefix = "vnet address e.g. 10.1.0.0/16"
$nicname = "Name of Nic"
$vnetName = "Name of vnet"
$subnetconfig = New-AzureRmVirtualNetworkSubnetConfig -Name $subnet1Name -AddressPrefix $vnetSubnetAddressPrefix
#$vnet = New-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName -Location $location -AddressPrefix $vnetAddressPrefix -Subnet $subnetconfig
$nic = New-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $rgName -Location $location -SubnetId $vnet.Subnets[0].Id -PublicIpAddressId $pip.Id
$vmName = "Name of VM"
$vmConfig = New-AzureRmVMConfig -VMName $vmName -VMSize "Standard_A4"
$computerName = "Nameof Cumputer"
$vm = Set-AzureRmVMOperatingSystem -VM $vmConfig -Windows -ComputerName $computerName -Credential $cred -ProvisionVMAgent -EnableAutoUpdate
$vm = Add-AzureRmVMNetworkInterface -VM $vm -Id $nic.Id
$osDiskName = "Name of Disk"
$osDiskUri = '{0}vhds/{1}{2}.vhd' -f $storageAcc.PrimaryEndpoints.Blob.ToString(), $vmName.ToLower(), $osDiskName
$urlOfUploadedImageVhd = "URL to generaized image https://somename.blob.core.windows.net/system/Microsoft.Compute/Images/templates/name-osDisk.00aaaa-1bbb-2dd3-4efg-hijlkmn0123.vhd"
$vm = Set-AzureRmVMOSDisk -VM $vm -Name $osDiskName -VhdUri $osDiskUri -CreateOption fromImage -SourceImageUri $urlOfUploadedImageVhd -Windows
$result = New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vm
$result

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Auto Shutdown ARM Virtual Machines in Azure | Azure Automation

With the release of the RunAs feature in Azure Automation.  A service account can now be called in Azure Automation scripts to enable and run Resource Manager functions.

I think one of the most useful features of this is to auto shutdown virtual machines by TAG.

In the example below I have set up the following:

  • A TAG called “Environment” with and ID of “Lab” and applied to each VM I want to control.
  • A RunAs service account as part of my AzureAutomation resource.
  • A PowerShell Workflow script to scan for the TAGs applied to Windows virtual machines and to shut them all down in parallel.
  • An Azure Automation schedule to run Monday-Friday at 17:00 to call the published workflow.

When configuring a schedule through the browser it uses the browser’s local time zone.  This is stored in UTC but is converted for you.   You’ll need to consider this is managing multiple resources across the globe.

This workflow and process has been created via the Azure Portal.

The -Parallel feature is only available in Powershell Workflows.

workflow TestPowershellworkflow
{
$Conn = Get-AutomationConnection -Name AzureRunAsConnection
Add-AzureRMAccount -ServicePrincipal -Tenant $Conn.TenantID -ApplicationId $Conn.ApplicationID -CertificateThumbprint $Conn.CertificateThumbprint

    $FindVMs = Find-AzureRmResource -TagName "Environment" -TagValue "Lab" | where {$_.ResourceType -like "Microsoft.Compute/virtualMachines"}

   Foreach -Parallel ($vm in $Findvms)

   {
    $vmName = $VM.Name
    $ResourceGroupName = $VM.ResourceGroupName

    Write-Output "Stopping $($vm.Name)";
    Stop-AzureRmVm -Name $vm.Name -ResourceGroupName $ResourceGroupName -Force;
    }
}

I’d be very interested in your feedback.  Happy automating.

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Moving Resources between Resource Groups | Azure

From a best practise point of view, I try to use Resource Groups as containers for all items I consider as part of the same lifecycle.  This allows me to remove, delete and recreate what I need without fear of losing a component and generally allows me to be more efficient.  I like peace of mind.

However, when it comes to best practise sometimes it feels slow and cumbersome.  “This is the Cloud I don’t want to be held back by anything” I shout from the roof tops in my superhero pyjamas!

The truth is best practise and / or procedure shouldn’t get in the way of anything at all but if I’m just spinning up a few resources to test a lab someone has sent me on a payment gateway or vNet to vNet VPN set up, this pyjama wearing superhero isn’t waiting around for anyone.   I therefore plough ahead.

Thankfully for rash people like me the Move-AzureRmResource command comes to the rescue.  https://msdn.microsoft.com/en-us/library/mt652516.aspx

For single resources I would first get the details of the resource you would like to move, this is important because you may have named two resources the same (remember what I was saying about being rash).

Get-AzureRmResource -name "resourcename" -ResourceGroupName "resourcegroupname"

Once you have the details you can then specify the ResourceType in the variable call.

Set up the variable as follows with the ResourceType, ResourceGroupName and ResourceName. Then move the resource.

$Resource = Get-AzureRmResource -ResourceType "Microsoft.Network/virtualNetworks" -ResourceGroupName "resourcegroupname" -ResourceName "resourcename"
Move-AzurermResource -ResourceId $Resource.ResourceId -DestinationResourceGroupName "newresourcegroupname"

Please note: It will move dependencies, for example if you want to move a VM it will move the components such as Public IP and Network Security Group.  As is, you will be prompted that you want to move the resource and the associated resources, if they exist.

Moving resources is simple and easy.  Best practise is important and no Cloud architect should be seen in public in their superhero pyjamas!

Azure Commander over and out……

Disclaimer:  Please note although I work for Microsoft the information provided here does not represent an official Microsoft position and is provided as is.

Citrix Provisioning Server – Cache in device RAM with overflow on hard disk

I first wrote about Citrix Provisioning Server (PVS) in 2012 and focused on a feature called vDisk Update Manager.  Back then PVS was at version 6.0, the current release is version 7.1 and again it’s worth time looking at a small change that has made a massive impact.

In this release Citrix has introduced the vDisk feature Cache in device RAM with overflow on hard disk.

Before we leap into cache first lets wind back a little and quickly look at PVS.  I have to admit that in a lot of recent work I have been using Citrix Machine Creation Services (MCS) not PVS, I’ve been neglecting one of Citrix’s imaging technologies because I’m not managing a production site and therefore not having to deal with patching and updates or worrying about backend performance.  A lot of the work I do is demonstrations and proof of concepts therefore convenience is good for me .  I’ve certainly found MCS useful and have a number of customers doing really good things with the utility in production at scale.  However the ace PVS has always carried is the ability to redirect the locations of disk writes and it’s a trump card as good as any you carried in the playground.

Why is that important?  It’s been well documented that virtual desktops create lots of writes, in small blocks too.   Although we are far from the early days of desktop virtualisation and therefore this no longer comes as a surprise (if it came as a surprise I’d argue you didn’t really understand desktops before you started), PVS has come up with the perfect answer with its new write cache option.

There are now six options for the vDisk Cache type:

  • Cache on device hard drive
  • Cache on device hard drive persisted (NT 6.1 and later)
  • Cache in device RAM
  • Cache in device RAM with overflow on hard disk
  • Cache on server
  • Cache on server persisted

I have only ever used PVS with XenDesktop and XenApp and have only ever looked at Cache in device RAM and Cache on device hard drive.  I’ve always liked the idea of caching things in RAM, its fast and has become relatively cheap but fill it up and you have no where to go.  Well you do it crashes the server instance and that in the end does give us somewhere to go the exit door!

The second option, up till now, has been move those writes to a hard disk on the host and take them away from your storage.  The theory, we don’t wan’t to keep them with our pooled desktops so let’s write to a location thats out of the way, of the network and cheaper.  Many production environments use this and it works very well.

But now we have the ultimate hybrid; Cache in device RAM with overflow on hard disk.  We can use the RAM option without the risk.

To implement this feature is a straight forward procedure.

Make sure you have a disk to overflow to, if you are using the XenDesktop Setup Wizard in PVS this is created for you.  If not you do need to have this; it will need to be part of your VM as  local disk on the host and will appear as the next available drive letter in the VM when it boots (note- the streamed disk will normally be the first disk).

You are now ready to switch on the feature in the vDisk properties.  Remember that to do this the disk has to have no locks. The feature is found in the properties section of the vDisk, in your Store.

Once enabled you are asked to select a value for the Maximum RAM size in MBs.  This is the amount of RAM to use as the cache, in the example below I have used 512MB.   Note you should make sure you have an additional 512MB or RAM assigned to your VM.  You can play around with these numbers to find the best fit for your environment.  I have found that with good storage and server based hardware 512MB works very well, however in older environments and some labs I’ve increased this number to 1.5GB to get good results.

 

 

 

Citrix Provisioning Server vDisk Update Management

Citrix Provisioning Server (PVS) is now at version 6.1.  Released in version 6.0 was the vDisk Update Manager and I think it is worth some time looking more closely at this feature.

Once installed and configured the PVS management console has a new node the vDisk Update Manager.  This has three sections; Hosts, vDisks and Tasks.

Hosts; references the hypervisor hosts in use, XenServer ESX and Hyper-V are all supported.

vDisks; is the PVS vDisks enabled for update management.

Tasks; is the automated scripts that power the Electronic Software Distribution (ESD) client software.  Microsoft System Center Configuration Manager (SCCM), Microsoft Windows Update Service (WSUS) and custom scripts are all supported.  Please note: the ESD client software must already be installed in the vDisk image.

First let’s take a look at manual updates. In previous versions you had to make a copy of the vhd file (vDisk), mount this against a new machine in PVS, boot and make the changes required, shutdown the image, increment the vDisk version number and make it available to all machines.  It was possible to script this process via PowerShell however in my experience not everyone did this and there was still manual work to do to integrate this into your environment.

To utilise the new features you require a running environment with machines utilising a standard mode vDisk.  This feature is only available for standard mode disks; private disks are read / write and therefore can be managed by existing ESD tools.

Step one is to add the host that you are using; right click on the Hosts node and follow the wizard.  You will require the correct host / pool credentials.

Step two is to add a vDisk to this tool; right click on the vDisks node and follow the wizard.  This will search your Store for available vDisks and ask you to enter the VM on your host that will be used as your maintenance VM. Finally it will require an AD machine account in order to process the updates to the vDisk.  If you have not created the VM on your host with then name specified in this step do so now.

In the image below you can see the PVS Services Console with the properties of the vDisk Update Management node highlighted.  It shows that the vDisk in the Store StoreW7 is on host XenServer-1 and the VM on the host that will use this disk is called W73.  The vDisk has to exist before you start step two however it does not check the Host to make sure the VM is there, so this can be created after if required.  It will however need to be present for this process to work correctly, as highlighted below XenCenter is showing a VM with the name of W73.

Once this is completed from the Stores node you can select the vDisk and manage the Versions.  Right click on the vDisk in the Store and select Versions.

Select New; this will create a new disk in Maintenance mode.  To edit this disk boot your maintenance VM from the Host.  Once this is completed if you refresh the vDisks Versions  console you will see a single device is now accessing this version of the disk and that the Access type is Maintenance. Please note: you have not had to remove any locks form the existing vDisk, log off any users or shut down machines to start this process.


You can now make any changes required to the VM as the version you are using is in read write mode.  To achieve this PVS is using avhd files and creating a chain to the original disk.   This saves on time and disk space when making changes,  it also means if we are not happy with the results we can revert back quickly to the previous image.  Once we are satisfied with the build we can merge all updates, this stops a long chain becoming a performance drain.
Reboot the VM to apply any changes and then shut the Maintenance VM down.  You can then Promote the vDisk and can set the access version to Test or Production.  If you set it to Production and apply the changes immediately, on next reboot all users will have access to this disk.

Before reboot the VMs are still using disk 7.3

After reboot they are now using 7.4

As you can see this is a great improvement on the original way of updating the vDisk.  However you will not always want to run through this process, especially when it comes to patching.  This is where the Tasks feature of the vDisk Update Management tool comes into play.  To implement; right click the Tasks node and follow the simple steps.  This will by default allow you to connect to WSUS, SCCM or implement pre or post scripts.  Like all tasks this can be scheduled and after the update the vDisk can be placed into Maintenance, Test or straight into Production modes.

In my opinion simplifying this process for desktops is a great win for XenDesktop.  It makes it an easy step to get to grips with PVS and by integrating into SCCM and WSUS most desktop admins see significant advantages to their current virtual desktop update process.  If you couple this with the advantages of PVS in terms of single image disk management, read IOPS cache and control over the write IOPS then we now have access to a powerful desktop management tool.

Finally lets not forget that all these advantages are available to XenApp too.  With a number of organisations now virtualising XenApp servers the number of server instances is on the rise, what better way to manage them than with PVS.

***Update***

Stephen (comments below) has provided some links to PVS documentation that go into more detail on additional tasks.  Thanks Stephen.

Creating and Managing Tasks

vDisk Update Task Properties

Thread: vDisk update: custom scripts

***Update*** 23/11/2012

You should all read Jarian Gibson’s post – Great article  Updating Provisioned XenApp vDisks: To XenAppPrep or not to XenAppPrep?

Citrix VDI-in-a-Box: Sizing Calculator

Using the calculations and assumptions made in the post Citrix VDI-in-a-Box: Sizing Guide I have created the following sizing calculator.

Procedure    

  • Enter total number of users (desktops)
  • Decide on the type of user; Power user or Normal user

Normal user: ~10 IOPS per concurrent user. This user is probably working in a few applications with minimal web browsing.

Power user: ~25 IOPS per concurrent user. This user usually runs multiple applications concurrently and spends considerable time browsing the web.

User definitions taken from “Finding a Better way to estimate IOPS for VDI

  • Enter golden image size
  • Enter number of Golden images you will use
  • Review total hardware requirements

Please note:

  • All assumptions can be edited, therefore you can change the IOPS, RAM or CPU numbers for each setting.  
  • This spread sheet has been published using Microsoft Office Web Apps and therefore might not be available on all platforms.  If demand exists I will look to change that.
  • All calculations use the ROUNDUP fucntion therefore numbers may vary from original post but will provide more accurate if looking at hardware configurations.

Citrix VDI-in-a-Box: Sizing Calculator Version 1.0