vRO Deepdive Series Part 4 – Log Handling, Exception Handling and Failing Back

Introduction

Continuing the vRO deep dive series and this is the 4th part. This will be discussing log handling, exception handling and failing back.

Feel free to revisit the previous deep dive series:

Log Handling

vRO provides 3 types of log handling:

  • Log
  • Warning
  • Error

Let’s do some exercise and see the difference between them.

First of all, create a workflow calling it what you would like to (I called it “hi”) and navigate to the Log tab under Schema. You will find 7 default loggings:

Screenshot 2015-06-16 09.44.53

For the starters, let’s try System log out. Drag and drop the element in like the following:

Screenshot 2015-06-16 09.45.39

Edit the System log and navigate to Scripting. You will find an auto-generated script “System.log(text);”.

Screenshot 2015-06-16 09.45.53

Let’s take a look at System warning and error as well, drag and drop others like the following screenshot:

Screenshot 2015-06-16 09.48.46

Edit the System warning and it will show you a similar script as System log, “System.warn(text);”

Screenshot 2015-06-16 09.46.43

Pretty much identical for System error, “System.error(text);”

Screenshot 2015-06-16 09.46.56

Let’s run the workflow and see how they look differ on the vRO logging tab. Create an attribute called attrText and the value to be “Different types of logging”.

Screenshot 2015-06-16 09.47.31

For each element, finish up the visual binding like the following:

Screenshot 2015-06-16 09.47.54

Time to run the workflow. Execute and it will present 3 different types of logging:

  • Log in a normal font
  • Warning in bold
  • Error in red and bold

Screenshot 2015-06-16 09.49.09

One thing I would like to highlight before moving on is that you do not need to use the above element in order to do logging. Within a scriptable task, you could always use System.log(text), System.warn(text) or System.error(text). Will go a bit deeper into this shortly.

Time for a proper exercise! For the next, I will be going through creating a network adapter on a virtual machine with different types of network adapters.

First of all, remove all 3 logging elements made previously and drag and drop a scriptable task. Navigate to the Scripting tab and paste the following script in:

System.log("Adding a virtual NIC to this VM with portgroup: " + Portgroup.name);
// Create connectable info for network
var connectInfo = new VcVirtualDeviceConnectInfo();
connectInfo.connected = true;
connectInfo.startConnected = true;
connectInfo.allowGuestControl = false;
// Create Network BackingInfo
var netBackingInfo = new VcVirtualEthernetCardDistributedVirtualPortBackingInfo();
netBackingInfo.port = new VcDistributedVirtualSwitchPortConnection();
netBackingInfo.port.switchUuid = Portgroup.config.distributedVirtualSwitch.uuid;
netBackingInfo.port.portgroupKey = Portgroup.key;
// Create VirtualNetwork
if (Type.toUpperCase() === "VMXNET3") {
vNetwork = new VcVirtualVmxnet3();
} else if(Type.toUpperCase() === "E1000E") {
vNetwork = new VcVirtualE1000e();
}
vNetwork.backing = netBackingInfo;
vNetwork.addressType = "Generated";
vNetwork.connectable = connectInfo;
// Create Network ConfigSpec
var deviceConfigSpec = new VcVirtualDeviceConfigSpec();
deviceConfigSpec.device = vNetwork;
deviceConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.add;
var configSpec = new VcVirtualMachineConfigSpec();
var configSpecArray = new Array(); 
configSpecArray.push(deviceConfigSpec);
configSpec.deviceChange = configSpecArray;
// Run the task
Task = VM.reconfigVM_Task(configSpec);

Once the script is in place, create three inputs as per the following screenshot:

Screenshot 2015-06-16 11.04.08

As depicted above, the workflow will require 3 inputs from the end users; virtual machine, portgroup and type. For the type, instead of asking the end user to manually type the input in, it would be better to pre-define a list and let them select one. This would make it easier for both workflow developers and users.

Go back to the General tab, change the type of the attribute attrTypeList to Array of string and add VMXNET3 and E1000E:

Screenshot 2015-06-16 11.04.31

Screenshot 2015-06-16 11.04.26

Once done, go to Presentation tab, select Type, choose “Predefined list of elements” and link it to pre created attribute attrTypeList.


Screenshot 2015-06-16 11.05.04

Screenshot 2015-06-16 11.05.14

 

Lastly, finish off the Visual Binding:

Screenshot 2015-06-16 11.05.47

All done! Let’s run the workflow to ensure it does the job. For the next example, I will be choosing a portgroup with VLAN1153 and VMXNET3 network adapter.

Screenshot 2015-06-16 11.18.10

Submit the request. Once the workflow completes, see if VMXNET 3 network adapter with portgroup VLAN1153 has added:

