VMware vRealize Automation 8.4 – PowerShell Action Scripts: Custom Hostname

This post is a first in a series in which I am sharing my experiences using PowerShell actions to customize virtual machine deployments using VMware vRealize Automation 8.4. vRA gives you the choice to create scripts based on the following programming languages: Node.js, Python and PowerShell. I chose PowerShell because it is not (yet) commonly used in vRA and therefore deserves some attention. This post covers the script responsible for generating a custom hostname for a virtual machine.

What are actions in vRA 8.x?

I will not go over the entire explanation of extensibility actions in vRA but to summarize:

Extensibility actions are small, lightweight scripts of code used to specify an action and how that action is to perform. You can import extensibility actions from pre-defined vRealize Automation Cloud Assembly action templates or from a ZIP file. You can also use the action editor to create custom scripts for your extensibility actions.

In case you want to learn more about Action Based Extensibility (“ABX“), please read the official VMware documentation available here.

Why Custom Hostname?

Whenever you deploy a virtual machine in vRA 8, the hostname is automatically generated at runtime according to the following default format: “Cloud_Machine_1-mcmxxx-xxxxxxxxxxxx“. If you do specify a machine name (e.g. “VM_MCL_1“) on the design canvas in vRA Cloud Assembly then the resulting hostname will become “VM_MCL_1-mcmxxx-xxxxxxxxxxxx”. Both scenarios will likely not satisfy your customer’s needs as they are always using a specific naming convention for their virtual machines. In my customer case, the requirements was to have a hostname generated based on the following format: “‘S'{Operating System}{Tier}{Number}{Environment}” resulting in a name such as “SWA1467P“.

To solve this problem I chose the creation of a custom ABX based on PowerShell, which is detailed in the following paragraph.

PowerShell Action Script “Custom Hostname”

In the first version of my PowerShell action script (“Custom Hostname“), I used a simple approach by using design canvas custom properties and a randomly generated 4-digit number:

    • Operating System
      • Custom property “vmOS
    • Tier
      • Custom property “vmSW
    • Number
      • Random number between 1 and 1000
    • Environment
      • Custom property “vmEnv

 

function handler($context, $inputs) {

   # Original hostname generated during deployment
   $old_name = $inputs.resourceNames[0]

   # Custom properties from design canvas
   $vm_OS = $inputs.customProperties.vmOS
   $vm_SW = $inputs.customProperties.vmSW
   $vm_Env = $inputs.customProperties.vmEnv

   # Generate random number
   $rd_No = Get-Random -Maximum 1000

   # Format random number with maximum 4 characters and leading zeros
   $rdf_No = "{0:0000}" -f $rd_No

   # Concatenate new hostname based on custom properties and formatted random number
   $new_name = ("S" + $vm_OS + $vm_SW + $rdf_No + $vm_Env)

   # Copy entire $inputs object into new $outputs object
   $outputs = $inputs

   # Overwrite .resourceNames[0] property with new hostname
   $outputs.resourceNames[0] = $new_name

   # Create output entry visible in Action Runs logs
   Write-Output ("Setting machine name from " + $old_name + " to " + $new_name)

   # Return updated outputs object containing new hostname used for remainder of deployment process
   return $outputs

}

In the second and final version, I changed the random number to become an incremental number ranging from 1 to 1000. And importantly, I added a check with the vCenter Server environment ensuring that a particular hostname does not already exist. To make this work, I needed to add 3 additional inputs required for the vCenter Server API connectivity:

    • vCenter Server URL
      • Action input “vcURL” (string)
    • vCenter Server Username
      • Action input “vcUSR” (secret)
    • vCenter Server Password
      • Action input “vcPWD” (secret)

 

function handler($context, $inputs) {

   # Original hostname generated during deployment 
   $old_name = $inputs.resourceNames[0] 

   # Custom properties from design canvas 
   $vm_OS = $inputs.customProperties.vmOS 
   $vm_SW = $inputs.customProperties.vmSW 
   $vm_Env = $inputs.customProperties.vmEnv

   # Action inputs required for vCenter Server connectivity 
   $vc_URL = $inputs.vcURL
   $vc_USR = $context.getSecret($inputs.vcUSR)
   $vc_PWD = $context.getSecret($inputs.vcPWD)
   # Loop to create a new hostname based on an incremental number
   for ($i=1; $i -le 1000; $i++) {

      # Format $i with maximum 4 characters and leading zeros
      $vm_fint = "{0:0000}" -f $i

      # Concatenate new hostname based on custom properties and formatted incremental number
      $new_name = ("S" + $vm_OS + $vm_SW + $vm_fint + $vm_Env)

      # Connect to vCenter Server using URL and User credentials
      Connect-VIServer -Server $vc_URL -User $vc_USR -Password $vc_PWD -force

      # API lookup VM based on new hostname
      $vm_list = Get-VM -Name $new_name

      # Disconnect from vCenter Server
      Disconnect-VIServer -Server $vc_URL -Confirm:$false

      # If $vm_list is empty then new hostname is available for usage
      # Else do nothing and continue the loop with the next incremental number $i
      if ($vm_list -eq $null) {
         
         # Copy entire $inputs object into new $outputs object
         $outputs = $inputs
         
         # Overwrite .resourceNames[0] property with new hostname
         $outputs.resourceNames[0] = $new_name

         # Create output entry visible in Action Runs logs
         Write-Output ("Setting machine name from " + $old_name + " to " + $new_name)

         # Break the loop immediately to proceed with returning the $outputs
         break
      }
   }

   # Return updated outputs object containing new hostname used for remainder of deployment process
   return $outputs

}

 Action Subscription

To enable the new action and use it as part of my vRA project deployment, I created a new Action “Subscription” in the Extensibility section. In that new Subscription, it is important to:

    • Select “Compute allocation” for Event Topic
    • Set “event.data.blueprintId == <my-blueprint-id>” as Condition
    • Select the “Custom Hostname” action script as Runnable Item
    • Enable the setting to Block execution of events in this topic
    • Added my project in the Subscription scope

Final Thoughts

Of course, improvements can be made to my Custom Hostname PowerShell script for vRA 8.4. Obviously, the speed of deployment is likely to be impacted when more virtual machines are being deployed. This is due to the above script repeatedly checking for existing hostnames in vCenter Server using that for-loop.

I hope this post is useful to those who, like me, are working with PowerShell scripting in VMware vRealize Automation 8.4.

Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.