In my last blog post ( I wrote about using the Horizon Service Installer fling for adding Horizon services to NSX for Desktop. From that blog post I have been evolving the services file with services and rules that will normally appear in an EUC solution with VMware products. Not just sticking with Horizon 7, but also getting App Volumes, UEM, UAG, and infrastructure components in the picture. And I will be continuing to evolve the services.

Another part I am working on is using PowerShell/PowerNSX for adding the services file to the NSX environment, and in turn, replace the need of the fling. And this blog post is about explaining the current structure from reading the yml file and using this information to check and add to NSX. For now, the services yml file will be maintained to keep on working with the fling.

Why replacing the fling?

So why replace the fling is a question you might ask. One, the dependency of Java itches my skin. Secondly executable jar is no readable source. And thirdly I encountered some issues or whishes with the current version, such as: not overwriting changed configuration for some blocks and for other blocks adding at every run (ruleset for example), or complaining if the input from the yml is wrongly formatted. And fourthly current project wants a script compatible with PowerNSX.

Why PowerNSX?

Why use PowerNSX and not a language that can directly talk with the API’s, like project Clarity? Well as Clarity sounds really interesting, it will need a (for me) steeper learning curve as I know nothing about Clarity, and also in my experience, EUC/NSX consultants know and use PowerShell/PowerNSX a bit more. And UI/UX for this, meh is a maybe in this time and place. Imho using Powershell currently fits better to the field and with the current project. Maybe in a further up in time moment it will be changed.

Description of current status – Walk through Script

Script Stages

The script will go through the following stages:

  • Description, settings, function and module declarations (glad you are here)
  • Check and read yml (log and exit on error)
  • Parse yml (log and exit on error)
  • Get connection input to vCenter / NSX (log and exit on error)
  • Connect to vCenter / NSX (log and exit on error)
  • Check current set services, service groups, security groups and rules (log and exit on error)
  • Save diffs (log and report)
  • Process Changes (log and exit/rollback on error)
  • Set default rule to reject (log and exit/rollback on error)
  • Report (log and present report)
  • End script (goodbye)

Walk through

We will walk through the status of the script. The script currently is one big amount of text, if it grows too big I will move parts to separate files. At this time the script processes NSX services only. But from this structure, it will be somewhat repetitive to expand with other configuration items from the yml configuration file. If only I would have some more time.

Anyhow walk through, here goes. After the description mumbo-jumbo, the script starts with the settings. Currently, this is not that big so in the script itself:

# Settings
$ymlFile = “horizon7_Service.yml” # Input yml file
$logon = “Yes” # Do we want log Yes or No
$logFile = “NSXHorizonJumpstart.log” # Log File location
$overwrite = “Yes” # Overwrite existing values, Yes or No
# End of Settings

Important here is the input $ymfile as we check for the existence of this file a little later on.

if (!(Test-Path $ymlFile))

Whether we log or not with $logon, this is used throughout the script

If ($logon -eq “Yes”) { Write-Log “$ymlFile does not exist. Exiting script” }

Write-Log is a function currently declared within the script. It might go to a functions module.

The content of the yml file is read as raw data with Get-Content and piped to ConvertFrom-Yaml to further process within the script.

$fileBody = Get-Content $PSScriptRoot\$ymlFile -Raw -ErrorAction:SilentlyContinue | ConvertFrom-Yaml -ErrorAction:SilentlyContinue


ConvertFrom-Yaml put this in the format to be used: $fileBody.section.entry. If we take a snippet from the yml file this means:

HorizonViewServices :
– name : HorizonView-Agent_TCP
protocol : TCP
dest_ports : 4172,3389,9427,32111,22443,4001,4002
source : any
description : PCoIP,RDP,CDR/MMR,USB redirection,Blast Extreme,JMS

If we want to look for the names of the HorizonViewServices we build this as $ As a result, you will have the names of all the services in the file. When checking and adding the services we will loop this. But that is further up in the script.
First, we want to see if all required service block and keys are present. We will test if for example $ and $fileBody.HorizonViewServices.protocol is present. If not we will log and throw an error (exit there). For example:

If (!($
# Requires at least one to be present
# If we don’t find exit
If ($logon -eq “Yes”) { Write-Log “[ERROR] Horizon View Services section name not found but is required. Exit script” }
throw “Horizon View Services section name not found but is required”} # Can’t propose user with default other than the default yml

We will repeat this for the other keys within the services block. Good input checking is done. Next get some user input for connection to NSX, we will ask and check for vCenter/NSX manager, user, and password. Input is requested via Read-Host and checked and logged (except for the password).

# Get input from user about
# NSX Manager
$nsxManager = Read-Host (“vCenter connected to NSX (FQDN/IP)”)
# no manager throw error and exit
If ($logon -eq “Yes”) { Write-Log “[ERROR] Asked user about vCenter/NSX manager. Got no usable response: $nsxManager” }
throw “Asked user about vCenter/NSX manager. Got no usable response: $nsxManager”
If ($logon -eq “Yes”) { Write-Log “Asked user about NSX manager. Got response: $nsxManager” }

Okay now we have the information to use and connect to NSX, finally some PowerNSX calling the Connect-NsxServer cmdlet. We don’t use the Defaultconnection, so it’s important to use -connection $NSXConnection with all the following PowerNSX cmdlets (when piped repeat per cmdlet!).

# Open Connection
# Use as -connection $NSXConnection is the remainder of commands
If ($logon -eq “Yes”) { Write-Log “Opening connection to NSX Manager” }
$NSXConnection = Connect-NsxServer -vCenterServer $nsxManager -username $nsxUser -Password $nsxPass -DefaultConnection:$false

Yay connection. Now to do something with the data and this connection. We will loop through the service names and Get-NsxService to check what is currently in NSX. If already in NSX we skip in this version of the script, later on we will check the values and if there is a diff overwrite (see the settings). If the service does not exist we will get the other key values required for adding the service. Around the ForEach loop of the names of the service there is a counter. When we want the protocol of a looped name we call this via $itemProt = $fileBody.HorizonViewServices.protocol[$countSvc]. And if we do this for the other keys and order where they appear we will have a matching service name, protocol, destination port and description. Putting this together and add the services with New-NsxService -Name $item -Protocol $itemProt -port $itemDest -Description $itemDesc -connection $NSXConnection

And as a result what do we see in NSX is

NSXForDesktop - Added Service

That block of code put together:

$countSvc = 0
# Lets test if the service exists in NSX.
ForEach ($item in ${
$itemfromNSX = Get-NsxService -name $item -connection $NSXConnection
If (!$itemfromNSX) {
# Does not exist
If ($logon -eq “Yes”) { Write-Log “$item does not exist as service in NSX. Need to add” }
# Get the other values that belong to service
$itemProt = $fileBody.HorizonViewServices.protocol[$countSvc]
$itemDest = $fileBody.HorizonViewServices.dest_ports[$countSvc]
$itemSrc = $fileBody.HorizonViewServices.source[$countSvc]
$itemDesc = $fileBody.HorizonViewServices.description[$countSvc]
If ($logon -eq “Yes”) { Write-Log “For $item there is $itemProt, DEST $itemDest, Src $itemSrc with description $itemDesc” }
If ($logon -eq “Yes”) { Write-Log “[ERROR] There is no protocol for $item”}
throw ” There is no protocol for $item”
If ($logon -eq “Yes”) { Write-Log “$item Adding here” }
New-NsxService -Name $item -Protocol $itemProt -port $itemDest -Description $itemDesc -connection $NSXConnection
# Does exist check for overwrite
# Later version will check on diffs in script
If ($logon -eq “Yes”) { Write-Log “$item does exist” }
# Check for settings to overwrite
If ($overwrite -eq “Yes”) {
# Will add overwrite in a later version
# NeedsAdding

And end script with some logging that our run is complete.


Apparently the PowerNSX New-NsxService does not take input for the source ports. The script does not use the input parameter and will be added with a source of any. I have put a bug issue on GitHub and will check if this can be done another way of loose the source in the service definition.


For using PowerShell you will need the VMware.PowerShell module. -> Install-Module -Name VMware.PowerShell.
For using PowerNSX you will need the PowerNSX module. -> Install-Module -Name PowerNSX.

The script also requires PSYaml module. This module is included within this project and called in the script. No specific need to download and install.


The script connects via the vCenter and uses SSO credentials. This SSO user must have permissions in vCenter and NSX manager specifically to add and change NSX rules, services, servicegroups and securitygroups.


The whole run is logged as the following screenshot shows



GitHub project

I am maintaining the script and services file on Github. See the GitHub project taking it all together. Find it here: You are invited to contribute!

I am also documenting there in the Wiki and so on. Probably going back and forth between blog explaining my current mind, and document on GitHub at some times. Parts of the blog posts will probably be used as documentation.

Important note

This is a work in progress and I will try to update the next couple of weeks while I’m working at this to get it running in a staging/test environment. Just the same goes for this set of rules as VMware Flings, use with caution and test test test before going anywhere near what some call production.

– Enjoy coding and contributing!