VRO Enable lockdown mode

I have been reading the VMware validated design documents of late.  I cannot recommend them enough they are awesome documents.   It’s really worth the deep read.   I noticed one of the design choices is to enable lockdown mode on all esx hosts.   This is common due to security needs but it additionally commented that host profiles don’t capture lockdown mode settings so you have to manually set it.   I have used PowerCLI to turn on and off (during issues) lockdown mode for years and VMware posted a KB article that includes the PowerCLI code here.

 

I wanted to write a piece of orchestrator code that would lock down esx hosts on a daily basis if they are not in lockdown mode.  Consider it a desired end state tool.

If you wanted to enable Normal lockdown mode on all ESXi hosts you would use the following code:

 

//Get all hosts
hosts = System.getModule(“com.vmware.library.vc.host”).getAllHostSystems();

for each (host in hosts)
{

// Compare lockdown modes
if (host.config.lockdownMode.value === “lockdownDisabled”)
{
host.enterLockdownMode();
System.log(host.name + ” is being locked down”);
}
else if (host.config.lockdownMode.value === “lockdownNormal”)
{
System.log(host.name + ” is already locked down”);
}

}

 

Now if you wanted to disable lockdown you would just run the following code:

//Get all hosts
hosts = System.getModule("com.vmware.library.vc.host").getAllHostSystems();

for each (host in hosts)
{

   // Compare lockdown modes
   if (host.config.lockdownMode.value === "lockdownDisabled")
   {
   System.log(host.name + " is already not in lock down mode");
    }
else if (host.config.lockdownMode.value === "lockdownNormal")
    {

    host.exitLockdownMode();
    System.log(host.name + " is now not in lock down mode.");
    }

}

 

You can enable / disable strict mode sing lockdownStrict as well.  I hope it helps… now all you need to do is create a scheduled task and perhaps do it cluster by cluster.

 

 

VRO to delete lots of virtual switches in NSX

I created a workflow to create 5000 virtual switches in NSX… which was cool.  But it did create 5000 virtual switches which now needed to be deleted.  So I created a new workflow to delete them.   In my case I created all 5000 switches on the same distributed logical router.   I had to delete the DLR before starting this workflow.   I used two RESTAPI calls to complete this work as show below:

And

 

Notice the URL templates on both as they are critical.  Otherwise it’s just a RESTAPI call to NSX Manager.

These two workflows along with the RestHost get passed into a workflow as shown:

 

Otherwise it’s just a scriptable task.  I ran into an issue with it running too fast for NSX manager so I put a 1 second wait in between each call.  Here is the code:

function sleep(milliseconds) {
 var start = new Date().getTime();
 for (var i = 0; i < 1e7; i++) {
 if ((new Date().getTime() - start) > milliseconds){
 break;
 }
 }
}

//Setup the get request for wires
var inParamtersValues = [];
var request = restOperation.createRequest(inParamtersValues, null);
request.contentType = "";
var response = request.execute();
//prepare output parameters
//System.log("Response: " + response);
statusCode = response.statusCode;
statusCodeAttribute = statusCode;
//System.log("Status code: " + statusCode);
contentLength = response.contentLength;
headers = response.getAllHeaders();
contentAsString = response.contentAsString;

System.log(response);

var xmlObj = new XML(contentAsString);

var document = XMLManager.fromString(contentAsString);

var count = document.getElementsByTagName("vdnId");

System.log("Count : " + count.length);

j = 0;

for (i=0; i < count.length; i++)
{
 //System.log("Scope: " + xmlObj.dataPage.virtualWire[i].objectId + " vdnId: " + xmlObj.dataPage.virtualWire[i].vdnId );
 if ( xmlObj.dataPage.virtualWire[i].vdnId > 5010)
 {
 System.log("Scope: " + xmlObj.dataPage.virtualWire[i].objectId + " vdnId: " + xmlObj.dataPage.virtualWire[i].vdnId );
 var virtualWireID = xmlObj.dataPage.virtualWire[i].objectId;
 var inParamtersValues = [virtualWireID];
 var request = restOperationDelete.createRequest(inParamtersValues, null);
 request.contentType = "";
 var response = request.execute();
 statusCode = response.statusCode;
 System.log("Response : " + statusCode + " Rest request : " + virtualWireID);
 j++;
 sleep(1000);
 }
}
System.log("j : " + j + " Total : " + count.length);

It should work great it’s currently set to delete every vnri above 5010 (mine start at 5000)  you can adjust this number to whatever you want…

 

 

 

 

