[PowerCLI] Assigning Tags based on VM Notes

Back to Blog

[PowerCLI] Assigning Tags based on VM Notes

This week’s challenge was introduced to me at a customer engagement. I helped the customer to migrate from vSphere 6.5 to the latest vSphere 6.7 Update 1 build. The customer was at first very impressed with the (finally) completed HTML5 client.

The problem with the new HTML5 client: finding VMs is hard

As the customer started working with the new HTML5 client he quickly found out that the search in the HTML5 client is not as good as the search in the flex client. He was not able to find his VMs based on the information he had added to each VM in the “Notes” property. I immediately thought: PowerCLI can surely help out here.I told him that the fastest way to find information on VMs is to work with Tags. I also told him about all the newer products that use tags like the automated response in NSX in conjunction with 3rd party antivirus solutions. He was quickly onboard with using tags. I think the “It’s just like a post-it” got through to him.

Searching custom attributes is useless

The starting ground was pretty easy. The customer not only used notes but had also defined a couple of custom attributes. Those were still searchable in the new client but you had to click way too much and be much too specific in the search mask to achieve this:

Screenshot 2019-02-21 at 08.22.53

One has to specify exactly which attribute and what values it should have in order for vCenter to find anything. To me that is total nonsense and therefore useless. The customer agreed. So we decided to migrate all the custom attributes to tags as well. As this was a one-time procedure I created the following logic for the customer:

#just to be thourough here is the code to actually create the Tag-Category
New-TagCategory -Name "Install Date" -Cardinality "Single" -EntityType "VirtualMachine" -Confirm:$false
foreach ($currentVm in get-vm) {
    #here we extract the value from our custom attribute
    $installDate = $currentVm.CustomFields | Where-Object {$_.Key -match "Install"} | Select-Object -ExpandProperty Value
    if ($installDate -eq "")
        #if the VM did not have the custom value defined we go ahead and give a value
        $installDate = "01.01.1900"
        #and we add the custome attribute as well
        $currentVm | Set-Annotation -CustomAttribute "Install Date" -Value $installDate -WhatIf
        #if the tag is not found we execute the "catch"
        get-tag -Name $installDate -ErrorAction Stop
        #create the tag if it does not exist
        New-Tag -Name $installDate -Category "Install Date" -WhatIf -Confirm:$false
        #at this point we know the tag exists so we assign it to the current VM from the loop
        New-TagAssignment -Tag (Get-Tag -Name $installDate) -Entity $currentVm -WhatIf


I changed the static parts and ran this little script for each of the customer’s custom attributes. Afterwards the customer decided to remove the custom attributes all-together and use the tags from now on.

Getting information from notes to tags

The next challenge was the notes property of the VMs. The customer wrote all kinds of information in that field and used this information to quickly find VMs in the day to day operations. How can we enable the customer to find his VMs again? It’s pretty easy we create a new tag category for “Notes” and loop through all the VMs and convert their notes to a tag which we then assign to that VM. The logic is basically the same as in the above example.

However, the customer raised a good point during the discussion:

I love using the notes property of the VMs because that is actually written to the VMX file and therefore also recovered when I have to restore a VM from backups.

This actually got me thinking, is there a backup vendor that can handle tag-assignment and re-assign those tags after a complete VM restore? I do not think so but did not look too much into this.

Update 1:
After publishing this blog a couple of colleagues from the VMware vExpert community reached out to me regarding this. It seems that Veeam is able to restore tags when a VM is restored. Good to know.
I hope more backup vendors will support restoring tags (and maybe custom attributes) in the future.

After discussing this we decided that the customer keeps using the VM notes property for his operational tasks and I will write a script for him that will automatically take the notes value and create a tag from it. A key thing the customer took away from that is that it makes sense to standardize the format of his VM notes. I told him that whenever he has done this and wants to remove all tags with the old VM notes syntax he should just remove the tag category (which will remove all tags as well). The next time the script runs all tags are created again.

The resulting script is too large to put into this post, but as always I have put it on my GitHub account here.

The script will write a logfile where you can track which VM has gotten assigned which tag. We have decided on a 4-hour schedule to run the script. Each 4 hours all the information from the notes are taken and used as tags and the information is instantly searchable in the HTML5 client.

Feel free to use the script and please give me any feedback. On thing that could probably improve the script tremendously is to handle multi-line notes and split them into different tags, but that is a challenge for another day.

The script has a requirement for the PSLogging Module from the Powershellgallery.

Share this post

Comments (2)

  • Scott Cooney Reply

    Looks great, would it be simple to apply this script only to an individual folder/s within vCenter rather than everything?

    03.26.2020 at 12:54
    • virtualFrog Reply

      Hi Scott,
      I’m glad it is helpful to you. Yes, of course you can apply this to only folders. The scope of VMs is defined at the start in the brackets of the foreach loop. My script simply does a “get-vm” which returns all VMs. You can of course make a filtered selection where you get for example a folder and then get the VM objects from only that folder (get-folder -Name “Foldername” | get-vm).

      04.01.2020 at 13:22

Leave a Reply

Your email address will not be published.

Back to Blog