
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
on
05-12-2015
01:34 PM
- edited on
03-25-2019
01:28 PM
by
ciscomoderator
Task Name | Passing Variables from PowerShell to UCSD |
Description | |
Prerequisites |
|
Category | Workflow |
Components | vSphere 5.x |
User Inputs |
Instructions for Regular Workflow Use:
- Download the attached .ZIP file below to your computer. *Remember the location of the saved file on your computer.
- Unzip the file on your computer. Should end up with a .WFD file.
- Log in to UCS Director as a user that has "system-admin" privileges.
- Navigate to "Policies-->Orchestration" and click on "Import".
- Click "Browse" and navigate to the location on your computer where the .WFD file resides. Choose the .WFD file and click "Open".
- Click "Upload" and then "OK" once the file upload is completed. Then click "Next".
- Click the "Select" button next to "Import Workflows". Click the "Check All" button to check all checkboxes and then the "Select" button.
- Click "Submit".
- A new folder should appear in "Policies-->Orchestration" that contains the imported workflow. You will now need to update the included tasks with information about the specific environment.
UCS Director supports running PowerShell scripts straight from a workflow. Although this adds powerful new possibilities, it can be tricky to pass objects back from PowerShell to UCS Director.
For example, let's take this trivial PowerShell script:
write "192.168.100.1";
return "Hello World!";
Running that from UCS Director will give me the following XML output:
<?xml version='1.0'?>
<Objects>
<Object Type='System.String'>192.168.100.1</Object>
<Object Type='System.String'>Hello World!</Object>
</Objects>
As you can see, anything that is written to the terminal or returned will be passed back to UCS Director. Although some basic Regular Expression might help out here, I wanted to do something a bit smarter.
Setting variables inside PowerShell
The first step was to create a method for containing my variables. For example, if I want to pass an IP Address, a machine name and some metadata back, how can I guarantee the order of the XML? What if it changes in the future?
The way I've dealt with this problem is to store everything in an associative array. This way I can pass key/value pairs back to UCS Director in a standard, easy to use way. For example:
$ip_address = "192.168.100.1";
$machine_name = "matday-test-01";
# Create an array to store all the UCSD return values in:
$ucsd = @{}
$ucsd.ip_address = $ip_address;
$ucsd.machine_name = $machine_name;
$ucsd.metadata = "Authored by Matt Day";
# Return the array back to UCSD:
return $ucsd;
The neat thing here is that I'm able to pass anything I like back to UCS Director in a safe fashion. Taking a look at the XML this will return, you get this:
<?xml version='1.0'?>
<Objects>
<Object Type='System.Collections.Hashtable'>
<Property Name='Key' Type='System.String'>metadata</Property>
<Property Name='Value' Type='System.String'>Authored by Matt Day</Property>
<Property Name='Key' Type='System.String'>ip_address</Property>
<Property Name='Value' Type='System.String'>192.168.100.1</Property>
<Property Name='Key' Type='System.String'>machine_name</Property>
<Property Name='Value' Type='System.String'>matday-test-01</Property>
</Object>
</Objects>
Parsing PowerShell variables
Once this PowerShell script is complete, we need to parse the XML data. To do this, we can create a custom workflow task to capture this output.
For this example, I'm going to create a custom task that captures IP Address, Machine Name and Metadata, although yours can include anything you like.
The first step is to import the UCS Director and Java libraries.
// Import UCS Director scripting library and Java standard library
importPackage(com.cloupia.lib.util);
importPackage(java.util);
Then the above XML needs to be included as a variable.
var xml = "<?xml version='1.0'?><Objects><Object Type='System.Collections.Hashtable'><Property Name='Key' Type='System.String'>metadata</Property><Property Name='Value' Type='System.String'>Authored by Matt Day</Property><Property Name='Key' Type='System.String'>ip_address</Property><Property Name='Value' Type='System.String'>192.168.100.1</Property><Property Name='Key' Type='System.String'>machine_name</Property><Property Name='Value' Type='System.String'>matday-test-01</Property></Object></Objects>";
You might want to map this to an input for your custom task.
I now need to use the built-in XMLUtil class to parse the above XML tree. It works hierarchically, so each layer of XML needs to be done sequentially.
The first step is to grab the data inside the <Objects>...</Objects> layer:
var objects_xml = XMLUtil.getValue("Objects", xml);
This returns a list of all the matching sections. In this case, it's only going to return 1 item containing the <Object>...</Object> tags. Again, we need to parse this:
// Get the first match (0) from the <Objects>...</Objects> section:
object_list = XMLUtil.getTag("Object",objects_xml.get(0))
Now we need to build a list of all the <Property>...</Property> tags from the single <Object>...</Object> tree:
// Get the first match (0) from the <Object>...</Object> section:
property_list = XMLUtil.getTag("Property",object_list.get(0))
As you saw above, the key/value pairs are on alternating lines. The easiest way to obtain this information is to iterate through the list, treating even numbers as keys and odd numbers as values.
// Store results in a HashMap (a Java associative array)
var variable_map = new HashMap();
// Store previous keys in buffer:
var key_buffer = "";
// Loop through all values taking even as keys and odd as values:
for (i = 0; i < property_list.size(); i++) {
// Remove XML tags with a bit of Regular Expression
property_list.set(i, property_list.get(i).replaceAll("<.*?>",""));
// Keys (even numbers)
if ((i % 2) == 0) {
key_buffer = property_list.get(i);
}
// Values (odd numbers)
else {
variable_map.put(key_buffer, property_list.get(i));
}
}
Now using the example above where the IP Address, Machine Name and Metadata are all being passed back, we can pull this out via a UCS Director script:
output.ip_address = variable_map.get("ip_address");
output.machine_name = variable_map.get("machine_name");
output.metadata = variable_map.get("metadata");
This could be extended to anything you like and further checked, mapped etc in to UCS Director's various types.
Putting it all together
I built a small Custom Workflow Task to show the concept.
Inputs:
Outputs:
Script
importPackage(com.cloupia.lib.util);
importPackage(java.util);
var xml = input.xml
// Try and parse the <Objects>...</Objects> section
var objects_xml = XMLUtil.getValue("Objects", xml);
// Parse the objects list now (should also be a single section):
object_list = XMLUtil.getTag("Object",objects_xml.get(0))
// Parse the object_list to get properties:
property_list = XMLUtil.getTag("Property",object_list.get(0))
// Store results in a HashMap (a Java associative array)
var variable_map = new HashMap();
// Store previous keys in buffer:
var key_buffer = "";
// Loop through all values taking even as keys and odd as values:
for (i = 0; i < property_list.size(); i++) {
// Remove XML tags
property_list.set(i, property_list.get(i).replaceAll("<.*?>",""));
// Keys
if ((i % 2) == 0) {
key_buffer = property_list.get(i);
}
// Values
else {
variable_map.put(key_buffer, property_list.get(i));
}
}
// Match desired output to HashMap fields:
output.ip_address = variable_map.get("ip_address");
output.machine_name = variable_map.get("machine_name");
output.metadata = variable_map.get("metadata");
Sample Output
To prove the concept, here's a sample workflow:
Workflow Summary
PowerShell Script
Custom Workflow Inputs
Results
Log File
Extending in the Future
This could be extended to support any output from a PowerShell script. By adding a new input to the above workflow, "variable", you could specify exactly what you wanted output and run it multiple times against the same PowerShell output, allowing a general purpose variable collector.
For example, we add a new input variable_name:
And reduce the outputs to a single variable result:
The following script could then be used to match any output:
importPackage(com.cloupia.lib.util);
importPackage(java.util);
var xml = input.xml
// Try and parse the <Objects>...</Objects> section
var objects_xml = XMLUtil.getValue("Objects", xml);
// Parse the objects list now (should also be a single section):
object_list = XMLUtil.getTag("Object",objects_xml.get(0));
// Parse the object_list to get properties:
property_list = XMLUtil.getTag("Property",object_list.get(0));
// PowerShell returns arrays weirdly to UCSD, alternating rows of keys/values
// Like this:
// <Property Name="Key" Type="System.String">ip</Property>
// <Property Name="Value" Type="System.String">192.168.100.1</Property>
// <Property Name="Key" Type="System.String">server_name</Property>
// <Property Name="Value" Type="System.String">New Server</Property>
//
// Store output in a HashMap:
var variable_map = new HashMap();
// Store previous keys in buffer:
var key_buffer = "";
// Loop through all values taking even as keys and odd as values:
for (i = 0; i < property_list.size(); i++) {
// Remove XML tags (can't seem to coax the XML library to do this for me!)
property_list.set(i, property_list.get(i).replaceAll("<.*?>",""));
// Keys
if ((i % 2) == 0) {
key_buffer = property_list.get(i);
}
// Values
else {
variable_map.put(key_buffer, property_list.get(i));
}
}
// Match desired output to HashMap fields:
output.variable = variable_map.get(input.variable_name);
Running the Workflow
In this case the user input mapping is the same (mapped to a PowerShell command output):
However this time we map the variable name to the desired outcome (in this case an IP address):
When run the variable that we desire is collected:
You can see in the logs how it's matched:
Here are the examples from the attached workflow:
Workflow:
Custom Workflow Tasks:
The workflow:

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This is absolute gold. Been hunting and playing for quite a while trying to figure out how to get this working properly with the little information that is out there. Thanks for explaining!

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
I really need to work with that to enhance my Workflows but I have a big problem.
When I try to check an output variable with IfElse or a Conditional Task it does not work.
For Example:
when I use your Example Workflow:
- Add an Output Variable "IPAddress" to the Workflow (Type: Generic Text)
- Map the User Output of Task "Get IP Address" to the Variable "IPAddress"
- Add an IfElse Task with the following condition: IPAddress == "192.168.100.1"
The Workflow Fails:
Apr 21, 2017 14:09:45 CEST Task: PowerShell Variable Passing Example (If Else) failed with error - Not able to parse to a integer value, please check the condition - IPAddress=='192.168.100.1', selectedContext=<None>
Apr 21, 2017 14:09:45 CEST Task #5 (PowerShell Variable Passing Example (If Else)) failed after 0 seconds
Can anyone help me out with that?
It would be great to get this running.

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
this is the new write up for the if statement
Conditional Operators Supported - integers
==, !=, <, <=, >, >=
Conditional Operators Supported - lexical
equals, notEquals, contains, startsWith, endsWith
Conditional Operators Supported - Boolean
|| - Logical Boolean OR operator, && - Logical Boolean AND operator

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
This works just tested it:

