Using the indexOf() method for Arrays and Strings for vRO and vRA

I’ve never been a developer so getting into JavaScript was quite a challenge at first and I probably always went the longest route possible to achieve something. As I use it more and more, I am picking up these neat little tricks and uses for built in methods that make my life easier.

In the world of vRA and vRO, I find that most of my time is spent iterating over arrays or parsing custom properties. One method that I have come to find extremely useful is the indexOf() that is available on Arrays and Strings. The methods are very similar but have very different use cases. Let’s take a look at each of them in turn.

String indexOf() Method

w3schools.com defines this as:

The indexOf() method returns the position of the first occurrence of a specified value in a string.

This method returns -1 if the value to search for never occurs.

So as an example, if we had the string “simplygeek.co.uk is fun”

string.indexOf(“m”) would return 2, which is the index within the string that ‘m’ first appears. Note that if ‘m’ appeared twice then only the first match would return a result. Indexes within arrays and strings always start at 0.

Another use case, one which I find the most useful, is being able to provide a string for the lookup. Take the following example:

string.indexOf(“simplygeek”) would return 0, because in a contiguous match the first index is returned.

When writing JavaScript that interacts with vRA you are often required to parse through custom properties, which are key value pairs of data. Such properties can contain useful information that relates to a deployment, such as virtual machine configuration. If custom properties follow a standardised naming convention, it can be easy to discover a set of properties. Let’s assume I have created the following custom properties in vRA for a deployment:

Custom.Deployment.Virtualmachine.Config.hotcpu : true
Custom.Deployment.Virtualmachine.Config.hotmem : true
Custom.Deployment.Virtualmachine.Config.sched.swap.vmxSwapEnabled : true

When the payload is sent to my vRO workflow it could contain over a 100 different key:value pairs of data. To find these easily I can use the indexOf method to iterate over each pair as follows:

The above will result in an array of properties related to virtual machine configs. I can then pass this array to some code that will handle the implementation of these advanced virtual machine settings. This allows for a very dynamic way to manage custom properties in property groups within vRA.

Array indexOf() method

Very similar to the String method, on an array, the indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present. I find this method useful when I need to return a set of unique values from another array. let’s assume we have the following array:

myArray = [‘one’, ‘two’, ‘two’, ‘three’, ‘three’, ‘three’]

If I wanted to return only unique items from myArray, I could use the indexOf method as follows:

The above code will result in an array:

[‘one’, ‘two’, ‘three’]

I hope that someone else finds these as useful as I have. If you know of more use cases, then please let me know.

vRO Coding Pet Hate – Badly formed IF statements

I was optimising some vRO actions today and came across something that always annoys me when I see it, badly formed IF statements (for one of a better description). When I write my code, I have learned that formatting and consistency is key to produce code that is easier to read and understand. I also like to keep things simple. However, I am constantly surprised at how much sloppy coding practices I encounter from the code that is shipped with vRO. Here are a couple of small examples of the kind of thing I am talking about.

Both of the above statements are pretty much identical in how they function. They are checking if a given variable is null (or not) and if the condition returns ‘true’ then execute the following statement. As you can see from the code snippets above, the structure of these statements are different. Why? Because this is a valid way to write conditionals in JavaScript, if you are only performing an action when the result is ‘true’. That said, it doesn’t mean we should use it in practice. The reason for this, is that it forces a lack of consistency in your code (which you can already see from the code above).

If we wanted to add another action for a result that returns ‘false’, we would need to add an ‘else’ clause. With the conditional statements above, we wouldn’t be able to do this as it would require adding curly braces so that the interpreter knows when to apply the correct code based on the result. Here is an example.

This is the structure that I like to adhere to every time I write a conditional. I also apply the ‘4 spaces rule’ for my indentation (and don’t get me started on the use of tab!). The two code snippets revised using this structure would look like:

I believe this is a much neater approach for the sake of a few more lines, which aren’t worth saving if the code is more readable.

Get a list of Datastores, quickly, using XPATH

The vCenter plugin has a very useful method for retrieving a list of objects quickly and easily. However, if your inventory is quite large, then this can be quite slow. There are two ways that this can be improved. 1) only retrieve the attributes that are useful for our code requirements, 2) use an XPATH query filter to limit the scope of the search.

In my situation there were over a 100 Datastores but I only wanted to retrieve a list based on a given prefix (of which there were less than 10). The Datastore names end with an incrementing number and I wanted to return all of these in an array.

I have used a similar approach which allowed me to retrieve several thousand virtual machines in approximately 3-5 seconds.

Get Datastore with Most Free Space & Check Datastore Meets Capacity Reservation

I do a lot of work that involves either creating new virtual hard disks or attaching existing ones to virtual machines in VMware vSphere. I do all of this through vRealize Orchestrator, written in JavaScript (yum).

