Converting Linux VMWare VM using MVMC 3.0 PowerShell cmdlets

Converting VMs from VMWare to Hyper-V

The most easiest way to convert a VMWare VM is to use Microsoft Virtual Machine Converter 3.0. It comes in two ways, UI and PowerShell Cmdlets. The latter offers more flexibility, especially when the conversion process needs to be automated. Using MVMC you can either just convert a VM or convert and upload directly into Microsoft Azure.

Enable MVMC PowerShell module

1) cd into C:\Program Files\Microsoft Virtual Machine Converter
2) import-module .\MvmcCmdlet.psd1

This example converts a Linux VMWare VM into a Hyper-V VM using a PowerShell ComdLet

ConvertTo-MvmcVirtualHardDisk -DestinationLiteralPath "c:\temp\debian" -SourceLiteralPath "C:\VMs\Debian\disk1.vmdk" -VhdFormat "Vhd" -VhdType FixedHardDisk

Note: In the example I selected the older Vhd format and FixedHardDisk just because these settings are required when importing to Azure. For simple Hyper-V usage VHDX and Dynamic disk size are also possible certainly.

Now you can just create a new VM in Hyper-V Manager and point to the VHD(x) and the VM is available.



Uploading a converted VM into Microsoft Azure

Uploading into Azure means basically to upload the VHD into blob storage which then is taken as a base image you point to when creating a new VM. The easiest way to upload a VHD into a blob store is to use Azure CLI.

A command to create an image of the Linux VHD I used earlier looks like this:

azure vm image create DebianImage –blob-url {blobstoreName}/{imageName} –os Linux "c:\temp\debian\disk1.vhd"

With a Windows Server VHD it’s of course much more convenient and can be done from the MVMC UI directly.

Powershell DSC

In an automated deployment world, window clicking to install Windows features and roles is first of all boring, much too slow, highly error-prone and nineteen nineties.

My team was searching for a solution that helps us to describe and create a specific state of configuration of the operating system of a virtual machine, and that automatically and unattended.

Powershell Desired State Configuration makes it possible to define the wanted state in an easy to use abstract language. Powershell DSC “compiles” the configuration script at runtime on the target machine and applies the necessary actions. Actually, it’s not a compilation, more a transformation process from a domain specific meta language into real Powershell. Each step in the configuration script can be executed atomically, but dependencies are honored and can be configured. The Powershell DSC runtime deals with reboots and continues to process the script after a reboot.

Here’s an example, that configures a desired state by installing different features:

