Tag Archives: powercli

Fun With Tags and PowerCLI

Tags were added to vSphere back in version 5.1 so they’re not a new feature but are still often overlooked. One or more tags can be applied to items (entities) in the inventory and then used as a search term or metadata not only in the GUI but also through tools such as PowerCLI. This post covers a few useful cmdlets for working with tags.


There are a number of cmdlets which deal with tags, here’s a quick list using Get-Command.


Notice that there’s three Nouns used here- “Tag” represents the tag itself. “TagAssignment” represents a relationship between a tag and another object (for example “This VM has been assigned This (or These) tags). Finally there’s “TagCategory” which represents the category that a tag belongs to.

Getting Tags

So, what can we do with tags in PowerCLI? Well, first we can look at a list of all the tags using Get-Tag. This returns a lot of information, particularly if you have assigned tags already, so we can neaten the quick view using the PowerShell “Select” function to show just the tag name and description:

Get-Tag | Select Name, Description

Name                 Description
– –                 – – – – – –
UrlShortener         URL Shortener Service
Documents            Document Management Service
Change               Change Management Service

In this example, I’ve created three tags to represent three different services operating in my environment. We can carry on from here and find out which entities have been assigned the “Documents” tag- i.e. what VMs form the Document Management Service.

(Get-TagAssignment |
  Where {$_.Tag.Name -eq 'Documents'}).Entity

Name                 PowerState Num CPUs MemoryGB
– –                  – – – – – – – – – – – – –
DocuWebServ          PoweredOn  1        4.000

DocuDBServ           PoweredOn  2        16.000
DocuFileServ         PoweredOn  1        4.000

Or we could flip that and ask the question- “What tags does this VM have assigned?”

Get-VM "DocuWebServ" |
     Get-TagAssignment | Select Tag

– –


Getting Bigger

As we’re using PowerCLI we can join more and more functions together and make bigger and bigger queries. For example, we can  list all VMs with their tags in a table.

Get-VM |
      Select Name,@{Name="Tags";Expression={(Get-TagAssignment -Entity $_).Tag.Name}} |
      Where {$_.Tags} |
      Format-Table - Autosize

Name         Tags
– –          – –
DocuWebServ  {Documents, WebServers}
DocuDBServ   Documents
DocuFileServ Documents
URLShort1    {UrlShortener, WebServers}
URLShort2  {UrlShortener, WebServers, TestAndDev}

This is only scratching the surface of the possibilities- by having useful metadata that lives with the VM and can be accessed programmatically we have plenty of avenues to explore in automation and reporting.


I was lucky enough to take delivery of some new ESXi hosts recently. After installing them in the datacentre, I wanted to test that the network had been patched correctly. This environment is going to have Distributed vSwitches configured, but I wanted to test the physical connectivity before joining them to vCenter- have the physical NICs been patched to the correct networks?

PowerCLI to the rescue! I put together some code which automates this process. Provided with a hostname and a list of NICs and targets which should respond, the code fires off a ping for each interface in turn and reports back with success/fail messages.

For each NIC it creates a temporary switch, portgroup, and VMkernel interface:

#Create Virtual Switches
$Switch1=New-VirtualSwitch -Name "sw_Connectivity_Test" -Nic $Nic
#Create PortGroups
$Portgroup1=New-VirtualPortGroup -Name "pg_Connectivity_Test" -VirtualSwitch $Switch1
#Create VMK Adapter
$vmk1=New-VMHostNetworkAdapter -PortGroup $Portgroup1 -VirtualSwitch $Switch1 -IP $HostIP -SubnetMask $SubnetMask

Then the esxcli functionality is used to ping a given target address:

#Test the connection
$esxcli= get-esxcli -V2                              #Use the ESXCLI to run the ping from the host
$arguments = $esxcli.network.diag.ping.CreateArgs()
$arguments.host=$TargetIP                            #Set IP Address to Ping
$arguments.count="2"                                 #How Many Times to Ping
$arguments.interface=$vmk1                           #Use the configured VMKernel Interface

Once the test is complete, the temporary virtual network components are removed.

#Tidy up- delete all the Networking Components created
Remove-VMHostNetworkAdapter $vmk1 -Confirm:$false
Remove-VirtualPortGroup $PortGroup1 -Confirm:$false
Remove-VirtualSwitch $Switch1 -Confirm:$false

