During a recent PoC at one of my customers, I was asked how they could assign some important vSphere Tags to their VMs during vRealize Automation’s provisioning process. While vRealize Orchestrator (vRO), is typically the place for such customizations, I found that vSphere tag functionality wasn’t included in vRO’s default Library. However, this functionality was included in PowerCLI, so to meet their need I showed them how to write a PowerCLI script for tag assignment, and then wrap it in a vRO workflow. In this article, I’ll show you how to achieve the same end, starting with configuring vRO’s PowerShell Plug-in, and ending with creating your own workflow for assigning a vSphere tag to a VM.
Since vSphere tags are a central concept of this article, here is an overview in case you’re not familiar with the concept just yet. Tags replace vSphere’s old custom attributes, and let you associate useful meta-data to vSphere objects like VMs or datastores, which you can then use for organizing your vCenter inventory, doing custom reporting, and custom automation/scripting.
Initial Setup
Orchestrator was recently re-branded from vCenter Orchestrator (vCO) to vRealize Orchestrator (vRO), so don’t let the mix of both references confuse you – they’re the same thing. I’ll also be abbreviating PowerShell as PS throughout this article.
I’ll start by adding some additional detail to the steps for setting up the PS plug-in and PS host that were originally posted in the initial PS plug-in release blog. Note: I did my testing for this article with vCenter 5.5 and the latest Orchestrator Appliance at the time, which was version 5.5.2 and included the PS Plug-in by default. I also designated a spare Windows 2008R2 VM in my lab to be my PS host.
The PS host is the Windows VM that will actually be running all the PS scripts that our vRO workflows call.
PS Host Installation
- On your PS host, look at this PS variable to check which version of PS you’re running: $PSVersionTable
- On your PS host, be sure you have PS 3.0 or higher. PS 3.0 also requires this hotfix for the memory change in step 10, below. On my PS host, I went ahead and installed PowerShell 4.0.
- On your PS host, download and install the latest version of PowerCLI.
PS Host Configuration
- On your PS host, open PS via “Run as Administrator” and run the following command:
set-executionpolicy unrestricted - On your PS host, open a Windows Command Prompt via “Run as Administrator.” We will use this Command Prompt window for the rest of the commands in this section.
- Set the default WinRM configuration values.
winrm quickconfig - (Optional) Check whether a listener is running on the default port of 5985 for HTTP.
winrm e winrm/config/listener - Configure the WinRM service.
- Check whether basic authentication is allowed.
winrm get winrm/config/service/auth - Enable basic authentication.
winrm set winrm/config/service/auth @{Basic=”true”} - Allow transfer of unencrypted data on the WinRM service.
winrm set winrm/config/service @{AllowUnencrypted=”true”}
- Check whether basic authentication is allowed.
- Configure the WinRM client.
- Check whether basic authentication is allowed.
winrm get winrm/config/client/auth - Enable basic authentication.
winrm set winrm/config/client/auth @{Basic=”true”} - Allow transfer of unencrypted data on the WinRM client.
winrm set winrm/config/client @{AllowUnencrypted=”true”}
- Check whether basic authentication is allowed.
- Run the following command to test the connection to the local WinRM service, specifying the local Administrator credentials of the PS host.
winrm identify -r:http://localhost:5985 -auth:basic -u:Administrator -p:password -encoding:utf-8 - Enable WinRM connections from vRO server. As a best practice I always use the FQDN, but short hostname (as long as it resolves) and IP number will work too.
winrm set winrm/config/client @{TrustedHosts =”myvro01.corp.local”} - Note: If your vRO is the virtual appliance, as opposed to a Windows-based installation, then you won’t be able to run the “winrm identify” command in in the next section from your vRO appliance. However, you can specify the a Windows-based “test machine” in your trusted hosts, like this:
winrm set winrm/config/client @{TrustedHosts =”myvro01.corp.local, mytestpc.corp.local”} - Increase the WSMan MaxMemoryPerShellMB setting on the PS host from its default 150MB to something much larger. I ran into “system.outofMemoryException” errors when calling PowerCLI scripts because its snap-in and vCenter connection required more memory. I went with 2048MB.
- Run the following command to check the MaxMemoryPerShellMB setting.
winrm get winrm/config/winrs - Run the following command to increase the MaxMemoryPerShellMB setting.
winrm set winrm/config/winrs @{MaxMemoryPerShellMB=”2048″}
- Run the following command to check the MaxMemoryPerShellMB setting.
Ensure Connectivity
- On your Windows-based vRO Server or Windows-based “test machine,” open a Windows Command Prompt via “Run as Administrator.” We will use this Command Prompt window for the rest of the commands in this section.
- Configure the WinRM client.
- Run the following command to check whether basic authentication is allowed.
winrm get winrm/config/client/auth - Run the following command to enable basic authentication.
winrm set winrm/config/client/auth @{Basic=”true”} - Run the following command to allow transfer of unencrypted data on the WinRM client.
winrm set winrm/config/client @{AllowUnencrypted=”true”}
- Run the following command to check whether basic authentication is allowed.
- Run the following command to enable WinRM connections with the vRO server.
winrm set winrm/config/client @{TrustedHosts =”myvro01.corp.local, mytestpc.corp.local”}
- Run the following command to test the connection to the WinRM service, specifying the local Administrator credentials of the PS host.
winrm identify -r:http://mypshost.corp.local:5985 -auth:basic -u:Administrator -p:password -encoding:utf-8
vRO Configuration
- In vRO, register your PowerShell host:
- Open the vCenter Orchestrator Client
- Browse to Library -> PowerShell -> Configuration and run the “Add a PowerShell Host” workflow
- Choose the default options, as depicted below.
Note: If your vRO “Authentication Mode” is configured for SSO (default for the embedded instance within the vRA/vCAC appliance) as opposed to LDAP, then you may run into this caveat, which requires you to specify Shared Session.
- (Optional) If you need to run PS scripts as an AD domain user, then configure kerberos on the PS host and vRO instance. This step isn’t needed for this article.
Starter PS Workflow
For this article, we’ll be calling PS scripts located in a C:\Scripts directory on our PS host. It’s also possible to embed a script right into a workflow, but I personally like to keep the scripts in the local file system, where I can easily read them and manually run them for troubleshooting.
- Let’s start by creating a very basic test script for our workflow to run. We’ll call it
C:\Scripts\test1.ps1 and give it the following contents:write-output “testing…” >> C:\Scripts\test1-output.txt
- In the tree structure on the left, browse to Library -> PowerShell, and then run the workflow called “Invoke an external script.” Fill in the values for your PS host and script path.
- Check that the C:\Scripts\test1-output.txt file was created as expected. If not, then trying running it by hand from a PowerShell command prompt on your PS host.
Test the Tagging Script
Hopefully, all has gone well and you’ve successfully called a basic PS script from a vRO workflow! Now let’s move on to our specific use case of assigning a vSphere tag to a target VM. We’ll nail down the syntax and then test it by hand from a PowerShell command line on your PS host.
- Take a look in your vSphere Web Client and make sure you have a couple of Tag Categories that you want to assign to target VMs. Keep in mind that my script only works with Tag Categories that have “Multiple Cardinality” set to “No.” If you want to follow this article exactly, create a Tag Category for Owner.
- On your PS host, download my PowerCLI script, AssignOneTagOnly.ps1 from GitHub HERE.
For those that are new to GitHub you CANNOT just right-click on this link and hit “save as.” You will want to click on the file, choose “Raw” and copy the script to:
C:\Scripts\AssignOneTagOnly.ps1 - Figure out the arguments you’ll need for this script.
- vCenter to connect to (FQDN, hostname, or IP#), for example 172.16.111.204
- vCenter user to connect with, for example [email protected]
- vCenter user’s password, for example vmware1!
- Tag value, for example the name of the VM’s owner, “Ted Spinks”
- Tag category, for example Owner
- Target VM to which the tag will be assigned, for example testvm01
- On your PS host, open a PowerShell window and run the script. Keep in mind that the arguments must be in this exact order. Here’s the syntax I used, with the example arguments above:
.\AssignOneTagOnly.ps1 172.16.111.204 [email protected] vmware1! “Ted Spinks” Owner testvm01 - Once you have successfully tested running the script from the command line, copy your syntax and paste it into notepad for safekeeping.
- In the vRO Client, run the Invoke an External Script workflow again, this time using the syntax we just saved to fill in the values.
Here is the tail end of my script output, from when I ran my workflow:
Note: If you get any “system.outofMemoryException” errors here, go back up to the Initial Setup section, and make sure you’ve completed the memory changes in the PS Host Configuration section above, in step 10. If you’re running PowerShell 3.0, you may also need to install this hotfix.
Create the Tagging Workflow
Now that we’ve successfully tested our tagging script from within a stock vRO workflow, let’s make a more permanent workflow. We’ll make a duplicate of the Invoke An External Script workflow that we can dedicate to the purpose of assigning a tag to a VM, and instead of prompting for a complicated argument string, we’ll create some inputs to prompt the user for each of the needed pieces of information.
- In the vRO Client, click Design from the drop-down at the top. In the tree structure on the left, create a working folder for yourself (mine is called “Ted”).
- Browse to Library -> PowerShell, and then Right-Click/Duplicate the workflow called “Invoke an external script.” Place the duplicate into your working folder and call it something descriptive, like “Assign a Tag to a VM”
- Edit the workflow.
- On the Inputs tab, right-click “externalScript” and select “Move as attribute.” We’ll bake the script name right into the workflow, so it won’t need to be an input.
- Do the same thing for “arguments”, right-clicking it and selecting “Move as attribute.” We’ll be filling this in programmatically using the new Inputs we’re about to add to the workflow.
- Add 6 new inputs – one for each of our script arguments. Make all of them strings except for vcPass – make that a SecureString.
- On the General tab, give it a new Description, such as “Assign a vSphere Tag to a VM” and fill in the externalScript attribute with the full path of the script on the PS host.
- Click the Schema tab and drag a new Scriptable Task element onto the canvas, placing it before the Invoke Script element. We’re going to use this Scriptable Task to turn our workflow inputs into the argument string needed by our AssignOneTagOnly.ps1 script.
- Mouse over the Scriptable Task, and click the pencil icon to edit it.
- On the Visual Binding tab, drag all 6 of the new inputs we just created to the IN column. Drag the “arguments” attribute to the OUT column.
- On the Scripting tab, add the following line of code. Copy it exactly – the arguments are positional, and JavaScript is case sensitive!
arguments = vCenter + " " + vcUser + " " + vcPass + " " + tagVal + " " + tagCat + " " + targetVM;
Make sure you see all 7 variables highlighted in blue as shown below; if not, double-check that you’ve typed them perfectly on the workflow’s Inputs tab too.
- Close the Scriptable Task dialog window.
- Mouse over Invoke Script element, and click the pencil icon to edit it.
- On the Visual Binding tab, note that externalScript and arguments are no longer bound to anything, since we changed their workflow inputs into attributes. Drag their attributes over top of their corresponding items in the IN column to re-bind them.
- Close the Invoke Script dialog window. We’re all done with the Schema tab.
- On the Presentation tab, delete the reference to External Script, since we pre-populated this value and no longer need to prompt the user to enter it.
- Save and Close the workflow.
- Now let’s test our new “Assign a Tag to a VM” workflow! Go ahead and run the workflow – you should be prompted to fill in all the inputs. Let’s go ahead and use the exact same argument values we’ve used previously. Note that for any value that contains a space you’ll need to enclose it in single quotes. Double quotes, aka quotation marks, won’t work!
- Success!! Here is the tail end of my script output, captured in the log. Since the tag was already present on the target VM from our previous test, it logged a warning telling me that there was nothing for it to do. Now go ahead and run it again, against a new test VM!
Final thoughts
Congratulations, you now have a vSphere Tagging workflow that you can run manually, or include in your other workflows!
In case you’d find a copy of my exact workflow helpful, I exported it and you can download it from GitHub HERE. Click the “Download Zip” button, and then extract it on your desktop. Rename the file “Simple Simple Tag Workflow.piz” as “.zip” and inside you’ll find a workflow file you can import into your vRO.
In a future blog article, I’ll cover a scalability scenario in which we prepare to run multiple PowerShell/PowerCLI scripts from within a single workflow. For that, we’ll go over some optimizations, like sharing a single PS Session across all the scripts to conserve resources, and organizing your workflows/code in a more modular, re-usable manner.
UPDATE: The “future” blog article has been published! You can find it here: Optimizing PowerShell Workflows in vRealize Orchestrator.