How to create and use VMs TAGs in VMware vCenter - TAGs Part 1

Luciano PatrãoICT Senior Infraestructure  Engineer  
CERTIFIED EXPERT
vExpert vSAN, NSX, Cloud Provider, Veeam Vanguard, Virtual Backups, and Storage design, and an active blogger.
Published:
Will try to explain how to use the VMware feature TAGs in the VMs and create Veeam Backup Jobs using TAGs. Since this article is too long, I will create second article for the Veeam tasks.
In this article we will focus how to create and use TAGs (and category TAGs), in a second article will explain how to use the same TAGs in Veeam and create Veeam Backup Jobs using TAGs.
 
What are VM TAGs?
 
TAGs in VMware have existed since version 5.1, but is a feature not highly advertised (in my opinion) and only some VMware customers used it.
 
Tags are the ability to create custom labels and/or metdata and apply to any object with the vCenter inventory.  TAGs purpose is to identify object adding metadata to object.
 
We use this for better management of our Virtual Infrastructure. With TAGs we can group VMs (as an example) by category (like Guest OS, Clusters, multiple vCenter). We can Backup VMs by Guest OS and easily identify the Guest OS in the VMs by script.
 
We can use also the Search in vSphere Web Client to search for objects by TAGs.
 
We can also use to identify a VM by application (like DNS, SQL, Exchange or other type of Application). For environments with thousand of VMs, TAGing is a very easy way to manage and organize our VMs(or other objects).
 
If you're managing a Hosting Datacenter for several costumers, TAGing VMs or Clusters by Costumers will also be easy to manage your Virtual Environment.
 
We can manage, search, or group VMs using TAGing regardless where they are located (like folder, Pool, host or even vCenter when using multiple vCenters)
 
VMware Notes: "With vSphere 6.0, vSphere tags are no longer stored in the Inventory Service database table as the source of truth. They are relocated to the vCenter Server's database (VCDB) table CIS_KV_Keystore and the VMware Directory Services (Lotus) Service Provider tagging. After the tag association is created, this information is then pulled into the Inventory Service database for display within the vSphere Web Client."

Some extra information about TAGs: KB:2130130
 
TAGs are set by Category and then by TAG with a Category.
 
We can TAG at the following object level:
 
  • Cluster
  • Datacenter
  • Datastore
  • Datastore Cluster
  • Distributed Port Group
  • Distributed Switch
  • Folder
  • Host
  • Network
  • Resource Pool
  • vApp
  • vCO Scheduled Workflow
  • vCO Workflow
  • Virtual Machine
 
What we will use in our article?
 
In our case we only TAG VMs and create a Category for the Guest System Operation (OS).
 
There will be a TAG Category call ‘Guest OS’
 
Name               Cardinality        Description
----                     -----------               -----------
Guest OS        Single                   VMs System Operation TAG
 
Inside of this Category we will have the type of TAGs OS.

These are the type of TAGs that VMs will have depending of the Guest System Operation
 
Name                Category             Description
----                      --------                   -----------
Linux                Guest OS             Linux Virtual Machine
Windows          Guest OS             Windows Virtual Machine
Other OS          Guest OS             Other OS Virtual Machine
 
Note: TAGs can only be added, or checked using vSphere Web Client. vSphere Client Tool will not provide TAGs information.
 
How to create TAGs?
 
TAGs can only be created using vSphere Web Client. In this article we will focus how to create TAGs using PowerCli scripts and also in the vSphere Web Client tasks.
 
Note: In this example we will only use TAGing for VMs. Like we stated above, we can TAG most of the objects in the vCenter.
 
How to create TAGS using vSphere Web Client
 
Create TAG Category:
 
TAGCategoryAs we can see in the image above, when connecting to vSphere Web Client in the left menu we have the TAG option.
 
Then we choose TAG Category (you cannot create a TAG without first create a TAG Category).
 
Options:
 
Category Name: The category name must be unique to the currently-selected vCenter Server system.
Description: You can provide text in the description to describe the purpose or usage of the category.
Cardinality:
 
>Select 1 tag per object to allow only one tag from this category to be applied to an object at any one time.
 
