On Windows PowerShell and other admin-related topics

Automate a task in System Center Virtual Machine Manager 2012 based on the “View Script” button

System Center Virtual Machine Manager has since the beginning had excellent automation capabilities in form of Windows PowerShell. In fact, everything that is performed in the SC VMM Console generates a PowerShell command which is being invoked as a job. A very useful feature in the SC VMM Console is the “View Script” button, which shows you the actual PowerShell commands that is being run. To show you how you can leverage this functionality, I am going to show you how I used it to automate one part of a new deployment.


Provisioning Logical Networks in System Center Virtual Machine Manager 2012

In System Center Virtual Machine Manager 2012 there is a concept called Logical Networks, which is defined as part of the Fabric. You can read more about Logical Networks in this article by the SC VMM team. Step-by-step guidance on how to create and assign a logical network is available in this TechNet Wiki guide by Microsoft MVP Kristian Nese.

What I want to show you in this article is how you in an easy manner can automate the process of creating and assigning virtual networks. I recently had to provision close to 100 logical networks in a new deployment, and as you can read in the mentioned articles I first needed to create the Logical Networks and then go to the Properties of every virtualization host and assign the correct Logical Network to the correct physical NIC.

In my scenario that would mean more than 1000 mouse clicks if doing the task manually. Next I will show you how to automate the creation and assignment of logical networks.


Create the Logical Network

Start the “Create Logical Network” wizard from the Fabric pane in VMM:


Creating a Network Site is not mandatory, but this is something I needed in my scenario:


Click on the “View Script” button on the Summary page (click Cancel in the wizard afterwards):



You will be presented with a PowerShell script in a Notepad window. This is the script I got:

$logicalNetwork = New-SCLogicalNetwork -Name "Backend"

$allHostGroups = @()
$allHostGroups += Get-SCVMHostGroup -ID "0e3ba228-a059-46be-aa41-2f5cf0f4b96e"
$allSubnetVlan = @()
$allSubnetVlan += New-SCSubnetVLan -VLanID 0

New-SCLogicalNetworkDefinition -Name "Oslo" -LogicalNetwork $logicalNetwork -VMHostGroup $allHostGroups -SubnetVLan $allSubnetVlan -RunAsynchronously

This above script is the what I will use as the template for my new Logical Network provisioning script. A common approach for creating multiple items is using a foreach loop, but first we need some data which the loop will iterate over. Ìf you have all your Logical Networks defined in an Excel spreadsheet, which was the case for me, you can save the spreadsheet as a comma-separated file and use that as the data source in the script. In PowerShell it is also possible to use a broad number of data sources, for example a SQL database.

After creating a CSV-file I customized the column headers in the file, which will serve as the property names for the imported objects. Here is a sample CSV-file from my lab environment:


Backend,"This is the corporate backend network","All Hosts",0,Oslo,Trunk

As you can see in my customized script there is not very much that is changed:

$networks = Import-Csv -Path C:\Import\VMM_logical_networks.csv