As part of this task, I always ensure that the datastores that I am creating disks on have sufficient capacity for these new disks. I use two simple functions that I have written which perform these checks for me, which is ‘getDatastoreWithMostFreeSpace’ and ‘DoesDSMeetCapcityReserve’. An additional function ‘convertToGB’, which is used by these functions is also provided at the end.

Function : getDatastoreWithMostFreeSpace

Description
Return a single VcDatastore object that has the most free space from an Array of provided VcDatastore objects. The function will always return a VcDatastore, regardless of how much free space is found.

Parameters
– VcDatastores (Array of VcDatastore)

Return Type : VcDatastore

Function : DoesDSMeetCapcityReserve

Description
Checks that a given VcDatastore has enough free space in which to place the virtual disk, taking into account current usage and a defined reservation value (in percent) that should be guaranteed. Returns true if the Datastore passes the capacity checks.

Parameters
– datastore (VcDatastore)
– reservation (Number)
– totalSizeRequired (Number)

Return Type : Boolean

Function : convertToGB

Description
Converts a value in Bytes to GB.

Parameters
– size (Number)

Return Type : Number

Example Output

[2017-09-18 15:09:37.459] [I] Selecting the datastore with the most free space:
[2017-09-18 15:09:37.714] [I] Datastore 1 information:
[2017-09-18 15:09:37.715] [I] name: DATASTORE1
[2017-09-18 15:09:37.717] [I] ID: datastore-99999
[2017-09-18 15:09:37.718] [I] Capacity: 2048 GB
[2017-09-18 15:09:37.719] [I] Free Space: 1762 GB
[2017-09-18 15:09:37.721] [I] Used Space: 286 GB
[2017-09-18 15:09:37.725] [I] MaxVMDKSize: 63488 GB
[2017-09-18 15:09:37.726] [I] Selected Candidate Datastore: DATASTORE1
[2017-09-18 15:09:37.728] [I] Performing capacity validation checks on the datastore.
[2017-09-18 15:09:37.729] [I] Datastore reservation is set to 10%
[2017-09-18 15:09:37.730] [I] Datastore has: 87% free space
[2017-09-18 15:09:37.733] [I] Datastore meets 10% reservation threshold.
[2017-09-18 15:09:37.735] [I] Checking that enough storage is available for the virtual disk(s)
[2017-09-18 15:09:37.737] [I] The reserved size at 10% is: 205 GB
[2017-09-18 15:09:37.738] [I] Free space available taking into account the reservation: 1557 GB
[2017-09-18 15:09:37.740] [I] The datastore will have 1556 GB of usable space remaining after the commit
[2017-09-18 15:09:37.741] [I] Datastore meets capacity requirements
[2017-09-18 15:09:37.744] [I] The Virtual Disk(s) will be located on: DATASTORE1

vRA 7 – Getting more information in workflows from the vRO ExecutionContext object

When a vRO workflow or action is called from vRA, additional input parameters (in addition to those specified as the workflow/action inputs) are provided in the Execution Context object. These can be very useful as they contain additional data that can be used inside the workflows. A couple of good examples would be the user that requested the resource or the name of the tenant.

Here is a list of parameters provided inside the Execution Context (those without a description I’m still trying to figure out):

 Parameter Name  Description
__asd_catalogRequestId
__asd_correlationId  The Request ID
__asd_requestInstanceId
__asd_requestInstanceTimestamp Request Date & Time
__asd_requestInstanceTypeId The lifecycle ID
__asd_requestTraceId
__asd_requestedBy The UPN of the user who made the request
__asd_requestedFor The UPN of the user the request was on behalf of
__asd_targetResourceId
__asd_targetResourceProviderId
__asd_targetResourceProviderTypeId com.vmware.csp.iaas.blueprint.service
__asd_targetResourceTypeId Type ID, i.e. ‘machine’
__asd_tenantRef The friendly name of the tenant (i.e. vsphere.local)

Wait, where is ‘__asd_subtenantRef’? More on that in my post here (soon).

You can also see these in the variables tab for the workflow run:

List all parameters

The parameters and their values in the execution context object can be retrieved using the System scripting class. There is a method called ‘getContext()‘, which returns an object called ‘ExecutionContext‘. The ExecutionContext object has the following methods:

boolean contains(String name)
Object getParameter(String name)
Array parameterNames(String name)

Insert the following code into a scripting task in your workflow to list all the parameters and their values:

Retrieve the value for a specific parameter

To retrieve a value for a specified parameter the following example can be used:

Retrieves the tenant name and sets it to a variable/attribute.

If anyone can shed some light on what the other parameters do then please comment and I’ll update the page.