Use this option for categories whose tags are mutually exclusive. For example, a category called Priority with tags High, Medium, and Low should allow one tag per object, because an object should have only one priority.
 
>Select Many tags per object to allow multiple tags from the category to be applied to an object at any one time.
 
Use this option for categories whose tags are not mutually exclusive.
 
After you have set the cardinality of a category, you can change the cardinality from 1 tag per object to Many tags per object, but not from Many tags per object to 1 tag per object.
 
Associable Object Types:
 
Select whether tags in this category can be assigned to all objects or only to a specific type of managed object, such as virtual machines or datastores.
 
After you have set the associable object types for a category, you can change a category that is associable with a single object type to be associable with all object types, but you cannot restrict a category that is associable to all object types to being associable to a single object type.
 
Note: In our example we have associated the TAG Category to Virtual Machines
 
After create the TAG Category we then can create TAGs linked to the TAG Category created above.
 
Create TAGs:
 
TAGs
Options:
 
TAG Name: Choose the name for your TAG. TAG name need to be unique inside of the same TAG Category.
TAG Category: Choose a TAG Category (created in the previous task) from the TAG Category list.
Description: You can provide text in the description to describe the purpose or usage of this TAGs.
 
Assign/Add TAG in VMs:
 
TAGs00
In the vSphere Client just go to the Virtual Machines section and click in the VM that you want to add the TAG.
 
As we can see above, in the VM summary will show a TAG area. Then just click Assign (1)
 
If we just click Mouse right click in the list of our VMs, we have also the VM menu and there is the option to assign a TAG to the VM.
 
Screen Shot 06-10-16 at 12.34 AM
Directly in the VM Summary, or VM menu options, will open the next Window to choose the VM TAG to assign.
 
TAGs02 
Then we just need to choose one of the VMs TAGs that exists. In this case is a Windows VM, so we will choose the Windows TAG and click Assign.
 
TAGs01 
After we can see the TAG already been assigned to this VM.
 
After all these tasks we have created TAG Category, TAGs and assign TAGs to our VMs using vSphere Web Client.
 
How to create TAGS using PowerCli scripts?
 
In the next section we will create the same TAG Category, same TAGs and also assign TAGs to all our VMs by checking automatically the type of Guest OS that VM is running.
 
Note: Since not all VMs can have VMware tools installed, checking Guest OS without VMware Tool cannot be 100% accurate. In that case we will check the Guest OS that user choose when created the VM.
 
Lets explain a little bit our script and how to use PowerCli commands to create TAGs.

Create TAG Category:
 
New-TAGCategory –Name $TAGCategoryName -Description "VMs System Operation TAG" –Cardinality single –EntityType VirtualMachine

Open in new window


This line creates the ‘Guest OS’ Category adding the description and choosing Cardinality single (since we will only use for VMs).

The script will always check if there is already a TAG ‘Guest OS’, if yes will skip this section. We are using this for our example, but you can change the script and put whatever TAG Category you need in your environment.
Create TAGs:
 
Get-TAGCategory -Name $TAGCategoryName | New-TAG -Name $TAGName -Description "$TAGName Virtual Machine"

Open in new window



This line creates the TAGs using the TAG Category created in the previous section.
Previously he have already set the TAGs names that we need for our environment
 

$TAGNames = @("Windows", "Linux", "Other OS")

Open in new window


Again the script will always check if there is already this TAGs already exists, if yes will skip this section. Again this is just for our example, you can change the script and put whatever TAG you need in your environment. Just change the $TAGNames array for whatever you need in your environment.
 

Assign/Add TAG in VMs:
 

Then the script will check all VMs in the vCenter to see if the VMs Guest OS, after knowing the Guest OS will check if there is a TAG assigned already to the right OS, if not will assign a Guest OS TAG to the VM according to Guest OS used. 

$Result=New-TAGAssignment -TAG $TAGName -Entity $vm

Open in new window


Note: We use also the option by Cluster that you can use, or comment to run in all Clusters in the vCenter.
 

The script will create a HTML report of all changes made (new TAG Category created, new TAGs created and all VMs that were assign to right TAG). Will also send by email (you need to change the script in the email settings, according to you email server)
 