vRealize Orchestrator scaling with 4K displays

I ran into this issue this week.   vRealize Orchestrator with Windows 10 on 4K displays makes the UI so small not even my seven year old could read it.   For those lucky enough to have 4K displays it’s a real challenge.  It’s a problem with java and dpi scaling not Orchestrator but it’s a magical challenge.   As much as I want to return to the day of using magnify glasses to read computer screens… here is a simple fix.

 

Download the client.jnlp and run it from an administrative command line with the following command:

 

javaws -J -Dsun.java2d.dpiaware=false client.jnlp

 

This should fix your vision issues and it’s cheaper that a new pair of glasses.

vRO Action to return virtual machines with a specific tag

I am a huge fan of tags in vSphere.   Meta data is the king for modular control and policy based administration.   I wrote a action for a lab I presented at VMUG sessions.   It takes the name of a tag as a string and returns the names of all virtual machines as an array of strings.  It does require a VAPI endpoint setup as explained here: (http://www.thevirtualist.org/vsphere-6-automation-vro-7-tags-vapi-part-i/) Here it is:

 

Return Type: Array/String (Could be Array VC:VirtualMachine)

Parameter: tagNameToMatch string

Code: return_vm_with_tag

 // array to hold the vm names
 var vmsWithSpecificTag = new Array();
 // VAPI connection
 var endpoints = VAPIManager.getAllEndpoints();
 //Use the first returned endpoint to gather information
 var client = endpoints[0].client();
 //var client = end.client(); 
 //Get associations
 var tagging = new com_vmware_cis_tagging_tag__association(client);
 //Get tags
 var tagMgr = new com_vmware_cis_tagging_tag(client);
 //Create object to hold VM
 var objId = new com_vmware_vapi_std_dynamic__ID() ;

//Get all virtual machines
 vms = System.getModule("com.vmware.library.vc.vm").getAllVMs();
 //loop though virtual machines
 for each (vm in vms)
 {
 // assign VM data to object
 objId.id = vm.id;
 // assign VM data to object
 objId.type = vm.vimType;
 //Get tags assigned to VM
 var tagList = tagging.list_attached_tags(objId);
 //Loop through VM assigned tags
 for each (var tagId in tagList) {
 //get object on tag
 var theTag = tagMgr.get(tagId);
 //assign name to compare
 var tagName=theTag.name;
 //compare to our requested tag
 if (tagName == tagNameToMatch) {
 System.log("VM : " + vm.name + " has the tag : " + tagName );
 // add to array
 vmsWithSpecificTag.push(vm.name);
 }
 
 }
 }


return vmsWithSpecificTag;

Learning vRealize Orchestrator

Recently I provided a lab to learn vRealize Orchestrator to the Austin VMUG.   It’s been too long since I attended a VMUG meeting due to moving to Dallas.   It was great to meet new peers in the Austin area.    The purpose of the lab was to provide people hands on experience using Orchestrator with some real world helpful examples.   I was present to answer questions and help the learning process.

I am working to bring the same lab to Dallas and Houston in the next few months but wanted to share the labs here.  It’s mostly possible to do the labs in the hands on lab environment of hol-1821-05-CMP partially made by my friend Ed Bontempo.  You will have to type a lot of code examples since HOL does not support cut and paste.   You can do it all in your home lab.    Contact me if you want to know about the next session we are presenting to a live VMUG if you want some instructor help.

Code: code_text

Lab Manual: VMUG_VRO_LAB_Manual

Enjoy!

Configuring a NSX load balancer from API

A customer asked me this week if there was any examples of customers configuring the NSX load balancer via vRealize Automation.   I was surprised when google didn’t turn up any examples.  The NSX API guide (which is one of the best guides around) provides the details for how to call each element.  You can download it here. Once you have the PDF you can navigate to page 200 which is the start of the load balancer section.

Too many Edge devices

NSX load balancers are Edge service gateways.   A normal NSX environment may have a few while others may have hundreds but not all are load balancers.   A quick API lookup of all Edges provides this information: (my NSX manager is 192.168.10.28 hence the usage in all examples)

https://192.168.10.28/api/4.0/edges
        <edgeSummary>
            <objectId>edge-57</objectId>
            <objectTypeName>Edge</objectTypeName>
            <vsmUuid>420CD713-469F-7053-8281-A7BD66A1CD46</vsmUuid>
            <nodeId>92484cee-ab3c-4ed2-955e-e5bd135f5be5</nodeId>
            <revision>2</revision>
            <type>
                <typeName>Edge</typeName>
            </type>
            <name>LB-1</name>
            <clientHandle></clientHandle>
            <extendedAttributes/>
            <isUniversal>false</isUniversal>
            <universalRevision>0</universalRevision>
            <id>edge-57</id>
            <state>deployed</state>
            <edgeType>gatewayServices</edgeType>
            <datacenterMoid>datacenter-21</datacenterMoid>
            <datacenterName>Home</datacenterName>
            <tenantId>default</tenantId>
            <apiVersion>4.0</apiVersion>
            <recentJobInfo>
                <jobId>jobdata-34935</jobId>
                <status>SUCCESS</status>
            </recentJobInfo>
            <edgeStatus>GREEN</edgeStatus>
            <numberOfConnectedVnics>1</numberOfConnectedVnics>
            <appliancesSummary>
                <vmVersion>6.2.0</vmVersion>
                <vmBuildInfo>6.2.0-2982179</vmBuildInfo>
                <applianceSize>compact</applianceSize>
                <fqdn>NSX-edge-57</fqdn>
                <numberOfDeployedVms>1</numberOfDeployedVms>
                <activeVseHaIndex>0</activeVseHaIndex>
                <vmMoidOfActiveVse>vm-283</vmMoidOfActiveVse>
                <vmNameOfActiveVse>LB-1-0</vmNameOfActiveVse>
                <hostMoidOfActiveVse>host-29</hostMoidOfActiveVse>
                <hostNameOfActiveVse>vmh1.griffiths.local</hostNameOfActiveVse>
                <resourcePoolMoidOfActiveVse>resgroup-27</resourcePoolMoidOfActiveVse>
                <resourcePoolNameOfActiveVse>Resources</resourcePoolNameOfActiveVse>
                <dataStoreMoidOfActiveVse>datastore-31</dataStoreMoidOfActiveVse>
                <dataStoreNameOfActiveVse>SYN8-NFS-GEN-VOL1</dataStoreNameOfActiveVse>
                <statusFromVseUpdatedOn>1478911807005</statusFromVseUpdatedOn>
                <communicationChannel>msgbus</communicationChannel>
            </appliancesSummary>
            <hypervisorAssist>false</hypervisorAssist>
            <allowedActions>
                <string>Change Log Level</string>
                <string>Add Edge Appliance</string>
                <string>Delete Edge Appliance</string>
                <string>Edit Edge Appliance</string>
                <string>Edit CLI Credentials</string>
                <string>Change edge appliance size</string>
                <string>Force Sync</string>
                <string>Redeploy Edge</string>
                <string>Change Edge Appliance Core Dump Configuration</string>
                <string>Enable hypervisorAssist</string>
                <string>Edit Highavailability</string>
                <string>Edit Dns</string>
                <string>Edit Syslog</string>
                <string>Edit Automatic Rule Generation Settings</string>
                <string>Disable SSH</string>
                <string>Download Edge TechSupport Logs</string>
            </allowedActions>
        </edgeSummary>

 

This is for a single Edge gateway in my case I have 57 Edges deployed over the life of my NSX environment and 15 active right now.   But only Edge-57 is a load balancer.   This report does not provide anything that can be used to identify it as a load balancer from a Edge as a firewall.   In order to identify if it’s a load balancer I have to query it’s load balancer configuration using:

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config

Notice the addition of the edge-57 name to the query.   It returns:

<loadBalancer>
    <version>2</version>
    <enabled>true</enabled>
    <enableServiceInsertion>false</enableServiceInsertion>
    <accelerationEnabled>false</accelerationEnabled>
    <monitor>
        <monitorId>monitor-1</monitorId>
        <type>tcp</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <name>default_tcp_monitor</name>
    </monitor>
    <monitor>
        <monitorId>monitor-2</monitorId>
        <type>http</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <method>GET</method>
        <url>/</url>
        <name>default_http_monitor</name>
    </monitor>
    <monitor>
        <monitorId>monitor-3</monitorId>
        <type>https</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <method>GET</method>
        <url>/</url>
        <name>default_https_monitor</name>
    </monitor>
    <logging>
        <enable>false</enable>
        <logLevel>info</logLevel>
    </logging>
</loadBalancer>

Notice that this edge has load balancer enabled as true with some default monitors.   To compare here is a edge without the feature enabled:

https://192.168.10.28/api/4.0/edges/edge-56/loadbalancer/config
<loadBalancer>
    <version>1</version>
    <enabled>false</enabled>
    <enableServiceInsertion>false</enableServiceInsertion>
    <accelerationEnabled>false</accelerationEnabled>
    <monitor>
        <monitorId>monitor-1</monitorId>
        <type>tcp</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <name>default_tcp_monitor</name>
    </monitor>
    <monitor>
        <monitorId>monitor-2</monitorId>
        <type>http</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <method>GET</method>
        <url>/</url>
        <name>default_http_monitor</name>
    </monitor>
    <monitor>
        <monitorId>monitor-3</monitorId>
        <type>https</type>
        <interval>5</interval>
        <timeout>15</timeout>
        <maxRetries>3</maxRetries>
        <method>GET</method>
        <url>/</url>
        <name>default_https_monitor</name>
    </monitor>
    <logging>
        <enable>false</enable>
        <logLevel>info</logLevel>
    </logging>
</loadBalancer>

Enabled is false with the same default monitors.   So now we know how to identify which edges are load balancers:

  • Get list of all Edges via API and pull out id element
  • Query each id element for load balancer config and match on true

 

 

Adding virtual servers

You can add virtual servers assuming the application profile and pools are already in place with a POST command with a XML body payload like this (the virtual server IP must already be assigned to the Edge as an interface):

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config/virtualservers
<virtualServer>
<name>http_vip_2</name>
<description>http virtualServer 2</description>
<enabled>true</enabled>
<ipAddress>192.168.10.18</ipAddress>
<protocol>http</protocol>
<port>443,6000-7000</port> 
<connectionLimit>123</connectionLimit>
<connectionRateLimit>123</connectionRateLimit>
<applicationProfileId>applicationProfile-1</applicationProfileId>
<defaultPoolId>pool-1</defaultPoolId>
<enableServiceInsertion>false</enableServiceInsertion>
<accelerationEnabled>true</accelerationEnabled>
</virtualServer>

capture

You can see it’s been created.  A quick query:

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config/virtualservers
<loadBalancer>
    <virtualServer>
        <virtualServerId>virtualServer-5</virtualServerId>
        <name>http_vip_2</name>
        <description>http virtualServer 2</description>
        <enabled>true</enabled>
        <ipAddress>192.168.10.18</ipAddress>
        <protocol>http</protocol>
        <port>443,6000-7000</port>
        <connectionLimit>123</connectionLimit>
        <connectionRateLimit>123</connectionRateLimit>
        <defaultPoolId>pool-1</defaultPoolId>
        <applicationProfileId>applicationProfile-1</applicationProfileId>
        <enableServiceInsertion>false</enableServiceInsertion>
        <accelerationEnabled>true</accelerationEnabled>
    </virtualServer>
</loadBalancer>

 

Shows it’s been created.  To delete just use the virtualServerId and pass to DELETE

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config/virtualservers/virtualserverID

 

Pool Members

For pools you have to update the full information to add a backend member or for that matter remove a member.  So you first query it:

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config/pools
<?xml version="1.0" encoding="UTF-8"?>
<loadBalancer>
    <pool>
        <poolId>pool-1</poolId>
        <name>pool-1</name>
        <algorithm>round-robin</algorithm>
        <transparent>false</transparent>
    </pool>
</loadBalancer>

Then you form your PUT with the data elements you need (taken from API guide).

https://192.168.10.28/api/4.0/edges/edge-57/loadbalancer/config/pools/pool-1
<pool>
<name>pool-1</name>
<description>pool-tcp-snat</description>
<transparent>false</transparent>
<algorithm>round-robin</algorithm>
<monitorId>monitor-3</monitorId>
<member>
<ipAddress>192.168.10.14</ipAddress>
<weight>1</weight>
<port>80</port>
<minConn>10</minConn>
<maxConn>100</maxConn>
<name>m5</name>
<monitorPort>80</monitorPort>
</member>
</pool>

In the client we see a member added:

capture

Tie it all together

Each of these actions have a update delete and query function that can be done.  The real challenge is taking the API inputs and creating user friendly data into vRealize Input to make it user friendly.    NSX continues to amaze me as a great product that has a very powerful and documented API.    I have run into very little issues trying to figure out how to do anything in NSX with the API.  In a future post I may provide some vRealize Orchestrator actions to speed up configuration of load balancers.

 

 

 

 

 

 

 

 

 

vRO scriptable task to return top level folder of a VM

Every so often you have nested folders in a vCenter and want to return only the top level folder.  Here is a function to return the top level folder only:

function return_folder_path(vm)
{  
                var parent = vm.parent;  
                var parentNames = new Array();  
                var vmPathName = "";  
                while (parent instanceof VcFolder){  
                                parentNames.push(parent.name);  
                                parent = parent.parent;  
                }  
                for (i=(parentNames.length-2); i>=0; i--){  
                                //vmPathName += "/"+parentNames.pop();  
                                vmPathName += "/"+parentNames[i]; 
                }  
                return vmPathName;
}

 

vRO add all virtual machines to NSX exception list

Almost everyone is using a brownfield environment to implement NSX.   Switching the DFW firewall to deny all is the safest bet but hard to do with brownfield environments.   Denying all traffic is a bad idea.  Doing a massive application conversion at once into DFW rules is not practical.  One method to solve this issue is to create an exception for all virtual machines then move them out of exception once you have created the correct allow rules for the machine.   I didn’t want to manually via the GUI add all my machines so I explored the API.

How to explore the API for NSX

VMware’s beta developer center provides the easiest way to explore the NSX API.   You can find the NSX section here.  Searching the api for “excep” quickly turned up the following answer:

api

As you can see there are three methods (get, put, delete).  It’s always safe to start with a get as it does not produce changes.   Using postman for chrome.  I was quickly connected to NSX see my setting below:

n1

The return from this get was lots of lines of machines that I had manually added to the exception list.  For example the following

n1

Looking at this virtual machine you can see it’s identified by the objectID which aligns with the put and delete functions the following worked perfectly:

Delete
https://192.168.10.28/api/2.1/app/excludelist/vm-47

Put
https://192.168.10.28/api/2.1/app/excludelist/vm-47

A quick get showed the vm-47 was back on the list.  Now we had one issue the designation and inventory of objectID’s is not a construct of NSX but of vCenter.

The Plan

In order to be successful in my plans I needed to do the following

  • Gather list of all objectID’s from vCenter
  • Put the list one at a time into NSX’s exclude list
  • Have some way to orchestrate it all together

No surprise I turned to vRealize orchestrator.   I wanted to keep it generic rest connections and not use NSX plugins.   So my journey began.

Orchestrator REST for NSX

  • Login to orchestrator
  • Switch to workflow view
  • Expand the library and locate the add rest host workflow
  • Run the workflow

1

2

3

4

  • Hit submit and wait for it to complete
  • You can verify the connect by visiting the administration section and expanding rest connections

Now we need to add a rest operation for addition to the exception list.

  • Locate the Add REST operation workflow
  • Run it
  • Fill out as shown

1

You now have a put method that takes input of {vm-id} before it can run.  In order to test we go back to our Postman and delete vm-47 and do a get to verify it’s gone:

Delete:

https://192.168.10.28/api/2.1/app/excludelist/vm-47

Get:

https://192.168.10.28/api/2.1/app/excludelist

 

It’ is missing from the get.   Now we need to run our REST operation

  • Locate the workflow called: Invoke a REST operation
  • Run it as shown below

1

2

3

Once completed a quick postman get showed me vm-47 is back on the exclude list.   Now I am ready for prime time.

Creation of an Add to Exclude List workflow

I need to create a workflow that just runs the rest operation to add to exclude list.

  • Copy the Invoke a REST operation
  • New workflow should be called AddNSXExclude
  • Edit new workflow
  • Go to inputs and remove all param_xxx except param_0
  • Move everything else but param_0 to Attributes

1

  • Let’s edit the attributes next
  • Click on the value for ther restOperation and set it to “Put on Exclude List ..” operation you created earlier

1

  • Go to the Schema and edit the REST call scriptable task
  • Remove all param_xxx except param_0 from the IN on the scriptable task

1

  • Edit the top line of the scripting to read like this:

var inParamtersValues = [param_0];

  • Close the scriptable task
  • Click on presentation and remove everything but the content question

1

Now we have a new issue.  We need to have it not error when the return code is not 200.  For example if the object is already on the exception list.   We just want everything on the list right away.   So edit your schema to remove everything but the rest call:

1

 

Put it all together with a list of virtual machines

Time for a new workflow with a scriptable task.

  • In the general tab put a single attribute that is an array of string

1

  • Add a scriptable task to the schema
  • Add a foreach element to the schema after the scriptable task
    • Link the foreach look to the AddNSX workflow you made in the last step
    • Link vmid to param_0

1

  • Edit the scriptable task and add the following code:

//get list of all VM’s
vms = System.getModule(“com.vmware.library.vc.vm”).getAllVMs();

var vmid = new Array();

for each (vm in vms)
{

vmid.push(vm.id);

}

 

  • Add an IN for vmid and an OUT for vmid
  • Run it and your complete you can see the response headers in the logs section

Hope it helps you automate some NSX.

vRO Scriptable tasks

An old friend contacted me today with some vRO questions.  He is struggling with learning vRO like so many administrators before him.  It’s not easy to learn vRO it’s a very different type of programming.  Once you learn the basics of the editor and especially JavaScript in scriptable tasks it becomes really powerful.  So a few tips that I provided to my friend that may help you out when learning vRO:

  • JavaScript is case sensitive – this is hard for PowerShell or Windows users to remember
  • Variables are local to your scriptable task unless you make them an input or output (or both)
  • JavaScript variables don’t have defined types during creation (they are just pointers to memory locations)
  • Errors from JavaScript are not always very helpful (they point you to the incorrect or offending line)
  • You really should validate your input before taking an action

 

Case Sensitivity

I have rewritten a whole script to find out I missed a case for example a common one would be that is valid is:

System.log("Message");

While:

system.log("Message");
system.Log("Message");

Will all fail with a odd error.  You have to watch case on reserved commands.  This is true of API explorer objects VcVirtualMachine is VcVirtualMachine not VCvirtualmachine etc…

Types

Javascript has lots of different variable types including user defined objects.   You can discover the object type using System.log.  Assume that my object / variable is called new.

System.log(new);

Will output the type of object into the log window when run.  This is very useful for discovering the object type.  In the vCenter API you might have something like

vCenter.Cluster.Host.runtime.config.scsi[0]

If you want to understand your object type just use:

System.log(vCenter.Cluster.Host.runtime.config.scsi[0]);

And it will tell you the object.  (this is a example and will not work)

Almost everything in vRO is a complex object which can be loosely defined as a combination of key value pairs in an array.   A traditional array have multiple objects referenced like this:

array[0] = "magic"
array[1] = "cheese"
array[2] = "need"

This is a array of strings with a length of 3.   If I called this:

System.log(array[0]);

The log would display “magic”

An object is an array with multiple key value pairs for each array element for example

array[0].firstname = Joseph
array[0].lastname = Griffiths
array[1].firstname = Tom
array[1].lastname = Bobo
array[2].firstname = Mac
array[2].lastname = Cheese

This allows me to store multiple elements that are connected and entries in the object don’t have to be the same type (e.g. firstname and lastname are both strings but I could add a age entry to hold a number).  This provides a huge flexibility… those familiar with powercli this is the same as:

get-vm | fl

This will display all vm’s with a full list of the elements on the object of vm.

Error Handling

Errors will display the line number.  Use that to determine the cause or source.   I know almost every programmer needs to have the ability to test their assumptions around variables when writing programs use the System.log for this:

System.log("variable 1: " + var1 + " variable 2: " + var2);

System log is readable only by someone in vRO and not exposed to customers (unless they are running it from vRO)

Input validation

First check for null

if (variable1 == null)
{
    //Null action
}

Then validate your object type using the System.log method above.  There is a way for checking for complex system defined objects like this:

if (vm instanceof VcVirtualMachine)

{

//Do some action

}

This can be very useful when working with objects validate before you act.

 

Hope it helps

vRo scriptable task to return the top level folder for a VM

Have you been nesting your virtual machines deep into folders.  If you want to return only the top level folder you can do it with this simple javascript function.  It can also be turned into a action if you would rather:

function return_top_folder(vm)
{
                //get the parent object for vm
                var parent = vm.parent;
                //create array to hold data
                var parentNames = new Array();
                var vmPathName = "";
                //create an array of VcFolder
                while (parent instanceof VcFolder){
                                //push folder names on top of array
                                parentNames.push(parent.name);
                                parent = parent.parent;
                }
                //get length of array
                j = parentNames.length;
                //Identify top level folder
                vmPathName = parentNames[j-2];
                //Identify vm's at root of vCenter
                if (vmPathName == null)
                {
                                vmPathName = "root no folder";
                }
                //Return folder name or root no folder
                return vmPathName;
}

 

 

Execute it by calling :

folder = return_top_folder(vm);

The vm must be an object of VCVirtualMachine.  Enjoy the scriptable task. You can download it here: topfolder