foreach ($network in $networks) {

$logicalNetwork = New-SCLogicalNetwork -Name $network.Name -Description $network.Description

$allHostGroups = @()
$allHostGroups += Get-SCVMHostGroup -Name $network.HostGroup
$allSubnetVlan = @()
$allSubnetVlan += New-SCSubnetVLan -VlanID $network.VlanID

New-SCLogicalNetworkDefinition -Name $network.Site -LogicalNetwork $logicalNetwork -VMHostGroup $allHostGroups -SubnetVLan $allSubnetVlan -RunAsynchronously

A brief overview of the changes:

  • On the first line we import the contents of the CSV-file using the Import-Csv cmdlet.
  • Next we iterate over each entry in the CSV-file by using a foreach loop from line 3 to 13. This means that line 4 to 12 will be repeated for every line in the CSV-file.
  • The last customization is made to the parameters of the cmdlets in the script. For example the Name property of New-SCLogicalNetwork is the value ($network.Name) of the Name property of the imported CSV objects.


Assigning the Logical Network

The final task is to assign the Logical Networks we created to the correct physical NICs of the virtualization hosts. Again we start by doing the task in the SC VMM Console:

Go into the Properties dialog of one of the virtualization hosts, select Hardware and then select a NIC.

Press the check box of two or more Virtual Networks, and the click the “View Script” button (click Cancel in the Properties dialog afterwards):


We can see that the generated script is a bit more complicated than the previous one:

$vmHost = Get-SCVMHost -ID "82b7c0f3-ed2e-4dcc-8b05-40765dba712e" -ComputerName "hpv-jr-02"

$vmHostNetworkAdapter = Get-SCVMHostNetworkAdapter -Name "Broadcom NetXtreme Gigabit Ethernet" -VMHost $vmHost

# Backend
$logicalNetwork = Get-SCLogicalNetwork -ID "b036b32a-8139-4b0e-babc-cda1e98ef2e7"
Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $vmHostNetworkAdapter -AddOrSetLogicalNetwork $logicalNetwork -JobGroup "4af63cdf-ea00-4647-b554-cc7167070f33"

$logicalNetwork = Get-SCLogicalNetwork -ID "292c0075-f81d-4af9-81f5-c775c5bcf90a"
Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $vmHostNetworkAdapter -AddOrSetLogicalNetwork $logicalNetwork -JobGroup "4af63cdf-ea00-4647-b554-cc7167070f33"

Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $vmHostNetworkAdapter -Description "" -JobGroup "4af63cdf-ea00-4647-b554-cc7167070f33" -VLanMode "Access" -AvailableForPlacement $true -UsedForManagement $true

Set-SCVMHost -VMHost $vmHost -JobGroup "4af63cdf-ea00-4647-b554-cc7167070f33" -RunAsynchronously

We will continue to use the same CSV-file as we did when creating the logical networks. You might have noticed that there was one column in the CSV-file we did not use in the first script: VMHostAdapterName. This is a property which will be used to assign the logical networks to a physical NIC on a virtualization host, based on the connection name of the network adapter. For example, I have renamed a network adapter from “Local Area Connection” to “Trunk #1”. In this case the VMHostAdapterName in the CSV-file should be “Trunk #1” for the Virtual Networks which is mapped to this physical NIC. This network adapter is configured in trunk mode, which means it is assigned multiple VLANs and thus may contain multiple Virtual Networks.

This way of performing the mapping between a physical NIC and a Virtual Network is a design decision I took when creating the script, although you may choose to do the mapping based on other properties, such as the IP-address range of the NIC. Since the environment I was working with had a consistent naming convention for the virtualization host network adapters I found this to be the most appropriate way of doing the mapping.

Before the walkthrough, I will first show you the customized version of the script the VMM Console generated:

$vmhosts = Get-SCVMHost
$networks = Import-Csv -Path C:\Import\VMM_logical_networks.csv

foreach ($vmhost in $vmhosts) {

# Create a Job Group ID
$JobGroupID = [Guid]::NewGuid().ToString()

foreach ($network in $networks) {

$vmHostNetworkAdapter = Get-SCVMHostNetworkAdapter -VMHost $vmhost | Where-Object {($_.LogicalNetworks | Select-Object -ExpandProperty Name) -contains $network.VMHostAdapterName}

if ($vmHostNetworkAdapter) {

$logicalNetwork = Get-SCLogicalNetwork -Name $

Set-SCVMHostNetworkAdapter -VMHostNetworkAdapter $vmHostNetworkAdapter -AddOrSetLogicalNetwork $logicalNetwork -JobGroup $JobGroupID

Set-SCVMHost -VMHost $vmhost -JobGroup $JobGroupID -RunAsynchronously


A brief overview of the changes:

  • On the first line we retrieve the virtualization hosts we want to iterate over. You may choose to limit the scope to a specific host group by using the –VMHostGroup parameter.
  • On the second line we import the contents of the CSV-file like we did in the previous script
  • On line 4 to 24 we create a foreach loop to iterate over all the virtualization hosts we initiated in the $vmhosts variable
  • The next thing we do is creating a job group (a GUID), which will make VMM perform all the following changes in a single job. This means that a single job will be run for each virtualization host when adding 100 Virtual Networks, instead of 100 jobs for each virtualization host. The concept of using Job Groups is described in this article in the VMM 2012 documentation on Microsoft TechNet.
  • On line 9-19 we iterate over all of the virtual networks in the CSV-file, and try to find a network adapter with a name equal to the VMHostAdapterName property of the Virtual Network defiend in the CSV-file.
  • Next, an if statement is used to determine if a network adapter was found. If the statement is evaluated to $true the actual change is being committed to the network adapter (this is the same as ticking the checkbox in the dialog box in the screenshot above).
  • When the inner foreach loop is finished the job will be commited by the command on line 21.
  • The same steps will be repeated until the outer foreach loop is finished.

The last recommendation I want to provide is to copy the script generated by the “View Script” button to a PowerShell editor like the Windows PowerShell ISE:


As you can see the script in the above screenshot is much easier to read than the following due to features such as syntax coloring and brace matching:




Overview of Scripting in VMM

Getting Started with Virtual Machine Manager

System Center: Virtual Machine Manager Engineering Team Blog


April 17, 2012 Posted by | Scripting, System Center Virtual Machine Manager, Virtualization, Windows PowerShell | | 4 Comments