This is the full script:
 

#########################################################################################
                      # Created by: Luciano Patrão and Vladimir Sokol                                         #
                      # Date: 7th of Jun 2016                                                                 #
                      # Set VMs TAGs by Guest OS                                                              #
                      # Version 7.0                                                                           #
                      #########################################################################################
                      
                      ### vCenter Server IP
                      $vCenter = 'Add your vCenter IP'
                      Connect-VIServer $vCenter
                      
                      ### vCenter Server Name(FQNP)
                      $vCentName = [system.net.dns]::GetHostByAddress($vCenter).hostname
                      
                      ### TAG Category
                      $TAGCategoryName="Guest OS"
                      
                      ### VM Guest Operation System TAGs
                      $TAGNames = @("Windows", "Linux", "Other OS")
                      
                      ### Counters for counting Guest OS TAGs
                      $Counters =  New-Object "int32[,]" $TAGNames.Count,2
                      
                      ### Cluster Name
                      $Cluster = "add your Cluster name" ## If you don't want to run by Cluster, please comment this line
                      
                      ### Mail Data
                      $MailFrom = "vCenter Report  <add your sender email address>"
                      $MailTo = "Sender Name <add your destination email address>"
                      $SMTPServer = "add your email smtp server"
                      $MailSubject = "Guest Os TAG Report "+$vCentName
                      
                      ### Function for highlight table row when mouse pointer is over it
                      function Set-AlternatingRows {
                          [CmdletBinding()]
                          Param(
                              [Parameter(Mandatory=$True,ValueFromPipeline=$True)]
                              [object[]]$HTMLDocument,
                              [Parameter(Mandatory=$True)]
                              [string]$CSSEvenClass,
                              [Parameter(Mandatory=$True)]
                              [string]$CSSOddClass
                              )
                          Begin {
                              $ClassName = $CSSEvenClass
                              }
                          Process {
                          [string]$Line = $HTMLDocument
                          $Line = $Line.Replace("<tr>","<tr class=""$ClassName"">")
                          if ($ClassName -eq $CSSEvenClass) {
                              $ClassName = $CSSOddClass
                              }
                          else {
                              $ClassName = $CSSEvenClass
                              }
                          $Line = $Line.Replace("<table>","<table width=""50%"">")
                          Return $Line
                          }
                      }
                      
                      cls
                      write-host "===============================================================================" -foreground Red
                      write-host "This script is provided as-is, no warranty is provided or implied. The author"
                      write-host "is NOT responsible for any damages or data loss that may occur through the use"
                      write-host "of this script. This script is free to use for both personal and business use,"
                      write-host "however, it may not be sold or included as part of a package that is for sale."
                      write-host "===============================================================================" -ForegroundColor Black
                      
                      # Create header of HTML report
                      $Header = @"
                      <style>
                      TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse; font-family: arial, verdana, sans-serif}
                      TR:Hover TD {Background-Color: #C1D5F8;}
                      TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
                      TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
                      .odd  { background-color:#ffffff; }
                      .even { background-color:#dddddd; }
                      H1,H2,H3,H4,H5,H6 {font-family: arial, verdana, sans-serif}
                      </style>
                      <title>
                      License Report
                      </title>
                      "@
                      
                      ##################################################################################################################
                      #############################################  TAG Categories   ##################################################
                      ##################################################################################################################
                      
                      #### First we will check if the category already exists, if not we will create a TAG Catergory for our Guest OS VMs
                      
                      
                      If ( (Get-TAGCategory -Name $TAGCategoryName -ErrorAction SilentlyContinue) -eq $null )
                      {
                          Write-Host "No $TAGCategoryName category founded, script will create one." -foreground Red 
                          $ToHTML="<H4>No $TAGCategoryName category founded, script will create one.</H4>"
                          $Result=New-TAGCategory –Name $TAGCategoryName -Description "VMs System Operation TAG" –Cardinality single –EntityType VirtualMachine
                      }
                      else {
                          Write-Host "### $TAGCategoryName TAG Category founded, no changes needed. ### "
                          $ToHTML="<H4>$TAGCategoryName TAG Category founded, no changes needed.</H4>"
                      }
                      
                      ### Check if TAGs exist in TAG Category ###
                      
                      $TAGs=@(Get-TAG -Category $TAGCategoryName)
                      $TAGCategory = @()
                      foreach ($TAGName in $TAGNames)
                      {
                          $Details = "" | select "TAG Category Name", "TAG Name", "TAG Newly Created"
                          $Details."TAG Category Name"=$TAGCategoryName
                          $Details."TAG Name"=$TAGName
                          $Details."TAG Newly Created"="NO"
                          $TAGCategory+=$Details
                          if (!($TAGName -in $TAGs.Name))
                          {
                              $Details."TAG Newly Created"="YES"
                              Write-Output "TAG $TAGName doesn't exist in category $TAGCategoryName, script will create it now" 
                              $Result = Get-TAGCategory -Name $TAGCategoryName | New-TAG -Name $TAGName -Description "$TAGName Virtual Machine"      
                          }
                      }
                      
                      
                      ##################################################################################################################
                      #############################################  VMs Guest TAGs    #################################################
                      ##################################################################################################################
                      
                      #### Set by Cluster
                      $vms = Get-Cluster $Cluster | Get-VM
                      #### Set by vCenter
                      #$vms = Get-VM # If you want to use by vCenter Uncomment this line and comment the above line
                      
                      $counter = 0
                      
                      #### Set for all VMs in the vCenter
                      $NewlyTAGgedVms= @()
                      foreach ($vm in $vms)
                      {
                          $Result=Get-TAGAssignment -Category $TAGCategoryName -Entity $vm
                          if ($Result)
                          {
                      #        Write-Host $vm "TAGged" $Result.TAG.name
                              $Counters[ [array]::indexof($TAGNames,$Result.TAG.Name),0]++    
                          }
                          else
                          # Virtual machine doesn't have TAG, so let it add one
                          {
                              $OSName= ($vm | Get-VIew).summary.config.GuestFullName
                              $Details = "" | Select "VM Name", "OS", "TAG Name"
                              $Details."VM Name" = $vm.Name
                              $Details.OS = $OSName
                              $TAGged=$false
                              # loop through all TAGs for virtual machines
                              foreach ($TAGName in $TAGNames)
                              {
                                  if ($OSName -match $TAGname)
                                  # part of guest OS name is in name of TAG for virtual machines
                                  {
                                      Write-Host  $vm "no TAG founded, add TAG to VM" $TAGName
                                      $Result=New-TAGAssignment -TAG $TAGName -Entity $vm
                                      $TAGged=$true
                                      $Counters[ [array]::indexof($TAGNames,$TAGName),1]++
                                      $Details."TAG Name" = $TAGName
                                  }
                              }
                              if (!$TAGged)
                              # Guest OS name doesn't have any match with name of TAG for virtual machines
                              {
                                  Write-Host  -NoNewline $vm "no TAG founded, add TAG to VM "
                                  if ($OSName -match "CentOS")
                                  {
                                      # exception: CentOS is Linux that has no word "Linux"in its name
                                      Write-Host "Linux"
                                      $Result=New-TAGAssignment -TAG "Linux" -Entity $vm
                                      $Counters[ [array]::indexof($TAGNames,"Linux"),1]++
                                      $Details."TAG Name" = "Linux"
                                  }
                                  else
                                  {
                                      Write-Host $TAGnames[$TAGNames.Count -1]
                                      # set TAG name to the last name in array of TAG names
                                      $Result=New-TAGAssignment -TAG $TAGNames[$TAGNames.Count -1] -Entity $vm
                                      $Counters[($TAGNames.Count-1),1]++
                                      $Details."TAG Name" = $TAGNames[$TAGNames.Count -1]
                                  }
                              }
                              $NewlyTAGgedVms+=$Details
                          }
                          $counter++
                          Write-Progress -Activity 'Processing VMs' -CurrentOperation $VM -PercentComplete (($counter / $VMs.count) * 100)
                          Start-Sleep -Milliseconds 200
                      }
                      
                      #### Number of VMs calculation ####
                      
                      $Summary=@()
                      $TotalVMsAlready=0
                      $TotalVMSNewly=0
                      for    ($i=0; $i -lt $TAGNames.Count; $i++)
                      {
                          $Details = "" | Select OS, "Already TAGged", "Newly TAGged"
                          $Details.OS=$TAGNames[$i]
                          $Details."Already TAGged"=$Counters[$i,0]
                          $Details."Newly TAGged"=$Counters[$i,1]
                          $TotalVMsAlready+=$Details."Already TAGged"
                          $TotalVMSNewly+=$Details."Newly TAGged"
                          $Summary+=$Details
                      }
                      
                      Write-Host "`n### SUMMARY ###" 
                      $totalVMs=($Counters|Measure-Object -Sum).sum
                      Write-Host "Founded $totalVMs VMs total"
                      $Summary | Format-Table -AutoSize
                       
                      ##################################################################################################################
                      #############################################   Generate HTML    #################################################
                      ##################################################################################################################
                      
                      $TAGCategory = $TAGCategory | ConvertTo-Html -PreContent "<H4>$TAGCategoryName TAG Category and its TAG Names:</H4>" -Fragment
                      if ($NewlyTAGgedVms)
                          {
                              $NewlyTAGgedVms = $NewlyTAGgedVms | ConvertTo-Html -PreContent "<H4>Report for Newly assigned TAGs to VMs:</H4>" -Fragment
                          }
                      else
                          {
                          $NewlyTAGgedVms = "<H4>There is no newly TAGged VMs.</H4>"
                          }
                      $Summary = $Summary | ConvertTo-HTML -PreContent "<H4>Summary Report for $TAGCategoryName TAG Category:</H4>" -PostContent "<H4>Total number of VMs: $totalVMs ($TotalVMsAlready already TAGged, $TotalVMsNewly  newly TAGged).</H4>" -Fragment
                      
                      $Report = ConvertTo-Html -Head $Header -Body "$ToHTML $TAGCategory $NewlyTAGgedVms $Summary" | Set-AlternatingRows -CSSEvenClass even -CSSOddClass odd
                      
                      ##################################################################################################################
                      ##########################################   Save report to disk  ################################################
                      ##################################################################################################################
                      
                      $ThisDate = Get-Date -format yyyy_MM_dd-HH_mm_ss
                      $Path=$PSScriptRoot
                      $GuestOSTAGFile = "$Path\GuestOSTAGs_Report_$vCentName-$ThisDate.html"
                      $Report | Out-File $GuestOSTAGFile
                      
                      ##################################################################################################################
                      ###########################################  Send report by mail  ################################################
                      ##################################################################################################################
                      
                      Write-Host -NoNewline "Sending HTML report by mail to $MailTo ... "
                      $MailSplat = @{
                          To          = $MailTo
                          From        = $MailFrom
                          Subject     = $MailSubject
                          Body        = ($Report | Out-String)
                          BodyAsHTML  = $true
                          Attachments = $GuestOSTAGFile
                          SMTPServer  = $SMTPServer
                      }
                      Send-MailMessage @MailSplat
                      Write-Host -ForegroundColor Green "done"
                      Write-Host "`nGuest OS TAG report in HTML is saved as $GuestOSTAGFile" 
                      
                      Disconnect-VIServer -Server $vCenter -Force -Confirm:$false

Open in new window


With the script we finish this first part of this TAGs article in VMware and Veeam Backup.
 

In our second part we will focus using the same VMs TAGs in Veeam and create Backup Jobs by VM TAG.
 

Final Note: I will like to thank to my colleague Vladimir Sokol for is great help improving the script. Thank you for all your support on this.
 

Important Note: This script and article is provided as-is, no warranty is provided or implied. The author is NOT responsible for any damages or data loss that may occur through the use these tasks or scripts included here in this article.

This is the part of my "TIP Articles". So, please vote "Helpful" on this Article. And I encourage your comments and feedback.
0
1,811 Views
Luciano PatrãoICT Senior Infraestructure  Engineer  
CERTIFIED EXPERT
vExpert vSAN, NSX, Cloud Provider, Veeam Vanguard, Virtual Backups, and Storage design, and an active blogger.

Comments (0)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.