Creating Azure Virtual Networks using Powershell and XML

Posted by Rik Hepworth on Monday, March 3, 2014

I’ll be honest, I expected this task to be easier than it is. What I’m working on is some powershell that we might use as part of automated build processes that will create a new Virtual Network in an Azure subscription. What I’m after is to add a new network to the existing configuration.

There aren’t many powershell commands for Azure virtual networks. The two we need to use are get-azureVnetConfig and set-azureVnetConfig.

Get-azureVnetConfig when run generates xml that details the configuration of all virtual networks within the current Azure subscriptions. Set-azureVnetConfig takes an xml configuration and modifies the entire virtual networking configuration to match that described in the file.

My original plan of simple powershell to add a new virtual network went quickly out of the window, then. My second thought was to grab the xml configuration, manipulate it using powershell, then stuff it back into Azure. That plan was hindered by the fact that the set-azureVnetConfig command insists on reading the configuration from a file on disk, so I can’t just hand it my XML object, created by manipulating the output of get-azureVnetConfig.

I’m still working on this – I now have a script with some tidy functions to do repetitive tasks. This post is simply going to outline the first bit of heavy lifting I’ve had to do in order to solve enough problems that I can get a config, add stuff to it and reload it into Azure.

The steps below don’t create all the configuration we will want, but it creates all the configuration we need to add a new network.

1. Get the current Azure Config

This bit is easy:

$currentVNetConfig = get-AzureVNetConfig

That gives us an object which contains the XML configuration. We need to get just the XML out, so:

[xml]$workingVnetConfig = $currentVNetConfig.XMLConfiguration

2. Find the VirtualNetworkSites element

The networks I want to create are all held in the VirtualNetworkSites element, each one in a VirtualNetworkSite element. I can create new VirtualNetworkSite elements, but I need to grab the element in which to create them first:

$virtNetCfg = $workingVnetConfig.GetElementsByTagName("VirtualNetworkSites")

3. Add a new Virtual Network

To add a new network we need to add a new VirtualNetworkSite element. I hit a snag with this, in that I kept getting a spurious xmlns attribute on the element that caused set-azureVnetConfig to spit out the file as invalid. It turns out that in order to avoid this, we have to specify the XML namespace URI when we create the new element. That’s the second parameter on the CreateElement method, below.

Creating the element itself is a two-stage process: First we create a new element inside our XML object, then we put that element in the right place by calling appendchild on the intended parent element. In addition, we need to add a couple of attributes to that element, specifying the name of the network and the affinity group it will sit in:

$newNetwork = $workingVnetConfig.CreateElement("VirtualNetworkSite","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$newNetwork.SetAttribute("name","myVirtualNetwork")
$newNetwork.SetAttribute("AffinityGroup","MyAffinityGroup")
$Network = $virtNetCfg.appendchild($newNetwork)

4. Add an address space

This is a similar process. I need an AddressSpace element and within that sits an AddressPrefix element. That element needs text that tells Azure the IP address space to use, and that’s added by setting the innerText property.

$newAddressSpace = $workingVnetConfig.CreateElement("AddressSpace","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$AddressSpace = $Network.appendchild($newAddressSpace)
$newAddressPrefix = $workingVnetConfig.CreateElement("AddressPrefix","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$newAddressPrefix.InnerText="10.0.0.0/8"
$AddressSpace.appendchild($newAddressPrefix)

5. Add a subnet

Virtual networks need subnets. There is a Subnets element that contains multiple Subnet elements, each of which has an AddressPrefix element.

$newSubnets = $workingVnetConfig.CreateElement("Subnets","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$Subnets = $Network.appendchild($newSubnets)
$newSubnet = $workingVnetConfig.CreateElement("Subnet","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$newSubnet.SetAttribute("name","Subnet-1")
$Subnet = $Subnets.appendchild($newSubnet)
$newAddressPrefix = $workingVnetConfig.CreateElement("AddressPrefix","http://schemas.microsoft.com/ServiceHosting/2011/07/NetworkConfiguration")
$newAddressPrefix.InnerText="10.0.0.0/11"
$Subnet.appendchild($newAddressPrefix)

6. Write out to a file and then use that file

$tempFileName = $env:TEMP + "\\azurevnetconfig.netcfg"  $workingVnetConfig.save($tempFileName)   set-AzureVNetConfig -configurationpath $tempFileName

Next Steps

If you don’t have any Azure networks defined then get-azureVnetConfig will give you nothing. That means that more XML needs to be generated for a new network configuration. I’m working on a more expansive script right now and I’ll post that when I get something meaningful to show.