The full code is available for download (and potential improvement) on GitHub.



Finding Deprecated VMFS Volumes

Following an upgrade to vSphere 6, hosts popped up an error message reporting that some old VMFS volumes were found on the host. Whilst these still worked, it would be prudent to tidy them up and replace them with modern datastores. The message is:

“Deprecated VMFS volume(s) found on the host. Please consider upgrading volume(s) to the latest version”


Whilst this highlights that there is an issue, the GUI message doesn’t indicate which volumes (or how many) are affected. The following quick bit of PowerCLI produces a table of the datastores with a VMFS version of less than 5.

Get-Datastore |
 Where-Object { $_.ExtensionData.Info.VMFS.MajorVersion -lt 5} |
 Select-Object Name, FreeSpaceGB, CapacityGB, @{n='VMFS Version';e={$_.ExtensionData.Info.VMFS.MajorVersion}}

Example Output:

Name           FreeSpaceGB CapacityGB VMFS Version
----           ----------- ---------- ------------
VOL-VM01            574.77    2047.75            3
VOL-VM02           1924.05    2047.75            3
The Home Lab

Automated Deployment in the HomeLab- Part 1

I’m commencing a project with my HomeLab- I’m going to build a system whereby I can produce custom mini-lab environments by means of a script. There are off the shelf solutions to do this (see AutoLab as an example) but if I build this myself I get something tailored exactly to my needs (and available resources) and hopefully learn something along the way- which is what the HomeLab is all about really. This is the first post in what should develop into a series showing how I work through the process to create my automation system.


The Aims

a.k.a. what I want to achieve

  • ExampleMiniLabThe ability to run a script to deploy a predefined lab environment. For example running “Build-Project-Lab-One.ps1” makes 3 Windows Server VMs, connected on a private switch, with one running AD/DNS/DHCP roles, one acting as a Gateway, and one ready for whatever experiment I throw at it
  • The ability to quickly and easily modify a copy of that script to produce a lab with a different configuration. Then I can have a script that builds me a WDS platform, or another one that produces a SCOM test environment. I can use this library to quickly rebuild, or build a copy of, and of my environments within the HomeLab
  • This script should also create a second script for decommissioning  /destroying the lab environment when I’ve finished.
  • Whilst perhaps not meeting full “production” standards, the scripts should be at least in a state whereby I can post them online and not have to hide in a cave for the next decade whilst they get laughed at.


The Resources

a.k.a. what I have to play with

  • One Intel NUC host running vSphere ESXi 6 providing some compute, memory, storageIntel NUC
  • One VMUG Advantage Subscription complete with VMware EVAL Experience licensing- this provides VMware vCenter amongst other things.
  • One Microsoft DreamSpark Subscription and Microsoft Evaluation Licensing (see “Microsoft Licensing” on the Open Homelab Project for details on how to get these)
  • Me with my knowledge of Windows, vSphere, PowerShell, PowerCLI, and how to Google for stuff.
  • The community who not only kindly put content up on the internet for me to Google for but also are there for me to tweet, slack, and (shock, horror) talk to when I encounter problems or lose direction.


The Plan

a.k.a. How I’m hoping to achieve those aims with those resources.

To do all this I’m starting out by preparing a vSphere template of Windows Server 2012R2. I can deploy this- with customisations- using PowerCLI to form the building blocks of the lab environment. Once I have Windows VMs deployed I need to be able to configure them- this is where PowerShell remoting will come in handy- I can deploy roles and features and do some basic configuration. I’ll put together a PowerShell function to do all that. This function can then be re-used in the script to deploy multiple VMs with different configurations. For example:

CreateVM "Server1" $TemplateName $CustomizationSpec "Web-Server"
CreateVM "Server2" $TemplateName $CustomizationSpec "WDS"

I’ll use PowerCLI to deploy a private network within the Hypervisor and connect the VMs to it. This method will also be used to configure the connections to the gateway -one NIC pointing at the private switch and one at the internet-facing vSwitch already in place.

Some more in-depth PowerShell (possibly also arranged into reusable functions) to do the in-depth configuration of the roles. For example, when the script completes I want the Active Directory to be up and running, the Gateway providing an internet connection to the VMs, the VMs getting IP addresses from the lab DHCP and domain-joined. Basically I want to be able to run the script, make a brew, and come back and find a fully configured system ready to go.


Coming Soon- Part 2, full of scripting goodness.