- Mark as Read
- Mark as New
- Bookmark
- Permalink
- Report Inappropriate Content
Hi Orf,
thanks for the information.
I had tested „equals“ but it always resulted in „False“.
I have now found the problem ☺
If I pass the output to an output variable and check the variable „IPAddress“ then IfElse always results in „False“.
I have to check the task-value itself:
Get IP Address.variable equals "192.168.100.1"
This works!
Best regards
Christian
i.A. Christian Jonszies
Professional Consultant
christian.jonszies@stemmer.de
<mailto:christian.jonszies@stemmer.de>Bitte beachten Sie die neue E-Mail-Adresse!
Tel.: +49 (2734) 2759-0
Fax: +49 (2734) 2759-44
BT Stemmer GmbH
Standort Freudenberg
Hommeswiese 136, 57258 Freudenberg, Germany
Sitz der Gesellschaft: Olching, AG München HR B 132831
Geschäftsführer: Stefan Hischer (Vorsitzender), Henning Heimann, Oliver Herrmann, Dirk Behrens
Von: Orf Gelbrich
Gesendet: Freitag, 21. April 2017 14:55
An: Jonszies, Christian <Christian.jonszies@stemmer.de>
Betreff: Re: - Passing variables from PowerShell to UCS Director
Cisco Communities <https://communities.cisco.com/>
Passing variables from PowerShell to UCS Director
new comment by Orf Gelbrich<https://communities.cisco.com/people/ogelbric>
View all comments on this document<https://communities.cisco.com/docs/DOC-58250#comment-29847>