Manage Azure Networks Using The .NET Azure Management Libraries

In this post I’m going to show you how to manage Azure Networks using the .NET Azure Management libraries.

In general I find the Azure Management Libraries a pleasure to work with except for the network management library. Retrieving your network configuration is easy enough but using it to configure your network is more difficult than it should be. I did this investigation out of curiosity more than anything else and I recommend using PowerShell to manage Azure instead of the management library. But enough ranting and on to the demo.

I used Visual Studio 2015 for this demo and .Net 4.5, I already had the Azure SDK installed in my environment so I’m not sure if it is a requirement for the management libraries but I doubt it.

For this demo I used an empty console project but there are project templates for Azure management projects in Visual Studio if you want to do something more complicated.

Manage Azure Networks Using The .NET Azure Management Libraries

After creating the your console application install the management library nuget packages.

install-package microsoft.windowsazure.management

It will install a slew of other packages so it might take a few minutes on a slow internet connection.

To create the credentials you need to manage Azure you have to download your .publishsettings file, if you are not sure how to do it look here it is in the first part of the post. Open the .publishsettings file in a text editor and copy the Id and ManagementCertificate strings and paste them into the code below.

var cred = new Microsoft.Azure.CertificateCloudCredentials("yoursubid", new X509Certificate2(Convert.FromBase64String("yourcert")));

The retrieve your network settings use the NetworkManagementClient class with your credentials created above and iterate over the properties in the Networks object, for example to list subnets:

using (var netclient = new NetworkManagementClient(cred))
{
var networks = netclient.Networks.List();
Console.WriteLine("Networks:");
networks.VirtualNetworkSites.ToList().ForEach(x =>
{
Console.WriteLine(x.Name);
x.Subnets.ToList().ForEach(y => Console.WriteLine(y.Name + " " +              y.AddressPrefix));
}
);
}

This was the easy part, to configure your network you have to retrieve the current configuration as xml, manipulate it and then send it back to Azure.

var config = netclient.Networks.GetConfiguration();


XmlDocument doc = new XmlDocument();
doc.LoadXml(config.Configuration);

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

string rootns = @"http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration";
nsmgr.AddNamespace("ns1",rootns );

var subnets = doc.SelectSingleNode("//ns1:Subnets",nsmgr);

//Create SubNet node
XmlNode newsub = doc.CreateNode(XmlNodeType.Element, "Subnet", rootns);
XmlAttribute subname = doc.CreateAttribute("name");
subname.Value = "NewSubName";
newsub.Attributes.Append(subname);

//Create AddressPrefix node
XmlNode newaddr = doc.CreateNode(XmlNodeType.Element, "AddressPrefix", rootns);
newaddr.InnerText = "10.32.1.0/24";
newsub.AppendChild(newaddr);

//Add to Subnets
subnets.AppendChild(newsub);

var sw = new System.IO.StringWriter();
doc.WriteContentTo(new XmlTextWriter(sw));
var newconfig = new NetworkSetConfigurationParameters(sw.ToString());

var result = netclient.Networks.SetConfiguration(newconfig);

Console.WriteLine(result.Status);

At least it is worth all the trouble and you end up with a new subnet.

Manage Azure Networks Using The .NET Azure Management Libraries

Francois Delport

Automating Installers And Editing Config Files With PowerShell

In this post I’m going to take a deep dive into automating installers and editing config files with PowerShell.

I spent the last few weeks automating the installation and configuration of various 3rd party software components. It involved a fair bit of trail and error to get all of it working. I decided to compile all the scripts into a blog post in case someone else or even future me need a refresher or quick start.