Screenshot 2015-06-16 11.19.01

Let’s create another one with VLAN1153 in E1000E type. Submit another request:

Screenshot 2015-06-16 11.19.50

Now we are confident that the workflow creates a portgroup as intended, it’s time to go through the logging. What I will be showing shortly is:

  • Selecting VMXNET3 = informational message will be logged
  • Selecting E1000E = warning message will be logged

Go back to the scriptable task and modify like the following:

Old

// Create VirtualNetwork
    if (Type.toUpperCase() === "VMXNET3") {
    vNetwork = new VcVirtualVmxnet3();
} else if(Type.toUpperCase() === "E1000E") {
    vNetwork = new VcVirtualE1000e();
}

New

// Create VirtualNetwork
if (Type.toUpperCase() === "VMXNET3") {
    vNetwork = new VcVirtualVmxnet3();
    System.log("VMXNET3 Virtual Adapter will be created");
} else if(Type.toUpperCase() === "E1000E") {
    vNetwork = new VcVirtualE1000e();
    System.warn("VMXNET3 is recommended, but E1000E will be created");
}

Have a look at the example runs below:

  • 1 x VLAN997 VMXNET3 portgroup

Screenshot 2015-06-16 11.26.38

  • 1 x VLAN997 E100E portgroup

Screenshot 2015-06-16 11.28.08

This is how informational or warning message could be used. For the error message, it will be discussed in the next topic “Exception Handling”.

Exception Handling

An exception handling in the programming world is defined as

Exception handling is the process of responding to the occurrence, during computation, of exceptions – anomalous or exceptional conditions requiring special processing – often changing the normal flow of program execution

Why would you need to do exception handling? The reason is simple, when something never expected happens, information of the exception has to be handled, e.g. error message logged, locate where it happened…etc, which will allow easier troubleshooting for the developers.

The best way to catch an exception is to use try & catch:

try {
    ...... script
} catch (e) {
    System.error(e);
}

Whatever fails in try statement, the error message will be saved to the variable e and then logged as an error message.

Will be continuing with the example used in the previous section. Edit the scriptable task and replace the whole lines with the following script:

Script

try {
    System.log("Adding a virtual NIC to this VM with portgroup: " + Portgroup.name);
    // Create connectable info for network
    var connectInfo = new VcVirtualDeviceConnectInfo();
    connectInfo.connected = true;
    connectInfo.startConnected = true;
    connectInfo.allowGuestControl = false;

    // Create Network BackingInfo
    var netBackingInfo = new VcVirtualEthernetCardDistributedVirtualPortBackingInfo();
    netBackingInfo.port = new VcDistributedVirtualSwitchPortConnection();
    netBackingInfo.port.switchUuid = Portgroup.config.distributedVirtualSwitch.uuid;
    netBackingInfo.port.portgroupKey = Portgroup.key;

    // Create VirtualNetwork
    if (Type.toUpperCase() === "VMXNET3") {
        vNetwork = new VcVirtualVmxnet3();
        System.log("VMXNET3 Virtual Adapter will be created");
    } else if(Type.toUpperCase() === "E1000E") {
        vNetwork = new VcVirtualE1000e();
        System.warn("VMXNET3 is recommended, but E1000E will be created");
    }

    vNetwork.backing = netBackingInfo;
    vNetwork.addressType = "Generated";
    vNetwork.connectable = connectInfo;
    
    // Create Network ConfigSpec
    var deviceConfigSpec = new VcVirtualDeviceConfigSpec();
    deviceConfigSpec.device = vNetwork;
    deviceConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.add;
    
    var configSpec = new VcVirtualMachineConfigSpec();
    var configSpecArray = new Array();
    configSpecArray.push(deviceConfigSpec);
    configSpec.deviceChange = configSpecArray;
    
    // Run the task
    Task = VM.reconfigVM_Task(configSpec);
} catch (e) {
    System.error(e);
}

Causing an exception with this workflow is quite simple, just pick a portgroup that the virtual machine doesn’t have access to. In this example, VLAN23 was chosen:

Screenshot 2015-06-16 11.50.40

Since VLAN23 portgroup doesn’t exist, it now presents an error message saying “vNetwork is not defined”. One odd thing here is that looking at history of the workflow, it says the workflow was successful. Why is this? It’s because the exception was caught but wasn’t thrown properly, i.e. the workflow was not terminated. The way of throwing an exception is using “throw” statement. Add the throw statement like the following:

Old

} catch (e) {
    System.error(e);
}
New
} catch (errorCode) {
    System.error(errorCode);
    throw errorCode;
}