1 configuration InstallMir 2 { 3 node ("localhost") 4 { 5 WindowsFeature IIS 6 { 7 Ensure = "Present" 8 Name = "Web-Server" 9 } 10 #Install NET-Framework-45-Core 11 WindowsFeature NET45 12 { 13 Ensure = “Present” 14 Name = “NET-Framework-45-Core” 15 } 16 17 #Install ASP.NET 4.5 18 WindowsFeature ASP 19 { 20 Ensure = “Present” 21 Name = “Web-Asp-Net45” 22 } 23 24 #Install MSMQ 25 WindowsFeature MessageQueueFeature 26 { 27 Ensure = “Present” 28 Name = “MSMQ” 29 } 30 31 } 32 }


Powershell DSC for developers

Powershell Desired State Configuration also allows a development team to describe easily the configuration the application need on the host system. The domain specific language Powershell DSC is providing makes it easy for developers, who are often not Powershell experts to describe the wanted state in a precise manner.

Powershell DSC for DevOps / QA

From a DevOps QA point of view starting each new deploy from scratch with a reliable and deterministic state is heaven. Poweshell DSC closed the gap between a new Windows image and the installation of the software. All the prerequisites that need to be preinstalled can be described and installed using Powershell DSC.

It also helps in communication with other IT operations teams, because the required state of configuration can be communicated precisely. In fact, most is said by sending the Powershell DSC script.

Powershell DSC and Microsoft Azure

Microsoft Azure provides a VM extension that can be installed when creating the virtual machine. Through that extension Powershell DSC scripts can be executed easily. The Powershell DSC script needs to be uploaded to a Azure storage account first to make the script available for the target machine.

Here a script that uploads a Powershell DSC script into the Azure storage. The $ConfigurationPath variable contains the full path to the PowerShellDSC *.ps1 script on the local machine.

1 $StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccount -StorageAccountKey $StorageKey 2 Publish-AzureVMDscConfiguration -ConfigurationPath $ConfigurationPath -ContainerName $StorageContainer -StorageContext $StorageContext -Force 3

The next script executes the script on the target machine. First it creates a storage credentials object, then it loads the reference to the target VM and calls Set-AzureVMDscExtension to run the earlier uploaded DSC script. The extension is going to be installed if not already.

1 $StorageContext = New-AzureStorageContext -StorageAccountName $StorageAccount -StorageAccountKey $StorageKey 2 $vm = Get-AzureVM -ServiceName $mySvc -Name $vmName 3 4 Set-AzureVMDscExtension -VM $vm -ConfigurationArchive $ConfigZipFilename -ConfigurationName $ConfigName -Verbose -StorageContext $StorageContext -ContainerName $StorageContainer -Force | Update-AzureVM 5

Powershell DSC on Windows

Powershell DSC is onboard Windows 2012 R2 and Windows 8.1. Remotely executed on Windows 2012 R2 in Azure makes fun the most.

Stopping Azure VMs without loosing your IP address

Stopping a virtual machine in Microsoft Azure can be tricky, if you need to rely on the IP address assigned to the virtual machine. Because Azure releases the IP address if you stop the machine by default.

To avoid loosing the IP address you can use the Stop-AzureVM cmdlet together with the -StayProvisioned switch. By using this switch you are basically telling Azure that you like the VM to be stopped but keep it provisioned. This prevents Azure from releasing the IP address.


Stop-AzureVM–ServiceName 'cloud service name' -Name 'virtual machine name' –StayProvisioned

How to disable the BGInfo extension in Azure VM Agent

BGInfo is a very useful tool by SysInternals that collects machine configuration data and renders an image out of it to present it as background image of the Windows Desktop.

If a new virtual machine is created, the current Microsoft Azure platform adds a light weight process, called VM Agent, to the machine. The idea behind the VM Agent is to provide extensibility to the virtual machine. That makes it easy for the Azure platform to add other solutions to machine. One extension for instance allows you reset the default user password, what was impossible earlier. Read more about the VM Agent and VM Extensions here.

The VM Agent Extension manager also contains BGInfo and enables it by default.

You can either disable the VM Agent itself, by unticking the option in the Virtual machine configuration on the Azure management website or by using powershell cmdlets, read more here.

To disable just a specific extension, here BGInfo, run the following powershell command:

Get-AzureVM –ServiceName ‘CLOUD_SERVICE_NAME’ –name ‘VM_NAME’ | Set-AzureVMBGInfoExtension -Disable -ReferenceName "BGInfo" | Update-AzureVM

Replace the cloud service and virtual machine name by yours.

PowerShell Windows remote management of virtual machines in Azure

Working remotely on virtual machines in Windows Azure using PowerShell is something I do quite often. The first thing I do after I created a new virtual machine is in fact to enable Windows Remote Management (WinRM). Enabling WinRM makes it possible to connect from you local PowerShell to a PowerShell session on the target machine, just like an SSH session in the Linux world. You also can register PowerShell script blocks, stored in external files, and get them executed on the target machine. Because WinRM in the Windows Azure world demands an SSL/TLS connection the communication is secured.

Adding a virtual machine endpoint for PS remoting

If it’s not created already you need to create en endpoint for the virtual machine to allow PowerShell remoting. PS remoting uses the TCP port 5986, so the definition for the Azure endpoint that allows HTTPS secured PowerShell remote sessions might look like this:

get-azurevm $mySvc $vmName | Add-AzureEndpoint -Name PS-HTTPS -Protocol TCP -LocalPort 5986 -PublicPort 5986 | Update-AzureVM

Enabling PowerShell remoting on the target machine

If you are dealing with a virtual machine that has an older versions of Windows 2012 R2 installed you need to run the following command:

This command starts the windows service, sets the startup type to automatic and assigns a (HTTP) listener endpoint to all addresses the vm is providing.
Microsoft made it much more easy for us with Windows 2012 R2, because since then the WinRM service is running by default.

Adding an HTTPS listener to WinRM

By default WinRM installs an HTTP listener, what is less secure. In Windows Azure we need to secure the communication using SSL/TLS. To enable that it’s necessary to add the appropriate listener on the target machine. This HTTPS listener needs to be bound to a server certificate, what can be self signed or assigned by the usual authorities on the internet.
If you have the certificate installed you can run following command to add the listener in a standard command shell on the target machine:
winrm create winrm/config/Listener?Address=*+Transport=HTTPS @{Hostname="";CertificateThumbprint="THUMBRPINT"}
You need to replace the HOSTNAME by the host name of the target machine and the THUMBPRINT by the thumbprint value of the server certificate.
Now the virtual machine is ready to accept PowerShell remoting.

Open a Powershell Remote session using SSL and a credentials object

To open a remote session on the target machine in PowerShell we need to create a credentials object based on a username and password pair of the remote machine. We use a secure string object in PowerShell to handle the password securely.
$password = ConvertTo-SecureString $myPwd -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ($username, $password)
Enter-PSSession -ComputerName -Credential $cred -UseSSL
First we declare two variables for the password and username. Then we convert the plain text password into a secure string representation. Based on the secure password and the username we create a PowerShell credential object.
Finally, the Enter-PSSession command connects the remote machine and switches the context of the your PowerShell to the remote session just like SSH does on a Linux system.

Running a remote script using SSL and a credentials object

Running a script on a remote machine needs the same setup. We also need to provide a credentials object. The command can be a single line of code or a whole PowerShell script stored in a external file.
$password = ConvertTo-SecureString $myPwd -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ($username, $password )
$computername= "HOSTNAME"
$cmdAutoAdmin = { New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name AutoAdminLogon -Value "1" }
invoke-command -ComputerName $computername -Credential $cred -UseSSL -ScriptBlock $cmdAutoAdmin

This example uses the invoke-command to patch the a registry value on the remote machine. First, the command is stored in the cmdAutoAmdin value and then invoked on the remote machine.

Dealing with virtual machines in Windows Azure using PowerShell

I’m a great fan of  Windows Powershell.

The Windows Azure CmdLets for Powershell are a handy and powerful collection of tools to configure virtual machines in Windows Azure. You could use the Azure portal though to create and configure virtual machines in Azure, but if you need spin up a lot of machines, the configuration can be much more convenient to setup Powershell scripts that do the job for you.

Here is a list of cmdlets I found most useful to create, update and delete virtual machines in Windows Azure.

Tipp: The examples might include values in UPPERCASE, those need to be replaced by real data, like credentials of subscription, storage names. 

First things first, download and Azure Subscriptions

First you need to install the Windows Azure Powershell, this can be done using the Web Platform Installer. If you need to know more about how to install and configure Windows Azure PowerShell follow this link.

After you’ve installed Windows Azure PowerShell it’s necessary to connect your Azure subscription to the Windows Azure Powershell. This is done by running the following command:


The command will open your default web browser and guide to the Azure portal. You will need to authenticate with your Microsoft Account.

You’ll be prompted to download and save a .publishsettings file.  The .publishsettings file contains a list of all subscriptions for which your Microsoft Account is an admin or co-admin, as well as a base64 encoded management certificate.

Windows Azure will automatically associate the newly created management certificate with every subscription for which your Microsoft Account is an admin or co-admin. (read more here)

After you’ve downloaded the setting file you need to import the file by running the following command:

Import-AzurePublishSettingsFile "PATH TO DOWNLOADED SETTINGS FILE"

To list all available subscriptions run:


Set current storage

To create virtual machines you need to tell your Azure Subscription which Azure storage it should use. This is done by:

Set-AzureSubscription -SubscriptionName "SUBSCRIPTION NAME" -CurrentStorageAccount "STORAGE NAME"

Browsing OS images and Datacenter locations in Windows Azure

To view Available OS Images just type Get-AzureVMImage. The following sample loads all images into the $images array and iterates through the array to print out the item index and name.

$images = Get-AzureVMImage
for ($i=0; $i -le $images.length-1;$i++) {Write-Host $i $images[$i].Imagename}

The following sample retrieves all images and pipes the result into the Where-Object cmdlet that returns just those images that have Windows in the imageName property.

Get-AzureVMImage | Where-Object {$_.ImageName -like "*windows*"}

To get a list of Datacenter Locations available in Windows Azure:

$locations = Get-AzureLocation
for ($i=0; $i -le $locations.length-1;$i++) {Write-Host $i $locations[$i].DisplayName}

Print only the names of the Azure Datacenter Locations using Select.

Get-AzureLocation | select Name

Creating a virtual machine using New-AzureQuickVM

To create a Quick VM, we need to name a unique service- and vm name. We need to provide a username and password for the administrator account and finally name the location where the system disk (VHD) should be placed in. Note: the current storage account and the location must fit together.

New-AzureQuickVM -Windows -name $vmName -ImageName $image -ServiceName $mySvc -Location $location -Password $myPwd -AdminUsername $username

Adding endpoints to the virtual machine

A virtual machine in Windows Azure is secured by an external firewall controlled by Windows Azure. To allow specific ports on the virtual machine to by accessible by the internet you need to configure endpoints for the virtual machines. Those endpoints are ports on the external firewall. Using port forwarding you can define which external ports should be open and to which internal ports requests should be forwarded.

Here’s a typical example using port 80 to allow access to a web server running on the virtual machine:

get-azurevm $mySvc $vmName | Add-AzureEndpoint -Name Web-HTTP -Protocol TCP -LocalPort 80 -PublicPort 80 | Update-AzureVM

This command is actually a concatenation of several cmdlets. First we get the virtual machine, then we add the endpoint and finally we perform an update of the vm. It needs a name, the protocol and the external and internal port to add an endpoint.