Runnig MSI and Exe installers silently
MSI installers are easy to run silently and you can prevent it from rebooting the machine after installation. I also specified verbose logging, it comes in handy if the installer fails for some reason. Note the accent character  (`) used for escaping the double quotes (“) around the MSI file name. I enclosed the file name in double quotes in case it contained spaces. The second last line prints the command line parameters that are about to run to the console, in my case I was using Octopus and it was handy for debugging since the output is shown in the Octopus deployment log.

$msi = "/i `"AppToInstall.msi`""
$cmd = "MSIEXEC"
$q = "/qn"
$nrst = "/norestart"
$log = "/lv verbose.log"
$fullparam = $msi + " " + $q + " "+ $log + " " + $nrst
$fullparam  #optional, output the parameters to the console for debugging
Start-Process -file $cmd -arg $fullparam -PassThru | wait-process

You can write everything in a single line but I split the command and parameters up into different variables to make it more readable and easier when you want to change the script.

You also get Exe installers that wrap a MSI installer and in this case you have to pass some parameters to the Exe to make it silent /S and also a second set of parameters that it will pass to the MSI /V to hide the installer gui /qn and also to prevent rebooting in this case. Note the single qoutes (‘) on line two, this is another way to deal with double quotes in a string, PowerShell will treat this as a literal string.

$cmd = ".\Setup.exe"
$param = '/s /v"REBOOT=ReallySupress /qn"'  #note single qoutes
$cmd + " " + $param  #optional output to concole for debugging
Start-Process -file $cmd -arg $param -PassThru | wait-process

Note that everything after /V is passed as a single parameter to the MSI and should be enclosed in quotes.

Editing config files using PowerShell
The easiest ones are XML files, you find the node to change and you give it a value. In this case I am changing the InnerText of the element.

$file = 'PathToXmlFile.xml'
$xml = [xml](Get-Content $file)
$node = $xml.customconfig.usersettings.servers.FirstChild
$node.InnerText = 'localhost'
$xml.Save($file)

If you are dealing with .NET config files you can use the same technique as above. In this example I am changing the value of the UserEmailAddress setting in the AppSettings section. Note I am changing an attribute on the XML element this time.

$xml.configuration.appSettings.add | Foreach-Object {
if ( $_.key -eq 'UserEmailAddress' ) {
$_.value = "$internalEmailAddress";
}
}

You can also modify connection strings.

$xml.configuration.connectionStrings.add | Foreach-Object {
if ( $_.name -eq 'DefaultContext' ) {
$_.connectionString = "$connectionString";
$_.providerName = "$dbProvider";
}
}

Editing text files turned out to be a bit more work but luckily this was for a clean install so it always had the same values to start with. I build up a new config file by reading all the existing lines into a collection, replacing the current setting with the new value and then I overwrite the existing file with the new lines.

$fileName = "Custom.cfg"
$lines = Get-Content $fileName
$newlines = @()   #create the collection


Foreach($line in $lines) {
if ('[email protected]'.CompareTo($line) -eq 0)
{
$line =   $line.Replace('[email protected]',
'[email protected]')
}
$newlines += $line
}

Out-File $fileName -inputobject $newlines

Setting registry values was also pretty easy.

Set-ItemProperty -Path "HKLM:\Software\AppName\LicenseSettings" -Name "LicenseFile" -Value "PathToLicenceFile.lic"

I also had to create some environment variables, in this case it was a machine wide setting but you can also create one at user and process level.

[Environment]::SetEnvironmentVariable('USERCFG', 'PathToUserConfig.xml', 'Machine')

Hopefully this post covered most of the common tasks when it comes to automating installers, editing config files and registry settings to get you going quickly.

Francois Delport

How To Assign A Public Static IP Address In Azure

In this post I’m going to show you how to assign a public static IP address in Azure. There are a few different IP address concepts in Azure to discuss before I get to assigning public static IPs.

VIP
When you create a Cloud Service you get a virtual IP address (VIP), this is your public IP address for the Cloud Service, your Cloud Service DNS name resolves to this IP address. By default it is randomly assigned from a pool of addresses but you can reserve one. There is a limit of 5 reserved public IP addresses per subscription. This is also the source IP address for traffic originating from VMs in the service. You can only assign a reserved VIP when you create the Cloud Service. When traffic hits your VIP it goes through the Azure Load Balancer and then it is forwarded to the endpoints you setup in your Cloud Service.

DIP
The VMs you create also get an internal IP address (DIP) for each NIC attached to the VM. The DIP is used to communicate with VMs in the same Cloud Service or VNET. The NIC will keep the same DIP until it is stopped or deallocated. The DIP is assigned via DHCP but you can reserve one by adding your VM to a subnet and reserving a static IP.

PIP/ILPIP
Instance level public IP (ILPIP) is assigned directly to a VM and bypasses the Azure Load Balancer. Outgoing traffic from the VM will show the ILPIP as the source instead of the VIP. You don’t have to map endpoints to forward ports like you do with endpoints in the VIP since all ports are open to the internet but you have to setup the firewall on your VM to protect it. ILPIP is useful for passive FTP or anything that requires a large number of open ports. You cannot reserve a ILPIP. You can assign a ILPIP to existing VMs. You can access your VM directly over the internet using the ILPIP but since it changes when you stop the VM it is not very useful unless you also assign a DNS name to the VM.

Reserved VIP
When you reserve an IP in Azure it is not assigned to a Cloud Service by default, it goes into a pool of reserved IP addresses in your subscription. You then assign them to Cloud Services and roles or release them back into your pool. You pay for reserved IP addresses in your subscription even when it is not assigned to a Cloud Service so it is better to delete them if you know you will not need it again soon.

Assigning A Reserved VIP
To reserve a new IP address run:
New-AzureReservedIP –ReservedIPName "MyReservedIP" –Location "AzureRegionName"

To see the list of reserved IP addresses for you subscription:
Get-AzureReservedIP

To remove the the reserved IP address from your subscription:
Remove-AzureReservedIP -ReservedIPName "MyReservedIP"

You can assign the reserved IP address to a virtual machine when creating it but not to an existing one so it is important to plan the IP address assignment before the time. You have specify at least one endpoint when you use a reserved IP.

$VM = New-AzureVMConfig -Name $VmName -InstanceSize $InstanceSize -ImageName $SourceName

$VM |  Add-AzureEndpoint -Name "Remote Desktop" -Protocol "tcp" -PublicPort 3389 -LocalPort 3389

$VM |  Add-AzureEndpoint -Name "PowerShell" -Protocol "tcp" -PublicPort 5986 -LocalPort 5986

New-AzureVM -ServiceName "NewServiceName" -ReservedIPName "MyReservedIP" -Location "AzureRegionName" -VM $VM

Although you add the reserved IP to a VM when creating it, it will actually be the VIP for your cloud service.

Assigning A LPIP
You can assign LPIPs to existing VMs or new ones but keep in mind you cannot reserve the IP. You can see full example here, but the syntax is the same, you pipe Set-AzurePublicIP to Get-AzureVM or New-AzureVM.

Get-AzureVM -ServiceName "ServiceName" -Name VMName | Set-AzurePublicIP -PublicIPName "LPIPName" | Update-AzureVM

You can also pass in the DomainNameLabel parameter if you have a DNS entry you want to use with this IP.

Update: This post covers the classic deployment model, the ARM version is here.

Francois Delport

Copy Azure Virtual Machines Between Subscriptions

In this post I’m going to show you how to copy Azure Virtual Machines between subscriptions. Copying VMs between subscriptions basically involves copying the VM VHD to a storage account in the other subscription. The same method can be used to copy your VM to another storage account to move it to a different region for instance.

Since this is not a recurring tasks for me this method is not completely automated, it does involve some manual steps. If you need a 100% automated solution please take a look at this post which is completely scripted but much  longer.

Firstly import the publishsettings files for your subscriptions using Get-AzurePublishSettingsFile and Import-AzurePublishSettingsFile if this the first time you are going to use them in PowerShell.

Then execute the following script to copy the VHD, replacing the parts in bold with your values.

#Source VHD
$srcUri="https://yourstorageaccount.blob.core.windows.net/vhds/src_image.vhd"


#Source StorageAccount
$srcStorageAccount="src_storageaccount_name"
$srcStorageKey="src_storage_account_key"

#DestinationStorageAccount
$destStorageAccount="dest_storageaccount"
$destStorageKey="dest_storage_account_key"

#Create the source storageaccount context
$srcContext=New-AzureStorageContext
-StorageAccountName $srcStorageAccount
-StorageAccountKey $srcStorageKey

#Create the destination storageaccount context
$destContext=New-AzureStorageContext
-StorageAccountName $destStorageAccount
-StorageAccountKey $destStorageKey

#Destination ContainerName
$containerName="destinationcontainer"

#Create the  container on the destination
New-AzureStorageContainer -Name $containerName -Context $destContext

#Start the asynchronous copy, specify the source authentication
$copyblob=Start-AzureStorageBlobCopy -srcUri $srcUri -SrcContext $srcContext
-DestContainer $containerName -DestBlob "NewVHD.vhd"
-DestContext $destContext

In my case I was copying inside the same datacentre so it was very quick but if you are copying between regions or copying very large files you can use the snippit below to report the progress of the copy operation.

#Get the status of the copy operation
$copystatus= $copyblob | Get-AzureStorageBlobCopyState


#Output the status every 5 seconds until it is finished
While($copystatus.Status-eq"Pending"){
$copystatus=$copyblob|Get-AzureStorageBlobCopyState
Start-Sleep 5
$copystatus
}

Next on the destination you have to create a disk from the VHD that was copied. In the portal click on Virtual Machines –> Disks –> Create Disk and follow the wizard to create a new disk from the VHD you copied.

Copy Azure Virtual Machines Between Subscriptions

Now you can choose it under My Disks when you create a new VM.

Copy Azure Virtual Machines Between Subscriptions

Tips: In my case both subscriptions had the same name, to differentiate between them edit the .publishsettings file and change the name of one of the subscriptions before importing it.

Francois Delport

Change The MAC Address On Your Azure Virtual Machine

Today I’m going to show you how to add a second NIC to an Azure Virtual Machine and how to change the MAC Address on your Azure Virtual Machine.

I had this requirement while automating the deployment of a component that is license locked to the MAC address of a NIC. In itself this is not a problem but combined with Azure and our deployment workflow it presented some challenges. As part of the deployment workflow the Azure VM is deleted and restored from a VHD image. Since this process creates a new VM and new NICs you also get a new MAC address every time which caused the license check to fail.

To avoid interfering with the normal operation of the networking in Azure I thought it best to add a second NIC on its own subnet and use it for the license while leaving the default NIC intact.

So the first step was to create a new subnet and to give it a different IP address range from the default NIC.

Change The MAC Address On Your Azure Virtual Machine

The second step is to add another NIC to the VM when you create it:

Add-AzureNetworkInterfaceConfig -Name "LicenseNIC" -SubnetName "License" -VM $NewVM

Thirdly there is the PowerShell script to change the MAC address when the new VM is created. Credit to Jason Fossen for the original script. This script is executed on the VM itself not against Azure. You can use Invoke-Command for instance as part of your deployment script to execute it remotely on the VM.

In the script I identify the NIC  used for licencing based on it’s IP address 10.32.2.* and then I  retrieve the index number for this NIC. This index is the same one used to find this NIC in the registry.

$indexobj = Get-WmiObject win32_networkadapterconfiguration -Filter "ipenabled = 'true'" | Where-Object {$_.IPAddress -like "10.32.2.*" } | Select-Object -Property Index
$index = $indexobj.index

The registry key for the NIC always has four digits, so padleft, then get the key.

$index = $index.tostring().padleft(4,"0")
$regkey = get-item "hklm:\system\CurrentControlSet\control\class\{4D36E972-E325-11CE-BFC1-08002BE10318}\$index"

Set a new value for MAC address, in this case 30-D5-1E-DD-F2-A5.
$regpath = "hklm:\system\CurrentControlSet\control\class\{4D36E972-E325-11CE-BFC1-08002BE10318}\$index"
set-itemproperty -path $regpath -name "NetworkAddress" -value $("30-D5-1E-DD-F2-A5")

If the NIC is not refreshed the new MAC address is not picked up by the licensing component we used. This may not be neccesary depending on your use case.

ipconfig.exe /release """$($thenic.netconnectionid)""" | out-null
$thenic.disable() | out-null
$thenic.enable() | out-null
ipconfig.exe /renew """$($thenic.netconnectionid)""" | out-null

If you now look at your NIC properties you will see the new MAC address.

Change The MAC Address On Your Azure Virtual Machine

PS. On my Windows 10 machine it didn’t display properly on the NIC properties but you can use ipconfig /all to see the MAC address.

Francois Delport