Once the change is made, the error will be thrown when an exception happens. One thing to consider is, where will it be thrown to? The exception must be handled once it is thrown.

Go back to the Schema and under the Generic tab, you will be able to find “Throw Exception” element.

Screenshot 2015-06-16 11.51.06

Throw exception element could be treated as End workflow but the difference is, the workflow was successful or failed.

Drag and drop the Throw exception element on the Scriptable task and a dotted red arrow will be created.

Screenshot 2015-06-16 11.51.21

Doing this will automatically create an attribute called errorCode. The purpose of this attribute is to catch any exception was thrown and forward it to the Throw exception element. This is why the variable e has been modified to errorCode earlier.

Saving the workflow will cause an error saying “Exception binding was not set”. This is because the workflow expects the scriptable task to bind the error message as an attribute. Edit the scriptable task, navigate to Exception and bind it to errorCode:

Screenshot 2015-06-16 11.51.30

Also, do the visual binding like below:

Screenshot 2015-06-16 11.52.05

Let’s run the workflow again choosing VLAN23. Unlike the previous example, now it will end in the throw exception state (the Throw exception element is highlighted).

Screenshot 2015-06-16 11.53.30

This is how you handle exceptions and will be moving onto fail-back process.

Fail-back

In my opinion, fail-back is one of the important aspects when developing a workflow. Continuing with the example above, let’s say there are 3 more tasks after creating a network adapter which I will be calling X, Y and Z and if task Y fails, what would you do to the network adapter created in the previous stage? The answer is obvious, it has to be removed, you don’t want the users to run the workflow multiple times ending up with 10 identical network adapters on a single virtual machine.

Let’s implement a simple fail-back process in this workflow. First of all, create an attribute called attrDevice with type to be Any (well there is no type with VC:VirtualDevice). This will be used to keep the device information.

Screenshot 2015-06-16 13.39.04

Once done, drag and drop 3 scriptable tasks between Create Network Adapter scriptable task and End element and call them Task X, Task Y and Task Z accordingly. Make sure you bind errorCode as the exception variable across 3 scriptable tasks and also, hover over and drag red arrow to Throw element.

Screenshot 2015-06-16 13.42.03

 

Screenshot 2015-06-16 13.42.11

Screenshot 2015-06-16 13.41.20

When task X,Y or Z fails, we want to delete the network adapter created. To do this, simply drag and drop a scriptable task between Task X and the Throw element and call it Remove Network Adapter:

Screenshot 2015-06-16 13.43.54

The problem in the above screenshot is that when the Task Y fails, it will just throw an exception without failing back. It will go directly to the Throw exception element. To correct it, click on the red line between the task Y and the Throw exception element, press delete and re-join it to Remove Network Adapter task. Repeat it to Task Z and the final state will look like the following:

Screenshot 2015-06-16 13.45.08

Paste the following script into Remove Network Adapter scriptable task:

try {
    System.error("An error has occurred, removing the created network adapter: " + attrDevice);

    var deviceConfigSpec = new VcVirtualDeviceConfigSpec();
    deviceConfigSpec.device = attrDevice;
    deviceConfigSpec.operation = VcVirtualDeviceConfigSpecOperation.remove;

    var configSpec = new VcVirtualMachineConfigSpec();

    var configSpecArray = new Array();
    configSpecArray.push(deviceConfigSpec);

    configSpec.deviceChange = configSpecArray;

    Task = VM.reconfigVM_Task(configSpec);
} catch (e) {
    errorCode = e;
    throw errorCode;
}

And also, finish off the Visual Binding:

In

Screenshot 2015-06-16 13.46.54

Out

Screenshot 2015-06-16 13.47.34

All done, let’s run and see the fail-back works. The following depicts the virtual machine has two network adapters, VLAN444 and VLAN1153:

Screenshot 2015-06-16 15.17.26

Let’s intentionally throw an exception in Task Y. Do the Visual Binding for errorCode and type the following in the scripting field:

errorCode = "This is intentional";
System.error(errorCode);
throw errorCode;

Let’s run it!

Screenshot 2015-06-16 15.20.41

It has thrown an exception at the Task Y and looking at how many network adapters the virtual machine has, you will see that the network adapter wasn’t created. Fail-back was successful!

Screenshot 2015-06-16 15.21.50

Wrap-Up

Hope this blog post was helpful and as always, feel free to contact me for any clarifications or help.

The next series will cover “Introduction to Relationship Between vRO & vRA” which is a big topic, stay tuned! 😀

6 Comments

  1. Thanks for this series.

    I test this series with vRO 7.1. i have a problem with example.

    I have no error in vRO when i specify a not accessible portgroup. But i have a error on the task of the vCenter when task start 😦

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s